summaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c/lc898212.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/lc898212.c')
-rw-r--r--drivers/media/i2c/lc898212.c645
1 files changed, 645 insertions, 0 deletions
diff --git a/drivers/media/i2c/lc898212.c b/drivers/media/i2c/lc898212.c
new file mode 100644
index 000000000..44cdb876e
--- /dev/null
+++ b/drivers/media/i2c/lc898212.c
@@ -0,0 +1,645 @@
1/*
2 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/delay.h>
18#include <linux/fs.h>
19#include <linux/i2c.h>
20#include <linux/miscdevice.h>
21#include <linux/regulator/consumer.h>
22#include <linux/slab.h>
23#include <linux/uaccess.h>
24#include <linux/module.h>
25#include <linux/regmap.h>
26#include <linux/gpio.h>
27#include <linux/of.h>
28#include <linux/of_device.h>
29#include <linux/of_gpio.h>
30
31#include <media/camera_common.h>
32
33#include "tegra_camera_dev_mfi.h"
34
35#define LC898212_ACTUATOR_RANGE 1023
36#define LC898212_POS_LOW_DEFAULT (0)
37#define LC898212_POS_HIGH_DEFAULT (1023)
38#define LC898212_FOCUS_MACRO (896)
39#define LC898212_FOCUS_INFINITY (128)
40#define LC898212_PWR_DEV_OFF (0)
41#define LC898212_PWR_DEV_ON (1)
42
43#define SETTLETIME_MS (15)
44#define FOCAL_LENGTH (47300)
45#define MAX_APERTURE (22000)
46#define FNUMBER (22000)
47#define LC898212_MOVE_TIME_VALUE (0x43)
48
49#define LC898212_MAX_RETRIES (3)
50
51#define LC898212_WAIT_REPEAT 0xFE
52#define LC898212_TABLE_END 0xFF
53
54#define LC898212_REG_ACCESS 0x1
55#define LC898212_RAM_ACCESS 0x2
56
57#define AF_MIN 0
58#define AF_MAX 1023
59#define AF_RANGE (AF_MAX - AF_MIN + 1)
60
61#define LC898212_RZ 0x04
62#define LC898212_ADOFFSET 0x3C
63#define LC898212_EQENBL 0x87
64
65/**
66* standard + custom controls
67* custom controls not added for this focuser yet
68*/
69#define NUM_FOCUS_STD_CTRLS 1
70#define NUM_FOCUS_CUSTOM_CTRLS 0
71#define NUM_FOCUS_CTRLS (NUM_FOCUS_STD_CTRLS + NUM_FOCUS_CUSTOM_CTRLS)
72
73static int lc898212_s_ctrl(struct v4l2_ctrl *ctrl);
74
75struct lc898212_reg {
76 u8 type;
77 u8 addr;
78 u16 val;
79};
80
81struct lc898212 {
82 struct i2c_client *i2c_client;
83 struct v4l2_subdev *subdev;
84 struct media_pad pad;
85
86 struct v4l2_ctrl_handler ctrl_handler;
87 struct regulator *regulator;
88 struct camera_common_focuser_data *s_data;
89 struct regmap *regmap8;
90 struct regmap *regmap16;
91 int numctrls;
92 struct camera_mfi_dev *cmfi_dev16;
93 bool support_mfi;
94 struct v4l2_ctrl *ctrls[];
95};
96
97static struct lc898212_reg lc898212_init_setting[] = {
98 {LC898212_REG_ACCESS, 0x80, 0x34},
99 {LC898212_REG_ACCESS, 0x81, 0xA0},
100 {LC898212_REG_ACCESS, 0x84, 0xE0},
101 {LC898212_REG_ACCESS, 0x87, 0x05},
102 {LC898212_REG_ACCESS, 0xA4, 0x24},
103 {LC898212_RAM_ACCESS, 0x3A, 0x0000},
104 {LC898212_RAM_ACCESS, 0x04, 0x0000},
105 {LC898212_RAM_ACCESS, 0x02, 0x0000},
106 {LC898212_RAM_ACCESS, 0x18, 0x0000},
107
108 /* Filter Setting */
109 {LC898212_RAM_ACCESS, 0x40, 0x4030},
110 {LC898212_RAM_ACCESS, 0x42, 0x7150},
111 {LC898212_RAM_ACCESS, 0x44, 0x8F90},
112 {LC898212_RAM_ACCESS, 0x46, 0x61B0},
113 {LC898212_RAM_ACCESS, 0x48, 0x7FF0},
114 {LC898212_RAM_ACCESS, 0x4A, 0x3930},
115 {LC898212_RAM_ACCESS, 0x4C, 0x4030},
116 {LC898212_RAM_ACCESS, 0x4E, 0x8010},
117 {LC898212_RAM_ACCESS, 0x50, 0x04F0},
118 {LC898212_RAM_ACCESS, 0x52, 0x7610},
119 {LC898212_RAM_ACCESS, 0x54, 0x2030},
120 {LC898212_RAM_ACCESS, 0x56, 0x0000},
121 {LC898212_RAM_ACCESS, 0x58, 0x7FF0},
122 {LC898212_RAM_ACCESS, 0x5A, 0x0680},
123 {LC898212_RAM_ACCESS, 0x5C, 0x72F0},
124 {LC898212_RAM_ACCESS, 0x5E, 0x7F70},
125 {LC898212_RAM_ACCESS, 0x60, 0x7ED0},
126 {LC898212_RAM_ACCESS, 0x62, 0x7FF0},
127 {LC898212_RAM_ACCESS, 0x64, 0x0000},
128 {LC898212_RAM_ACCESS, 0x66, 0x0000},
129 {LC898212_RAM_ACCESS, 0x68, 0x5130},
130 {LC898212_RAM_ACCESS, 0x6A, 0x72F0},
131 {LC898212_RAM_ACCESS, 0x6C, 0x8010},
132 {LC898212_RAM_ACCESS, 0x6E, 0x0000},
133 {LC898212_RAM_ACCESS, 0x70, 0x0000},
134 {LC898212_RAM_ACCESS, 0x72, 0x18E0},
135 {LC898212_RAM_ACCESS, 0x74, 0x4E30},
136 {LC898212_RAM_ACCESS, 0x30, 0x0000},
137 {LC898212_RAM_ACCESS, 0x76, 0x0C50},
138 {LC898212_RAM_ACCESS, 0x78, 0x4000},
139
140 {LC898212_REG_ACCESS, 0x86, 0x60},
141 {LC898212_REG_ACCESS, 0x88, 0x70},
142 {LC898212_RAM_ACCESS, 0x28, 0x8020},
143 {LC898212_RAM_ACCESS, 0x4C, 0x4000},
144 {LC898212_REG_ACCESS, 0x83, 0x2C},
145 {LC898212_REG_ACCESS, 0x85, 0xC0},
146
147 /* Repeat to read the register until the value turns 0x00 */
148 {LC898212_REG_ACCESS, LC898212_WAIT_REPEAT, 0x85},
149
150 {LC898212_REG_ACCESS, 0x84, 0xE3},
151 {LC898212_REG_ACCESS, 0x97, 0x00},
152 {LC898212_REG_ACCESS, 0x98, 0x42},
153 {LC898212_REG_ACCESS, 0x99, 0x00},
154 {LC898212_REG_ACCESS, 0x9A, 0x00},
155
156 {LC898212_REG_ACCESS, LC898212_TABLE_END, 0x00}
157};
158
159const struct of_device_id lc898212_of_match[] = {
160 { .compatible = "nvidia,lc898212", },
161 { },
162};
163MODULE_DEVICE_TABLE(of, lc898212_of_match);
164
165static int lc898212_set_position(struct lc898212 *priv, u32 position)
166{
167 int ret = 0;
168 s16 new_pos = 0;
169 struct camera_common_focuser_data *s_data = priv->s_data;
170 struct nv_focuser_config *cfg = &s_data->config;
171
172 dev_dbg(&s_data->i2c_client->dev, "%s++\n", __func__);
173 if (position < cfg->pos_actual_low ||
174 position > cfg->pos_actual_high) {
175 dev_dbg(&priv->i2c_client->dev,
176 "%s: position(%d) out of bound([%d, %d])\n",
177 __func__, position, cfg->pos_actual_low,
178 cfg->pos_actual_high);
179 if (position < cfg->pos_actual_low)
180 position = cfg->pos_actual_low;
181 if (position > cfg->pos_actual_high)
182 position = cfg->pos_actual_high;
183 }
184
185 /* unsigned 10 bit to signed 16 bit */
186 new_pos = ((s16) position - AF_RANGE / 2) * 64;
187
188 if (priv->support_mfi) {
189 ret = tegra_camera_dev_mfi_clear(priv->cmfi_dev16);
190 ret |= tegra_camera_dev_mfi_wr_add(priv->cmfi_dev16,
191 LC898212_RZ,
192 (u16) new_pos);
193 } else {
194 ret = regmap_write(priv->regmap16, LC898212_RZ, (u16) new_pos);
195 }
196
197 dev_dbg(&s_data->i2c_client->dev, "%s--\n", __func__);
198 return ret;
199}
200
201/*
202 * V4l2 controls
203 */
204
205static const struct v4l2_ctrl_ops lc898212_ctrl_ops = {
206 .s_ctrl = lc898212_s_ctrl,
207};
208
209static int lc898212_s_ctrl(struct v4l2_ctrl *ctrl)
210{
211 struct lc898212 *priv =
212 container_of(ctrl->handler, struct lc898212, ctrl_handler);
213 int err;
214
215 dev_dbg(&priv->s_data->i2c_client->dev, "%s++\n", __func__);
216 /* check for power state */
217 if (priv->s_data->pwr_dev == LC898212_PWR_DEV_OFF)
218 return -ENODEV;
219
220 switch (ctrl->id) {
221 case V4L2_CID_FOCUS_ABSOLUTE:
222 err = lc898212_set_position(priv, ctrl->val);
223 break;
224 default:
225 pr_err("%s: unknown v4l2 ctlr id\n", __func__);
226 return -EINVAL;
227 }
228
229 return err;
230}
231
232static int lc898212_ctrls_init(struct camera_common_focuser_data *s_data)
233{
234 struct lc898212 *priv = (struct lc898212 *)s_data->priv;
235 struct i2c_client *client = priv->i2c_client;
236 struct v4l2_ctrl *ctrl;
237 struct nv_focuser_config *cfg = &s_data->config;
238 int min = cfg->pos_actual_low;
239 int max = cfg->pos_actual_high;
240 int def = priv->s_data->def_position;
241 int err = 0;
242
243 v4l2_ctrl_handler_init(&priv->ctrl_handler, priv->numctrls);
244 priv->subdev->ctrl_handler = &priv->ctrl_handler;
245 err = priv->ctrl_handler.error;
246 if (err) {
247 dev_err(&client->dev, "Error %d adding controls\n", err);
248 goto error;
249 }
250
251 /* add std controls */
252 ctrl = v4l2_ctrl_new_std(&priv->ctrl_handler, &lc898212_ctrl_ops,
253 V4L2_CID_FOCUS_ABSOLUTE, min, max, 1, def);
254 if (ctrl == NULL) {
255 dev_err(&client->dev, "Error initializing controls\n");
256 err = -EINVAL;
257 goto error;
258 }
259 priv->ctrls[0] = ctrl;
260
261 err = v4l2_ctrl_handler_setup(&priv->ctrl_handler);
262 if (err) {
263 dev_err(&client->dev, "Error setting default controls\n");
264 goto error;
265 }
266
267 return 0;
268error:
269 v4l2_ctrl_handler_free(&priv->ctrl_handler);
270 return err;
271}
272
273static int lc898212_write_table(struct lc898212 *priv,
274 const struct lc898212_reg table[])
275{
276 int err;
277 const struct lc898212_reg *next;
278 u16 val;
279
280 for (next = table; next->addr != LC898212_TABLE_END; next++) {
281 val = next->val;
282
283 if (next->addr == LC898212_WAIT_REPEAT) {
284 u8 data = 0;
285 u8 count = 0;
286
287 err = regmap_read(priv->regmap8, val,
288 (unsigned int *) &data);
289 if (err) {
290 pr_err("%s: regmap_read: %d\n", __func__, err);
291 return err;
292 }
293 while (data != 0) {
294 if (count >= 10)
295 return -EFAULT; /* focuser not ready */
296
297 usleep_range(10, 20);
298 err = regmap_read(priv->regmap8, val,
299 (unsigned int *) &data);
300 if (err) {
301 pr_err("%s: regmap_read: %d\n",
302 __func__, err);
303 return err;
304 }
305 count++;
306 }
307 continue;
308 }
309
310 if (next->type == LC898212_RAM_ACCESS)
311 err = regmap_write(priv->regmap16, next->addr, val);
312 else
313 err = regmap_write(priv->regmap8, next->addr, val);
314 if (err) {
315 pr_err("%s:lc898212_write_table:%d", __func__, err);
316 return err;
317 }
318 }
319 return 0;
320}
321
322static unsigned int convert_signed16b_to_unsigned10b(s16 data)
323{
324 return (u16)(data / 64 + (AF_RANGE>>1));
325}
326
327static int lc898212_init(struct lc898212 *priv)
328{
329 int err;
330 int data;
331
332 err = lc898212_write_table(priv, lc898212_init_setting);
333
334 err |= regmap_read(priv->regmap16, LC898212_ADOFFSET, &data);
335 priv->s_data->def_position =
336 convert_signed16b_to_unsigned10b((s16)(data & 0xffff));
337 err |= regmap_write(priv->regmap16, LC898212_RZ, data);
338
339 /* Servo On */
340 err |= regmap_write(priv->regmap8, LC898212_EQENBL, 0x85);
341
342 return err;
343}
344
345static int lc898212_load_config(struct camera_common_focuser_data *s_data)
346{
347 struct nv_focuser_config *cfg = &s_data->config;
348
349 /* load default configuration */
350 /* TODO: parse these values from DT */
351
352 cfg->focal_length = FOCAL_LENGTH;
353 cfg->fnumber = FNUMBER;
354 cfg->max_aperture = MAX_APERTURE;
355 cfg->range_ends_reversed = 0;
356
357 cfg->pos_working_low = LC898212_FOCUS_INFINITY;
358 cfg->pos_working_high = LC898212_FOCUS_MACRO;
359 cfg->pos_actual_low = LC898212_POS_LOW_DEFAULT;
360 cfg->pos_actual_high = LC898212_POS_HIGH_DEFAULT;
361
362 cfg->num_focuser_sets = 1;
363 cfg->focuser_set[0].macro = LC898212_FOCUS_MACRO;
364 cfg->focuser_set[0].hyper = LC898212_FOCUS_INFINITY;
365 cfg->focuser_set[0].inf = LC898212_FOCUS_INFINITY;
366 cfg->focuser_set[0].settle_time = SETTLETIME_MS;
367
368 return 0;
369}
370
371static int lc898212_power_off(struct camera_common_focuser_data *s_data)
372{
373 struct lc898212 *priv = (struct lc898212 *)s_data->priv;
374
375 dev_dbg(&s_data->i2c_client->dev, "%s++\n", __func__);
376 if (priv->regulator)
377 regulator_disable(priv->regulator);
378 s_data->pwr_dev = LC898212_PWR_DEV_OFF;
379
380 return 0;
381}
382
383static int lc898212_power_on(struct camera_common_focuser_data *s_data)
384{
385 int err = 0;
386 struct lc898212 *priv = (struct lc898212 *)s_data->priv;
387
388 dev_dbg(&s_data->i2c_client->dev, "%s++\n", __func__);
389 if (priv->regulator) {
390 err = regulator_enable(priv->regulator);
391 if (err) {
392 dev_err(&s_data->i2c_client->dev,
393 "%s:regulator enabled failed\n", __func__);
394 return err;
395 }
396 }
397
398 err = lc898212_init(priv);
399 if (err)
400 return err;
401
402 s_data->pwr_dev = LC898212_PWR_DEV_ON;
403
404 return 0;
405}
406
407static struct camera_common_focuser_ops lc898212_ops = {
408 .power_on = lc898212_power_on,
409 .power_off = lc898212_power_off,
410 .load_config = lc898212_load_config,
411 .ctrls_init = lc898212_ctrls_init,
412};
413
414#if 0
415static int lc898212_s_stream(struct v4l2_subdev *sd, int enable)
416{
417 struct i2c_client *client = v4l2_get_subdevdata(sd);
418 struct camera_common_focuser_data *s_data =
419 to_camera_common_focuser_data(client);
420 struct lc898212 *priv = (struct lc898212 *)s_data->priv;
421 struct v4l2_control control;
422 int err = 0;
423
424 dev_dbg(&client->dev, "%s++\n", __func__);
425 err = lc898212_init(priv);
426 if (err)
427 return err;
428
429 /* write override registers for focus position */
430 control.id = V4L2_CID_FOCUS_ABSOLUTE;
431 err = v4l2_g_ctrl(&priv->ctrl_handler, &control);
432 err |= lc898212_set_position(priv, control.value);
433 if (err)
434 dev_dbg(&client->dev, "%s:warning focus pos %d set failed\n",
435 __func__, control.value);
436
437 dev_dbg(&client->dev, "%s--\n", __func__);
438 return 0;
439}
440
441static struct v4l2_subdev_video_ops lc898212_subdev_video_ops = {
442 .s_stream = lc898212_s_stream,
443};
444
445#endif
446
447static int lc898212_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
448{
449 struct i2c_client *client = v4l2_get_subdevdata(sd);
450
451 dev_dbg(&client->dev, "%s:\n", __func__);
452 return 0;
453}
454
455static struct v4l2_subdev_core_ops lc898212_subdev_core_ops = {
456 .s_power = camera_common_focuser_s_power,
457};
458
459static struct v4l2_subdev_ops lc898212_subdev_ops = {
460 .core = &lc898212_subdev_core_ops,
461};
462
463static const struct v4l2_subdev_internal_ops lc898212_subdev_internal_ops = {
464 .open = lc898212_open,
465};
466
467static const struct media_entity_operations lc898212_media_ops = {
468#ifdef CONFIG_MEDIA_CONTROLLER
469 .link_validate = v4l2_subdev_link_validate,
470#endif
471};
472
473static int lc898212_probe(struct i2c_client *client,
474 const struct i2c_device_id *id)
475{
476 int err;
477 struct lc898212 *priv;
478 struct camera_common_focuser_data *common_data;
479 char dev_id[20];
480 const char *p_mfi_str;
481
482 static struct regmap_config lc898212_regmap_config8 = {
483 .reg_bits = 8,
484 .val_bits = 8,
485 .name = "8bit",
486 };
487 static struct regmap_config lc898212_regmap_config16 = {
488 .reg_bits = 8,
489 .val_bits = 16,
490 .name = "16bit",
491 };
492
493 pr_info("[lc898212]: probing sensor\n");
494
495 common_data = devm_kzalloc(&client->dev,
496 sizeof(struct camera_common_focuser_data), GFP_KERNEL);
497 if (!common_data)
498 return -ENOMEM;
499
500 priv = devm_kzalloc(&client->dev, (sizeof(struct lc898212) +
501 sizeof(struct v4l2_ctrl *) * NUM_FOCUS_CTRLS), GFP_KERNEL);
502 if (!priv)
503 return -ENOMEM;
504
505 priv->regulator = devm_regulator_get(&client->dev, "vvcm");
506 if (IS_ERR(priv->regulator)) {
507 dev_err(&client->dev, "unable to get regulator %s\n",
508 dev_name(&client->dev));
509 priv->regulator = NULL;
510 }
511
512 priv->regmap8 = devm_regmap_init_i2c(client,
513 &lc898212_regmap_config8);
514 if (IS_ERR(priv->regmap8)) {
515 err = PTR_ERR(priv->regmap8);
516 dev_err(&client->dev,
517 "Failed to allocate register map 8: %d\n", err);
518 goto ERROR_RET;
519 }
520 priv->regmap16 = devm_regmap_init_i2c(client,
521 &lc898212_regmap_config16);
522 if (IS_ERR(priv->regmap16)) {
523 err = PTR_ERR(priv->regmap16);
524 dev_err(&client->dev,
525 "Failed to allocate register map 16: %d\n", err);
526 goto ERROR_RET;
527 }
528
529 common_data->ops = &lc898212_ops;
530 common_data->ctrl_handler = &priv->ctrl_handler;
531 common_data->i2c_client = client;
532 common_data->ctrls = priv->ctrls;
533 common_data->priv = (void *)priv;
534 priv->numctrls = NUM_FOCUS_CTRLS;
535 priv->i2c_client = client;
536 priv->s_data = common_data;
537 priv->subdev = &common_data->subdev;
538 priv->subdev->dev = &client->dev;
539
540 if (client->dev.of_node) {
541 err = of_property_read_string(client->dev.of_node,
542 "support_mfi",
543 &p_mfi_str);
544 if (err < 0) {
545 dev_err(&client->dev,
546 "%s unable to read MFI property\n",
547 __func__);
548 goto ERROR_RET;
549 }
550
551 priv->support_mfi = !strcmp(p_mfi_str, "true") ? true : false;
552
553 if (priv->support_mfi) {
554 int remain;
555
556 memset(dev_id, 0, sizeof(dev_id));
557 strncpy(dev_id, "lc898212", (sizeof(dev_id) - 1));
558 /* calculate how many bytes remaining in dev_id[] */
559 remain = sizeof(dev_id) - strlen(dev_id) - 1;
560 /* strncat most of 'remain' bytes from dev_name[] */
561 strncat(dev_id, dev_name(&client->dev), remain);
562 err = tegra_camera_dev_mfi_add_regmap(&priv->cmfi_dev16,
563 dev_id, priv->regmap16);
564 if (err < 0) {
565 dev_err(&client->dev,
566 "%s unable to add to mfi regmap\n",
567 __func__);
568 goto ERROR_RET;
569 }
570 }
571 }
572
573 err = camera_common_focuser_init(common_data);
574 if (err) {
575 dev_err(&client->dev, "unable to initialize focuser\n");
576 goto ERROR_RET;
577 }
578
579 v4l2_i2c_subdev_init(priv->subdev, client, &lc898212_subdev_ops);
580
581 priv->subdev->internal_ops = &lc898212_subdev_internal_ops;
582 priv->subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
583 V4L2_SUBDEV_FL_HAS_EVENTS;
584
585#if defined(CONFIG_MEDIA_CONTROLLER)
586 priv->pad.flags = MEDIA_PAD_FL_SOURCE;
587 priv->subdev->entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
588 priv->subdev->entity.ops = &lc898212_media_ops;
589 err = media_entity_init(&priv->subdev->entity, 1, &priv->pad, 0);
590 if (err < 0) {
591 dev_err(&client->dev, "unable to init media entity\n");
592 goto ERROR_RET;
593 }
594#endif
595
596 err = v4l2_async_register_subdev(priv->subdev);
597 if (err)
598 goto ERROR_RET;
599
600 dev_dbg(&client->dev, "Detected lc898212 sensor\n");
601 return 0;
602
603ERROR_RET:
604 dev_err(&client->dev, "lc898212: probing sensor failed!!\n");
605 return err;
606}
607
608static int lc898212_remove(struct i2c_client *client)
609{
610 struct camera_common_focuser_data *s_data =
611 to_camera_common_focuser_data(client);
612 struct lc898212 *priv = (struct lc898212 *)s_data->priv;
613
614 v4l2_async_unregister_subdev(priv->subdev);
615#if defined(CONFIG_MEDIA_CONTROLLER)
616 media_entity_cleanup(&priv->subdev->entity);
617#endif
618 v4l2_ctrl_handler_free(&priv->ctrl_handler);
619
620 return 0;
621}
622
623static const struct i2c_device_id lc898212_id[] = {
624 { "lc898212", 0 },
625 { },
626};
627
628MODULE_DEVICE_TABLE(i2c, lc898212_id);
629
630static struct i2c_driver lc898212_i2c_driver = {
631 .driver = {
632 .name = "lc898212",
633 .owner = THIS_MODULE,
634 .of_match_table = of_match_ptr(lc898212_of_match),
635 },
636 .probe = lc898212_probe,
637 .remove = lc898212_remove,
638 .id_table = lc898212_id,
639};
640
641module_i2c_driver(lc898212_i2c_driver);
642
643MODULE_DESCRIPTION("I2C driver for LC898212");
644MODULE_AUTHOR("Bhanu Murthy V <bmurthyv@nvidia.com>");
645MODULE_LICENSE("GPL v2");