diff options
Diffstat (limited to 'drivers/media/video/bt856.c')
-rw-r--r-- | drivers/media/video/bt856.c | 218 |
1 files changed, 49 insertions, 169 deletions
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index ab2ce4d7b5de..4213867507f8 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c | |||
@@ -29,43 +29,24 @@ | |||
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 <linux/types.h> | 32 | #include <linux/types.h> |
42 | #include <linux/i2c.h> | 33 | #include <linux/ioctl.h> |
43 | #include <linux/video_encoder.h> | ||
44 | #include <asm/io.h> | ||
45 | #include <asm/pgtable.h> | ||
46 | #include <asm/page.h> | ||
47 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
48 | 35 | #include <linux/i2c.h> | |
36 | #include <linux/i2c-id.h> | ||
49 | #include <linux/videodev.h> | 37 | #include <linux/videodev.h> |
38 | #include <linux/video_encoder.h> | ||
39 | #include <media/v4l2-common.h> | ||
40 | #include <media/v4l2-i2c-drv-legacy.h> | ||
50 | 41 | ||
51 | MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); | 42 | MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); |
52 | MODULE_AUTHOR("Mike Bernson & Dave Perks"); | 43 | MODULE_AUTHOR("Mike Bernson & Dave Perks"); |
53 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
54 | 45 | ||
55 | |||
56 | #define I2C_NAME(s) (s)->name | ||
57 | |||
58 | |||
59 | static int debug; | 46 | static int debug; |
60 | module_param(debug, int, 0); | 47 | module_param(debug, int, 0); |
61 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | 48 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
62 | 49 | ||
63 | #define dprintk(num, format, args...) \ | ||
64 | do { \ | ||
65 | if (debug >= num) \ | ||
66 | printk(format, ##args); \ | ||
67 | } while (0) | ||
68 | |||
69 | /* ----------------------------------------------------------------------- */ | 50 | /* ----------------------------------------------------------------------- */ |
70 | 51 | ||
71 | #define BT856_REG_OFFSET 0xDA | 52 | #define BT856_REG_OFFSET 0xDA |
@@ -78,14 +59,9 @@ struct bt856 { | |||
78 | int enable; | 59 | int enable; |
79 | }; | 60 | }; |
80 | 61 | ||
81 | #define I2C_BT856 0x88 | ||
82 | |||
83 | /* ----------------------------------------------------------------------- */ | 62 | /* ----------------------------------------------------------------------- */ |
84 | 63 | ||
85 | static inline int | 64 | static inline int bt856_write(struct i2c_client *client, u8 reg, u8 value) |
86 | bt856_write (struct i2c_client *client, | ||
87 | u8 reg, | ||
88 | u8 value) | ||
89 | { | 65 | { |
90 | struct bt856 *encoder = i2c_get_clientdata(client); | 66 | struct bt856 *encoder = i2c_get_clientdata(client); |
91 | 67 | ||
@@ -93,46 +69,36 @@ bt856_write (struct i2c_client *client, | |||
93 | return i2c_smbus_write_byte_data(client, reg, value); | 69 | return i2c_smbus_write_byte_data(client, reg, value); |
94 | } | 70 | } |
95 | 71 | ||
96 | static inline int | 72 | static inline int bt856_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value) |
97 | bt856_setbit (struct i2c_client *client, | ||
98 | u8 reg, | ||
99 | u8 bit, | ||
100 | u8 value) | ||
101 | { | 73 | { |
102 | struct bt856 *encoder = i2c_get_clientdata(client); | 74 | struct bt856 *encoder = i2c_get_clientdata(client); |
103 | 75 | ||
104 | return bt856_write(client, reg, | 76 | return bt856_write(client, reg, |
105 | (encoder-> | 77 | (encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) | |
106 | reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) | | 78 | (value ? (1 << bit) : 0)); |
107 | (value ? (1 << bit) : 0)); | ||
108 | } | 79 | } |
109 | 80 | ||
110 | static void | 81 | static void bt856_dump(struct i2c_client *client) |
111 | bt856_dump (struct i2c_client *client) | ||
112 | { | 82 | { |
113 | int i; | 83 | int i; |
114 | struct bt856 *encoder = i2c_get_clientdata(client); | 84 | struct bt856 *encoder = i2c_get_clientdata(client); |
115 | 85 | ||
116 | printk(KERN_INFO "%s: register dump:", I2C_NAME(client)); | 86 | v4l_info(client, "register dump:\n"); |
117 | for (i = 0; i < BT856_NR_REG; i += 2) | 87 | for (i = 0; i < BT856_NR_REG; i += 2) |
118 | printk(" %02x", encoder->reg[i]); | 88 | printk(KERN_CONT " %02x", encoder->reg[i]); |
119 | printk("\n"); | 89 | printk(KERN_CONT "\n"); |
120 | } | 90 | } |
121 | 91 | ||
122 | /* ----------------------------------------------------------------------- */ | 92 | /* ----------------------------------------------------------------------- */ |
123 | 93 | ||
124 | static int | 94 | static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) |
125 | bt856_command (struct i2c_client *client, | ||
126 | unsigned int cmd, | ||
127 | void *arg) | ||
128 | { | 95 | { |
129 | struct bt856 *encoder = i2c_get_clientdata(client); | 96 | struct bt856 *encoder = i2c_get_clientdata(client); |
130 | 97 | ||
131 | switch (cmd) { | 98 | switch (cmd) { |
132 | |||
133 | case 0: | 99 | case 0: |
134 | /* This is just for testing!!! */ | 100 | /* This is just for testing!!! */ |
135 | dprintk(1, KERN_INFO "bt856: init\n"); | 101 | v4l_dbg(1, debug, client, "init\n"); |
136 | bt856_write(client, 0xdc, 0x18); | 102 | bt856_write(client, 0xdc, 0x18); |
137 | bt856_write(client, 0xda, 0); | 103 | bt856_write(client, 0xda, 0); |
138 | bt856_write(client, 0xde, 0); | 104 | bt856_write(client, 0xde, 0); |
@@ -142,7 +108,6 @@ bt856_command (struct i2c_client *client, | |||
142 | bt856_setbit(client, 0xdc, 4, 1); | 108 | bt856_setbit(client, 0xdc, 4, 1); |
143 | 109 | ||
144 | switch (encoder->norm) { | 110 | switch (encoder->norm) { |
145 | |||
146 | case VIDEO_MODE_NTSC: | 111 | case VIDEO_MODE_NTSC: |
147 | bt856_setbit(client, 0xdc, 2, 0); | 112 | bt856_setbit(client, 0xdc, 2, 0); |
148 | break; | 113 | break; |
@@ -163,26 +128,23 @@ bt856_command (struct i2c_client *client, | |||
163 | { | 128 | { |
164 | struct video_encoder_capability *cap = arg; | 129 | struct video_encoder_capability *cap = arg; |
165 | 130 | ||
166 | dprintk(1, KERN_INFO "%s: get capabilities\n", | 131 | v4l_dbg(1, debug, client, "get capabilities\n"); |
167 | I2C_NAME(client)); | ||
168 | 132 | ||
169 | cap->flags = VIDEO_ENCODER_PAL | | 133 | cap->flags = VIDEO_ENCODER_PAL | |
170 | VIDEO_ENCODER_NTSC | | 134 | VIDEO_ENCODER_NTSC | |
171 | VIDEO_ENCODER_CCIR; | 135 | VIDEO_ENCODER_CCIR; |
172 | cap->inputs = 2; | 136 | cap->inputs = 2; |
173 | cap->outputs = 1; | 137 | cap->outputs = 1; |
174 | } | ||
175 | break; | 138 | break; |
139 | } | ||
176 | 140 | ||
177 | case ENCODER_SET_NORM: | 141 | case ENCODER_SET_NORM: |
178 | { | 142 | { |
179 | int *iarg = arg; | 143 | int *iarg = arg; |
180 | 144 | ||
181 | dprintk(1, KERN_INFO "%s: set norm %d\n", I2C_NAME(client), | 145 | v4l_dbg(1, debug, client, "set norm %d\n", *iarg); |
182 | *iarg); | ||
183 | 146 | ||
184 | switch (*iarg) { | 147 | switch (*iarg) { |
185 | |||
186 | case VIDEO_MODE_NTSC: | 148 | case VIDEO_MODE_NTSC: |
187 | bt856_setbit(client, 0xdc, 2, 0); | 149 | bt856_setbit(client, 0xdc, 2, 0); |
188 | break; | 150 | break; |
@@ -195,27 +157,23 @@ bt856_command (struct i2c_client *client, | |||
195 | 157 | ||
196 | default: | 158 | default: |
197 | return -EINVAL; | 159 | return -EINVAL; |
198 | |||
199 | } | 160 | } |
200 | encoder->norm = *iarg; | 161 | encoder->norm = *iarg; |
201 | if (debug != 0) | 162 | if (debug != 0) |
202 | bt856_dump(client); | 163 | bt856_dump(client); |
203 | } | ||
204 | break; | 164 | break; |
165 | } | ||
205 | 166 | ||
206 | case ENCODER_SET_INPUT: | 167 | case ENCODER_SET_INPUT: |
207 | { | 168 | { |
208 | int *iarg = arg; | 169 | int *iarg = arg; |
209 | 170 | ||
210 | dprintk(1, KERN_INFO "%s: set input %d\n", I2C_NAME(client), | 171 | v4l_dbg(1, debug, client, "set input %d\n", *iarg); |
211 | *iarg); | ||
212 | 172 | ||
213 | /* We only have video bus. | 173 | /* We only have video bus. |
214 | * iarg = 0: input is from bt819 | 174 | * iarg = 0: input is from bt819 |
215 | * iarg = 1: input is from ZR36060 */ | 175 | * iarg = 1: input is from ZR36060 */ |
216 | |||
217 | switch (*iarg) { | 176 | switch (*iarg) { |
218 | |||
219 | case 0: | 177 | case 0: |
220 | bt856_setbit(client, 0xde, 4, 0); | 178 | bt856_setbit(client, 0xde, 4, 0); |
221 | bt856_setbit(client, 0xde, 3, 1); | 179 | bt856_setbit(client, 0xde, 3, 1); |
@@ -234,27 +192,24 @@ bt856_command (struct i2c_client *client, | |||
234 | break; | 192 | break; |
235 | default: | 193 | default: |
236 | return -EINVAL; | 194 | return -EINVAL; |
237 | |||
238 | } | 195 | } |
239 | 196 | ||
240 | if (debug != 0) | 197 | if (debug != 0) |
241 | bt856_dump(client); | 198 | bt856_dump(client); |
242 | } | ||
243 | break; | 199 | break; |
200 | } | ||
244 | 201 | ||
245 | case ENCODER_SET_OUTPUT: | 202 | case ENCODER_SET_OUTPUT: |
246 | { | 203 | { |
247 | int *iarg = arg; | 204 | int *iarg = arg; |
248 | 205 | ||
249 | dprintk(1, KERN_INFO "%s: set output %d\n", I2C_NAME(client), | 206 | v4l_dbg(1, debug, client, "set output %d\n", *iarg); |
250 | *iarg); | ||
251 | 207 | ||
252 | /* not much choice of outputs */ | 208 | /* not much choice of outputs */ |
253 | if (*iarg != 0) { | 209 | if (*iarg != 0) |
254 | return -EINVAL; | 210 | return -EINVAL; |
255 | } | ||
256 | } | ||
257 | break; | 211 | break; |
212 | } | ||
258 | 213 | ||
259 | case ENCODER_ENABLE_OUTPUT: | 214 | case ENCODER_ENABLE_OUTPUT: |
260 | { | 215 | { |
@@ -262,10 +217,9 @@ bt856_command (struct i2c_client *client, | |||
262 | 217 | ||
263 | encoder->enable = !!*iarg; | 218 | encoder->enable = !!*iarg; |
264 | 219 | ||
265 | dprintk(1, KERN_INFO "%s: enable output %d\n", | 220 | v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable); |
266 | I2C_NAME(client), encoder->enable); | ||
267 | } | ||
268 | break; | 221 | break; |
222 | } | ||
269 | 223 | ||
270 | default: | 224 | default: |
271 | return -EINVAL; | 225 | return -EINVAL; |
@@ -276,64 +230,29 @@ bt856_command (struct i2c_client *client, | |||
276 | 230 | ||
277 | /* ----------------------------------------------------------------------- */ | 231 | /* ----------------------------------------------------------------------- */ |
278 | 232 | ||
279 | /* | 233 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; |
280 | * Generic i2c probe | ||
281 | * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' | ||
282 | */ | ||
283 | static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END }; | ||
284 | |||
285 | static unsigned short ignore = I2C_CLIENT_END; | ||
286 | |||
287 | static struct i2c_client_address_data addr_data = { | ||
288 | .normal_i2c = normal_i2c, | ||
289 | .probe = &ignore, | ||
290 | .ignore = &ignore, | ||
291 | }; | ||
292 | 234 | ||
293 | static struct i2c_driver i2c_driver_bt856; | 235 | I2C_CLIENT_INSMOD; |
294 | 236 | ||
295 | static int | 237 | static int bt856_probe(struct i2c_client *client, |
296 | bt856_detect_client (struct i2c_adapter *adapter, | 238 | const struct i2c_device_id *id) |
297 | int address, | ||
298 | int kind) | ||
299 | { | 239 | { |
300 | int i; | ||
301 | struct i2c_client *client; | ||
302 | struct bt856 *encoder; | 240 | struct bt856 *encoder; |
303 | 241 | ||
304 | dprintk(1, | ||
305 | KERN_INFO | ||
306 | "bt856.c: detecting bt856 client on address 0x%x\n", | ||
307 | address << 1); | ||
308 | |||
309 | /* Check if the adapter supports the needed features */ | 242 | /* Check if the adapter supports the needed features */ |
310 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 243 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
311 | return 0; | 244 | return -ENODEV; |
312 | 245 | ||
313 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | 246 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
314 | if (!client) | 247 | client->addr << 1, client->adapter->name); |
315 | return -ENOMEM; | ||
316 | client->addr = address; | ||
317 | client->adapter = adapter; | ||
318 | client->driver = &i2c_driver_bt856; | ||
319 | strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client))); | ||
320 | 248 | ||
321 | encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL); | 249 | encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL); |
322 | if (encoder == NULL) { | 250 | if (encoder == NULL) |
323 | kfree(client); | ||
324 | return -ENOMEM; | 251 | return -ENOMEM; |
325 | } | ||
326 | encoder->norm = VIDEO_MODE_NTSC; | 252 | encoder->norm = VIDEO_MODE_NTSC; |
327 | encoder->enable = 1; | 253 | encoder->enable = 1; |
328 | i2c_set_clientdata(client, encoder); | 254 | i2c_set_clientdata(client, encoder); |
329 | 255 | ||
330 | i = i2c_attach_client(client); | ||
331 | if (i) { | ||
332 | kfree(client); | ||
333 | kfree(encoder); | ||
334 | return i; | ||
335 | } | ||
336 | |||
337 | bt856_write(client, 0xdc, 0x18); | 256 | bt856_write(client, 0xdc, 0x18); |
338 | bt856_write(client, 0xda, 0); | 257 | bt856_write(client, 0xda, 0); |
339 | bt856_write(client, 0xde, 0); | 258 | bt856_write(client, 0xde, 0); |
@@ -359,65 +278,26 @@ bt856_detect_client (struct i2c_adapter *adapter, | |||
359 | 278 | ||
360 | if (debug != 0) | 279 | if (debug != 0) |
361 | bt856_dump(client); | 280 | bt856_dump(client); |
362 | |||
363 | dprintk(1, KERN_INFO "%s_attach: at address 0x%x\n", I2C_NAME(client), | ||
364 | client->addr << 1); | ||
365 | |||
366 | return 0; | 281 | return 0; |
367 | } | 282 | } |
368 | 283 | ||
369 | static int | 284 | static int bt856_remove(struct i2c_client *client) |
370 | bt856_attach_adapter (struct i2c_adapter *adapter) | ||
371 | { | 285 | { |
372 | dprintk(1, | 286 | kfree(i2c_get_clientdata(client)); |
373 | KERN_INFO | ||
374 | "bt856.c: starting probe for adapter %s (0x%x)\n", | ||
375 | I2C_NAME(adapter), adapter->id); | ||
376 | return i2c_probe(adapter, &addr_data, &bt856_detect_client); | ||
377 | } | ||
378 | |||
379 | static int | ||
380 | bt856_detach_client (struct i2c_client *client) | ||
381 | { | ||
382 | struct bt856 *encoder = i2c_get_clientdata(client); | ||
383 | int err; | ||
384 | |||
385 | err = i2c_detach_client(client); | ||
386 | if (err) { | ||
387 | return err; | ||
388 | } | ||
389 | |||
390 | kfree(encoder); | ||
391 | kfree(client); | ||
392 | |||
393 | return 0; | 287 | return 0; |
394 | } | 288 | } |
395 | 289 | ||
396 | /* ----------------------------------------------------------------------- */ | 290 | static const struct i2c_device_id bt856_id[] = { |
397 | 291 | { "bt856", 0 }, | |
398 | static struct i2c_driver i2c_driver_bt856 = { | 292 | { } |
399 | .driver = { | 293 | }; |
400 | .name = "bt856", | 294 | MODULE_DEVICE_TABLE(i2c, bt856_id); |
401 | }, | ||
402 | |||
403 | .id = I2C_DRIVERID_BT856, | ||
404 | 295 | ||
405 | .attach_adapter = bt856_attach_adapter, | 296 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
406 | .detach_client = bt856_detach_client, | 297 | .name = "bt856", |
298 | .driverid = I2C_DRIVERID_BT856, | ||
407 | .command = bt856_command, | 299 | .command = bt856_command, |
300 | .probe = bt856_probe, | ||
301 | .remove = bt856_remove, | ||
302 | .id_table = bt856_id, | ||
408 | }; | 303 | }; |
409 | |||
410 | static int __init | ||
411 | bt856_init (void) | ||
412 | { | ||
413 | return i2c_add_driver(&i2c_driver_bt856); | ||
414 | } | ||
415 | |||
416 | static void __exit | ||
417 | bt856_exit (void) | ||
418 | { | ||
419 | i2c_del_driver(&i2c_driver_bt856); | ||
420 | } | ||
421 | |||
422 | module_init(bt856_init); | ||
423 | module_exit(bt856_exit); | ||