]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/bt866.c
V4L/DVB (10718): bt866: convert to v4l2_subdev.
[linux-2.6-omap-h63xx.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/types.h>
33 #include <linux/ioctl.h>
34 #include <asm/uaccess.h>
35 #include <linux/i2c.h>
36 #include <linux/i2c-id.h>
37 #include <linux/videodev2.h>
38 #include <media/v4l2-device.h>
39 #include <media/v4l2-chip-ident.h>
40 #include <media/v4l2-i2c-drv-legacy.h>
41
42 MODULE_DESCRIPTION("Brooktree-866 video encoder driver");
43 MODULE_AUTHOR("Mike Bernson & Dave Perks");
44 MODULE_LICENSE("GPL");
45
46 static int debug;
47 module_param(debug, int, 0);
48 MODULE_PARM_DESC(debug, "Debug level (0-1)");
49
50 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
51
52 I2C_CLIENT_INSMOD;
53
54 /* ----------------------------------------------------------------------- */
55
56 struct bt866 {
57         struct v4l2_subdev sd;
58         u8 reg[256];
59 };
60
61 static inline struct bt866 *to_bt866(struct v4l2_subdev *sd)
62 {
63         return container_of(sd, struct bt866, sd);
64 }
65
66 static int bt866_write(struct bt866 *encoder, u8 subaddr, u8 data)
67 {
68         struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd);
69         u8 buffer[2];
70         int err;
71
72         buffer[0] = subaddr;
73         buffer[1] = data;
74
75         encoder->reg[subaddr] = data;
76
77         v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data);
78
79         for (err = 0; err < 3;) {
80                 if (i2c_master_send(client, buffer, 2) == 2)
81                         break;
82                 err++;
83                 v4l_warn(client, "error #%d writing to 0x%02x\n",
84                                 err, subaddr);
85                 schedule_timeout_interruptible(msecs_to_jiffies(100));
86         }
87         if (err == 3) {
88                 v4l_warn(client, "giving up\n");
89                 return -1;
90         }
91
92         return 0;
93 }
94
95 static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
96 {
97         v4l2_dbg(1, debug, sd, "set norm %llx\n", std);
98
99         /* Only PAL supported by this driver at the moment! */
100         if (!(std & V4L2_STD_NTSC))
101                 return -EINVAL;
102         return 0;
103 }
104
105 static int bt866_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
106 {
107         static const __u8 init[] = {
108                 0xc8, 0xcc, /* CRSCALE */
109                 0xca, 0x91, /* CBSCALE */
110                 0xcc, 0x24, /* YC16 | OSDNUM */
111                 0xda, 0x00, /*  */
112                 0xdc, 0x24, /* SETMODE | PAL */
113                 0xde, 0x02, /* EACTIVE */
114
115                 /* overlay colors */
116                 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
117                 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
118                 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
119                 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
120                 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
121                 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
122                 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
123                 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
124
125                 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
126                 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
127                 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
128                 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
129                 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
130                 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
131                 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
132                 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
133         };
134         struct bt866 *encoder = to_bt866(sd);
135         u8 val;
136         int i;
137
138         for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
139                 bt866_write(encoder, init[i], init[i+1]);
140
141         val = encoder->reg[0xdc];
142
143         if (route->input == 0)
144                 val |= 0x40; /* CBSWAP */
145         else
146                 val &= ~0x40; /* !CBSWAP */
147
148         bt866_write(encoder, 0xdc, val);
149
150         val = encoder->reg[0xcc];
151         if (route->input == 2)
152                 val |= 0x01; /* OSDBAR */
153         else
154                 val &= ~0x01; /* !OSDBAR */
155         bt866_write(encoder, 0xcc, val);
156
157         v4l2_dbg(1, debug, sd, "set input %d\n", route->input);
158
159         switch (route->input) {
160         case 0:
161         case 1:
162         case 2:
163                 break;
164         default:
165                 return -EINVAL;
166         }
167         return 0;
168 }
169
170 #if 0
171 /* Code to setup square pixels, might be of some use in the future,
172    but is currently unused. */
173         val = encoder->reg[0xdc];
174         if (*iarg)
175                 val |= 1; /* SQUARE */
176         else
177                 val &= ~1; /* !SQUARE */
178         bt866_write(client, 0xdc, val);
179 #endif
180
181 static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
182 {
183         struct i2c_client *client = v4l2_get_subdevdata(sd);
184
185         return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0);
186 }
187
188 static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
189 {
190         return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
191 }
192
193 /* ----------------------------------------------------------------------- */
194
195 static const struct v4l2_subdev_core_ops bt866_core_ops = {
196         .g_chip_ident = bt866_g_chip_ident,
197 };
198
199 static const struct v4l2_subdev_video_ops bt866_video_ops = {
200         .s_std_output = bt866_s_std_output,
201         .s_routing = bt866_s_routing,
202 };
203
204 static const struct v4l2_subdev_ops bt866_ops = {
205         .core = &bt866_core_ops,
206         .video = &bt866_video_ops,
207 };
208
209 static int bt866_probe(struct i2c_client *client,
210                         const struct i2c_device_id *id)
211 {
212         struct bt866 *encoder;
213         struct v4l2_subdev *sd;
214
215         v4l_info(client, "chip found @ 0x%x (%s)\n",
216                         client->addr << 1, client->adapter->name);
217
218         encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
219         if (encoder == NULL)
220                 return -ENOMEM;
221         sd = &encoder->sd;
222         v4l2_i2c_subdev_init(sd, client, &bt866_ops);
223         return 0;
224 }
225
226 static int bt866_remove(struct i2c_client *client)
227 {
228         struct v4l2_subdev *sd = i2c_get_clientdata(client);
229
230         v4l2_device_unregister_subdev(sd);
231         kfree(to_bt866(sd));
232         return 0;
233 }
234
235 static int bt866_legacy_probe(struct i2c_adapter *adapter)
236 {
237         return adapter->id == I2C_HW_B_ZR36067;
238 }
239
240 static const struct i2c_device_id bt866_id[] = {
241         { "bt866", 0 },
242         { }
243 };
244 MODULE_DEVICE_TABLE(i2c, bt866_id);
245
246 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
247         .name = "bt866",
248         .driverid = I2C_DRIVERID_BT866,
249         .command = bt866_command,
250         .probe = bt866_probe,
251         .remove = bt866_remove,
252         .legacy_probe = bt866_legacy_probe,
253         .id_table = bt866_id,
254 };