diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-09-07 04:42:15 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-02-05 15:02:49 -0500 |
commit | ea01a83d5c88a3e0bb124ec4b3abf3aefcf0d719 (patch) | |
tree | ea64349f3dc44692457d54305adea592281888f5 /drivers/media/i2c/mt9v011.c | |
parent | 28718152e0a78085297ec7705f53869e41d1ae73 (diff) |
[media] mt9v011: convert to the control framework
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Frank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/i2c/mt9v011.c')
-rw-r--r-- | drivers/media/i2c/mt9v011.c | 223 |
1 files changed, 67 insertions, 156 deletions
diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index 6bf01ad62765..73b7688cbebd 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/div64.h> | 13 | #include <asm/div64.h> |
14 | #include <media/v4l2-device.h> | 14 | #include <media/v4l2-device.h> |
15 | #include <media/v4l2-chip-ident.h> | 15 | #include <media/v4l2-chip-ident.h> |
16 | #include <media/v4l2-ctrls.h> | ||
16 | #include <media/mt9v011.h> | 17 | #include <media/mt9v011.h> |
17 | 18 | ||
18 | MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); | 19 | MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); |
@@ -48,68 +49,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); | |||
48 | #define MT9V011_VERSION 0x8232 | 49 | #define MT9V011_VERSION 0x8232 |
49 | #define MT9V011_REV_B_VERSION 0x8243 | 50 | #define MT9V011_REV_B_VERSION 0x8243 |
50 | 51 | ||
51 | /* supported controls */ | ||
52 | static struct v4l2_queryctrl mt9v011_qctrl[] = { | ||
53 | { | ||
54 | .id = V4L2_CID_GAIN, | ||
55 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
56 | .name = "Gain", | ||
57 | .minimum = 0, | ||
58 | .maximum = (1 << 12) - 1 - 0x0020, | ||
59 | .step = 1, | ||
60 | .default_value = 0x0020, | ||
61 | .flags = 0, | ||
62 | }, { | ||
63 | .id = V4L2_CID_EXPOSURE, | ||
64 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
65 | .name = "Exposure", | ||
66 | .minimum = 0, | ||
67 | .maximum = 2047, | ||
68 | .step = 1, | ||
69 | .default_value = 0x01fc, | ||
70 | .flags = 0, | ||
71 | }, { | ||
72 | .id = V4L2_CID_RED_BALANCE, | ||
73 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
74 | .name = "Red Balance", | ||
75 | .minimum = -1 << 9, | ||
76 | .maximum = (1 << 9) - 1, | ||
77 | .step = 1, | ||
78 | .default_value = 0, | ||
79 | .flags = 0, | ||
80 | }, { | ||
81 | .id = V4L2_CID_BLUE_BALANCE, | ||
82 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
83 | .name = "Blue Balance", | ||
84 | .minimum = -1 << 9, | ||
85 | .maximum = (1 << 9) - 1, | ||
86 | .step = 1, | ||
87 | .default_value = 0, | ||
88 | .flags = 0, | ||
89 | }, { | ||
90 | .id = V4L2_CID_HFLIP, | ||
91 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
92 | .name = "Mirror", | ||
93 | .minimum = 0, | ||
94 | .maximum = 1, | ||
95 | .step = 1, | ||
96 | .default_value = 0, | ||
97 | .flags = 0, | ||
98 | }, { | ||
99 | .id = V4L2_CID_VFLIP, | ||
100 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
101 | .name = "Vflip", | ||
102 | .minimum = 0, | ||
103 | .maximum = 1, | ||
104 | .step = 1, | ||
105 | .default_value = 0, | ||
106 | .flags = 0, | ||
107 | }, { | ||
108 | } | ||
109 | }; | ||
110 | |||
111 | struct mt9v011 { | 52 | struct mt9v011 { |
112 | struct v4l2_subdev sd; | 53 | struct v4l2_subdev sd; |
54 | struct v4l2_ctrl_handler ctrls; | ||
113 | unsigned width, height; | 55 | unsigned width, height; |
114 | unsigned xtal; | 56 | unsigned xtal; |
115 | unsigned hflip:1; | 57 | unsigned hflip:1; |
@@ -381,99 +323,6 @@ static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) | |||
381 | set_read_mode(sd); | 323 | set_read_mode(sd); |
382 | 324 | ||
383 | return 0; | 325 | return 0; |
384 | }; | ||
385 | |||
386 | static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
387 | { | ||
388 | struct mt9v011 *core = to_mt9v011(sd); | ||
389 | |||
390 | v4l2_dbg(1, debug, sd, "g_ctrl called\n"); | ||
391 | |||
392 | switch (ctrl->id) { | ||
393 | case V4L2_CID_GAIN: | ||
394 | ctrl->value = core->global_gain; | ||
395 | return 0; | ||
396 | case V4L2_CID_EXPOSURE: | ||
397 | ctrl->value = core->exposure; | ||
398 | return 0; | ||
399 | case V4L2_CID_RED_BALANCE: | ||
400 | ctrl->value = core->red_bal; | ||
401 | return 0; | ||
402 | case V4L2_CID_BLUE_BALANCE: | ||
403 | ctrl->value = core->blue_bal; | ||
404 | return 0; | ||
405 | case V4L2_CID_HFLIP: | ||
406 | ctrl->value = core->hflip ? 1 : 0; | ||
407 | return 0; | ||
408 | case V4L2_CID_VFLIP: | ||
409 | ctrl->value = core->vflip ? 1 : 0; | ||
410 | return 0; | ||
411 | } | ||
412 | return -EINVAL; | ||
413 | } | ||
414 | |||
415 | static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | ||
416 | { | ||
417 | int i; | ||
418 | |||
419 | v4l2_dbg(1, debug, sd, "queryctrl called\n"); | ||
420 | |||
421 | for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++) | ||
422 | if (qc->id && qc->id == mt9v011_qctrl[i].id) { | ||
423 | memcpy(qc, &(mt9v011_qctrl[i]), | ||
424 | sizeof(*qc)); | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | return -EINVAL; | ||
429 | } | ||
430 | |||
431 | |||
432 | static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
433 | { | ||
434 | struct mt9v011 *core = to_mt9v011(sd); | ||
435 | u8 i, n; | ||
436 | n = ARRAY_SIZE(mt9v011_qctrl); | ||
437 | |||
438 | for (i = 0; i < n; i++) { | ||
439 | if (ctrl->id != mt9v011_qctrl[i].id) | ||
440 | continue; | ||
441 | if (ctrl->value < mt9v011_qctrl[i].minimum || | ||
442 | ctrl->value > mt9v011_qctrl[i].maximum) | ||
443 | return -ERANGE; | ||
444 | v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", | ||
445 | ctrl->id, ctrl->value); | ||
446 | break; | ||
447 | } | ||
448 | |||
449 | switch (ctrl->id) { | ||
450 | case V4L2_CID_GAIN: | ||
451 | core->global_gain = ctrl->value; | ||
452 | break; | ||
453 | case V4L2_CID_EXPOSURE: | ||
454 | core->exposure = ctrl->value; | ||
455 | break; | ||
456 | case V4L2_CID_RED_BALANCE: | ||
457 | core->red_bal = ctrl->value; | ||
458 | break; | ||
459 | case V4L2_CID_BLUE_BALANCE: | ||
460 | core->blue_bal = ctrl->value; | ||
461 | break; | ||
462 | case V4L2_CID_HFLIP: | ||
463 | core->hflip = ctrl->value; | ||
464 | set_read_mode(sd); | ||
465 | return 0; | ||
466 | case V4L2_CID_VFLIP: | ||
467 | core->vflip = ctrl->value; | ||
468 | set_read_mode(sd); | ||
469 | return 0; | ||
470 | default: | ||
471 | return -EINVAL; | ||
472 | } | ||
473 | |||
474 | set_balance(sd); | ||
475 | |||
476 | return 0; | ||
477 | } | 326 | } |
478 | 327 | ||
479 | static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, | 328 | static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, |
@@ -599,10 +448,46 @@ static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, | |||
599 | version); | 448 | version); |
600 | } | 449 | } |
601 | 450 | ||
602 | static const struct v4l2_subdev_core_ops mt9v011_core_ops = { | 451 | static int mt9v011_s_ctrl(struct v4l2_ctrl *ctrl) |
603 | .queryctrl = mt9v011_queryctrl, | 452 | { |
604 | .g_ctrl = mt9v011_g_ctrl, | 453 | struct mt9v011 *core = |
454 | container_of(ctrl->handler, struct mt9v011, ctrls); | ||
455 | struct v4l2_subdev *sd = &core->sd; | ||
456 | |||
457 | switch (ctrl->id) { | ||
458 | case V4L2_CID_GAIN: | ||
459 | core->global_gain = ctrl->val; | ||
460 | break; | ||
461 | case V4L2_CID_EXPOSURE: | ||
462 | core->exposure = ctrl->val; | ||
463 | break; | ||
464 | case V4L2_CID_RED_BALANCE: | ||
465 | core->red_bal = ctrl->val; | ||
466 | break; | ||
467 | case V4L2_CID_BLUE_BALANCE: | ||
468 | core->blue_bal = ctrl->val; | ||
469 | break; | ||
470 | case V4L2_CID_HFLIP: | ||
471 | core->hflip = ctrl->val; | ||
472 | set_read_mode(sd); | ||
473 | return 0; | ||
474 | case V4L2_CID_VFLIP: | ||
475 | core->vflip = ctrl->val; | ||
476 | set_read_mode(sd); | ||
477 | return 0; | ||
478 | default: | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | |||
482 | set_balance(sd); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static struct v4l2_ctrl_ops mt9v011_ctrl_ops = { | ||
605 | .s_ctrl = mt9v011_s_ctrl, | 487 | .s_ctrl = mt9v011_s_ctrl, |
488 | }; | ||
489 | |||
490 | static const struct v4l2_subdev_core_ops mt9v011_core_ops = { | ||
606 | .reset = mt9v011_reset, | 491 | .reset = mt9v011_reset, |
607 | .g_chip_ident = mt9v011_g_chip_ident, | 492 | .g_chip_ident = mt9v011_g_chip_ident, |
608 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 493 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -658,6 +543,30 @@ static int mt9v011_probe(struct i2c_client *c, | |||
658 | return -EINVAL; | 543 | return -EINVAL; |
659 | } | 544 | } |
660 | 545 | ||
546 | v4l2_ctrl_handler_init(&core->ctrls, 5); | ||
547 | v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, | ||
548 | V4L2_CID_GAIN, 0, (1 << 12) - 1 - 0x20, 1, 0x20); | ||
549 | v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, | ||
550 | V4L2_CID_EXPOSURE, 0, 2047, 1, 0x01fc); | ||
551 | v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, | ||
552 | V4L2_CID_RED_BALANCE, -(1 << 9), (1 << 9) - 1, 1, 0); | ||
553 | v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, | ||
554 | V4L2_CID_BLUE_BALANCE, -(1 << 9), (1 << 9) - 1, 1, 0); | ||
555 | v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, | ||
556 | V4L2_CID_HFLIP, 0, 1, 1, 0); | ||
557 | v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, | ||
558 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
559 | |||
560 | if (core->ctrls.error) { | ||
561 | int ret = core->ctrls.error; | ||
562 | |||
563 | v4l2_err(sd, "control initialization error %d\n", ret); | ||
564 | v4l2_ctrl_handler_free(&core->ctrls); | ||
565 | kfree(core); | ||
566 | return ret; | ||
567 | } | ||
568 | core->sd.ctrl_handler = &core->ctrls; | ||
569 | |||
661 | core->global_gain = 0x0024; | 570 | core->global_gain = 0x0024; |
662 | core->exposure = 0x01fc; | 571 | core->exposure = 0x01fc; |
663 | core->width = 640; | 572 | core->width = 640; |
@@ -681,12 +590,14 @@ static int mt9v011_probe(struct i2c_client *c, | |||
681 | static int mt9v011_remove(struct i2c_client *c) | 590 | static int mt9v011_remove(struct i2c_client *c) |
682 | { | 591 | { |
683 | struct v4l2_subdev *sd = i2c_get_clientdata(c); | 592 | struct v4l2_subdev *sd = i2c_get_clientdata(c); |
593 | struct mt9v011 *core = to_mt9v011(sd); | ||
684 | 594 | ||
685 | v4l2_dbg(1, debug, sd, | 595 | v4l2_dbg(1, debug, sd, |
686 | "mt9v011.c: removing mt9v011 adapter on address 0x%x\n", | 596 | "mt9v011.c: removing mt9v011 adapter on address 0x%x\n", |
687 | c->addr << 1); | 597 | c->addr << 1); |
688 | 598 | ||
689 | v4l2_device_unregister_subdev(sd); | 599 | v4l2_device_unregister_subdev(sd); |
600 | v4l2_ctrl_handler_free(&core->ctrls); | ||
690 | kfree(to_mt9v011(sd)); | 601 | kfree(to_mt9v011(sd)); |
691 | return 0; | 602 | return 0; |
692 | } | 603 | } |