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