aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/bt866.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/bt866.c')
-rw-r--r--drivers/media/video/bt866.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
new file mode 100644
index 000000000000..05e42bbcfc3d
--- /dev/null
+++ b/drivers/media/video/bt866.c
@@ -0,0 +1,377 @@
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
54MODULE_LICENSE("GPL");
55
56#define BT866_DEVNAME "bt866"
57#define I2C_BT866 0x88
58
59MODULE_LICENSE("GPL");
60
61#define DEBUG(x) /* Debug driver */
62
63/* ----------------------------------------------------------------------- */
64
65struct bt866 {
66 struct i2c_client *i2c;
67 int addr;
68 unsigned char reg[128];
69
70 int norm;
71 int enable;
72 int bright;
73 int contrast;
74 int hue;
75 int sat;
76};
77
78static int bt866_write(struct bt866 *dev,
79 unsigned char subaddr, unsigned char data);
80
81static 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
239static 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
272static int bt866_attach(struct i2c_adapter *adapter);
273static int bt866_detach(struct i2c_client *client);
274static int bt866_command(struct i2c_client *client,
275 unsigned int cmd, void *arg);
276
277
278/* Addresses to scan */
279static unsigned short normal_i2c[] = {I2C_BT866>>1, I2C_CLIENT_END};
280static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
281static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END};
282
283static struct i2c_client_address_data addr_data = {
284 normal_i2c,
285 probe,
286 ignore,
287};
288
289static 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
298static 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
307static 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
340static 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
347static 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
358static 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
365static int __devinit bt866_init(void)
366{
367 i2c_add_driver(&i2c_driver_bt866);
368 return 0;
369}
370
371static void __devexit bt866_exit(void)
372{
373 i2c_del_driver(&i2c_driver_bt866);
374}
375
376module_init(bt866_init);
377module_exit(bt866_exit);