linux/drivers/media/video/adv7175.c
<<
>>
Prefs
   1/*
   2 *  adv7175 - adv7175a video encoder driver version 0.0.3
   3 *
   4 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
   5 * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
   6 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
   7 *    - some corrections for Pinnacle Systems Inc. DC10plus card.
   8 *
   9 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
  10 *    - moved over to linux>=2.4.x i2c protocol (9/9/2002)
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25 */
  26
  27#include <linux/module.h>
  28#include <linux/init.h>
  29#include <linux/delay.h>
  30#include <linux/errno.h>
  31#include <linux/fs.h>
  32#include <linux/kernel.h>
  33#include <linux/major.h>
  34#include <linux/slab.h>
  35#include <linux/mm.h>
  36#include <linux/signal.h>
  37#include <linux/types.h>
  38#include <linux/i2c.h>
  39#include <asm/io.h>
  40#include <asm/pgtable.h>
  41#include <asm/page.h>
  42#include <asm/uaccess.h>
  43
  44#include <linux/videodev.h>
  45#include <linux/video_encoder.h>
  46
  47MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
  48MODULE_AUTHOR("Dave Perks");
  49MODULE_LICENSE("GPL");
  50
  51
  52#define I2C_NAME(s) (s)->name
  53
  54
  55static int debug = 0;
  56module_param(debug, int, 0);
  57MODULE_PARM_DESC(debug, "Debug level (0-1)");
  58
  59#define dprintk(num, format, args...) \
  60        do { \
  61                if (debug >= num) \
  62                        printk(format, ##args); \
  63        } while (0)
  64
  65/* ----------------------------------------------------------------------- */
  66
  67struct adv7175 {
  68        int norm;
  69        int input;
  70        int enable;
  71        int bright;
  72        int contrast;
  73        int hue;
  74        int sat;
  75};
  76
  77#define   I2C_ADV7175        0xd4
  78#define   I2C_ADV7176        0x54
  79
  80static char adv7175_name[] = "adv7175";
  81static char adv7176_name[] = "adv7176";
  82
  83static char *inputs[] = { "pass_through", "play_back", "color_bar" };
  84static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
  85
  86/* ----------------------------------------------------------------------- */
  87
  88static inline int
  89adv7175_write (struct i2c_client *client,
  90               u8                 reg,
  91               u8                 value)
  92{
  93        return i2c_smbus_write_byte_data(client, reg, value);
  94}
  95
  96static inline int
  97adv7175_read (struct i2c_client *client,
  98              u8                 reg)
  99{
 100        return i2c_smbus_read_byte_data(client, reg);
 101}
 102
 103static int
 104adv7175_write_block (struct i2c_client *client,
 105                     const u8          *data,
 106                     unsigned int       len)
 107{
 108        int ret = -1;
 109        u8 reg;
 110
 111        /* the adv7175 has an autoincrement function, use it if
 112         * the adapter understands raw I2C */
 113        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 114                /* do raw I2C, not smbus compatible */
 115                u8 block_data[32];
 116                int block_len;
 117
 118                while (len >= 2) {
 119                        block_len = 0;
 120                        block_data[block_len++] = reg = data[0];
 121                        do {
 122                                block_data[block_len++] = data[1];
 123                                reg++;
 124                                len -= 2;
 125                                data += 2;
 126                        } while (len >= 2 && data[0] == reg &&
 127                                 block_len < 32);
 128                        if ((ret = i2c_master_send(client, block_data,
 129                                                   block_len)) < 0)
 130                                break;
 131                }
 132        } else {
 133                /* do some slow I2C emulation kind of thing */
 134                while (len >= 2) {
 135                        reg = *data++;
 136                        if ((ret = adv7175_write(client, reg,
 137                                                 *data++)) < 0)
 138                                break;
 139                        len -= 2;
 140                }
 141        }
 142
 143        return ret;
 144}
 145
 146static void
 147set_subcarrier_freq (struct i2c_client *client,
 148                     int                pass_through)
 149{
 150        /* for some reason pass_through NTSC needs
 151         * a different sub-carrier freq to remain stable. */
 152        if(pass_through)
 153                adv7175_write(client, 0x02, 0x00);
 154        else
 155                adv7175_write(client, 0x02, 0x55);
 156
 157        adv7175_write(client, 0x03, 0x55);
 158        adv7175_write(client, 0x04, 0x55);
 159        adv7175_write(client, 0x05, 0x25);
 160}
 161
 162/* ----------------------------------------------------------------------- */
 163// Output filter:  S-Video  Composite
 164
 165#define MR050       0x11        //0x09
 166#define MR060       0x14        //0x0c
 167
 168//---------------------------------------------------------------------------
 169
 170#define TR0MODE     0x46
 171#define TR0RST      0x80
 172
 173#define TR1CAPT     0x80
 174#define TR1PLAY     0x00
 175
 176static const unsigned char init_common[] = {
 177
 178        0x00, MR050,            /* MR0, PAL enabled */
 179        0x01, 0x00,             /* MR1 */
 180        0x02, 0x0c,             /* subc. freq. */
 181        0x03, 0x8c,             /* subc. freq. */
 182        0x04, 0x79,             /* subc. freq. */
 183        0x05, 0x26,             /* subc. freq. */
 184        0x06, 0x40,             /* subc. phase */
 185
 186        0x07, TR0MODE,          /* TR0, 16bit */
 187        0x08, 0x21,             /*  */
 188        0x09, 0x00,             /*  */
 189        0x0a, 0x00,             /*  */
 190        0x0b, 0x00,             /*  */
 191        0x0c, TR1CAPT,          /* TR1 */
 192        0x0d, 0x4f,             /* MR2 */
 193        0x0e, 0x00,             /*  */
 194        0x0f, 0x00,             /*  */
 195        0x10, 0x00,             /*  */
 196        0x11, 0x00,             /*  */
 197};
 198
 199static const unsigned char init_pal[] = {
 200        0x00, MR050,            /* MR0, PAL enabled */
 201        0x01, 0x00,             /* MR1 */
 202        0x02, 0x0c,             /* subc. freq. */
 203        0x03, 0x8c,             /* subc. freq. */
 204        0x04, 0x79,             /* subc. freq. */
 205        0x05, 0x26,             /* subc. freq. */
 206        0x06, 0x40,             /* subc. phase */
 207};
 208
 209static const unsigned char init_ntsc[] = {
 210        0x00, MR060,            /* MR0, NTSC enabled */
 211        0x01, 0x00,             /* MR1 */
 212        0x02, 0x55,             /* subc. freq. */
 213        0x03, 0x55,             /* subc. freq. */
 214        0x04, 0x55,             /* subc. freq. */
 215        0x05, 0x25,             /* subc. freq. */
 216        0x06, 0x1a,             /* subc. phase */
 217};
 218
 219static int
 220adv7175_command (struct i2c_client *client,
 221                 unsigned int       cmd,
 222                 void              *arg)
 223{
 224        struct adv7175 *encoder = i2c_get_clientdata(client);
 225
 226        switch (cmd) {
 227
 228        case 0:
 229                /* This is just for testing!!! */
 230                adv7175_write_block(client, init_common,
 231                                    sizeof(init_common));
 232                adv7175_write(client, 0x07, TR0MODE | TR0RST);
 233                adv7175_write(client, 0x07, TR0MODE);
 234                break;
 235
 236        case ENCODER_GET_CAPABILITIES:
 237        {
 238                struct video_encoder_capability *cap = arg;
 239
 240                cap->flags = VIDEO_ENCODER_PAL |
 241                             VIDEO_ENCODER_NTSC |
 242                             VIDEO_ENCODER_SECAM; /* well, hacky */
 243                cap->inputs = 2;
 244                cap->outputs = 1;
 245        }
 246                break;
 247
 248        case ENCODER_SET_NORM:
 249        {
 250                int iarg = *(int *) arg;
 251
 252                switch (iarg) {
 253
 254                case VIDEO_MODE_NTSC:
 255                        adv7175_write_block(client, init_ntsc,
 256                                            sizeof(init_ntsc));
 257                        if (encoder->input == 0)
 258                                adv7175_write(client, 0x0d, 0x4f);      // Enable genlock
 259                        adv7175_write(client, 0x07, TR0MODE | TR0RST);
 260                        adv7175_write(client, 0x07, TR0MODE);
 261                        break;
 262
 263                case VIDEO_MODE_PAL:
 264                        adv7175_write_block(client, init_pal,
 265                                            sizeof(init_pal));
 266                        if (encoder->input == 0)
 267                                adv7175_write(client, 0x0d, 0x4f);      // Enable genlock
 268                        adv7175_write(client, 0x07, TR0MODE | TR0RST);
 269                        adv7175_write(client, 0x07, TR0MODE);
 270                        break;
 271
 272                case VIDEO_MODE_SECAM:  // WARNING! ADV7176 does not support SECAM.
 273                        /* This is an attempt to convert
 274                         * SECAM->PAL (typically it does not work
 275                         * due to genlock: when decoder is in SECAM
 276                         * and encoder in in PAL the subcarrier can
 277                         * not be syncronized with horizontal
 278                         * quency) */
 279                        adv7175_write_block(client, init_pal,
 280                                            sizeof(init_pal));
 281                        if (encoder->input == 0)
 282                                adv7175_write(client, 0x0d, 0x49);      // Disable genlock
 283                        adv7175_write(client, 0x07, TR0MODE | TR0RST);
 284                        adv7175_write(client, 0x07, TR0MODE);
 285                        break;
 286                default:
 287                        dprintk(1, KERN_ERR "%s: illegal norm: %d\n",
 288                                I2C_NAME(client), iarg);
 289                        return -EINVAL;
 290
 291                }
 292                dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client),
 293                        norms[iarg]);
 294                encoder->norm = iarg;
 295        }
 296                break;
 297
 298        case ENCODER_SET_INPUT:
 299        {
 300                int iarg = *(int *) arg;
 301
 302                /* RJ: *iarg = 0: input is from SAA7110
 303                 *iarg = 1: input is from ZR36060
 304                 *iarg = 2: color bar */
 305
 306                switch (iarg) {
 307
 308                case 0:
 309                        adv7175_write(client, 0x01, 0x00);
 310
 311                        if (encoder->norm == VIDEO_MODE_NTSC)
 312                                set_subcarrier_freq(client, 1);
 313
 314                        adv7175_write(client, 0x0c, TR1CAPT);   /* TR1 */
 315                        if (encoder->norm == VIDEO_MODE_SECAM)
 316                                adv7175_write(client, 0x0d, 0x49);      // Disable genlock
 317                        else
 318                                adv7175_write(client, 0x0d, 0x4f);      // Enable genlock
 319                        adv7175_write(client, 0x07, TR0MODE | TR0RST);
 320                        adv7175_write(client, 0x07, TR0MODE);
 321                        //udelay(10);
 322                        break;
 323
 324                case 1:
 325                        adv7175_write(client, 0x01, 0x00);
 326
 327                        if (encoder->norm == VIDEO_MODE_NTSC)
 328                                set_subcarrier_freq(client, 0);
 329
 330                        adv7175_write(client, 0x0c, TR1PLAY);   /* TR1 */
 331                        adv7175_write(client, 0x0d, 0x49);
 332                        adv7175_write(client, 0x07, TR0MODE | TR0RST);
 333                        adv7175_write(client, 0x07, TR0MODE);
 334                        //udelay(10);
 335                        break;
 336
 337                case 2:
 338                        adv7175_write(client, 0x01, 0x80);
 339
 340                        if (encoder->norm == VIDEO_MODE_NTSC)
 341                                set_subcarrier_freq(client, 0);
 342
 343                        adv7175_write(client, 0x0d, 0x49);
 344                        adv7175_write(client, 0x07, TR0MODE | TR0RST);
 345                        adv7175_write(client, 0x07, TR0MODE);
 346                        //udelay(10);
 347                        break;
 348
 349                default:
 350                        dprintk(1, KERN_ERR "%s: illegal input: %d\n",
 351                                I2C_NAME(client), iarg);
 352                        return -EINVAL;
 353
 354                }
 355                dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client),
 356                        inputs[iarg]);
 357                encoder->input = iarg;
 358        }
 359                break;
 360
 361        case ENCODER_SET_OUTPUT:
 362        {
 363                int *iarg = arg;
 364
 365                /* not much choice of outputs */
 366                if (*iarg != 0) {
 367                        return -EINVAL;
 368                }
 369        }
 370                break;
 371
 372        case ENCODER_ENABLE_OUTPUT:
 373        {
 374                int *iarg = arg;
 375
 376                encoder->enable = !!*iarg;
 377        }
 378                break;
 379
 380        default:
 381                return -EINVAL;
 382        }
 383
 384        return 0;
 385}
 386
 387/* ----------------------------------------------------------------------- */
 388
 389/*
 390 * Generic i2c probe
 391 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
 392 */
 393static unsigned short normal_i2c[] =
 394    { I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1,
 395        I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
 396        I2C_CLIENT_END
 397};
 398
 399static unsigned short ignore = I2C_CLIENT_END;
 400
 401static struct i2c_client_address_data addr_data = {
 402        .normal_i2c             = normal_i2c,
 403        .probe                  = &ignore,
 404        .ignore                 = &ignore,
 405};
 406
 407static struct i2c_driver i2c_driver_adv7175;
 408
 409static int
 410adv7175_detect_client (struct i2c_adapter *adapter,
 411                       int                 address,
 412                       int                 kind)
 413{
 414        int i;
 415        struct i2c_client *client;
 416        struct adv7175 *encoder;
 417        char *dname;
 418
 419        dprintk(1,
 420                KERN_INFO
 421                "adv7175.c: detecting adv7175 client on address 0x%x\n",
 422                address << 1);
 423
 424        /* Check if the adapter supports the needed features */
 425        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 426                return 0;
 427
 428        client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 429        if (client == 0)
 430                return -ENOMEM;
 431        client->addr = address;
 432        client->adapter = adapter;
 433        client->driver = &i2c_driver_adv7175;
 434        if ((client->addr == I2C_ADV7175 >> 1) ||
 435            (client->addr == (I2C_ADV7175 >> 1) + 1)) {
 436                dname = adv7175_name;
 437        } else if ((client->addr == I2C_ADV7176 >> 1) ||
 438                   (client->addr == (I2C_ADV7176 >> 1) + 1)) {
 439                dname = adv7176_name;
 440        } else {
 441                /* We should never get here!!! */
 442                kfree(client);
 443                return 0;
 444        }
 445        strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
 446
 447        encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
 448        if (encoder == NULL) {
 449                kfree(client);
 450                return -ENOMEM;
 451        }
 452        encoder->norm = VIDEO_MODE_PAL;
 453        encoder->input = 0;
 454        encoder->enable = 1;
 455        i2c_set_clientdata(client, encoder);
 456
 457        i = i2c_attach_client(client);
 458        if (i) {
 459                kfree(client);
 460                kfree(encoder);
 461                return i;
 462        }
 463
 464        i = adv7175_write_block(client, init_common, sizeof(init_common));
 465        if (i >= 0) {
 466                i = adv7175_write(client, 0x07, TR0MODE | TR0RST);
 467                i = adv7175_write(client, 0x07, TR0MODE);
 468                i = adv7175_read(client, 0x12);
 469                dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%x\n",
 470                        I2C_NAME(client), i & 1, client->addr << 1);
 471        }
 472        if (i < 0) {
 473                dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n",
 474                        I2C_NAME(client), i);
 475        }
 476
 477        return 0;
 478}
 479
 480static int
 481adv7175_attach_adapter (struct i2c_adapter *adapter)
 482{
 483        dprintk(1,
 484                KERN_INFO
 485                "adv7175.c: starting probe for adapter %s (0x%x)\n",
 486                I2C_NAME(adapter), adapter->id);
 487        return i2c_probe(adapter, &addr_data, &adv7175_detect_client);
 488}
 489
 490static int
 491adv7175_detach_client (struct i2c_client *client)
 492{
 493        struct adv7175 *encoder = i2c_get_clientdata(client);
 494        int err;
 495
 496        err = i2c_detach_client(client);
 497        if (err) {
 498                return err;
 499        }
 500
 501        kfree(encoder);
 502        kfree(client);
 503
 504        return 0;
 505}
 506
 507/* ----------------------------------------------------------------------- */
 508
 509static struct i2c_driver i2c_driver_adv7175 = {
 510        .driver = {
 511                .name = "adv7175",      /* name */
 512        },
 513
 514        .id = I2C_DRIVERID_ADV7175,
 515
 516        .attach_adapter = adv7175_attach_adapter,
 517        .detach_client = adv7175_detach_client,
 518        .command = adv7175_command,
 519};
 520
 521static int __init
 522adv7175_init (void)
 523{
 524        return i2c_add_driver(&i2c_driver_adv7175);
 525}
 526
 527static void __exit
 528adv7175_exit (void)
 529{
 530        i2c_del_driver(&i2c_driver_adv7175);
 531}
 532
 533module_init(adv7175_init);
 534module_exit(adv7175_exit);
 535