Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
timblogiw.c
Go to the documentation of this file.
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>
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 {
49  struct v4l2_device v4l2_dev; /* mutual exclusion */
50  struct mutex lock;
51  struct device *dev;
53  struct v4l2_subdev *sd_enc; /* encoder */
54  bool opened;
55 };
56 
62 };
63 
64 struct timblogiw_fh {
68  struct dma_chan *chan;
69  spinlock_t queue_lock; /* mutual exclusion */
70  unsigned int frame_count;
71 };
72 
74  /* common v4l buffer stuff -- must be first */
76  struct scatterlist sg[16];
78  struct timblogiw_fh *fh;
79 };
80 
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 
96 static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm)
97 {
98  return norm->width * 2;
99 }
100 
101 
102 static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm)
103 {
104  return norm->height * timblogiw_bytes_per_line(norm);
105 }
106 
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 
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  do_gettimeofday(&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 
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 
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 
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 
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 
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  memset(cap, 0, sizeof(*cap));
243  strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1);
244  strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1);
245  strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info));
249 
250  return 0;
251 }
252 
253 static int timblogiw_enum_fmt(struct file *file, void *priv,
254  struct v4l2_fmtdesc *fmt)
255 {
256  struct video_device *vdev = video_devdata(file);
257 
258  dev_dbg(&vdev->dev, "%s, index: %d\n", __func__, fmt->index);
259 
260  if (fmt->index != 0)
261  return -EINVAL;
262  memset(fmt, 0, sizeof(*fmt));
263  fmt->index = 0;
265  strncpy(fmt->description, "4:2:2, packed, YUYV",
266  sizeof(fmt->description)-1);
268 
269  return 0;
270 }
271 
272 static int timblogiw_g_parm(struct file *file, void *priv,
273  struct v4l2_streamparm *sp)
274 {
275  struct timblogiw_fh *fh = priv;
276  struct v4l2_captureparm *cp = &sp->parm.capture;
277 
279  cp->timeperframe.numerator = 1;
280  cp->timeperframe.denominator = fh->cur_norm->fps;
281 
282  return 0;
283 }
284 
285 static int timblogiw_reqbufs(struct file *file, void *priv,
286  struct v4l2_requestbuffers *rb)
287 {
288  struct video_device *vdev = video_devdata(file);
289  struct timblogiw_fh *fh = priv;
290 
291  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
292 
293  return videobuf_reqbufs(&fh->vb_vidq, rb);
294 }
295 
296 static int timblogiw_querybuf(struct file *file, void *priv,
297  struct v4l2_buffer *b)
298 {
299  struct video_device *vdev = video_devdata(file);
300  struct timblogiw_fh *fh = priv;
301 
302  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
303 
304  return videobuf_querybuf(&fh->vb_vidq, b);
305 }
306 
307 static int timblogiw_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
308 {
309  struct video_device *vdev = video_devdata(file);
310  struct timblogiw_fh *fh = priv;
311 
312  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
313 
314  return videobuf_qbuf(&fh->vb_vidq, b);
315 }
316 
317 static int timblogiw_dqbuf(struct file *file, void *priv,
318  struct v4l2_buffer *b)
319 {
320  struct video_device *vdev = video_devdata(file);
321  struct timblogiw_fh *fh = priv;
322 
323  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
324 
325  return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
326 }
327 
328 static int timblogiw_g_std(struct file *file, void *priv, v4l2_std_id *std)
329 {
330  struct video_device *vdev = video_devdata(file);
331  struct timblogiw_fh *fh = priv;
332 
333  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
334 
335  *std = fh->cur_norm->std;
336  return 0;
337 }
338 
339 static int timblogiw_s_std(struct file *file, void *priv, v4l2_std_id *std)
340 {
341  struct video_device *vdev = video_devdata(file);
342  struct timblogiw *lw = video_get_drvdata(vdev);
343  struct timblogiw_fh *fh = priv;
344  int err = 0;
345 
346  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
347 
348  mutex_lock(&lw->lock);
349 
350  if (TIMBLOGIW_HAS_DECODER(lw))
351  err = v4l2_subdev_call(lw->sd_enc, core, s_std, *std);
352 
353  if (!err)
354  fh->cur_norm = timblogiw_get_norm(*std);
355 
356  mutex_unlock(&lw->lock);
357 
358  return err;
359 }
360 
361 static int timblogiw_enuminput(struct file *file, void *priv,
362  struct v4l2_input *inp)
363 {
364  struct video_device *vdev = video_devdata(file);
365  int i;
366 
367  dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
368 
369  if (inp->index != 0)
370  return -EINVAL;
371 
372  inp->index = 0;
373 
374  strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1);
376 
377  inp->std = 0;
378  for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
379  inp->std |= timblogiw_tvnorms[i].std;
380 
381  return 0;
382 }
383 
384 static int timblogiw_g_input(struct file *file, void *priv,
385  unsigned int *input)
386 {
387  struct video_device *vdev = video_devdata(file);
388 
389  dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
390 
391  *input = 0;
392 
393  return 0;
394 }
395 
396 static int timblogiw_s_input(struct file *file, void *priv, unsigned int input)
397 {
398  struct video_device *vdev = video_devdata(file);
399 
400  dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
401 
402  if (input != 0)
403  return -EINVAL;
404  return 0;
405 }
406 
407 static int timblogiw_streamon(struct file *file, void *priv, unsigned int type)
408 {
409  struct video_device *vdev = video_devdata(file);
410  struct timblogiw_fh *fh = priv;
411 
412  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
413 
414  if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
415  dev_dbg(&vdev->dev, "%s - No capture device\n", __func__);
416  return -EINVAL;
417  }
418 
419  fh->frame_count = 0;
420  return videobuf_streamon(&fh->vb_vidq);
421 }
422 
423 static int timblogiw_streamoff(struct file *file, void *priv,
424  unsigned int type)
425 {
426  struct video_device *vdev = video_devdata(file);
427  struct timblogiw_fh *fh = priv;
428 
429  dev_dbg(&vdev->dev, "%s entry\n", __func__);
430 
431  if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
432  return -EINVAL;
433 
434  return videobuf_streamoff(&fh->vb_vidq);
435 }
436 
437 static int timblogiw_querystd(struct file *file, void *priv, v4l2_std_id *std)
438 {
439  struct video_device *vdev = video_devdata(file);
440  struct timblogiw *lw = video_get_drvdata(vdev);
441  struct timblogiw_fh *fh = priv;
442 
443  dev_dbg(&vdev->dev, "%s entry\n", __func__);
444 
445  if (TIMBLOGIW_HAS_DECODER(lw))
446  return v4l2_subdev_call(lw->sd_enc, video, querystd, std);
447  else {
448  *std = fh->cur_norm->std;
449  return 0;
450  }
451 }
452 
453 static int timblogiw_enum_framesizes(struct file *file, void *priv,
454  struct v4l2_frmsizeenum *fsize)
455 {
456  struct video_device *vdev = video_devdata(file);
457  struct timblogiw_fh *fh = priv;
458 
459  dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n", __func__,
460  fsize->index, fsize->pixel_format);
461 
462  if ((fsize->index != 0) ||
463  (fsize->pixel_format != V4L2_PIX_FMT_UYVY))
464  return -EINVAL;
465 
467  fsize->discrete.width = fh->cur_norm->width;
468  fsize->discrete.height = fh->cur_norm->height;
469 
470  return 0;
471 }
472 
473 /* Video buffer functions */
474 
475 static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
476  unsigned int *size)
477 {
478  struct timblogiw_fh *fh = vq->priv_data;
479 
480  *size = timblogiw_frame_size(fh->cur_norm);
481 
482  if (!*count)
483  *count = 32;
484 
485  while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024)
486  (*count)--;
487 
488  return 0;
489 }
490 
491 static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
492  enum v4l2_field field)
493 {
494  struct timblogiw_fh *fh = vq->priv_data;
495  struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
496  vb);
497  unsigned int data_size = timblogiw_frame_size(fh->cur_norm);
498  int err = 0;
499 
500  if (vb->baddr && vb->bsize < data_size)
501  /* User provided buffer, but it is too small */
502  return -ENOMEM;
503 
504  vb->size = data_size;
505  vb->width = fh->cur_norm->width;
506  vb->height = fh->cur_norm->height;
507  vb->field = field;
508 
509  if (vb->state == VIDEOBUF_NEEDS_INIT) {
510  int i;
511  unsigned int size;
512  unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
513  timblogiw_bytes_per_line(fh->cur_norm);
515 
516  sg_init_table(buf->sg, ARRAY_SIZE(buf->sg));
517 
518  err = videobuf_iolock(vq, vb, NULL);
519  if (err)
520  goto err;
521 
522  addr = videobuf_to_dma_contig(vb);
523  for (i = 0, size = 0; size < data_size; i++) {
524  sg_dma_address(buf->sg + i) = addr + size;
525  size += bytes_per_desc;
526  sg_dma_len(buf->sg + i) = (size > data_size) ?
527  (bytes_per_desc - (size - data_size)) :
528  bytes_per_desc;
529  }
530 
531  vb->state = VIDEOBUF_PREPARED;
532  buf->cookie = -1;
533  buf->fh = fh;
534  }
535 
536  return 0;
537 
538 err:
539  videobuf_dma_contig_free(vq, vb);
541  return err;
542 }
543 
544 static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
545 {
546  struct timblogiw_fh *fh = vq->priv_data;
547  struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
548  vb);
550  int sg_elems;
551  int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
552  timblogiw_bytes_per_line(fh->cur_norm);
553 
554  sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc;
555  sg_elems +=
556  (timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0;
557 
558  if (list_empty(&fh->capture))
559  vb->state = VIDEOBUF_ACTIVE;
560  else
561  vb->state = VIDEOBUF_QUEUED;
562 
563  list_add_tail(&vb->queue, &fh->capture);
564 
565  spin_unlock_irq(&fh->queue_lock);
566 
567  desc = dmaengine_prep_slave_sg(fh->chan,
568  buf->sg, sg_elems, DMA_DEV_TO_MEM,
570  if (!desc) {
571  spin_lock_irq(&fh->queue_lock);
572  list_del_init(&vb->queue);
573  vb->state = VIDEOBUF_PREPARED;
574  return;
575  }
576 
577  desc->callback_param = buf;
578  desc->callback = timblogiw_dma_cb;
579 
580  buf->cookie = desc->tx_submit(desc);
581 
582  spin_lock_irq(&fh->queue_lock);
583 }
584 
585 static void buffer_release(struct videobuf_queue *vq,
586  struct videobuf_buffer *vb)
587 {
588  struct timblogiw_fh *fh = vq->priv_data;
589  struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
590  vb);
591 
592  videobuf_waiton(vq, vb, 0, 0);
593  if (buf->cookie >= 0)
594  dma_sync_wait(fh->chan, buf->cookie);
595 
596  videobuf_dma_contig_free(vq, vb);
598 }
599 
600 static struct videobuf_queue_ops timblogiw_video_qops = {
601  .buf_setup = buffer_setup,
602  .buf_prepare = buffer_prepare,
603  .buf_queue = buffer_queue,
604  .buf_release = buffer_release,
605 };
606 
607 /* Device Operations functions */
608 
609 static int timblogiw_open(struct file *file)
610 {
611  struct video_device *vdev = video_devdata(file);
612  struct timblogiw *lw = video_get_drvdata(vdev);
613  struct timblogiw_fh *fh;
616  int err = 0;
617 
618  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
619 
620  mutex_lock(&lw->lock);
621  if (lw->opened) {
622  err = -EBUSY;
623  goto out;
624  }
625 
626  if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) {
627  struct i2c_adapter *adapt;
628 
629  /* find the video decoder */
630  adapt = i2c_get_adapter(lw->pdata.i2c_adapter);
631  if (!adapt) {
632  dev_err(&vdev->dev, "No I2C bus #%d\n",
633  lw->pdata.i2c_adapter);
634  err = -ENODEV;
635  goto out;
636  }
637 
638  /* now find the encoder */
639  lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt,
640  lw->pdata.encoder.info, NULL);
641 
642  i2c_put_adapter(adapt);
643 
644  if (!lw->sd_enc) {
645  dev_err(&vdev->dev, "Failed to get encoder: %s\n",
646  lw->pdata.encoder.module_name);
647  err = -ENODEV;
648  goto out;
649  }
650  }
651 
652  fh = kzalloc(sizeof(*fh), GFP_KERNEL);
653  if (!fh) {
654  err = -ENOMEM;
655  goto out;
656  }
657 
659  timblogiw_querystd(file, fh, &std);
660  fh->cur_norm = timblogiw_get_norm(std);
661 
662  INIT_LIST_HEAD(&fh->capture);
664 
665  dma_cap_zero(mask);
666  dma_cap_set(DMA_SLAVE, mask);
667  dma_cap_set(DMA_PRIVATE, mask);
668 
669  /* find the DMA channel */
670  fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn,
671  (void *)(uintptr_t)lw->pdata.dma_channel);
672  if (!fh->chan) {
673  dev_err(&vdev->dev, "Failed to get DMA channel\n");
674  kfree(fh);
675  err = -ENODEV;
676  goto out;
677  }
678 
679  file->private_data = fh;
681  &timblogiw_video_qops, lw->dev, &fh->queue_lock,
683  sizeof(struct timblogiw_buffer), fh, NULL);
684 
685  lw->opened = true;
686 out:
687  mutex_unlock(&lw->lock);
688 
689  return err;
690 }
691 
692 static int timblogiw_close(struct file *file)
693 {
694  struct video_device *vdev = video_devdata(file);
695  struct timblogiw *lw = video_get_drvdata(vdev);
696  struct timblogiw_fh *fh = file->private_data;
697 
698  dev_dbg(&vdev->dev, "%s: Entry\n", __func__);
699 
700  videobuf_stop(&fh->vb_vidq);
702 
704 
705  kfree(fh);
706 
707  mutex_lock(&lw->lock);
708  lw->opened = false;
709  mutex_unlock(&lw->lock);
710  return 0;
711 }
712 
713 static ssize_t timblogiw_read(struct file *file, char __user *data,
714  size_t count, loff_t *ppos)
715 {
716  struct video_device *vdev = video_devdata(file);
717  struct timblogiw_fh *fh = file->private_data;
718 
719  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
720 
721  return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
722  file->f_flags & O_NONBLOCK);
723 }
724 
725 static unsigned int timblogiw_poll(struct file *file,
726  struct poll_table_struct *wait)
727 {
728  struct video_device *vdev = video_devdata(file);
729  struct timblogiw_fh *fh = file->private_data;
730 
731  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
732 
733  return videobuf_poll_stream(file, &fh->vb_vidq, wait);
734 }
735 
736 static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma)
737 {
738  struct video_device *vdev = video_devdata(file);
739  struct timblogiw_fh *fh = file->private_data;
740 
741  dev_dbg(&vdev->dev, "%s: entry\n", __func__);
742 
743  return videobuf_mmap_mapper(&fh->vb_vidq, vma);
744 }
745 
746 /* Platform device functions */
747 
748 static __devinitconst struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
749  .vidioc_querycap = timblogiw_querycap,
750  .vidioc_enum_fmt_vid_cap = timblogiw_enum_fmt,
751  .vidioc_g_fmt_vid_cap = timblogiw_g_fmt,
752  .vidioc_try_fmt_vid_cap = timblogiw_try_fmt,
753  .vidioc_s_fmt_vid_cap = timblogiw_s_fmt,
754  .vidioc_g_parm = timblogiw_g_parm,
755  .vidioc_reqbufs = timblogiw_reqbufs,
756  .vidioc_querybuf = timblogiw_querybuf,
757  .vidioc_qbuf = timblogiw_qbuf,
758  .vidioc_dqbuf = timblogiw_dqbuf,
759  .vidioc_g_std = timblogiw_g_std,
760  .vidioc_s_std = timblogiw_s_std,
761  .vidioc_enum_input = timblogiw_enuminput,
762  .vidioc_g_input = timblogiw_g_input,
763  .vidioc_s_input = timblogiw_s_input,
764  .vidioc_streamon = timblogiw_streamon,
765  .vidioc_streamoff = timblogiw_streamoff,
766  .vidioc_querystd = timblogiw_querystd,
767  .vidioc_enum_framesizes = timblogiw_enum_framesizes,
768 };
769 
770 static __devinitconst struct v4l2_file_operations timblogiw_fops = {
771  .owner = THIS_MODULE,
772  .open = timblogiw_open,
773  .release = timblogiw_close,
774  .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
775  .mmap = timblogiw_mmap,
776  .read = timblogiw_read,
777  .poll = timblogiw_poll,
778 };
779 
780 static __devinitconst struct video_device timblogiw_template = {
781  .name = TIMBLOGIWIN_NAME,
782  .fops = &timblogiw_fops,
783  .ioctl_ops = &timblogiw_ioctl_ops,
784  .release = video_device_release_empty,
785  .minor = -1,
786  .tvnorms = V4L2_STD_PAL | V4L2_STD_NTSC
787 };
788 
789 static int __devinit timblogiw_probe(struct platform_device *pdev)
790 {
791  int err;
792  struct timblogiw *lw = NULL;
793  struct timb_video_platform_data *pdata = pdev->dev.platform_data;
794 
795  if (!pdata) {
796  dev_err(&pdev->dev, "No platform data\n");
797  err = -EINVAL;
798  goto err;
799  }
800 
801  if (!pdata->encoder.module_name)
802  dev_info(&pdev->dev, "Running without decoder\n");
803 
804  lw = kzalloc(sizeof(*lw), GFP_KERNEL);
805  if (!lw) {
806  err = -ENOMEM;
807  goto err;
808  }
809 
810  if (pdev->dev.parent)
811  lw->dev = pdev->dev.parent;
812  else
813  lw->dev = &pdev->dev;
814 
815  memcpy(&lw->pdata, pdata, sizeof(lw->pdata));
816 
817  mutex_init(&lw->lock);
818 
819  lw->video_dev = timblogiw_template;
820 
821  strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name));
822  err = v4l2_device_register(NULL, &lw->v4l2_dev);
823  if (err)
824  goto err_register;
825 
826  lw->video_dev.v4l2_dev = &lw->v4l2_dev;
827 
828  platform_set_drvdata(pdev, lw);
829  video_set_drvdata(&lw->video_dev, lw);
830 
831  err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0);
832  if (err) {
833  dev_err(&pdev->dev, "Error reg video: %d\n", err);
834  goto err_request;
835  }
836 
837 
838  return 0;
839 
840 err_request:
841  platform_set_drvdata(pdev, NULL);
843 err_register:
844  kfree(lw);
845 err:
846  dev_err(&pdev->dev, "Failed to register: %d\n", err);
847 
848  return err;
849 }
850 
851 static int __devexit timblogiw_remove(struct platform_device *pdev)
852 {
853  struct timblogiw *lw = platform_get_drvdata(pdev);
854 
856 
858 
859  kfree(lw);
860 
861  platform_set_drvdata(pdev, NULL);
862 
863  return 0;
864 }
865 
866 static struct platform_driver timblogiw_platform_driver = {
867  .driver = {
868  .name = DRIVER_NAME,
869  .owner = THIS_MODULE,
870  },
871  .probe = timblogiw_probe,
872  .remove = __devexit_p(timblogiw_remove),
873 };
874 
875 module_platform_driver(timblogiw_platform_driver);
876 
878 MODULE_AUTHOR("Pelagicore AB <[email protected]>");
879 MODULE_LICENSE("GPL v2");
880 MODULE_ALIAS("platform:"DRIVER_NAME);