linux/drivers/media/video/pms.c
<<
>>
Prefs
   1/*
   2 *      Media Vision Pro Movie Studio
   3 *                      or
   4 *      "all you need is an I2C bus some RAM and a prayer"
   5 *
   6 *      This draws heavily on code
   7 *
   8 *      (c) Wolfgang Koehler,  wolf@first.gmd.de, Dec. 1994
   9 *      Kiefernring 15
  10 *      14478 Potsdam, Germany
  11 *
  12 *      Most of this code is directly derived from his userspace driver.
  13 *      His driver works so send any reports to alan@lxorguk.ukuu.org.uk
  14 *      unless the userspace driver also doesn't work for you...
  15 *
  16 *      Changes:
  17 *      25-11-2009      Hans Verkuil <hverkuil@xs4all.nl>
  18 *                      - converted to version 2 of the V4L API.
  19 *      08/07/2003      Daniele Bellucci <bellucda@tiscali.it>
  20 *                      - pms_capture: report back -EFAULT
  21 */
  22
  23#include <linux/module.h>
  24#include <linux/delay.h>
  25#include <linux/errno.h>
  26#include <linux/fs.h>
  27#include <linux/kernel.h>
  28#include <linux/mm.h>
  29#include <linux/ioport.h>
  30#include <linux/init.h>
  31#include <linux/version.h>
  32#include <linux/mutex.h>
  33#include <linux/uaccess.h>
  34#include <asm/io.h>
  35
  36#include <linux/videodev2.h>
  37#include <media/v4l2-common.h>
  38#include <media/v4l2-ioctl.h>
  39#include <media/v4l2-device.h>
  40
  41MODULE_LICENSE("GPL");
  42
  43
  44#define MOTOROLA        1
  45#define PHILIPS2        2               /* SAA7191 */
  46#define PHILIPS1        3
  47#define MVVMEMORYWIDTH  0x40            /* 512 bytes */
  48
  49struct i2c_info {
  50        u8 slave;
  51        u8 sub;
  52        u8 data;
  53        u8 hits;
  54};
  55
  56struct pms {
  57        struct v4l2_device v4l2_dev;
  58        struct video_device vdev;
  59        int height;
  60        int width;
  61        int depth;
  62        int input;
  63        s32 brightness, saturation, hue, contrast;
  64        struct mutex lock;
  65        int i2c_count;
  66        struct i2c_info i2cinfo[64];
  67
  68        int decoder;
  69        int standard;   /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
  70        v4l2_std_id std;
  71        int io;
  72        int data;
  73        void __iomem *mem;
  74};
  75
  76static struct pms pms_card;
  77
  78/*
  79 *      I/O ports and Shared Memory
  80 */
  81
  82static int io_port = 0x250;
  83module_param(io_port, int, 0);
  84
  85static int mem_base = 0xc8000;
  86module_param(mem_base, int, 0);
  87
  88static int video_nr = -1;
  89module_param(video_nr, int, 0);
  90
  91
  92static inline void mvv_write(struct pms *dev, u8 index, u8 value)
  93{
  94        outw(index | (value << 8), dev->io);
  95}
  96
  97static inline u8 mvv_read(struct pms *dev, u8 index)
  98{
  99        outb(index, dev->io);
 100        return inb(dev->data);
 101}
 102
 103static int pms_i2c_stat(struct pms *dev, u8 slave)
 104{
 105        int counter = 0;
 106        int i;
 107
 108        outb(0x28, dev->io);
 109
 110        while ((inb(dev->data) & 0x01) == 0)
 111                if (counter++ == 256)
 112                        break;
 113
 114        while ((inb(dev->data) & 0x01) != 0)
 115                if (counter++ == 256)
 116                        break;
 117
 118        outb(slave, dev->io);
 119
 120        counter = 0;
 121        while ((inb(dev->data) & 0x01) == 0)
 122                if (counter++ == 256)
 123                        break;
 124
 125        while ((inb(dev->data) & 0x01) != 0)
 126                if (counter++ == 256)
 127                        break;
 128
 129        for (i = 0; i < 12; i++) {
 130                char st = inb(dev->data);
 131
 132                if ((st & 2) != 0)
 133                        return -1;
 134                if ((st & 1) == 0)
 135                        break;
 136        }
 137        outb(0x29, dev->io);
 138        return inb(dev->data);
 139}
 140
 141static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data)
 142{
 143        int skip = 0;
 144        int count;
 145        int i;
 146
 147        for (i = 0; i < dev->i2c_count; i++) {
 148                if ((dev->i2cinfo[i].slave == slave) &&
 149                    (dev->i2cinfo[i].sub == sub)) {
 150                        if (dev->i2cinfo[i].data == data)
 151                                skip = 1;
 152                        dev->i2cinfo[i].data = data;
 153                        i = dev->i2c_count + 1;
 154                }
 155        }
 156
 157        if (i == dev->i2c_count && dev->i2c_count < 64) {
 158                dev->i2cinfo[dev->i2c_count].slave = slave;
 159                dev->i2cinfo[dev->i2c_count].sub = sub;
 160                dev->i2cinfo[dev->i2c_count].data = data;
 161                dev->i2c_count++;
 162        }
 163
 164        if (skip)
 165                return 0;
 166
 167        mvv_write(dev, 0x29, sub);
 168        mvv_write(dev, 0x2A, data);
 169        mvv_write(dev, 0x28, slave);
 170
 171        outb(0x28, dev->io);
 172
 173        count = 0;
 174        while ((inb(dev->data) & 1) == 0)
 175                if (count > 255)
 176                        break;
 177        while ((inb(dev->data) & 1) != 0)
 178                if (count > 255)
 179                        break;
 180
 181        count = inb(dev->data);
 182
 183        if (count & 2)
 184                return -1;
 185        return count;
 186}
 187
 188static int pms_i2c_read(struct pms *dev, int slave, int sub)
 189{
 190        int i;
 191
 192        for (i = 0; i < dev->i2c_count; i++) {
 193                if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub)
 194                        return dev->i2cinfo[i].data;
 195        }
 196        return 0;
 197}
 198
 199
 200static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or)
 201{
 202        u8 tmp;
 203
 204        tmp = pms_i2c_read(dev, slave, sub);
 205        tmp = (tmp & and) | or;
 206        pms_i2c_write(dev, slave, sub, tmp);
 207}
 208
 209/*
 210 *      Control functions
 211 */
 212
 213
 214static void pms_videosource(struct pms *dev, short source)
 215{
 216        switch (dev->decoder) {
 217        case MOTOROLA:
 218                break;
 219        case PHILIPS2:
 220                pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0);
 221                break;
 222        case PHILIPS1:
 223                break;
 224        }
 225        mvv_write(dev, 0x2E, 0x31);
 226        /* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30);
 227           But could not make this work correctly. Only Composite input
 228           worked for me. */
 229}
 230
 231static void pms_hue(struct pms *dev, short hue)
 232{
 233        switch (dev->decoder) {
 234        case MOTOROLA:
 235                pms_i2c_write(dev, 0x8a, 0x00, hue);
 236                break;
 237        case PHILIPS2:
 238                pms_i2c_write(dev, 0x8a, 0x07, hue);
 239                break;
 240        case PHILIPS1:
 241                pms_i2c_write(dev, 0x42, 0x07, hue);
 242                break;
 243        }
 244}
 245
 246static void pms_saturation(struct pms *dev, short sat)
 247{
 248        switch (dev->decoder) {
 249        case MOTOROLA:
 250                pms_i2c_write(dev, 0x8a, 0x00, sat);
 251                break;
 252        case PHILIPS1:
 253                pms_i2c_write(dev, 0x42, 0x12, sat);
 254                break;
 255        }
 256}
 257
 258
 259static void pms_contrast(struct pms *dev, short contrast)
 260{
 261        switch (dev->decoder) {
 262        case MOTOROLA:
 263                pms_i2c_write(dev, 0x8a, 0x00, contrast);
 264                break;
 265        case PHILIPS1:
 266                pms_i2c_write(dev, 0x42, 0x13, contrast);
 267                break;
 268        }
 269}
 270
 271static void pms_brightness(struct pms *dev, short brightness)
 272{
 273        switch (dev->decoder) {
 274        case MOTOROLA:
 275                pms_i2c_write(dev, 0x8a, 0x00, brightness);
 276                pms_i2c_write(dev, 0x8a, 0x00, brightness);
 277                pms_i2c_write(dev, 0x8a, 0x00, brightness);
 278                break;
 279        case PHILIPS1:
 280                pms_i2c_write(dev, 0x42, 0x19, brightness);
 281                break;
 282        }
 283}
 284
 285
 286static void pms_format(struct pms *dev, short format)
 287{
 288        int target;
 289
 290        dev->standard = format;
 291
 292        if (dev->decoder == PHILIPS1)
 293                target = 0x42;
 294        else if (dev->decoder == PHILIPS2)
 295                target = 0x8a;
 296        else
 297                return;
 298
 299        switch (format) {
 300        case 0: /* Auto */
 301                pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
 302                pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80);
 303                break;
 304        case 1: /* NTSC */
 305                pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
 306                pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40);
 307                break;
 308        case 2: /* PAL */
 309                pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
 310                pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
 311                break;
 312        case 3: /* SECAM */
 313                pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01);
 314                pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
 315                break;
 316        }
 317}
 318
 319#ifdef FOR_FUTURE_EXPANSION
 320
 321/*
 322 *      These features of the PMS card are not currently exposes. They
 323 *      could become a private v4l ioctl for PMSCONFIG or somesuch if
 324 *      people need it. We also don't yet use the PMS interrupt.
 325 */
 326
 327static void pms_hstart(struct pms *dev, short start)
 328{
 329        switch (dev->decoder) {
 330        case PHILIPS1:
 331                pms_i2c_write(dev, 0x8a, 0x05, start);
 332                pms_i2c_write(dev, 0x8a, 0x18, start);
 333                break;
 334        case PHILIPS2:
 335                pms_i2c_write(dev, 0x42, 0x05, start);
 336                pms_i2c_write(dev, 0x42, 0x18, start);
 337                break;
 338        }
 339}
 340
 341/*
 342 *      Bandpass filters
 343 */
 344
 345static void pms_bandpass(struct pms *dev, short pass)
 346{
 347        if (dev->decoder == PHILIPS2)
 348                pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4);
 349        else if (dev->decoder == PHILIPS1)
 350                pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4);
 351}
 352
 353static void pms_antisnow(struct pms *dev, short snow)
 354{
 355        if (dev->decoder == PHILIPS2)
 356                pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2);
 357        else if (dev->decoder == PHILIPS1)
 358                pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2);
 359}
 360
 361static void pms_sharpness(struct pms *dev, short sharp)
 362{
 363        if (dev->decoder == PHILIPS2)
 364                pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03);
 365        else if (dev->decoder == PHILIPS1)
 366                pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03);
 367}
 368
 369static void pms_chromaagc(struct pms *dev, short agc)
 370{
 371        if (dev->decoder == PHILIPS2)
 372                pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5);
 373        else if (dev->decoder == PHILIPS1)
 374                pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5);
 375}
 376
 377static void pms_vertnoise(struct pms *dev, short noise)
 378{
 379        if (dev->decoder == PHILIPS2)
 380                pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3);
 381        else if (dev->decoder == PHILIPS1)
 382                pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3);
 383}
 384
 385static void pms_forcecolour(struct pms *dev, short colour)
 386{
 387        if (dev->decoder == PHILIPS2)
 388                pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7);
 389        else if (dev->decoder == PHILIPS1)
 390                pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7);
 391}
 392
 393static void pms_antigamma(struct pms *dev, short gamma)
 394{
 395        if (dev->decoder == PHILIPS2)
 396                pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7);
 397        else if (dev->decoder == PHILIPS1)
 398                pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7);
 399}
 400
 401static void pms_prefilter(struct pms *dev, short filter)
 402{
 403        if (dev->decoder == PHILIPS2)
 404                pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6);
 405        else if (dev->decoder == PHILIPS1)
 406                pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6);
 407}
 408
 409static void pms_hfilter(struct pms *dev, short filter)
 410{
 411        if (dev->decoder == PHILIPS2)
 412                pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5);
 413        else if (dev->decoder == PHILIPS1)
 414                pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5);
 415}
 416
 417static void pms_vfilter(struct pms *dev, short filter)
 418{
 419        if (dev->decoder == PHILIPS2)
 420                pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5);
 421        else if (dev->decoder == PHILIPS1)
 422                pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5);
 423}
 424
 425static void pms_killcolour(struct pms *dev, short colour)
 426{
 427        if (dev->decoder == PHILIPS2) {
 428                pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3);
 429                pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3);
 430        } else if (dev->decoder == PHILIPS1) {
 431                pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3);
 432                pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3);
 433        }
 434}
 435
 436static void pms_chromagain(struct pms *dev, short chroma)
 437{
 438        if (dev->decoder == PHILIPS2)
 439                pms_i2c_write(dev, 0x8a, 0x11, chroma);
 440        else if (dev->decoder == PHILIPS1)
 441                pms_i2c_write(dev, 0x42, 0x11, chroma);
 442}
 443
 444
 445static void pms_spacialcompl(struct pms *dev, short data)
 446{
 447        mvv_write(dev, 0x3b, data);
 448}
 449
 450static void pms_spacialcomph(struct pms *dev, short data)
 451{
 452        mvv_write(dev, 0x3a, data);
 453}
 454
 455static void pms_vstart(struct pms *dev, short start)
 456{
 457        mvv_write(dev, 0x16, start);
 458        mvv_write(dev, 0x17, (start >> 8) & 0x01);
 459}
 460
 461#endif
 462
 463static void pms_secamcross(struct pms *dev, short cross)
 464{
 465        if (dev->decoder == PHILIPS2)
 466                pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5);
 467        else if (dev->decoder == PHILIPS1)
 468                pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5);
 469}
 470
 471
 472static void pms_swsense(struct pms *dev, short sense)
 473{
 474        if (dev->decoder == PHILIPS2) {
 475                pms_i2c_write(dev, 0x8a, 0x0a, sense);
 476                pms_i2c_write(dev, 0x8a, 0x0b, sense);
 477        } else if (dev->decoder == PHILIPS1) {
 478                pms_i2c_write(dev, 0x42, 0x0a, sense);
 479                pms_i2c_write(dev, 0x42, 0x0b, sense);
 480        }
 481}
 482
 483
 484static void pms_framerate(struct pms *dev, short frr)
 485{
 486        int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25;
 487
 488        if (frr == 0)
 489                return;
 490        fps = fps/frr;
 491        mvv_write(dev, 0x14, 0x80 | fps);
 492        mvv_write(dev, 0x15, 1);
 493}
 494
 495static void pms_vert(struct pms *dev, u8 deciden, u8 decinum)
 496{
 497        mvv_write(dev, 0x1c, deciden);  /* Denominator */
 498        mvv_write(dev, 0x1d, decinum);  /* Numerator */
 499}
 500
 501/*
 502 *      Turn 16bit ratios into best small ratio the chipset can grok
 503 */
 504
 505static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden)
 506{
 507        /* Knock it down by / 5 once */
 508        if (decinum % 5 == 0) {
 509                deciden /= 5;
 510                decinum /= 5;
 511        }
 512        /*
 513         *      3's
 514         */
 515        while (decinum % 3 == 0 && deciden % 3 == 0) {
 516                deciden /= 3;
 517                decinum /= 3;
 518        }
 519        /*
 520         *      2's
 521         */
 522        while (decinum % 2 == 0 && deciden % 2 == 0) {
 523                decinum /= 2;
 524                deciden /= 2;
 525        }
 526        /*
 527         *      Fudgyify
 528         */
 529        while (deciden > 32) {
 530                deciden /= 2;
 531                decinum = (decinum + 1) / 2;
 532        }
 533        if (deciden == 32)
 534                deciden--;
 535        pms_vert(dev, deciden, decinum);
 536}
 537
 538static void pms_horzdeci(struct pms *dev, short decinum, short deciden)
 539{
 540        if (decinum <= 512) {
 541                if (decinum % 5 == 0) {
 542                        decinum /= 5;
 543                        deciden /= 5;
 544                }
 545        } else {
 546                decinum = 512;
 547                deciden = 640;  /* 768 would be ideal */
 548        }
 549
 550        while (((decinum | deciden) & 1) == 0) {
 551                decinum >>= 1;
 552                deciden >>= 1;
 553        }
 554        while (deciden > 32) {
 555                deciden >>= 1;
 556                decinum = (decinum + 1) >> 1;
 557        }
 558        if (deciden == 32)
 559                deciden--;
 560
 561        mvv_write(dev, 0x24, 0x80 | deciden);
 562        mvv_write(dev, 0x25, decinum);
 563}
 564
 565static void pms_resolution(struct pms *dev, short width, short height)
 566{
 567        int fg_height;
 568
 569        fg_height = height;
 570        if (fg_height > 280)
 571                fg_height = 280;
 572
 573        mvv_write(dev, 0x18, fg_height);
 574        mvv_write(dev, 0x19, fg_height >> 8);
 575
 576        if (dev->std & V4L2_STD_525_60) {
 577                mvv_write(dev, 0x1a, 0xfc);
 578                mvv_write(dev, 0x1b, 0x00);
 579                if (height > fg_height)
 580                        pms_vertdeci(dev, 240, 240);
 581                else
 582                        pms_vertdeci(dev, fg_height, 240);
 583        } else {
 584                mvv_write(dev, 0x1a, 0x1a);
 585                mvv_write(dev, 0x1b, 0x01);
 586                if (fg_height > 256)
 587                        pms_vertdeci(dev, 270, 270);
 588                else
 589                        pms_vertdeci(dev, fg_height, 270);
 590        }
 591        mvv_write(dev, 0x12, 0);
 592        mvv_write(dev, 0x13, MVVMEMORYWIDTH);
 593        mvv_write(dev, 0x42, 0x00);
 594        mvv_write(dev, 0x43, 0x00);
 595        mvv_write(dev, 0x44, MVVMEMORYWIDTH);
 596
 597        mvv_write(dev, 0x22, width + 8);
 598        mvv_write(dev, 0x23, (width + 8) >> 8);
 599
 600        if (dev->std & V4L2_STD_525_60)
 601                pms_horzdeci(dev, width, 640);
 602        else
 603                pms_horzdeci(dev, width + 8, 768);
 604
 605        mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe);
 606        mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01);
 607        mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd);
 608        mvv_write(dev, 0x32, 0x00);
 609        mvv_write(dev, 0x33, MVVMEMORYWIDTH);
 610}
 611
 612
 613/*
 614 *      Set Input
 615 */
 616
 617static void pms_vcrinput(struct pms *dev, short input)
 618{
 619        if (dev->decoder == PHILIPS2)
 620                pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7);
 621        else if (dev->decoder == PHILIPS1)
 622                pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7);
 623}
 624
 625
 626static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
 627{
 628        int y;
 629        int dw = 2 * dev->width;
 630        char tmp[dw + 32]; /* using a temp buffer is faster than direct  */
 631        int cnt = 0;
 632        int len = 0;
 633        unsigned char r8 = 0x5;  /* value for reg8  */
 634
 635        if (rgb555)
 636                r8 |= 0x20; /* else use untranslated rgb = 565 */
 637        mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */
 638
 639/*      printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
 640
 641        for (y = 0; y < dev->height; y++) {
 642                writeb(0, dev->mem);  /* synchronisiert neue Zeile */
 643
 644                /*
 645                 *      This is in truth a fifo, be very careful as if you
 646                 *      forgot this odd things will occur 8)
 647                 */
 648
 649                memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word   */
 650                cnt -= dev->height;
 651                while (cnt <= 0) {
 652                        /*
 653                         *      Don't copy too far
 654                         */
 655                        int dt = dw;
 656                        if (dt + len > count)
 657                                dt = count - len;
 658                        cnt += dev->height;
 659                        if (copy_to_user(buf, tmp + 32, dt))
 660                                return len ? len : -EFAULT;
 661                        buf += dt;
 662                        len += dt;
 663                }
 664        }
 665        return len;
 666}
 667
 668
 669/*
 670 *      Video4linux interfacing
 671 */
 672
 673static int pms_querycap(struct file *file, void  *priv,
 674                                        struct v4l2_capability *vcap)
 675{
 676        struct pms *dev = video_drvdata(file);
 677
 678        strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver));
 679        strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card));
 680        strlcpy(vcap->bus_info, "ISA", sizeof(vcap->bus_info));
 681        vcap->version = KERNEL_VERSION(0, 0, 3);
 682        vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
 683        return 0;
 684}
 685
 686static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
 687{
 688        static const char *inputs[4] = {
 689                "Composite",
 690                "S-Video",
 691                "Composite (VCR)",
 692                "S-Video (VCR)"
 693        };
 694
 695        if (vin->index > 3)
 696                return -EINVAL;
 697        strlcpy(vin->name, inputs[vin->index], sizeof(vin->name));
 698        vin->type = V4L2_INPUT_TYPE_CAMERA;
 699        vin->audioset = 0;
 700        vin->tuner = 0;
 701        vin->std = V4L2_STD_ALL;
 702        vin->status = 0;
 703        return 0;
 704}
 705
 706static int pms_g_input(struct file *file, void *fh, unsigned int *inp)
 707{
 708        struct pms *dev = video_drvdata(file);
 709
 710        *inp = dev->input;
 711        return 0;
 712}
 713
 714static int pms_s_input(struct file *file, void *fh, unsigned int inp)
 715{
 716        struct pms *dev = video_drvdata(file);
 717
 718        if (inp > 3)
 719                return -EINVAL;
 720
 721        mutex_lock(&dev->lock);
 722        dev->input = inp;
 723        pms_videosource(dev, inp & 1);
 724        pms_vcrinput(dev, inp >> 1);
 725        mutex_unlock(&dev->lock);
 726        return 0;
 727}
 728
 729static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std)
 730{
 731        struct pms *dev = video_drvdata(file);
 732
 733        *std = dev->std;
 734        return 0;
 735}
 736
 737static int pms_s_std(struct file *file, void *fh, v4l2_std_id *std)
 738{
 739        struct pms *dev = video_drvdata(file);
 740        int ret = 0;
 741
 742        dev->std = *std;
 743        mutex_lock(&dev->lock);
 744        if (dev->std & V4L2_STD_NTSC) {
 745                pms_framerate(dev, 30);
 746                pms_secamcross(dev, 0);
 747                pms_format(dev, 1);
 748        } else if (dev->std & V4L2_STD_PAL) {
 749                pms_framerate(dev, 25);
 750                pms_secamcross(dev, 0);
 751                pms_format(dev, 2);
 752        } else if (dev->std & V4L2_STD_SECAM) {
 753                pms_framerate(dev, 25);
 754                pms_secamcross(dev, 1);
 755                pms_format(dev, 2);
 756        } else {
 757                ret = -EINVAL;
 758        }
 759        /*
 760        switch (v->mode) {
 761        case VIDEO_MODE_AUTO:
 762                pms_framerate(dev, 25);
 763                pms_secamcross(dev, 0);
 764                pms_format(dev, 0);
 765                break;
 766        }*/
 767        mutex_unlock(&dev->lock);
 768        return 0;
 769}
 770
 771static int pms_queryctrl(struct file *file, void *priv,
 772                                        struct v4l2_queryctrl *qc)
 773{
 774        switch (qc->id) {
 775        case V4L2_CID_BRIGHTNESS:
 776                return v4l2_ctrl_query_fill(qc, 0, 255, 1, 139);
 777        case V4L2_CID_CONTRAST:
 778                return v4l2_ctrl_query_fill(qc, 0, 255, 1, 70);
 779        case V4L2_CID_SATURATION:
 780                return v4l2_ctrl_query_fill(qc, 0, 255, 1, 64);
 781        case V4L2_CID_HUE:
 782                return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0);
 783        }
 784        return -EINVAL;
 785}
 786
 787static int pms_g_ctrl(struct file *file, void *priv,
 788                                        struct v4l2_control *ctrl)
 789{
 790        struct pms *dev = video_drvdata(file);
 791        int ret = 0;
 792
 793        switch (ctrl->id) {
 794        case V4L2_CID_BRIGHTNESS:
 795                ctrl->value = dev->brightness;
 796                break;
 797        case V4L2_CID_CONTRAST:
 798                ctrl->value = dev->contrast;
 799                break;
 800        case V4L2_CID_SATURATION:
 801                ctrl->value = dev->saturation;
 802                break;
 803        case V4L2_CID_HUE:
 804                ctrl->value = dev->hue;
 805                break;
 806        default:
 807                ret = -EINVAL;
 808                break;
 809        }
 810        return ret;
 811}
 812
 813static int pms_s_ctrl(struct file *file, void *priv,
 814                                        struct v4l2_control *ctrl)
 815{
 816        struct pms *dev = video_drvdata(file);
 817        int ret = 0;
 818
 819        mutex_lock(&dev->lock);
 820        switch (ctrl->id) {
 821        case V4L2_CID_BRIGHTNESS:
 822                dev->brightness = ctrl->value;
 823                pms_brightness(dev, dev->brightness);
 824                break;
 825        case V4L2_CID_CONTRAST:
 826                dev->contrast = ctrl->value;
 827                pms_contrast(dev, dev->contrast);
 828                break;
 829        case V4L2_CID_SATURATION:
 830                dev->saturation = ctrl->value;
 831                pms_saturation(dev, dev->saturation);
 832                break;
 833        case V4L2_CID_HUE:
 834                dev->hue = ctrl->value;
 835                pms_hue(dev, dev->hue);
 836                break;
 837        default:
 838                ret = -EINVAL;
 839                break;
 840        }
 841        mutex_unlock(&dev->lock);
 842        return ret;
 843}
 844
 845static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 846{
 847        struct pms *dev = video_drvdata(file);
 848        struct v4l2_pix_format *pix = &fmt->fmt.pix;
 849
 850        pix->width = dev->width;
 851        pix->height = dev->height;
 852        pix->pixelformat = dev->width == 15 ?
 853                            V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565;
 854        pix->field = V4L2_FIELD_NONE;
 855        pix->bytesperline = 2 * dev->width;
 856        pix->sizeimage = 2 * dev->width * dev->height;
 857        /* Just a guess */
 858        pix->colorspace = V4L2_COLORSPACE_SRGB;
 859        return 0;
 860}
 861
 862static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 863{
 864        struct v4l2_pix_format *pix = &fmt->fmt.pix;
 865
 866        if (pix->height < 16 || pix->height > 480)
 867                return -EINVAL;
 868        if (pix->width < 16 || pix->width > 640)
 869                return -EINVAL;
 870        if (pix->pixelformat != V4L2_PIX_FMT_RGB555 &&
 871            pix->pixelformat != V4L2_PIX_FMT_RGB565)
 872                return -EINVAL;
 873        pix->field = V4L2_FIELD_NONE;
 874        pix->bytesperline = 2 * pix->width;
 875        pix->sizeimage = 2 * pix->width * pix->height;
 876        /* Just a guess */
 877        pix->colorspace = V4L2_COLORSPACE_SRGB;
 878        return 0;
 879}
 880
 881static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 882{
 883        struct pms *dev = video_drvdata(file);
 884        struct v4l2_pix_format *pix = &fmt->fmt.pix;
 885        int ret = pms_try_fmt_vid_cap(file, fh, fmt);
 886
 887        if (ret)
 888                return ret;
 889        mutex_lock(&dev->lock);
 890        dev->width = pix->width;
 891        dev->height = pix->height;
 892        dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16;
 893        pms_resolution(dev, dev->width, dev->height);
 894        /* Ok we figured out what to use from our wide choice */
 895        mutex_unlock(&dev->lock);
 896        return 0;
 897}
 898
 899static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
 900{
 901        static struct v4l2_fmtdesc formats[] = {
 902                { 0, 0, 0,
 903                  "RGB 5:5:5", V4L2_PIX_FMT_RGB555,
 904                  { 0, 0, 0, 0 }
 905                },
 906                { 0, 0, 0,
 907                  "RGB 5:6:5", V4L2_PIX_FMT_RGB565,
 908                  { 0, 0, 0, 0 }
 909                },
 910        };
 911        enum v4l2_buf_type type = fmt->type;
 912
 913        if (fmt->index > 1)
 914                return -EINVAL;
 915
 916        *fmt = formats[fmt->index];
 917        fmt->type = type;
 918        return 0;
 919}
 920
 921static ssize_t pms_read(struct file *file, char __user *buf,
 922                    size_t count, loff_t *ppos)
 923{
 924        struct pms *dev = video_drvdata(file);
 925        int len;
 926
 927        mutex_lock(&dev->lock);
 928        len = pms_capture(dev, buf, (dev->depth == 15), count);
 929        mutex_unlock(&dev->lock);
 930        return len;
 931}
 932
 933static const struct v4l2_file_operations pms_fops = {
 934        .owner          = THIS_MODULE,
 935        .unlocked_ioctl = video_ioctl2,
 936        .read           = pms_read,
 937};
 938
 939static const struct v4l2_ioctl_ops pms_ioctl_ops = {
 940        .vidioc_querycap                    = pms_querycap,
 941        .vidioc_g_input                     = pms_g_input,
 942        .vidioc_s_input                     = pms_s_input,
 943        .vidioc_enum_input                  = pms_enum_input,
 944        .vidioc_g_std                       = pms_g_std,
 945        .vidioc_s_std                       = pms_s_std,
 946        .vidioc_queryctrl                   = pms_queryctrl,
 947        .vidioc_g_ctrl                      = pms_g_ctrl,
 948        .vidioc_s_ctrl                      = pms_s_ctrl,
 949        .vidioc_enum_fmt_vid_cap            = pms_enum_fmt_vid_cap,
 950        .vidioc_g_fmt_vid_cap               = pms_g_fmt_vid_cap,
 951        .vidioc_s_fmt_vid_cap               = pms_s_fmt_vid_cap,
 952        .vidioc_try_fmt_vid_cap             = pms_try_fmt_vid_cap,
 953};
 954
 955/*
 956 *      Probe for and initialise the Mediavision PMS
 957 */
 958
 959static int init_mediavision(struct pms *dev)
 960{
 961        int id;
 962        int idec, decst;
 963        int i;
 964        static const unsigned char i2c_defs[] = {
 965                0x4c, 0x30, 0x00, 0xe8,
 966                0xb6, 0xe2, 0x00, 0x00,
 967                0xff, 0xff, 0x00, 0x00,
 968                0x00, 0x00, 0x78, 0x98,
 969                0x00, 0x00, 0x00, 0x00,
 970                0x34, 0x0a, 0xf4, 0xce,
 971                0xe4
 972        };
 973
 974        dev->mem = ioremap(mem_base, 0x800);
 975        if (!dev->mem)
 976                return -ENOMEM;
 977
 978        if (!request_region(0x9a01, 1, "Mediavision PMS config")) {
 979                printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n");
 980                iounmap(dev->mem);
 981                return -EBUSY;
 982        }
 983        if (!request_region(dev->io, 3, "Mediavision PMS")) {
 984                printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io);
 985                release_region(0x9a01, 1);
 986                iounmap(dev->mem);
 987                return -EBUSY;
 988        }
 989        outb(0xb8, 0x9a01);             /* Unlock */
 990        outb(dev->io >> 4, 0x9a01);     /* Set IO port */
 991
 992
 993        id = mvv_read(dev, 3);
 994        decst = pms_i2c_stat(dev, 0x43);
 995
 996        if (decst != -1)
 997                idec = 2;
 998        else if (pms_i2c_stat(dev, 0xb9) != -1)
 999                idec = 3;
