diff options
Diffstat (limited to 'drivers/media/video/ov772x.c')
| -rw-r--r-- | drivers/media/video/ov772x.c | 114 |
1 files changed, 36 insertions, 78 deletions
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index f77e8995fe40..9b540421e2cb 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <media/ov772x.h> | 25 | #include <media/ov772x.h> |
| 26 | #include <media/soc_camera.h> | 26 | #include <media/soc_camera.h> |
| 27 | #include <media/soc_mediabus.h> | 27 | #include <media/soc_mediabus.h> |
| 28 | #include <media/v4l2-ctrls.h> | ||
| 28 | #include <media/v4l2-chip-ident.h> | 29 | #include <media/v4l2-chip-ident.h> |
| 29 | #include <media/v4l2-subdev.h> | 30 | #include <media/v4l2-subdev.h> |
| 30 | 31 | ||
| @@ -401,6 +402,7 @@ struct ov772x_win_size { | |||
| 401 | 402 | ||
| 402 | struct ov772x_priv { | 403 | struct ov772x_priv { |
| 403 | struct v4l2_subdev subdev; | 404 | struct v4l2_subdev subdev; |
| 405 | struct v4l2_ctrl_handler hdl; | ||
| 404 | struct ov772x_camera_info *info; | 406 | struct ov772x_camera_info *info; |
| 405 | const struct ov772x_color_format *cfmt; | 407 | const struct ov772x_color_format *cfmt; |
| 406 | const struct ov772x_win_size *win; | 408 | const struct ov772x_win_size *win; |
| @@ -518,36 +520,6 @@ static const struct ov772x_win_size ov772x_win_qvga = { | |||
| 518 | .regs = ov772x_qvga_regs, | 520 | .regs = ov772x_qvga_regs, |
| 519 | }; | 521 | }; |
| 520 | 522 | ||
| 521 | static const struct v4l2_queryctrl ov772x_controls[] = { | ||
| 522 | { | ||
| 523 | .id = V4L2_CID_VFLIP, | ||
| 524 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 525 | .name = "Flip Vertically", | ||
| 526 | .minimum = 0, | ||
| 527 | .maximum = 1, | ||
| 528 | .step = 1, | ||
| 529 | .default_value = 0, | ||
| 530 | }, | ||
| 531 | { | ||
| 532 | .id = V4L2_CID_HFLIP, | ||
| 533 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 534 | .name = "Flip Horizontally", | ||
| 535 | .minimum = 0, | ||
| 536 | .maximum = 1, | ||
| 537 | .step = 1, | ||
| 538 | .default_value = 0, | ||
| 539 | }, | ||
| 540 | { | ||
| 541 | .id = V4L2_CID_BAND_STOP_FILTER, | ||
| 542 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 543 | .name = "Band-stop filter", | ||
| 544 | .minimum = 0, | ||
| 545 | .maximum = 256, | ||
| 546 | .step = 1, | ||
| 547 | .default_value = 0, | ||
| 548 | }, | ||
| 549 | }; | ||
| 550 | |||
| 551 | /* | 523 | /* |
| 552 | * general function | 524 | * general function |
| 553 | */ | 525 | */ |
| @@ -621,52 +593,30 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) | |||
| 621 | return 0; | 593 | return 0; |
| 622 | } | 594 | } |
| 623 | 595 | ||
| 624 | static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 596 | static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) |
| 625 | { | ||
| 626 | struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); | ||
| 627 | |||
| 628 | switch (ctrl->id) { | ||
| 629 | case V4L2_CID_VFLIP: | ||
| 630 | ctrl->value = priv->flag_vflip; | ||
| 631 | break; | ||
| 632 | case V4L2_CID_HFLIP: | ||
| 633 | ctrl->value = priv->flag_hflip; | ||
| 634 | break; | ||
| 635 | case V4L2_CID_BAND_STOP_FILTER: | ||
| 636 | ctrl->value = priv->band_filter; | ||
| 637 | break; | ||
| 638 | } | ||
| 639 | return 0; | ||
| 640 | } | ||
| 641 | |||
| 642 | static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
| 643 | { | 597 | { |
| 598 | struct ov772x_priv *priv = container_of(ctrl->handler, | ||
| 599 | struct ov772x_priv, hdl); | ||
| 600 | struct v4l2_subdev *sd = &priv->subdev; | ||
| 644 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 601 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 645 | struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); | ||
| 646 | int ret = 0; | 602 | int ret = 0; |
| 647 | u8 val; | 603 | u8 val; |
| 648 | 604 | ||
| 649 | switch (ctrl->id) { | 605 | switch (ctrl->id) { |
| 650 | case V4L2_CID_VFLIP: | 606 | case V4L2_CID_VFLIP: |
| 651 | val = ctrl->value ? VFLIP_IMG : 0x00; | 607 | val = ctrl->val ? VFLIP_IMG : 0x00; |
| 652 | priv->flag_vflip = ctrl->value; | 608 | priv->flag_vflip = ctrl->val; |
| 653 | if (priv->info->flags & OV772X_FLAG_VFLIP) | 609 | if (priv->info->flags & OV772X_FLAG_VFLIP) |
| 654 | val ^= VFLIP_IMG; | 610 | val ^= VFLIP_IMG; |
| 655 | ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val); | 611 | return ov772x_mask_set(client, COM3, VFLIP_IMG, val); |
| 656 | break; | ||
| 657 | case V4L2_CID_HFLIP: | 612 | case V4L2_CID_HFLIP: |
| 658 | val = ctrl->value ? HFLIP_IMG : 0x00; | 613 | val = ctrl->val ? HFLIP_IMG : 0x00; |
| 659 | priv->flag_hflip = ctrl->value; | 614 | priv->flag_hflip = ctrl->val; |
| 660 | if (priv->info->flags & OV772X_FLAG_HFLIP) | 615 | if (priv->info->flags & OV772X_FLAG_HFLIP) |
| 661 | val ^= HFLIP_IMG; | 616 | val ^= HFLIP_IMG; |
| 662 | ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val); | 617 | return ov772x_mask_set(client, COM3, HFLIP_IMG, val); |
| 663 | break; | ||
| 664 | case V4L2_CID_BAND_STOP_FILTER: | 618 | case V4L2_CID_BAND_STOP_FILTER: |
| 665 | if ((unsigned)ctrl->value > 256) | 619 | if (!ctrl->val) { |
| 666 | ctrl->value = 256; | ||
| 667 | if (ctrl->value == priv->band_filter) | ||
| 668 | break; | ||
| 669 | if (!ctrl->value) { | ||
| 670 | /* Switch the filter off, it is on now */ | 620 | /* Switch the filter off, it is on now */ |
| 671 | ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff); | 621 | ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff); |
| 672 | if (!ret) | 622 | if (!ret) |
| @@ -674,7 +624,7 @@ static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
| 674 | BNDF_ON_OFF, 0); | 624 | BNDF_ON_OFF, 0); |
| 675 | } else { | 625 | } else { |
| 676 | /* Switch the filter on, set AEC low limit */ | 626 | /* Switch the filter on, set AEC low limit */ |
| 677 | val = 256 - ctrl->value; | 627 | val = 256 - ctrl->val; |
| 678 | ret = ov772x_mask_set(client, COM8, | 628 | ret = ov772x_mask_set(client, COM8, |
| 679 | BNDF_ON_OFF, BNDF_ON_OFF); | 629 | BNDF_ON_OFF, BNDF_ON_OFF); |
| 680 | if (!ret) | 630 | if (!ret) |
| @@ -682,11 +632,11 @@ static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
| 682 | 0xff, val); | 632 | 0xff, val); |
| 683 | } | 633 | } |
| 684 | if (!ret) | 634 | if (!ret) |
| 685 | priv->band_filter = ctrl->value; | 635 | priv->band_filter = ctrl->val; |
| 686 | break; | 636 | return ret; |
| 687 | } | 637 | } |
| 688 | 638 | ||
| 689 | return ret; | 639 | return -EINVAL; |
| 690 | } | 640 | } |
| 691 | 641 | ||
| 692 | static int ov772x_g_chip_ident(struct v4l2_subdev *sd, | 642 | static int ov772x_g_chip_ident(struct v4l2_subdev *sd, |
| @@ -1042,18 +992,14 @@ static int ov772x_video_probe(struct soc_camera_device *icd, | |||
| 1042 | ver, | 992 | ver, |
| 1043 | i2c_smbus_read_byte_data(client, MIDH), | 993 | i2c_smbus_read_byte_data(client, MIDH), |
| 1044 | i2c_smbus_read_byte_data(client, MIDL)); | 994 | i2c_smbus_read_byte_data(client, MIDL)); |
| 1045 | 995 | return v4l2_ctrl_handler_setup(&priv->hdl); | |
| 1046 | return 0; | ||
| 1047 | } | 996 | } |
| 1048 | 997 | ||
| 1049 | static struct soc_camera_ops ov772x_ops = { | 998 | static const struct v4l2_ctrl_ops ov772x_ctrl_ops = { |
| 1050 | .controls = ov772x_controls, | 999 | .s_ctrl = ov772x_s_ctrl, |
| 1051 | .num_controls = ARRAY_SIZE(ov772x_controls), | ||
| 1052 | }; | 1000 | }; |
| 1053 | 1001 | ||
| 1054 | static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { | 1002 | static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { |
| 1055 | .g_ctrl = ov772x_g_ctrl, | ||
| 1056 | .s_ctrl = ov772x_s_ctrl, | ||
| 1057 | .g_chip_ident = ov772x_g_chip_ident, | 1003 | .g_chip_ident = ov772x_g_chip_ident, |
| 1058 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1004 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| 1059 | .g_register = ov772x_g_register, | 1005 | .g_register = ov772x_g_register, |
| @@ -1139,12 +1085,24 @@ static int ov772x_probe(struct i2c_client *client, | |||
| 1139 | priv->info = icl->priv; | 1085 | priv->info = icl->priv; |
| 1140 | 1086 | ||
| 1141 | v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); | 1087 | v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); |
| 1088 | v4l2_ctrl_handler_init(&priv->hdl, 3); | ||
| 1089 | v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, | ||
| 1090 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
| 1091 | v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, | ||
| 1092 | V4L2_CID_HFLIP, 0, 1, 1, 0); | ||
| 1093 | v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, | ||
| 1094 | V4L2_CID_BAND_STOP_FILTER, 0, 256, 1, 0); | ||
| 1095 | priv->subdev.ctrl_handler = &priv->hdl; | ||
| 1096 | if (priv->hdl.error) { | ||
| 1097 | int err = priv->hdl.error; | ||
| 1142 | 1098 | ||
| 1143 | icd->ops = &ov772x_ops; | 1099 | kfree(priv); |
| 1100 | return err; | ||
| 1101 | } | ||
| 1144 | 1102 | ||
| 1145 | ret = ov772x_video_probe(icd, client); | 1103 | ret = ov772x_video_probe(icd, client); |
| 1146 | if (ret) { | 1104 | if (ret) { |
| 1147 | icd->ops = NULL; | 1105 | v4l2_ctrl_handler_free(&priv->hdl); |
| 1148 | kfree(priv); | 1106 | kfree(priv); |
| 1149 | } | 1107 | } |
| 1150 | 1108 | ||
| @@ -1154,9 +1112,9 @@ static int ov772x_probe(struct i2c_client *client, | |||
| 1154 | static int ov772x_remove(struct i2c_client *client) | 1112 | static int ov772x_remove(struct i2c_client *client) |
| 1155 | { | 1113 | { |
| 1156 | struct ov772x_priv *priv = to_ov772x(client); | 1114 | struct ov772x_priv *priv = to_ov772x(client); |
| 1157 | struct soc_camera_device *icd = client->dev.platform_data; | ||
| 1158 | 1115 | ||
| 1159 | icd->ops = NULL; | 1116 | v4l2_device_unregister_subdev(&priv->subdev); |
| 1117 | v4l2_ctrl_handler_free(&priv->hdl); | ||
| 1160 | kfree(priv); | 1118 | kfree(priv); |
| 1161 | return 0; | 1119 | return 0; |
| 1162 | } | 1120 | } |
