Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.1-rc4 892 lines 22 kB view raw
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 <media/v4l2-ioctl.h> 31#include <media/v4l2-device.h> 32#include <media/videobuf-dma-contig.h> 33#include <media/timb_video.h> 34 35#define DRIVER_NAME "timb-video" 36 37#define TIMBLOGIWIN_NAME "Timberdale Video-In" 38#define TIMBLOGIW_VERSION_CODE 0x04 39 40#define TIMBLOGIW_LINES_PER_DESC 44 41#define TIMBLOGIW_MAX_VIDEO_MEM 16 42 43#define TIMBLOGIW_HAS_DECODER(lw) (lw->pdata.encoder.module_name) 44 45 46struct timblogiw { 47 struct video_device video_dev; 48 struct v4l2_device v4l2_dev; /* mutual exclusion */ 49 struct mutex lock; 50 struct device *dev; 51 struct timb_video_platform_data pdata; 52 struct v4l2_subdev *sd_enc; /* encoder */ 53 bool opened; 54}; 55 56struct timblogiw_tvnorm { 57 v4l2_std_id std; 58 u16 width; 59 u16 height; 60 u8 fps; 61}; 62 63struct timblogiw_fh { 64 struct videobuf_queue vb_vidq; 65 struct timblogiw_tvnorm const *cur_norm; 66 struct list_head capture; 67 struct dma_chan *chan; 68 spinlock_t queue_lock; /* mutual exclusion */ 69 unsigned int frame_count; 70}; 71 72struct timblogiw_buffer { 73 /* common v4l buffer stuff -- must be first */ 74 struct videobuf_buffer vb; 75 struct scatterlist sg[16]; 76 dma_cookie_t cookie; 77 struct timblogiw_fh *fh; 78}; 79 80const struct timblogiw_tvnorm timblogiw_tvnorms[] = { 81 { 82 .std = V4L2_STD_PAL, 83 .width = 720, 84 .height = 576, 85 .fps = 25 86 }, 87 { 88 .std = V4L2_STD_NTSC, 89 .width = 720, 90 .height = 480, 91 .fps = 30 92 } 93}; 94 95static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm) 96{ 97 return norm->width * 2; 98} 99 100 101static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm) 102{ 103 return norm->height * timblogiw_bytes_per_line(norm); 104} 105 106static const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std) 107{ 108 int i; 109 for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++) 110 if (timblogiw_tvnorms[i].std & std) 111 return timblogiw_tvnorms + i; 112 113 /* default to first element */ 114 return timblogiw_tvnorms; 115} 116 117static void timblogiw_dma_cb(void *data) 118{ 119 struct timblogiw_buffer *buf = data; 120 struct timblogiw_fh *fh = buf->fh; 121 struct videobuf_buffer *vb = &buf->vb; 122 123 spin_lock(&fh->queue_lock); 124 125 /* mark the transfer done */ 126 buf->cookie = -1; 127 128 fh->frame_count++; 129 130 if (vb->state != VIDEOBUF_ERROR) { 131 list_del(&vb->queue); 132 do_gettimeofday(&vb->ts); 133 vb->field_count = fh->frame_count * 2; 134 vb->state = VIDEOBUF_DONE; 135 136 wake_up(&vb->done); 137 } 138 139 if (!list_empty(&fh->capture)) { 140 vb = list_entry(fh->capture.next, struct videobuf_buffer, 141 queue); 142 vb->state = VIDEOBUF_ACTIVE; 143 } 144 145 spin_unlock(&fh->queue_lock); 146} 147 148static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param) 149{ 150 return chan->chan_id == (uintptr_t)filter_param; 151} 152 153/* IOCTL functions */ 154 155static int timblogiw_g_fmt(struct file *file, void *priv, 156 struct v4l2_format *format) 157{ 158 struct video_device *vdev = video_devdata(file); 159 struct timblogiw *lw = video_get_drvdata(vdev); 160 struct timblogiw_fh *fh = priv; 161 162 dev_dbg(&vdev->dev, "%s entry\n", __func__); 163 164 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 165 return -EINVAL; 166 167 mutex_lock(&lw->lock); 168 169 format->fmt.pix.width = fh->cur_norm->width; 170 format->fmt.pix.height = fh->cur_norm->height; 171 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; 172 format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm); 173 format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm); 174 format->fmt.pix.field = V4L2_FIELD_NONE; 175 176 mutex_unlock(&lw->lock); 177 178 return 0; 179} 180 181static int timblogiw_try_fmt(struct file *file, void *priv, 182 struct v4l2_format *format) 183{ 184 struct video_device *vdev = video_devdata(file); 185 struct v4l2_pix_format *pix = &format->fmt.pix; 186 187 dev_dbg(&vdev->dev, 188 "%s - width=%d, height=%d, pixelformat=%d, field=%d\n" 189 "bytes per line %d, size image: %d, colorspace: %d\n", 190 __func__, 191 pix->width, pix->height, pix->pixelformat, pix->field, 192 pix->bytesperline, pix->sizeimage, pix->colorspace); 193 194 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 195 return -EINVAL; 196 197 if (pix->field != V4L2_FIELD_NONE) 198 return -EINVAL; 199 200 if (pix->pixelformat != V4L2_PIX_FMT_UYVY) 201 return -EINVAL; 202 203 return 0; 204} 205 206static int timblogiw_s_fmt(struct file *file, void *priv, 207 struct v4l2_format *format) 208{ 209 struct video_device *vdev = video_devdata(file); 210 struct timblogiw *lw = video_get_drvdata(vdev); 211 struct timblogiw_fh *fh = priv; 212 struct v4l2_pix_format *pix = &format->fmt.pix; 213 int err; 214 215 mutex_lock(&lw->lock); 216 217 err = timblogiw_try_fmt(file, priv, format); 218 if (err) 219 goto out; 220 221 if (videobuf_queue_is_busy(&fh->vb_vidq)) { 222 dev_err(&vdev->dev, "%s queue busy\n", __func__); 223 err = -EBUSY; 224 goto out; 225 } 226 227 pix->width = fh->cur_norm->width; 228 pix->height = fh->cur_norm->height; 229 230out: 231 mutex_unlock(&lw->lock); 232 return err; 233} 234 235static int timblogiw_querycap(struct file *file, void *priv, 236 struct v4l2_capability *cap) 237{ 238 struct video_device *vdev = video_devdata(file); 239 240 dev_dbg(&vdev->dev, "%s: Entry\n", __func__); 241 memset(cap, 0, sizeof(*cap)); 242 strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1); 243 strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1); 244 strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info)); 245 cap->version = TIMBLOGIW_VERSION_CODE; 246 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | 247 V4L2_CAP_READWRITE; 248 249 return 0; 250} 251 252static 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 271static 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 284static 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 295static 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 306static 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 316static 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 327static 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 338static 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, core, 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 360static 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 383static 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 395static 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 406static int timblogiw_streamon(struct file *file, void *priv, unsigned int 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 422static int timblogiw_streamoff(struct file *file, void *priv, 423 unsigned int 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 436static 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 452static 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 474static 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 490static 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 537err: 538 videobuf_dma_contig_free(vq, vb); 539 vb->state = VIDEOBUF_NEEDS_INIT; 540 return err; 541} 542 543static 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 = fh->chan->device->device_prep_slave_sg(fh->chan, 567 buf->sg, sg_elems, DMA_FROM_DEVICE, 568 DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); 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 584static 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 599static 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 608static 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; 685out: 686 mutex_unlock(&lw->lock); 687 688 return err; 689} 690 691static 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 712static 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 724static 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 735static 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 747static __devinitconst 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 769static __devinitconst 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 779static __devinitconst 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 788static int __devinit 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 = kzalloc(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_register; 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 837 return 0; 838 839err_request: 840 platform_set_drvdata(pdev, NULL); 841 v4l2_device_unregister(&lw->v4l2_dev); 842err_register: 843 kfree(lw); 844err: 845 dev_err(&pdev->dev, "Failed to register: %d\n", err); 846 847 return err; 848} 849 850static int __devexit timblogiw_remove(struct platform_device *pdev) 851{ 852 struct timblogiw *lw = platform_get_drvdata(pdev); 853 854 video_unregister_device(&lw->video_dev); 855 856 v4l2_device_unregister(&lw->v4l2_dev); 857 858 kfree(lw); 859 860 platform_set_drvdata(pdev, NULL); 861 862 return 0; 863} 864 865static struct platform_driver timblogiw_platform_driver = { 866 .driver = { 867 .name = DRIVER_NAME, 868 .owner = THIS_MODULE, 869 }, 870 .probe = timblogiw_probe, 871 .remove = __devexit_p(timblogiw_remove), 872}; 873 874/* Module functions */ 875 876static int __init timblogiw_init(void) 877{ 878 return platform_driver_register(&timblogiw_platform_driver); 879} 880 881static void __exit timblogiw_exit(void) 882{ 883 platform_driver_unregister(&timblogiw_platform_driver); 884} 885 886module_init(timblogiw_init); 887module_exit(timblogiw_exit); 888 889MODULE_DESCRIPTION(TIMBLOGIWIN_NAME); 890MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>"); 891MODULE_LICENSE("GPL v2"); 892MODULE_ALIAS("platform:"DRIVER_NAME);