1000        else if (pms_i2c_stat(dev, 0x8b) != -1)
1001                idec = 1;
1002        else
1003                idec = 0;
1004
1005        printk(KERN_INFO "PMS type is %d\n", idec);
1006        if (idec == 0) {
1007                release_region(dev->io, 3);
1008                release_region(0x9a01, 1);
1009                iounmap(dev->mem);
1010                return -ENODEV;
1011        }
1012
1013        /*
1014         *      Ok we have a PMS of some sort
1015         */
1016
1017        mvv_write(dev, 0x04, mem_base >> 12);   /* Set the memory area */
1018
1019        /* Ok now load the defaults */
1020
1021        for (i = 0; i < 0x19; i++) {
1022                if (i2c_defs[i] == 0xff)
1023                        pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00);
1024                else
1025                        pms_i2c_write(dev, 0x8a, i, i2c_defs[i]);
1026        }
1027
1028        pms_i2c_write(dev, 0xb8, 0x00, 0x12);
1029        pms_i2c_write(dev, 0xb8, 0x04, 0x00);
1030        pms_i2c_write(dev, 0xb8, 0x07, 0x00);
1031        pms_i2c_write(dev, 0xb8, 0x08, 0x00);
1032        pms_i2c_write(dev, 0xb8, 0x09, 0xff);
1033        pms_i2c_write(dev, 0xb8, 0x0a, 0x00);
1034        pms_i2c_write(dev, 0xb8, 0x0b, 0x10);
1035        pms_i2c_write(dev, 0xb8, 0x10, 0x03);
1036
1037        mvv_write(dev, 0x01, 0x00);
1038        mvv_write(dev, 0x05, 0xa0);
1039        mvv_write(dev, 0x08, 0x25);
1040        mvv_write(dev, 0x09, 0x00);
1041        mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH);
1042
1043        mvv_write(dev, 0x10, 0x02);
1044        mvv_write(dev, 0x1e, 0x0c);
1045        mvv_write(dev, 0x1f, 0x03);
1046        mvv_write(dev, 0x26, 0x06);
1047
1048        mvv_write(dev, 0x2b, 0x00);
1049        mvv_write(dev, 0x2c, 0x20);
1050        mvv_write(dev, 0x2d, 0x00);
1051        mvv_write(dev, 0x2f, 0x70);
1052        mvv_write(dev, 0x32, 0x00);
1053        mvv_write(dev, 0x33, MVVMEMORYWIDTH);
1054        mvv_write(dev, 0x34, 0x00);
1055        mvv_write(dev, 0x35, 0x00);
1056        mvv_write(dev, 0x3a, 0x80);
1057        mvv_write(dev, 0x3b, 0x10);
1058        mvv_write(dev, 0x20, 0x00);
1059        mvv_write(dev, 0x21, 0x00);
1060        mvv_write(dev, 0x30, 0x22);
1061        return 0;
1062}
1063
1064/*
1065 *      Initialization and module stuff
1066 */
1067
1068#ifndef MODULE
1069static int enable;
1070module_param(enable, int, 0);
1071#endif
1072
1073static int __init pms_init(void)
1074{
1075        struct pms *dev = &pms_card;
1076        struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
1077        int res;
1078
1079        strlcpy(v4l2_dev->name, "pms", sizeof(v4l2_dev->name));
1080
1081        v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.03\n");
1082
1083#ifndef MODULE
1084        if (!enable) {
1085                v4l2_err(v4l2_dev,
1086                        "PMS: not enabled, use pms.enable=1 to probe\n");
1087                return -ENODEV;
1088        }
1089#endif
1090
1091        dev->decoder = PHILIPS2;
1092        dev->io = io_port;
1093        dev->data = io_port + 1;
1094
1095        if (init_mediavision(dev)) {
1096                v4l2_err(v4l2_dev, "Board not found.\n");
1097                return -ENODEV;
1098        }
1099
1100        res = v4l2_device_register(NULL, v4l2_dev);
1101        if (res < 0) {
1102                v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
1103                return res;
1104        }
1105
1106        strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
1107        dev->vdev.v4l2_dev = v4l2_dev;
1108        dev->vdev.fops = &pms_fops;
1109        dev->vdev.ioctl_ops = &pms_ioctl_ops;
1110        dev->vdev.release = video_device_release_empty;
1111        video_set_drvdata(&dev->vdev, dev);
1112        mutex_init(&dev->lock);
1113        dev->std = V4L2_STD_NTSC_M;
1114        dev->height = 240;
1115        dev->width = 320;
1116        dev->depth = 15;
1117        dev->brightness = 139;
1118        dev->contrast = 70;
1119        dev->hue = 0;
1120        dev->saturation = 64;
1121        pms_swsense(dev, 75);
1122        pms_resolution(dev, 320, 240);
1123        pms_videosource(dev, 0);
1124        pms_vcrinput(dev, 0);
1125        if (video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
1126                v4l2_device_unregister(&dev->v4l2_dev);
1127                release_region(dev->io, 3);
1128                release_region(0x9a01, 1);
1129                iounmap(dev->mem);
1130                return -EINVAL;
1131        }
1132        return 0;
1133}
1134
1135static void __exit pms_exit(void)
1136{
1137        struct pms *dev = &pms_card;
1138
1139        video_unregister_device(&dev->vdev);
1140        release_region(dev->io, 3);
1141        release_region(0x9a01, 1);
1142        iounmap(dev->mem);
1143}
1144
1145module_init(pms_init);
1146module_exit(pms_exit);
1147