saa7146_video.c (33909B)
1#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2 3#include <media/drv-intf/saa7146_vv.h> 4#include <media/v4l2-event.h> 5#include <media/v4l2-ctrls.h> 6#include <linux/module.h> 7#include <linux/kernel.h> 8 9static int max_memory = 32; 10 11module_param(max_memory, int, 0644); 12MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)"); 13 14#define IS_CAPTURE_ACTIVE(fh) \ 15 (((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh)) 16 17#define IS_OVERLAY_ACTIVE(fh) \ 18 (((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh)) 19 20/* format descriptions for capture and preview */ 21static struct saa7146_format formats[] = { 22 { 23 .pixelformat = V4L2_PIX_FMT_RGB332, 24 .trans = RGB08_COMPOSED, 25 .depth = 8, 26 .flags = 0, 27 }, { 28 .pixelformat = V4L2_PIX_FMT_RGB565, 29 .trans = RGB16_COMPOSED, 30 .depth = 16, 31 .flags = 0, 32 }, { 33 .pixelformat = V4L2_PIX_FMT_BGR24, 34 .trans = RGB24_COMPOSED, 35 .depth = 24, 36 .flags = 0, 37 }, { 38 .pixelformat = V4L2_PIX_FMT_BGR32, 39 .trans = RGB32_COMPOSED, 40 .depth = 32, 41 .flags = 0, 42 }, { 43 .pixelformat = V4L2_PIX_FMT_RGB32, 44 .trans = RGB32_COMPOSED, 45 .depth = 32, 46 .flags = 0, 47 .swap = 0x2, 48 }, { 49 .pixelformat = V4L2_PIX_FMT_GREY, 50 .trans = Y8, 51 .depth = 8, 52 .flags = 0, 53 }, { 54 .pixelformat = V4L2_PIX_FMT_YUV422P, 55 .trans = YUV422_DECOMPOSED, 56 .depth = 16, 57 .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR, 58 }, { 59 .pixelformat = V4L2_PIX_FMT_YVU420, 60 .trans = YUV420_DECOMPOSED, 61 .depth = 12, 62 .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR, 63 }, { 64 .pixelformat = V4L2_PIX_FMT_YUV420, 65 .trans = YUV420_DECOMPOSED, 66 .depth = 12, 67 .flags = FORMAT_IS_PLANAR, 68 }, { 69 .pixelformat = V4L2_PIX_FMT_UYVY, 70 .trans = YUV422_COMPOSED, 71 .depth = 16, 72 .flags = 0, 73 } 74}; 75 76/* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps. 77 due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped 78 (like V4L2_PIX_FMT_YUYV) ... 8-( */ 79 80struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc) 81{ 82 int i; 83 84 for (i = 0; i < ARRAY_SIZE(formats); i++) { 85 if (formats[i].pixelformat == fourcc) { 86 return formats+i; 87 } 88 } 89 90 DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc); 91 return NULL; 92} 93 94static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f); 95 96int saa7146_start_preview(struct saa7146_fh *fh) 97{ 98 struct saa7146_dev *dev = fh->dev; 99 struct saa7146_vv *vv = dev->vv_data; 100 struct v4l2_format fmt; 101 int ret = 0, err = 0; 102 103 DEB_EE("dev:%p, fh:%p\n", dev, fh); 104 105 /* check if we have overlay information */ 106 if (vv->ov.fh == NULL) { 107 DEB_D("no overlay data available. try S_FMT first.\n"); 108 return -EAGAIN; 109 } 110 111 /* check if streaming capture is running */ 112 if (IS_CAPTURE_ACTIVE(fh) != 0) { 113 DEB_D("streaming capture is active\n"); 114 return -EBUSY; 115 } 116 117 /* check if overlay is running */ 118 if (IS_OVERLAY_ACTIVE(fh) != 0) { 119 if (vv->video_fh == fh) { 120 DEB_D("overlay is already active\n"); 121 return 0; 122 } 123 DEB_D("overlay is already active in another open\n"); 124 return -EBUSY; 125 } 126 127 if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) { 128 DEB_D("cannot get necessary overlay resources\n"); 129 return -EBUSY; 130 } 131 132 fmt.fmt.win = vv->ov.win; 133 err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt); 134 if (0 != err) { 135 saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); 136 return -EBUSY; 137 } 138 vv->ov.win = fmt.fmt.win; 139 140 DEB_D("%dx%d+%d+%d 0x%08x field=%s\n", 141 vv->ov.win.w.width, vv->ov.win.w.height, 142 vv->ov.win.w.left, vv->ov.win.w.top, 143 vv->ov_fmt->pixelformat, v4l2_field_names[vv->ov.win.field]); 144 145 if (0 != (ret = saa7146_enable_overlay(fh))) { 146 DEB_D("enabling overlay failed: %d\n", ret); 147 saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); 148 return ret; 149 } 150 151 vv->video_status = STATUS_OVERLAY; 152 vv->video_fh = fh; 153 154 return 0; 155} 156EXPORT_SYMBOL_GPL(saa7146_start_preview); 157 158int saa7146_stop_preview(struct saa7146_fh *fh) 159{ 160 struct saa7146_dev *dev = fh->dev; 161 struct saa7146_vv *vv = dev->vv_data; 162 163 DEB_EE("dev:%p, fh:%p\n", dev, fh); 164 165 /* check if streaming capture is running */ 166 if (IS_CAPTURE_ACTIVE(fh) != 0) { 167 DEB_D("streaming capture is active\n"); 168 return -EBUSY; 169 } 170 171 /* check if overlay is running at all */ 172 if ((vv->video_status & STATUS_OVERLAY) == 0) { 173 DEB_D("no active overlay\n"); 174 return 0; 175 } 176 177 if (vv->video_fh != fh) { 178 DEB_D("overlay is active, but in another open\n"); 179 return -EBUSY; 180 } 181 182 vv->video_status = 0; 183 vv->video_fh = NULL; 184 185 saa7146_disable_overlay(fh); 186 187 saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); 188 189 return 0; 190} 191EXPORT_SYMBOL_GPL(saa7146_stop_preview); 192 193/********************************************************************************/ 194/* common pagetable functions */ 195 196static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) 197{ 198 struct pci_dev *pci = dev->pci; 199 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); 200 struct scatterlist *list = dma->sglist; 201 int length = dma->sglen; 202 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); 203 204 DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length); 205 206 if( 0 != IS_PLANAR(sfmt->trans)) { 207 struct saa7146_pgtable *pt1 = &buf->pt[0]; 208 struct saa7146_pgtable *pt2 = &buf->pt[1]; 209 struct saa7146_pgtable *pt3 = &buf->pt[2]; 210 __le32 *ptr1, *ptr2, *ptr3; 211 __le32 fill; 212 213 int size = buf->fmt->width*buf->fmt->height; 214 int i,p,m1,m2,m3,o1,o2; 215 216 switch( sfmt->depth ) { 217 case 12: { 218 /* create some offsets inside the page table */ 219 m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1; 220 m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1; 221 m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1; 222 o1 = size%PAGE_SIZE; 223 o2 = (size+(size/4))%PAGE_SIZE; 224 DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n", 225 size, m1, m2, m3, o1, o2); 226 break; 227 } 228 case 16: { 229 /* create some offsets inside the page table */ 230 m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1; 231 m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1; 232 m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1; 233 o1 = size%PAGE_SIZE; 234 o2 = (size+(size/2))%PAGE_SIZE; 235 DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n", 236 size, m1, m2, m3, o1, o2); 237 break; 238 } 239 default: { 240 return -1; 241 } 242 } 243 244 ptr1 = pt1->cpu; 245 ptr2 = pt2->cpu; 246 ptr3 = pt3->cpu; 247 248 /* walk all pages, copy all page addresses to ptr1 */ 249 for (i = 0; i < length; i++, list++) { 250 for (p = 0; p * 4096 < sg_dma_len(list); p++, ptr1++) 251 *ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset); 252 } 253/* 254 ptr1 = pt1->cpu; 255 for(j=0;j<40;j++) { 256 printk("ptr1 %d: 0x%08x\n",j,ptr1[j]); 257 } 258*/ 259 260 /* if we have a user buffer, the first page may not be 261 aligned to a page boundary. */ 262 pt1->offset = dma->sglist->offset; 263 pt2->offset = pt1->offset+o1; 264 pt3->offset = pt1->offset+o2; 265 266 /* create video-dma2 page table */ 267 ptr1 = pt1->cpu; 268 for(i = m1; i <= m2 ; i++, ptr2++) { 269 *ptr2 = ptr1[i]; 270 } 271 fill = *(ptr2-1); 272 for(;i<1024;i++,ptr2++) { 273 *ptr2 = fill; 274 } 275 /* create video-dma3 page table */ 276 ptr1 = pt1->cpu; 277 for(i = m2; i <= m3; i++,ptr3++) { 278 *ptr3 = ptr1[i]; 279 } 280 fill = *(ptr3-1); 281 for(;i<1024;i++,ptr3++) { 282 *ptr3 = fill; 283 } 284 /* finally: finish up video-dma1 page table */ 285 ptr1 = pt1->cpu+m1; 286 fill = pt1->cpu[m1]; 287 for(i=m1;i<1024;i++,ptr1++) { 288 *ptr1 = fill; 289 } 290/* 291 ptr1 = pt1->cpu; 292 ptr2 = pt2->cpu; 293 ptr3 = pt3->cpu; 294 for(j=0;j<40;j++) { 295 printk("ptr1 %d: 0x%08x\n",j,ptr1[j]); 296 } 297 for(j=0;j<40;j++) { 298 printk("ptr2 %d: 0x%08x\n",j,ptr2[j]); 299 } 300 for(j=0;j<40;j++) { 301 printk("ptr3 %d: 0x%08x\n",j,ptr3[j]); 302 } 303*/ 304 } else { 305 struct saa7146_pgtable *pt = &buf->pt[0]; 306 return saa7146_pgtable_build_single(pci, pt, list, length); 307 } 308 309 return 0; 310} 311 312 313/********************************************************************************/ 314/* file operations */ 315 316static int video_begin(struct saa7146_fh *fh) 317{ 318 struct saa7146_dev *dev = fh->dev; 319 struct saa7146_vv *vv = dev->vv_data; 320 struct saa7146_format *fmt = NULL; 321 unsigned int resource; 322 int ret = 0, err = 0; 323 324 DEB_EE("dev:%p, fh:%p\n", dev, fh); 325 326 if ((vv->video_status & STATUS_CAPTURE) != 0) { 327 if (vv->video_fh == fh) { 328 DEB_S("already capturing\n"); 329 return 0; 330 } 331 DEB_S("already capturing in another open\n"); 332 return -EBUSY; 333 } 334 335 if ((vv->video_status & STATUS_OVERLAY) != 0) { 336 DEB_S("warning: suspending overlay video for streaming capture\n"); 337 vv->ov_suspend = vv->video_fh; 338 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ 339 if (0 != err) { 340 DEB_D("suspending video failed. aborting\n"); 341 return err; 342 } 343 } 344 345 fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat); 346 /* we need to have a valid format set here */ 347 if (!fmt) 348 return -EINVAL; 349 350 if (0 != (fmt->flags & FORMAT_IS_PLANAR)) { 351 resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS; 352 } else { 353 resource = RESOURCE_DMA1_HPS; 354 } 355 356 ret = saa7146_res_get(fh, resource); 357 if (0 == ret) { 358 DEB_S("cannot get capture resource %d\n", resource); 359 if (vv->ov_suspend != NULL) { 360 saa7146_start_preview(vv->ov_suspend); 361 vv->ov_suspend = NULL; 362 } 363 return -EBUSY; 364 } 365 366 /* clear out beginning of streaming bit (rps register 0)*/ 367 saa7146_write(dev, MC2, MASK_27 ); 368 369 /* enable rps0 irqs */ 370 SAA7146_IER_ENABLE(dev, MASK_27); 371 372 vv->video_fh = fh; 373 vv->video_status = STATUS_CAPTURE; 374 375 return 0; 376} 377 378static int video_end(struct saa7146_fh *fh, struct file *file) 379{ 380 struct saa7146_dev *dev = fh->dev; 381 struct saa7146_vv *vv = dev->vv_data; 382 struct saa7146_dmaqueue *q = &vv->video_dmaq; 383 struct saa7146_format *fmt = NULL; 384 unsigned long flags; 385 unsigned int resource; 386 u32 dmas = 0; 387 DEB_EE("dev:%p, fh:%p\n", dev, fh); 388 389 if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { 390 DEB_S("not capturing\n"); 391 return 0; 392 } 393 394 if (vv->video_fh != fh) { 395 DEB_S("capturing, but in another open\n"); 396 return -EBUSY; 397 } 398 399 fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat); 400 /* we need to have a valid format set here */ 401 if (!fmt) 402 return -EINVAL; 403 404 if (0 != (fmt->flags & FORMAT_IS_PLANAR)) { 405 resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS; 406 dmas = MASK_22 | MASK_21 | MASK_20; 407 } else { 408 resource = RESOURCE_DMA1_HPS; 409 dmas = MASK_22; 410 } 411 spin_lock_irqsave(&dev->slock,flags); 412 413 /* disable rps0 */ 414 saa7146_write(dev, MC1, MASK_28); 415 416 /* disable rps0 irqs */ 417 SAA7146_IER_DISABLE(dev, MASK_27); 418 419 /* shut down all used video dma transfers */ 420 saa7146_write(dev, MC1, dmas); 421 422 if (q->curr) 423 saa7146_buffer_finish(dev, q, VIDEOBUF_DONE); 424 425 spin_unlock_irqrestore(&dev->slock, flags); 426 427 vv->video_fh = NULL; 428 vv->video_status = 0; 429 430 saa7146_res_free(fh, resource); 431 432 if (vv->ov_suspend != NULL) { 433 saa7146_start_preview(vv->ov_suspend); 434 vv->ov_suspend = NULL; 435 } 436 437 return 0; 438} 439 440static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) 441{ 442 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 443 444 strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver)); 445 strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); 446 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | 447 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | 448 V4L2_CAP_DEVICE_CAPS; 449 cap->capabilities |= dev->ext_vv_data->capabilities; 450 return 0; 451} 452 453static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) 454{ 455 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 456 struct saa7146_vv *vv = dev->vv_data; 457 458 *fb = vv->ov_fb; 459 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; 460 fb->flags = V4L2_FBUF_FLAG_PRIMARY; 461 return 0; 462} 463 464static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb) 465{ 466 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 467 struct saa7146_vv *vv = dev->vv_data; 468 struct saa7146_format *fmt; 469 470 DEB_EE("VIDIOC_S_FBUF\n"); 471 472 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) 473 return -EPERM; 474 475 /* check args */ 476 fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat); 477 if (NULL == fmt) 478 return -EINVAL; 479 480 /* planar formats are not allowed for overlay video, clipping and video dma would clash */ 481 if (fmt->flags & FORMAT_IS_PLANAR) 482 DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n", 483 (char *)&fmt->pixelformat); 484 485 /* check if overlay is running */ 486 if (IS_OVERLAY_ACTIVE(fh) != 0) { 487 if (vv->video_fh != fh) { 488 DEB_D("refusing to change framebuffer information while overlay is active in another open\n"); 489 return -EBUSY; 490 } 491 } 492 493 /* ok, accept it */ 494 vv->ov_fb = *fb; 495 vv->ov_fmt = fmt; 496 497 if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) { 498 vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8; 499 DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline); 500 } 501 return 0; 502} 503 504static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) 505{ 506 if (f->index >= ARRAY_SIZE(formats)) 507 return -EINVAL; 508 f->pixelformat = formats[f->index].pixelformat; 509 return 0; 510} 511 512int saa7146_s_ctrl(struct v4l2_ctrl *ctrl) 513{ 514 struct saa7146_dev *dev = container_of(ctrl->handler, 515 struct saa7146_dev, ctrl_handler); 516 struct saa7146_vv *vv = dev->vv_data; 517 u32 val; 518 519 switch (ctrl->id) { 520 case V4L2_CID_BRIGHTNESS: 521 val = saa7146_read(dev, BCS_CTRL); 522 val &= 0x00ffffff; 523 val |= (ctrl->val << 24); 524 saa7146_write(dev, BCS_CTRL, val); 525 saa7146_write(dev, MC2, MASK_22 | MASK_06); 526 break; 527 528 case V4L2_CID_CONTRAST: 529 val = saa7146_read(dev, BCS_CTRL); 530 val &= 0xff00ffff; 531 val |= (ctrl->val << 16); 532 saa7146_write(dev, BCS_CTRL, val); 533 saa7146_write(dev, MC2, MASK_22 | MASK_06); 534 break; 535 536 case V4L2_CID_SATURATION: 537 val = saa7146_read(dev, BCS_CTRL); 538 val &= 0xffffff00; 539 val |= (ctrl->val << 0); 540 saa7146_write(dev, BCS_CTRL, val); 541 saa7146_write(dev, MC2, MASK_22 | MASK_06); 542 break; 543 544 case V4L2_CID_HFLIP: 545 /* fixme: we can support changing VFLIP and HFLIP here... */ 546 if ((vv->video_status & STATUS_CAPTURE)) 547 return -EBUSY; 548 vv->hflip = ctrl->val; 549 break; 550 551 case V4L2_CID_VFLIP: 552 if ((vv->video_status & STATUS_CAPTURE)) 553 return -EBUSY; 554 vv->vflip = ctrl->val; 555 break; 556 557 default: 558 return -EINVAL; 559 } 560 561 if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */ 562 struct saa7146_fh *fh = vv->video_fh; 563 564 saa7146_stop_preview(fh); 565 saa7146_start_preview(fh); 566 } 567 return 0; 568} 569 570static int vidioc_g_parm(struct file *file, void *fh, 571 struct v4l2_streamparm *parm) 572{ 573 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 574 struct saa7146_vv *vv = dev->vv_data; 575 576 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 577 return -EINVAL; 578 parm->parm.capture.readbuffers = 1; 579 v4l2_video_std_frame_period(vv->standard->id, 580 &parm->parm.capture.timeperframe); 581 return 0; 582} 583 584static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) 585{ 586 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 587 struct saa7146_vv *vv = dev->vv_data; 588 589 f->fmt.pix = vv->video_fmt; 590 return 0; 591} 592 593static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) 594{ 595 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 596 struct saa7146_vv *vv = dev->vv_data; 597 598 f->fmt.win = vv->ov.win; 599 return 0; 600} 601 602static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f) 603{ 604 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 605 struct saa7146_vv *vv = dev->vv_data; 606 607 f->fmt.vbi = vv->vbi_fmt; 608 return 0; 609} 610 611static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) 612{ 613 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 614 struct saa7146_vv *vv = dev->vv_data; 615 struct saa7146_format *fmt; 616 enum v4l2_field field; 617 int maxw, maxh; 618 int calc_bpl; 619 620 DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh); 621 622 fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat); 623 if (NULL == fmt) 624 return -EINVAL; 625 626 field = f->fmt.pix.field; 627 maxw = vv->standard->h_max_out; 628 maxh = vv->standard->v_max_out; 629 630 if (V4L2_FIELD_ANY == field) { 631 field = (f->fmt.pix.height > maxh / 2) 632 ? V4L2_FIELD_INTERLACED 633 : V4L2_FIELD_BOTTOM; 634 } 635 switch (field) { 636 case V4L2_FIELD_ALTERNATE: 637 vv->last_field = V4L2_FIELD_TOP; 638 maxh = maxh / 2; 639 break; 640 case V4L2_FIELD_TOP: 641 case V4L2_FIELD_BOTTOM: 642 vv->last_field = V4L2_FIELD_INTERLACED; 643 maxh = maxh / 2; 644 break; 645 case V4L2_FIELD_INTERLACED: 646 vv->last_field = V4L2_FIELD_INTERLACED; 647 break; 648 default: 649 DEB_D("no known field mode '%d'\n", field); 650 return -EINVAL; 651 } 652 653 f->fmt.pix.field = field; 654 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 655 if (f->fmt.pix.width > maxw) 656 f->fmt.pix.width = maxw; 657 if (f->fmt.pix.height > maxh) 658 f->fmt.pix.height = maxh; 659 660 calc_bpl = (f->fmt.pix.width * fmt->depth) / 8; 661 662 if (f->fmt.pix.bytesperline < calc_bpl) 663 f->fmt.pix.bytesperline = calc_bpl; 664 665 if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */ 666 f->fmt.pix.bytesperline = calc_bpl; 667 668 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; 669 DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", 670 f->fmt.pix.width, f->fmt.pix.height, 671 f->fmt.pix.bytesperline, f->fmt.pix.sizeimage); 672 673 return 0; 674} 675 676 677static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) 678{ 679 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 680 struct saa7146_vv *vv = dev->vv_data; 681 struct v4l2_window *win = &f->fmt.win; 682 enum v4l2_field field; 683 int maxw, maxh; 684 685 DEB_EE("dev:%p\n", dev); 686 687 if (NULL == vv->ov_fb.base) { 688 DEB_D("no fb base set\n"); 689 return -EINVAL; 690 } 691 if (NULL == vv->ov_fmt) { 692 DEB_D("no fb fmt set\n"); 693 return -EINVAL; 694 } 695 if (win->w.width < 48 || win->w.height < 32) { 696 DEB_D("min width/height. (%d,%d)\n", 697 win->w.width, win->w.height); 698 return -EINVAL; 699 } 700 if (win->clipcount > 16) { 701 DEB_D("clipcount too big\n"); 702 return -EINVAL; 703 } 704 705 field = win->field; 706 maxw = vv->standard->h_max_out; 707 maxh = vv->standard->v_max_out; 708 709 if (V4L2_FIELD_ANY == field) { 710 field = (win->w.height > maxh / 2) 711 ? V4L2_FIELD_INTERLACED 712 : V4L2_FIELD_TOP; 713 } 714 switch (field) { 715 case V4L2_FIELD_TOP: 716 case V4L2_FIELD_BOTTOM: 717 case V4L2_FIELD_ALTERNATE: 718 maxh = maxh / 2; 719 break; 720 case V4L2_FIELD_INTERLACED: 721 break; 722 default: 723 DEB_D("no known field mode '%d'\n", field); 724 return -EINVAL; 725 } 726 727 win->field = field; 728 if (win->w.width > maxw) 729 win->w.width = maxw; 730 if (win->w.height > maxh) 731 win->w.height = maxh; 732 733 return 0; 734} 735 736static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) 737{ 738 struct saa7146_fh *fh = __fh; 739 struct saa7146_dev *dev = fh->dev; 740 struct saa7146_vv *vv = dev->vv_data; 741 int err; 742 743 DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh); 744 if (IS_CAPTURE_ACTIVE(fh) != 0) { 745 DEB_EE("streaming capture is active\n"); 746 return -EBUSY; 747 } 748 err = vidioc_try_fmt_vid_cap(file, fh, f); 749 if (0 != err) 750 return err; 751 vv->video_fmt = f->fmt.pix; 752 DEB_EE("set to pixelformat '%4.4s'\n", 753 (char *)&vv->video_fmt.pixelformat); 754 return 0; 755} 756 757static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f) 758{ 759 struct saa7146_fh *fh = __fh; 760 struct saa7146_dev *dev = fh->dev; 761 struct saa7146_vv *vv = dev->vv_data; 762 int err; 763 764 DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh); 765 err = vidioc_try_fmt_vid_overlay(file, fh, f); 766 if (0 != err) 767 return err; 768 vv->ov.win = f->fmt.win; 769 vv->ov.nclips = f->fmt.win.clipcount; 770 if (vv->ov.nclips > 16) 771 vv->ov.nclips = 16; 772 memcpy(vv->ov.clips, f->fmt.win.clips, 773 sizeof(struct v4l2_clip) * vv->ov.nclips); 774 775 /* vv->ov.fh is used to indicate that we have valid overlay information, too */ 776 vv->ov.fh = fh; 777 778 /* check if our current overlay is active */ 779 if (IS_OVERLAY_ACTIVE(fh) != 0) { 780 saa7146_stop_preview(fh); 781 saa7146_start_preview(fh); 782 } 783 return 0; 784} 785 786static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm) 787{ 788 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 789 struct saa7146_vv *vv = dev->vv_data; 790 791 *norm = vv->standard->id; 792 return 0; 793} 794 795 /* the saa7146 supfhrts (used in conjunction with the saa7111a for example) 796 PAL / NTSC / SECAM. if your hardware does not (or does more) 797 -- override this function in your extension */ 798/* 799 case VIDIOC_ENUMSTD: 800 { 801 struct v4l2_standard *e = arg; 802 if (e->index < 0 ) 803 return -EINVAL; 804 if( e->index < dev->ext_vv_data->num_stds ) { 805 DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index); 806 v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name); 807 return 0; 808 } 809 return -EINVAL; 810 } 811 */ 812 813static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id) 814{ 815 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 816 struct saa7146_vv *vv = dev->vv_data; 817 int found = 0; 818 int err, i; 819 820 DEB_EE("VIDIOC_S_STD\n"); 821 822 if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) { 823 DEB_D("cannot change video standard while streaming capture is active\n"); 824 return -EBUSY; 825 } 826 827 if ((vv->video_status & STATUS_OVERLAY) != 0) { 828 vv->ov_suspend = vv->video_fh; 829 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ 830 if (0 != err) { 831 DEB_D("suspending video failed. aborting\n"); 832 return err; 833 } 834 } 835 836 for (i = 0; i < dev->ext_vv_data->num_stds; i++) 837 if (id & dev->ext_vv_data->stds[i].id) 838 break; 839 if (i != dev->ext_vv_data->num_stds) { 840 vv->standard = &dev->ext_vv_data->stds[i]; 841 if (NULL != dev->ext_vv_data->std_callback) 842 dev->ext_vv_data->std_callback(dev, vv->standard); 843 found = 1; 844 } 845 846 if (vv->ov_suspend != NULL) { 847 saa7146_start_preview(vv->ov_suspend); 848 vv->ov_suspend = NULL; 849 } 850 851 if (!found) { 852 DEB_EE("VIDIOC_S_STD: standard not found\n"); 853 return -EINVAL; 854 } 855 856 DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name); 857 return 0; 858} 859 860static int vidioc_overlay(struct file *file, void *fh, unsigned int on) 861{ 862 int err; 863 864 DEB_D("VIDIOC_OVERLAY on:%d\n", on); 865 if (on) 866 err = saa7146_start_preview(fh); 867 else 868 err = saa7146_stop_preview(fh); 869 return err; 870} 871 872static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b) 873{ 874 struct saa7146_fh *fh = __fh; 875 876 if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 877 return videobuf_reqbufs(&fh->video_q, b); 878 if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE) 879 return videobuf_reqbufs(&fh->vbi_q, b); 880 return -EINVAL; 881} 882 883static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf) 884{ 885 struct saa7146_fh *fh = __fh; 886 887 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 888 return videobuf_querybuf(&fh->video_q, buf); 889 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) 890 return videobuf_querybuf(&fh->vbi_q, buf); 891 return -EINVAL; 892} 893 894static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) 895{ 896 struct saa7146_fh *fh = __fh; 897 898 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 899 return videobuf_qbuf(&fh->video_q, buf); 900 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) 901 return videobuf_qbuf(&fh->vbi_q, buf); 902 return -EINVAL; 903} 904 905static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) 906{ 907 struct saa7146_fh *fh = __fh; 908 909 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 910 return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK); 911 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) 912 return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK); 913 return -EINVAL; 914} 915 916static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type) 917{ 918 struct saa7146_fh *fh = __fh; 919 int err; 920 921 DEB_D("VIDIOC_STREAMON, type:%d\n", type); 922 923 err = video_begin(fh); 924 if (err) 925 return err; 926 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 927 return videobuf_streamon(&fh->video_q); 928 if (type == V4L2_BUF_TYPE_VBI_CAPTURE) 929 return videobuf_streamon(&fh->vbi_q); 930 return -EINVAL; 931} 932 933static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type) 934{ 935 struct saa7146_fh *fh = __fh; 936 struct saa7146_dev *dev = fh->dev; 937 struct saa7146_vv *vv = dev->vv_data; 938 int err; 939 940 DEB_D("VIDIOC_STREAMOFF, type:%d\n", type); 941 942 /* ugly: we need to copy some checks from video_end(), 943 because videobuf_streamoff() relies on the capture running. 944 check and fix this */ 945 if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { 946 DEB_S("not capturing\n"); 947 return 0; 948 } 949 950 if (vv->video_fh != fh) { 951 DEB_S("capturing, but in another open\n"); 952 return -EBUSY; 953 } 954 955 err = -EINVAL; 956 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 957 err = videobuf_streamoff(&fh->video_q); 958 else if (type == V4L2_BUF_TYPE_VBI_CAPTURE) 959 err = videobuf_streamoff(&fh->vbi_q); 960 if (0 != err) { 961 DEB_D("warning: videobuf_streamoff() failed\n"); 962 video_end(fh, file); 963 } else { 964 err = video_end(fh, file); 965 } 966 return err; 967} 968 969const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { 970 .vidioc_querycap = vidioc_querycap, 971 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, 972 .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap, 973 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, 974 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, 975 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, 976 .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, 977 .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, 978 .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, 979 980 .vidioc_overlay = vidioc_overlay, 981 .vidioc_g_fbuf = vidioc_g_fbuf, 982 .vidioc_s_fbuf = vidioc_s_fbuf, 983 .vidioc_reqbufs = vidioc_reqbufs, 984 .vidioc_querybuf = vidioc_querybuf, 985 .vidioc_qbuf = vidioc_qbuf, 986 .vidioc_dqbuf = vidioc_dqbuf, 987 .vidioc_g_std = vidioc_g_std, 988 .vidioc_s_std = vidioc_s_std, 989 .vidioc_streamon = vidioc_streamon, 990 .vidioc_streamoff = vidioc_streamoff, 991 .vidioc_g_parm = vidioc_g_parm, 992 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 993 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 994}; 995 996const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = { 997 .vidioc_querycap = vidioc_querycap, 998 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, 999 1000 .vidioc_reqbufs = vidioc_reqbufs, 1001 .vidioc_querybuf = vidioc_querybuf, 1002 .vidioc_qbuf = vidioc_qbuf, 1003 .vidioc_dqbuf = vidioc_dqbuf, 1004 .vidioc_g_std = vidioc_g_std, 1005 .vidioc_s_std = vidioc_s_std, 1006 .vidioc_streamon = vidioc_streamon, 1007 .vidioc_streamoff = vidioc_streamoff, 1008 .vidioc_g_parm = vidioc_g_parm, 1009 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 1010 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1011}; 1012 1013/*********************************************************************************/ 1014/* buffer handling functions */ 1015 1016static int buffer_activate (struct saa7146_dev *dev, 1017 struct saa7146_buf *buf, 1018 struct saa7146_buf *next) 1019{ 1020 struct saa7146_vv *vv = dev->vv_data; 1021 1022 buf->vb.state = VIDEOBUF_ACTIVE; 1023 saa7146_set_capture(dev,buf,next); 1024 1025 mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT); 1026 return 0; 1027} 1028 1029static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf) 1030{ 1031 saa7146_pgtable_free(dev->pci, &buf->pt[0]); 1032 saa7146_pgtable_free(dev->pci, &buf->pt[1]); 1033 saa7146_pgtable_free(dev->pci, &buf->pt[2]); 1034} 1035 1036static int buffer_prepare(struct videobuf_queue *q, 1037 struct videobuf_buffer *vb, enum v4l2_field field) 1038{ 1039 struct file *file = q->priv_data; 1040 struct saa7146_fh *fh = file->private_data; 1041 struct saa7146_dev *dev = fh->dev; 1042 struct saa7146_vv *vv = dev->vv_data; 1043 struct saa7146_buf *buf = (struct saa7146_buf *)vb; 1044 int size,err = 0; 1045 1046 DEB_CAP("vbuf:%p\n", vb); 1047 1048 /* sanity checks */ 1049 if (vv->video_fmt.width < 48 || 1050 vv->video_fmt.height < 32 || 1051 vv->video_fmt.width > vv->standard->h_max_out || 1052 vv->video_fmt.height > vv->standard->v_max_out) { 1053 DEB_D("w (%d) / h (%d) out of bounds\n", 1054 vv->video_fmt.width, vv->video_fmt.height); 1055 return -EINVAL; 1056 } 1057 1058 size = vv->video_fmt.sizeimage; 1059 if (0 != buf->vb.baddr && buf->vb.bsize < size) { 1060 DEB_D("size mismatch\n"); 1061 return -EINVAL; 1062 } 1063 1064 DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n", 1065 vv->video_fmt.width, vv->video_fmt.height, 1066 size, v4l2_field_names[vv->video_fmt.field]); 1067 if (buf->vb.width != vv->video_fmt.width || 1068 buf->vb.bytesperline != vv->video_fmt.bytesperline || 1069 buf->vb.height != vv->video_fmt.height || 1070 buf->vb.size != size || 1071 buf->vb.field != field || 1072 buf->vb.field != vv->video_fmt.field || 1073 buf->fmt != &vv->video_fmt) { 1074 saa7146_dma_free(dev,q,buf); 1075 } 1076 1077 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { 1078 struct saa7146_format *sfmt; 1079 1080 buf->vb.bytesperline = vv->video_fmt.bytesperline; 1081 buf->vb.width = vv->video_fmt.width; 1082 buf->vb.height = vv->video_fmt.height; 1083 buf->vb.size = size; 1084 buf->vb.field = field; 1085 buf->fmt = &vv->video_fmt; 1086 buf->vb.field = vv->video_fmt.field; 1087 1088 sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); 1089 1090 release_all_pagetables(dev, buf); 1091 if( 0 != IS_PLANAR(sfmt->trans)) { 1092 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); 1093 saa7146_pgtable_alloc(dev->pci, &buf->pt[1]); 1094 saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); 1095 } else { 1096 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); 1097 } 1098 1099 err = videobuf_iolock(q,&buf->vb, &vv->ov_fb); 1100 if (err) 1101 goto oops; 1102 err = saa7146_pgtable_build(dev,buf); 1103 if (err) 1104 goto oops; 1105 } 1106 buf->vb.state = VIDEOBUF_PREPARED; 1107 buf->activate = buffer_activate; 1108 1109 return 0; 1110 1111 oops: 1112 DEB_D("error out\n"); 1113 saa7146_dma_free(dev,q,buf); 1114 1115 return err; 1116} 1117 1118static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) 1119{ 1120 struct file *file = q->priv_data; 1121 struct saa7146_fh *fh = file->private_data; 1122 struct saa7146_vv *vv = fh->dev->vv_data; 1123 1124 if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS) 1125 *count = MAX_SAA7146_CAPTURE_BUFFERS; 1126 1127 *size = vv->video_fmt.sizeimage; 1128 1129 /* check if we exceed the "max_memory" parameter */ 1130 if( (*count * *size) > (max_memory*1048576) ) { 1131 *count = (max_memory*1048576) / *size; 1132 } 1133 1134 DEB_CAP("%d buffers, %d bytes each\n", *count, *size); 1135 1136 return 0; 1137} 1138 1139static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) 1140{ 1141 struct file *file = q->priv_data; 1142 struct saa7146_fh *fh = file->private_data; 1143 struct saa7146_dev *dev = fh->dev; 1144 struct saa7146_vv *vv = dev->vv_data; 1145 struct saa7146_buf *buf = (struct saa7146_buf *)vb; 1146 1147 DEB_CAP("vbuf:%p\n", vb); 1148 saa7146_buffer_queue(fh->dev, &vv->video_dmaq, buf); 1149} 1150 1151static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) 1152{ 1153 struct file *file = q->priv_data; 1154 struct saa7146_fh *fh = file->private_data; 1155 struct saa7146_dev *dev = fh->dev; 1156 struct saa7146_buf *buf = (struct saa7146_buf *)vb; 1157 1158 DEB_CAP("vbuf:%p\n", vb); 1159 1160 saa7146_dma_free(dev,q,buf); 1161 1162 release_all_pagetables(dev, buf); 1163} 1164 1165static const struct videobuf_queue_ops video_qops = { 1166 .buf_setup = buffer_setup, 1167 .buf_prepare = buffer_prepare, 1168 .buf_queue = buffer_queue, 1169 .buf_release = buffer_release, 1170}; 1171 1172/********************************************************************************/ 1173/* file operations */ 1174 1175static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv) 1176{ 1177 INIT_LIST_HEAD(&vv->video_dmaq.queue); 1178 1179 timer_setup(&vv->video_dmaq.timeout, saa7146_buffer_timeout, 0); 1180 vv->video_dmaq.dev = dev; 1181 1182 /* set some default values */ 1183 vv->standard = &dev->ext_vv_data->stds[0]; 1184 1185 /* FIXME: what's this? */ 1186 vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A; 1187 vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A; 1188} 1189 1190 1191static int video_open(struct saa7146_dev *dev, struct file *file) 1192{ 1193 struct saa7146_fh *fh = file->private_data; 1194 1195 videobuf_queue_sg_init(&fh->video_q, &video_qops, 1196 &dev->pci->dev, &dev->slock, 1197 V4L2_BUF_TYPE_VIDEO_CAPTURE, 1198 V4L2_FIELD_INTERLACED, 1199 sizeof(struct saa7146_buf), 1200 file, &dev->v4l2_lock); 1201 1202 return 0; 1203} 1204 1205 1206static void video_close(struct saa7146_dev *dev, struct file *file) 1207{ 1208 struct saa7146_fh *fh = file->private_data; 1209 struct saa7146_vv *vv = dev->vv_data; 1210 struct videobuf_queue *q = &fh->video_q; 1211 1212 if (IS_CAPTURE_ACTIVE(fh) != 0) 1213 video_end(fh, file); 1214 else if (IS_OVERLAY_ACTIVE(fh) != 0) 1215 saa7146_stop_preview(fh); 1216 1217 videobuf_stop(q); 1218 /* hmm, why is this function declared void? */ 1219} 1220 1221 1222static void video_irq_done(struct saa7146_dev *dev, unsigned long st) 1223{ 1224 struct saa7146_vv *vv = dev->vv_data; 1225 struct saa7146_dmaqueue *q = &vv->video_dmaq; 1226 1227 spin_lock(&dev->slock); 1228 DEB_CAP("called\n"); 1229 1230 /* only finish the buffer if we have one... */ 1231 if( NULL != q->curr ) { 1232 saa7146_buffer_finish(dev,q,VIDEOBUF_DONE); 1233 } 1234 saa7146_buffer_next(dev,q,0); 1235 1236 spin_unlock(&dev->slock); 1237} 1238 1239static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) 1240{ 1241 struct saa7146_fh *fh = file->private_data; 1242 struct saa7146_dev *dev = fh->dev; 1243 struct saa7146_vv *vv = dev->vv_data; 1244 ssize_t ret = 0; 1245 1246 DEB_EE("called\n"); 1247 1248 if ((vv->video_status & STATUS_CAPTURE) != 0) { 1249 /* fixme: should we allow read() captures while streaming capture? */ 1250 if (vv->video_fh == fh) { 1251 DEB_S("already capturing\n"); 1252 return -EBUSY; 1253 } 1254 DEB_S("already capturing in another open\n"); 1255 return -EBUSY; 1256 } 1257 1258 ret = video_begin(fh); 1259 if( 0 != ret) { 1260 goto out; 1261 } 1262 1263 ret = videobuf_read_one(&fh->video_q , data, count, ppos, 1264 file->f_flags & O_NONBLOCK); 1265 if (ret != 0) { 1266 video_end(fh, file); 1267 } else { 1268 ret = video_end(fh, file); 1269 } 1270out: 1271 /* restart overlay if it was active before */ 1272 if (vv->ov_suspend != NULL) { 1273 saa7146_start_preview(vv->ov_suspend); 1274 vv->ov_suspend = NULL; 1275 } 1276 1277 return ret; 1278} 1279 1280const struct saa7146_use_ops saa7146_video_uops = { 1281 .init = video_init, 1282 .open = video_open, 1283 .release = video_close, 1284 .irq_done = video_irq_done, 1285 .read = video_read, 1286};