V4L/DVB (9222): S2API: Add Multiple-frontend on a single adapter support.
[linux-2.6.git] / drivers / media / video / adv7175.c
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/ioctl.h>
30 #include <asm/uaccess.h>
31 #include <linux/i2c.h>
32 #include <linux/i2c-id.h>
33 #include <linux/videodev.h>
34 #include <linux/video_encoder.h>
35 #include <media/v4l2-common.h>
36 #include <media/v4l2-i2c-drv-legacy.h>
37
38 MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
39 MODULE_AUTHOR("Dave Perks");
40 MODULE_LICENSE("GPL");
41
42 static int debug;
43 module_param(debug, int, 0);
44 MODULE_PARM_DESC(debug, "Debug level (0-1)");
45
46 /* ----------------------------------------------------------------------- */
47
48 struct adv7175 {
49         int norm;
50         int input;
51         int enable;
52         int bright;
53         int contrast;
54         int hue;
55         int sat;
56 };
57
58 #define   I2C_ADV7175        0xd4
59 #define   I2C_ADV7176        0x54
60
61 static char *inputs[] = { "pass_through", "play_back", "color_bar" };
62 static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
63
64 /* ----------------------------------------------------------------------- */
65
66 static inline int adv7175_write(struct i2c_client *client, u8 reg, u8 value)
67 {
68         return i2c_smbus_write_byte_data(client, reg, value);
69 }
70
71 static inline int adv7175_read(struct i2c_client *client, u8 reg)
72 {
73         return i2c_smbus_read_byte_data(client, reg);
74 }
75
76 static int adv7175_write_block(struct i2c_client *client,
77                      const u8 *data, unsigned int len)
78 {
79         int ret = -1;
80         u8 reg;
81
82         /* the adv7175 has an autoincrement function, use it if
83          * the adapter understands raw I2C */
84         if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
85                 /* do raw I2C, not smbus compatible */
86                 u8 block_data[32];
87                 int block_len;
88
89                 while (len >= 2) {
90                         block_len = 0;
91                         block_data[block_len++] = reg = data[0];
92                         do {
93                                 block_data[block_len++] = data[1];
94                                 reg++;
95                                 len -= 2;
96                                 data += 2;
97                         } while (len >= 2 && data[0] == reg && block_len < 32);
98                         ret = i2c_master_send(client, block_data, block_len);
99                         if (ret < 0)
100                                 break;
101                 }
102         } else {
103                 /* do some slow I2C emulation kind of thing */
104                 while (len >= 2) {
105                         reg = *data++;
106                         ret = adv7175_write(client, reg, *data++);
107                         if (ret < 0)
108                                 break;
109                         len -= 2;
110                 }
111         }
112
113         return ret;
114 }
115
116 static void set_subcarrier_freq(struct i2c_client *client, int pass_through)
117 {
118         /* for some reason pass_through NTSC needs
119          * a different sub-carrier freq to remain stable. */
120         if (pass_through)
121                 adv7175_write(client, 0x02, 0x00);
122         else
123                 adv7175_write(client, 0x02, 0x55);
124
125         adv7175_write(client, 0x03, 0x55);
126         adv7175_write(client, 0x04, 0x55);
127         adv7175_write(client, 0x05, 0x25);
128 }
129
130 /* ----------------------------------------------------------------------- */
131 /* Output filter:  S-Video  Composite */
132
133 #define MR050       0x11        /* 0x09 */
134 #define MR060       0x14        /* 0x0c */
135
136 /* ----------------------------------------------------------------------- */
137
138 #define TR0MODE     0x46
139 #define TR0RST      0x80
140
141 #define TR1CAPT     0x80
142 #define TR1PLAY     0x00
143
144 static const unsigned char init_common[] = {
145
146         0x00, MR050,            /* MR0, PAL enabled */
147         0x01, 0x00,             /* MR1 */
148         0x02, 0x0c,             /* subc. freq. */
149         0x03, 0x8c,             /* subc. freq. */
150         0x04, 0x79,             /* subc. freq. */
151         0x05, 0x26,             /* subc. freq. */
152         0x06, 0x40,             /* subc. phase */
153
154         0x07, TR0MODE,          /* TR0, 16bit */
155         0x08, 0x21,             /*  */
156         0x09, 0x00,             /*  */
157         0x0a, 0x00,             /*  */
158         0x0b, 0x00,             /*  */
159         0x0c, TR1CAPT,          /* TR1 */
160         0x0d, 0x4f,             /* MR2 */
161         0x0e, 0x00,             /*  */
162         0x0f, 0x00,             /*  */
163         0x10, 0x00,             /*  */
164         0x11, 0x00,             /*  */
165 };
166
167 static const unsigned char init_pal[] = {
168         0x00, MR050,            /* MR0, PAL enabled */
169         0x01, 0x00,             /* MR1 */
170         0x02, 0x0c,             /* subc. freq. */
171         0x03, 0x8c,             /* subc. freq. */
172         0x04, 0x79,             /* subc. freq. */
173         0x05, 0x26,             /* subc. freq. */
174         0x06, 0x40,             /* subc. phase */
175 };
176
177 static const unsigned char init_ntsc[] = {
178         0x00, MR060,            /* MR0, NTSC enabled */
179         0x01, 0x00,             /* MR1 */
180         0x02, 0x55,             /* subc. freq. */
181         0x03, 0x55,             /* subc. freq. */
182         0x04, 0x55,             /* subc. freq. */
183         0x05, 0x25,             /* subc. freq. */
184         0x06, 0x1a,             /* subc. phase */
185 };
186
187 static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
188 {
189         struct adv7175 *encoder = i2c_get_clientdata(client);
190
191         switch (cmd) {
192         case 0:
193                 /* This is just for testing!!! */
194                 adv7175_write_block(client, init_common,
195                                     sizeof(init_common));
196                 adv7175_write(client, 0x07, TR0MODE | TR0RST);
197                 adv7175_write(client, 0x07, TR0MODE);
198                 break;
199
200         case ENCODER_GET_CAPABILITIES:
201         {
202                 struct video_encoder_capability *cap = arg;
203
204                 cap->flags = VIDEO_ENCODER_PAL |
205                              VIDEO_ENCODER_NTSC |
206                              VIDEO_ENCODER_SECAM; /* well, hacky */
207                 cap->inputs = 2;
208                 cap->outputs = 1;
209                 break;
210         }
211
212         case ENCODER_SET_NORM:
213         {
214                 int iarg = *(int *) arg;
215
216                 switch (iarg) {
217                 case VIDEO_MODE_NTSC:
218                         adv7175_write_block(client, init_ntsc,
219                                             sizeof(init_ntsc));
220                         if (encoder->input == 0)
221                                 adv7175_write(client, 0x0d, 0x4f);      // Enable genlock
222                         adv7175_write(client, 0x07, TR0MODE | TR0RST);
223                         adv7175_write(client, 0x07, TR0MODE);
224                         break;
225
226                 case VIDEO_MODE_PAL:
227                         adv7175_write_block(client, init_pal,
228                                             sizeof(init_pal));
229                         if (encoder->input == 0)
230                                 adv7175_write(client, 0x0d, 0x4f);      // Enable genlock
231                         adv7175_write(client, 0x07, TR0MODE | TR0RST);
232                         adv7175_write(client, 0x07, TR0MODE);
233                         break;
234
235                 case VIDEO_MODE_SECAM:  // WARNING! ADV7176 does not support SECAM.
236                         /* This is an attempt to convert
237                          * SECAM->PAL (typically it does not work
238                          * due to genlock: when decoder is in SECAM
239                          * and encoder in in PAL the subcarrier can
240                          * not be syncronized with horizontal
241                          * quency) */
242                         adv7175_write_block(client, init_pal,
243                                             sizeof(init_pal));
244                         if (encoder->input == 0)
245                                 adv7175_write(client, 0x0d, 0x49);      // Disable genlock
246                         adv7175_write(client, 0x07, TR0MODE | TR0RST);
247                         adv7175_write(client, 0x07, TR0MODE);
248                         break;
249                 default:
250                         v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg);
251                         return -EINVAL;
252                 }
253                 v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]);
254                 encoder->norm = iarg;
255                 break;
256         }
257
258         case ENCODER_SET_INPUT:
259         {
260                 int iarg = *(int *) arg;
261
262                 /* RJ: *iarg = 0: input is from SAA7110
263                  *iarg = 1: input is from ZR36060
264                  *iarg = 2: color bar */
265
266                 switch (iarg) {
267                 case 0:
268                         adv7175_write(client, 0x01, 0x00);
269
270                         if (encoder->norm == VIDEO_MODE_NTSC)
271                                 set_subcarrier_freq(client, 1);
272
273                         adv7175_write(client, 0x0c, TR1CAPT);   /* TR1 */
274                         if (encoder->norm == VIDEO_MODE_SECAM)
275                                 adv7175_write(client, 0x0d, 0x49);      // Disable genlock
276                         else
277                                 adv7175_write(client, 0x0d, 0x4f);      // Enable genlock
278                         adv7175_write(client, 0x07, TR0MODE | TR0RST);
279                         adv7175_write(client, 0x07, TR0MODE);
280                         //udelay(10);
281                         break;
282
283                 case 1:
284                         adv7175_write(client, 0x01, 0x00);
285
286                         if (encoder->norm == VIDEO_MODE_NTSC)
287                                 set_subcarrier_freq(client, 0);
288
289                         adv7175_write(client, 0x0c, TR1PLAY);   /* TR1 */
290                         adv7175_write(client, 0x0d, 0x49);
291                         adv7175_write(client, 0x07, TR0MODE | TR0RST);
292                         adv7175_write(client, 0x07, TR0MODE);
293                         /* udelay(10); */
294                         break;
295
296                 case 2:
297                         adv7175_write(client, 0x01, 0x80);
298
299                         if (encoder->norm == VIDEO_MODE_NTSC)
300                                 set_subcarrier_freq(client, 0);
301
302                         adv7175_write(client, 0x0d, 0x49);
303                         adv7175_write(client, 0x07, TR0MODE | TR0RST);
304                         adv7175_write(client, 0x07, TR0MODE);
305                         /* udelay(10); */
306                         break;
307
308                 default:
309                         v4l_dbg(1, debug, client, "illegal input: %d\n", iarg);
310                         return -EINVAL;
311                 }
312                 v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]);
313                 encoder->input = iarg;
314                 break;
315         }
316
317         case ENCODER_SET_OUTPUT:
318         {
319                 int *iarg = arg;
320
321                 /* not much choice of outputs */
322                 if (*iarg != 0)
323                         return -EINVAL;
324                 break;
325         }
326
327         case ENCODER_ENABLE_OUTPUT:
328         {
329                 int *iarg = arg;
330
331                 encoder->enable = !!*iarg;
332                 break;
333         }
334
335         default:
336                 return -EINVAL;
337         }
338
339         return 0;
340 }
341
342 /* ----------------------------------------------------------------------- */
343
344 /*
345  * Generic i2c probe
346  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
347  */
348 static unsigned short normal_i2c[] = {
349         I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1,
350         I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
351         I2C_CLIENT_END
352 };
353
354 I2C_CLIENT_INSMOD;
355
356 static int adv7175_probe(struct i2c_client *client,
357                         const struct i2c_device_id *id)
358 {
359         int i;
360         struct adv7175 *encoder;
361
362         /* Check if the adapter supports the needed features */
363         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
364                 return -ENODEV;
365
366         v4l_info(client, "chip found @ 0x%x (%s)\n",
367                         client->addr << 1, client->adapter->name);
368
369         encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
370         if (encoder == NULL)
371                 return -ENOMEM;
372         encoder->norm = VIDEO_MODE_PAL;
373         encoder->input = 0;
374         encoder->enable = 1;
375         i2c_set_clientdata(client, encoder);
376
377         i = adv7175_write_block(client, init_common, sizeof(init_common));
378         if (i >= 0) {
379                 i = adv7175_write(client, 0x07, TR0MODE | TR0RST);
380                 i = adv7175_write(client, 0x07, TR0MODE);
381                 i = adv7175_read(client, 0x12);
382                 v4l_dbg(1, debug, client, "revision %d\n", i & 1);
383         }
384         if (i < 0)
385                 v4l_dbg(1, debug, client, "init error 0x%x\n", i);
386         return 0;
387 }
388
389 static int adv7175_remove(struct i2c_client *client)
390 {
391         kfree(i2c_get_clientdata(client));
392         return 0;
393 }
394
395 /* ----------------------------------------------------------------------- */
396
397 static const struct i2c_device_id adv7175_id[] = {
398         { "adv7175", 0 },
399         { "adv7176", 0 },
400         { }
401 };
402 MODULE_DEVICE_TABLE(i2c, adv7175_id);
403
404 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
405         .name = "adv7175",
406         .driverid = I2C_DRIVERID_ADV7175,
407         .command = adv7175_command,
408         .probe = adv7175_probe,
409         .remove = adv7175_remove,
410         .id_table = adv7175_id,
411 };