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/init.h> 29#include <linux/delay.h> 30#include <linux/errno.h> 31#include <linux/fs.h> 32#include <linux/kernel.h> 33#include <linux/major.h> 34#include <linux/slab.h> 35#include <linux/mm.h> 36#include <linux/signal.h> 37#include <asm/io.h> 38#include <asm/pgtable.h> 39#include <asm/page.h> 40#include <linux/types.h> 41 42#include <linux/videodev.h> 43#include <asm/uaccess.h> 44 45MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); 46MODULE_AUTHOR("Dave Perks"); 47MODULE_LICENSE("GPL"); 48 49#include <linux/i2c.h> 50 51#define I2C_NAME(s) (s)->name 52 53#include <linux/video_encoder.h> 54 55static int debug = 0; 56module_param(debug, int, 0); 57MODULE_PARM_DESC(debug, "Debug level (0-1)"); 58 59#define dprintk(num, format, args...) \ 60 do { \ 61 if (debug >= num) \ 62 printk(format, ##args); \ 63 } while (0) 64 65/* ----------------------------------------------------------------------- */ 66 67struct adv7175 { 68 int norm; 69 int input; 70 int enable; 71 int bright; 72 int contrast; 73 int hue; 74 int sat; 75}; 76 77#define I2C_ADV7175 0xd4 78#define I2C_ADV7176 0x54 79 80static char adv7175_name[] = "adv7175"; 81static char adv7176_name[] = "adv7176"; 82 83static char *inputs[] = { "pass_through", "play_back", "color_bar" }; 84static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" }; 85 86/* ----------------------------------------------------------------------- */ 87 88static inline int 89adv7175_write (struct i2c_client *client, 90 u8 reg, 91 u8 value) 92{ 93 return i2c_smbus_write_byte_data(client, reg, value); 94} 95 96static inline int 97adv7175_read (struct i2c_client *client, 98 u8 reg) 99{ 100 return i2c_smbus_read_byte_data(client, reg); 101} 102 103static int 104adv7175_write_block (struct i2c_client *client, 105 const u8 *data, 106 unsigned int len) 107{ 108 int ret = -1; 109 u8 reg; 110 111 /* the adv7175 has an autoincrement function, use it if 112 * the adapter understands raw I2C */ 113 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 114 /* do raw I2C, not smbus compatible */ 115 u8 block_data[32]; 116 int block_len; 117 118 while (len >= 2) { 119 block_len = 0; 120 block_data[block_len++] = reg = data[0]; 121 do { 122 block_data[block_len++] = data[1]; 123 reg++; 124 len -= 2; 125 data += 2; 126 } while (len >= 2 && data[0] == reg && 127 block_len < 32); 128 if ((ret = i2c_master_send(client, block_data, 129 block_len)) < 0) 130 break; 131 } 132 } else { 133 /* do some slow I2C emulation kind of thing */ 134 while (len >= 2) { 135 reg = *data++; 136 if ((ret = adv7175_write(client, reg, 137 *data++)) < 0) 138 break; 139 len -= 2; 140 } 141 } 142 143 return ret; 144} 145 146static void 147set_subcarrier_freq (struct i2c_client *client, 148 int pass_through) 149{ 150 /* for some reason pass_through NTSC needs 151 * a different sub-carrier freq to remain stable. */ 152 if(pass_through) 153 adv7175_write(client, 0x02, 0x00); 154 else 155 adv7175_write(client, 0x02, 0x55); 156 157 adv7175_write(client, 0x03, 0x55); 158 adv7175_write(client, 0x04, 0x55); 159 adv7175_write(client, 0x05, 0x25); 160} 161 162/* ----------------------------------------------------------------------- */ 163// Output filter: S-Video Composite 164 165#define MR050 0x11 //0x09 166#define MR060 0x14 //0x0c 167 168//--------------------------------------------------------------------------- 169 170#define TR0MODE 0x46 171#define TR0RST 0x80 172 173#define TR1CAPT 0x80 174#define TR1PLAY 0x00 175 176static const unsigned char init_common[] = { 177 178 0x00, MR050, /* MR0, PAL enabled */ 179 0x01, 0x00, /* MR1 */ 180 0x02, 0x0c, /* subc. freq. */ 181 0x03, 0x8c, /* subc. freq. */ 182 0x04, 0x79, /* subc. freq. */ 183 0x05, 0x26, /* subc. freq. */ 184 0x06, 0x40, /* subc. phase */ 185 186 0x07, TR0MODE, /* TR0, 16bit */ 187 0x08, 0x21, /* */ 188 0x09, 0x00, /* */ 189 0x0a, 0x00, /* */ 190 0x0b, 0x00, /* */ 191 0x0c, TR1CAPT, /* TR1 */ 192 0x0d, 0x4f, /* MR2 */ 193 0x0e, 0x00, /* */ 194 0x0f, 0x00, /* */ 195 0x10, 0x00, /* */ 196 0x11, 0x00, /* */ 197}; 198 199static const unsigned char init_pal[] = { 200 0x00, MR050, /* MR0, PAL enabled */ 201 0x01, 0x00, /* MR1 */ 202 0x02, 0x0c, /* subc. freq. */ 203 0x03, 0x8c, /* subc. freq. */ 204 0x04, 0x79, /* subc. freq. */ 205 0x05, 0x26, /* subc. freq. */ 206 0x06, 0x40, /* subc. phase */ 207}; 208 209static const unsigned char init_ntsc[] = { 210 0x00, MR060, /* MR0, NTSC enabled */ 211 0x01, 0x00, /* MR1 */ 212 0x02, 0x55, /* subc. freq. */ 213 0x03, 0x55, /* subc. freq. */ 214 0x04, 0x55, /* subc. freq. */ 215 0x05, 0x25, /* subc. freq. */ 216 0x06, 0x1a, /* subc. phase */ 217}; 218 219static int 220adv7175_command (struct i2c_client *client, 221 unsigned int cmd, 222 void *arg) 223{ 224 struct adv7175 *encoder = i2c_get_clientdata(client); 225 226 switch (cmd) { 227 228 case 0: 229 /* This is just for testing!!! */ 230 adv7175_write_block(client, init_common, 231 sizeof(init_common)); 232 adv7175_write(client, 0x07, TR0MODE | TR0RST); 233 adv7175_write(client, 0x07, TR0MODE); 234 break; 235 236 case ENCODER_GET_CAPABILITIES: 237 { 238 struct video_encoder_capability *cap = arg; 239 240 cap->flags = VIDEO_ENCODER_PAL | 241 VIDEO_ENCODER_NTSC | 242 VIDEO_ENCODER_SECAM; /* well, hacky */ 243 cap->inputs = 2; 244 cap->outputs = 1; 245 } 246 break; 247 248 case ENCODER_SET_NORM: 249 { 250 int iarg = *(int *) arg; 251 252 switch (iarg) { 253 254 case VIDEO_MODE_NTSC: 255 adv7175_write_block(client, init_ntsc, 256 sizeof(init_ntsc)); 257 if (encoder->input == 0) 258 adv7175_write(client, 0x0d, 0x4f); // Enable genlock 259 adv7175_write(client, 0x07, TR0MODE | TR0RST); 260 adv7175_write(client, 0x07, TR0MODE); 261 break; 262 263 case VIDEO_MODE_PAL: 264 adv7175_write_block(client, init_pal, 265 sizeof(init_pal)); 266 if (encoder->input == 0) 267 adv7175_write(client, 0x0d, 0x4f); // Enable genlock 268 adv7175_write(client, 0x07, TR0MODE | TR0RST); 269 adv7175_write(client, 0x07, TR0MODE); 270 break; 271 272 case VIDEO_MODE_SECAM: // WARNING! ADV7176 does not support SECAM. 273 /* This is an attempt to convert 274 * SECAM->PAL (typically it does not work 275 * due to genlock: when decoder is in SECAM 276 * and encoder in in PAL the subcarrier can 277 * not be syncronized with horizontal 278 * quency) */ 279 adv7175_write_block(client, init_pal, 280 sizeof(init_pal)); 281 if (encoder->input == 0) 282 adv7175_write(client, 0x0d, 0x49); // Disable genlock 283 adv7175_write(client, 0x07, TR0MODE | TR0RST); 284 adv7175_write(client, 0x07, TR0MODE); 285 break; 286 default: 287 dprintk(1, KERN_ERR "%s: illegal norm: %d\n", 288 I2C_NAME(client), iarg); 289 return -EINVAL; 290 291 } 292 dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client), 293 norms[iarg]); 294 encoder->norm = iarg; 295 } 296 break; 297 298 case ENCODER_SET_INPUT: 299 { 300 int iarg = *(int *) arg; 301 302 /* RJ: *iarg = 0: input is from SAA7110 303 *iarg = 1: input is from ZR36060 304 *iarg = 2: color bar */ 305 306 switch (iarg) { 307 308 case 0: 309 adv7175_write(client, 0x01, 0x00); 310 311 if (encoder->norm == VIDEO_MODE_NTSC) 312 set_subcarrier_freq(client, 1); 313 314 adv7175_write(client, 0x0c, TR1CAPT); /* TR1 */ 315 if (encoder->norm == VIDEO_MODE_SECAM) 316 adv7175_write(client, 0x0d, 0x49); // Disable genlock 317 else 318 adv7175_write(client, 0x0d, 0x4f); // Enable genlock 319 adv7175_write(client, 0x07, TR0MODE | TR0RST); 320 adv7175_write(client, 0x07, TR0MODE); 321 //udelay(10); 322 break; 323 324 case 1: 325 adv7175_write(client, 0x01, 0x00); 326 327 if (encoder->norm == VIDEO_MODE_NTSC) 328 set_subcarrier_freq(client, 0); 329 330 adv7175_write(client, 0x0c, TR1PLAY); /* TR1 */ 331 adv7175_write(client, 0x0d, 0x49); 332 adv7175_write(client, 0x07, TR0MODE | TR0RST); 333 adv7175_write(client, 0x07, TR0MODE); 334 //udelay(10); 335 break; 336 337 case 2: 338 adv7175_write(client, 0x01, 0x80); 339 340 if (encoder->norm == VIDEO_MODE_NTSC) 341 set_subcarrier_freq(client, 0); 342 343 adv7175_write(client, 0x0d, 0x49); 344 adv7175_write(client, 0x07, TR0MODE | TR0RST); 345 adv7175_write(client, 0x07, TR0MODE); 346 //udelay(10); 347 break; 348 349 default: 350 dprintk(1, KERN_ERR "%s: illegal input: %d\n", 351 I2C_NAME(client), iarg); 352 return -EINVAL; 353 354 } 355 dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client), 356 inputs[iarg]); 357 encoder->input = iarg; 358 } 359 break; 360 361 case ENCODER_SET_OUTPUT: 362 { 363 int *iarg = arg; 364 365 /* not much choice of outputs */ 366 if (*iarg != 0) { 367 return -EINVAL; 368 } 369 } 370 break; 371 372 case ENCODER_ENABLE_OUTPUT: 373 { 374 int *iarg = arg; 375 376 encoder->enable = !!*iarg; 377 } 378 break; 379 380 default: 381 return -EINVAL; 382 } 383 384 return 0; 385} 386 387/* ----------------------------------------------------------------------- */ 388 389/* 390 * Generic i2c probe 391 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' 392 */ 393static unsigned short normal_i2c[] = 394 { I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, 395 I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, 396 I2C_CLIENT_END 397}; 398 399static unsigned short ignore = I2C_CLIENT_END; 400 401static struct i2c_client_address_data addr_data = { 402 .normal_i2c = normal_i2c, 403 .probe = &ignore, 404 .ignore = &ignore, 405}; 406 407static struct i2c_driver i2c_driver_adv7175; 408 409static int 410adv7175_detect_client (struct i2c_adapter *adapter, 411 int address, 412 int kind) 413{ 414 int i; 415 struct i2c_client *client; 416 struct adv7175 *encoder; 417 char *dname; 418 419 dprintk(1, 420 KERN_INFO 421 "adv7175.c: detecting adv7175 client on address 0x%x\n", 422 address << 1); 423 424 /* Check if the adapter supports the needed features */ 425 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 426 return 0; 427 428 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); 429 if (client == 0) 430 return -ENOMEM; 431 client->addr = address; 432 client->adapter = adapter; 433 client->driver = &i2c_driver_adv7175; 434 if ((client->addr == I2C_ADV7175 >> 1) || 435 (client->addr == (I2C_ADV7175 >> 1) + 1)) { 436 dname = adv7175_name; 437 } else if ((client->addr == I2C_ADV7176 >> 1) || 438 (client->addr == (I2C_ADV7176 >> 1) + 1)) { 439 dname = adv7176_name; 440 } else { 441 /* We should never get here!!! */ 442 kfree(client); 443 return 0; 444 } 445 strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client))); 446 447 encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); 448 if (encoder == NULL) { 449 kfree(client); 450 return -ENOMEM; 451 } 452 encoder->norm = VIDEO_MODE_PAL; 453 encoder->input = 0; 454 encoder->enable = 1; 455 i2c_set_clientdata(client, encoder); 456 457 i = i2c_attach_client(client); 458 if (i) { 459 kfree(client); 460 kfree(encoder); 461 return i; 462 } 463 464 i = adv7175_write_block(client, init_common, sizeof(init_common)); 465 if (i >= 0) { 466 i = adv7175_write(client, 0x07, TR0MODE | TR0RST); 467 i = adv7175_write(client, 0x07, TR0MODE); 468 i = adv7175_read(client, 0x12); 469 dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%x\n", 470 I2C_NAME(client), i & 1, client->addr << 1); 471 } 472 if (i < 0) { 473 dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n", 474 I2C_NAME(client), i); 475 } 476 477 return 0; 478} 479 480static int 481adv7175_attach_adapter (struct i2c_adapter *adapter) 482{ 483 dprintk(1, 484 KERN_INFO 485 "adv7175.c: starting probe for adapter %s (0x%x)\n", 486 I2C_NAME(adapter), adapter->id); 487 return i2c_probe(adapter, &addr_data, &adv7175_detect_client); 488} 489 490static int 491adv7175_detach_client (struct i2c_client *client) 492{ 493 struct adv7175 *encoder = i2c_get_clientdata(client); 494 int err; 495 496 err = i2c_detach_client(client); 497 if (err) { 498 return err; 499 } 500 501 kfree(encoder); 502 kfree(client); 503 504 return 0; 505} 506 507/* ----------------------------------------------------------------------- */ 508 509static struct i2c_driver i2c_driver_adv7175 = { 510 .driver = { 511 .name = "adv7175", /* name */ 512 }, 513 514 .id = I2C_DRIVERID_ADV7175, 515 516 .attach_adapter = adv7175_attach_adapter, 517 .detach_client = adv7175_detach_client, 518 .command = adv7175_command, 519}; 520 521static int __init 522adv7175_init (void) 523{ 524 return i2c_add_driver(&i2c_driver_adv7175); 525} 526 527static void __exit 528adv7175_exit (void) 529{ 530 i2c_del_driver(&i2c_driver_adv7175); 531} 532 533module_init(adv7175_init); 534module_exit(adv7175_exit); 535