Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.19 507 lines 12 kB view raw
1/* 2 * saa7185 - Philips SAA7185B video encoder driver version 0.0.3 3 * 4 * Copyright (C) 1998 Dave Perks <dperks@ibm.net> 5 * 6 * Slight changes for video timing and attachment output by 7 * Wolfgang Scherr <scherr@net4you.net> 8 * 9 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net> 10 * - moved over to linux>=2.4.x i2c protocol (1/1/2003) 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/pci.h> 37#include <linux/signal.h> 38#include <asm/io.h> 39#include <asm/pgtable.h> 40#include <asm/page.h> 41#include <linux/sched.h> 42#include <linux/types.h> 43 44#include <linux/videodev.h> 45#include <asm/uaccess.h> 46 47MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); 48MODULE_AUTHOR("Dave Perks"); 49MODULE_LICENSE("GPL"); 50 51#include <linux/i2c.h> 52 53#define I2C_NAME(s) (s)->name 54 55#include <linux/video_encoder.h> 56 57static int debug = 0; 58module_param(debug, int, 0); 59MODULE_PARM_DESC(debug, "Debug level (0-1)"); 60 61#define dprintk(num, format, args...) \ 62 do { \ 63 if (debug >= num) \ 64 printk(format, ##args); \ 65 } while (0) 66 67/* ----------------------------------------------------------------------- */ 68 69struct saa7185 { 70 unsigned char reg[128]; 71 72 int norm; 73 int enable; 74 int bright; 75 int contrast; 76 int hue; 77 int sat; 78}; 79 80#define I2C_SAA7185 0x88 81 82/* ----------------------------------------------------------------------- */ 83 84static inline int 85saa7185_read (struct i2c_client *client) 86{ 87 return i2c_smbus_read_byte(client); 88} 89 90static int 91saa7185_write (struct i2c_client *client, 92 u8 reg, 93 u8 value) 94{ 95 struct saa7185 *encoder = i2c_get_clientdata(client); 96 97 dprintk(1, KERN_DEBUG "SAA7185: %02x set to %02x\n", reg, value); 98 encoder->reg[reg] = value; 99 return i2c_smbus_write_byte_data(client, reg, value); 100} 101 102static int 103saa7185_write_block (struct i2c_client *client, 104 const u8 *data, 105 unsigned int len) 106{ 107 int ret = -1; 108 u8 reg; 109 110 /* the adv7175 has an autoincrement function, use it if 111 * the adapter understands raw I2C */ 112 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 113 /* do raw I2C, not smbus compatible */ 114 struct saa7185 *encoder = i2c_get_clientdata(client); 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++] = 123 encoder->reg[reg++] = data[1]; 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 = saa7185_write(client, reg, 137 *data++)) < 0) 138 break; 139 len -= 2; 140 } 141 } 142 143 return ret; 144} 145 146/* ----------------------------------------------------------------------- */ 147 148static const unsigned char init_common[] = { 149 0x3a, 0x0f, /* CBENB=0, V656=0, VY2C=1, 150 * YUV2C=1, MY2C=1, MUV2C=1 */ 151 152 0x42, 0x6b, /* OVLY0=107 */ 153 0x43, 0x00, /* OVLU0=0 white */ 154 0x44, 0x00, /* OVLV0=0 */ 155 0x45, 0x22, /* OVLY1=34 */ 156 0x46, 0xac, /* OVLU1=172 yellow */ 157 0x47, 0x0e, /* OVLV1=14 */ 158 0x48, 0x03, /* OVLY2=3 */ 159 0x49, 0x1d, /* OVLU2=29 cyan */ 160 0x4a, 0xac, /* OVLV2=172 */ 161 0x4b, 0xf0, /* OVLY3=240 */ 162 0x4c, 0xc8, /* OVLU3=200 green */ 163 0x4d, 0xb9, /* OVLV3=185 */ 164 0x4e, 0xd4, /* OVLY4=212 */ 165 0x4f, 0x38, /* OVLU4=56 magenta */ 166 0x50, 0x47, /* OVLV4=71 */ 167 0x51, 0xc1, /* OVLY5=193 */ 168 0x52, 0xe3, /* OVLU5=227 red */ 169 0x53, 0x54, /* OVLV5=84 */ 170 0x54, 0xa3, /* OVLY6=163 */ 171 0x55, 0x54, /* OVLU6=84 blue */ 172 0x56, 0xf2, /* OVLV6=242 */ 173 0x57, 0x90, /* OVLY7=144 */ 174 0x58, 0x00, /* OVLU7=0 black */ 175 0x59, 0x00, /* OVLV7=0 */ 176 177 0x5a, 0x00, /* CHPS=0 */ 178 0x5b, 0x76, /* GAINU=118 */ 179 0x5c, 0xa5, /* GAINV=165 */ 180 0x5d, 0x3c, /* BLCKL=60 */ 181 0x5e, 0x3a, /* BLNNL=58 */ 182 0x5f, 0x3a, /* CCRS=0, BLNVB=58 */ 183 0x60, 0x00, /* NULL */ 184 185 /* 0x61 - 0x66 set according to norm */ 186 187 0x67, 0x00, /* 0 : caption 1st byte odd field */ 188 0x68, 0x00, /* 0 : caption 2nd byte odd field */ 189 0x69, 0x00, /* 0 : caption 1st byte even field */ 190 0x6a, 0x00, /* 0 : caption 2nd byte even field */ 191 192 0x6b, 0x91, /* MODIN=2, PCREF=0, SCCLN=17 */ 193 0x6c, 0x20, /* SRCV1=0, TRCV2=1, ORCV1=0, PRCV1=0, 194 * CBLF=0, ORCV2=0, PRCV2=0 */ 195 0x6d, 0x00, /* SRCM1=0, CCEN=0 */ 196 197 0x6e, 0x0e, /* HTRIG=0x005, approx. centered, at 198 * least for PAL */ 199 0x6f, 0x00, /* HTRIG upper bits */ 200 0x70, 0x20, /* PHRES=0, SBLN=1, VTRIG=0 */ 201 202 /* The following should not be needed */ 203 204 0x71, 0x15, /* BMRQ=0x115 */ 205 0x72, 0x90, /* EMRQ=0x690 */ 206 0x73, 0x61, /* EMRQ=0x690, BMRQ=0x115 */ 207 0x74, 0x00, /* NULL */ 208 0x75, 0x00, /* NULL */ 209 0x76, 0x00, /* NULL */ 210 0x77, 0x15, /* BRCV=0x115 */ 211 0x78, 0x90, /* ERCV=0x690 */ 212 0x79, 0x61, /* ERCV=0x690, BRCV=0x115 */ 213 214 /* Field length controls */ 215 216 0x7a, 0x70, /* FLC=0 */ 217 218 /* The following should not be needed if SBLN = 1 */ 219 220 0x7b, 0x16, /* FAL=22 */ 221 0x7c, 0x35, /* LAL=244 */ 222 0x7d, 0x20, /* LAL=244, FAL=22 */ 223}; 224 225static const unsigned char init_pal[] = { 226 0x61, 0x1e, /* FISE=0, PAL=1, SCBW=1, RTCE=1, 227 * YGS=1, INPI=0, DOWN=0 */ 228 0x62, 0xc8, /* DECTYP=1, BSTA=72 */ 229 0x63, 0xcb, /* FSC0 */ 230 0x64, 0x8a, /* FSC1 */ 231 0x65, 0x09, /* FSC2 */ 232 0x66, 0x2a, /* FSC3 */ 233}; 234 235static const unsigned char init_ntsc[] = { 236 0x61, 0x1d, /* FISE=1, PAL=0, SCBW=1, RTCE=1, 237 * YGS=1, INPI=0, DOWN=0 */ 238 0x62, 0xe6, /* DECTYP=1, BSTA=102 */ 239 0x63, 0x1f, /* FSC0 */ 240 0x64, 0x7c, /* FSC1 */ 241 0x65, 0xf0, /* FSC2 */ 242 0x66, 0x21, /* FSC3 */ 243}; 244 245static int 246saa7185_command (struct i2c_client *client, 247 unsigned int cmd, 248 void *arg) 249{ 250 struct saa7185 *encoder = i2c_get_clientdata(client); 251 252 switch (cmd) { 253 254 case 0: 255 saa7185_write_block(client, init_common, 256 sizeof(init_common)); 257 switch (encoder->norm) { 258 259 case VIDEO_MODE_NTSC: 260 saa7185_write_block(client, init_ntsc, 261 sizeof(init_ntsc)); 262 break; 263 264 case VIDEO_MODE_PAL: 265 saa7185_write_block(client, init_pal, 266 sizeof(init_pal)); 267 break; 268 } 269 270 break; 271 272 case ENCODER_GET_CAPABILITIES: 273 { 274 struct video_encoder_capability *cap = arg; 275 276 cap->flags = 277 VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC | 278 VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR; 279 cap->inputs = 1; 280 cap->outputs = 1; 281 } 282 break; 283 284 case ENCODER_SET_NORM: 285 { 286 int *iarg = arg; 287 288 //saa7185_write_block(client, init_common, sizeof(init_common)); 289 290 switch (*iarg) { 291 292 case VIDEO_MODE_NTSC: 293 saa7185_write_block(client, init_ntsc, 294 sizeof(init_ntsc)); 295 break; 296 297 case VIDEO_MODE_PAL: 298 saa7185_write_block(client, init_pal, 299 sizeof(init_pal)); 300 break; 301 302 case VIDEO_MODE_SECAM: 303 default: 304 return -EINVAL; 305 306 } 307 encoder->norm = *iarg; 308 } 309 break; 310 311 case ENCODER_SET_INPUT: 312 { 313 int *iarg = arg; 314 315 /* RJ: *iarg = 0: input is from SA7111 316 *iarg = 1: input is from ZR36060 */ 317 318 switch (*iarg) { 319 320 case 0: 321 /* Switch RTCE to 1 */ 322 saa7185_write(client, 0x61, 323 (encoder->reg[0x61] & 0xf7) | 0x08); 324 saa7185_write(client, 0x6e, 0x01); 325 break; 326 327 case 1: 328 /* Switch RTCE to 0 */ 329 saa7185_write(client, 0x61, 330 (encoder->reg[0x61] & 0xf7) | 0x00); 331 /* SW: a slight sync problem... */ 332 saa7185_write(client, 0x6e, 0x00); 333 break; 334 335 default: 336 return -EINVAL; 337 338 } 339 } 340 break; 341 342 case ENCODER_SET_OUTPUT: 343 { 344 int *iarg = arg; 345 346 /* not much choice of outputs */ 347 if (*iarg != 0) { 348 return -EINVAL; 349 } 350 } 351 break; 352 353 case ENCODER_ENABLE_OUTPUT: 354 { 355 int *iarg = arg; 356 357 encoder->enable = !!*iarg; 358 saa7185_write(client, 0x61, 359 (encoder->reg[0x61] & 0xbf) | 360 (encoder->enable ? 0x00 : 0x40)); 361 } 362 break; 363 364 default: 365 return -EINVAL; 366 } 367 368 return 0; 369} 370 371/* ----------------------------------------------------------------------- */ 372 373/* 374 * Generic i2c probe 375 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' 376 */ 377static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END }; 378 379static unsigned short ignore = I2C_CLIENT_END; 380 381static struct i2c_client_address_data addr_data = { 382 .normal_i2c = normal_i2c, 383 .probe = &ignore, 384 .ignore = &ignore, 385}; 386 387static struct i2c_driver i2c_driver_saa7185; 388 389static int 390saa7185_detect_client (struct i2c_adapter *adapter, 391 int address, 392 int kind) 393{ 394 int i; 395 struct i2c_client *client; 396 struct saa7185 *encoder; 397 398 dprintk(1, 399 KERN_INFO 400 "saa7185.c: detecting saa7185 client on address 0x%x\n", 401 address << 1); 402 403 /* Check if the adapter supports the needed features */ 404 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 405 return 0; 406 407 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); 408 if (client == 0) 409 return -ENOMEM; 410 client->addr = address; 411 client->adapter = adapter; 412 client->driver = &i2c_driver_saa7185; 413 strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client))); 414 415 encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL); 416 if (encoder == NULL) { 417 kfree(client); 418 return -ENOMEM; 419 } 420 encoder->norm = VIDEO_MODE_NTSC; 421 encoder->enable = 1; 422 i2c_set_clientdata(client, encoder); 423 424 i = i2c_attach_client(client); 425 if (i) { 426 kfree(client); 427 kfree(encoder); 428 return i; 429 } 430 431 i = saa7185_write_block(client, init_common, sizeof(init_common)); 432 if (i >= 0) { 433 i = saa7185_write_block(client, init_ntsc, 434 sizeof(init_ntsc)); 435 } 436 if (i < 0) { 437 dprintk(1, KERN_ERR "%s_attach: init error %d\n", 438 I2C_NAME(client), i); 439 } else { 440 dprintk(1, 441 KERN_INFO 442 "%s_attach: chip version %d at address 0x%x\n", 443 I2C_NAME(client), saa7185_read(client) >> 5, 444 client->addr << 1); 445 } 446 447 return 0; 448} 449 450static int 451saa7185_attach_adapter (struct i2c_adapter *adapter) 452{ 453 dprintk(1, 454 KERN_INFO 455 "saa7185.c: starting probe for adapter %s (0x%x)\n", 456 I2C_NAME(adapter), adapter->id); 457 return i2c_probe(adapter, &addr_data, &saa7185_detect_client); 458} 459 460static int 461saa7185_detach_client (struct i2c_client *client) 462{ 463 struct saa7185 *encoder = i2c_get_clientdata(client); 464 int err; 465 466 err = i2c_detach_client(client); 467 if (err) { 468 return err; 469 } 470 471 saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */ 472 //saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */ 473 474 kfree(encoder); 475 kfree(client); 476 477 return 0; 478} 479 480/* ----------------------------------------------------------------------- */ 481 482static struct i2c_driver i2c_driver_saa7185 = { 483 .driver = { 484 .name = "saa7185", /* name */ 485 }, 486 487 .id = I2C_DRIVERID_SAA7185B, 488 489 .attach_adapter = saa7185_attach_adapter, 490 .detach_client = saa7185_detach_client, 491 .command = saa7185_command, 492}; 493 494static int __init 495saa7185_init (void) 496{ 497 return i2c_add_driver(&i2c_driver_saa7185); 498} 499 500static void __exit 501saa7185_exit (void) 502{ 503 i2c_del_driver(&i2c_driver_saa7185); 504} 505 506module_init(saa7185_init); 507module_exit(saa7185_exit);