linux/drivers/media/video/bt866.c
<<
>>
Prefs
   1/*
   2    bt866 - BT866 Digital Video Encoder (Rockwell Part)
   3
   4    Copyright (C) 1999 Mike Bernson <mike@mlb.org>
   5    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
   6
   7    Modifications for LML33/DC10plus unified driver
   8    Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
   9
  10    This code was modify/ported from the saa7111 driver written
  11    by Dave Perks.
  12
  13    This code was adapted for the bt866 by Christer Weinigel and ported
  14    to 2.6 by Martin Samuelsson.
  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/init.h>
  33#include <linux/delay.h>
  34#include <linux/errno.h>
  35#include <linux/fs.h>
  36#include <linux/kernel.h>
  37#include <linux/major.h>
  38#include <linux/slab.h>
  39#include <linux/mm.h>
  40#include <linux/signal.h>
  41#include <asm/io.h>
  42#include <asm/pgtable.h>
  43#include <asm/page.h>
  44#include <linux/sched.h>
  45#include <linux/types.h>
  46#include <linux/i2c.h>
  47
  48#include <linux/videodev.h>
  49#include <asm/uaccess.h>
  50
  51#include <linux/video_encoder.h>
  52
  53MODULE_LICENSE("GPL");
  54
  55#define BT866_DEVNAME   "bt866"
  56#define I2C_BT866       0x88
  57
  58MODULE_LICENSE("GPL");
  59
  60#define DEBUG(x)                /* Debug driver */
  61
  62/* ----------------------------------------------------------------------- */
  63
  64struct bt866 {
  65        struct i2c_client *i2c;
  66        int addr;
  67        unsigned char reg[256];
  68
  69        int norm;
  70        int enable;
  71        int bright;
  72        int contrast;
  73        int hue;
  74        int sat;
  75};
  76
  77static int bt866_write(struct bt866 *dev,
  78                        unsigned char subaddr, unsigned char data);
  79
  80static int bt866_do_command(struct bt866 *encoder,
  81                        unsigned int cmd, void *arg)
  82{
  83        switch (cmd) {
  84        case ENCODER_GET_CAPABILITIES:
  85        {
  86                struct video_encoder_capability *cap = arg;
  87
  88                DEBUG(printk
  89                      (KERN_INFO "%s: get capabilities\n",
  90                       encoder->i2c->name));
  91
  92                cap->flags
  93                        = VIDEO_ENCODER_PAL
  94                        | VIDEO_ENCODER_NTSC
  95                        | VIDEO_ENCODER_CCIR;
  96                cap->inputs = 2;
  97                cap->outputs = 1;
  98        }
  99        break;
 100
 101        case ENCODER_SET_NORM:
 102        {
 103                int *iarg = arg;
 104
 105                DEBUG(printk(KERN_INFO "%s: set norm %d\n",
 106                             encoder->i2c->name, *iarg));
 107
 108                switch (*iarg) {
 109
 110                case VIDEO_MODE_NTSC:
 111                        break;
 112
 113                case VIDEO_MODE_PAL:
 114                        break;
 115
 116                default:
 117                        return -EINVAL;
 118
 119                }
 120                encoder->norm = *iarg;
 121        }
 122        break;
 123
 124        case ENCODER_SET_INPUT:
 125        {
 126                int *iarg = arg;
 127                static const __u8 init[] = {
 128                        0xc8, 0xcc, /* CRSCALE */
 129                        0xca, 0x91, /* CBSCALE */
 130                        0xcc, 0x24, /* YC16 | OSDNUM */
 131                        0xda, 0x00, /*  */
 132                        0xdc, 0x24, /* SETMODE | PAL */
 133                        0xde, 0x02, /* EACTIVE */
 134
 135                        /* overlay colors */
 136                        0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
 137                        0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
 138                        0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
 139                        0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
 140                        0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
 141                        0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
 142                        0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
 143                        0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
 144
 145                        0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
 146                        0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
 147                        0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
 148                        0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
 149                        0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
 150                        0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
 151                        0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
 152                        0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
 153                };
 154                int i;
 155                u8 val;
 156
 157                for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
 158                        bt866_write(encoder, init[i], init[i+1]);
 159
 160                val = encoder->reg[0xdc];
 161
 162                if (*iarg == 0)
 163                        val |= 0x40; /* CBSWAP */
 164                else
 165                        val &= ~0x40; /* !CBSWAP */
 166
 167                bt866_write(encoder, 0xdc, val);
 168
 169                val = encoder->reg[0xcc];
 170                if (*iarg == 2)
 171                        val |= 0x01; /* OSDBAR */
 172                else
 173                        val &= ~0x01; /* !OSDBAR */
 174                bt866_write(encoder, 0xcc, val);
 175
 176                DEBUG(printk(KERN_INFO "%s: set input %d\n",
 177                             encoder->i2c->name, *iarg));
 178
 179                switch (*iarg) {
 180                case 0:
 181                        break;
 182                case 1:
 183                        break;
 184                default:
 185                        return -EINVAL;
 186
 187                }
 188        }
 189        break;
 190
 191        case ENCODER_SET_OUTPUT:
 192        {
 193                int *iarg = arg;
 194
 195                DEBUG(printk(KERN_INFO "%s: set output %d\n",
 196                             encoder->i2c->name, *iarg));
 197
 198                /* not much choice of outputs */
 199                if (*iarg != 0)
 200                        return -EINVAL;
 201        }
 202        break;
 203
 204        case ENCODER_ENABLE_OUTPUT:
 205        {
 206                int *iarg = arg;
 207                encoder->enable = !!*iarg;
 208
 209                DEBUG(printk
 210                      (KERN_INFO "%s: enable output %d\n",
 211                       encoder->i2c->name, encoder->enable));
 212        }
 213        break;
 214
 215        case 4711:
 216        {
 217                int *iarg = arg;
 218                __u8 val;
 219
 220                printk("bt866: square = %d\n", *iarg);
 221
 222                val = encoder->reg[0xdc];
 223                if (*iarg)
 224                        val |= 1; /* SQUARE */
 225                else
 226                        val &= ~1; /* !SQUARE */
 227                bt866_write(encoder, 0xdc, val);
 228                break;
 229        }
 230
 231        default:
 232                return -EINVAL;
 233        }
 234
 235        return 0;
 236}
 237
 238static int bt866_write(struct bt866 *encoder,
 239                        unsigned char subaddr, unsigned char data)
 240{
 241        unsigned char buffer[2];
 242        int err;
 243
 244        buffer[0] = subaddr;
 245        buffer[1] = data;
 246
 247        encoder->reg[subaddr] = data;
 248
 249        DEBUG(printk
 250              ("%s: write 0x%02X = 0x%02X\n",
 251               encoder->i2c->name, subaddr, data));
 252
 253        for (err = 0; err < 3;) {
 254                if (i2c_master_send(encoder->i2c, buffer, 2) == 2)
 255                        break;
 256                err++;
 257                printk(KERN_WARNING "%s: I/O error #%d "
 258                       "(write 0x%02x/0x%02x)\n",
 259                       encoder->i2c->name, err, encoder->addr, subaddr);
 260                schedule_timeout_interruptible(msecs_to_jiffies(100));
 261        }
 262        if (err == 3) {
 263                printk(KERN_WARNING "%s: giving up\n",
 264                       encoder->i2c->name);
 265                return -1;
 266        }
 267
 268        return 0;
 269}
 270
 271static int bt866_attach(struct i2c_adapter *adapter);
 272static int bt866_detach(struct i2c_client *client);
 273static int bt866_command(struct i2c_client *client,
 274                         unsigned int cmd, void *arg);
 275
 276
 277/* Addresses to scan */
 278static unsigned short normal_i2c[]      = {I2C_BT866>>1, I2C_CLIENT_END};
 279static unsigned short probe[2]          = {I2C_CLIENT_END, I2C_CLIENT_END};
 280static unsigned short ignore[2]         = {I2C_CLIENT_END, I2C_CLIENT_END};
 281
 282static struct i2c_client_address_data addr_data = {
 283        normal_i2c,
 284        probe,
 285        ignore,
 286};
 287
 288static struct i2c_driver i2c_driver_bt866 = {
 289        .driver.name = BT866_DEVNAME,
 290        .id = I2C_DRIVERID_BT866,
 291        .attach_adapter = bt866_attach,
 292        .detach_client = bt866_detach,
 293        .command = bt866_command
 294};
 295
 296
 297static struct i2c_client bt866_client_tmpl =
 298{
 299        .name = "(nil)",
 300        .addr = 0,
 301        .adapter = NULL,
 302        .driver = &i2c_driver_bt866,
 303};
 304
 305static int bt866_found_proc(struct i2c_adapter *adapter,
 306                            int addr, int kind)
 307{
 308        struct bt866 *encoder;
 309        struct i2c_client *client;
 310
 311        client = kzalloc(sizeof(*client), GFP_KERNEL);
 312        if (client == NULL)
 313                return -ENOMEM;
 314        memcpy(client, &bt866_client_tmpl, sizeof(*client));
 315
 316        encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
 317        if (encoder == NULL) {
 318                kfree(client);
 319                return -ENOMEM;
 320        }
 321
 322        i2c_set_clientdata(client, encoder);
 323        client->adapter = adapter;
 324        client->addr = addr;
 325        sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id);
 326
 327        encoder->i2c = client;
 328        encoder->addr = addr;
 329        //encoder->encoder_type = ENCODER_TYPE_UNKNOWN;
 330
 331        /* initialize */
 332
 333        i2c_attach_client(client);
 334
 335        return 0;
 336}
 337
 338static int bt866_attach(struct i2c_adapter *adapter)
 339{
 340        if (adapter->id == I2C_HW_B_ZR36067)
 341                return i2c_probe(adapter, &addr_data, bt866_found_proc);
 342        return 0;
 343}
 344
 345static int bt866_detach(struct i2c_client *client)
 346{
 347        struct bt866 *encoder = i2c_get_clientdata(client);
 348
 349        i2c_detach_client(client);
 350        kfree(encoder);
 351        kfree(client);
 352
 353        return 0;
 354}
 355
 356static int bt866_command(struct i2c_client *client,
 357                         unsigned int cmd, void *arg)
 358{
 359        struct bt866 *encoder = i2c_get_clientdata(client);
 360        return bt866_do_command(encoder, cmd, arg);
 361}
 362
 363static int __devinit bt866_init(void)
 364{
 365        i2c_add_driver(&i2c_driver_bt866);
 366        return 0;
 367}
 368
 369static void __devexit bt866_exit(void)
 370{
 371        i2c_del_driver(&i2c_driver_bt866);
 372}
 373
 374module_init(bt866_init);
 375module_exit(bt866_exit);
 376