3 adv7175 - adv7175a video encoder driver version 0.0.3
5 Copyright (C) 1998 Dave Perks <dperks@ibm.net>
7 Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
8 Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
9 - some corrections for Pinnacle Systems Inc. DC10plus card.
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/errno.h>
31 #include <linux/kernel.h>
32 #include <linux/major.h>
33 #include <linux/slab.h>
35 #include <linux/pci.h>
36 #include <linux/signal.h>
38 #include <asm/pgtable.h>
40 #include <linux/sched.h>
41 #include <linux/types.h>
43 #include <linux/videodev.h>
44 #include <linux/version.h>
45 #include <asm/uaccess.h>
47 #include <linux/i2c.h>
49 #include <linux/video_encoder.h>
52 #define DEBUG(x...) x /* Debug driver */
57 #define I2C_ADV7175 0xd4
58 #define I2C_ADV7176 0x54
60 #define IF_NAME "adv7175"
62 static char adv7175_name[] = "adv7175";
63 static char adv7176_name[] = "adv7176";
64 static char unknown_name[] = "UNKNOWN";
68 static char *inputs[] = { "pass_through", "play_back", "color_bar" };
69 static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
74 static unsigned short normal_i2c[] = {I2C_ADV7175, I2C_CLIENT_END};
75 static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
76 static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
77 static unsigned short probe_range[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
78 static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
79 static unsigned short ignore_range[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
80 static unsigned short force[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
82 static struct i2c_client_address_data addr_data = {
83 normal_i2c, normal_i2c_range,
87 static struct i2c_client client_template;
90 struct i2c_client *client;
92 unsigned char reg[128];
93 struct semaphore lock;
103 /* ----------------------------------------------------------------------- */
104 // Output filter: S-Video Composite
106 #define MR050 0x11 //0x09
107 #define MR060 0x14 //0x0c
109 //---------------------------------------------------------------------------
117 static const unsigned char init_common[] = {
119 0x00, MR050, /* MR0, PAL enabled */
120 0x01, 0x00, /* MR1 */
121 0x02, 0x0c, /* subc. freq. */
122 0x03, 0x8c, /* subc. freq. */
123 0x04, 0x79, /* subc. freq. */
124 0x05, 0x26, /* subc. freq. */
125 0x06, 0x40, /* subc. phase */
127 0x07, TR0MODE, /* TR0, 16bit */
132 0x0c, TR1CAPT, /* TR1 */
133 0x0d, 0x4f, /* MR2 */
138 0x12, 0x00, /* MR3 */
142 static const unsigned char init_pal[] = {
143 0x00, MR050, /* MR0, PAL enabled */
144 0x01, 0x00, /* MR1 */
145 0x02, 0x0c, /* subc. freq. */
146 0x03, 0x8c, /* subc. freq. */
147 0x04, 0x79, /* subc. freq. */
148 0x05, 0x26, /* subc. freq. */
149 0x06, 0x40, /* subc. phase */
152 static const unsigned char init_ntsc[] = {
153 0x00, MR060, /* MR0, NTSC enabled */
154 0x01, 0x00, /* MR1 */
155 0x02, 0x55, /* subc. freq. */
156 0x03, 0x55, /* subc. freq. */
157 0x04, 0x55, /* subc. freq. */
158 0x05, 0x25, /* subc. freq. */
159 0x06, 0x1a, /* subc. phase */
162 static int adv717x_attach(struct i2c_adapter *adap, int addr, int kind)
164 struct adv7175 *encoder;
165 struct i2c_client *client;
167 int i, x_common=39; /* x is number entries init_common - 1 */
169 printk(KERN_INFO "adv717x: video chip found.\n");
170 client=kmalloc(sizeof(*client), GFP_KERNEL);
173 memset(client, 0, sizeof(*client));
175 client_template.adapter = adap;
176 client_template.addr = addr;
177 memcpy(client, &client_template, sizeof(*client));
179 encoder = kmalloc(sizeof(*encoder), GFP_KERNEL);
180 if (encoder == NULL) {
185 memset(encoder, 0, sizeof(*encoder));
186 if ((encoder->addr == I2C_ADV7175) || (encoder->addr == (I2C_ADV7175 + 2))) {
187 dname = adv7175_name;
188 } else if ((encoder->addr == I2C_ADV7176) || (encoder->addr == (I2C_ADV7176 + 2))) {
189 dname = adv7176_name;
191 // We should never get here!!!
192 dname = unknown_name;
194 strlcpy(client->name, dname, DEVICE_NAME_SIZE);
195 init_MUTEX(&encoder->lock);
196 encoder->client = client;
197 i2c_set_clientdata(client, encoder);
198 encoder->addr = addr;
199 encoder->norm = VIDEO_MODE_PAL;
203 for (i=1; i<x_common; i++) {
204 rv = i2c_smbus_write_byte(client,init_common[i]);
206 printk(KERN_ERR "%s_attach: init error %d\n", client->name, rv);
212 i2c_smbus_write_byte_data(client,0x07, TR0MODE | TR0RST);
213 i2c_smbus_write_byte_data(client,0x07, TR0MODE);
214 i2c_smbus_read_byte_data(client,0x12);
215 printk(KERN_INFO "%s_attach: %s rev. %d at 0x%02x\n",
216 client->name, dname, rv & 1, client->addr);
219 i2c_attach_client(client);
225 int adv717x_probe(struct i2c_adapter *adap)
227 return i2c_probe(adap, &addr_data, adv717x_attach);
231 static int adv717x_detach(struct i2c_client *client)
233 i2c_detach_client(client);
234 kfree(i2c_get_clientdata(client));
239 static int adv717x_command(struct i2c_client *client, unsigned int cmd,
242 struct adv7175 *encoder = i2c_get_clientdata(client);
243 int i, x_ntsc=13, x_pal=13;
244 /* x_ntsc is number of entries in init_ntsc -1 */
245 /* x_pal is number of entries in init_pal -1 */
249 case ENCODER_GET_CAPABILITIES:
251 struct video_encoder_capability *cap = arg;
253 cap->flags = VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC
254 // | VIDEO_ENCODER_SECAM
255 // | VIDEO_ENCODER_CCIR
262 case ENCODER_SET_NORM:
264 int iarg = *(int *) arg;
266 if (encoder->norm != iarg) {
269 case VIDEO_MODE_NTSC:
270 for (i=1; i< x_ntsc; i++)
271 i2c_smbus_write_byte(client, init_ntsc[i]);
272 if (encoder->input == 0)
273 i2c_smbus_write_byte_data(client,0x0d, 0x4f); // Enable genlock
274 i2c_smbus_write_byte_data(client,0x07, TR0MODE | TR0RST);
275 i2c_smbus_write_byte_data(client,0x07, TR0MODE);
279 for (i=1; i< x_pal; i++)
280 i2c_smbus_write_byte(client, init_pal[i]);
281 if (encoder->input == 0)
282 i2c_smbus_write_byte_data(client,0x0d, 0x4f); // Enable genlock
283 i2c_smbus_write_byte_data(client,0x07, TR0MODE | TR0RST);
284 i2c_smbus_write_byte_data(client,0x07, TR0MODE);
287 case VIDEO_MODE_SECAM: // WARNING! ADV7176 does not support SECAM.
288 // This is an attempt to convert SECAM->PAL (typically
289 // it does not work due to genlock: when decoder
290 // is in SECAM and encoder in in PAL the subcarrier
291 // can not be syncronized with horizontal frequency)
292 for (i=1; i< x_pal; i++)
293 i2c_smbus_write_byte(client, init_pal[i]);
294 if (encoder->input == 0)
295 i2c_smbus_write_byte_data(client,0x0d, 0x49); // Disable genlock
296 i2c_smbus_write_byte_data(client,0x07, TR0MODE | TR0RST);
297 i2c_smbus_write_byte_data(client,0x07, TR0MODE);
300 printk(KERN_ERR "%s: illegal norm: %d\n",
306 (KERN_INFO "%s: switched to %s\n",
307 client->name, norms[iarg]));
308 encoder->norm = iarg;
313 case ENCODER_SET_INPUT:
315 int iarg = *(int *) arg;
317 /* RJ: *iarg = 0: input is from SAA7110
318 *iarg = 1: input is from ZR36060
319 *iarg = 2: color bar */
321 if (encoder->input != iarg) {
325 i2c_smbus_write_byte_data(client, 0x01, 0x00);
326 i2c_smbus_write_byte_data(client, 0x0c, TR1CAPT); /* TR1 */
329 i2c_smbus_write_byte_data(client, 0x0d, 0x49); // Disable genlock
331 i2c_smbus_write_byte_data(client, 0x0d, 0x4f); // Enable genlock
332 i2c_smbus_write_byte_data(client, 0x07, TR0MODE | TR0RST);
333 i2c_smbus_write_byte_data(client, 0x07, TR0MODE);
338 i2c_smbus_write_byte_data(client, 0x01, 0x00);
339 i2c_smbus_write_byte_data(client, 0x0c, TR1PLAY); /* TR1 */
340 i2c_smbus_write_byte_data(client, 0x0d, 0x49);
341 i2c_smbus_write_byte_data(client, 0x07, TR0MODE | TR0RST);
342 i2c_smbus_write_byte_data(client, 0x07, TR0MODE);
347 i2c_smbus_write_byte_data(client, 0x01, 0x80);
348 i2c_smbus_write_byte_data(client, 0x0d, 0x49);
349 i2c_smbus_write_byte_data(client, 0x07, TR0MODE | TR0RST);
350 i2c_smbus_write_byte_data(client, 0x07, TR0MODE);
355 printk(KERN_ERR "%s: illegal input: %d\n",
361 (KERN_INFO "%s: switched to %s\n",
362 client->name, inputs[iarg]));
363 encoder->input = iarg;
368 case ENCODER_SET_OUTPUT:
372 /* not much choice of outputs */
379 case ENCODER_ENABLE_OUTPUT:
383 encoder->enable = !!*iarg;
384 i2c_smbus_write_byte_data(client, 0x61,
386 reg[0x61] & 0xbf) | (encoder->
399 /* ----------------------------------------------------------------------- */
401 static struct i2c_driver i2c_driver_adv7175 = {
402 .owner = THIS_MODULE,
403 .name = "adv7175", /* name */
404 .id = I2C_DRIVERID_ADV717x, /* ID */
405 .flags = I2C_DF_NOTIFY, //I2C_ADV7175, I2C_ADV7175 + 3,
406 .attach_adapter = adv717x_probe,
407 .detach_client = adv717x_detach,
408 .command = adv717x_command,
411 static struct i2c_driver i2c_driver_adv7176 = {
412 .owner = THIS_MODULE,
413 .name = "adv7176", /* name */
414 .id = I2C_DRIVERID_ADV717x, /* ID */
415 .flags = I2C_DF_NOTIFY, //I2C_ADV7176, I2C_ADV7176 + 3,
416 .attach_adapter = adv717x_probe,
417 .detach_client = adv717x_detach,
418 .command = adv717x_command,
421 static struct i2c_client client_template = {
422 .driver = &i2c_driver_adv7175,
423 .name = "adv7175_client",
426 static int adv717x_init(void)
428 int res_adv7175 = 0, res_adv7176 = 0;
429 res_adv7175 = i2c_add_driver(&i2c_driver_adv7175);
430 res_adv7176 = i2c_add_driver(&i2c_driver_adv7176);
431 return (res_adv7175 | res_adv7176); // Any idea how to make it better?
434 static void adv717x_exit(void)
436 i2c_del_driver(&i2c_driver_adv7176);
437 i2c_del_driver(&i2c_driver_adv7175);
440 module_init(adv717x_init);
441 module_exit(adv717x_exit);
442 MODULE_LICENSE("GPL");