blob: bc37467e2fe50ab19de918e321f593d8126104a8 [file] [log] [blame]
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001/*
2 * ispvideo.c
3 *
4 * TI OMAP3 ISP - Generic video node
5 *
6 * Copyright (C) 2009-2010 Nokia Corporation
7 *
8 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
9 * Sakari Ailus <sakari.ailus@iki.fi>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
Laurent Pinchartad614ac2011-02-12 18:05:06 -030014 */
15
16#include <asm/cacheflush.h>
17#include <linux/clk.h>
18#include <linux/mm.h>
Dmitry Artamonow025521f2011-11-20 12:54:26 -030019#include <linux/module.h>
Laurent Pinchartad614ac2011-02-12 18:05:06 -030020#include <linux/pagemap.h>
21#include <linux/scatterlist.h>
22#include <linux/sched.h>
23#include <linux/slab.h>
24#include <linux/vmalloc.h>
25#include <media/v4l2-dev.h>
26#include <media/v4l2-ioctl.h>
Laurent Pinchartfbac1402014-03-09 20:36:15 -030027#include <media/videobuf2-dma-contig.h>
Laurent Pinchartad614ac2011-02-12 18:05:06 -030028
29#include "ispvideo.h"
30#include "isp.h"
31
32
33/* -----------------------------------------------------------------------------
34 * Helper functions
35 */
36
Sakari Ailus8f4f2982011-12-28 06:28:41 -030037/*
38 * NOTE: When adding new media bus codes, always remember to add
39 * corresponding in-memory formats to the table below!!!
40 */
Laurent Pinchartad614ac2011-02-12 18:05:06 -030041static struct isp_format_info formats[] = {
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030042 { MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
43 MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030044 V4L2_PIX_FMT_GREY, 8, 1, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030045 { MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10,
46 MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030047 V4L2_PIX_FMT_Y10, 10, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030048 { MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y10_1X10,
49 MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030050 V4L2_PIX_FMT_Y12, 12, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030051 { MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
52 MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030053 V4L2_PIX_FMT_SBGGR8, 8, 1, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030054 { MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
55 MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030056 V4L2_PIX_FMT_SGBRG8, 8, 1, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030057 { MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
58 MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030059 V4L2_PIX_FMT_SGRBG8, 8, 1, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030060 { MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
61 MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030062 V4L2_PIX_FMT_SRGGB8, 8, 1, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030063 { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8,
64 MEDIA_BUS_FMT_SBGGR10_1X10, 0,
Laurent Pinchart1697e492011-08-31 11:57:12 -030065 V4L2_PIX_FMT_SBGGR10DPCM8, 8, 1, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030066 { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8,
67 MEDIA_BUS_FMT_SGBRG10_1X10, 0,
Laurent Pinchart1697e492011-08-31 11:57:12 -030068 V4L2_PIX_FMT_SGBRG10DPCM8, 8, 1, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030069 { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
70 MEDIA_BUS_FMT_SGRBG10_1X10, 0,
Laurent Pinchart1697e492011-08-31 11:57:12 -030071 V4L2_PIX_FMT_SGRBG10DPCM8, 8, 1, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030072 { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8,
73 MEDIA_BUS_FMT_SRGGB10_1X10, 0,
Laurent Pinchart1697e492011-08-31 11:57:12 -030074 V4L2_PIX_FMT_SRGGB10DPCM8, 8, 1, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030075 { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10,
76 MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030077 V4L2_PIX_FMT_SBGGR10, 10, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030078 { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10,
79 MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030080 V4L2_PIX_FMT_SGBRG10, 10, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030081 { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10,
82 MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030083 V4L2_PIX_FMT_SGRBG10, 10, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030084 { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10,
85 MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030086 V4L2_PIX_FMT_SRGGB10, 10, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030087 { MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR10_1X10,
88 MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030089 V4L2_PIX_FMT_SBGGR12, 12, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030090 { MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG10_1X10,
91 MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030092 V4L2_PIX_FMT_SGBRG12, 12, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030093 { MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG10_1X10,
94 MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030095 V4L2_PIX_FMT_SGRBG12, 12, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030096 { MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10,
97 MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB8_1X8,
Laurent Pinchart1697e492011-08-31 11:57:12 -030098 V4L2_PIX_FMT_SRGGB12, 12, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -030099 { MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16,
100 MEDIA_BUS_FMT_UYVY8_1X16, 0,
Laurent Pinchart1697e492011-08-31 11:57:12 -0300101 V4L2_PIX_FMT_UYVY, 16, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -0300102 { MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YUYV8_1X16,
103 MEDIA_BUS_FMT_YUYV8_1X16, 0,
Laurent Pinchart1697e492011-08-31 11:57:12 -0300104 V4L2_PIX_FMT_YUYV, 16, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -0300105 { MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_UYVY8_2X8,
106 MEDIA_BUS_FMT_UYVY8_2X8, 0,
Laurent Pinchart0810fd92012-05-24 11:55:00 -0300107 V4L2_PIX_FMT_UYVY, 8, 2, },
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -0300108 { MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YUYV8_2X8,
109 MEDIA_BUS_FMT_YUYV8_2X8, 0,
Laurent Pinchart0810fd92012-05-24 11:55:00 -0300110 V4L2_PIX_FMT_YUYV, 8, 2, },
Laurent Pinchartc51364c2011-08-31 11:03:53 -0300111 /* Empty entry to catch the unsupported pixel code (0) used by the CCDC
112 * module and avoid NULL pointer dereferences.
113 */
114 { 0, }
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300115};
116
Boris BREZILLON27ffaeb2014-11-10 14:28:31 -0300117const struct isp_format_info *omap3isp_video_format_info(u32 code)
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300118{
119 unsigned int i;
120
121 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
122 if (formats[i].code == code)
123 return &formats[i];
124 }
125
126 return NULL;
127}
128
129/*
130 * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
131 * @video: ISP video instance
132 * @mbus: v4l2_mbus_framefmt format (input)
133 * @pix: v4l2_pix_format format (output)
134 *
135 * Fill the output pix structure with information from the input mbus format.
136 * The bytesperline and sizeimage fields are computed from the requested bytes
137 * per line value in the pix format and information from the video instance.
138 *
139 * Return the number of padding bytes at end of line.
140 */
141static unsigned int isp_video_mbus_to_pix(const struct isp_video *video,
142 const struct v4l2_mbus_framefmt *mbus,
143 struct v4l2_pix_format *pix)
144{
145 unsigned int bpl = pix->bytesperline;
146 unsigned int min_bpl;
147 unsigned int i;
148
149 memset(pix, 0, sizeof(*pix));
150 pix->width = mbus->width;
151 pix->height = mbus->height;
152
153 for (i = 0; i < ARRAY_SIZE(formats); ++i) {
154 if (formats[i].code == mbus->code)
155 break;
156 }
157
158 if (WARN_ON(i == ARRAY_SIZE(formats)))
159 return 0;
160
Laurent Pinchart1697e492011-08-31 11:57:12 -0300161 min_bpl = pix->width * formats[i].bpp;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300162
163 /* Clamp the requested bytes per line value. If the maximum bytes per
164 * line value is zero, the module doesn't support user configurable line
165 * sizes. Override the requested value with the minimum in that case.
166 */
167 if (video->bpl_max)
168 bpl = clamp(bpl, min_bpl, video->bpl_max);
169 else
170 bpl = min_bpl;
171
172 if (!video->bpl_zero_padding || bpl != min_bpl)
173 bpl = ALIGN(bpl, video->bpl_alignment);
174
175 pix->pixelformat = formats[i].pixelformat;
176 pix->bytesperline = bpl;
177 pix->sizeimage = pix->bytesperline * pix->height;
178 pix->colorspace = mbus->colorspace;
179 pix->field = mbus->field;
180
181 return bpl - min_bpl;
182}
183
184static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix,
185 struct v4l2_mbus_framefmt *mbus)
186{
187 unsigned int i;
188
189 memset(mbus, 0, sizeof(*mbus));
190 mbus->width = pix->width;
191 mbus->height = pix->height;
192
Laurent Pinchartc3cd2572011-11-28 08:25:30 -0300193 /* Skip the last format in the loop so that it will be selected if no
194 * match is found.
195 */
196 for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) {
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300197 if (formats[i].pixelformat == pix->pixelformat)
198 break;
199 }
200
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300201 mbus->code = formats[i].code;
202 mbus->colorspace = pix->colorspace;
203 mbus->field = pix->field;
204}
205
206static struct v4l2_subdev *
207isp_video_remote_subdev(struct isp_video *video, u32 *pad)
208{
209 struct media_pad *remote;
210
Andrzej Hajda1bddf1b2013-06-03 05:16:13 -0300211 remote = media_entity_remote_pad(&video->pad);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300212
Mauro Carvalho Chehab3efdf622015-05-07 22:12:32 -0300213 if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300214 return NULL;
215
216 if (pad)
217 *pad = remote->index;
218
219 return media_entity_to_v4l2_subdev(remote->entity);
220}
221
222/* Return a pointer to the ISP video instance at the far end of the pipeline. */
Sakari Ailusae5df812012-03-05 20:22:41 -0300223static int isp_video_get_graph_data(struct isp_video *video,
224 struct isp_pipeline *pipe)
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300225{
226 struct media_entity_graph graph;
227 struct media_entity *entity = &video->video.entity;
Javier Martinez Canillasd10c9892015-08-19 12:35:21 -0300228 struct media_device *mdev = entity->graph_obj.mdev;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300229 struct isp_video *far_end = NULL;
Sakari Ailus28461452015-12-16 11:32:24 -0200230 int ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300231
232 mutex_lock(&mdev->graph_mutex);
Sakari Ailus28461452015-12-16 11:32:24 -0200233 ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev);
234 if (ret) {
235 mutex_unlock(&mdev->graph_mutex);
236 return ret;
237 }
238
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300239 media_entity_graph_walk_start(&graph, entity);
240
241 while ((entity = media_entity_graph_walk_next(&graph))) {
Sakari Ailusae5df812012-03-05 20:22:41 -0300242 struct isp_video *__video;
243
Sakari Ailus17d3d402015-12-16 11:32:30 -0200244 media_entity_enum_set(&pipe->ent_enum, entity);
Sakari Ailusae5df812012-03-05 20:22:41 -0300245
246 if (far_end != NULL)
247 continue;
248
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300249 if (entity == &video->video.entity)
250 continue;
251
Mauro Carvalho Chehab3efdf622015-05-07 22:12:32 -0300252 if (!is_media_entity_v4l2_io(entity))
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300253 continue;
254
Sakari Ailusae5df812012-03-05 20:22:41 -0300255 __video = to_isp_video(media_entity_to_video_device(entity));
256 if (__video->type != video->type)
257 far_end = __video;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300258 }
259
260 mutex_unlock(&mdev->graph_mutex);
Sakari Ailusae5df812012-03-05 20:22:41 -0300261
Sakari Ailus28461452015-12-16 11:32:24 -0200262 media_entity_graph_walk_cleanup(&graph);
263
Sakari Ailusae5df812012-03-05 20:22:41 -0300264 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
265 pipe->input = far_end;
266 pipe->output = video;
267 } else {
268 if (far_end == NULL)
269 return -EPIPE;
270
271 pipe->input = video;
272 pipe->output = far_end;
273 }
274
275 return 0;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300276}
277
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300278static int
279__isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
280{
281 struct v4l2_subdev_format fmt;
282 struct v4l2_subdev *subdev;
283 u32 pad;
284 int ret;
285
286 subdev = isp_video_remote_subdev(video, &pad);
287 if (subdev == NULL)
288 return -EINVAL;
289
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300290 fmt.pad = pad;
291 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300292
Laurent Pinchart52646822013-11-04 06:52:10 -0300293 mutex_lock(&video->mutex);
294 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300295 mutex_unlock(&video->mutex);
296
297 if (ret)
298 return ret;
299
300 format->type = video->type;
301 return isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
302}
303
304static int
305isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
306{
307 struct v4l2_format format;
308 int ret;
309
310 memcpy(&format, &vfh->format, sizeof(format));
311 ret = __isp_video_get_format(video, &format);
312 if (ret < 0)
313 return ret;
314
315 if (vfh->format.fmt.pix.pixelformat != format.fmt.pix.pixelformat ||
316 vfh->format.fmt.pix.height != format.fmt.pix.height ||
317 vfh->format.fmt.pix.width != format.fmt.pix.width ||
318 vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline ||
Laurent Pinchartf7abbe92014-05-19 12:14:42 -0300319 vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage ||
320 vfh->format.fmt.pix.field != format.fmt.pix.field)
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300321 return -EINVAL;
322
Laurent Pinchartf7abbe92014-05-19 12:14:42 -0300323 return 0;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300324}
325
326/* -----------------------------------------------------------------------------
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300327 * Video queue operations
328 */
329
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300330static int isp_video_queue_setup(struct vb2_queue *queue,
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300331 unsigned int *count, unsigned int *num_planes,
332 unsigned int sizes[], void *alloc_ctxs[])
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300333{
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300334 struct isp_video_fh *vfh = vb2_get_drv_priv(queue);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300335 struct isp_video *video = vfh->video;
336
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300337 *num_planes = 1;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300338
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300339 sizes[0] = vfh->format.fmt.pix.sizeimage;
340 if (sizes[0] == 0)
341 return -EINVAL;
342
343 alloc_ctxs[0] = video->alloc_ctx;
344
345 *count = min(*count, video->capture_mem / PAGE_ALIGN(sizes[0]));
346
347 return 0;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300348}
349
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300350static int isp_video_buffer_prepare(struct vb2_buffer *buf)
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300351{
Junghak Sung2d700712015-09-22 10:30:30 -0300352 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf);
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300353 struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue);
Junghak Sung2d700712015-09-22 10:30:30 -0300354 struct isp_buffer *buffer = to_isp_buffer(vbuf);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300355 struct isp_video *video = vfh->video;
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300356 dma_addr_t addr;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300357
Laurent Pinchart661112c2013-12-09 11:36:51 -0300358 /* Refuse to prepare the buffer is the video node has registered an
359 * error. We don't need to take any lock here as the operation is
360 * inherently racy. The authoritative check will be performed in the
361 * queue handler, which can't return an error, this check is just a best
362 * effort to notify userspace as early as possible.
363 */
364 if (unlikely(video->error))
365 return -EIO;
366
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300367 addr = vb2_dma_contig_plane_dma_addr(buf, 0);
368 if (!IS_ALIGNED(addr, 32)) {
369 dev_dbg(video->isp->dev,
370 "Buffer address must be aligned to 32 bytes boundary.\n");
371 return -EINVAL;
372 }
373
Junghak Sung2d700712015-09-22 10:30:30 -0300374 vb2_set_plane_payload(&buffer->vb.vb2_buf, 0,
375 vfh->format.fmt.pix.sizeimage);
Laurent Pinchart21d85822014-03-09 20:17:12 -0300376 buffer->dma = addr;
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300377
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300378 return 0;
379}
380
381/*
382 * isp_video_buffer_queue - Add buffer to streaming queue
383 * @buf: Video buffer
384 *
385 * In memory-to-memory mode, start streaming on the pipeline if buffers are
386 * queued on both the input and the output, if the pipeline isn't already busy.
387 * If the pipeline is busy, it will be restarted in the output module interrupt
388 * handler.
389 */
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300390static void isp_video_buffer_queue(struct vb2_buffer *buf)
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300391{
Junghak Sung2d700712015-09-22 10:30:30 -0300392 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf);
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300393 struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue);
Junghak Sung2d700712015-09-22 10:30:30 -0300394 struct isp_buffer *buffer = to_isp_buffer(vbuf);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300395 struct isp_video *video = vfh->video;
396 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
397 enum isp_pipeline_state state;
398 unsigned long flags;
399 unsigned int empty;
400 unsigned int start;
401
Laurent Pincharte8feb872014-03-09 20:57:53 -0300402 spin_lock_irqsave(&video->irqlock, flags);
403
Laurent Pinchart661112c2013-12-09 11:36:51 -0300404 if (unlikely(video->error)) {
Junghak Sung2d700712015-09-22 10:30:30 -0300405 vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_ERROR);
Laurent Pincharte8feb872014-03-09 20:57:53 -0300406 spin_unlock_irqrestore(&video->irqlock, flags);
Laurent Pinchart661112c2013-12-09 11:36:51 -0300407 return;
408 }
409
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300410 empty = list_empty(&video->dmaqueue);
Laurent Pincharteb2c00d2014-03-09 20:57:53 -0300411 list_add_tail(&buffer->irqlist, &video->dmaqueue);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300412
Laurent Pincharte8feb872014-03-09 20:57:53 -0300413 spin_unlock_irqrestore(&video->irqlock, flags);
414
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300415 if (empty) {
416 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
417 state = ISP_PIPELINE_QUEUE_OUTPUT;
418 else
419 state = ISP_PIPELINE_QUEUE_INPUT;
420
421 spin_lock_irqsave(&pipe->lock, flags);
422 pipe->state |= state;
423 video->ops->queue(video, buffer);
424 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
425
426 start = isp_pipeline_ready(pipe);
427 if (start)
428 pipe->state |= ISP_PIPELINE_STREAM;
429 spin_unlock_irqrestore(&pipe->lock, flags);
430
431 if (start)
432 omap3isp_pipeline_set_stream(pipe,
433 ISP_PIPELINE_STREAM_SINGLESHOT);
434 }
435}
436
Sakari Ailus35c5f632014-09-18 18:57:48 -0300437static int isp_video_start_streaming(struct vb2_queue *queue,
438 unsigned int count)
439{
440 struct isp_video_fh *vfh = vb2_get_drv_priv(queue);
441 struct isp_video *video = vfh->video;
442 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
443 unsigned long flags;
444 int ret;
445
446 /* In sensor-to-memory mode, the stream can be started synchronously
447 * to the stream on command. In memory-to-memory mode, it will be
448 * started when buffers are queued on both the input and output.
449 */
450 if (pipe->input)
451 return 0;
452
453 ret = omap3isp_pipeline_set_stream(pipe,
454 ISP_PIPELINE_STREAM_CONTINUOUS);
455 if (ret < 0)
456 return ret;
457
458 spin_lock_irqsave(&video->irqlock, flags);
459 if (list_empty(&video->dmaqueue))
460 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
461 spin_unlock_irqrestore(&video->irqlock, flags);
462
463 return 0;
464}
465
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300466static const struct vb2_ops isp_video_queue_ops = {
467 .queue_setup = isp_video_queue_setup,
468 .buf_prepare = isp_video_buffer_prepare,
469 .buf_queue = isp_video_buffer_queue,
Sakari Ailus35c5f632014-09-18 18:57:48 -0300470 .start_streaming = isp_video_start_streaming,
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300471};
472
473/*
474 * omap3isp_video_buffer_next - Complete the current buffer and return the next
475 * @video: ISP video object
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300476 *
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300477 * Remove the current video buffer from the DMA queue and fill its timestamp and
478 * field count before handing it back to videobuf2.
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300479 *
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300480 * For capture video nodes the buffer state is set to VB2_BUF_STATE_DONE if no
481 * error has been flagged in the pipeline, or to VB2_BUF_STATE_ERROR otherwise.
482 * For video output nodes the buffer state is always set to VB2_BUF_STATE_DONE.
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300483 *
484 * The DMA queue is expected to contain at least one buffer.
485 *
486 * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
487 * empty.
488 */
Laurent Pinchart875e2e32011-12-07 08:34:50 -0300489struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300490{
491 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300492 enum isp_pipeline_state state;
Laurent Pincharteb2c00d2014-03-09 20:57:53 -0300493 struct isp_buffer *buf;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300494 unsigned long flags;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300495
Laurent Pincharte8feb872014-03-09 20:57:53 -0300496 spin_lock_irqsave(&video->irqlock, flags);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300497 if (WARN_ON(list_empty(&video->dmaqueue))) {
Laurent Pincharte8feb872014-03-09 20:57:53 -0300498 spin_unlock_irqrestore(&video->irqlock, flags);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300499 return NULL;
500 }
501
Laurent Pincharteb2c00d2014-03-09 20:57:53 -0300502 buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300503 irqlist);
504 list_del(&buf->irqlist);
Laurent Pincharte8feb872014-03-09 20:57:53 -0300505 spin_unlock_irqrestore(&video->irqlock, flags);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300506
Junghak Sungd6dd6452015-11-03 08:16:37 -0200507 buf->vb.vb2_buf.timestamp = ktime_get_ns();
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300508
509 /* Do frame number propagation only if this is the output video node.
510 * Frame number either comes from the CSI receivers or it gets
511 * incremented here if H3A is not active.
512 * Note: There is no guarantee that the output buffer will finish
513 * first, so the input number might lag behind by 1 in some cases.
514 */
515 if (video == pipe->output && !pipe->do_propagation)
Junghak Sung2d700712015-09-22 10:30:30 -0300516 buf->vb.sequence =
Laurent Pincharteb2c00d2014-03-09 20:57:53 -0300517 atomic_inc_return(&pipe->frame_number);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300518 else
Junghak Sung2d700712015-09-22 10:30:30 -0300519 buf->vb.sequence = atomic_read(&pipe->frame_number);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300520
Laurent Pinchart9a36d8e2014-05-19 16:37:38 -0300521 if (pipe->field != V4L2_FIELD_NONE)
Junghak Sung2d700712015-09-22 10:30:30 -0300522 buf->vb.sequence /= 2;
Laurent Pinchart9a36d8e2014-05-19 16:37:38 -0300523
Junghak Sung2d700712015-09-22 10:30:30 -0300524 buf->vb.field = pipe->field;
Laurent Pinchart9a36d8e2014-05-19 16:37:38 -0300525
Laurent Pinchart875e2e32011-12-07 08:34:50 -0300526 /* Report pipeline errors to userspace on the capture device side. */
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300527 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
528 state = VB2_BUF_STATE_ERROR;
Laurent Pinchart875e2e32011-12-07 08:34:50 -0300529 pipe->error = false;
530 } else {
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300531 state = VB2_BUF_STATE_DONE;
Laurent Pinchart875e2e32011-12-07 08:34:50 -0300532 }
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300533
Junghak Sung2d700712015-09-22 10:30:30 -0300534 vb2_buffer_done(&buf->vb.vb2_buf, state);
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300535
536 spin_lock_irqsave(&video->irqlock, flags);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300537
538 if (list_empty(&video->dmaqueue)) {
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300539 spin_unlock_irqrestore(&video->irqlock, flags);
540
541 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300542 state = ISP_PIPELINE_QUEUE_OUTPUT
543 | ISP_PIPELINE_STREAM;
544 else
545 state = ISP_PIPELINE_QUEUE_INPUT
546 | ISP_PIPELINE_STREAM;
547
548 spin_lock_irqsave(&pipe->lock, flags);
549 pipe->state &= ~state;
550 if (video->pipe.stream_state == ISP_PIPELINE_STREAM_CONTINUOUS)
551 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
552 spin_unlock_irqrestore(&pipe->lock, flags);
553 return NULL;
554 }
555
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300556 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
557 spin_lock(&pipe->lock);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300558 pipe->state &= ~ISP_PIPELINE_STREAM;
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300559 spin_unlock(&pipe->lock);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300560 }
561
Laurent Pincharteb2c00d2014-03-09 20:57:53 -0300562 buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300563 irqlist);
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300564
565 spin_unlock_irqrestore(&video->irqlock, flags);
566
Laurent Pincharteb2c00d2014-03-09 20:57:53 -0300567 return buf;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300568}
569
570/*
Laurent Pinchart661112c2013-12-09 11:36:51 -0300571 * omap3isp_video_cancel_stream - Cancel stream on a video node
572 * @video: ISP video object
573 *
574 * Cancelling a stream mark all buffers on the video node as erroneous and makes
575 * sure no new buffer can be queued.
576 */
577void omap3isp_video_cancel_stream(struct isp_video *video)
578{
Laurent Pinchart661112c2013-12-09 11:36:51 -0300579 unsigned long flags;
580
Laurent Pincharte8feb872014-03-09 20:57:53 -0300581 spin_lock_irqsave(&video->irqlock, flags);
Laurent Pinchart661112c2013-12-09 11:36:51 -0300582
583 while (!list_empty(&video->dmaqueue)) {
Laurent Pincharteb2c00d2014-03-09 20:57:53 -0300584 struct isp_buffer *buf;
Laurent Pinchart661112c2013-12-09 11:36:51 -0300585
586 buf = list_first_entry(&video->dmaqueue,
Laurent Pincharteb2c00d2014-03-09 20:57:53 -0300587 struct isp_buffer, irqlist);
Laurent Pinchart661112c2013-12-09 11:36:51 -0300588 list_del(&buf->irqlist);
Junghak Sung2d700712015-09-22 10:30:30 -0300589 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
Laurent Pinchart661112c2013-12-09 11:36:51 -0300590 }
591
592 video->error = true;
593
Laurent Pincharte8feb872014-03-09 20:57:53 -0300594 spin_unlock_irqrestore(&video->irqlock, flags);
Laurent Pinchart661112c2013-12-09 11:36:51 -0300595}
596
597/*
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300598 * omap3isp_video_resume - Perform resume operation on the buffers
599 * @video: ISP video object
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300600 * @continuous: Pipeline is in single shot mode if 0 or continuous mode otherwise
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300601 *
602 * This function is intended to be used on suspend/resume scenario. It
603 * requests video queue layer to discard buffers marked as DONE if it's in
604 * continuous mode and requests ISP modules to queue again the ACTIVE buffer
605 * if there's any.
606 */
607void omap3isp_video_resume(struct isp_video *video, int continuous)
608{
609 struct isp_buffer *buf = NULL;
610
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300611 if (continuous && video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
612 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300613 vb2_discard_done(video->queue);
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300614 mutex_unlock(&video->queue_lock);
615 }
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300616
617 if (!list_empty(&video->dmaqueue)) {
618 buf = list_first_entry(&video->dmaqueue,
Laurent Pincharteb2c00d2014-03-09 20:57:53 -0300619 struct isp_buffer, irqlist);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300620 video->ops->queue(video, buf);
621 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
622 } else {
623 if (continuous)
624 video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
625 }
626}
627
628/* -----------------------------------------------------------------------------
629 * V4L2 ioctls
630 */
631
632static int
633isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
634{
635 struct isp_video *video = video_drvdata(file);
636
637 strlcpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
638 strlcpy(cap->card, video->video.name, sizeof(cap->card));
639 strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300640
Sakari Ailus2c0108e2015-01-01 18:13:54 -0300641 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
642 | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
643
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300644 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
Sakari Ailus2c0108e2015-01-01 18:13:54 -0300645 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300646 else
Sakari Ailus2c0108e2015-01-01 18:13:54 -0300647 cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300648
649 return 0;
650}
651
652static int
653isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format)
654{
655 struct isp_video_fh *vfh = to_isp_video_fh(fh);
656 struct isp_video *video = video_drvdata(file);
657
658 if (format->type != video->type)
659 return -EINVAL;
660
661 mutex_lock(&video->mutex);
662 *format = vfh->format;
663 mutex_unlock(&video->mutex);
664
665 return 0;
666}
667
668static int
669isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
670{
671 struct isp_video_fh *vfh = to_isp_video_fh(fh);
672 struct isp_video *video = video_drvdata(file);
673 struct v4l2_mbus_framefmt fmt;
674
675 if (format->type != video->type)
676 return -EINVAL;
677
Laurent Pinchartbcb4e0e2014-05-19 19:40:04 -0300678 /* Replace unsupported field orders with sane defaults. */
679 switch (format->fmt.pix.field) {
680 case V4L2_FIELD_NONE:
681 /* Progressive is supported everywhere. */
682 break;
683 case V4L2_FIELD_ALTERNATE:
684 /* ALTERNATE is not supported on output nodes. */
685 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
686 format->fmt.pix.field = V4L2_FIELD_NONE;
687 break;
688 case V4L2_FIELD_INTERLACED:
689 /* The ISP has no concept of video standard, select the
690 * top-bottom order when the unqualified interlaced order is
691 * requested.
692 */
693 format->fmt.pix.field = V4L2_FIELD_INTERLACED_TB;
694 /* Fall-through */
695 case V4L2_FIELD_INTERLACED_TB:
696 case V4L2_FIELD_INTERLACED_BT:
697 /* Interlaced orders are only supported at the CCDC output. */
698 if (video != &video->isp->isp_ccdc.video_out)
699 format->fmt.pix.field = V4L2_FIELD_NONE;
700 break;
701 case V4L2_FIELD_TOP:
702 case V4L2_FIELD_BOTTOM:
703 case V4L2_FIELD_SEQ_TB:
704 case V4L2_FIELD_SEQ_BT:
705 default:
706 /* All other field orders are currently unsupported, default to
707 * progressive.
708 */
Laurent Pinchart48a8a0c2014-05-19 10:49:58 -0300709 format->fmt.pix.field = V4L2_FIELD_NONE;
Laurent Pinchartbcb4e0e2014-05-19 19:40:04 -0300710 break;
711 }
Laurent Pinchart48a8a0c2014-05-19 10:49:58 -0300712
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300713 /* Fill the bytesperline and sizeimage fields by converting to media bus
714 * format and back to pixel format.
715 */
716 isp_video_pix_to_mbus(&format->fmt.pix, &fmt);
717 isp_video_mbus_to_pix(video, &fmt, &format->fmt.pix);
718
Laurent Pinchart25c5cc92014-05-19 10:33:15 -0300719 mutex_lock(&video->mutex);
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300720 vfh->format = *format;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300721 mutex_unlock(&video->mutex);
Laurent Pinchart25c5cc92014-05-19 10:33:15 -0300722
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300723 return 0;
724}
725
726static int
727isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
728{
729 struct isp_video *video = video_drvdata(file);
730 struct v4l2_subdev_format fmt;
731 struct v4l2_subdev *subdev;
732 u32 pad;
733 int ret;
734
735 if (format->type != video->type)
736 return -EINVAL;
737
738 subdev = isp_video_remote_subdev(video, &pad);
739 if (subdev == NULL)
740 return -EINVAL;
741
742 isp_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
743
744 fmt.pad = pad;
745 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
746 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
747 if (ret)
Wanlong Gaoa694f1b2012-08-27 04:23:15 -0300748 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300749
750 isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
751 return 0;
752}
753
754static int
755isp_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
756{
757 struct isp_video *video = video_drvdata(file);
758 struct v4l2_subdev *subdev;
759 int ret;
760
761 subdev = isp_video_remote_subdev(video, NULL);
762 if (subdev == NULL)
763 return -EINVAL;
764
765 mutex_lock(&video->mutex);
766 ret = v4l2_subdev_call(subdev, video, cropcap, cropcap);
767 mutex_unlock(&video->mutex);
768
Wanlong Gaoa694f1b2012-08-27 04:23:15 -0300769 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300770}
771
772static int
773isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
774{
775 struct isp_video *video = video_drvdata(file);
776 struct v4l2_subdev_format format;
777 struct v4l2_subdev *subdev;
778 u32 pad;
779 int ret;
780
781 subdev = isp_video_remote_subdev(video, &pad);
782 if (subdev == NULL)
783 return -EINVAL;
784
785 /* Try the get crop operation first and fallback to get format if not
786 * implemented.
787 */
788 ret = v4l2_subdev_call(subdev, video, g_crop, crop);
789 if (ret != -ENOIOCTLCMD)
790 return ret;
791
792 format.pad = pad;
793 format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
794 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
795 if (ret < 0)
Wanlong Gaoa694f1b2012-08-27 04:23:15 -0300796 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300797
798 crop->c.left = 0;
799 crop->c.top = 0;
800 crop->c.width = format.format.width;
801 crop->c.height = format.format.height;
802
803 return 0;
804}
805
806static int
Laurent Pinchart1fa48cd2012-10-12 11:28:40 -0300807isp_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300808{
809 struct isp_video *video = video_drvdata(file);
810 struct v4l2_subdev *subdev;
811 int ret;
812
813 subdev = isp_video_remote_subdev(video, NULL);
814 if (subdev == NULL)
815 return -EINVAL;
816
817 mutex_lock(&video->mutex);
818 ret = v4l2_subdev_call(subdev, video, s_crop, crop);
819 mutex_unlock(&video->mutex);
820
Wanlong Gaoa694f1b2012-08-27 04:23:15 -0300821 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300822}
823
824static int
825isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a)
826{
827 struct isp_video_fh *vfh = to_isp_video_fh(fh);
828 struct isp_video *video = video_drvdata(file);
829
830 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
831 video->type != a->type)
832 return -EINVAL;
833
834 memset(a, 0, sizeof(*a));
835 a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
836 a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
837 a->parm.output.timeperframe = vfh->timeperframe;
838
839 return 0;
840}
841
842static int
843isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a)
844{
845 struct isp_video_fh *vfh = to_isp_video_fh(fh);
846 struct isp_video *video = video_drvdata(file);
847
848 if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
849 video->type != a->type)
850 return -EINVAL;
851
852 if (a->parm.output.timeperframe.denominator == 0)
853 a->parm.output.timeperframe.denominator = 1;
854
855 vfh->timeperframe = a->parm.output.timeperframe;
856
857 return 0;
858}
859
860static int
861isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
862{
863 struct isp_video_fh *vfh = to_isp_video_fh(fh);
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300864 struct isp_video *video = video_drvdata(file);
865 int ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300866
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300867 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300868 ret = vb2_reqbufs(&vfh->queue, rb);
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300869 mutex_unlock(&video->queue_lock);
870
871 return ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300872}
873
874static int
875isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
876{
877 struct isp_video_fh *vfh = to_isp_video_fh(fh);
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300878 struct isp_video *video = video_drvdata(file);
879 int ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300880
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300881 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300882 ret = vb2_querybuf(&vfh->queue, b);
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300883 mutex_unlock(&video->queue_lock);
884
885 return ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300886}
887
888static int
889isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
890{
891 struct isp_video_fh *vfh = to_isp_video_fh(fh);
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300892 struct isp_video *video = video_drvdata(file);
893 int ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300894
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300895 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300896 ret = vb2_qbuf(&vfh->queue, b);
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300897 mutex_unlock(&video->queue_lock);
898
899 return ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300900}
901
902static int
903isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
904{
905 struct isp_video_fh *vfh = to_isp_video_fh(fh);
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300906 struct isp_video *video = video_drvdata(file);
907 int ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300908
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300909 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -0300910 ret = vb2_dqbuf(&vfh->queue, b, file->f_flags & O_NONBLOCK);
Laurent Pinchart988d54c2014-03-09 20:57:53 -0300911 mutex_unlock(&video->queue_lock);
912
913 return ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -0300914}
915
Sakari Ailusccddd912012-01-17 12:29:38 -0300916static int isp_video_check_external_subdevs(struct isp_video *video,
917 struct isp_pipeline *pipe)
918{
919 struct isp_device *isp = video->isp;
920 struct media_entity *ents[] = {
921 &isp->isp_csi2a.subdev.entity,
922 &isp->isp_csi2c.subdev.entity,
923 &isp->isp_ccp2.subdev.entity,
924 &isp->isp_ccdc.subdev.entity
925 };
926 struct media_pad *source_pad;
927 struct media_entity *source = NULL;
928 struct media_entity *sink;
929 struct v4l2_subdev_format fmt;
930 struct v4l2_ext_controls ctrls;
931 struct v4l2_ext_control ctrl;
932 unsigned int i;
Laurent Pinchart7c486c02014-02-14 21:45:50 -0300933 int ret;
Sakari Ailusccddd912012-01-17 12:29:38 -0300934
Laurent Pinchart4b2f1ed2014-02-14 21:40:48 -0300935 /* Memory-to-memory pipelines have no external subdev. */
936 if (pipe->input != NULL)
937 return 0;
938
Sakari Ailusccddd912012-01-17 12:29:38 -0300939 for (i = 0; i < ARRAY_SIZE(ents); i++) {
940 /* Is the entity part of the pipeline? */
Sakari Ailus17d3d402015-12-16 11:32:30 -0200941 if (!media_entity_enum_test(&pipe->ent_enum, ents[i]))
Sakari Ailusccddd912012-01-17 12:29:38 -0300942 continue;
943
944 /* ISP entities have always sink pad == 0. Find source. */
Andrzej Hajda1bddf1b2013-06-03 05:16:13 -0300945 source_pad = media_entity_remote_pad(&ents[i]->pads[0]);
Sakari Ailusccddd912012-01-17 12:29:38 -0300946 if (source_pad == NULL)
947 continue;
948
949 source = source_pad->entity;
950 sink = ents[i];
951 break;
952 }
953
954 if (!source) {
955 dev_warn(isp->dev, "can't find source, failing now\n");
Laurent Pinchart7c486c02014-02-14 21:45:50 -0300956 return -EINVAL;
Sakari Ailusccddd912012-01-17 12:29:38 -0300957 }
958
Mauro Carvalho Chehab3efdf622015-05-07 22:12:32 -0300959 if (!is_media_entity_v4l2_subdev(source))
Sakari Ailusccddd912012-01-17 12:29:38 -0300960 return 0;
961
962 pipe->external = media_entity_to_v4l2_subdev(source);
963
964 fmt.pad = source_pad->index;
965 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
966 ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(sink),
967 pad, get_fmt, NULL, &fmt);
968 if (unlikely(ret < 0)) {
969 dev_warn(isp->dev, "get_fmt returned null!\n");
970 return ret;
971 }
972
Laurent Pinchart1697e492011-08-31 11:57:12 -0300973 pipe->external_width =
974 omap3isp_video_format_info(fmt.format.code)->width;
Sakari Ailusccddd912012-01-17 12:29:38 -0300975
976 memset(&ctrls, 0, sizeof(ctrls));
977 memset(&ctrl, 0, sizeof(ctrl));
978
979 ctrl.id = V4L2_CID_PIXEL_RATE;
980
981 ctrls.count = 1;
982 ctrls.controls = &ctrl;
983
984 ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, &ctrls);
985 if (ret < 0) {
986 dev_warn(isp->dev, "no pixel rate control in subdev %s\n",
987 pipe->external->name);
988 return ret;
989 }
990
991 pipe->external_rate = ctrl.value64;
992
Sakari Ailus17d3d402015-12-16 11:32:30 -0200993 if (media_entity_enum_test(&pipe->ent_enum,
994 &isp->isp_ccdc.subdev.entity)) {
Sakari Ailusa6d7a622012-02-25 20:42:07 -0300995 unsigned int rate = UINT_MAX;
996 /*
997 * Check that maximum allowed CCDC pixel rate isn't
998 * exceeded by the pixel rate.
999 */
1000 omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
1001 if (pipe->external_rate > rate)
1002 return -ENOSPC;
1003 }
1004
Sakari Ailusccddd912012-01-17 12:29:38 -03001005 return 0;
1006}
1007
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001008/*
1009 * Stream management
1010 *
1011 * Every ISP pipeline has a single input and a single output. The input can be
1012 * either a sensor or a video node. The output is always a video node.
1013 *
1014 * As every pipeline has an output video node, the ISP video objects at the
1015 * pipeline output stores the pipeline state. It tracks the streaming state of
1016 * both the input and output, as well as the availability of buffers.
1017 *
1018 * In sensor-to-memory mode, frames are always available at the pipeline input.
1019 * Starting the sensor usually requires I2C transfers and must be done in
1020 * interruptible context. The pipeline is started and stopped synchronously
1021 * to the stream on/off commands. All modules in the pipeline will get their
1022 * subdev set stream handler called. The module at the end of the pipeline must
1023 * delay starting the hardware until buffers are available at its output.
1024 *
1025 * In memory-to-memory mode, starting/stopping the stream requires
1026 * synchronization between the input and output. ISP modules can't be stopped
1027 * in the middle of a frame, and at least some of the modules seem to become
1028 * busy as soon as they're started, even if they don't receive a frame start
1029 * event. For that reason frames need to be processed in single-shot mode. The
1030 * driver needs to wait until a frame is completely processed and written to
1031 * memory before restarting the pipeline for the next frame. Pipelined
1032 * processing might be possible but requires more testing.
1033 *
1034 * Stream start must be delayed until buffers are available at both the input
1035 * and output. The pipeline must be started in the videobuf queue callback with
1036 * the buffers queue spinlock held. The modules subdev set stream operation must
1037 * not sleep.
1038 */
1039static int
1040isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
1041{
1042 struct isp_video_fh *vfh = to_isp_video_fh(fh);
1043 struct isp_video *video = video_drvdata(file);
1044 enum isp_pipeline_state state;
1045 struct isp_pipeline *pipe;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001046 unsigned long flags;
1047 int ret;
1048
1049 if (type != video->type)
1050 return -EINVAL;
1051
1052 mutex_lock(&video->stream_lock);
1053
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001054 /* Start streaming on the pipeline. No link touching an entity in the
1055 * pipeline can be activated or deactivated once streaming is started.
1056 */
1057 pipe = video->video.entity.pipe
1058 ? to_isp_pipeline(&video->video.entity) : &video->pipe;
Sakari Ailusb0cd79e2012-01-16 18:59:02 -03001059
Sakari Ailus17d3d402015-12-16 11:32:30 -02001060 ret = media_entity_enum_init(&pipe->ent_enum, &video->isp->media_dev);
1061 if (ret)
1062 goto err_enum_init;
Sakari Ailusae5df812012-03-05 20:22:41 -03001063
Laurent Pinchart78c66fb2015-05-20 04:08:30 -03001064 /* TODO: Implement PM QoS */
Sakari Ailusb0cd79e2012-01-16 18:59:02 -03001065 pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]);
1066 pipe->max_rate = pipe->l3_ick;
1067
Sakari Ailusda392572011-10-10 17:05:24 -03001068 ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe);
1069 if (ret < 0)
1070 goto err_pipeline_start;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001071
1072 /* Verify that the currently configured format matches the output of
1073 * the connected subdev.
1074 */
1075 ret = isp_video_check_format(video, vfh);
1076 if (ret < 0)
Sakari Ailusda392572011-10-10 17:05:24 -03001077 goto err_check_format;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001078
1079 video->bpl_padding = ret;
1080 video->bpl_value = vfh->format.fmt.pix.bytesperline;
1081
Sakari Ailusae5df812012-03-05 20:22:41 -03001082 ret = isp_video_get_graph_data(video, pipe);
1083 if (ret < 0)
1084 goto err_check_format;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001085
Sakari Ailusae5df812012-03-05 20:22:41 -03001086 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001087 state = ISP_PIPELINE_STREAM_OUTPUT | ISP_PIPELINE_IDLE_OUTPUT;
Sakari Ailusae5df812012-03-05 20:22:41 -03001088 else
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001089 state = ISP_PIPELINE_STREAM_INPUT | ISP_PIPELINE_IDLE_INPUT;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001090
Sakari Ailusccddd912012-01-17 12:29:38 -03001091 ret = isp_video_check_external_subdevs(video, pipe);
1092 if (ret < 0)
1093 goto err_check_format;
1094
Laurent Pinchart875e2e32011-12-07 08:34:50 -03001095 pipe->error = false;
1096
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001097 spin_lock_irqsave(&pipe->lock, flags);
1098 pipe->state &= ~ISP_PIPELINE_STREAM;
1099 pipe->state |= state;
1100 spin_unlock_irqrestore(&pipe->lock, flags);
1101
1102 /* Set the maximum time per frame as the value requested by userspace.
1103 * This is a soft limit that can be overridden if the hardware doesn't
1104 * support the request limit.
1105 */
1106 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1107 pipe->max_timeperframe = vfh->timeperframe;
1108
1109 video->queue = &vfh->queue;
1110 INIT_LIST_HEAD(&video->dmaqueue);
1111 atomic_set(&pipe->frame_number, -1);
Laurent Pinchart9a36d8e2014-05-19 16:37:38 -03001112 pipe->field = vfh->format.fmt.pix.field;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001113
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001114 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001115 ret = vb2_streamon(&vfh->queue, type);
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001116 mutex_unlock(&video->queue_lock);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001117 if (ret < 0)
Sakari Ailusda392572011-10-10 17:05:24 -03001118 goto err_check_format;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001119
Sakari Ailusda392572011-10-10 17:05:24 -03001120 mutex_unlock(&video->stream_lock);
Sakari Ailus17d3d402015-12-16 11:32:30 -02001121
Sakari Ailusda392572011-10-10 17:05:24 -03001122 return 0;
1123
Sakari Ailusda392572011-10-10 17:05:24 -03001124err_check_format:
1125 media_entity_pipeline_stop(&video->video.entity);
1126err_pipeline_start:
Laurent Pinchart78c66fb2015-05-20 04:08:30 -03001127 /* TODO: Implement PM QoS */
Sakari Ailusda392572011-10-10 17:05:24 -03001128 /* The DMA queue must be emptied here, otherwise CCDC interrupts that
1129 * will get triggered the next time the CCDC is powered up will try to
1130 * access buffers that might have been freed but still present in the
1131 * DMA queue. This can easily get triggered if the above
1132 * omap3isp_pipeline_set_stream() call fails on a system with a
1133 * free-running sensor.
1134 */
1135 INIT_LIST_HEAD(&video->dmaqueue);
1136 video->queue = NULL;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001137
Sakari Ailus17d3d402015-12-16 11:32:30 -02001138 media_entity_enum_cleanup(&pipe->ent_enum);
1139
1140err_enum_init:
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001141 mutex_unlock(&video->stream_lock);
Sakari Ailus17d3d402015-12-16 11:32:30 -02001142
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001143 return ret;
1144}
1145
1146static int
1147isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
1148{
1149 struct isp_video_fh *vfh = to_isp_video_fh(fh);
1150 struct isp_video *video = video_drvdata(file);
1151 struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
1152 enum isp_pipeline_state state;
1153 unsigned int streaming;
1154 unsigned long flags;
1155
1156 if (type != video->type)
1157 return -EINVAL;
1158
1159 mutex_lock(&video->stream_lock);
1160
1161 /* Make sure we're not streaming yet. */
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001162 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001163 streaming = vb2_is_streaming(&vfh->queue);
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001164 mutex_unlock(&video->queue_lock);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001165
1166 if (!streaming)
1167 goto done;
1168
1169 /* Update the pipeline state. */
1170 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1171 state = ISP_PIPELINE_STREAM_OUTPUT
1172 | ISP_PIPELINE_QUEUE_OUTPUT;
1173 else
1174 state = ISP_PIPELINE_STREAM_INPUT
1175 | ISP_PIPELINE_QUEUE_INPUT;
1176
1177 spin_lock_irqsave(&pipe->lock, flags);
1178 pipe->state &= ~state;
1179 spin_unlock_irqrestore(&pipe->lock, flags);
1180
1181 /* Stop the stream. */
1182 omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_STOPPED);
Laurent Pinchart08344492014-04-20 20:59:03 -03001183 omap3isp_video_cancel_stream(video);
1184
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001185 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001186 vb2_streamoff(&vfh->queue, type);
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001187 mutex_unlock(&video->queue_lock);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001188 video->queue = NULL;
Laurent Pinchart661112c2013-12-09 11:36:51 -03001189 video->error = false;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001190
Laurent Pinchart78c66fb2015-05-20 04:08:30 -03001191 /* TODO: Implement PM QoS */
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001192 media_entity_pipeline_stop(&video->video.entity);
1193
Sakari Ailus17d3d402015-12-16 11:32:30 -02001194 media_entity_enum_cleanup(&pipe->ent_enum);
1195
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001196done:
1197 mutex_unlock(&video->stream_lock);
1198 return 0;
1199}
1200
1201static int
1202isp_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
1203{
1204 if (input->index > 0)
1205 return -EINVAL;
1206
1207 strlcpy(input->name, "camera", sizeof(input->name));
1208 input->type = V4L2_INPUT_TYPE_CAMERA;
1209
1210 return 0;
1211}
1212
1213static int
1214isp_video_g_input(struct file *file, void *fh, unsigned int *input)
1215{
1216 *input = 0;
1217
1218 return 0;
1219}
1220
1221static int
1222isp_video_s_input(struct file *file, void *fh, unsigned int input)
1223{
1224 return input == 0 ? 0 : -EINVAL;
1225}
1226
1227static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
1228 .vidioc_querycap = isp_video_querycap,
1229 .vidioc_g_fmt_vid_cap = isp_video_get_format,
1230 .vidioc_s_fmt_vid_cap = isp_video_set_format,
1231 .vidioc_try_fmt_vid_cap = isp_video_try_format,
1232 .vidioc_g_fmt_vid_out = isp_video_get_format,
1233 .vidioc_s_fmt_vid_out = isp_video_set_format,
1234 .vidioc_try_fmt_vid_out = isp_video_try_format,
1235 .vidioc_cropcap = isp_video_cropcap,
1236 .vidioc_g_crop = isp_video_get_crop,
1237 .vidioc_s_crop = isp_video_set_crop,
1238 .vidioc_g_parm = isp_video_get_param,
1239 .vidioc_s_parm = isp_video_set_param,
1240 .vidioc_reqbufs = isp_video_reqbufs,
1241 .vidioc_querybuf = isp_video_querybuf,
1242 .vidioc_qbuf = isp_video_qbuf,
1243 .vidioc_dqbuf = isp_video_dqbuf,
1244 .vidioc_streamon = isp_video_streamon,
1245 .vidioc_streamoff = isp_video_streamoff,
1246 .vidioc_enum_input = isp_video_enum_input,
1247 .vidioc_g_input = isp_video_g_input,
1248 .vidioc_s_input = isp_video_s_input,
1249};
1250
1251/* -----------------------------------------------------------------------------
1252 * V4L2 file operations
1253 */
1254
1255static int isp_video_open(struct file *file)
1256{
1257 struct isp_video *video = video_drvdata(file);
1258 struct isp_video_fh *handle;
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001259 struct vb2_queue *queue;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001260 int ret = 0;
1261
1262 handle = kzalloc(sizeof(*handle), GFP_KERNEL);
1263 if (handle == NULL)
1264 return -ENOMEM;
1265
1266 v4l2_fh_init(&handle->vfh, &video->video);
1267 v4l2_fh_add(&handle->vfh);
1268
1269 /* If this is the first user, initialise the pipeline. */
1270 if (omap3isp_get(video->isp) == NULL) {
1271 ret = -EBUSY;
1272 goto done;
1273 }
1274
Sakari Ailus28461452015-12-16 11:32:24 -02001275 ret = media_entity_graph_walk_init(&handle->graph,
1276 &video->isp->media_dev);
1277 if (ret)
1278 goto done;
1279
1280 ret = omap3isp_pipeline_pm_use(&video->video.entity, 1, &handle->graph);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001281 if (ret < 0) {
1282 omap3isp_put(video->isp);
1283 goto done;
1284 }
1285
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001286 queue = &handle->queue;
1287 queue->type = video->type;
1288 queue->io_modes = VB2_MMAP | VB2_USERPTR;
1289 queue->drv_priv = handle;
1290 queue->ops = &isp_video_queue_ops;
1291 queue->mem_ops = &vb2_dma_contig_memops;
1292 queue->buf_struct_size = sizeof(struct isp_buffer);
1293 queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1294
1295 ret = vb2_queue_init(&handle->queue);
1296 if (ret < 0) {
1297 omap3isp_put(video->isp);
1298 goto done;
1299 }
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001300
1301 memset(&handle->format, 0, sizeof(handle->format));
1302 handle->format.type = video->type;
1303 handle->timeperframe.denominator = 1;
1304
1305 handle->video = video;
1306 file->private_data = &handle->vfh;
1307
1308done:
1309 if (ret < 0) {
1310 v4l2_fh_del(&handle->vfh);
Sakari Ailus28461452015-12-16 11:32:24 -02001311 media_entity_graph_walk_cleanup(&handle->graph);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001312 kfree(handle);
1313 }
1314
1315 return ret;
1316}
1317
1318static int isp_video_release(struct file *file)
1319{
1320 struct isp_video *video = video_drvdata(file);
1321 struct v4l2_fh *vfh = file->private_data;
1322 struct isp_video_fh *handle = to_isp_video_fh(vfh);
1323
1324 /* Disable streaming and free the buffers queue resources. */
1325 isp_video_streamoff(file, vfh, video->type);
1326
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001327 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001328 vb2_queue_release(&handle->queue);
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001329 mutex_unlock(&video->queue_lock);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001330
Sakari Ailus28461452015-12-16 11:32:24 -02001331 omap3isp_pipeline_pm_use(&video->video.entity, 0, &handle->graph);
1332 media_entity_graph_walk_cleanup(&handle->graph);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001333
1334 /* Release the file handle. */
1335 v4l2_fh_del(vfh);
1336 kfree(handle);
1337 file->private_data = NULL;
1338
1339 omap3isp_put(video->isp);
1340
1341 return 0;
1342}
1343
1344static unsigned int isp_video_poll(struct file *file, poll_table *wait)
1345{
1346 struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001347 struct isp_video *video = video_drvdata(file);
1348 int ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001349
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001350 mutex_lock(&video->queue_lock);
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001351 ret = vb2_poll(&vfh->queue, file, wait);
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001352 mutex_unlock(&video->queue_lock);
1353
1354 return ret;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001355}
1356
1357static int isp_video_mmap(struct file *file, struct vm_area_struct *vma)
1358{
1359 struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
1360
Laurent Pinchart9be293692015-02-24 07:39:49 -03001361 return vb2_mmap(&vfh->queue, vma);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001362}
1363
1364static struct v4l2_file_operations isp_video_fops = {
1365 .owner = THIS_MODULE,
1366 .unlocked_ioctl = video_ioctl2,
1367 .open = isp_video_open,
1368 .release = isp_video_release,
1369 .poll = isp_video_poll,
1370 .mmap = isp_video_mmap,
1371};
1372
1373/* -----------------------------------------------------------------------------
1374 * ISP video core
1375 */
1376
1377static const struct isp_video_operations isp_video_dummy_ops = {
1378};
1379
1380int omap3isp_video_init(struct isp_video *video, const char *name)
1381{
1382 const char *direction;
1383 int ret;
1384
1385 switch (video->type) {
1386 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1387 direction = "output";
Sakari Ailus8dad9362013-10-02 20:17:52 -03001388 video->pad.flags = MEDIA_PAD_FL_SINK
1389 | MEDIA_PAD_FL_MUST_CONNECT;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001390 break;
1391 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1392 direction = "input";
Sakari Ailus8dad9362013-10-02 20:17:52 -03001393 video->pad.flags = MEDIA_PAD_FL_SOURCE
1394 | MEDIA_PAD_FL_MUST_CONNECT;
Hans Verkuil954f3402012-09-05 06:05:50 -03001395 video->video.vfl_dir = VFL_DIR_TX;
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001396 break;
1397
1398 default:
1399 return -EINVAL;
1400 }
1401
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001402 video->alloc_ctx = vb2_dma_contig_init_ctx(video->isp->dev);
1403 if (IS_ERR(video->alloc_ctx))
1404 return PTR_ERR(video->alloc_ctx);
1405
Mauro Carvalho Chehabab22e772015-12-11 07:44:40 -02001406 ret = media_entity_pads_init(&video->video.entity, 1, &video->pad);
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001407 if (ret < 0) {
1408 vb2_dma_contig_cleanup_ctx(video->alloc_ctx);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001409 return ret;
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001410 }
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001411
1412 mutex_init(&video->mutex);
1413 atomic_set(&video->active, 0);
1414
1415 spin_lock_init(&video->pipe.lock);
1416 mutex_init(&video->stream_lock);
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001417 mutex_init(&video->queue_lock);
Laurent Pincharte8feb872014-03-09 20:57:53 -03001418 spin_lock_init(&video->irqlock);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001419
1420 /* Initialize the video device. */
1421 if (video->ops == NULL)
1422 video->ops = &isp_video_dummy_ops;
1423
1424 video->video.fops = &isp_video_fops;
1425 snprintf(video->video.name, sizeof(video->video.name),
1426 "OMAP3 ISP %s %s", name, direction);
1427 video->video.vfl_type = VFL_TYPE_GRABBER;
1428 video->video.release = video_device_release_empty;
1429 video->video.ioctl_ops = &isp_video_ioctl_ops;
1430 video->pipe.stream_state = ISP_PIPELINE_STREAM_STOPPED;
1431
1432 video_set_drvdata(&video->video, video);
1433
1434 return 0;
1435}
1436
Laurent Pinchart63b4ca22011-09-22 16:54:34 -03001437void omap3isp_video_cleanup(struct isp_video *video)
1438{
Laurent Pinchartfbac1402014-03-09 20:36:15 -03001439 vb2_dma_contig_cleanup_ctx(video->alloc_ctx);
Laurent Pinchart63b4ca22011-09-22 16:54:34 -03001440 media_entity_cleanup(&video->video.entity);
Laurent Pinchart988d54c2014-03-09 20:57:53 -03001441 mutex_destroy(&video->queue_lock);
Laurent Pincharted33ac82011-09-22 17:09:26 -03001442 mutex_destroy(&video->stream_lock);
1443 mutex_destroy(&video->mutex);
Laurent Pinchart63b4ca22011-09-22 16:54:34 -03001444}
1445
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001446int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
1447{
1448 int ret;
1449
1450 video->video.v4l2_dev = vdev;
1451
1452 ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
1453 if (ret < 0)
Laurent Pinchart4feca392012-10-22 08:28:51 -03001454 dev_err(video->isp->dev,
1455 "%s: could not register video device (%d)\n",
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001456 __func__, ret);
1457
1458 return ret;
1459}
1460
1461void omap3isp_video_unregister(struct isp_video *video)
1462{
Laurent Pinchart63b4ca22011-09-22 16:54:34 -03001463 if (video_is_registered(&video->video))
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001464 video_unregister_device(&video->video);
Laurent Pinchartad614ac2011-02-12 18:05:06 -03001465}