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 mutex_lock(&dev->lock); 557 558 /* ok, accept it */ 559 vv->ov_fb = *fb; 560 vv->ov_fmt = fmt; 561 562 if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) { 563 vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8; 564 DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline)); 565 } 566 567 mutex_unlock(&dev->lock); 568 return 0; 569} 570 571static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) 572{ 573 if (f->index >= NUM_FORMATS) 574 return -EINVAL; 575 strlcpy((char *)f->description, formats[f->index].name, 576 sizeof(f->description)); 577 f->pixelformat = formats[f->index].pixelformat; 578 return 0; 579} 580 581static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c) 582{ 583 const struct v4l2_queryctrl *ctrl; 584 585 if ((c->id < V4L2_CID_BASE || 586 c->id >= V4L2_CID_LASTP1) && 587 (c->id < V4L2_CID_PRIVATE_BASE || 588 c->id >= V4L2_CID_PRIVATE_LASTP1)) 589 return -EINVAL; 590 591 ctrl = ctrl_by_id(c->id); 592 if (ctrl == NULL) 593 return -EINVAL; 594 595 DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n", c->id)); 596 *c = *ctrl; 597 return 0; 598} 599 600static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c) 601{ 602 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 603 struct saa7146_vv *vv = dev->vv_data; 604 const struct v4l2_queryctrl *ctrl; 605 u32 value = 0; 606 607 ctrl = ctrl_by_id(c->id); 608 if (NULL == ctrl) 609 return -EINVAL; 610 switch (c->id) { 611 case V4L2_CID_BRIGHTNESS: 612 value = saa7146_read(dev, BCS_CTRL); 613 c->value = 0xff & (value >> 24); 614 DEB_D(("V4L2_CID_BRIGHTNESS: %d\n", c->value)); 615 break; 616 case V4L2_CID_CONTRAST: 617 value = saa7146_read(dev, BCS_CTRL); 618 c->value = 0x7f & (value >> 16); 619 DEB_D(("V4L2_CID_CONTRAST: %d\n", c->value)); 620 break; 621 case V4L2_CID_SATURATION: 622 value = saa7146_read(dev, BCS_CTRL); 623 c->value = 0x7f & (value >> 0); 624 DEB_D(("V4L2_CID_SATURATION: %d\n", c->value)); 625 break; 626 case V4L2_CID_VFLIP: 627 c->value = vv->vflip; 628 DEB_D(("V4L2_CID_VFLIP: %d\n", c->value)); 629 break; 630 case V4L2_CID_HFLIP: 631 c->value = vv->hflip; 632 DEB_D(("V4L2_CID_HFLIP: %d\n", c->value)); 633 break; 634 default: 635 return -EINVAL; 636 } 637 return 0; 638} 639 640static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) 641{ 642 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 643 struct saa7146_vv *vv = dev->vv_data; 644 const struct v4l2_queryctrl *ctrl; 645 646 ctrl = ctrl_by_id(c->id); 647 if (NULL == ctrl) { 648 DEB_D(("unknown control %d\n", c->id)); 649 return -EINVAL; 650 } 651 652 mutex_lock(&dev->lock); 653 654 switch (ctrl->type) { 655 case V4L2_CTRL_TYPE_BOOLEAN: 656 case V4L2_CTRL_TYPE_MENU: 657 case V4L2_CTRL_TYPE_INTEGER: 658 if (c->value < ctrl->minimum) 659 c->value = ctrl->minimum; 660 if (c->value > ctrl->maximum) 661 c->value = ctrl->maximum; 662 break; 663 default: 664 /* nothing */; 665 } 666 667 switch (c->id) { 668 case V4L2_CID_BRIGHTNESS: { 669 u32 value = saa7146_read(dev, BCS_CTRL); 670 value &= 0x00ffffff; 671 value |= (c->value << 24); 672 saa7146_write(dev, BCS_CTRL, value); 673 saa7146_write(dev, MC2, MASK_22 | MASK_06); 674 break; 675 } 676 case V4L2_CID_CONTRAST: { 677 u32 value = saa7146_read(dev, BCS_CTRL); 678 value &= 0xff00ffff; 679 value |= (c->value << 16); 680 saa7146_write(dev, BCS_CTRL, value); 681 saa7146_write(dev, MC2, MASK_22 | MASK_06); 682 break; 683 } 684 case V4L2_CID_SATURATION: { 685 u32 value = saa7146_read(dev, BCS_CTRL); 686 value &= 0xffffff00; 687 value |= (c->value << 0); 688 saa7146_write(dev, BCS_CTRL, value); 689 saa7146_write(dev, MC2, MASK_22 | MASK_06); 690 break; 691 } 692 case V4L2_CID_HFLIP: 693 if (IS_CAPTURE_ACTIVE(fh) != 0) { 694 DEB_D(("V4L2_CID_HFLIP while active capture.\n")); 695 mutex_unlock(&dev->lock); 696 return -EBUSY; 697 } 698 vv->hflip = c->value; 699 break; 700 case V4L2_CID_VFLIP: 701 if (IS_CAPTURE_ACTIVE(fh) != 0) { 702 DEB_D(("V4L2_CID_VFLIP while active capture.\n")); 703 mutex_unlock(&dev->lock); 704 return -EBUSY; 705 } 706 vv->vflip = c->value; 707 break; 708 default: 709 mutex_unlock(&dev->lock); 710 return -EINVAL; 711 } 712 mutex_unlock(&dev->lock); 713 714 if (IS_OVERLAY_ACTIVE(fh) != 0) { 715 saa7146_stop_preview(fh); 716 saa7146_start_preview(fh); 717 } 718 return 0; 719} 720 721static int vidioc_g_parm(struct file *file, void *fh, 722 struct v4l2_streamparm *parm) 723{ 724 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 725 struct saa7146_vv *vv = dev->vv_data; 726 727 parm->parm.capture.readbuffers = 1; 728 v4l2_video_std_frame_period(vv->standard->id, 729 &parm->parm.capture.timeperframe); 730 return 0; 731} 732 733static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) 734{ 735 f->fmt.pix = ((struct saa7146_fh *)fh)->video_fmt; 736 return 0; 737} 738 739static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) 740{ 741 f->fmt.win = ((struct saa7146_fh *)fh)->ov.win; 742 return 0; 743} 744 745static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f) 746{ 747 f->fmt.vbi = ((struct saa7146_fh *)fh)->vbi_fmt; 748 return 0; 749} 750 751static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) 752{ 753 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 754 struct saa7146_vv *vv = dev->vv_data; 755 struct saa7146_format *fmt; 756 enum v4l2_field field; 757 int maxw, maxh; 758 int calc_bpl; 759 760 DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh)); 761 762 fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat); 763 if (NULL == fmt) 764 return -EINVAL; 765 766 field = f->fmt.pix.field; 767 maxw = vv->standard->h_max_out; 768 maxh = vv->standard->v_max_out; 769 770 if (V4L2_FIELD_ANY == field) { 771 field = (f->fmt.pix.height > maxh / 2) 772 ? V4L2_FIELD_INTERLACED 773 : V4L2_FIELD_BOTTOM; 774 } 775 switch (field) { 776 case V4L2_FIELD_ALTERNATE: 777 vv->last_field = V4L2_FIELD_TOP; 778 maxh = maxh / 2; 779 break; 780 case V4L2_FIELD_TOP: 781 case V4L2_FIELD_BOTTOM: 782 vv->last_field = V4L2_FIELD_INTERLACED; 783 maxh = maxh / 2; 784 break; 785 case V4L2_FIELD_INTERLACED: 786 vv->last_field = V4L2_FIELD_INTERLACED; 787 break; 788 default: 789 DEB_D(("no known field mode '%d'.\n", field)); 790 return -EINVAL; 791 } 792 793 f->fmt.pix.field = field; 794 if (f->fmt.pix.width > maxw) 795 f->fmt.pix.width = maxw; 796 if (f->fmt.pix.height > maxh) 797 f->fmt.pix.height = maxh; 798 799 calc_bpl = (f->fmt.pix.width * fmt->depth) / 8; 800 801 if (f->fmt.pix.bytesperline < calc_bpl) 802 f->fmt.pix.bytesperline = calc_bpl; 803 804 if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */ 805 f->fmt.pix.bytesperline = calc_bpl; 806 807 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; 808 DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width, 809 f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage)); 810 811 return 0; 812} 813 814 815static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) 816{ 817 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 818 struct saa7146_vv *vv = dev->vv_data; 819 struct v4l2_window *win = &f->fmt.win; 820 enum v4l2_field field; 821 int maxw, maxh; 822 823 DEB_EE(("dev:%p\n", dev)); 824 825 if (NULL == vv->ov_fb.base) { 826 DEB_D(("no fb base set.\n")); 827 return -EINVAL; 828 } 829 if (NULL == vv->ov_fmt) { 830 DEB_D(("no fb fmt set.\n")); 831 return -EINVAL; 832 } 833 if (win->w.width < 48 || win->w.height < 32) { 834 DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height)); 835 return -EINVAL; 836 } 837 if (win->clipcount > 16) { 838 DEB_D(("clipcount too big.\n")); 839 return -EINVAL; 840 } 841 842 field = win->field; 843 maxw = vv->standard->h_max_out; 844 maxh = vv->standard->v_max_out; 845 846 if (V4L2_FIELD_ANY == field) { 847 field = (win->w.height > maxh / 2) 848 ? V4L2_FIELD_INTERLACED 849 : V4L2_FIELD_TOP; 850 } 851 switch (field) { 852 case V4L2_FIELD_TOP: 853 case V4L2_FIELD_BOTTOM: 854 case V4L2_FIELD_ALTERNATE: 855 maxh = maxh / 2; 856 break; 857 case V4L2_FIELD_INTERLACED: 858 break; 859 default: 860 DEB_D(("no known field mode '%d'.\n", field)); 861 return -EINVAL; 862 } 863 864 win->field = field; 865 if (win->w.width > maxw) 866 win->w.width = maxw; 867 if (win->w.height > maxh) 868 win->w.height = maxh; 869 870 return 0; 871} 872 873static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) 874{ 875 struct saa7146_fh *fh = __fh; 876 struct saa7146_dev *dev = fh->dev; 877 struct saa7146_vv *vv = dev->vv_data; 878 int err; 879 880 DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh)); 881 if (IS_CAPTURE_ACTIVE(fh) != 0) { 882 DEB_EE(("streaming capture is active\n")); 883 return -EBUSY; 884 } 885 err = vidioc_try_fmt_vid_cap(file, fh, f); 886 if (0 != err) 887 return err; 888 fh->video_fmt = f->fmt.pix; 889 DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat)); 890 return 0; 891} 892 893static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f) 894{ 895 struct saa7146_fh *fh = __fh; 896 struct saa7146_dev *dev = fh->dev; 897 struct saa7146_vv *vv = dev->vv_data; 898 int err; 899 900 DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh)); 901 err = vidioc_try_fmt_vid_overlay(file, fh, f); 902 if (0 != err) 903 return err; 904 mutex_lock(&dev->lock); 905 fh->ov.win = f->fmt.win; 906 fh->ov.nclips = f->fmt.win.clipcount; 907 if (fh->ov.nclips > 16) 908 fh->ov.nclips = 16; 909 if (copy_from_user(fh->ov.clips, f->fmt.win.clips, 910 sizeof(struct v4l2_clip) * fh->ov.nclips)) { 911 mutex_unlock(&dev->lock); 912 return -EFAULT; 913 } 914 915 /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ 916 fh->ov.fh = fh; 917 918 mutex_unlock(&dev->lock); 919 920 /* check if our current overlay is active */ 921 if (IS_OVERLAY_ACTIVE(fh) != 0) { 922 saa7146_stop_preview(fh); 923 saa7146_start_preview(fh); 924 } 925 return 0; 926} 927 928static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm) 929{ 930 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 931 struct saa7146_vv *vv = dev->vv_data; 932 933 *norm = vv->standard->id; 934 return 0; 935} 936 937 /* the saa7146 supfhrts (used in conjunction with the saa7111a for example) 938 PAL / NTSC / SECAM. if your hardware does not (or does more) 939 -- override this function in your extension */ 940/* 941 case VIDIOC_ENUMSTD: 942 { 943 struct v4l2_standard *e = arg; 944 if (e->index < 0 ) 945 return -EINVAL; 946 if( e->index < dev->ext_vv_data->num_stds ) { 947 DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index)); 948 v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name); 949 return 0; 950 } 951 return -EINVAL; 952 } 953 */ 954 955static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id) 956{ 957 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 958 struct saa7146_vv *vv = dev->vv_data; 959 int found = 0; 960 int err, i; 961 962 DEB_EE(("VIDIOC_S_STD\n")); 963 964 if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) { 965 DEB_D(("cannot change video standard while streaming capture is active\n")); 966 return -EBUSY; 967 } 968 969 if ((vv->video_status & STATUS_OVERLAY) != 0) { 970 vv->ov_suspend = vv->video_fh; 971 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ 972 if (0 != err) { 973 DEB_D(("suspending video failed. aborting\n")); 974 return err; 975 } 976 } 977 978 mutex_lock(&dev->lock); 979 980 for (i = 0; i < dev->ext_vv_data->num_stds; i++) 981 if (*id & dev->ext_vv_data->stds[i].id) 982 break; 983 if (i != dev->ext_vv_data->num_stds) { 984 vv->standard = &dev->ext_vv_data->stds[i]; 985 if (NULL != dev->ext_vv_data->std_callback) 986 dev->ext_vv_data->std_callback(dev, vv->standard); 987 found = 1; 988 } 989 990 mutex_unlock(&dev->lock); 991 992 if (vv->ov_suspend != NULL) { 993 saa7146_start_preview(vv->ov_suspend); 994 vv->ov_suspend = NULL; 995 } 996 997 if (!found) { 998 DEB_EE(("VIDIOC_S_STD: standard not found.\n")); 999 return -EINVAL; 1000 } 1001 1002 DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name)); 1003 return 0; 1004} 1005 1006static int vidioc_overlay(struct file *file, void *fh, unsigned int on) 1007{ 1008 int err; 1009 1010 DEB_D(("VIDIOC_OVERLAY on:%d\n", on)); 1011 if (on) 1012 err = saa7146_start_preview(fh); 1013 else 1014 err = saa7146_stop_preview(fh); 1015 return err; 1016} 1017 1018static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b) 1019{ 1020 struct saa7146_fh *fh = __fh; 1021 1022 if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1023 return videobuf_reqbufs(&fh->video_q, b); 1024 if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE) 1025 return videobuf_reqbufs(&fh->vbi_q, b); 1026 return -EINVAL; 1027} 1028 1029static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf) 1030{ 1031 struct saa7146_fh *fh = __fh; 1032 1033 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1034 return videobuf_querybuf(&fh->video_q, buf); 1035 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) 1036 return videobuf_querybuf(&fh->vbi_q, buf); 1037 return -EINVAL; 1038} 1039 1040static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) 1041{ 1042 struct saa7146_fh *fh = __fh; 1043 1044 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1045 return videobuf_qbuf(&fh->video_q, buf); 1046 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) 1047 return videobuf_qbuf(&fh->vbi_q, buf); 1048 return -EINVAL; 1049} 1050 1051static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) 1052{ 1053 struct saa7146_fh *fh = __fh; 1054 1055 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1056 return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK); 1057 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) 1058 return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK); 1059 return -EINVAL; 1060} 1061 1062static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type) 1063{ 1064 struct saa7146_fh *fh = __fh; 1065 int err; 1066 1067 DEB_D(("VIDIOC_STREAMON, type:%d\n", type)); 1068 1069 err = video_begin(fh); 1070 if (err) 1071 return err; 1072 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1073 return videobuf_streamon(&fh->video_q); 1074 if (type == V4L2_BUF_TYPE_VBI_CAPTURE) 1075 return videobuf_streamon(&fh->vbi_q); 1076 return -EINVAL; 1077} 1078 1079static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type) 1080{ 1081 struct saa7146_fh *fh = __fh; 1082 struct saa7146_dev *dev = fh->dev; 1083 struct saa7146_vv *vv = dev->vv_data; 1084 int err; 1085 1086 DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type)); 1087 1088 /* ugly: we need to copy some checks from video_end(), 1089 because videobuf_streamoff() relies on the capture running. 1090 check and fix this */ 1091 if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { 1092 DEB_S(("not capturing.\n")); 1093 return 0; 1094 } 1095 1096 if (vv->video_fh != fh) { 1097 DEB_S(("capturing, but in another open.\n")); 1098 return -EBUSY; 1099 } 1100 1101 err = -EINVAL; 1102 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1103 err = videobuf_streamoff(&fh->video_q); 1104 else if (type == V4L2_BUF_TYPE_VBI_CAPTURE) 1105 err = videobuf_streamoff(&fh->vbi_q); 1106 if (0 != err) { 1107 DEB_D(("warning: videobuf_streamoff() failed.\n")); 1108 video_end(fh, file); 1109 } else { 1110 err = video_end(fh, file); 1111 } 1112 return err; 1113} 1114 1115static int vidioc_g_chip_ident(struct file *file, void *__fh, 1116 struct v4l2_dbg_chip_ident *chip) 1117{ 1118 struct saa7146_fh *fh = __fh; 1119 struct saa7146_dev *dev = fh->dev; 1120 1121 chip->ident = V4L2_IDENT_NONE; 1122 chip->revision = 0; 1123 if (chip->match.type == V4L2_CHIP_MATCH_HOST && !chip->match.addr) { 1124 chip->ident = V4L2_IDENT_SAA7146; 1125 return 0; 1126 } 1127 return v4l2_device_call_until_err(&dev->v4l2_dev, 0, 1128 core, g_chip_ident, chip); 1129} 1130 1131#ifdef CONFIG_VIDEO_V4L1_COMPAT 1132static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf) 1133{ 1134 struct saa7146_fh *fh = __fh; 1135 struct videobuf_queue *q = &fh->video_q; 1136 int err, i; 1137 1138 int gbuffers = 2; 1139 int gbufsize = 768 * 576 * 4; 1140 1141 DEB_D(("VIDIOCGMBUF \n")); 1142 1143 q = &fh->video_q; 1144 err = videobuf_mmap_setup(q, gbuffers, gbufsize, 1145 V4L2_MEMORY_MMAP); 1146 if (err < 0) 1147 return err; 1148 1149 gbuffers = err; 1150 memset(mbuf, 0, sizeof(*mbuf)); 1151 mbuf->frames = gbuffers; 1152 mbuf->size = gbuffers * gbufsize; 1153 for (i = 0; i < gbuffers; i++) 1154 mbuf->offsets[i] = i * gbufsize; 1155 return 0; 1156} 1157#endif 1158 1159const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { 1160 .vidioc_querycap = vidioc_querycap, 1161 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, 1162 .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap, 1163 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, 1164 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, 1165 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, 1166 .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, 1167 .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, 1168 .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, 1169 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, 1170 .vidioc_g_chip_ident = vidioc_g_chip_ident, 1171 1172 .vidioc_overlay = vidioc_overlay, 1173 .vidioc_g_fbuf = vidioc_g_fbuf, 1174 .vidioc_s_fbuf = vidioc_s_fbuf, 1175 .vidioc_reqbufs = vidioc_reqbufs, 1176 .vidioc_querybuf = vidioc_querybuf, 1177 .vidioc_qbuf = vidioc_qbuf, 1178 .vidioc_dqbuf = vidioc_dqbuf, 1179 .vidioc_g_std = vidioc_g_std, 1180 .vidioc_s_std = vidioc_s_std, 1181 .vidioc_queryctrl = vidioc_queryctrl, 1182 .vidioc_g_ctrl = vidioc_g_ctrl, 1183 .vidioc_s_ctrl = vidioc_s_ctrl, 1184 .vidioc_streamon = vidioc_streamon, 1185 .vidioc_streamoff = vidioc_streamoff, 1186 .vidioc_g_parm = vidioc_g_parm, 1187#ifdef CONFIG_VIDEO_V4L1_COMPAT 1188 .vidiocgmbuf = vidiocgmbuf, 1189#endif 1190}; 1191 1192/*********************************************************************************/ 1193/* buffer handling functions */ 1194 1195static int buffer_activate (struct saa7146_dev *dev, 1196 struct saa7146_buf *buf, 1197 struct saa7146_buf *next) 1198{ 1199 struct saa7146_vv *vv = dev->vv_data; 1200 1201 buf->vb.state = VIDEOBUF_ACTIVE; 1202 saa7146_set_capture(dev,buf,next); 1203 1204 mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT); 1205 return 0; 1206} 1207 1208static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf) 1209{ 1210 saa7146_pgtable_free(dev->pci, &buf->pt[0]); 1211 saa7146_pgtable_free(dev->pci, &buf->pt[1]); 1212 saa7146_pgtable_free(dev->pci, &buf->pt[2]); 1213} 1214 1215static int buffer_prepare(struct videobuf_queue *q, 1216 struct videobuf_buffer *vb, enum v4l2_field field) 1217{ 1218 struct file *file = q->priv_data; 1219 struct saa7146_fh *fh = file->private_data; 1220 struct saa7146_dev *dev = fh->dev; 1221 struct saa7146_vv *vv = dev->vv_data; 1222 struct saa7146_buf *buf = (struct saa7146_buf *)vb; 1223 int size,err = 0; 1224 1225 DEB_CAP(("vbuf:%p\n",vb)); 1226 1227 /* sanity checks */ 1228 if (fh->video_fmt.width < 48 || 1229 fh->video_fmt.height < 32 || 1230 fh->video_fmt.width > vv->standard->h_max_out || 1231 fh->video_fmt.height > vv->standard->v_max_out) { 1232 DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height)); 1233 return -EINVAL; 1234 } 1235 1236 size = fh->video_fmt.sizeimage; 1237 if (0 != buf->vb.baddr && buf->vb.bsize < size) { 1238 DEB_D(("size mismatch.\n")); 1239 return -EINVAL; 1240 } 1241 1242 DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n", 1243 fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field])); 1244 if (buf->vb.width != fh->video_fmt.width || 1245 buf->vb.bytesperline != fh->video_fmt.bytesperline || 1246 buf->vb.height != fh->video_fmt.height || 1247 buf->vb.size != size || 1248 buf->vb.field != field || 1249 buf->vb.field != fh->video_fmt.field || 1250 buf->fmt != &fh->video_fmt) { 1251 saa7146_dma_free(dev,q,buf); 1252 } 1253 1254 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { 1255 struct saa7146_format *sfmt; 1256 1257 buf->vb.bytesperline = fh->video_fmt.bytesperline; 1258 buf->vb.width = fh->video_fmt.width; 1259 buf->vb.height = fh->video_fmt.height; 1260 buf->vb.size = size; 1261 buf->vb.field = field; 1262 buf->fmt = &fh->video_fmt; 1263 buf->vb.field = fh->video_fmt.field; 1264 1265 sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); 1266 1267 release_all_pagetables(dev, buf); 1268 if( 0 != IS_PLANAR(sfmt->trans)) { 1269 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); 1270 saa7146_pgtable_alloc(dev->pci, &buf->pt[1]); 1271 saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); 1272 } else { 1273 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); 1274 } 1275 1276 err = videobuf_iolock(q,&buf->vb, &vv->ov_fb); 1277 if (err) 1278 goto oops; 1279 err = saa7146_pgtable_build(dev,buf); 1280 if (err) 1281 goto oops; 1282 } 1283 buf->vb.state = VIDEOBUF_PREPARED; 1284 buf->activate = buffer_activate; 1285 1286 return 0; 1287 1288 oops: 1289 DEB_D(("error out.\n")); 1290 saa7146_dma_free(dev,q,buf); 1291 1292 return err; 1293} 1294 1295static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) 1296{ 1297 struct file *file = q->priv_data; 1298 struct saa7146_fh *fh = file->private_data; 1299 1300 if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS) 1301 *count = MAX_SAA7146_CAPTURE_BUFFERS; 1302 1303 *size = fh->video_fmt.sizeimage; 1304 1305 /* check if we exceed the "max_memory" parameter */ 1306 if( (*count * *size) > (max_memory*1048576) ) { 1307 *count = (max_memory*1048576) / *size; 1308 } 1309 1310 DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size)); 1311 1312 return 0; 1313} 1314 1315static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) 1316{ 1317 struct file *file = q->priv_data; 1318 struct saa7146_fh *fh = file->private_data; 1319 struct saa7146_dev *dev = fh->dev; 1320 struct saa7146_vv *vv = dev->vv_data; 1321 struct saa7146_buf *buf = (struct saa7146_buf *)vb; 1322 1323 DEB_CAP(("vbuf:%p\n",vb)); 1324 saa7146_buffer_queue(fh->dev,&vv->video_q,buf); 1325} 1326 1327static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) 1328{ 1329 struct file *file = q->priv_data; 1330 struct saa7146_fh *fh = file->private_data; 1331 struct saa7146_dev *dev = fh->dev; 1332 struct saa7146_buf *buf = (struct saa7146_buf *)vb; 1333 1334 DEB_CAP(("vbuf:%p\n",vb)); 1335 1336 saa7146_dma_free(dev,q,buf); 1337 1338 release_all_pagetables(dev, buf); 1339} 1340 1341static struct videobuf_queue_ops video_qops = { 1342 .buf_setup = buffer_setup, 1343 .buf_prepare = buffer_prepare, 1344 .buf_queue = buffer_queue, 1345 .buf_release = buffer_release, 1346}; 1347 1348/********************************************************************************/ 1349/* file operations */ 1350 1351static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv) 1352{ 1353 INIT_LIST_HEAD(&vv->video_q.queue); 1354 1355 init_timer(&vv->video_q.timeout); 1356 vv->video_q.timeout.function = saa7146_buffer_timeout; 1357 vv->video_q.timeout.data = (unsigned long)(&vv->video_q); 1358 vv->video_q.dev = dev; 1359 1360 /* set some default values */ 1361 vv->standard = &dev->ext_vv_data->stds[0]; 1362 1363 vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A; 1364 vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A; 1365} 1366 1367 1368static int video_open(struct saa7146_dev *dev, struct file *file) 1369{ 1370 struct saa7146_fh *fh = file->private_data; 1371 struct saa7146_format *sfmt; 1372 1373 fh->video_fmt.width = 384; 1374 fh->video_fmt.height = 288; 1375 fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24; 1376 fh->video_fmt.bytesperline = 0; 1377 fh->video_fmt.field = V4L2_FIELD_ANY; 1378 sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); 1379 fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; 1380 1381 videobuf_queue_sg_init(&fh->video_q, &video_qops, 1382 &dev->pci->dev, &dev->slock, 1383 V4L2_BUF_TYPE_VIDEO_CAPTURE, 1384 V4L2_FIELD_INTERLACED, 1385 sizeof(struct saa7146_buf), 1386 file); 1387 1388 return 0; 1389} 1390 1391 1392static void video_close(struct saa7146_dev *dev, struct file *file) 1393{ 1394 struct saa7146_fh *fh = file->private_data; 1395 struct saa7146_vv *vv = dev->vv_data; 1396 struct videobuf_queue *q = &fh->video_q; 1397 int err; 1398 1399 if (IS_CAPTURE_ACTIVE(fh) != 0) { 1400 err = video_end(fh, file); 1401 } else if (IS_OVERLAY_ACTIVE(fh) != 0) { 1402 err = saa7146_stop_preview(fh); 1403 } 1404 1405 videobuf_stop(q); 1406 1407 /* hmm, why is this function declared void? */ 1408 /* return err */ 1409} 1410 1411 1412static void video_irq_done(struct saa7146_dev *dev, unsigned long st) 1413{ 1414 struct saa7146_vv *vv = dev->vv_data; 1415 struct saa7146_dmaqueue *q = &vv->video_q; 1416 1417 spin_lock(&dev->slock); 1418 DEB_CAP(("called.\n")); 1419 1420 /* only finish the buffer if we have one... */ 1421 if( NULL != q->curr ) { 1422 saa7146_buffer_finish(dev,q,VIDEOBUF_DONE); 1423 } 1424 saa7146_buffer_next(dev,q,0); 1425 1426 spin_unlock(&dev->slock); 1427} 1428 1429static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) 1430{ 1431 struct saa7146_fh *fh = file->private_data; 1432 struct saa7146_dev *dev = fh->dev; 1433 struct saa7146_vv *vv = dev->vv_data; 1434 ssize_t ret = 0; 1435 1436 DEB_EE(("called.\n")); 1437 1438 if ((vv->video_status & STATUS_CAPTURE) != 0) { 1439 if (vv->video_fh == fh) { 1440 DEB_S(("already capturing.\n")); 1441 return -EBUSY; 1442 } 1443 DEB_S(("already capturing in another open.\n")); 1444 return -EBUSY; 1445 } 1446 1447 ret = video_begin(fh); 1448 if( 0 != ret) { 1449 goto out; 1450 } 1451 1452 ret = videobuf_read_one(&fh->video_q , data, count, ppos, 1453 file->f_flags & O_NONBLOCK); 1454 if (ret != 0) { 1455 video_end(fh, file); 1456 } else { 1457 ret = video_end(fh, file); 1458 } 1459out: 1460 /* restart overlay if it was active before */ 1461 if (vv->ov_suspend != NULL) { 1462 saa7146_start_preview(vv->ov_suspend); 1463 vv->ov_suspend = NULL; 1464 } 1465 1466 return ret; 1467} 1468 1469struct saa7146_use_ops saa7146_video_uops = { 1470 .init = video_init, 1471 .open = video_open, 1472 .release = video_close, 1473 .irq_done = video_irq_done, 1474 .read = video_read, 1475}; 1476