commented early_printk patch because of rejects.
[linux-flexiantxendom0-3.2.10.git] / drivers / media / video / adv7175.c
1 #define DEBUGLEVEL 0
2 /* 
3     adv7175 - adv7175a video encoder driver version 0.0.3
4
5     Copyright (C) 1998 Dave Perks <dperks@ibm.net>
6
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.
10
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.
15
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.
20
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.
24 */
25
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/errno.h>
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/major.h>
33 #include <linux/slab.h>
34 #include <linux/mm.h>
35 #include <linux/pci.h>
36 #include <linux/signal.h>
37 #include <asm/io.h>
38 #include <asm/pgtable.h>
39 #include <asm/page.h>
40 #include <linux/sched.h>
41 #include <linux/types.h>
42
43 #include <linux/videodev.h>
44 #include <linux/version.h>
45 #include <asm/uaccess.h>
46
47 #include <linux/i2c.h>
48
49 #include <linux/video_encoder.h>
50
51 #if (DEBUGLEVEL > 0)
52 #define DEBUG(x...)  x          /* Debug driver */
53 #else
54 #define DEBUG(x...)
55 #endif
56
57 #define I2C_ADV7175     0xd4
58 #define I2C_ADV7176     0x54
59
60 #define IF_NAME         "adv7175"
61
62 static char adv7175_name[] = "adv7175";
63 static char adv7176_name[] = "adv7176";
64 static char unknown_name[] = "UNKNOWN";
65 char *dname;
66
67 #if (DEBUGLEVEL > 0)
68 static char *inputs[] = { "pass_through", "play_back", "color_bar" };
69 static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
70 #endif
71
72 #define I2C_DELAY   10
73
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};
81
82 static struct i2c_client_address_data addr_data = {
83                                                 normal_i2c, normal_i2c_range,
84                                                 probe, probe_range,
85                                                 ignore, ignore_range,
86                                                 force};
87 static struct i2c_client client_template;
88
89 struct adv7175 {
90         struct i2c_client       *client;
91         int                     addr;
92         unsigned char           reg[128];
93         struct semaphore        lock;
94         int                     norm;
95         int                     input;
96         int                     enable;
97         int                     bright;
98         int                     contrast;
99         int                     hue;
100         int                     sat;
101 };
102
103 /* ----------------------------------------------------------------------- */
104 // Output filter:  S-Video  Composite
105
106 #define MR050       0x11        //0x09
107 #define MR060       0x14        //0x0c
108
109 //---------------------------------------------------------------------------
110
111 #define TR0MODE     0x46
112 #define TR0RST      0x80
113
114 #define TR1CAPT     0x80
115 #define TR1PLAY     0x00
116
117 static const unsigned char init_common[] = {
118
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 */
126
127         0x07, TR0MODE,          /* TR0, 16bit */
128         0x08, 0x21,             /*  */
129         0x09, 0x00,             /*  */
130         0x0a, 0x00,             /*  */
131         0x0b, 0x00,             /*  */
132         0x0c, TR1CAPT,          /* TR1 */
133         0x0d, 0x4f,             /* MR2 */
134         0x0e, 0x00,             /*  */
135         0x0f, 0x00,             /*  */
136         0x10, 0x00,             /*  */
137         0x11, 0x00,             /*  */
138         0x12, 0x00,             /* MR3 */
139         0x24, 0x00,             /*  */
140 };
141
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 */
150 };
151
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 */
160 };
161
162 static int adv717x_attach(struct i2c_adapter *adap, int addr, int kind)
163 {
164         struct adv7175 *encoder;
165         struct  i2c_client      *client;
166         int rv = 0;
167         int i, x_common=39; /* x is number entries init_common - 1 */
168
169         printk(KERN_INFO "adv717x: video chip found.\n");
170         client=kmalloc(sizeof(*client), GFP_KERNEL);
171         if(client == NULL)
172                 return -ENOMEM;
173         memset(client, 0, sizeof(*client));
174
175         client_template.adapter = adap;
176         client_template.addr = addr;
177         memcpy(client, &client_template, sizeof(*client));
178
179         encoder = kmalloc(sizeof(*encoder), GFP_KERNEL);
180         if (encoder == NULL) {
181                 kfree(client);
182                 return -ENOMEM;
183         }
184
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;
190         } else {
191                 // We should never get here!!!
192                 dname = unknown_name;
193         }
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;
200         encoder->input = 0;
201         encoder->enable = 1;
202
203         for (i=1; i<x_common; i++) {
204                 rv = i2c_smbus_write_byte(client,init_common[i]);
205                 if (rv < 0) {
206                         printk(KERN_ERR "%s_attach: init error %d\n", client->name, rv);
207                         break;
208                 }
209         }
210
211         if (rv >= 0) {
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);
217         }
218
219         i2c_attach_client(client);
220
221         return 0;
222 }
223
224 static
225 int adv717x_probe(struct i2c_adapter *adap)
226 {
227         return i2c_probe(adap, &addr_data, adv717x_attach);
228 }
229
230
231 static int adv717x_detach(struct i2c_client *client)
232 {
233         i2c_detach_client(client);
234         kfree(i2c_get_clientdata(client));
235         kfree(client);
236         return 0;
237 }
238
239 static int adv717x_command(struct i2c_client *client, unsigned int cmd,
240                            void *arg)
241 {
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 */
246
247         switch (cmd) {
248
249         case ENCODER_GET_CAPABILITIES:
250                 {
251                         struct video_encoder_capability *cap = arg;
252
253                         cap->flags = VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC
254                             // | VIDEO_ENCODER_SECAM
255                             // | VIDEO_ENCODER_CCIR
256                             ;
257                         cap->inputs = 2;
258                         cap->outputs = 1;
259                 }
260                 break;
261
262         case ENCODER_SET_NORM:
263                 {
264                         int iarg = *(int *) arg;
265
266                         if (encoder->norm != iarg) {
267                                 switch (iarg) {
268
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);
276                                         break;
277
278                                 case VIDEO_MODE_PAL:
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);
285                                         break;
286
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);
298                                         break;
299                                 default:
300                                         printk(KERN_ERR "%s: illegal norm: %d\n",
301                                                client->name, iarg);
302                                         return -EINVAL;
303
304                                 }
305                                 DEBUG(printk
306                                       (KERN_INFO "%s: switched to %s\n",
307                                        client->name, norms[iarg]));
308                                 encoder->norm = iarg;
309                         }
310                 }
311                 break;
312
313         case ENCODER_SET_INPUT:
314                 {
315                         int iarg = *(int *) arg;
316
317                         /* RJ: *iarg = 0: input is from SAA7110
318                            *iarg = 1: input is from ZR36060
319                            *iarg = 2: color bar */
320
321                         if (encoder->input != iarg) {
322                                 switch (iarg) {
323
324                                 case 0:
325                                         i2c_smbus_write_byte_data(client, 0x01, 0x00);
326                                         i2c_smbus_write_byte_data(client, 0x0c, TR1CAPT);       /* TR1 */
327                                         if (encoder->norm ==
328                                             VIDEO_MODE_SECAM)
329                                                 i2c_smbus_write_byte_data(client, 0x0d, 0x49);  // Disable genlock
330                                         else
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);
334                                         //udelay(10);
335                                         break;
336
337                                 case 1:
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);
343                                         //udelay(10);
344                                         break;
345
346                                 case 2:
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);
351                                         //udelay(10);
352                                         break;
353
354                                 default:
355                                         printk(KERN_ERR "%s: illegal input: %d\n",
356                                                client->name, iarg);
357                                         return -EINVAL;
358
359                                 }
360                                 DEBUG(printk
361                                       (KERN_INFO "%s: switched to %s\n",
362                                        client->name, inputs[iarg]));
363                                 encoder->input = iarg;
364                         }
365                 }
366                 break;
367
368         case ENCODER_SET_OUTPUT:
369                 {
370                         int *iarg = arg;
371
372                         /* not much choice of outputs */
373                         if (*iarg != 0) {
374                                 return -EINVAL;
375                         }
376                 }
377                 break;
378
379         case ENCODER_ENABLE_OUTPUT:
380                 {
381                         int *iarg = arg;
382
383                         encoder->enable = !!*iarg;
384                         i2c_smbus_write_byte_data(client, 0x61,
385                                       (encoder->
386                                        reg[0x61] & 0xbf) | (encoder->
387                                                             enable ? 0x00 :
388                                                             0x40));
389                 }
390                 break;
391
392         default:
393                 return -EINVAL;
394         }
395
396         return 0;
397 }
398
399 /* ----------------------------------------------------------------------- */
400
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,
409 };
410
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,
419 };
420
421 static struct i2c_client client_template = {
422         .driver         = &i2c_driver_adv7175,
423         .name           = "adv7175_client",
424 };
425
426 static int adv717x_init(void)
427 {
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?
432 }
433
434 static void adv717x_exit(void)
435 {
436         i2c_del_driver(&i2c_driver_adv7176);
437         i2c_del_driver(&i2c_driver_adv7175);
438 }
439
440 module_init(adv717x_init);
441 module_exit(adv717x_exit);
442 MODULE_LICENSE("GPL");