blob: b767b098d14bb677b9c9b7e6393825c61cedff38 [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 Chehab09df5cb2007-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,
303 .usage_count = 0
304};
305
306static int bt866_found_proc(struct i2c_adapter *adapter,
307 int addr, int kind)
308{
309 struct bt866 *encoder;
310 struct i2c_client *client;
311
312 client = kzalloc(sizeof(*client), GFP_KERNEL);
313 if (client == NULL)
314 return -ENOMEM;
315 memcpy(client, &bt866_client_tmpl, sizeof(*client));
316
317 encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
318 if (encoder == NULL) {
319 kfree(client);
320 return -ENOMEM;
321 }
322
323 i2c_set_clientdata(client, encoder);
324 client->adapter = adapter;
325 client->addr = addr;
326 sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id);
327
328 encoder->i2c = client;
329 encoder->addr = addr;
330 //encoder->encoder_type = ENCODER_TYPE_UNKNOWN;
331
332 /* initialize */
333
334 i2c_attach_client(client);
335
336 return 0;
337}
338
339static int bt866_attach(struct i2c_adapter *adapter)
340{
341 if (adapter->id == I2C_HW_B_ZR36067)
342 return i2c_probe(adapter, &addr_data, bt866_found_proc);
343 return 0;
344}
345
346static int bt866_detach(struct i2c_client *client)
347{
348 struct bt866 *encoder = i2c_get_clientdata(client);
349
350 i2c_detach_client(client);
351 kfree(encoder);
352 kfree(client);
353
354 return 0;
355}
356
357static int bt866_command(struct i2c_client *client,
358 unsigned int cmd, void *arg)
359{
360 struct bt866 *encoder = i2c_get_clientdata(client);
361 return bt866_do_command(encoder, cmd, arg);
362}
363
364static int __devinit bt866_init(void)
365{
366 i2c_add_driver(&i2c_driver_bt866);
367 return 0;
368}
369
370static void __devexit bt866_exit(void)
371{
372 i2c_del_driver(&i2c_driver_bt866);
373}
374
375module_init(bt866_init);
376module_exit(bt866_exit);