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