1/* 2 * adv7175 - adv7175a video encoder driver version 0.0.3 3 * 4 * Copyright (C) 1998 Dave Perks <dperks@ibm.net> 5 * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net> 6 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx> 7 * - some corrections for Pinnacle Systems Inc. DC10plus card. 8 * 9 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net> 10 * - moved over to linux>=2.4.x i2c protocol (9/9/2002) 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 */ 26 27#include <linux/module.h> 28#include <linux/types.h> 29#include <linux/slab.h> 30#include <linux/ioctl.h> 31#include <asm/uaccess.h> 32#include <linux/i2c.h> 33#include <linux/i2c-id.h> 34#include <linux/videodev2.h> 35#include <media/v4l2-device.h> 36#include <media/v4l2-chip-ident.h> 37#include <media/v4l2-i2c-drv.h> 38 39MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); 40MODULE_AUTHOR("Dave Perks"); 41MODULE_LICENSE("GPL"); 42 43#define I2C_ADV7175 0xd4 44#define I2C_ADV7176 0x54 45 46 47static int debug; 48module_param(debug, int, 0); 49MODULE_PARM_DESC(debug, "Debug level (0-1)"); 50 51/* ----------------------------------------------------------------------- */ 52 53struct adv7175 { 54 struct v4l2_subdev sd; 55 v4l2_std_id norm; 56 int input; 57}; 58 59static inline struct adv7175 *to_adv7175(struct v4l2_subdev *sd) 60{ 61 return container_of(sd, struct adv7175, sd); 62} 63 64static char *inputs[] = { "pass_through", "play_back", "color_bar" }; 65 66/* ----------------------------------------------------------------------- */ 67 68static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value) 69{ 70 struct i2c_client *client = v4l2_get_subdevdata(sd); 71 72 return i2c_smbus_write_byte_data(client, reg, value); 73} 74 75static inline int adv7175_read(struct v4l2_subdev *sd, u8 reg) 76{ 77 struct i2c_client *client = v4l2_get_subdevdata(sd); 78 79 return i2c_smbus_read_byte_data(client, reg); 80} 81 82static int adv7175_write_block(struct v4l2_subdev *sd, 83 const u8 *data, unsigned int len) 84{ 85 struct i2c_client *client = v4l2_get_subdevdata(sd); 86 int ret = -1; 87 u8 reg; 88 89 /* the adv7175 has an autoincrement function, use it if 90 * the adapter understands raw I2C */ 91 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 92 /* do raw I2C, not smbus compatible */ 93 u8 block_data[32]; 94 int block_len; 95 96 while (len >= 2) { 97 block_len = 0; 98 block_data[block_len++] = reg = data[0]; 99 do { 100 block_data[block_len++] = data[1]; 101 reg++; 102 len -= 2; 103 data += 2; 104 } while (len >= 2 && data[0] == reg && block_len < 32); 105 ret = i2c_master_send(client, block_data, block_len); 106 if (ret < 0) 107 break; 108 } 109 } else { 110 /* do some slow I2C emulation kind of thing */ 111 while (len >= 2) { 112 reg = *data++; 113 ret = adv7175_write(sd, reg, *data++); 114 if (ret < 0) 115 break; 116 len -= 2; 117 } 118 } 119 120 return ret; 121} 122 123static void set_subcarrier_freq(struct v4l2_subdev *sd, int pass_through) 124{ 125 /* for some reason pass_through NTSC needs 126 * a different sub-carrier freq to remain stable. */ 127 if (pass_through) 128 adv7175_write(sd, 0x02, 0x00); 129 else 130 adv7175_write(sd, 0x02, 0x55); 131 132 adv7175_write(sd, 0x03, 0x55); 133 adv7175_write(sd, 0x04, 0x55); 134 adv7175_write(sd, 0x05, 0x25); 135} 136 137/* ----------------------------------------------------------------------- */ 138/* Output filter: S-Video Composite */ 139 140#define MR050 0x11 /* 0x09 */ 141#define MR060 0x14 /* 0x0c */ 142 143/* ----------------------------------------------------------------------- */ 144 145#define TR0MODE 0x46 146#define TR0RST 0x80 147 148#define TR1CAPT 0x80 149#define TR1PLAY 0x00 150 151static const unsigned char init_common[] = { 152 153 0x00, MR050, /* MR0, PAL enabled */ 154 0x01, 0x00, /* MR1 */ 155 0x02, 0x0c, /* subc. freq. */ 156 0x03, 0x8c, /* subc. freq. */ 157 0x04, 0x79, /* subc. freq. */ 158 0x05, 0x26, /* subc. freq. */ 159 0x06, 0x40, /* subc. phase */ 160 161 0x07, TR0MODE, /* TR0, 16bit */ 162 0x08, 0x21, /* */ 163 0x09, 0x00, /* */ 164 0x0a, 0x00, /* */ 165 0x0b, 0x00, /* */ 166 0x0c, TR1CAPT, /* TR1 */ 167 0x0d, 0x4f, /* MR2 */ 168 0x0e, 0x00, /* */ 169 0x0f, 0x00, /* */ 170 0x10, 0x00, /* */ 171 0x11, 0x00, /* */ 172}; 173 174static const unsigned char init_pal[] = { 175 0x00, MR050, /* MR0, PAL enabled */ 176 0x01, 0x00, /* MR1 */ 177 0x02, 0x0c, /* subc. freq. */ 178 0x03, 0x8c, /* subc. freq. */ 179 0x04, 0x79, /* subc. freq. */ 180 0x05, 0x26, /* subc. freq. */ 181 0x06, 0x40, /* subc. phase */ 182}; 183 184static const unsigned char init_ntsc[] = { 185 0x00, MR060, /* MR0, NTSC enabled */ 186 0x01, 0x00, /* MR1 */ 187 0x02, 0x55, /* subc. freq. */ 188 0x03, 0x55, /* subc. freq. */ 189 0x04, 0x55, /* subc. freq. */ 190 0x05, 0x25, /* subc. freq. */ 191 0x06, 0x1a, /* subc. phase */ 192}; 193 194static int adv7175_init(struct v4l2_subdev *sd, u32 val) 195{ 196 /* This is just for testing!!! */ 197 adv7175_write_block(sd, init_common, sizeof(init_common)); 198 adv7175_write(sd, 0x07, TR0MODE | TR0RST); 199 adv7175_write(sd, 0x07, TR0MODE); 200 return 0; 201} 202 203static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) 204{ 205 struct adv7175 *encoder = to_adv7175(sd); 206 207 if (std & V4L2_STD_NTSC) { 208 adv7175_write_block(sd, init_ntsc, sizeof(init_ntsc)); 209 if (encoder->input == 0) 210 adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */ 211 adv7175_write(sd, 0x07, TR0MODE | TR0RST); 212 adv7175_write(sd, 0x07, TR0MODE); 213 } else if (std & V4L2_STD_PAL) { 214 adv7175_write_block(sd, init_pal, sizeof(init_pal)); 215 if (encoder->input == 0) 216 adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */ 217 adv7175_write(sd, 0x07, TR0MODE | TR0RST); 218 adv7175_write(sd, 0x07, TR0MODE); 219 } else if (std & V4L2_STD_SECAM) { 220 /* This is an attempt to convert 221 * SECAM->PAL (typically it does not work 222 * due to genlock: when decoder is in SECAM 223 * and encoder in in PAL the subcarrier can 224 * not be syncronized with horizontal 225 * quency) */ 226 adv7175_write_block(sd, init_pal, sizeof(init_pal)); 227 if (encoder->input == 0) 228 adv7175_write(sd, 0x0d, 0x49); /* Disable genlock */ 229 adv7175_write(sd, 0x07, TR0MODE | TR0RST); 230 adv7175_write(sd, 0x07, TR0MODE); 231 } else { 232 v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", 233 (unsigned long long)std); 234 return -EINVAL; 235 } 236 v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std); 237 encoder->norm = std; 238 return 0; 239} 240 241static int adv7175_s_routing(struct v4l2_subdev *sd, 242 u32 input, u32 output, u32 config) 243{ 244 struct adv7175 *encoder = to_adv7175(sd); 245 246 /* RJ: input = 0: input is from decoder 247 input = 1: input is from ZR36060 248 input = 2: color bar */ 249 250 switch (input) { 251 case 0: 252 adv7175_write(sd, 0x01, 0x00); 253 254 if (encoder->norm & V4L2_STD_NTSC) 255 set_subcarrier_freq(sd, 1); 256 257 adv7175_write(sd, 0x0c, TR1CAPT); /* TR1 */ 258 if (encoder->norm & V4L2_STD_SECAM) 259 adv7175_write(sd, 0x0d, 0x49); /* Disable genlock */ 260 else 261 adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */ 262 adv7175_write(sd, 0x07, TR0MODE | TR0RST); 263 adv7175_write(sd, 0x07, TR0MODE); 264 /*udelay(10);*/ 265 break; 266 267 case 1: 268 adv7175_write(sd, 0x01, 0x00); 269 270 if (encoder->norm & V4L2_STD_NTSC) 271 set_subcarrier_freq(sd, 0); 272 273 adv7175_write(sd, 0x0c, TR1PLAY); /* TR1 */ 274 adv7175_write(sd, 0x0d, 0x49); 275 adv7175_write(sd, 0x07, TR0MODE | TR0RST); 276 adv7175_write(sd, 0x07, TR0MODE); 277 /* udelay(10); */ 278 break; 279 280 case 2: 281 adv7175_write(sd, 0x01, 0x80); 282 283 if (encoder->norm & V4L2_STD_NTSC) 284 set_subcarrier_freq(sd, 0); 285 286 adv7175_write(sd, 0x0d, 0x49); 287 adv7175_write(sd, 0x07, TR0MODE | TR0RST); 288 adv7175_write(sd, 0x07, TR0MODE); 289 /* udelay(10); */ 290 break; 291 292 default: 293 v4l2_dbg(1, debug, sd, "illegal input: %d\n", input); 294 return -EINVAL; 295 } 296 v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[input]); 297 encoder->input = input; 298 return 0; 299} 300 301static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) 302{ 303 struct i2c_client *client = v4l2_get_subdevdata(sd); 304 305 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0); 306} 307 308/* ----------------------------------------------------------------------- */ 309 310static const struct v4l2_subdev_core_ops adv7175_core_ops = { 311 .g_chip_ident = adv7175_g_chip_ident, 312 .init = adv7175_init, 313}; 314 315static const struct v4l2_subdev_video_ops adv7175_video_ops = { 316 .s_std_output = adv7175_s_std_output, 317 .s_routing = adv7175_s_routing, 318}; 319 320static const struct v4l2_subdev_ops adv7175_ops = { 321 .core = &adv7175_core_ops, 322 .video = &adv7175_video_ops, 323}; 324 325/* ----------------------------------------------------------------------- */ 326 327static int adv7175_probe(struct i2c_client *client, 328 const struct i2c_device_id *id) 329{ 330 int i; 331 struct adv7175 *encoder; 332 struct v4l2_subdev *sd; 333 334 /* Check if the adapter supports the needed features */ 335 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 336 return -ENODEV; 337 338 v4l_info(client, "chip found @ 0x%x (%s)\n", 339 client->addr << 1, client->adapter->name); 340 341 encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); 342 if (encoder == NULL) 343 return -ENOMEM; 344 sd = &encoder->sd; 345 v4l2_i2c_subdev_init(sd, client, &adv7175_ops); 346 encoder->norm = V4L2_STD_NTSC; 347 encoder->input = 0; 348 349 i = adv7175_write_block(sd, init_common, sizeof(init_common)); 350 if (i >= 0) { 351 i = adv7175_write(sd, 0x07, TR0MODE | TR0RST); 352 i = adv7175_write(sd, 0x07, TR0MODE); 353 i = adv7175_read(sd, 0x12); 354 v4l2_dbg(1, debug, sd, "revision %d\n", i & 1); 355 } 356 if (i < 0) 357 v4l2_dbg(1, debug, sd, "init error 0x%x\n", i); 358 return 0; 359} 360 361static int adv7175_remove(struct i2c_client *client) 362{ 363 struct v4l2_subdev *sd = i2c_get_clientdata(client); 364 365 v4l2_device_unregister_subdev(sd); 366 kfree(to_adv7175(sd)); 367 return 0; 368} 369 370/* ----------------------------------------------------------------------- */ 371 372static const struct i2c_device_id adv7175_id[] = { 373 { "adv7175", 0 }, 374 { "adv7176", 0 }, 375 { } 376}; 377MODULE_DEVICE_TABLE(i2c, adv7175_id); 378 379static struct v4l2_i2c_driver_data v4l2_i2c_data = { 380 .name = "adv7175", 381 .probe = adv7175_probe, 382 .remove = adv7175_remove, 383 .id_table = adv7175_id, 384}; 385