diff options
Diffstat (limited to 'drivers/media/video/bt866.c')
-rw-r--r-- | drivers/media/video/bt866.c | 255 |
1 files changed, 83 insertions, 172 deletions
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 96b415576f0d..596f9e2376be 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c | |||
@@ -29,42 +29,28 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <linux/module.h> | 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/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> | 32 | #include <linux/types.h> |
33 | #include <linux/ioctl.h> | ||
34 | #include <asm/uaccess.h> | ||
46 | #include <linux/i2c.h> | 35 | #include <linux/i2c.h> |
47 | 36 | #include <linux/i2c-id.h> | |
48 | #include <linux/videodev.h> | 37 | #include <linux/videodev.h> |
49 | #include <asm/uaccess.h> | ||
50 | |||
51 | #include <linux/video_encoder.h> | 38 | #include <linux/video_encoder.h> |
39 | #include <media/v4l2-common.h> | ||
40 | #include <media/v4l2-i2c-drv-legacy.h> | ||
52 | 41 | ||
42 | MODULE_DESCRIPTION("Brooktree-866 video encoder driver"); | ||
43 | MODULE_AUTHOR("Mike Bernson & Dave Perks"); | ||
53 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
54 | 45 | ||
55 | #define BT866_DEVNAME "bt866" | 46 | static int debug; |
56 | #define I2C_BT866 0x88 | 47 | module_param(debug, int, 0); |
57 | 48 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | |
58 | MODULE_LICENSE("GPL"); | ||
59 | |||
60 | #define DEBUG(x) /* Debug driver */ | ||
61 | 49 | ||
62 | /* ----------------------------------------------------------------------- */ | 50 | /* ----------------------------------------------------------------------- */ |
63 | 51 | ||
64 | struct bt866 { | 52 | struct bt866 { |
65 | struct i2c_client *i2c; | 53 | u8 reg[256]; |
66 | int addr; | ||
67 | unsigned char reg[256]; | ||
68 | 54 | ||
69 | int norm; | 55 | int norm; |
70 | int enable; | 56 | int enable; |
@@ -74,20 +60,45 @@ struct bt866 { | |||
74 | int sat; | 60 | int sat; |
75 | }; | 61 | }; |
76 | 62 | ||
77 | static int bt866_write(struct bt866 *dev, | 63 | static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data) |
78 | unsigned char subaddr, unsigned char data); | 64 | { |
65 | struct bt866 *encoder = i2c_get_clientdata(client); | ||
66 | u8 buffer[2]; | ||
67 | int err; | ||
68 | |||
69 | buffer[0] = subaddr; | ||
70 | buffer[1] = data; | ||
71 | |||
72 | encoder->reg[subaddr] = data; | ||
73 | |||
74 | v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data); | ||
75 | |||
76 | for (err = 0; err < 3;) { | ||
77 | if (i2c_master_send(client, buffer, 2) == 2) | ||
78 | break; | ||
79 | err++; | ||
80 | v4l_warn(client, "error #%d writing to 0x%02x\n", | ||
81 | err, subaddr); | ||
82 | schedule_timeout_interruptible(msecs_to_jiffies(100)); | ||
83 | } | ||
84 | if (err == 3) { | ||
85 | v4l_warn(client, "giving up\n"); | ||
86 | return -1; | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | } | ||
79 | 91 | ||
80 | static int bt866_do_command(struct bt866 *encoder, | 92 | static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) |
81 | unsigned int cmd, void *arg) | ||
82 | { | 93 | { |
94 | struct bt866 *encoder = i2c_get_clientdata(client); | ||
95 | |||
83 | switch (cmd) { | 96 | switch (cmd) { |
84 | case ENCODER_GET_CAPABILITIES: | 97 | case ENCODER_GET_CAPABILITIES: |
85 | { | 98 | { |
86 | struct video_encoder_capability *cap = arg; | 99 | struct video_encoder_capability *cap = arg; |
87 | 100 | ||
88 | DEBUG(printk | 101 | v4l_dbg(1, debug, client, "get capabilities\n"); |
89 | (KERN_INFO "%s: get capabilities\n", | ||
90 | encoder->i2c->name)); | ||
91 | 102 | ||
92 | cap->flags | 103 | cap->flags |
93 | = VIDEO_ENCODER_PAL | 104 | = VIDEO_ENCODER_PAL |
@@ -95,18 +106,16 @@ static int bt866_do_command(struct bt866 *encoder, | |||
95 | | VIDEO_ENCODER_CCIR; | 106 | | VIDEO_ENCODER_CCIR; |
96 | cap->inputs = 2; | 107 | cap->inputs = 2; |
97 | cap->outputs = 1; | 108 | cap->outputs = 1; |
109 | break; | ||
98 | } | 110 | } |
99 | break; | ||
100 | 111 | ||
101 | case ENCODER_SET_NORM: | 112 | case ENCODER_SET_NORM: |
102 | { | 113 | { |
103 | int *iarg = arg; | 114 | int *iarg = arg; |
104 | 115 | ||
105 | DEBUG(printk(KERN_INFO "%s: set norm %d\n", | 116 | v4l_dbg(1, debug, client, "set norm %d\n", *iarg); |
106 | encoder->i2c->name, *iarg)); | ||
107 | 117 | ||
108 | switch (*iarg) { | 118 | switch (*iarg) { |
109 | |||
110 | case VIDEO_MODE_NTSC: | 119 | case VIDEO_MODE_NTSC: |
111 | break; | 120 | break; |
112 | 121 | ||
@@ -115,11 +124,10 @@ static int bt866_do_command(struct bt866 *encoder, | |||
115 | 124 | ||
116 | default: | 125 | default: |
117 | return -EINVAL; | 126 | return -EINVAL; |
118 | |||
119 | } | 127 | } |
120 | encoder->norm = *iarg; | 128 | encoder->norm = *iarg; |
129 | break; | ||
121 | } | 130 | } |
122 | break; | ||
123 | 131 | ||
124 | case ENCODER_SET_INPUT: | 132 | case ENCODER_SET_INPUT: |
125 | { | 133 | { |
@@ -155,7 +163,7 @@ static int bt866_do_command(struct bt866 *encoder, | |||
155 | u8 val; | 163 | u8 val; |
156 | 164 | ||
157 | for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) | 165 | for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) |
158 | bt866_write(encoder, init[i], init[i+1]); | 166 | bt866_write(client, init[i], init[i+1]); |
159 | 167 | ||
160 | val = encoder->reg[0xdc]; | 168 | val = encoder->reg[0xdc]; |
161 | 169 | ||
@@ -164,17 +172,16 @@ static int bt866_do_command(struct bt866 *encoder, | |||
164 | else | 172 | else |
165 | val &= ~0x40; /* !CBSWAP */ | 173 | val &= ~0x40; /* !CBSWAP */ |
166 | 174 | ||
167 | bt866_write(encoder, 0xdc, val); | 175 | bt866_write(client, 0xdc, val); |
168 | 176 | ||
169 | val = encoder->reg[0xcc]; | 177 | val = encoder->reg[0xcc]; |
170 | if (*iarg == 2) | 178 | if (*iarg == 2) |
171 | val |= 0x01; /* OSDBAR */ | 179 | val |= 0x01; /* OSDBAR */ |
172 | else | 180 | else |
173 | val &= ~0x01; /* !OSDBAR */ | 181 | val &= ~0x01; /* !OSDBAR */ |
174 | bt866_write(encoder, 0xcc, val); | 182 | bt866_write(client, 0xcc, val); |
175 | 183 | ||
176 | DEBUG(printk(KERN_INFO "%s: set input %d\n", | 184 | v4l_dbg(1, debug, client, "set input %d\n", *iarg); |
177 | encoder->i2c->name, *iarg)); | ||
178 | 185 | ||
179 | switch (*iarg) { | 186 | switch (*iarg) { |
180 | case 0: | 187 | case 0: |
@@ -183,48 +190,44 @@ static int bt866_do_command(struct bt866 *encoder, | |||
183 | break; | 190 | break; |
184 | default: | 191 | default: |
185 | return -EINVAL; | 192 | return -EINVAL; |
186 | |||
187 | } | 193 | } |
194 | break; | ||
188 | } | 195 | } |
189 | break; | ||
190 | 196 | ||
191 | case ENCODER_SET_OUTPUT: | 197 | case ENCODER_SET_OUTPUT: |
192 | { | 198 | { |
193 | int *iarg = arg; | 199 | int *iarg = arg; |
194 | 200 | ||
195 | DEBUG(printk(KERN_INFO "%s: set output %d\n", | 201 | v4l_dbg(1, debug, client, "set output %d\n", *iarg); |
196 | encoder->i2c->name, *iarg)); | ||
197 | 202 | ||
198 | /* not much choice of outputs */ | 203 | /* not much choice of outputs */ |
199 | if (*iarg != 0) | 204 | if (*iarg != 0) |
200 | return -EINVAL; | 205 | return -EINVAL; |
206 | break; | ||
201 | } | 207 | } |
202 | break; | ||
203 | 208 | ||
204 | case ENCODER_ENABLE_OUTPUT: | 209 | case ENCODER_ENABLE_OUTPUT: |
205 | { | 210 | { |
206 | int *iarg = arg; | 211 | int *iarg = arg; |
207 | encoder->enable = !!*iarg; | 212 | encoder->enable = !!*iarg; |
208 | 213 | ||
209 | DEBUG(printk | 214 | v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable); |
210 | (KERN_INFO "%s: enable output %d\n", | 215 | break; |
211 | encoder->i2c->name, encoder->enable)); | ||
212 | } | 216 | } |
213 | break; | ||
214 | 217 | ||
215 | case 4711: | 218 | case 4711: |
216 | { | 219 | { |
217 | int *iarg = arg; | 220 | int *iarg = arg; |
218 | __u8 val; | 221 | __u8 val; |
219 | 222 | ||
220 | printk("bt866: square = %d\n", *iarg); | 223 | v4l_dbg(1, debug, client, "square %d\n", *iarg); |
221 | 224 | ||
222 | val = encoder->reg[0xdc]; | 225 | val = encoder->reg[0xdc]; |
223 | if (*iarg) | 226 | if (*iarg) |
224 | val |= 1; /* SQUARE */ | 227 | val |= 1; /* SQUARE */ |
225 | else | 228 | else |
226 | val &= ~1; /* !SQUARE */ | 229 | val &= ~1; /* !SQUARE */ |
227 | bt866_write(encoder, 0xdc, val); | 230 | bt866_write(client, 0xdc, val); |
228 | break; | 231 | break; |
229 | } | 232 | } |
230 | 233 | ||
@@ -235,141 +238,49 @@ static int bt866_do_command(struct bt866 *encoder, | |||
235 | return 0; | 238 | return 0; |
236 | } | 239 | } |
237 | 240 | ||
238 | static int bt866_write(struct bt866 *encoder, | 241 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; |
239 | unsigned char subaddr, unsigned char data) | ||
240 | { | ||
241 | unsigned char buffer[2]; | ||
242 | int err; | ||
243 | 242 | ||
244 | buffer[0] = subaddr; | 243 | I2C_CLIENT_INSMOD; |
245 | buffer[1] = data; | ||
246 | |||
247 | encoder->reg[subaddr] = data; | ||
248 | 244 | ||
249 | DEBUG(printk | 245 | static int bt866_probe(struct i2c_client *client, |
250 | ("%s: write 0x%02X = 0x%02X\n", | 246 | const struct i2c_device_id *id) |
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); | ||
260 | schedule_timeout_interruptible(msecs_to_jiffies(100)); | ||
261 | } | ||
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 | |||
271 | static int bt866_attach(struct i2c_adapter *adapter); | ||
272 | static int bt866_detach(struct i2c_client *client); | ||
273 | static int bt866_command(struct i2c_client *client, | ||
274 | unsigned int cmd, void *arg); | ||
275 | |||
276 | |||
277 | /* Addresses to scan */ | ||
278 | static unsigned short normal_i2c[] = {I2C_BT866>>1, I2C_CLIENT_END}; | ||
279 | static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; | ||
280 | static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; | ||
281 | |||
282 | static struct i2c_client_address_data addr_data = { | ||
283 | normal_i2c, | ||
284 | probe, | ||
285 | ignore, | ||
286 | }; | ||
287 | |||
288 | static 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 | |||
297 | static struct i2c_client bt866_client_tmpl = | ||
298 | { | ||
299 | .name = "(nil)", | ||
300 | .addr = 0, | ||
301 | .adapter = NULL, | ||
302 | .driver = &i2c_driver_bt866, | ||
303 | }; | ||
304 | |||
305 | static int bt866_found_proc(struct i2c_adapter *adapter, | ||
306 | int addr, int kind) | ||
307 | { | 247 | { |
308 | struct bt866 *encoder; | 248 | struct bt866 *encoder; |
309 | struct i2c_client *client; | ||
310 | 249 | ||
311 | client = kzalloc(sizeof(*client), GFP_KERNEL); | 250 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
312 | if (client == NULL) | 251 | client->addr << 1, client->adapter->name); |
313 | return -ENOMEM; | ||
314 | memcpy(client, &bt866_client_tmpl, sizeof(*client)); | ||
315 | 252 | ||
316 | encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); | 253 | encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); |
317 | if (encoder == NULL) { | 254 | if (encoder == NULL) |
318 | kfree(client); | ||
319 | return -ENOMEM; | 255 | return -ENOMEM; |
320 | } | ||
321 | 256 | ||
322 | i2c_set_clientdata(client, encoder); | 257 | 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 | |||
338 | static 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 | |||
345 | static 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; | 258 | return 0; |
354 | } | 259 | } |
355 | 260 | ||
356 | static int bt866_command(struct i2c_client *client, | 261 | static int bt866_remove(struct i2c_client *client) |
357 | unsigned int cmd, void *arg) | ||
358 | { | 262 | { |
359 | struct bt866 *encoder = i2c_get_clientdata(client); | 263 | kfree(i2c_get_clientdata(client)); |
360 | return bt866_do_command(encoder, cmd, arg); | ||
361 | } | ||
362 | |||
363 | static int __devinit bt866_init(void) | ||
364 | { | ||
365 | i2c_add_driver(&i2c_driver_bt866); | ||
366 | return 0; | 264 | return 0; |
367 | } | 265 | } |
368 | 266 | ||
369 | static void __devexit bt866_exit(void) | 267 | static int bt866_legacy_probe(struct i2c_adapter *adapter) |
370 | { | 268 | { |
371 | i2c_del_driver(&i2c_driver_bt866); | 269 | return adapter->id == I2C_HW_B_ZR36067; |
372 | } | 270 | } |
373 | 271 | ||
374 | module_init(bt866_init); | 272 | static const struct i2c_device_id bt866_id[] = { |
375 | module_exit(bt866_exit); | 273 | { "bt866", 0 }, |
274 | { } | ||
275 | }; | ||
276 | MODULE_DEVICE_TABLE(i2c, bt866_id); | ||
277 | |||
278 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
279 | .name = "bt866", | ||
280 | .driverid = I2C_DRIVERID_BT866, | ||
281 | .command = bt866_command, | ||
282 | .probe = bt866_probe, | ||
283 | .remove = bt866_remove, | ||
284 | .legacy_probe = bt866_legacy_probe, | ||
285 | .id_table = bt866_id, | ||
286 | }; | ||