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