• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * timblogiw.c timberdale FPGA LogiWin Video In driver
3  * Copyright (c) 2009-2010 Intel Corporation
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 /* Supports:
20  * Timberdale FPGA LogiWin Video In
21  */
22 
23 #include <linux/platform_device.h>
24 #include <linux/slab.h>
25 #include <linux/dmaengine.h>
26 #include <linux/scatterlist.h>
27 #include <linux/interrupt.h>
28 #include <linux/list.h>
29 #include <linux/i2c.h>
30 #include <linux/module.h>
31 #include <media/v4l2-ioctl.h>
32 #include <media/v4l2-device.h>
33 #include <media/videobuf-dma-contig.h>
34 #include <media/timb_video.h>
35 
36 #define DRIVER_NAME			"timb-video"
37 
38 #define TIMBLOGIWIN_NAME		"Timberdale Video-In"
39 #define TIMBLOGIW_VERSION_CODE		0x04
40 
41 #define TIMBLOGIW_LINES_PER_DESC	44
42 #define TIMBLOGIW_MAX_VIDEO_MEM		16
43 
44 #define TIMBLOGIW_HAS_DECODER(lw)	(lw->pdata.encoder.module_name)
45 
46 
47 struct timblogiw {
48 	struct video_device		video_dev;
49 	struct v4l2_device		v4l2_dev; /* mutual exclusion */
50 	struct mutex			lock;
51 	struct device			*dev;
52 	struct timb_video_platform_data pdata;
53 	struct v4l2_subdev		*sd_enc;	/* encoder */
54 	bool				opened;
55 };
56 
57 struct timblogiw_tvnorm {
58 	v4l2_std_id std;
59 	u16     width;
60 	u16     height;
61 	u8	fps;
62 };
63 
64 struct timblogiw_fh {
65 	struct videobuf_queue		vb_vidq;
66 	struct timblogiw_tvnorm const	*cur_norm;
67 	struct list_head		capture;
68 	struct dma_chan			*chan;
69 	spinlock_t			queue_lock; /* mutual exclusion */
70 	unsigned int			frame_count;
71 };
72 
73 struct timblogiw_buffer {
74 	/* common v4l buffer stuff -- must be first */
75 	struct videobuf_buffer	vb;
76 	struct scatterlist	sg[16];
77 	dma_cookie_t		cookie;
78 	struct timblogiw_fh	*fh;
79 };
80 
81 static const struct timblogiw_tvnorm timblogiw_tvnorms[] = {
82 	{
83 		.std			= V4L2_STD_PAL,
84 		.width			= 720,
85 		.height			= 576,
86 		.fps			= 25
87 	},
88 	{
89 		.std			= V4L2_STD_NTSC,
90 		.width			= 720,
91 		.height			= 480,
92 		.fps			= 30
93 	}
94 };
95 
timblogiw_bytes_per_line(const struct timblogiw_tvnorm * norm)96 static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm)
97 {
98 	return norm->width * 2;
99 }
100 
101 
timblogiw_frame_size(const struct timblogiw_tvnorm * norm)102 static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm)
103 {
104 	return norm->height * timblogiw_bytes_per_line(norm);
105 }
106 
timblogiw_get_norm(const v4l2_std_id std)107 static const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std)
108 {
109 	int i;
110 	for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
111 		if (timblogiw_tvnorms[i].std & std)
112 			return timblogiw_tvnorms + i;
113 
114 	/* default to first element */
115 	return timblogiw_tvnorms;
116 }
117 
timblogiw_dma_cb(void * data)118 static void timblogiw_dma_cb(void *data)
119 {
120 	struct timblogiw_buffer *buf = data;
121 	struct timblogiw_fh *fh = buf->fh;
122 	struct videobuf_buffer *vb = &buf->vb;
123 
124 	spin_lock(&fh->queue_lock);
125 
126 	/* mark the transfer done */
127 	buf->cookie = -1;
128 
129 	fh->frame_count++;
130 
131 	if (vb->state != VIDEOBUF_ERROR) {
132 		list_del(&vb->queue);
133 		v4l2_get_timestamp(&vb->ts);
134 		vb->field_count = fh->frame_count * 2;
135 		vb->state = VIDEOBUF_DONE;
136 
137 		wake_up(&vb->done);
138 	}
139 
140 	if (!list_empty(&fh->capture)) {
141 		vb = list_entry(fh->capture.next, struct videobuf_buffer,
142 			queue);
143 		vb->state = VIDEOBUF_ACTIVE;
144 	}
145 
146 	spin_unlock(&fh->queue_lock);
147 }
148 
timblogiw_dma_filter_fn(struct dma_chan * chan,void * filter_param)149 static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param)
150 {
151 	return chan->chan_id == (uintptr_t)filter_param;
152 }
153 
154 /* IOCTL functions */
155 
timblogiw_g_fmt(struct file * file,void * priv,struct v4l2_format * format)156 static int timblogiw_g_fmt(struct file *file, void  *priv,
157 	struct v4l2_format *format)
158 {
159 	struct video_device *vdev = video_devdata(file);
160 	struct timblogiw *lw = video_get_drvdata(vdev);
161 	struct timblogiw_fh *fh = priv;
162 
163 	dev_dbg(&vdev->dev, "%s entry\n", __func__);
164 
165 	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
166 		return -EINVAL;
167 
168 	mutex_lock(&lw->lock);
169 
170 	format->fmt.pix.width = fh->cur_norm->width;
171 	format->fmt.pix.height = fh->cur_norm->height;
172 	format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
173 	format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm);
174 	format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm);
175 	format->fmt.pix.field = V4L2_FIELD_NONE;
176 
177 	mutex_unlock(&lw->lock);
178 
179 	return 0;
180 }
181 
timblogiw_try_fmt(struct file * file,void * priv,struct v4l2_format * format)182 static int timblogiw_try_fmt(struct file *file, void  *priv,
183 	struct v4l2_format *format)
184 {
185 	struct video_device *vdev = video_devdata(file);
186 	struct v4l2_pix_format *pix = &format->fmt.pix;
187 
188 	dev_dbg(&vdev->dev,
189 		"%s - width=%d, height=%d, pixelformat=%d, field=%d\n"
190 		"bytes per line %d, size image: %d, colorspace: %d\n",
191 		__func__,
192 		pix->width, pix->height, pix->pixelformat, pix->field,
193 		pix->bytesperline, pix->sizeimage, pix->colorspace);
194 
195 	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
196 		return -EINVAL;
197 
198 	if (pix->field != V4L2_FIELD_NONE)
199 		return -EINVAL;
200 
201 	if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
202 		return -EINVAL;
203 
204 	return 0;
205 }
206 
timblogiw_s_fmt(struct file * file,void * priv,struct v4l2_format * format)207 static int timblogiw_s_fmt(struct file *file, void  *priv,
208 	struct v4l2_format *format)
209 {
210 	struct video_device *vdev = video_devdata(file);
211 	struct timblogiw *lw = video_get_drvdata(vdev);
212 	struct timblogiw_fh *fh = priv;
213 	struct v4l2_pix_format *pix = &format->fmt.pix;
214 	int err;
215 
216 	mutex_lock(&lw->lock);
217 
218 	err = timblogiw_try_fmt(file, priv, format);
219 	if (err)
220 		goto out;
221 
222 	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
223 		dev_err(&vdev->dev, "%s queue busy\n", __func__);
224 		err = -EBUSY;
225 		goto out;
226 	}
227 
228 	pix->width = fh->cur_norm->width;
229 	pix->height = fh->cur_norm->height;
230 
231 out:
232 	mutex_unlock(&lw->lock);
233 	return err;
234 }
235 
timblogiw_querycap(struct file * file,void * priv,struct v4l2_capability * cap)236 static int timblogiw_querycap(struct file *file, void  *priv,
237 	struct v4l2_capability *cap)
238 {
239 	struct video_device *vdev = video_devdata(file);
240 
241 	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
242 	strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1);
243 	strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1);
244 	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vdev->name);
245 	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
246 		V4L2_CAP_READWRITE;
247 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
248 
249 	return 0;
250 }
251 
timblogiw_enum_fmt(struct file * file,void * priv,struct v4l2_fmtdesc * fmt)252 static int timblogiw_enum_fmt(struct file *file, void  *priv,
253 	struct v4l2_fmtdesc *fmt)
254 {
255 	struct video_device *vdev = video_devdata(file);
256 
257 	dev_dbg(&vdev->dev, "%s, index: %d\n",  __func__, fmt->index);
258 
259 	if (fmt->index != 0)
260 		return -EINVAL;
261 	memset(fmt, 0, sizeof(*fmt));
262 	fmt->index = 0;
263 	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
264 	strncpy(fmt->description, "4:2:2, packed, YUYV",
265 		sizeof(fmt->description)-1);
266 	fmt->pixelformat = V4L2_PIX_FMT_UYVY;
267 
268 	return 0;
269 }
270 
timblogiw_g_parm(struct file * file,void * priv,struct v4l2_streamparm * sp)271 static int timblogiw_g_parm(struct file *file, void *priv,
272 	struct v4l2_streamparm *sp)
273 {
274 	struct timblogiw_fh *fh = priv;
275 	struct v4l2_captureparm *cp = &sp->parm.capture;
276 
277 	cp->capability = V4L2_CAP_TIMEPERFRAME;
278 	cp->timeperframe.numerator = 1;
279 	cp->timeperframe.denominator = fh->cur_norm->fps;
280 
281 	return 0;
282 }
283 
timblogiw_reqbufs(struct file * file,void * priv,struct v4l2_requestbuffers * rb)284 static int timblogiw_reqbufs(struct file *file, void  *priv,
285 	struct v4l2_requestbuffers *rb)
286 {
287 	struct video_device *vdev = video_devdata(file);
288 	struct timblogiw_fh *fh = priv;
289 
290 	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
291 
292 	return videobuf_reqbufs(&fh->vb_vidq, rb);
293 }
294 
timblogiw_querybuf(struct file * file,void * priv,struct v4l2_buffer * b)295 static int timblogiw_querybuf(struct file *file, void  *priv,
296 	struct v4l2_buffer *b)
297 {
298 	struct video_device *vdev = video_devdata(file);
299 	struct timblogiw_fh *fh = priv;
300 
301 	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
302 
303 	return videobuf_querybuf(&fh->vb_vidq, b);
304 }
305 
timblogiw_qbuf(struct file * file,void * priv,struct v4l2_buffer * b)306 static int timblogiw_qbuf(struct file *file, void  *priv, struct v4l2_buffer *b)
307 {
308 	struct video_device *vdev = video_devdata(file);
309 	struct timblogiw_fh *fh = priv;
310 
311 	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
312 
313 	return videobuf_qbuf(&fh->vb_vidq, b);
314 }
315 
timblogiw_dqbuf(struct file * file,void * priv,struct v4l2_buffer * b)316 static int timblogiw_dqbuf(struct file *file, void  *priv,
317 	struct v4l2_buffer *b)
318 {
319 	struct video_device *vdev = video_devdata(file);
320 	struct timblogiw_fh *fh = priv;
321 
322 	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
323 
324 	return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
325 }
326 
timblogiw_g_std(struct file * file,void * priv,v4l2_std_id * std)327 static int timblogiw_g_std(struct file *file, void  *priv, v4l2_std_id *std)
328 {
329 	struct video_device *vdev = video_devdata(file);
330 	struct timblogiw_fh *fh = priv;
331 
332 	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
333 
334 	*std = fh->cur_norm->std;
335 	return 0;
336 }
337 
timblogiw_s_std(struct file * file,void * priv,v4l2_std_id std)338 static int timblogiw_s_std(struct file *file, void  *priv, v4l2_std_id std)
339 {
340 	struct video_device *vdev = video_devdata(file);
341 	struct timblogiw *lw = video_get_drvdata(vdev);
342 	struct timblogiw_fh *fh = priv;
343 	int err = 0;
344 
345 	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
346 
347 	mutex_lock(&lw->lock);
348 
349 	if (TIMBLOGIW_HAS_DECODER(lw))
350 		err = v4l2_subdev_call(lw->sd_enc, video, s_std, std);
351 
352 	if (!err)
353 		fh->cur_norm = timblogiw_get_norm(std);
354 
355 	mutex_unlock(&lw->lock);
356 
357 	return err;
358 }
359 
timblogiw_enuminput(struct file * file,void * priv,struct v4l2_input * inp)360 static int timblogiw_enuminput(struct file *file, void  *priv,
361 	struct v4l2_input *inp)
362 {
363 	struct video_device *vdev = video_devdata(file);
364 	int i;
365 
366 	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
367 
368 	if (inp->index != 0)
369 		return -EINVAL;
370 
371 	inp->index = 0;
372 
373 	strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1);
374 	inp->type = V4L2_INPUT_TYPE_CAMERA;
375 
376 	inp->std = 0;
377 	for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
378 		inp->std |= timblogiw_tvnorms[i].std;
379 
380 	return 0;
381 }
382 
timblogiw_g_input(struct file * file,void * priv,unsigned int * input)383 static int timblogiw_g_input(struct file *file, void  *priv,
384 	unsigned int *input)
385 {
386 	struct video_device *vdev = video_devdata(file);
387 
388 	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
389 
390 	*input = 0;
391 
392 	return 0;
393 }
394 
timblogiw_s_input(struct file * file,void * priv,unsigned int input)395 static int timblogiw_s_input(struct file *file, void  *priv, unsigned int input)
396 {
397 	struct video_device *vdev = video_devdata(file);
398 
399 	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
400 
401 	if (input != 0)
402 		return -EINVAL;
403 	return 0;
404 }
405 
timblogiw_streamon(struct file * file,void * priv,enum v4l2_buf_type type)406 static int timblogiw_streamon(struct file *file, void  *priv, enum v4l2_buf_type type)
407 {
408 	struct video_device *vdev = video_devdata(file);
409 	struct timblogiw_fh *fh = priv;
410 
411 	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
412 
413 	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
414 		dev_dbg(&vdev->dev, "%s - No capture device\n", __func__);
415 		return -EINVAL;
416 	}
417 
418 	fh->frame_count = 0;
419 	return videobuf_streamon(&fh->vb_vidq);
420 }
421 
timblogiw_streamoff(struct file * file,void * priv,enum v4l2_buf_type type)422 static int timblogiw_streamoff(struct file *file, void  *priv,
423 	enum v4l2_buf_type type)
424 {
425 	struct video_device *vdev = video_devdata(file);
426 	struct timblogiw_fh *fh = priv;
427 
428 	dev_dbg(&vdev->dev, "%s entry\n",  __func__);
429 
430 	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
431 		return -EINVAL;
432 
433 	return videobuf_streamoff(&fh->vb_vidq);
434 }
435 
timblogiw_querystd(struct file * file,void * priv,v4l2_std_id * std)436 static int timblogiw_querystd(struct file *file, void  *priv, v4l2_std_id *std)
437 {
438 	struct video_device *vdev = video_devdata(file);
439 	struct timblogiw *lw = video_get_drvdata(vdev);
440 	struct timblogiw_fh *fh = priv;
441 
442 	dev_dbg(&vdev->dev, "%s entry\n",  __func__);
443 
444 	if (TIMBLOGIW_HAS_DECODER(lw))
445 		return v4l2_subdev_call(lw->sd_enc, video, querystd, std);
446 	else {
447 		*std = fh->cur_norm->std;
448 		return 0;
449 	}
450 }
451 
timblogiw_enum_framesizes(struct file * file,void * priv,struct v4l2_frmsizeenum * fsize)452 static int timblogiw_enum_framesizes(struct file *file, void  *priv,
453 	struct v4l2_frmsizeenum *fsize)
454 {
455 	struct video_device *vdev = video_devdata(file);
456 	struct timblogiw_fh *fh = priv;
457 
458 	dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n",  __func__,
459 		fsize->index, fsize->pixel_format);
460 
461 	if ((fsize->index != 0) ||
462 		(fsize->pixel_format != V4L2_PIX_FMT_UYVY))
463 		return -EINVAL;
464 
465 	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
466 	fsize->discrete.width = fh->cur_norm->width;
467 	fsize->discrete.height = fh->cur_norm->height;
468 
469 	return 0;
470 }
471 
472 /* Video buffer functions */
473 
buffer_setup(struct videobuf_queue * vq,unsigned int * count,unsigned int * size)474 static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
475 	unsigned int *size)
476 {
477 	struct timblogiw_fh *fh = vq->priv_data;
478 
479 	*size = timblogiw_frame_size(fh->cur_norm);
480 
481 	if (!*count)
482 		*count = 32;
483 
484 	while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024)
485 		(*count)--;
486 
487 	return 0;
488 }
489 
buffer_prepare(struct videobuf_queue * vq,struct videobuf_buffer * vb,enum v4l2_field field)490 static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
491 	enum v4l2_field field)
492 {
493 	struct timblogiw_fh *fh = vq->priv_data;
494 	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
495 		vb);
496 	unsigned int data_size = timblogiw_frame_size(fh->cur_norm);
497 	int err = 0;
498 
499 	if (vb->baddr && vb->bsize < data_size)
500 		/* User provided buffer, but it is too small */
501 		return -ENOMEM;
502 
503 	vb->size = data_size;
504 	vb->width = fh->cur_norm->width;
505 	vb->height = fh->cur_norm->height;
506 	vb->field = field;
507 
508 	if (vb->state == VIDEOBUF_NEEDS_INIT) {
509 		int i;
510 		unsigned int size;
511 		unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
512 			timblogiw_bytes_per_line(fh->cur_norm);
513 		dma_addr_t addr;
514 
515 		sg_init_table(buf->sg, ARRAY_SIZE(buf->sg));
516 
517 		err = videobuf_iolock(vq, vb, NULL);
518 		if (err)
519 			goto err;
520 
521 		addr = videobuf_to_dma_contig(vb);
522 		for (i = 0, size = 0; size < data_size; i++) {
523 			sg_dma_address(buf->sg + i) = addr + size;
524 			size += bytes_per_desc;
525 			sg_dma_len(buf->sg + i) = (size > data_size) ?
526 				(bytes_per_desc - (size - data_size)) :
527 				bytes_per_desc;
528 		}
529 
530 		vb->state = VIDEOBUF_PREPARED;
531 		buf->cookie = -1;
532 		buf->fh = fh;
533 	}
534 
535 	return 0;
536 
537 err:
538 	videobuf_dma_contig_free(vq, vb);
539 	vb->state = VIDEOBUF_NEEDS_INIT;
540 	return err;
541 }
542 
buffer_queue(struct videobuf_queue * vq,struct videobuf_buffer * vb)543 static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
544 {
545 	struct timblogiw_fh *fh = vq->priv_data;
546 	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
547 		vb);
548 	struct dma_async_tx_descriptor *desc;
549 	int sg_elems;
550 	int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
551 		timblogiw_bytes_per_line(fh->cur_norm);
552 
553 	sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc;
554 	sg_elems +=
555 		(timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0;
556 
557 	if (list_empty(&fh->capture))
558 		vb->state = VIDEOBUF_ACTIVE;
559 	else
560 		vb->state = VIDEOBUF_QUEUED;
561 
562 	list_add_tail(&vb->queue, &fh->capture);
563 
564 	spin_unlock_irq(&fh->queue_lock);
565 
566 	desc = dmaengine_prep_slave_sg(fh->chan,
567 		buf->sg, sg_elems, DMA_DEV_TO_MEM,
568 		DMA_PREP_INTERRUPT);
569 	if (!desc) {
570 		spin_lock_irq(&fh->queue_lock);
571 		list_del_init(&vb->queue);
572 		vb->state = VIDEOBUF_PREPARED;
573 		return;
574 	}
575 
576 	desc->callback_param = buf;
577 	desc->callback = timblogiw_dma_cb;
578 
579 	buf->cookie = desc->tx_submit(desc);
580 
581 	spin_lock_irq(&fh->queue_lock);
582 }
583 
buffer_release(struct videobuf_queue * vq,struct videobuf_buffer * vb)584 static void buffer_release(struct videobuf_queue *vq,
585 	struct videobuf_buffer *vb)
586 {
587 	struct timblogiw_fh *fh = vq->priv_data;
588 	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
589 		vb);
590 
591 	videobuf_waiton(vq, vb, 0, 0);
592 	if (buf->cookie >= 0)
593 		dma_sync_wait(fh->chan, buf->cookie);
594 
595 	videobuf_dma_contig_free(vq, vb);
596 	vb->state = VIDEOBUF_NEEDS_INIT;
597 }
598 
599 static struct videobuf_queue_ops timblogiw_video_qops = {
600 	.buf_setup      = buffer_setup,
601 	.buf_prepare    = buffer_prepare,
602 	.buf_queue      = buffer_queue,
603 	.buf_release    = buffer_release,
604 };
605 
606 /* Device Operations functions */
607 
timblogiw_open(struct file * file)608 static int timblogiw_open(struct file *file)
609 {
610 	struct video_device *vdev = video_devdata(file);
611 	struct timblogiw *lw = video_get_drvdata(vdev);
612 	struct timblogiw_fh *fh;
613 	v4l2_std_id std;
614 	dma_cap_mask_t mask;
615 	int err = 0;
616 
617 	dev_dbg(&vdev->dev, "%s: entry\n", __func__);
618 
619 	mutex_lock(&lw->lock);
620 	if (lw->opened) {
621 		err = -EBUSY;
622 		goto out;
623 	}
624 
625 	if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) {
626 		struct i2c_adapter *adapt;
627 
628 		/* find the video decoder */
629 		adapt = i2c_get_adapter(lw->pdata.i2c_adapter);
630 		if (!adapt) {
631 			dev_err(&vdev->dev, "No I2C bus #%d\n",
632 				lw->pdata.i2c_adapter);
633 			err = -ENODEV;
634 			goto out;
635 		}
636 
637 		/* now find the encoder */
638 		lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt,
639 			lw->pdata.encoder.info, NULL);
640 
641 		i2c_put_adapter(adapt);
642 
643 		if (!lw->sd_enc) {
644 			dev_err(&vdev->dev, "Failed to get encoder: %s\n",
645 				lw->pdata.encoder.module_name);
646 			err = -ENODEV;
647 			goto out;
648 		}
649 	}
650 
651 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
652 	if (!fh) {
653 		err = -ENOMEM;
654 		goto out;
655 	}
656 
657 	fh->cur_norm = timblogiw_tvnorms;
658 	timblogiw_querystd(file, fh, &std);
659 	fh->cur_norm = timblogiw_get_norm(std);
660 
661 	INIT_LIST_HEAD(&fh->capture);
662 	spin_lock_init(&fh->queue_lock);
663 
664 	dma_cap_zero(mask);
665 	dma_cap_set(DMA_SLAVE, mask);
666 	dma_cap_set(DMA_PRIVATE, mask);
667 
668 	/* find the DMA channel */
669 	fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn,
670 			(void *)(uintptr_t)lw->pdata.dma_channel);
671 	if (!fh->chan) {
672 		dev_err(&vdev->dev, "Failed to get DMA channel\n");
673 		kfree(fh);
674 		err = -ENODEV;
675 		goto out;
676 	}
677 
678 	file->private_data = fh;
679 	videobuf_queue_dma_contig_init(&fh->vb_vidq,
680 		&timblogiw_video_qops, lw->dev, &fh->queue_lock,
681 		V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
682 		sizeof(struct timblogiw_buffer), fh, NULL);
683 
684 	lw->opened = true;
685 out:
686 	mutex_unlock(&lw->lock);
687 
688 	return err;
689 }
690 
timblogiw_close(struct file * file)691 static int timblogiw_close(struct file *file)
692 {
693 	struct video_device *vdev = video_devdata(file);
694 	struct timblogiw *lw = video_get_drvdata(vdev);
695 	struct timblogiw_fh *fh = file->private_data;
696 
697 	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
698 
699 	videobuf_stop(&fh->vb_vidq);
700 	videobuf_mmap_free(&fh->vb_vidq);
701 
702 	dma_release_channel(fh->chan);
703 
704 	kfree(fh);
705 
706 	mutex_lock(&lw->lock);
707 	lw->opened = false;
708 	mutex_unlock(&lw->lock);
709 	return 0;
710 }
711 
timblogiw_read(struct file * file,char __user * data,size_t count,loff_t * ppos)712 static ssize_t timblogiw_read(struct file *file, char __user *data,
713 	size_t count, loff_t *ppos)
714 {
715 	struct video_device *vdev = video_devdata(file);
716 	struct timblogiw_fh *fh = file->private_data;
717 
718 	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
719 
720 	return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
721 		file->f_flags & O_NONBLOCK);
722 }
723 
timblogiw_poll(struct file * file,struct poll_table_struct * wait)724 static unsigned int timblogiw_poll(struct file *file,
725 	struct poll_table_struct *wait)
726 {
727 	struct video_device *vdev = video_devdata(file);
728 	struct timblogiw_fh *fh = file->private_data;
729 
730 	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
731 
732 	return videobuf_poll_stream(file, &fh->vb_vidq, wait);
733 }
734 
timblogiw_mmap(struct file * file,struct vm_area_struct * vma)735 static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma)
736 {
737 	struct video_device *vdev = video_devdata(file);
738 	struct timblogiw_fh *fh = file->private_data;
739 
740 	dev_dbg(&vdev->dev, "%s: entry\n", __func__);
741 
742 	return videobuf_mmap_mapper(&fh->vb_vidq, vma);
743 }
744 
745 /* Platform device functions */
746 
747 static struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
748 	.vidioc_querycap		= timblogiw_querycap,
749 	.vidioc_enum_fmt_vid_cap	= timblogiw_enum_fmt,
750 	.vidioc_g_fmt_vid_cap		= timblogiw_g_fmt,
751 	.vidioc_try_fmt_vid_cap		= timblogiw_try_fmt,
752 	.vidioc_s_fmt_vid_cap		= timblogiw_s_fmt,
753 	.vidioc_g_parm			= timblogiw_g_parm,
754 	.vidioc_reqbufs			= timblogiw_reqbufs,
755 	.vidioc_querybuf		= timblogiw_querybuf,
756 	.vidioc_qbuf			= timblogiw_qbuf,
757 	.vidioc_dqbuf			= timblogiw_dqbuf,
758 	.vidioc_g_std			= timblogiw_g_std,
759 	.vidioc_s_std			= timblogiw_s_std,
760 	.vidioc_enum_input		= timblogiw_enuminput,
761 	.vidioc_g_input			= timblogiw_g_input,
762 	.vidioc_s_input			= timblogiw_s_input,
763 	.vidioc_streamon		= timblogiw_streamon,
764 	.vidioc_streamoff		= timblogiw_streamoff,
765 	.vidioc_querystd		= timblogiw_querystd,
766 	.vidioc_enum_framesizes		= timblogiw_enum_framesizes,
767 };
768 
769 static struct v4l2_file_operations timblogiw_fops = {
770 	.owner		= THIS_MODULE,
771 	.open		= timblogiw_open,
772 	.release	= timblogiw_close,
773 	.unlocked_ioctl		= video_ioctl2, /* V4L2 ioctl handler */
774 	.mmap		= timblogiw_mmap,
775 	.read		= timblogiw_read,
776 	.poll		= timblogiw_poll,
777 };
778 
779 static struct video_device timblogiw_template = {
780 	.name		= TIMBLOGIWIN_NAME,
781 	.fops		= &timblogiw_fops,
782 	.ioctl_ops	= &timblogiw_ioctl_ops,
783 	.release	= video_device_release_empty,
784 	.minor		= -1,
785 	.tvnorms	= V4L2_STD_PAL | V4L2_STD_NTSC
786 };
787 
timblogiw_probe(struct platform_device * pdev)788 static int timblogiw_probe(struct platform_device *pdev)
789 {
790 	int err;
791 	struct timblogiw *lw = NULL;
792 	struct timb_video_platform_data *pdata = pdev->dev.platform_data;
793 
794 	if (!pdata) {
795 		dev_err(&pdev->dev, "No platform data\n");
796 		err = -EINVAL;
797 		goto err;
798 	}
799 
800 	if (!pdata->encoder.module_name)
801 		dev_info(&pdev->dev, "Running without decoder\n");
802 
803 	lw = devm_kzalloc(&pdev->dev, sizeof(*lw), GFP_KERNEL);
804 	if (!lw) {
805 		err = -ENOMEM;
806 		goto err;
807 	}
808 
809 	if (pdev->dev.parent)
810 		lw->dev = pdev->dev.parent;
811 	else
812 		lw->dev = &pdev->dev;
813 
814 	memcpy(&lw->pdata, pdata, sizeof(lw->pdata));
815 
816 	mutex_init(&lw->lock);
817 
818 	lw->video_dev = timblogiw_template;
819 
820 	strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name));
821 	err = v4l2_device_register(NULL, &lw->v4l2_dev);
822 	if (err)
823 		goto err;
824 
825 	lw->video_dev.v4l2_dev = &lw->v4l2_dev;
826 
827 	platform_set_drvdata(pdev, lw);
828 	video_set_drvdata(&lw->video_dev, lw);
829 
830 	err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0);
831 	if (err) {
832 		dev_err(&pdev->dev, "Error reg video: %d\n", err);
833 		goto err_request;
834 	}
835 
836 	return 0;
837 
838 err_request:
839 	v4l2_device_unregister(&lw->v4l2_dev);
840 err:
841 	dev_err(&pdev->dev, "Failed to register: %d\n", err);
842 
843 	return err;
844 }
845 
timblogiw_remove(struct platform_device * pdev)846 static int timblogiw_remove(struct platform_device *pdev)
847 {
848 	struct timblogiw *lw = platform_get_drvdata(pdev);
849 
850 	video_unregister_device(&lw->video_dev);
851 
852 	v4l2_device_unregister(&lw->v4l2_dev);
853 
854 	return 0;
855 }
856 
857 static struct platform_driver timblogiw_platform_driver = {
858 	.driver = {
859 		.name	= DRIVER_NAME,
860 	},
861 	.probe		= timblogiw_probe,
862 	.remove		= timblogiw_remove,
863 };
864 
865 module_platform_driver(timblogiw_platform_driver);
866 
867 MODULE_DESCRIPTION(TIMBLOGIWIN_NAME);
868 MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>");
869 MODULE_LICENSE("GPL v2");
870 MODULE_ALIAS("platform:"DRIVER_NAME);
871