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