blob: 7c68937853b0c13e50a520cee9d7688b8ea3fb5f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * bt856 - BT856A 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 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
14 * - moved over to linux>=2.4.x i2c protocol (9/9/2002)
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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <linux/types.h>
47
48#include <linux/videodev.h>
49#include <asm/uaccess.h>
50
51MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
52MODULE_AUTHOR("Mike Bernson & Dave Perks");
53MODULE_LICENSE("GPL");
54
55#include <linux/i2c.h>
56#include <linux/i2c-dev.h>
57
58#define I2C_NAME(s) (s)->name
59
60#include <linux/video_encoder.h>
61
62static int debug = 0;
63module_param(debug, int, 0);
64MODULE_PARM_DESC(debug, "Debug level (0-1)");
65
66#define dprintk(num, format, args...) \
67 do { \
68 if (debug >= num) \
69 printk(format, ##args); \
70 } while (0)
71
72/* ----------------------------------------------------------------------- */
73
Jean Delvaref49a5ea2006-03-22 03:48:36 -030074#define REG_OFFSET 0xDA
75#define BT856_NR_REG 6
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77struct bt856 {
Jean Delvaref49a5ea2006-03-22 03:48:36 -030078 unsigned char reg[BT856_NR_REG];
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80 int norm;
81 int enable;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082};
83
84#define I2C_BT856 0x88
85
86/* ----------------------------------------------------------------------- */
87
88static inline int
89bt856_write (struct i2c_client *client,
90 u8 reg,
91 u8 value)
92{
93 struct bt856 *encoder = i2c_get_clientdata(client);
94
95 encoder->reg[reg - REG_OFFSET] = value;
96 return i2c_smbus_write_byte_data(client, reg, value);
97}
98
99static inline int
100bt856_setbit (struct i2c_client *client,
101 u8 reg,
102 u8 bit,
103 u8 value)
104{
105 struct bt856 *encoder = i2c_get_clientdata(client);
106
107 return bt856_write(client, reg,
108 (encoder->
109 reg[reg - REG_OFFSET] & ~(1 << bit)) |
110 (value ? (1 << bit) : 0));
111}
112
113static void
114bt856_dump (struct i2c_client *client)
115{
116 int i;
117 struct bt856 *encoder = i2c_get_clientdata(client);
118
119 printk(KERN_INFO "%s: register dump:", I2C_NAME(client));
Jean Delvaref49a5ea2006-03-22 03:48:36 -0300120 for (i = 0; i < BT856_NR_REG; i += 2)
121 printk(" %02x", encoder->reg[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 printk("\n");
123}
124
125/* ----------------------------------------------------------------------- */
126
127static int
128bt856_command (struct i2c_client *client,
129 unsigned int cmd,
130 void *arg)
131{
132 struct bt856 *encoder = i2c_get_clientdata(client);
133
134 switch (cmd) {
135
136 case 0:
137 /* This is just for testing!!! */
138 dprintk(1, KERN_INFO "bt856: init\n");
139 bt856_write(client, 0xdc, 0x18);
140 bt856_write(client, 0xda, 0);
141 bt856_write(client, 0xde, 0);
142
143 bt856_setbit(client, 0xdc, 3, 1);
144 //bt856_setbit(client, 0xdc, 6, 0);
145 bt856_setbit(client, 0xdc, 4, 1);
146
147 switch (encoder->norm) {
148
149 case VIDEO_MODE_NTSC:
150 bt856_setbit(client, 0xdc, 2, 0);
151 break;
152
153 case VIDEO_MODE_PAL:
154 bt856_setbit(client, 0xdc, 2, 1);
155 break;
156 }
157
158 bt856_setbit(client, 0xdc, 1, 1);
159 bt856_setbit(client, 0xde, 4, 0);
160 bt856_setbit(client, 0xde, 3, 1);
161 if (debug != 0)
162 bt856_dump(client);
163 break;
164
165 case ENCODER_GET_CAPABILITIES:
166 {
167 struct video_encoder_capability *cap = arg;
168
169 dprintk(1, KERN_INFO "%s: get capabilities\n",
170 I2C_NAME(client));
171
172 cap->flags = VIDEO_ENCODER_PAL |
173 VIDEO_ENCODER_NTSC |
174 VIDEO_ENCODER_CCIR;
175 cap->inputs = 2;
176 cap->outputs = 1;
177 }
178 break;
179
180 case ENCODER_SET_NORM:
181 {
182 int *iarg = arg;
183
184 dprintk(1, KERN_INFO "%s: set norm %d\n", I2C_NAME(client),
185 *iarg);
186
187 switch (*iarg) {
188
189 case VIDEO_MODE_NTSC:
190 bt856_setbit(client, 0xdc, 2, 0);
191 break;
192
193 case VIDEO_MODE_PAL:
194 bt856_setbit(client, 0xdc, 2, 1);
195 bt856_setbit(client, 0xda, 0, 0);
196 //bt856_setbit(client, 0xda, 0, 1);
197 break;
198
199 default:
200 return -EINVAL;
201
202 }
203 encoder->norm = *iarg;
204 if (debug != 0)
205 bt856_dump(client);
206 }
207 break;
208
209 case ENCODER_SET_INPUT:
210 {
211 int *iarg = arg;
212
213 dprintk(1, KERN_INFO "%s: set input %d\n", I2C_NAME(client),
214 *iarg);
215
216 /* We only have video bus.
217 * iarg = 0: input is from bt819
218 * iarg = 1: input is from ZR36060 */
219
220 switch (*iarg) {
221
222 case 0:
223 bt856_setbit(client, 0xde, 4, 0);
224 bt856_setbit(client, 0xde, 3, 1);
225 bt856_setbit(client, 0xdc, 3, 1);
226 bt856_setbit(client, 0xdc, 6, 0);
227 break;
228 case 1:
229 bt856_setbit(client, 0xde, 4, 0);
230 bt856_setbit(client, 0xde, 3, 1);
231 bt856_setbit(client, 0xdc, 3, 1);
232 bt856_setbit(client, 0xdc, 6, 1);
233 break;
234 case 2: // Color bar
235 bt856_setbit(client, 0xdc, 3, 0);
236 bt856_setbit(client, 0xde, 4, 1);
237 break;
238 default:
239 return -EINVAL;
240
241 }
242
243 if (debug != 0)
244 bt856_dump(client);
245 }
246 break;
247
248 case ENCODER_SET_OUTPUT:
249 {
250 int *iarg = arg;
251
252 dprintk(1, KERN_INFO "%s: set output %d\n", I2C_NAME(client),
253 *iarg);
254
255 /* not much choice of outputs */
256 if (*iarg != 0) {
257 return -EINVAL;
258 }
259 }
260 break;
261
262 case ENCODER_ENABLE_OUTPUT:
263 {
264 int *iarg = arg;
265
266 encoder->enable = !!*iarg;
267
268 dprintk(1, KERN_INFO "%s: enable output %d\n",
269 I2C_NAME(client), encoder->enable);
270 }
271 break;
272
273 default:
274 return -EINVAL;
275 }
276
277 return 0;
278}
279
280/* ----------------------------------------------------------------------- */
281
282/*
283 * Generic i2c probe
284 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
285 */
286static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Jean Delvare68cc9d02005-04-02 20:04:41 +0200288static unsigned short ignore = I2C_CLIENT_END;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
290static struct i2c_client_address_data addr_data = {
291 .normal_i2c = normal_i2c,
Jean Delvare68cc9d02005-04-02 20:04:41 +0200292 .probe = &ignore,
293 .ignore = &ignore,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294};
295
296static struct i2c_driver i2c_driver_bt856;
297
298static int
299bt856_detect_client (struct i2c_adapter *adapter,
300 int address,
301 int kind)
302{
303 int i;
304 struct i2c_client *client;
305 struct bt856 *encoder;
306
307 dprintk(1,
308 KERN_INFO
309 "bt856.c: detecting bt856 client on address 0x%x\n",
310 address << 1);
311
312 /* Check if the adapter supports the needed features */
313 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
314 return 0;
315
Panagiotis Issaris74081872006-01-11 19:40:56 -0200316 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 if (client == 0)
318 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 client->addr = address;
320 client->adapter = adapter;
321 client->driver = &i2c_driver_bt856;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client)));
323
Panagiotis Issaris74081872006-01-11 19:40:56 -0200324 encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 if (encoder == NULL) {
326 kfree(client);
327 return -ENOMEM;
328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 encoder->norm = VIDEO_MODE_NTSC;
330 encoder->enable = 1;
331 i2c_set_clientdata(client, encoder);
332
333 i = i2c_attach_client(client);
334 if (i) {
335 kfree(client);
336 kfree(encoder);
337 return i;
338 }
339
340 bt856_write(client, 0xdc, 0x18);
341 bt856_write(client, 0xda, 0);
342 bt856_write(client, 0xde, 0);
343
344 bt856_setbit(client, 0xdc, 3, 1);
345 //bt856_setbit(client, 0xdc, 6, 0);
346 bt856_setbit(client, 0xdc, 4, 1);
347
348 switch (encoder->norm) {
349
350 case VIDEO_MODE_NTSC:
351 bt856_setbit(client, 0xdc, 2, 0);
352 break;
353
354 case VIDEO_MODE_PAL:
355 bt856_setbit(client, 0xdc, 2, 1);
356 break;
357 }
358
359 bt856_setbit(client, 0xdc, 1, 1);
360 bt856_setbit(client, 0xde, 4, 0);
361 bt856_setbit(client, 0xde, 3, 1);
362
363 if (debug != 0)
364 bt856_dump(client);
365
366 dprintk(1, KERN_INFO "%s_attach: at address 0x%x\n", I2C_NAME(client),
367 client->addr << 1);
368
369 return 0;
370}
371
372static int
373bt856_attach_adapter (struct i2c_adapter *adapter)
374{
375 dprintk(1,
376 KERN_INFO
377 "bt856.c: starting probe for adapter %s (0x%x)\n",
378 I2C_NAME(adapter), adapter->id);
379 return i2c_probe(adapter, &addr_data, &bt856_detect_client);
380}
381
382static int
383bt856_detach_client (struct i2c_client *client)
384{
385 struct bt856 *encoder = i2c_get_clientdata(client);
386 int err;
387
388 err = i2c_detach_client(client);
389 if (err) {
390 return err;
391 }
392
393 kfree(encoder);
394 kfree(client);
395
396 return 0;
397}
398
399/* ----------------------------------------------------------------------- */
400
401static struct i2c_driver i2c_driver_bt856 = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100402 .driver = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100403 .name = "bt856",
404 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
406 .id = I2C_DRIVERID_BT856,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
408 .attach_adapter = bt856_attach_adapter,
409 .detach_client = bt856_detach_client,
410 .command = bt856_command,
411};
412
413static int __init
414bt856_init (void)
415{
416 return i2c_add_driver(&i2c_driver_bt856);
417}
418
419static void __exit
420bt856_exit (void)
421{
422 i2c_del_driver(&i2c_driver_bt856);
423}
424
425module_init(bt856_init);
426module_exit(bt856_exit);