linux/drivers/staging/media/go7007/wis-saa7113.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2005-2006 Micronas USA Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License (Version 2) as
   6 * published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software Foundation,
  15 * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/init.h>
  20#include <linux/i2c.h>
  21#include <linux/videodev2.h>
  22#include <linux/ioctl.h>
  23#include <linux/slab.h>
  24
  25#include "wis-i2c.h"
  26
  27struct wis_saa7113 {
  28        int norm;
  29        int brightness;
  30        int contrast;
  31        int saturation;
  32        int hue;
  33};
  34
  35static u8 initial_registers[] =
  36{
  37        0x01, 0x08,
  38        0x02, 0xc0,
  39        0x03, 0x33,
  40        0x04, 0x00,
  41        0x05, 0x00,
  42        0x06, 0xe9,
  43        0x07, 0x0d,
  44        0x08, 0xd8,
  45        0x09, 0x40,
  46        0x0a, 0x80,
  47        0x0b, 0x47,
  48        0x0c, 0x40,
  49        0x0d, 0x00,
  50        0x0e, 0x01,
  51        0x0f, 0x2a,
  52        0x10, 0x40,
  53        0x11, 0x0c,
  54        0x12, 0xfe,
  55        0x13, 0x00,
  56        0x14, 0x00,
  57        0x15, 0x04,
  58        0x16, 0x00,
  59        0x17, 0x00,
  60        0x18, 0x00,
  61        0x19, 0x00,
  62        0x1a, 0x00,
  63        0x1b, 0x00,
  64        0x1c, 0x00,
  65        0x1d, 0x00,
  66        0x1e, 0x00,
  67        0x1f, 0xc8,
  68        0x40, 0x00,
  69        0x41, 0xff,
  70        0x42, 0xff,
  71        0x43, 0xff,
  72        0x44, 0xff,
  73        0x45, 0xff,
  74        0x46, 0xff,
  75        0x47, 0xff,
  76        0x48, 0xff,
  77        0x49, 0xff,
  78        0x4a, 0xff,
  79        0x4b, 0xff,
  80        0x4c, 0xff,
  81        0x4d, 0xff,
  82        0x4e, 0xff,
  83        0x4f, 0xff,
  84        0x50, 0xff,
  85        0x51, 0xff,
  86        0x52, 0xff,
  87        0x53, 0xff,
  88        0x54, 0xff,
  89        0x55, 0xff,
  90        0x56, 0xff,
  91        0x57, 0xff,
  92        0x58, 0x00,
  93        0x59, 0x54,
  94        0x5a, 0x07,
  95        0x5b, 0x83,
  96        0x5c, 0x00,
  97        0x5d, 0x00,
  98        0x5e, 0x00,
  99        0x5f, 0x00,
 100        0x60, 0x00,
 101        0x61, 0x00,
 102        0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
 103};
 104
 105static int write_reg(struct i2c_client *client, u8 reg, u8 value)
 106{
 107        return i2c_smbus_write_byte_data(client, reg, value);
 108}
 109
 110static int write_regs(struct i2c_client *client, u8 *regs)
 111{
 112        int i;
 113
 114        for (i = 0; regs[i] != 0x00; i += 2)
 115                if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
 116                        return -1;
 117        return 0;
 118}
 119
 120static int wis_saa7113_command(struct i2c_client *client,
 121                                unsigned int cmd, void *arg)
 122{
 123        struct wis_saa7113 *dec = i2c_get_clientdata(client);
 124
 125        switch (cmd) {
 126        case VIDIOC_S_INPUT:
 127        {
 128                int *input = arg;
 129
 130                i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
 131                i2c_smbus_write_byte_data(client, 0x09,
 132                                *input < 6 ? 0x40 : 0x80);
 133                break;
 134        }
 135        case VIDIOC_S_STD:
 136        {
 137                v4l2_std_id *input = arg;
 138                dec->norm = *input;
 139                if (dec->norm & V4L2_STD_NTSC) {
 140                        write_reg(client, 0x0e, 0x01);
 141                        write_reg(client, 0x10, 0x40);
 142                } else if (dec->norm & V4L2_STD_PAL) {
 143                        write_reg(client, 0x0e, 0x01);
 144                        write_reg(client, 0x10, 0x48);
 145                } else if (dec->norm * V4L2_STD_SECAM) {
 146                        write_reg(client, 0x0e, 0x50);
 147                        write_reg(client, 0x10, 0x48);
 148                }
 149                break;
 150        }
 151        case VIDIOC_QUERYCTRL:
 152        {
 153                struct v4l2_queryctrl *ctrl = arg;
 154
 155                switch (ctrl->id) {
 156                case V4L2_CID_BRIGHTNESS:
 157                        ctrl->type = V4L2_CTRL_TYPE_INTEGER;
 158                        strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
 159                        ctrl->minimum = 0;
 160                        ctrl->maximum = 255;
 161                        ctrl->step = 1;
 162                        ctrl->default_value = 128;
 163                        ctrl->flags = 0;
 164                        break;
 165                case V4L2_CID_CONTRAST:
 166                        ctrl->type = V4L2_CTRL_TYPE_INTEGER;
 167                        strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
 168                        ctrl->minimum = 0;
 169                        ctrl->maximum = 127;
 170                        ctrl->step = 1;
 171                        ctrl->default_value = 71;
 172                        ctrl->flags = 0;
 173                        break;
 174                case V4L2_CID_SATURATION:
 175                        ctrl->type = V4L2_CTRL_TYPE_INTEGER;
 176                        strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
 177                        ctrl->minimum = 0;
 178                        ctrl->maximum = 127;
 179                        ctrl->step = 1;
 180                        ctrl->default_value = 64;
 181                        ctrl->flags = 0;
 182                        break;
 183                case V4L2_CID_HUE:
 184                        ctrl->type = V4L2_CTRL_TYPE_INTEGER;
 185                        strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
 186                        ctrl->minimum = -128;
 187                        ctrl->maximum = 127;
 188                        ctrl->step = 1;
 189                        ctrl->default_value = 0;
 190                        ctrl->flags = 0;
 191                        break;
 192                }
 193                break;
 194        }
 195        case VIDIOC_S_CTRL:
 196        {
 197                struct v4l2_control *ctrl = arg;
 198
 199                switch (ctrl->id) {
 200                case V4L2_CID_BRIGHTNESS:
 201                        if (ctrl->value > 255)
 202                                dec->brightness = 255;
 203                        else if (ctrl->value < 0)
 204                                dec->brightness = 0;
 205                        else
 206                                dec->brightness = ctrl->value;
 207                        write_reg(client, 0x0a, dec->brightness);
 208                        break;
 209                case V4L2_CID_CONTRAST:
 210                        if (ctrl->value > 127)
 211                                dec->contrast = 127;
 212                        else if (ctrl->value < 0)
 213                                dec->contrast = 0;
 214                        else
 215                                dec->contrast = ctrl->value;
 216                        write_reg(client, 0x0b, dec->contrast);
 217                        break;
 218                case V4L2_CID_SATURATION:
 219                        if (ctrl->value > 127)
 220                                dec->saturation = 127;
 221                        else if (ctrl->value < 0)
 222                                dec->saturation = 0;
 223                        else
 224                                dec->saturation = ctrl->value;
 225                        write_reg(client, 0x0c, dec->saturation);
 226                        break;
 227                case V4L2_CID_HUE:
 228                        if (ctrl->value > 127)
 229                                dec->hue = 127;
 230                        else if (ctrl->value < -128)
 231                                dec->hue = -128;
 232                        else
 233                                dec->hue = ctrl->value;
 234                        write_reg(client, 0x0d, dec->hue);
 235                        break;
 236                }
 237                break;
 238        }
 239        case VIDIOC_G_CTRL:
 240        {
 241                struct v4l2_control *ctrl = arg;
 242
 243                switch (ctrl->id) {
 244                case V4L2_CID_BRIGHTNESS:
 245                        ctrl->value = dec->brightness;
 246                        break;
 247                case V4L2_CID_CONTRAST:
 248                        ctrl->value = dec->contrast;
 249                        break;
 250                case V4L2_CID_SATURATION:
 251                        ctrl->value = dec->saturation;
 252                        break;
 253                case V4L2_CID_HUE:
 254                        ctrl->value = dec->hue;
 255                        break;
 256                }
 257                break;
 258        }
 259        default:
 260                break;
 261        }
 262        return 0;
 263}
 264
 265static int wis_saa7113_probe(struct i2c_client *client,
 266                             const struct i2c_device_id *id)
 267{
 268        struct i2c_adapter *adapter = client->adapter;
 269        struct wis_saa7113 *dec;
 270
 271        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 272                return -ENODEV;
 273
 274        dec = kmalloc(sizeof(struct wis_saa7113), GFP_KERNEL);
 275        if (dec == NULL)
 276                return -ENOMEM;
 277
 278        dec->norm = V4L2_STD_NTSC;
 279        dec->brightness = 128;
 280        dec->contrast = 71;
 281        dec->saturation = 64;
 282        dec->hue = 0;
 283        i2c_set_clientdata(client, dec);
 284
 285        printk(KERN_DEBUG
 286                "wis-saa7113: initializing SAA7113 at address %d on %s\n",
 287                client->addr, adapter->name);
 288
 289        if (write_regs(client, initial_registers) < 0) {
 290                printk(KERN_ERR
 291                        "wis-saa7113: error initializing SAA7113\n");
 292                kfree(dec);
 293                return -ENODEV;
 294        }
 295
 296        return 0;
 297}
 298
 299static int wis_saa7113_remove(struct i2c_client *client)
 300{
 301        struct wis_saa7113 *dec = i2c_get_clientdata(client);
 302
 303        kfree(dec);
 304        return 0;
 305}
 306
 307static const struct i2c_device_id wis_saa7113_id[] = {
 308        { "wis_saa7113", 0 },
 309        { }
 310};
 311MODULE_DEVICE_TABLE(i2c, wis_saa7113_id);
 312
 313static struct i2c_driver wis_saa7113_driver = {
 314        .driver = {
 315                .name   = "WIS SAA7113 I2C driver",
 316        },
 317        .probe          = wis_saa7113_probe,
 318        .remove         = wis_saa7113_remove,
 319        .command        = wis_saa7113_command,
 320        .id_table       = wis_saa7113_id,
 321};
 322
 323static int __init wis_saa7113_init(void)
 324{
 325        return i2c_add_driver(&wis_saa7113_driver);
 326}
 327
 328static void __exit wis_saa7113_cleanup(void)
 329{
 330        i2c_del_driver(&wis_saa7113_driver);
 331}
 332
 333module_init(wis_saa7113_init);
 334module_exit(wis_saa7113_cleanup);
 335
 336MODULE_LICENSE("GPL v2");
 337