linux/drivers/media/i2c/bt856.c
<<
>>
Prefs
   1/*
   2 * bt856 - BT856A 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 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
  14 *   - moved over to linux>=2.4.x i2c protocol (9/9/2002)
  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
  27#include <linux/module.h>
  28#include <linux/types.h>
  29#include <linux/slab.h>
  30#include <linux/ioctl.h>
  31#include <linux/uaccess.h>
  32#include <linux/i2c.h>
  33#include <linux/videodev2.h>
  34#include <media/v4l2-device.h>
  35
  36MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
  37MODULE_AUTHOR("Mike Bernson & Dave Perks");
  38MODULE_LICENSE("GPL");
  39
  40static int debug;
  41module_param(debug, int, 0);
  42MODULE_PARM_DESC(debug, "Debug level (0-1)");
  43
  44
  45/* ----------------------------------------------------------------------- */
  46
  47#define BT856_REG_OFFSET        0xDA
  48#define BT856_NR_REG            6
  49
  50struct bt856 {
  51        struct v4l2_subdev sd;
  52        unsigned char reg[BT856_NR_REG];
  53
  54        v4l2_std_id norm;
  55};
  56
  57static inline struct bt856 *to_bt856(struct v4l2_subdev *sd)
  58{
  59        return container_of(sd, struct bt856, sd);
  60}
  61
  62/* ----------------------------------------------------------------------- */
  63
  64static inline int bt856_write(struct bt856 *encoder, u8 reg, u8 value)
  65{
  66        struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd);
  67
  68        encoder->reg[reg - BT856_REG_OFFSET] = value;
  69        return i2c_smbus_write_byte_data(client, reg, value);
  70}
  71
  72static inline int bt856_setbit(struct bt856 *encoder, u8 reg, u8 bit, u8 value)
  73{
  74        return bt856_write(encoder, reg,
  75                (encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
  76                                (value ? (1 << bit) : 0));
  77}
  78
  79static void bt856_dump(struct bt856 *encoder)
  80{
  81        int i;
  82
  83        v4l2_info(&encoder->sd, "register dump:\n");
  84        for (i = 0; i < BT856_NR_REG; i += 2)
  85                printk(KERN_CONT " %02x", encoder->reg[i]);
  86        printk(KERN_CONT "\n");
  87}
  88
  89/* ----------------------------------------------------------------------- */
  90
  91static int bt856_init(struct v4l2_subdev *sd, u32 arg)
  92{
  93        struct bt856 *encoder = to_bt856(sd);
  94
  95        /* This is just for testing!!! */
  96        v4l2_dbg(1, debug, sd, "init\n");
  97        bt856_write(encoder, 0xdc, 0x18);
  98        bt856_write(encoder, 0xda, 0);
  99        bt856_write(encoder, 0xde, 0);
 100
 101        bt856_setbit(encoder, 0xdc, 3, 1);
 102        /*bt856_setbit(encoder, 0xdc, 6, 0);*/
 103        bt856_setbit(encoder, 0xdc, 4, 1);
 104
 105        if (encoder->norm & V4L2_STD_NTSC)
 106                bt856_setbit(encoder, 0xdc, 2, 0);
 107        else
 108                bt856_setbit(encoder, 0xdc, 2, 1);
 109
 110        bt856_setbit(encoder, 0xdc, 1, 1);
 111        bt856_setbit(encoder, 0xde, 4, 0);
 112        bt856_setbit(encoder, 0xde, 3, 1);
 113        if (debug != 0)
 114                bt856_dump(encoder);
 115        return 0;
 116}
 117
 118static int bt856_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
 119{
 120        struct bt856 *encoder = to_bt856(sd);
 121
 122        v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
 123
 124        if (std & V4L2_STD_NTSC) {
 125                bt856_setbit(encoder, 0xdc, 2, 0);
 126        } else if (std & V4L2_STD_PAL) {
 127                bt856_setbit(encoder, 0xdc, 2, 1);
 128                bt856_setbit(encoder, 0xda, 0, 0);
 129                /*bt856_setbit(encoder, 0xda, 0, 1);*/
 130        } else {
 131                return -EINVAL;
 132        }
 133        encoder->norm = std;
 134        if (debug != 0)
 135                bt856_dump(encoder);
 136        return 0;
 137}
 138
 139static int bt856_s_routing(struct v4l2_subdev *sd,
 140                           u32 input, u32 output, u32 config)
 141{
 142        struct bt856 *encoder = to_bt856(sd);
 143
 144        v4l2_dbg(1, debug, sd, "set input %d\n", input);
 145
 146        /* We only have video bus.
 147         * input= 0: input is from bt819
 148         * input= 1: input is from ZR36060 */
 149        switch (input) {
 150        case 0:
 151                bt856_setbit(encoder, 0xde, 4, 0);
 152                bt856_setbit(encoder, 0xde, 3, 1);
 153                bt856_setbit(encoder, 0xdc, 3, 1);
 154                bt856_setbit(encoder, 0xdc, 6, 0);
 155                break;
 156        case 1:
 157                bt856_setbit(encoder, 0xde, 4, 0);
 158                bt856_setbit(encoder, 0xde, 3, 1);
 159                bt856_setbit(encoder, 0xdc, 3, 1);
 160                bt856_setbit(encoder, 0xdc, 6, 1);
 161                break;
 162        case 2: /* Color bar */
 163                bt856_setbit(encoder, 0xdc, 3, 0);
 164                bt856_setbit(encoder, 0xde, 4, 1);
 165                break;
 166        default:
 167                return -EINVAL;
 168        }
 169
 170        if (debug != 0)
 171                bt856_dump(encoder);
 172        return 0;
 173}
 174
 175/* ----------------------------------------------------------------------- */
 176
 177static const struct v4l2_subdev_core_ops bt856_core_ops = {
 178        .init = bt856_init,
 179};
 180
 181static const struct v4l2_subdev_video_ops bt856_video_ops = {
 182        .s_std_output = bt856_s_std_output,
 183        .s_routing = bt856_s_routing,
 184};
 185
 186static const struct v4l2_subdev_ops bt856_ops = {
 187        .core = &bt856_core_ops,
 188        .video = &bt856_video_ops,
 189};
 190
 191/* ----------------------------------------------------------------------- */
 192
 193static int bt856_probe(struct i2c_client *client,
 194                        const struct i2c_device_id *id)
 195{
 196        struct bt856 *encoder;
 197        struct v4l2_subdev *sd;
 198
 199        /* Check if the adapter supports the needed features */
 200        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 201                return -ENODEV;
 202
 203        v4l_info(client, "chip found @ 0x%x (%s)\n",
 204                        client->addr << 1, client->adapter->name);
 205
 206        encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL);
 207        if (encoder == NULL)
 208                return -ENOMEM;
 209        sd = &encoder->sd;
 210        v4l2_i2c_subdev_init(sd, client, &bt856_ops);
 211        encoder->norm = V4L2_STD_NTSC;
 212
 213        bt856_write(encoder, 0xdc, 0x18);
 214        bt856_write(encoder, 0xda, 0);
 215        bt856_write(encoder, 0xde, 0);
 216
 217        bt856_setbit(encoder, 0xdc, 3, 1);
 218        /*bt856_setbit(encoder, 0xdc, 6, 0);*/
 219        bt856_setbit(encoder, 0xdc, 4, 1);
 220
 221        if (encoder->norm & V4L2_STD_NTSC)
 222                bt856_setbit(encoder, 0xdc, 2, 0);
 223        else
 224                bt856_setbit(encoder, 0xdc, 2, 1);
 225
 226        bt856_setbit(encoder, 0xdc, 1, 1);
 227        bt856_setbit(encoder, 0xde, 4, 0);
 228        bt856_setbit(encoder, 0xde, 3, 1);
 229
 230        if (debug != 0)
 231                bt856_dump(encoder);
 232        return 0;
 233}
 234
 235static int bt856_remove(struct i2c_client *client)
 236{
 237        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 238
 239        v4l2_device_unregister_subdev(sd);
 240        return 0;
 241}
 242
 243static const struct i2c_device_id bt856_id[] = {
 244        { "bt856", 0 },
 245        { }
 246};
 247MODULE_DEVICE_TABLE(i2c, bt856_id);
 248
 249static struct i2c_driver bt856_driver = {
 250        .driver = {
 251                .name   = "bt856",
 252        },
 253        .probe          = bt856_probe,
 254        .remove         = bt856_remove,
 255        .id_table       = bt856_id,
 256};
 257
 258module_i2c_driver(bt856_driver);
 259