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