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

Configure Feed

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

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