V4L/DVB (4508): Fix an array overflow on bt866
[linux-2.6.git] / 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/init.h>
33 #include <linux/delay.h>
34 #include <linux/errno.h>
35 #include <linux/fs.h>
36 #include <linux/kernel.h>
37 #include <linux/major.h>
38 #include <linux/slab.h>
39 #include <linux/mm.h>
40 #include <linux/pci.h>
41 #include <linux/signal.h>
42 #include <asm/io.h>
43 #include <asm/pgtable.h>
44 #include <asm/page.h>
45 #include <linux/sched.h>
46 #include <linux/types.h>
47 #include <linux/i2c.h>
48
49 #include <linux/videodev.h>
50 #include <asm/uaccess.h>
51
52 #include <linux/video_encoder.h>
53
54 MODULE_LICENSE("GPL");
55
56 #define BT866_DEVNAME   "bt866"
57 #define I2C_BT866       0x88
58
59 MODULE_LICENSE("GPL");
60
61 #define DEBUG(x)                /* Debug driver */
62
63 /* ----------------------------------------------------------------------- */
64
65 struct bt866 {
66         struct i2c_client *i2c;
67         int addr;
68         unsigned char reg[256];
69
70         int norm;
71         int enable;
72         int bright;
73         int contrast;
74         int hue;
75         int sat;
76 };
77
78 static int bt866_write(struct bt866 *dev,
79                         unsigned char subaddr, unsigned char data);
80
81 static int bt866_do_command(struct bt866 *encoder,
82                         unsigned int cmd, void *arg)
83 {
84         switch (cmd) {
85         case ENCODER_GET_CAPABILITIES:
86         {
87                 struct video_encoder_capability *cap = arg;
88
89                 DEBUG(printk
90                       (KERN_INFO "%s: get capabilities\n",
91                        encoder->i2c->name));
92
93                 cap->flags
94                         = VIDEO_ENCODER_PAL
95                         | VIDEO_ENCODER_NTSC
96                         | VIDEO_ENCODER_CCIR;
97                 cap->inputs = 2;
98                 cap->outputs = 1;
99         }
100         break;
101
102         case ENCODER_SET_NORM:
103         {
104                 int *iarg = arg;
105
106                 DEBUG(printk(KERN_INFO "%s: set norm %d\n",
107                              encoder->i2c->name, *iarg));
108
109                 switch (*iarg) {
110
111                 case VIDEO_MODE_NTSC:
112                         break;
113
114                 case VIDEO_MODE_PAL:
115                         break;
116
117                 default:
118                         return -EINVAL;
119
120                 }
121                 encoder->norm = *iarg;
122         }
123         break;
124
125         case ENCODER_SET_INPUT:
126         {
127                 int *iarg = arg;
128                 static const __u8 init[] = {
129                         0xc8, 0xcc, /* CRSCALE */
130                         0xca, 0x91, /* CBSCALE */
131                         0xcc, 0x24, /* YC16 | OSDNUM */
132                         0xda, 0x00, /*  */
133                         0xdc, 0x24, /* SETMODE | PAL */
134                         0xde, 0x02, /* EACTIVE */
135
136                         /* overlay colors */
137                         0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
138                         0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
139                         0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
140                         0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
141                         0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
142                         0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
143                         0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
144                         0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
145
146                         0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
147                         0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
148                         0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
149                         0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
150                         0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
151                         0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
152                         0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
153                         0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
154                 };
155                 int i;
156                 u8 val;
157
158                 for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
159                         bt866_write(encoder, init[i], init[i+1]);
160
161                 val = encoder->reg[0xdc];
162
163                 if (*iarg == 0)
164                         val |= 0x40; /* CBSWAP */
165                 else
166                         val &= ~0x40; /* !CBSWAP */
167
168                 bt866_write(encoder, 0xdc, val);
169
170                 val = encoder->reg[0xcc];
171                 if (*iarg == 2)
172                         val |= 0x01; /* OSDBAR */
173                 else
174                         val &= ~0x01; /* !OSDBAR */
175                 bt866_write(encoder, 0xcc, val);
176
177                 DEBUG(printk(KERN_INFO "%s: set input %d\n",
178                              encoder->i2c->name, *iarg));
179
180                 switch (*iarg) {
181                 case 0:
182                         break;
183                 case 1:
184                         break;
185                 default:
186                         return -EINVAL;
187
188                 }
189         }
190         break;
191
192         case ENCODER_SET_OUTPUT:
193         {
194                 int *iarg = arg;
195
196                 DEBUG(printk(KERN_INFO "%s: set output %d\n",
197                              encoder->i2c->name, *iarg));
198
199                 /* not much choice of outputs */
200                 if (*iarg != 0)
201                         return -EINVAL;
202         }
203         break;
204
205         case ENCODER_ENABLE_OUTPUT:
206         {
207                 int *iarg = arg;
208                 encoder->enable = !!*iarg;
209
210                 DEBUG(printk
211                       (KERN_INFO "%s: enable output %d\n",
212                        encoder->i2c->name, encoder->enable));
213         }
214         break;
215
216         case 4711:
217         {
218                 int *iarg = arg;
219                 __u8 val;
220
221                 printk("bt866: square = %d\n", *iarg);
222
223                 val = encoder->reg[0xdc];
224                 if (*iarg)
225                         val |= 1; /* SQUARE */
226                 else
227                         val &= ~1; /* !SQUARE */
228                 bt866_write(encoder, 0xdc, val);
229                 break;
230         }
231
232         default:
233                 return -EINVAL;
234         }
235
236         return 0;
237 }
238
239 static int bt866_write(struct bt866 *encoder,
240                         unsigned char subaddr, unsigned char data)
241 {
242         unsigned char buffer[2];
243         int err;
244
245         buffer[0] = subaddr;
246         buffer[1] = data;
247
248         encoder->reg[subaddr] = data;
249
250         DEBUG(printk
251               ("%s: write 0x%02X = 0x%02X\n",
252                encoder->i2c->name, subaddr, data));
253
254         for (err = 0; err < 3;) {
255                 if (i2c_master_send(encoder->i2c, buffer, 2) == 2)
256                         break;
257                 err++;
258                 printk(KERN_WARNING "%s: I/O error #%d "
259                        "(write 0x%02x/0x%02x)\n",
260                        encoder->i2c->name, err, encoder->addr, subaddr);
261                 schedule_timeout_interruptible(HZ/10);
262         }
263         if (err == 3) {
264                 printk(KERN_WARNING "%s: giving up\n",
265                        encoder->i2c->name);
266                 return -1;
267         }
268
269         return 0;
270 }
271
272 static int bt866_attach(struct i2c_adapter *adapter);
273 static int bt866_detach(struct i2c_client *client);
274 static int bt866_command(struct i2c_client *client,
275                          unsigned int cmd, void *arg);
276
277
278 /* Addresses to scan */
279 static unsigned short normal_i2c[]      = {I2C_BT866>>1, I2C_CLIENT_END};
280 static unsigned short probe[2]          = {I2C_CLIENT_END, I2C_CLIENT_END};
281 static unsigned short ignore[2]         = {I2C_CLIENT_END, I2C_CLIENT_END};
282
283 static struct i2c_client_address_data addr_data = {
284         normal_i2c,
285         probe,
286         ignore,
287 };
288
289 static struct i2c_driver i2c_driver_bt866 = {
290         .driver.name = BT866_DEVNAME,
291         .id = I2C_DRIVERID_BT866,
292         .attach_adapter = bt866_attach,
293         .detach_client = bt866_detach,
294         .command = bt866_command
295 };
296
297
298 static struct i2c_client bt866_client_tmpl =
299 {
300         .name = "(nil)",
301         .addr = 0,
302         .adapter = NULL,
303         .driver = &i2c_driver_bt866,
304         .usage_count = 0
305 };
306
307 static int bt866_found_proc(struct i2c_adapter *adapter,
308                             int addr, int kind)
309 {
310         struct bt866 *encoder;
311         struct i2c_client *client;
312
313         client = kzalloc(sizeof(*client), GFP_KERNEL);
314         if (client == NULL)
315                 return -ENOMEM;
316         memcpy(client, &bt866_client_tmpl, sizeof(*client));
317
318         encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
319         if (encoder == NULL) {
320                 kfree(client);
321                 return -ENOMEM;
322         }
323
324         i2c_set_clientdata(client, encoder);
325         client->adapter = adapter;
326         client->addr = addr;
327         sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id);
328
329         encoder->i2c = client;
330         encoder->addr = addr;
331         //encoder->encoder_type = ENCODER_TYPE_UNKNOWN;
332
333         /* initialize */
334
335         i2c_attach_client(client);
336
337         return 0;
338 }
339
340 static int bt866_attach(struct i2c_adapter *adapter)
341 {
342         if (adapter->id == I2C_HW_B_ZR36067)
343                 return i2c_probe(adapter, &addr_data, bt866_found_proc);
344         return 0;
345 }
346
347 static int bt866_detach(struct i2c_client *client)
348 {
349         struct bt866 *encoder = i2c_get_clientdata(client);
350
351         i2c_detach_client(client);
352         kfree(encoder);
353         kfree(client);
354
355         return 0;
356 }
357
358 static int bt866_command(struct i2c_client *client,
359                          unsigned int cmd, void *arg)
360 {
361         struct bt866 *encoder = i2c_get_clientdata(client);
362         return bt866_do_command(encoder, cmd, arg);
363 }
364
365 static int __devinit bt866_init(void)
366 {
367         i2c_add_driver(&i2c_driver_bt866);
368         return 0;
369 }
370
371 static void __devexit bt866_exit(void)
372 {
373         i2c_del_driver(&i2c_driver_bt866);
374 }
375
376 module_init(bt866_init);
377 module_exit(bt866_exit);