linux/drivers/media/video/saa7114.c
<<
>>
Prefs
   1/*
   2 * saa7114 - Philips SAA7114H video decoder driver version 0.0.1
   3 *
   4 * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
   5 *
   6 * Based on saa7111 driver by Dave Perks
   7 *
   8 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
   9 *
  10 * Slight changes for video timing and attachment output by
  11 * Wolfgang Scherr <scherr@net4you.net>
  12 *
  13 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
  14 *    - moved over to linux>=2.4.x i2c protocol (1/1/2003)
  15 *
  16 * This program is free software; you can redistribute it and/or modify
  17 * it under the terms of the GNU General Public License as published by
  18 * the Free Software Foundation; either version 2 of the License, or
  19 * (at your option) any later version.
  20 *
  21 * This program is distributed in the hope that it will be useful,
  22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24 * GNU General Public License for more details.
  25 *
  26 * You should have received a copy of the GNU General Public License
  27 * along with this program; if not, write to the Free Software
  28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29 */
  30
  31#include <linux/module.h>
  32#include <linux/types.h>
  33#include <linux/ioctl.h>
  34#include <asm/uaccess.h>
  35#include <linux/i2c.h>
  36#include <linux/i2c-id.h>
  37#include <linux/videodev.h>
  38#include <linux/video_decoder.h>
  39#include <media/v4l2-common.h>
  40#include <media/v4l2-i2c-drv-legacy.h>
  41
  42MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
  43MODULE_AUTHOR("Maxim Yevtyushkin");
  44MODULE_LICENSE("GPL");
  45
  46static int debug;
  47module_param(debug, int, 0);
  48MODULE_PARM_DESC(debug, "Debug level (0-1)");
  49
  50/* ----------------------------------------------------------------------- */
  51
  52struct saa7114 {
  53        unsigned char reg[0xf0 * 2];
  54
  55        int norm;
  56        int input;
  57        int enable;
  58        int bright;
  59        int contrast;
  60        int hue;
  61        int sat;
  62        int playback;
  63};
  64
  65#define   I2C_DELAY   10
  66
  67
  68//#define SAA_7114_NTSC_HSYNC_START       (-3)
  69//#define SAA_7114_NTSC_HSYNC_STOP        (-18)
  70
  71#define SAA_7114_NTSC_HSYNC_START  (-17)
  72#define SAA_7114_NTSC_HSYNC_STOP   (-32)
  73
  74//#define SAA_7114_NTSC_HOFFSET           (5)
  75#define SAA_7114_NTSC_HOFFSET           (6)
  76#define SAA_7114_NTSC_VOFFSET           (10)
  77#define SAA_7114_NTSC_WIDTH             (720)
  78#define SAA_7114_NTSC_HEIGHT            (250)
  79
  80#define SAA_7114_SECAM_HSYNC_START      (-17)
  81#define SAA_7114_SECAM_HSYNC_STOP       (-32)
  82
  83#define SAA_7114_SECAM_HOFFSET          (2)
  84#define SAA_7114_SECAM_VOFFSET          (10)
  85#define SAA_7114_SECAM_WIDTH            (720)
  86#define SAA_7114_SECAM_HEIGHT           (300)
  87
  88#define SAA_7114_PAL_HSYNC_START        (-17)
  89#define SAA_7114_PAL_HSYNC_STOP         (-32)
  90
  91#define SAA_7114_PAL_HOFFSET            (2)
  92#define SAA_7114_PAL_VOFFSET            (10)
  93#define SAA_7114_PAL_WIDTH              (720)
  94#define SAA_7114_PAL_HEIGHT             (300)
  95
  96
  97
  98#define SAA_7114_VERTICAL_CHROMA_OFFSET         0       //0x50504040
  99#define SAA_7114_VERTICAL_LUMA_OFFSET           0
 100
 101#define REG_ADDR(x) (((x) << 1) + 1)
 102#define LOBYTE(x) ((unsigned char)((x) & 0xff))
 103#define HIBYTE(x) ((unsigned char)(((x) >> 8) & 0xff))
 104#define LOWORD(x) ((unsigned short int)((x) & 0xffff))
 105#define HIWORD(x) ((unsigned short int)(((x) >> 16) & 0xffff))
 106
 107
 108/* ----------------------------------------------------------------------- */
 109
 110static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value)
 111{
 112        return i2c_smbus_write_byte_data(client, reg, value);
 113}
 114
 115static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
 116{
 117        int ret = -1;
 118        u8 reg;
 119
 120        /* the saa7114 has an autoincrement function, use it if
 121         * the adapter understands raw I2C */
 122        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 123                /* do raw I2C, not smbus compatible */
 124                u8 block_data[32];
 125                int block_len;
 126
 127                while (len >= 2) {
 128                        block_len = 0;
 129                        block_data[block_len++] = reg = data[0];
 130                        do {
 131                                block_data[block_len++] = data[1];
 132                                reg++;
 133                                len -= 2;
 134                                data += 2;
 135                        } while (len >= 2 && data[0] == reg && block_len < 32);
 136                        ret = i2c_master_send(client, block_data, block_len);
 137                        if (ret < 0)
 138                                break;
 139                }
 140        } else {
 141                /* do some slow I2C emulation kind of thing */
 142                while (len >= 2) {
 143                        reg = *data++;
 144                        ret = saa7114_write(client, reg, *data++);
 145                        if (ret < 0)
 146                                break;
 147                        len -= 2;
 148                }
 149        }
 150
 151        return ret;
 152}
 153
 154static inline int saa7114_read(struct i2c_client *client, u8 reg)
 155{
 156        return i2c_smbus_read_byte_data(client, reg);
 157}
 158
 159/* ----------------------------------------------------------------------- */
 160
 161// initially set NTSC, composite
 162
 163
 164static const unsigned char init[] = {
 165        0x00, 0x00,             /* 00 - ID byte , chip version,
 166                                 * read only */
 167        0x01, 0x08,             /* 01 - X,X,X,X, IDEL3 to IDEL0 -
 168                                 * horizontal increment delay,
 169                                 * recommended position */
 170        0x02, 0x00,             /* 02 - FUSE=3, GUDL=2, MODE=0 ;
 171                                 * input control */
 172        0x03, 0x10,             /* 03 - HLNRS=0, VBSL=1, WPOFF=0,
 173                                 * HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
 174        0x04, 0x90,             /* 04 - GAI1=256 */
 175        0x05, 0x90,             /* 05 - GAI2=256 */
 176        0x06, SAA_7114_NTSC_HSYNC_START,        /* 06 - HSB: hsync start,
 177                                 * depends on the video standard */
 178        0x07, SAA_7114_NTSC_HSYNC_STOP, /* 07 - HSS: hsync stop, depends
 179                                 *on the video standard */
 180        0x08, 0xb8,             /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1,
 181                                 * HPLL: free running in playback, locked
 182                                 * in capture, VNOI=0 */
 183        0x09, 0x80,             /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0,
 184                                 * UPTCV=0, APER=1; depends from input */
 185        0x0a, 0x80,             /* 0a - BRIG=128 */
 186        0x0b, 0x44,             /* 0b - CONT=1.109 */
 187        0x0c, 0x40,             /* 0c - SATN=1.0 */
 188        0x0d, 0x00,             /* 0d - HUE=0 */
 189        0x0e, 0x84,             /* 0e - CDTO, CSTD2 to 0, DCVF, FCTC,
 190                                 * CCOMB; depends from video standard */
 191        0x0f, 0x24,             /* 0f - ACGC,CGAIN6 to CGAIN0; depends
 192                                 * from video standard */
 193        0x10, 0x03,             /* 10 - OFFU1 to 0, OFFV1 to 0, CHBW,
 194                                 * LCBW2 to 0 */
 195        0x11, 0x59,             /* 11 - COLO, RTP1, HEDL1 to 0, RTP0,
 196                                 * YDEL2 to 0 */
 197        0x12, 0xc9,             /* 12 - RT signal control RTSE13 to 10
 198                                 * and 03 to 00 */
 199        0x13, 0x80,             /* 13 - RT/X port output control  */
 200        0x14, 0x00,             /* 14 - analog, ADC, compatibility control */
 201        0x15, 0x00,             /* 15 - VGATE start FID change  */
 202        0x16, 0xfe,             /* 16 - VGATE stop */
 203        0x17, 0x00,             /* 17 - Misc., VGATE MSBs */
 204        0x18, 0x40,             /* RAWG */
 205        0x19, 0x80,             /* RAWO */
 206        0x1a, 0x00,
 207        0x1b, 0x00,
 208        0x1c, 0x00,
 209        0x1d, 0x00,
 210        0x1e, 0x00,
 211        0x1f, 0x00,             /* status byte, read only */
 212        0x20, 0x00,             /* video decoder reserved part */
 213        0x21, 0x00,
 214        0x22, 0x00,
 215        0x23, 0x00,
 216        0x24, 0x00,
 217        0x25, 0x00,
 218        0x26, 0x00,
 219        0x27, 0x00,
 220        0x28, 0x00,
 221        0x29, 0x00,
 222        0x2a, 0x00,
 223        0x2b, 0x00,
 224        0x2c, 0x00,
 225        0x2d, 0x00,
 226        0x2e, 0x00,
 227        0x2f, 0x00,
 228        0x30, 0xbc,             /* audio clock generator */
 229        0x31, 0xdf,
 230        0x32, 0x02,
 231        0x33, 0x00,
 232        0x34, 0xcd,
 233        0x35, 0xcc,
 234        0x36, 0x3a,
 235        0x37, 0x00,
 236        0x38, 0x03,
 237        0x39, 0x10,
 238        0x3a, 0x00,
 239        0x3b, 0x00,
 240        0x3c, 0x00,
 241        0x3d, 0x00,
 242        0x3e, 0x00,
 243        0x3f, 0x00,
 244        0x40, 0x00,             /* VBI data slicer */
 245        0x41, 0xff,
 246        0x42, 0xff,
 247        0x43, 0xff,
 248        0x44, 0xff,
 249        0x45, 0xff,
 250        0x46, 0xff,
 251        0x47, 0xff,
 252        0x48, 0xff,
 253        0x49, 0xff,
 254        0x4a, 0xff,
 255        0x4b, 0xff,
 256        0x4c, 0xff,
 257        0x4d, 0xff,
 258        0x4e, 0xff,
 259        0x4f, 0xff,
 260        0x50, 0xff,
 261        0x51, 0xff,
 262        0x52, 0xff,
 263        0x53, 0xff,
 264        0x54, 0xff,
 265        0x55, 0xff,
 266        0x56, 0xff,
 267        0x57, 0xff,
 268        0x58, 0x40,             // framing code
 269        0x59, 0x47,             // horizontal offset
 270        0x5a, 0x06,             // vertical offset
 271        0x5b, 0x83,             // field offset
 272        0x5c, 0x00,             // reserved
 273        0x5d, 0x3e,             // header and data
 274        0x5e, 0x00,             // sliced data
 275        0x5f, 0x00,             // reserved
 276        0x60, 0x00,             /* video decoder reserved part */
 277        0x61, 0x00,
 278        0x62, 0x00,
 279        0x63, 0x00,
 280        0x64, 0x00,
 281        0x65, 0x00,
 282        0x66, 0x00,
 283        0x67, 0x00,
 284        0x68, 0x00,
 285        0x69, 0x00,
 286        0x6a, 0x00,
 287        0x6b, 0x00,
 288        0x6c, 0x00,
 289        0x6d, 0x00,
 290        0x6e, 0x00,
 291        0x6f, 0x00,
 292        0x70, 0x00,             /* video decoder reserved part */
 293        0x71, 0x00,
 294        0x72, 0x00,
 295        0x73, 0x00,
 296        0x74, 0x00,
 297        0x75, 0x00,
 298        0x76, 0x00,
 299        0x77, 0x00,
 300        0x78, 0x00,
 301        0x79, 0x00,
 302        0x7a, 0x00,
 303        0x7b, 0x00,
 304        0x7c, 0x00,
 305        0x7d, 0x00,
 306        0x7e, 0x00,
 307        0x7f, 0x00,
 308        0x80, 0x00,             /* X-port, I-port and scaler */
 309        0x81, 0x00,
 310        0x82, 0x00,
 311        0x83, 0x00,
 312        0x84, 0xc5,
 313        0x85, 0x0d,             // hsync and vsync ?
 314        0x86, 0x40,
 315        0x87, 0x01,
 316        0x88, 0x00,
 317        0x89, 0x00,
 318        0x8a, 0x00,
 319        0x8b, 0x00,
 320        0x8c, 0x00,
 321        0x8d, 0x00,
 322        0x8e, 0x00,
 323        0x8f, 0x00,
 324        0x90, 0x03,             /* Task A definition           */
 325        0x91, 0x08,
 326        0x92, 0x00,
 327        0x93, 0x40,
 328        0x94, 0x00,             // window settings
 329        0x95, 0x00,
 330        0x96, 0x00,
 331        0x97, 0x00,
 332        0x98, 0x00,
 333        0x99, 0x00,
 334        0x9a, 0x00,
 335        0x9b, 0x00,
 336        0x9c, 0x00,
 337        0x9d, 0x00,
 338        0x9e, 0x00,
 339        0x9f, 0x00,
 340        0xa0, 0x01,             /* horizontal integer prescaling ratio */
 341        0xa1, 0x00,             /* horizontal prescaler accumulation
 342                                 * sequence length */
 343        0xa2, 0x00,             /* UV FIR filter, Y FIR filter, prescaler
 344                                 * DC gain */
 345        0xa3, 0x00,
 346        0xa4, 0x80,             // luminance brightness
 347        0xa5, 0x40,             // luminance gain
 348        0xa6, 0x40,             // chrominance saturation
 349        0xa7, 0x00,
 350        0xa8, 0x00,             // horizontal luminance scaling increment
 351        0xa9, 0x04,
 352        0xaa, 0x00,             // horizontal luminance phase offset
 353        0xab, 0x00,
 354        0xac, 0x00,             // horizontal chrominance scaling increment
 355        0xad, 0x02,
 356        0xae, 0x00,             // horizontal chrominance phase offset
 357        0xaf, 0x00,
 358        0xb0, 0x00,             // vertical luminance scaling increment
 359        0xb1, 0x04,
 360        0xb2, 0x00,             // vertical chrominance scaling increment
 361        0xb3, 0x04,
 362        0xb4, 0x00,
 363        0xb5, 0x00,
 364        0xb6, 0x00,
 365        0xb7, 0x00,
 366        0xb8, 0x00,
 367        0xb9, 0x00,
 368        0xba, 0x00,
 369        0xbb, 0x00,
 370        0xbc, 0x00,
 371        0xbd, 0x00,
 372        0xbe, 0x00,
 373        0xbf, 0x00,
 374        0xc0, 0x02,             // Task B definition
 375        0xc1, 0x08,
 376        0xc2, 0x00,
 377        0xc3, 0x40,
 378        0xc4, 0x00,             // window settings
 379        0xc5, 0x00,
 380        0xc6, 0x00,
 381        0xc7, 0x00,
 382        0xc8, 0x00,
 383        0xc9, 0x00,
 384        0xca, 0x00,
 385        0xcb, 0x00,
 386        0xcc, 0x00,
 387        0xcd, 0x00,
 388        0xce, 0x00,
 389        0xcf, 0x00,
 390        0xd0, 0x01,             // horizontal integer prescaling ratio
 391        0xd1, 0x00,             // horizontal prescaler accumulation sequence length
 392        0xd2, 0x00,             // UV FIR filter, Y FIR filter, prescaler DC gain
 393        0xd3, 0x00,
 394        0xd4, 0x80,             // luminance brightness
 395        0xd5, 0x40,             // luminance gain
 396        0xd6, 0x40,             // chrominance saturation
 397        0xd7, 0x00,
 398        0xd8, 0x00,             // horizontal luminance scaling increment
 399        0xd9, 0x04,
 400        0xda, 0x00,             // horizontal luminance phase offset
 401        0xdb, 0x00,
 402        0xdc, 0x00,             // horizontal chrominance scaling increment
 403        0xdd, 0x02,
 404        0xde, 0x00,             // horizontal chrominance phase offset
 405        0xdf, 0x00,
 406        0xe0, 0x00,             // vertical luminance scaling increment
 407        0xe1, 0x04,
 408        0xe2, 0x00,             // vertical chrominance scaling increment
 409        0xe3, 0x04,
 410        0xe4, 0x00,
 411        0xe5, 0x00,
 412        0xe6, 0x00,
 413        0xe7, 0x00,
 414        0xe8, 0x00,
 415        0xe9, 0x00,
 416        0xea, 0x00,
 417        0xeb, 0x00,
 418        0xec, 0x00,
 419        0xed, 0x00,
 420        0xee, 0x00,
 421        0xef, 0x00
 422};
 423
 424static int saa7114_command(struct i2c_client *client, unsigned cmd, void *arg)
 425{
 426        struct saa7114 *decoder = i2c_get_clientdata(client);
 427
 428        switch (cmd) {
 429        case 0:
 430                //dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client));
 431                //saa7114_write_block(client, init, sizeof(init));
 432                break;
 433
 434        case DECODER_DUMP:
 435        {
 436                int i;
 437
 438                if (!debug)
 439                        break;
 440                v4l_info(client, "decoder dump\n");
 441
 442                for (i = 0; i < 32; i += 16) {
 443                        int j;
 444
 445                        v4l_info(client, "%03x", i);
 446                        for (j = 0; j < 16; ++j) {
 447                                printk(KERN_CONT " %02x",
 448                                       saa7114_read(client, i + j));
 449                        }
 450                        printk(KERN_CONT "\n");
 451                }
 452                break;
 453        }
 454
 455        case DECODER_GET_CAPABILITIES:
 456        {
 457                struct video_decoder_capability *cap = arg;
 458
 459                v4l_dbg(1, debug, client, "get capabilities\n");
 460
 461                cap->flags = VIDEO_DECODER_PAL |
 462                             VIDEO_DECODER_NTSC |
 463                             VIDEO_DECODER_AUTO |
 464                             VIDEO_DECODER_CCIR;
 465                cap->inputs = 8;
 466                cap->outputs = 1;
 467                break;
 468        }
 469
 470        case DECODER_GET_STATUS:
 471        {
 472                int *iarg = arg;
 473                int status;
 474                int res;
 475
 476                status = saa7114_read(client, 0x1f);
 477
 478                v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
 479                res = 0;
 480                if ((status & (1 << 6)) == 0) {
 481                        res |= DECODER_STATUS_GOOD;
 482                }
 483                switch (decoder->norm) {
 484                case VIDEO_MODE_NTSC:
 485                        res |= DECODER_STATUS_NTSC;
 486                        break;
 487                case VIDEO_MODE_PAL:
 488                        res |= DECODER_STATUS_PAL;
 489                        break;
 490                case VIDEO_MODE_SECAM:
 491                        res |= DECODER_STATUS_SECAM;
 492                        break;
 493                default:
 494                case VIDEO_MODE_AUTO:
 495                        if ((status & (1 << 5)) != 0) {
 496                                res |= DECODER_STATUS_NTSC;
 497                        } else {
 498                                res |= DECODER_STATUS_PAL;
 499                        }
 500                        break;
 501                }
 502                if ((status & (1 << 0)) != 0) {
 503                        res |= DECODER_STATUS_COLOR;
 504                }
 505                *iarg = res;
 506                break;
 507        }
 508
 509        case DECODER_SET_NORM:
 510        {
 511                int *iarg = arg;
 512
 513                short int hoff = 0, voff = 0, w = 0, h = 0;
 514
 515                v4l_dbg(1, debug, client, "set norm\n");
 516
 517                switch (*iarg) {
 518                case VIDEO_MODE_NTSC:
 519                        v4l_dbg(1, debug, client, "NTSC\n");
 520                        decoder->reg[REG_ADDR(0x06)] =
 521                            SAA_7114_NTSC_HSYNC_START;
 522                        decoder->reg[REG_ADDR(0x07)] =
 523                            SAA_7114_NTSC_HSYNC_STOP;
 524
 525                        decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture
 526
 527                        decoder->reg[REG_ADDR(0x0e)] = 0x85;
 528                        decoder->reg[REG_ADDR(0x0f)] = 0x24;
 529
 530                        hoff = SAA_7114_NTSC_HOFFSET;
 531                        voff = SAA_7114_NTSC_VOFFSET;
 532                        w = SAA_7114_NTSC_WIDTH;
 533                        h = SAA_7114_NTSC_HEIGHT;
 534
 535                        break;
 536
 537                case VIDEO_MODE_PAL:
 538                        v4l_dbg(1, debug, client, "PAL\n");
 539                        decoder->reg[REG_ADDR(0x06)] =
 540                            SAA_7114_PAL_HSYNC_START;
 541                        decoder->reg[REG_ADDR(0x07)] =
 542                            SAA_7114_PAL_HSYNC_STOP;
 543
 544                        decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture
 545
 546                        decoder->reg[REG_ADDR(0x0e)] = 0x81;
 547                        decoder->reg[REG_ADDR(0x0f)] = 0x24;
 548
 549                        hoff = SAA_7114_PAL_HOFFSET;
 550                        voff = SAA_7114_PAL_VOFFSET;
 551                        w = SAA_7114_PAL_WIDTH;
 552                        h = SAA_7114_PAL_HEIGHT;
 553
 554                        break;
 555
 556                default:
 557                        v4l_dbg(1, debug, client, "Unknown video mode\n");
 558                        return -EINVAL;
 559                }
 560
 561
 562                decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff);    // hoffset low
 563                decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f;     // hoffset high
 564                decoder->reg[REG_ADDR(0x96)] = LOBYTE(w);       // width low
 565                decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f;        // width high
 566                decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff);    // voffset low
 567                decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f;     // voffset high
 568                decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2);   // height low
 569                decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f;    // height high
 570                decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w);       // out width low
 571                decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f;        // out width high
 572                decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h);       // out height low
 573                decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f;        // out height high
 574
 575                decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff);    // hoffset low
 576                decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f;     // hoffset high
 577                decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w);       // width low
 578                decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f;        // width high
 579                decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff);    // voffset low
 580                decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f;     // voffset high
 581                decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2);   // height low
 582                decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f;    // height high
 583                decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w);       // out width low
 584                decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f;        // out width high
 585                decoder->reg[REG_ADDR(0xce)] = LOBYTE(h);       // out height low
 586                decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f;        // out height high
 587
 588
 589                saa7114_write(client, 0x80, 0x06);      // i-port and scaler back end clock selection, task A&B off
 590                saa7114_write(client, 0x88, 0xd8);      // sw reset scaler
 591                saa7114_write(client, 0x88, 0xf8);      // sw reset scaler release
 592
 593                saa7114_write_block(client, decoder->reg + (0x06 << 1),
 594                                    3 << 1);
 595                saa7114_write_block(client, decoder->reg + (0x0e << 1),
 596                                    2 << 1);
 597                saa7114_write_block(client, decoder->reg + (0x5a << 1),
 598                                    2 << 1);
 599
 600                saa7114_write_block(client, decoder->reg + (0x94 << 1),
 601                                    (0x9f + 1 - 0x94) << 1);
 602                saa7114_write_block(client, decoder->reg + (0xc4 << 1),
 603                                    (0xcf + 1 - 0xc4) << 1);
 604
 605                saa7114_write(client, 0x88, 0xd8);      // sw reset scaler
 606                saa7114_write(client, 0x88, 0xf8);      // sw reset scaler release
 607                saa7114_write(client, 0x80, 0x36);      // i-port and scaler back end clock selection
 608
 609                decoder->norm = *iarg;
 610                break;
 611        }
 612
 613        case DECODER_SET_INPUT:
 614        {
 615                int *iarg = arg;
 616
 617                v4l_dbg(1, debug, client, "set input (%d)\n", *iarg);
 618                if (*iarg < 0 || *iarg > 7) {
 619                        return -EINVAL;
 620                }
 621
 622                if (decoder->input != *iarg) {
 623                        v4l_dbg(1, debug, client, "now setting %s input\n",
 624                                *iarg >= 6 ? "S-Video" : "Composite");
 625                        decoder->input = *iarg;
 626
 627                        /* select mode */
 628                        decoder->reg[REG_ADDR(0x02)] =
 629                            (decoder->
 630                             reg[REG_ADDR(0x02)] & 0xf0) | (decoder->
 631                                                            input <
 632                                                            6 ? 0x0 : 0x9);
 633                        saa7114_write(client, 0x02,
 634                                      decoder->reg[REG_ADDR(0x02)]);
 635
 636                        /* bypass chrominance trap for modes 6..9 */
 637                        decoder->reg[REG_ADDR(0x09)] =
 638                            (decoder->
 639                             reg[REG_ADDR(0x09)] & 0x7f) | (decoder->
 640                                                            input <
 641                                                            6 ? 0x0 :
 642                                                            0x80);
 643                        saa7114_write(client, 0x09,
 644                                      decoder->reg[REG_ADDR(0x09)]);
 645
 646                        decoder->reg[REG_ADDR(0x0e)] =
 647                            decoder->input <
 648                            6 ? decoder->
 649                            reg[REG_ADDR(0x0e)] | 1 : decoder->
 650                            reg[REG_ADDR(0x0e)] & ~1;
 651                        saa7114_write(client, 0x0e,
 652                                      decoder->reg[REG_ADDR(0x0e)]);
 653                }
 654                break;
 655        }
 656
 657        case DECODER_SET_OUTPUT:
 658        {
 659                int *iarg = arg;
 660
 661                v4l_dbg(1, debug, client, "set output\n");
 662
 663                /* not much choice of outputs */
 664                if (*iarg != 0) {
 665                        return -EINVAL;
 666                }
 667                break;
 668        }
 669
 670        case DECODER_ENABLE_OUTPUT:
 671        {
 672                int *iarg = arg;
 673                int enable = (*iarg != 0);
 674
 675                v4l_dbg(1, debug, client, "%s output\n",
 676                        enable ? "enable" : "disable");
 677
 678                decoder->playback = !enable;
 679
 680                if (decoder->enable != enable) {
 681                        decoder->enable = enable;
 682
 683                        /* RJ: If output should be disabled (for
 684                         * playing videos), we also need a open PLL.
 685                         * The input is set to 0 (where no input
 686                         * source is connected), although this
 687                         * is not necessary.
 688                         *
 689                         * If output should be enabled, we have to
 690                         * reverse the above.
 691                         */
 692
 693                        if (decoder->enable) {
 694                                decoder->reg[REG_ADDR(0x08)] = 0xb8;
 695                                decoder->reg[REG_ADDR(0x12)] = 0xc9;
 696                                decoder->reg[REG_ADDR(0x13)] = 0x80;
 697                                decoder->reg[REG_ADDR(0x87)] = 0x01;
 698                        } else {
 699                                decoder->reg[REG_ADDR(0x08)] = 0x7c;
 700                                decoder->reg[REG_ADDR(0x12)] = 0x00;
 701                                decoder->reg[REG_ADDR(0x13)] = 0x00;
 702                                decoder->reg[REG_ADDR(0x87)] = 0x00;
 703                        }
 704
 705                        saa7114_write_block(client,
 706                                            decoder->reg + (0x12 << 1),
 707                                            2 << 1);
 708                        saa7114_write(client, 0x08,
 709                                      decoder->reg[REG_ADDR(0x08)]);
 710                        saa7114_write(client, 0x87,
 711                                      decoder->reg[REG_ADDR(0x87)]);
 712                        saa7114_write(client, 0x88, 0xd8);      // sw reset scaler
 713                        saa7114_write(client, 0x88, 0xf8);      // sw reset scaler release
 714                        saa7114_write(client, 0x80, 0x36);
 715
 716                }
 717                break;
 718        }
 719
 720        case DECODER_SET_PICTURE:
 721        {
 722                struct video_picture *pic = arg;
 723
 724                v4l_dbg(1, debug, client,
 725                        "decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
 726                        pic->brightness, pic->contrast, pic->colour, pic->hue);
 727
 728                if (decoder->bright != pic->brightness) {
 729                        /* We want 0 to 255 we get 0-65535 */
 730                        decoder->bright = pic->brightness;
 731                        saa7114_write(client, 0x0a, decoder->bright >> 8);
 732                }
 733                if (decoder->contrast != pic->contrast) {
 734                        /* We want 0 to 127 we get 0-65535 */
 735                        decoder->contrast = pic->contrast;
 736                        saa7114_write(client, 0x0b,
 737                                      decoder->contrast >> 9);
 738                }
 739                if (decoder->sat != pic->colour) {
 740                        /* We want 0 to 127 we get 0-65535 */
 741                        decoder->sat = pic->colour;
 742                        saa7114_write(client, 0x0c, decoder->sat >> 9);
 743                }
 744                if (decoder->hue != pic->hue) {
 745                        /* We want -128 to 127 we get 0-65535 */
 746                        decoder->hue = pic->hue;
 747                        saa7114_write(client, 0x0d,
 748                                      (decoder->hue - 32768) >> 8);
 749                }
 750                break;
 751        }
 752
 753        default:
 754                return -EINVAL;
 755        }
 756
 757        return 0;
 758}
 759
 760/* ----------------------------------------------------------------------- */
 761
 762static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
 763
 764I2C_CLIENT_INSMOD;
 765
 766static int saa7114_probe(struct i2c_client *client,
 767                        const struct i2c_device_id *id)
 768{
 769        int i, err[30];
 770        short int hoff = SAA_7114_NTSC_HOFFSET;
 771        short int voff = SAA_7114_NTSC_VOFFSET;
 772        short int w = SAA_7114_NTSC_WIDTH;
 773        short int h = SAA_7114_NTSC_HEIGHT;
 774        struct saa7114 *decoder;
 775
 776        /* Check if the adapter supports the needed features */
 777        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 778                return -ENODEV;
 779
 780        v4l_info(client, "chip found @ 0x%x (%s)\n",
 781                        client->addr << 1, client->adapter->name);
 782
 783        decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL);
 784        if (decoder == NULL)
 785                return -ENOMEM;
 786        decoder->norm = VIDEO_MODE_NTSC;
 787        decoder->input = -1;
 788        decoder->enable = 1;
 789        decoder->bright = 32768;
 790        decoder->contrast = 32768;
 791        decoder->hue = 32768;
 792        decoder->sat = 32768;
 793        decoder->playback = 0;  // initially capture mode useda
 794        i2c_set_clientdata(client, decoder);
 795
 796        memcpy(decoder->reg, init, sizeof(init));
 797
 798        decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff);    // hoffset low
 799        decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f;     // hoffset high
 800        decoder->reg[REG_ADDR(0x96)] = LOBYTE(w);       // width low
 801        decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f;        // width high
 802        decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff);    // voffset low
 803        decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f;     // voffset high
 804        decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2);   // height low
 805        decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f;    // height high
 806        decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w);       // out width low
 807        decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f;        // out width high
 808        decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h);       // out height low
 809        decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f;        // out height high
 810
 811        decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff);    // hoffset low
 812        decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f;     // hoffset high
 813        decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w);       // width low
 814        decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f;        // width high
 815        decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff);    // voffset low
 816        decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f;     // voffset high
 817        decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2);   // height low
 818        decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f;    // height high
 819        decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w);       // out width low
 820        decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f;        // out width high
 821        decoder->reg[REG_ADDR(0xce)] = LOBYTE(h);       // out height low
 822        decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f;        // out height high
 823
 824        decoder->reg[REG_ADDR(0xb8)] =
 825            LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
 826        decoder->reg[REG_ADDR(0xb9)] =
 827            HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
 828        decoder->reg[REG_ADDR(0xba)] =
 829            LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
 830        decoder->reg[REG_ADDR(0xbb)] =
 831            HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
 832
 833        decoder->reg[REG_ADDR(0xbc)] =
 834            LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
 835        decoder->reg[REG_ADDR(0xbd)] =
 836            HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
 837        decoder->reg[REG_ADDR(0xbe)] =
 838            LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
 839        decoder->reg[REG_ADDR(0xbf)] =
 840            HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
 841
 842        decoder->reg[REG_ADDR(0xe8)] =
 843            LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
 844        decoder->reg[REG_ADDR(0xe9)] =
 845            HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
 846        decoder->reg[REG_ADDR(0xea)] =
 847            LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
 848        decoder->reg[REG_ADDR(0xeb)] =
 849            HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
 850
 851        decoder->reg[REG_ADDR(0xec)] =
 852            LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
 853        decoder->reg[REG_ADDR(0xed)] =
 854            HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
 855        decoder->reg[REG_ADDR(0xee)] =
 856            LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
 857        decoder->reg[REG_ADDR(0xef)] =
 858            HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
 859
 860
 861        decoder->reg[REG_ADDR(0x13)] = 0x80;    // RTC0 on
 862        decoder->reg[REG_ADDR(0x87)] = 0x01;    // I-Port
 863        decoder->reg[REG_ADDR(0x12)] = 0xc9;    // RTS0
 864
 865        decoder->reg[REG_ADDR(0x02)] = 0xc0;    // set composite1 input, aveasy
 866        decoder->reg[REG_ADDR(0x09)] = 0x00;    // chrominance trap
 867        decoder->reg[REG_ADDR(0x0e)] |= 1;      // combfilter on
 868
 869
 870        v4l_dbg(1, debug, client, "starting init\n");
 871
 872        err[0] =
 873            saa7114_write_block(client, decoder->reg + (0x20 << 1),
 874                                0x10 << 1);
 875        err[1] =
 876            saa7114_write_block(client, decoder->reg + (0x30 << 1),
 877                                0x10 << 1);
 878        err[2] =
 879            saa7114_write_block(client, decoder->reg + (0x63 << 1),
 880                                (0x7f + 1 - 0x63) << 1);
 881        err[3] =
 882            saa7114_write_block(client, decoder->reg + (0x89 << 1),
 883                                6 << 1);
 884        err[4] =
 885            saa7114_write_block(client, decoder->reg + (0xb8 << 1),
 886                                8 << 1);
 887        err[5] =
 888            saa7114_write_block(client, decoder->reg + (0xe8 << 1),
 889                                8 << 1);
 890
 891
 892        for (i = 0; i <= 5; i++) {
 893                if (err[i] < 0) {
 894                        v4l_dbg(1, debug, client,
 895                                "init error %d at stage %d, leaving attach.\n",
 896                                i, err[i]);
 897                        kfree(decoder);
 898                        return -EIO;
 899                }
 900        }
 901
 902        for (i = 6; i < 8; i++) {
 903                v4l_dbg(1, debug, client,
 904                        "reg[0x%02x] = 0x%02x (0x%02x)\n",
 905                        i, saa7114_read(client, i),
 906                        decoder->reg[REG_ADDR(i)]);
 907        }
 908
 909        v4l_dbg(1, debug, client,
 910                "performing decoder reset sequence\n");
 911
 912        err[6] = saa7114_write(client, 0x80, 0x06);     // i-port and scaler backend clock selection, task A&B off
 913        err[7] = saa7114_write(client, 0x88, 0xd8);     // sw reset scaler
 914        err[8] = saa7114_write(client, 0x88, 0xf8);     // sw reset scaler release
 915
 916        for (i = 6; i <= 8; i++) {
 917                if (err[i] < 0) {
 918                        v4l_dbg(1, debug, client,
 919                                "init error %d at stage %d, leaving attach.\n",
 920                                i, err[i]);
 921                        kfree(decoder);
 922                        return -EIO;
 923                }
 924        }
 925
 926        v4l_dbg(1, debug, client, "performing the rest of init\n");
 927
 928        err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]);
 929        err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1);      // big seq
 930        err[11] = saa7114_write_block(client, decoder->reg + (0x40 << 1), (0x5f + 1 - 0x40) << 1);      // slicer
 931        err[12] = saa7114_write_block(client, decoder->reg + (0x81 << 1), 2 << 1);      // ?
 932        err[13] = saa7114_write_block(client, decoder->reg + (0x83 << 1), 5 << 1);      // ?
 933        err[14] = saa7114_write_block(client, decoder->reg + (0x90 << 1), 4 << 1);      // Task A
 934        err[15] =
 935            saa7114_write_block(client, decoder->reg + (0x94 << 1),
 936                                12 << 1);
 937        err[16] =
 938            saa7114_write_block(client, decoder->reg + (0xa0 << 1),
 939                                8 << 1);
 940        err[17] =
 941            saa7114_write_block(client, decoder->reg + (0xa8 << 1),
 942                                8 << 1);
 943        err[18] =
 944            saa7114_write_block(client, decoder->reg + (0xb0 << 1),
 945                                8 << 1);
 946        err[19] = saa7114_write_block(client, decoder->reg + (0xc0 << 1), 4 << 1);      // Task B
 947        err[15] =
 948            saa7114_write_block(client, decoder->reg + (0xc4 << 1),
 949                                12 << 1);
 950        err[16] =
 951            saa7114_write_block(client, decoder->reg + (0xd0 << 1),
 952                                8 << 1);
 953        err[17] =
 954            saa7114_write_block(client, decoder->reg + (0xd8 << 1),
 955                                8 << 1);
 956        err[18] =
 957            saa7114_write_block(client, decoder->reg + (0xe0 << 1),
 958                                8 << 1);
 959
 960        for (i = 9; i <= 18; i++) {
 961                if (err[i] < 0) {
 962                        v4l_dbg(1, debug, client,
 963                                "init error %d at stage %d, leaving attach.\n",
 964                                i, err[i]);
 965                        kfree(decoder);
 966                        return -EIO;
 967                }
 968        }
 969
 970
 971        for (i = 6; i < 8; i++) {
 972                v4l_dbg(1, debug, client,
 973                        "reg[0x%02x] = 0x%02x (0x%02x)\n",
 974                        i, saa7114_read(client, i),
 975                        decoder->reg[REG_ADDR(i)]);
 976        }
 977
 978
 979        for (i = 0x11; i <= 0x13; i++) {
 980                v4l_dbg(1, debug, client,
 981                        "reg[0x%02x] = 0x%02x (0x%02x)\n",
 982                        i, saa7114_read(client, i),
 983                        decoder->reg[REG_ADDR(i)]);
 984        }
 985
 986
 987        v4l_dbg(1, debug, client, "setting video input\n");
 988
 989        err[19] =
 990            saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]);
 991        err[20] =
 992            saa7114_write(client, 0x09, decoder->reg[REG_ADDR(0x09)]);
 993        err[21] =
 994            saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]);
 995
 996        for (i = 19; i <= 21; i++) {
 997                if (err[i] < 0) {
 998                        v4l_dbg(1, debug, client,
 999                                "init error %d at stage %d, leaving attach.\n",
1000                                i, err[i]);
1001                        kfree(decoder);
1002                        return -EIO;
1003                }
1004        }
1005
1006        v4l_dbg(1, debug, client, "performing decoder reset sequence\n");
1007
1008        err[22] = saa7114_write(client, 0x88, 0xd8);    // sw reset scaler
1009        err[23] = saa7114_write(client, 0x88, 0xf8);    // sw reset scaler release
1010        err[24] = saa7114_write(client, 0x80, 0x36);    // i-port and scaler backend clock selection, task A&B off
1011
1012
1013        for (i = 22; i <= 24; i++) {
1014                if (err[i] < 0) {
1015                        v4l_dbg(1, debug, client,
1016                                "init error %d at stage %d, leaving attach.\n",
1017                                i, err[i]);
1018                        kfree(decoder);
1019                        return -EIO;
1020                }
1021        }
1022
1023        err[25] = saa7114_write(client, 0x06, init[REG_ADDR(0x06)]);
1024        err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]);
1025        err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]);
1026
1027        v4l_dbg(1, debug, client, "chip version %x, decoder status 0x%02x\n",
1028                saa7114_read(client, 0x00) >> 4,
1029                saa7114_read(client, 0x1f));
1030        v4l_dbg(1, debug, client,
1031                "power save control: 0x%02x, scaler status: 0x%02x\n",
1032                saa7114_read(client, 0x88),
1033                saa7114_read(client, 0x8f));
1034
1035
1036        for (i = 0x94; i < 0x96; i++) {
1037                v4l_dbg(1, debug, client,
1038                        "reg[0x%02x] = 0x%02x (0x%02x)\n",
1039                        i, saa7114_read(client, i),
1040                        decoder->reg[REG_ADDR(i)]);
1041        }
1042
1043        //i = saa7114_write_block(client, init, sizeof(init));
1044        return 0;
1045}
1046
1047static int saa7114_remove(struct i2c_client *client)
1048{
1049        kfree(i2c_get_clientdata(client));
1050        return 0;
1051}
1052
1053/* ----------------------------------------------------------------------- */
1054
1055static const struct i2c_device_id saa7114_id[] = {
1056        { "saa7114_old", 0 },   /* "saa7114" maps to the saa7115 driver */
1057        { }
1058};
1059MODULE_DEVICE_TABLE(i2c, saa7114_id);
1060
1061static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1062        .name = "saa7114",
1063        .driverid = I2C_DRIVERID_SAA7114,
1064        .command = saa7114_command,
1065        .probe = saa7114_probe,
1066        .remove = saa7114_remove,
1067        .id_table = saa7114_id,
1068};
1069
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.