diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-09-07 06:58:20 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-17 16:15:58 -0400 |
commit | b9a21f84bc0ac39fc0b959b40aa27b2f66af243c (patch) | |
tree | 5c34f8256732f4462a655d6673e14e9122992182 /drivers/media | |
parent | 54c776a5bccf5b8c92ecdb480561df05e784128b (diff) |
V4L/DVB (9198): adv7170: convert i2c driver for new i2c API
- Convert to use v4l2-i2c-drv-legacy.h to be able to handle the new i2c API
- Cleanups
- Use v4l_dbg/v4l_info to have uniform kernel messages
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/adv7170.c | 251 |
1 files changed, 57 insertions, 194 deletions
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index f794f2dbfb32..e0eb4f321442 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.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 <asm/io.h> | ||
44 | #include <asm/pgtable.h> | ||
45 | #include <asm/page.h> | ||
46 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
47 | 35 | #include <linux/i2c.h> | |
36 | #include <linux/i2c-id.h> | ||
48 | #include <linux/videodev.h> | 37 | #include <linux/videodev.h> |
49 | #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> | ||
50 | 41 | ||
51 | MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); | 42 | MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); |
52 | MODULE_AUTHOR("Maxim Yevtyushkin"); | 43 | MODULE_AUTHOR("Maxim Yevtyushkin"); |
53 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
54 | 45 | ||
55 | |||
56 | #define I2C_NAME(x) (x)->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 | struct adv7170 { | 52 | struct adv7170 { |
@@ -80,21 +61,12 @@ struct adv7170 { | |||
80 | int sat; | 61 | int sat; |
81 | }; | 62 | }; |
82 | 63 | ||
83 | #define I2C_ADV7170 0xd4 | ||
84 | #define I2C_ADV7171 0x54 | ||
85 | |||
86 | static char adv7170_name[] = "adv7170"; | ||
87 | static char adv7171_name[] = "adv7171"; | ||
88 | |||
89 | static char *inputs[] = { "pass_through", "play_back" }; | 64 | static char *inputs[] = { "pass_through", "play_back" }; |
90 | static char *norms[] = { "PAL", "NTSC" }; | 65 | static char *norms[] = { "PAL", "NTSC" }; |
91 | 66 | ||
92 | /* ----------------------------------------------------------------------- */ | 67 | /* ----------------------------------------------------------------------- */ |
93 | 68 | ||
94 | static inline int | 69 | static inline int adv7170_write(struct i2c_client *client, u8 reg, u8 value) |
95 | adv7170_write (struct i2c_client *client, | ||
96 | u8 reg, | ||
97 | u8 value) | ||
98 | { | 70 | { |
99 | struct adv7170 *encoder = i2c_get_clientdata(client); | 71 | struct adv7170 *encoder = i2c_get_clientdata(client); |
100 | 72 | ||
@@ -102,17 +74,13 @@ adv7170_write (struct i2c_client *client, | |||
102 | return i2c_smbus_write_byte_data(client, reg, value); | 74 | return i2c_smbus_write_byte_data(client, reg, value); |
103 | } | 75 | } |
104 | 76 | ||
105 | static inline int | 77 | static inline int adv7170_read(struct i2c_client *client, u8 reg) |
106 | adv7170_read (struct i2c_client *client, | ||
107 | u8 reg) | ||
108 | { | 78 | { |
109 | return i2c_smbus_read_byte_data(client, reg); | 79 | return i2c_smbus_read_byte_data(client, reg); |
110 | } | 80 | } |
111 | 81 | ||
112 | static int | 82 | static int adv7170_write_block(struct i2c_client *client, |
113 | adv7170_write_block (struct i2c_client *client, | 83 | const u8 *data, unsigned int len) |
114 | const u8 *data, | ||
115 | unsigned int len) | ||
116 | { | 84 | { |
117 | int ret = -1; | 85 | int ret = -1; |
118 | u8 reg; | 86 | u8 reg; |
@@ -133,33 +101,25 @@ adv7170_write_block (struct i2c_client *client, | |||
133 | encoder->reg[reg++] = data[1]; | 101 | encoder->reg[reg++] = data[1]; |
134 | len -= 2; | 102 | len -= 2; |
135 | data += 2; | 103 | data += 2; |
136 | } while (len >= 2 && data[0] == reg && | 104 | } while (len >= 2 && data[0] == reg && block_len < 32); |
137 | block_len < 32); | 105 | ret = i2c_master_send(client, block_data, block_len); |
138 | if ((ret = i2c_master_send(client, block_data, | 106 | if (ret < 0) |
139 | block_len)) < 0) | ||
140 | break; | 107 | break; |
141 | } | 108 | } |
142 | } else { | 109 | } else { |
143 | /* do some slow I2C emulation kind of thing */ | 110 | /* do some slow I2C emulation kind of thing */ |
144 | while (len >= 2) { | 111 | while (len >= 2) { |
145 | reg = *data++; | 112 | reg = *data++; |
146 | if ((ret = adv7170_write(client, reg, | 113 | ret = adv7170_write(client, reg, *data++); |
147 | *data++)) < 0) | 114 | if (ret < 0) |
148 | break; | 115 | break; |
149 | len -= 2; | 116 | len -= 2; |
150 | } | 117 | } |
151 | } | 118 | } |
152 | |||
153 | return ret; | 119 | return ret; |
154 | } | 120 | } |
155 | 121 | ||
156 | /* ----------------------------------------------------------------------- */ | 122 | /* ----------------------------------------------------------------------- */ |
157 | // Output filter: S-Video Composite | ||
158 | |||
159 | #define MR050 0x11 //0x09 | ||
160 | #define MR060 0x14 //0x0c | ||
161 | |||
162 | //--------------------------------------------------------------------------- | ||
163 | 123 | ||
164 | #define TR0MODE 0x4c | 124 | #define TR0MODE 0x4c |
165 | #define TR0RST 0x80 | 125 | #define TR0RST 0x80 |
@@ -167,7 +127,6 @@ adv7170_write_block (struct i2c_client *client, | |||
167 | #define TR1CAPT 0x00 | 127 | #define TR1CAPT 0x00 |
168 | #define TR1PLAY 0x00 | 128 | #define TR1PLAY 0x00 |
169 | 129 | ||
170 | |||
171 | static const unsigned char init_NTSC[] = { | 130 | static const unsigned char init_NTSC[] = { |
172 | 0x00, 0x10, // MR0 | 131 | 0x00, 0x10, // MR0 |
173 | 0x01, 0x20, // MR1 | 132 | 0x01, 0x20, // MR1 |
@@ -227,15 +186,11 @@ static const unsigned char init_PAL[] = { | |||
227 | }; | 186 | }; |
228 | 187 | ||
229 | 188 | ||
230 | static int | 189 | static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) |
231 | adv7170_command (struct i2c_client *client, | ||
232 | unsigned int cmd, | ||
233 | void * arg) | ||
234 | { | 190 | { |
235 | struct adv7170 *encoder = i2c_get_clientdata(client); | 191 | struct adv7170 *encoder = i2c_get_clientdata(client); |
236 | 192 | ||
237 | switch (cmd) { | 193 | switch (cmd) { |
238 | |||
239 | case 0: | 194 | case 0: |
240 | #if 0 | 195 | #if 0 |
241 | /* This is just for testing!!! */ | 196 | /* This is just for testing!!! */ |
@@ -254,18 +209,16 @@ adv7170_command (struct i2c_client *client, | |||
254 | VIDEO_ENCODER_NTSC; | 209 | VIDEO_ENCODER_NTSC; |
255 | cap->inputs = 2; | 210 | cap->inputs = 2; |
256 | cap->outputs = 1; | 211 | cap->outputs = 1; |
257 | } | ||
258 | break; | 212 | break; |
213 | } | ||
259 | 214 | ||
260 | case ENCODER_SET_NORM: | 215 | case ENCODER_SET_NORM: |
261 | { | 216 | { |
262 | int iarg = *(int *) arg; | 217 | int iarg = *(int *) arg; |
263 | 218 | ||
264 | dprintk(1, KERN_DEBUG "%s_command: set norm %d", | 219 | v4l_dbg(1, debug, client, "set norm %d\n", iarg); |
265 | I2C_NAME(client), iarg); | ||
266 | 220 | ||
267 | switch (iarg) { | 221 | switch (iarg) { |
268 | |||
269 | case VIDEO_MODE_NTSC: | 222 | case VIDEO_MODE_NTSC: |
270 | adv7170_write_block(client, init_NTSC, | 223 | adv7170_write_block(client, init_NTSC, |
271 | sizeof(init_NTSC)); | 224 | sizeof(init_NTSC)); |
@@ -285,16 +238,13 @@ adv7170_command (struct i2c_client *client, | |||
285 | break; | 238 | break; |
286 | 239 | ||
287 | default: | 240 | default: |
288 | dprintk(1, KERN_ERR "%s: illegal norm: %d\n", | 241 | v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg); |
289 | I2C_NAME(client), iarg); | ||
290 | return -EINVAL; | 242 | return -EINVAL; |
291 | |||
292 | } | 243 | } |
293 | dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client), | 244 | v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]); |
294 | norms[iarg]); | ||
295 | encoder->norm = iarg; | 245 | encoder->norm = iarg; |
296 | } | ||
297 | break; | 246 | break; |
247 | } | ||
298 | 248 | ||
299 | case ENCODER_SET_INPUT: | 249 | case ENCODER_SET_INPUT: |
300 | { | 250 | { |
@@ -304,19 +254,17 @@ adv7170_command (struct i2c_client *client, | |||
304 | *iarg = 1: input is from ZR36060 | 254 | *iarg = 1: input is from ZR36060 |
305 | *iarg = 2: color bar */ | 255 | *iarg = 2: color bar */ |
306 | 256 | ||
307 | dprintk(1, KERN_DEBUG "%s_command: set input from %s\n", | 257 | v4l_dbg(1, debug, client, "set input from %s\n", |
308 | I2C_NAME(client), | ||
309 | iarg == 0 ? "decoder" : "ZR36060"); | 258 | iarg == 0 ? "decoder" : "ZR36060"); |
310 | 259 | ||
311 | switch (iarg) { | 260 | switch (iarg) { |
312 | |||
313 | case 0: | 261 | case 0: |
314 | adv7170_write(client, 0x01, 0x20); | 262 | adv7170_write(client, 0x01, 0x20); |
315 | adv7170_write(client, 0x08, TR1CAPT); /* TR1 */ | 263 | adv7170_write(client, 0x08, TR1CAPT); /* TR1 */ |
316 | adv7170_write(client, 0x02, 0x0e); // Enable genlock | 264 | adv7170_write(client, 0x02, 0x0e); // Enable genlock |
317 | adv7170_write(client, 0x07, TR0MODE | TR0RST); | 265 | adv7170_write(client, 0x07, TR0MODE | TR0RST); |
318 | adv7170_write(client, 0x07, TR0MODE); | 266 | adv7170_write(client, 0x07, TR0MODE); |
319 | //udelay(10); | 267 | /* udelay(10); */ |
320 | break; | 268 | break; |
321 | 269 | ||
322 | case 1: | 270 | case 1: |
@@ -325,20 +273,17 @@ adv7170_command (struct i2c_client *client, | |||
325 | adv7170_write(client, 0x02, 0x08); | 273 | adv7170_write(client, 0x02, 0x08); |
326 | adv7170_write(client, 0x07, TR0MODE | TR0RST); | 274 | adv7170_write(client, 0x07, TR0MODE | TR0RST); |
327 | adv7170_write(client, 0x07, TR0MODE); | 275 | adv7170_write(client, 0x07, TR0MODE); |
328 | //udelay(10); | 276 | /* udelay(10); */ |
329 | break; | 277 | break; |
330 | 278 | ||
331 | default: | 279 | default: |
332 | dprintk(1, KERN_ERR "%s: illegal input: %d\n", | 280 | v4l_dbg(1, debug, client, "illegal input: %d\n", iarg); |
333 | I2C_NAME(client), iarg); | ||
334 | return -EINVAL; | 281 | return -EINVAL; |
335 | |||
336 | } | 282 | } |
337 | dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client), | 283 | v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]); |
338 | inputs[iarg]); | ||
339 | encoder->input = iarg; | 284 | encoder->input = iarg; |
340 | } | ||
341 | break; | 285 | break; |
286 | } | ||
342 | 287 | ||
343 | case ENCODER_SET_OUTPUT: | 288 | case ENCODER_SET_OUTPUT: |
344 | { | 289 | { |
@@ -348,16 +293,16 @@ adv7170_command (struct i2c_client *client, | |||
348 | if (*iarg != 0) { | 293 | if (*iarg != 0) { |
349 | return -EINVAL; | 294 | return -EINVAL; |
350 | } | 295 | } |
351 | } | ||
352 | break; | 296 | break; |
297 | } | ||
353 | 298 | ||
354 | case ENCODER_ENABLE_OUTPUT: | 299 | case ENCODER_ENABLE_OUTPUT: |
355 | { | 300 | { |
356 | int *iarg = arg; | 301 | int *iarg = arg; |
357 | 302 | ||
358 | encoder->enable = !!*iarg; | 303 | encoder->enable = !!*iarg; |
359 | } | ||
360 | break; | 304 | break; |
305 | } | ||
361 | 306 | ||
362 | default: | 307 | default: |
363 | return -EINVAL; | 308 | return -EINVAL; |
@@ -368,149 +313,67 @@ adv7170_command (struct i2c_client *client, | |||
368 | 313 | ||
369 | /* ----------------------------------------------------------------------- */ | 314 | /* ----------------------------------------------------------------------- */ |
370 | 315 | ||
371 | /* | 316 | static unsigned short normal_i2c[] = { |
372 | * Generic i2c probe | 317 | 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */ |
373 | * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' | 318 | 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */ |
374 | */ | ||
375 | static unsigned short normal_i2c[] = | ||
376 | { I2C_ADV7170 >> 1, (I2C_ADV7170 >> 1) + 1, | ||
377 | I2C_ADV7171 >> 1, (I2C_ADV7171 >> 1) + 1, | ||
378 | I2C_CLIENT_END | 319 | I2C_CLIENT_END |
379 | }; | 320 | }; |
380 | 321 | ||
381 | static unsigned short ignore = I2C_CLIENT_END; | 322 | I2C_CLIENT_INSMOD; |
382 | 323 | ||
383 | static struct i2c_client_address_data addr_data = { | 324 | static int adv7170_probe(struct i2c_client *client, |
384 | .normal_i2c = normal_i2c, | 325 | const struct i2c_device_id *id) |
385 | .probe = &ignore, | ||
386 | .ignore = &ignore, | ||
387 | }; | ||
388 | |||
389 | static struct i2c_driver i2c_driver_adv7170; | ||
390 | |||
391 | static int | ||
392 | adv7170_detect_client (struct i2c_adapter *adapter, | ||
393 | int address, | ||
394 | int kind) | ||
395 | { | 326 | { |
396 | int i; | ||
397 | struct i2c_client *client; | ||
398 | struct adv7170 *encoder; | 327 | struct adv7170 *encoder; |
399 | char *dname; | 328 | int i; |
400 | |||
401 | dprintk(1, | ||
402 | KERN_INFO | ||
403 | "adv7170.c: detecting adv7170 client on address 0x%x\n", | ||
404 | address << 1); | ||
405 | 329 | ||
406 | /* Check if the adapter supports the needed features */ | 330 | /* Check if the adapter supports the needed features */ |
407 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 331 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
408 | return 0; | 332 | return -ENODEV; |
409 | 333 | ||
410 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | 334 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
411 | if (!client) | 335 | client->addr << 1, client->adapter->name); |
412 | return -ENOMEM; | ||
413 | client->addr = address; | ||
414 | client->adapter = adapter; | ||
415 | client->driver = &i2c_driver_adv7170; | ||
416 | if ((client->addr == I2C_ADV7170 >> 1) || | ||
417 | (client->addr == (I2C_ADV7170 >> 1) + 1)) { | ||
418 | dname = adv7170_name; | ||
419 | } else if ((client->addr == I2C_ADV7171 >> 1) || | ||
420 | (client->addr == (I2C_ADV7171 >> 1) + 1)) { | ||
421 | dname = adv7171_name; | ||
422 | } else { | ||
423 | /* We should never get here!!! */ | ||
424 | kfree(client); | ||
425 | return 0; | ||
426 | } | ||
427 | strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client))); | ||
428 | 336 | ||
429 | encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL); | 337 | encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL); |
430 | if (encoder == NULL) { | 338 | if (encoder == NULL) |
431 | kfree(client); | ||
432 | return -ENOMEM; | 339 | return -ENOMEM; |
433 | } | ||
434 | encoder->norm = VIDEO_MODE_NTSC; | 340 | encoder->norm = VIDEO_MODE_NTSC; |
435 | encoder->input = 0; | 341 | encoder->input = 0; |
436 | encoder->enable = 1; | 342 | encoder->enable = 1; |
437 | i2c_set_clientdata(client, encoder); | 343 | i2c_set_clientdata(client, encoder); |
438 | 344 | ||
439 | i = i2c_attach_client(client); | ||
440 | if (i) { | ||
441 | kfree(client); | ||
442 | kfree(encoder); | ||
443 | return i; | ||
444 | } | ||
445 | |||
446 | i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); | 345 | i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); |
447 | if (i >= 0) { | 346 | if (i >= 0) { |
448 | i = adv7170_write(client, 0x07, TR0MODE | TR0RST); | 347 | i = adv7170_write(client, 0x07, TR0MODE | TR0RST); |
449 | i = adv7170_write(client, 0x07, TR0MODE); | 348 | i = adv7170_write(client, 0x07, TR0MODE); |
450 | i = adv7170_read(client, 0x12); | 349 | i = adv7170_read(client, 0x12); |
451 | dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%02x\n", | 350 | v4l_dbg(1, debug, client, "revision %d\n", i & 1); |
452 | I2C_NAME(client), i & 1, client->addr << 1); | ||
453 | } | ||
454 | if (i < 0) { | ||
455 | dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n", | ||
456 | I2C_NAME(client), i); | ||
457 | } | 351 | } |
458 | 352 | if (i < 0) | |
353 | v4l_dbg(1, debug, client, "init error 0x%x\n", i); | ||
459 | return 0; | 354 | return 0; |
460 | } | 355 | } |
461 | 356 | ||
462 | static int | 357 | static int adv7170_remove(struct i2c_client *client) |
463 | adv7170_attach_adapter (struct i2c_adapter *adapter) | ||
464 | { | ||
465 | dprintk(1, | ||
466 | KERN_INFO | ||
467 | "adv7170.c: starting probe for adapter %s (0x%x)\n", | ||
468 | I2C_NAME(adapter), adapter->id); | ||
469 | return i2c_probe(adapter, &addr_data, &adv7170_detect_client); | ||
470 | } | ||
471 | |||
472 | static int | ||
473 | adv7170_detach_client (struct i2c_client *client) | ||
474 | { | 358 | { |
475 | struct adv7170 *encoder = i2c_get_clientdata(client); | 359 | kfree(i2c_get_clientdata(client)); |
476 | int err; | ||
477 | |||
478 | err = i2c_detach_client(client); | ||
479 | if (err) { | ||
480 | return err; | ||
481 | } | ||
482 | |||
483 | kfree(encoder); | ||
484 | kfree(client); | ||
485 | |||
486 | return 0; | 360 | return 0; |
487 | } | 361 | } |
488 | 362 | ||
489 | /* ----------------------------------------------------------------------- */ | 363 | /* ----------------------------------------------------------------------- */ |
490 | 364 | ||
491 | static struct i2c_driver i2c_driver_adv7170 = { | 365 | static const struct i2c_device_id adv7170_id[] = { |
492 | .driver = { | 366 | { "adv7170", 0 }, |
493 | .name = "adv7170", /* name */ | 367 | { "adv7171", 0 }, |
494 | }, | 368 | { } |
495 | 369 | }; | |
496 | .id = I2C_DRIVERID_ADV7170, | 370 | MODULE_DEVICE_TABLE(i2c, adv7170_id); |
497 | 371 | ||
498 | .attach_adapter = adv7170_attach_adapter, | 372 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
499 | .detach_client = adv7170_detach_client, | 373 | .name = "adv7170", |
374 | .driverid = I2C_DRIVERID_ADV7170, | ||
500 | .command = adv7170_command, | 375 | .command = adv7170_command, |
376 | .probe = adv7170_probe, | ||
377 | .remove = adv7170_remove, | ||
378 | .id_table = adv7170_id, | ||
501 | }; | 379 | }; |
502 | |||
503 | static int __init | ||
504 | adv7170_init (void) | ||
505 | { | ||
506 | return i2c_add_driver(&i2c_driver_adv7170); | ||
507 | } | ||
508 | |||
509 | static void __exit | ||
510 | adv7170_exit (void) | ||
511 | { | ||
512 | i2c_del_driver(&i2c_driver_adv7170); | ||
513 | } | ||
514 | |||
515 | module_init(adv7170_init); | ||
516 | module_exit(adv7170_exit); | ||