bt866.c revision c18fdcf65732b87f6015ea4e423fc7abf7c26dd2
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/types.h> 33#include <linux/ioctl.h> 34#include <asm/uaccess.h> 35#include <linux/i2c.h> 36#include <linux/i2c-id.h> 37#include <linux/videodev.h> 38#include <linux/video_encoder.h> 39#include <media/v4l2-common.h> 40#include <media/v4l2-i2c-drv-legacy.h> 41 42MODULE_DESCRIPTION("Brooktree-866 video encoder driver"); 43MODULE_AUTHOR("Mike Bernson & Dave Perks"); 44MODULE_LICENSE("GPL"); 45 46static int debug; 47module_param(debug, int, 0); 48MODULE_PARM_DESC(debug, "Debug level (0-1)"); 49 50/* ----------------------------------------------------------------------- */ 51 52struct bt866 { 53 u8 reg[256]; 54 55 int norm; 56 int enable; 57 int bright; 58 int contrast; 59 int hue; 60 int sat; 61}; 62 63static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data) 64{ 65 struct bt866 *encoder = i2c_get_clientdata(client); 66 u8 buffer[2]; 67 int err; 68 69 buffer[0] = subaddr; 70 buffer[1] = data; 71 72 encoder->reg[subaddr] = data; 73 74 v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data); 75 76 for (err = 0; err < 3;) { 77 if (i2c_master_send(client, buffer, 2) == 2) 78 break; 79 err++; 80 v4l_warn(client, "error #%d writing to 0x%02x\n", 81 err, subaddr); 82 schedule_timeout_interruptible(msecs_to_jiffies(100)); 83 } 84 if (err == 3) { 85 v4l_warn(client, "giving up\n"); 86 return -1; 87 } 88 89 return 0; 90} 91 92static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) 93{ 94 struct bt866 *encoder = i2c_get_clientdata(client); 95 96 switch (cmd) { 97 case ENCODER_GET_CAPABILITIES: 98 { 99 struct video_encoder_capability *cap = arg; 100 101 v4l_dbg(1, debug, client, "get capabilities\n"); 102 103 cap->flags 104 = VIDEO_ENCODER_PAL 105 | VIDEO_ENCODER_NTSC 106 | VIDEO_ENCODER_CCIR; 107 cap->inputs = 2; 108 cap->outputs = 1; 109 break; 110 } 111 112 case ENCODER_SET_NORM: 113 { 114 int *iarg = arg; 115 116 v4l_dbg(1, debug, client, "set norm %d\n", *iarg); 117 118 switch (*iarg) { 119 case VIDEO_MODE_NTSC: 120 break; 121 122 case VIDEO_MODE_PAL: 123 break; 124 125 default: 126 return -EINVAL; 127 } 128 encoder->norm = *iarg; 129 break; 130 } 131 132 case ENCODER_SET_INPUT: 133 { 134 int *iarg = arg; 135 static const __u8 init[] = { 136 0xc8, 0xcc, /* CRSCALE */ 137 0xca, 0x91, /* CBSCALE */ 138 0xcc, 0x24, /* YC16 | OSDNUM */ 139 0xda, 0x00, /* */ 140 0xdc, 0x24, /* SETMODE | PAL */ 141 0xde, 0x02, /* EACTIVE */ 142 143 /* overlay colors */ 144 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */ 145 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */ 146 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */ 147 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */ 148 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */ 149 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */ 150 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */ 151 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */ 152 153 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */ 154 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */ 155 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */ 156 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */ 157 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */ 158 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */ 159 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */ 160 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */ 161 }; 162 int i; 163 u8 val; 164 165 for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) 166 bt866_write(client, init[i], init[i+1]); 167 168 val = encoder->reg[0xdc]; 169 170 if (*iarg == 0) 171 val |= 0x40; /* CBSWAP */ 172 else 173 val &= ~0x40; /* !CBSWAP */ 174 175 bt866_write(client, 0xdc, val); 176 177 val = encoder->reg[0xcc]; 178 if (*iarg == 2) 179 val |= 0x01; /* OSDBAR */ 180 else 181 val &= ~0x01; /* !OSDBAR */ 182 bt866_write(client, 0xcc, val); 183 184 v4l_dbg(1, debug, client, "set input %d\n", *iarg); 185 186 switch (*iarg) { 187 case 0: 188 break; 189 case 1: 190 break; 191 default: 192 return -EINVAL; 193 } 194 break; 195 } 196 197 case ENCODER_SET_OUTPUT: 198 { 199 int *iarg = arg; 200 201 v4l_dbg(1, debug, client, "set output %d\n", *iarg); 202 203 /* not much choice of outputs */ 204 if (*iarg != 0) 205 return -EINVAL; 206 break; 207 } 208 209 case ENCODER_ENABLE_OUTPUT: 210 { 211 int *iarg = arg; 212 encoder->enable = !!*iarg; 213 214 v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable); 215 break; 216 } 217 218 case 4711: 219 { 220 int *iarg = arg; 221 __u8 val; 222 223 v4l_dbg(1, debug, client, "square %d\n", *iarg); 224 225 val = encoder->reg[0xdc]; 226 if (*iarg) 227 val |= 1; /* SQUARE */ 228 else 229 val &= ~1; /* !SQUARE */ 230 bt866_write(client, 0xdc, val); 231 break; 232 } 233 234 default: 235 return -EINVAL; 236 } 237 238 return 0; 239} 240 241static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; 242 243I2C_CLIENT_INSMOD; 244 245static int bt866_probe(struct i2c_client *client, 246 const struct i2c_device_id *id) 247{ 248 struct bt866 *encoder; 249 250 v4l_info(client, "chip found @ 0x%x (%s)\n", 251 client->addr << 1, client->adapter->name); 252 253 encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); 254 if (encoder == NULL) 255 return -ENOMEM; 256 257 i2c_set_clientdata(client, encoder); 258 return 0; 259} 260 261static int bt866_remove(struct i2c_client *client) 262{ 263 kfree(i2c_get_clientdata(client)); 264 return 0; 265} 266 267static int bt866_legacy_probe(struct i2c_adapter *adapter) 268{ 269 return adapter->id == I2C_HW_B_ZR36067; 270} 271 272static const struct i2c_device_id bt866_id[] = { 273 { "bt866", 0 }, 274 { } 275}; 276MODULE_DEVICE_TABLE(i2c, bt866_id); 277 278static struct v4l2_i2c_driver_data v4l2_i2c_data = { 279 .name = "bt866", 280 .driverid = I2C_DRIVERID_BT866, 281 .command = bt866_command, 282 .probe = bt866_probe, 283 .remove = bt866_remove, 284 .legacy_probe = bt866_legacy_probe, 285 .id_table = bt866_id, 286}; 287