Merge branch 'timers/range-hrtimers' into v28-range-hrtimers-for-linus-v2
[linux-2.6] / drivers / media / video / bt866.c
1 /*
2     bt866 - BT866 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     This code was adapted for the bt866 by Christer Weinigel and ported
14     to 2.6 by Martin Samuelsson.
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-866 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 struct bt866 {
53         u8 reg[256];
54
55         int norm;
56         int enable;
57         int bright;
58         int contrast;
59         int hue;
60         int sat;
61 };
62
63 static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data)
64 {
65         struct bt866 *encoder = i2c_get_clientdata(client);
66         u8 buffer[2];
67         int err;
68
69         buffer[0] = subaddr;
70         buffer[1] = data;
71
72         encoder->reg[subaddr] = data;
73
74         v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data);
75
76         for (err = 0; err < 3;) {
77                 if (i2c_master_send(client, buffer, 2) == 2)
78                         break;
79                 err++;
80                 v4l_warn(client, "error #%d writing to 0x%02x\n",
81                                 err, subaddr);
82                 schedule_timeout_interruptible(msecs_to_jiffies(100));
83         }
84         if (err == 3) {
85                 v4l_warn(client, "giving up\n");
86                 return -1;
87         }
88
89         return 0;
90 }
91
92 static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
93 {
94         struct bt866 *encoder = i2c_get_clientdata(client);
95
96         switch (cmd) {
97         case ENCODER_GET_CAPABILITIES:
98         {
99                 struct video_encoder_capability *cap = arg;
100
101                 v4l_dbg(1, debug, client, "get capabilities\n");
102
103                 cap->flags
104                         = VIDEO_ENCODER_PAL
105                         | VIDEO_ENCODER_NTSC
106                         | VIDEO_ENCODER_CCIR;
107                 cap->inputs = 2;
108                 cap->outputs = 1;
109                 break;
110         }
111
112         case ENCODER_SET_NORM:
113         {
114                 int *iarg = arg;
115
116                 v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
117
118                 switch (*iarg) {
119                 case VIDEO_MODE_NTSC:
120                         break;
121
122                 case VIDEO_MODE_PAL:
123                         break;
124
125                 default:
126                         return -EINVAL;
127                 }
128                 encoder->norm = *iarg;
129                 break;
130         }
131
132         case ENCODER_SET_INPUT:
133         {
134                 int *iarg = arg;
135                 static const __u8 init[] = {
136                         0xc8, 0xcc, /* CRSCALE */
137                         0xca, 0x91, /* CBSCALE */
138                         0xcc, 0x24, /* YC16 | OSDNUM */
139                         0xda, 0x00, /*  */
140                         0xdc, 0x24, /* SETMODE | PAL */
141                         0xde, 0x02, /* EACTIVE */
142
143                         /* overlay colors */
144                         0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
145                         0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
146                         0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
147                         0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
148                         0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
149                         0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
150                         0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
151                         0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
152
153                         0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
154                         0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
155                         0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
156                         0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
157                         0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
158                         0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
159                         0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
160                         0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
161                 };
162                 int i;
163                 u8 val;
164
165                 for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
166                         bt866_write(client, init[i], init[i+1]);
167
168                 val = encoder->reg[0xdc];
169
170                 if (*iarg == 0)
171                         val |= 0x40; /* CBSWAP */
172                 else
173                         val &= ~0x40; /* !CBSWAP */
174
175                 bt866_write(client, 0xdc, val);
176
177                 val = encoder->reg[0xcc];
178                 if (*iarg == 2)
179                         val |= 0x01; /* OSDBAR */
180                 else
181                         val &= ~0x01; /* !OSDBAR */
182                 bt866_write(client, 0xcc, val);
183
184                 v4l_dbg(1, debug, client, "set input %d\n", *iarg);
185
186                 switch (*iarg) {
187                 case 0:
188                         break;
189                 case 1:
190                         break;
191                 default:
192                         return -EINVAL;
193                 }
194                 break;
195         }
196
197         case ENCODER_SET_OUTPUT:
198         {
199                 int *iarg = arg;
200
201                 v4l_dbg(1, debug, client, "set output %d\n", *iarg);
202
203                 /* not much choice of outputs */
204                 if (*iarg != 0)
205                         return -EINVAL;
206                 break;
207         }
208
209         case ENCODER_ENABLE_OUTPUT:
210         {
211                 int *iarg = arg;
212                 encoder->enable = !!*iarg;
213
214                 v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
215                 break;
216         }
217
218         case 4711:
219         {
220                 int *iarg = arg;
221                 __u8 val;
222
223                 v4l_dbg(1, debug, client, "square %d\n", *iarg);
224
225                 val = encoder->reg[0xdc];
226                 if (*iarg)
227                         val |= 1; /* SQUARE */
228                 else
229                         val &= ~1; /* !SQUARE */
230                 bt866_write(client, 0xdc, val);
231                 break;
232         }
233
234         default:
235                 return -EINVAL;
236         }
237
238         return 0;
239 }
240
241 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
242
243 I2C_CLIENT_INSMOD;
244
245 static int bt866_probe(struct i2c_client *client,
246                         const struct i2c_device_id *id)
247 {
248         struct bt866 *encoder;
249
250         v4l_info(client, "chip found @ 0x%x (%s)\n",
251                         client->addr << 1, client->adapter->name);
252
253         encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
254         if (encoder == NULL)
255                 return -ENOMEM;
256
257         i2c_set_clientdata(client, encoder);
258         return 0;
259 }
260
261 static int bt866_remove(struct i2c_client *client)
262 {
263         kfree(i2c_get_clientdata(client));
264         return 0;
265 }
266
267 static int bt866_legacy_probe(struct i2c_adapter *adapter)
268 {
269         return adapter->id == I2C_HW_B_ZR36067;
270 }
271
272 static const struct i2c_device_id bt866_id[] = {
273         { "bt866", 0 },
274         { }
275 };
276 MODULE_DEVICE_TABLE(i2c, bt866_id);
277
278 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
279         .name = "bt866",
280         .driverid = I2C_DRIVERID_BT866,
281         .command = bt866_command,
282         .probe = bt866_probe,
283         .remove = bt866_remove,
284         .legacy_probe = bt866_legacy_probe,
285         .id_table = bt866_id,
286 };