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