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