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