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 47struct 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 57struct timblogiw_tvnorm { 58 v4l2_std_id std; 59 u16 width; 60 u16 height; 61 u8 fps; 62}; 63 64struct 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 73struct 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 81static 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 96static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm) 97{ 98 return norm->width * 2; 99} 100 101 102static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm) 103{ 104 return norm->height * timblogiw_bytes_per_line(norm); 105} 106 107static 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 118static 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 149static 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 156static 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 182static 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 207static 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 231out: 232 mutex_unlock(&lw->lock); 233 return err; 234} 235 236static 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 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, 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 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, 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 422static 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 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 = 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 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 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 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 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 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 838err_request: 839 v4l2_device_unregister(&lw->v4l2_dev); 840err: 841 dev_err(&pdev->dev, "Failed to register: %d\n", err); 842 843 return err; 844} 845 846static 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 857static struct platform_driver timblogiw_platform_driver = { 858 .driver = { 859 .name = DRIVER_NAME, 860 }, 861 .probe = timblogiw_probe, 862 .remove = timblogiw_remove, 863}; 864 865module_platform_driver(timblogiw_platform_driver); 866 867MODULE_DESCRIPTION(TIMBLOGIWIN_NAME); 868MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>"); 869MODULE_LICENSE("GPL v2"); 870MODULE_ALIAS("platform:"DRIVER_NAME); 871