Merge commit 'v2.6.28-rc8' into x86/doc
[linux-2.6] / drivers / media / video / bt856.c
1 /*
2  * bt856 - BT856A Digital Video Encoder (Rockwell Part)
3  *
4  * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
5  * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
6  *
7  * Modifications for LML33/DC10plus unified driver
8  * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
9  *
10  * This code was modify/ported from the saa7111 driver written
11  * by Dave Perks.
12  *
13  * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
14  *   - moved over to linux>=2.4.x i2c protocol (9/9/2002)
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29  */
30
31 #include <linux/module.h>
32 #include <linux/types.h>
33 #include <linux/ioctl.h>
34 #include <asm/uaccess.h>
35 #include <linux/i2c.h>
36 #include <linux/i2c-id.h>
37 #include <linux/videodev.h>
38 #include <linux/video_encoder.h>
39 #include <media/v4l2-common.h>
40 #include <media/v4l2-i2c-drv-legacy.h>
41
42 MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
43 MODULE_AUTHOR("Mike Bernson & Dave Perks");
44 MODULE_LICENSE("GPL");
45
46 static int debug;
47 module_param(debug, int, 0);
48 MODULE_PARM_DESC(debug, "Debug level (0-1)");
49
50 /* ----------------------------------------------------------------------- */
51
52 #define BT856_REG_OFFSET        0xDA
53 #define BT856_NR_REG            6
54
55 struct bt856 {
56         unsigned char reg[BT856_NR_REG];
57
58         int norm;
59         int enable;
60 };
61
62 /* ----------------------------------------------------------------------- */
63
64 static inline int bt856_write(struct i2c_client *client, u8 reg, u8 value)
65 {
66         struct bt856 *encoder = i2c_get_clientdata(client);
67
68         encoder->reg[reg - BT856_REG_OFFSET] = value;
69         return i2c_smbus_write_byte_data(client, reg, value);
70 }
71
72 static inline int bt856_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value)
73 {
74         struct bt856 *encoder = i2c_get_clientdata(client);
75
76         return bt856_write(client, reg,
77                 (encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
78                                 (value ? (1 << bit) : 0));
79 }
80
81 static void bt856_dump(struct i2c_client *client)
82 {
83         int i;
84         struct bt856 *encoder = i2c_get_clientdata(client);
85
86         v4l_info(client, "register dump:\n");
87         for (i = 0; i < BT856_NR_REG; i += 2)
88                 printk(KERN_CONT " %02x", encoder->reg[i]);
89         printk(KERN_CONT "\n");
90 }
91
92 /* ----------------------------------------------------------------------- */
93
94 static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
95 {
96         struct bt856 *encoder = i2c_get_clientdata(client);
97
98         switch (cmd) {
99         case 0:
100                 /* This is just for testing!!! */
101                 v4l_dbg(1, debug, client, "init\n");
102                 bt856_write(client, 0xdc, 0x18);
103                 bt856_write(client, 0xda, 0);
104                 bt856_write(client, 0xde, 0);
105
106                 bt856_setbit(client, 0xdc, 3, 1);
107                 //bt856_setbit(client, 0xdc, 6, 0);
108                 bt856_setbit(client, 0xdc, 4, 1);
109
110                 switch (encoder->norm) {
111                 case VIDEO_MODE_NTSC:
112                         bt856_setbit(client, 0xdc, 2, 0);
113                         break;
114
115                 case VIDEO_MODE_PAL:
116                         bt856_setbit(client, 0xdc, 2, 1);
117                         break;
118                 }
119
120                 bt856_setbit(client, 0xdc, 1, 1);
121                 bt856_setbit(client, 0xde, 4, 0);
122                 bt856_setbit(client, 0xde, 3, 1);
123                 if (debug != 0)
124                         bt856_dump(client);
125                 break;
126
127         case ENCODER_GET_CAPABILITIES:
128         {
129                 struct video_encoder_capability *cap = arg;
130
131                 v4l_dbg(1, debug, client, "get capabilities\n");
132
133                 cap->flags = VIDEO_ENCODER_PAL |
134                              VIDEO_ENCODER_NTSC |
135                              VIDEO_ENCODER_CCIR;
136                 cap->inputs = 2;
137                 cap->outputs = 1;
138                 break;
139         }
140
141         case ENCODER_SET_NORM:
142         {
143                 int *iarg = arg;
144
145                 v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
146
147                 switch (*iarg) {
148                 case VIDEO_MODE_NTSC:
149                         bt856_setbit(client, 0xdc, 2, 0);
150                         break;
151
152                 case VIDEO_MODE_PAL:
153                         bt856_setbit(client, 0xdc, 2, 1);
154                         bt856_setbit(client, 0xda, 0, 0);
155                         //bt856_setbit(client, 0xda, 0, 1);
156                         break;
157
158                 default:
159                         return -EINVAL;
160                 }
161                 encoder->norm = *iarg;
162                 if (debug != 0)
163                         bt856_dump(client);
164                 break;
165         }
166
167         case ENCODER_SET_INPUT:
168         {
169                 int *iarg = arg;
170
171                 v4l_dbg(1, debug, client, "set input %d\n", *iarg);
172
173                 /* We only have video bus.
174                  * iarg = 0: input is from bt819
175                  * iarg = 1: input is from ZR36060 */
176                 switch (*iarg) {
177                 case 0:
178                         bt856_setbit(client, 0xde, 4, 0);
179                         bt856_setbit(client, 0xde, 3, 1);
180                         bt856_setbit(client, 0xdc, 3, 1);
181                         bt856_setbit(client, 0xdc, 6, 0);
182                         break;
183                 case 1:
184                         bt856_setbit(client, 0xde, 4, 0);
185                         bt856_setbit(client, 0xde, 3, 1);
186                         bt856_setbit(client, 0xdc, 3, 1);
187                         bt856_setbit(client, 0xdc, 6, 1);
188                         break;
189                 case 2: // Color bar
190                         bt856_setbit(client, 0xdc, 3, 0);
191                         bt856_setbit(client, 0xde, 4, 1);
192                         break;
193                 default:
194                         return -EINVAL;
195                 }
196
197                 if (debug != 0)
198                         bt856_dump(client);
199                 break;
200         }
201
202         case ENCODER_SET_OUTPUT:
203         {
204                 int *iarg = arg;
205
206                 v4l_dbg(1, debug, client, "set output %d\n", *iarg);
207
208                 /* not much choice of outputs */
209                 if (*iarg != 0)
210                         return -EINVAL;
211                 break;
212         }
213
214         case ENCODER_ENABLE_OUTPUT:
215         {
216                 int *iarg = arg;
217
218                 encoder->enable = !!*iarg;
219
220                 v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
221                 break;
222         }
223
224         default:
225                 return -EINVAL;
226         }
227
228         return 0;
229 }
230
231 /* ----------------------------------------------------------------------- */
232
233 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
234
235 I2C_CLIENT_INSMOD;
236
237 static int bt856_probe(struct i2c_client *client,
238                         const struct i2c_device_id *id)
239 {
240         struct bt856 *encoder;
241
242         /* Check if the adapter supports the needed features */
243         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
244                 return -ENODEV;
245
246         v4l_info(client, "chip found @ 0x%x (%s)\n",
247                         client->addr << 1, client->adapter->name);
248
249         encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
250         if (encoder == NULL)
251                 return -ENOMEM;
252         encoder->norm = VIDEO_MODE_NTSC;
253         encoder->enable = 1;
254         i2c_set_clientdata(client, encoder);
255
256         bt856_write(client, 0xdc, 0x18);
257         bt856_write(client, 0xda, 0);
258         bt856_write(client, 0xde, 0);
259
260         bt856_setbit(client, 0xdc, 3, 1);
261         //bt856_setbit(client, 0xdc, 6, 0);
262         bt856_setbit(client, 0xdc, 4, 1);
263
264         switch (encoder->norm) {
265
266         case VIDEO_MODE_NTSC:
267                 bt856_setbit(client, 0xdc, 2, 0);
268                 break;
269
270         case VIDEO_MODE_PAL:
271                 bt856_setbit(client, 0xdc, 2, 1);
272                 break;
273         }
274
275         bt856_setbit(client, 0xdc, 1, 1);
276         bt856_setbit(client, 0xde, 4, 0);
277         bt856_setbit(client, 0xde, 3, 1);
278
279         if (debug != 0)
280                 bt856_dump(client);
281         return 0;
282 }
283
284 static int bt856_remove(struct i2c_client *client)
285 {
286         kfree(i2c_get_clientdata(client));
287         return 0;
288 }
289
290 static const struct i2c_device_id bt856_id[] = {
291         { "bt856", 0 },
292         { }
293 };
294 MODULE_DEVICE_TABLE(i2c, bt856_id);
295
296 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
297         .name = "bt856",
298         .driverid = I2C_DRIVERID_BT856,
299         .command = bt856_command,
300         .probe = bt856_probe,
301         .remove = bt856_remove,
302         .id_table = bt856_id,
303 };