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