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