diff options
| author | Bhanu Murthy V <bmurthyv@nvidia.com> | 2018-08-29 18:21:55 -0400 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2019-01-09 03:17:04 -0500 |
| commit | 0e15664e4eda6e09c799d1d0fb7c791fb59b257c (patch) | |
| tree | e337d7ecc5882975b101fe95f296749cc9a79143 | |
| parent | 647118deb4c0682d1205e4707c4bc6759e05c2ff (diff) | |
drivers: camera: Move v4l2 subdev ops to tegracam
Move all v4l2 initialization to common framework, ensures
most of the duplicated code in sensor drivers reduced.
Now sensor drivers will have control and core ops for
all operations.
New ops - set_mode, start_streaming and stop_streaming
are added to modularize sensor drivers.
Update current sensor drivers with the new modifications.
Bug 2101376
Change-Id: Ic4070bde28f3dce61430af9ecded0541cda2f6fe
Signed-off-by: Bhanu Murthy V <bmurthyv@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1810324
(cherry picked from commit e5801b45ee0ca88a4d3ea6e98ac24800f1971806)
Reviewed-on: https://git-master.nvidia.com/r/1961293
Tested-by: Vincent Chung <vincentc@nvidia.com>
GVS: Gerrit_Virtual_Submit
Tested-by: Frank Chen <frankc@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
Reviewed-by: David Bang <dbang@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
| -rw-r--r-- | drivers/media/i2c/imx185.c | 186 | ||||
| -rw-r--r-- | drivers/media/i2c/imx268.c | 179 | ||||
| -rw-r--r-- | drivers/media/i2c/imx318.c | 181 | ||||
| -rw-r--r-- | drivers/media/platform/tegra/camera/Makefile | 2 | ||||
| -rw-r--r-- | drivers/media/platform/tegra/camera/tegracam_core.c | 88 | ||||
| -rw-r--r-- | drivers/media/platform/tegra/camera/tegracam_ctrls.c | 69 | ||||
| -rw-r--r-- | drivers/media/platform/tegra/camera/tegracam_v4l2.c | 189 | ||||
| -rw-r--r-- | include/media/camera_common.h | 4 | ||||
| -rw-r--r-- | include/media/tegracam_core.h | 4 |
9 files changed, 398 insertions, 504 deletions
diff --git a/drivers/media/i2c/imx185.c b/drivers/media/i2c/imx185.c index 5c9536cd7..9fef03a53 100644 --- a/drivers/media/i2c/imx185.c +++ b/drivers/media/i2c/imx185.c | |||
| @@ -591,165 +591,77 @@ error: | |||
| 591 | return ret; | 591 | return ret; |
| 592 | } | 592 | } |
| 593 | 593 | ||
| 594 | static struct camera_common_sensor_ops imx185_common_ops = { | 594 | static int imx185_set_mode(struct tegracam_device *tc_dev) |
| 595 | .numfrmfmts = ARRAY_SIZE(imx185_frmfmt), | ||
| 596 | .frmfmt_table = imx185_frmfmt, | ||
| 597 | .power_on = imx185_power_on, | ||
| 598 | .power_off = imx185_power_off, | ||
| 599 | .write_reg = imx185_write_reg, | ||
| 600 | .read_reg = imx185_read_reg, | ||
| 601 | .parse_dt = imx185_parse_dt, | ||
| 602 | .power_get = imx185_power_get, | ||
| 603 | .power_put = imx185_power_put, | ||
| 604 | }; | ||
| 605 | |||
| 606 | static int imx185_s_stream(struct v4l2_subdev *sd, int enable) | ||
| 607 | { | 595 | { |
| 608 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 596 | struct imx185 *priv = (struct imx185 *)tegracam_get_privdata(tc_dev); |
| 609 | struct device *dev = &client->dev; | 597 | struct camera_common_data *s_data = tc_dev->s_data; |
| 610 | struct camera_common_data *s_data = to_camera_common_data(dev); | ||
| 611 | struct imx185 *priv = (struct imx185 *)s_data->priv; | ||
| 612 | struct v4l2_ext_controls ctrls; | ||
| 613 | struct v4l2_ext_control control[3]; | ||
| 614 | int err; | 598 | int err; |
| 615 | 599 | ||
| 616 | dev_dbg(dev, "%s++ enable %d\n", __func__, enable); | ||
| 617 | |||
| 618 | trace_imx185_s_stream(sd->name, enable, s_data->mode); | ||
| 619 | if (!enable) { | ||
| 620 | err = imx185_write_table(priv, | ||
| 621 | mode_table[IMX185_MODE_STOP_STREAM]); | ||
| 622 | |||
| 623 | if (err) | ||
| 624 | return err; | ||
| 625 | |||
| 626 | /* SW_RESET will have no ACK */ | ||
| 627 | regmap_write(s_data->regmap, IMX185_SW_RESET_ADDR, 0x01); | ||
| 628 | |||
| 629 | /* Wait for one frame to make sure sensor is set to | ||
| 630 | * software standby in V-blank | ||
| 631 | * | ||
| 632 | * delay = frame length rows * Tline (10 us) | ||
| 633 | */ | ||
| 634 | usleep_range(priv->frame_length * 10, | ||
| 635 | priv->frame_length * 10 + 1000); | ||
| 636 | return 0; | ||
| 637 | } | ||
| 638 | err = imx185_write_table(priv, mode_table[s_data->mode_prop_idx]); | 600 | err = imx185_write_table(priv, mode_table[s_data->mode_prop_idx]); |
| 639 | if (err) | 601 | if (err) |
| 640 | goto exit; | 602 | return err; |
| 641 | 603 | ||
| 642 | if (s_data->override_enable) { | 604 | return 0; |
| 643 | /* write list of override regs for the asking gain, */ | 605 | } |
| 644 | /* frame rate and exposure time */ | 606 | |
| 645 | memset(&ctrls, 0, sizeof(ctrls)); | 607 | static int imx185_start_streaming(struct tegracam_device *tc_dev) |
| 646 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 9, 0) | 608 | { |
| 647 | ctrls.which = V4L2_CTRL_ID2WHICH(TEGRA_CAMERA_CID_GAIN); | 609 | struct imx185 *priv = (struct imx185 *)tegracam_get_privdata(tc_dev); |
| 648 | #else | 610 | int err; |
| 649 | ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(TEGRA_CAMERA_CID_GAIN); | ||
| 650 | #endif | ||
| 651 | ctrls.count = 3; | ||
| 652 | ctrls.controls = control; | ||
| 653 | |||
| 654 | control[0].id = TEGRA_CAMERA_CID_GAIN; | ||
| 655 | control[1].id = TEGRA_CAMERA_CID_FRAME_RATE; | ||
| 656 | control[2].id = TEGRA_CAMERA_CID_EXPOSURE; | ||
| 657 | |||
| 658 | err = v4l2_g_ext_ctrls(s_data->ctrl_handler, &ctrls); | ||
| 659 | if (err == 0) { | ||
| 660 | err |= imx185_set_gain(priv->tc_dev, control[0].value64); | ||
| 661 | if (err) | ||
| 662 | dev_err(dev, "%s: error gain override\n", | ||
| 663 | __func__); | ||
| 664 | |||
| 665 | err |= imx185_set_frame_rate(priv->tc_dev, | ||
| 666 | control[1].value64); | ||
| 667 | if (err) | ||
| 668 | dev_err(dev, | ||
| 669 | "%s: error frame length override\n", | ||
| 670 | __func__); | ||
| 671 | |||
| 672 | err |= imx185_set_exposure(priv->tc_dev, control[2].value64); | ||
| 673 | if (err) | ||
| 674 | dev_err(dev, "%s: error exposure override\n", | ||
| 675 | __func__); | ||
| 676 | |||
| 677 | } else { | ||
| 678 | dev_err(dev, "%s: faile to get overrides\n", __func__); | ||
| 679 | } | ||
| 680 | } | ||
| 681 | 611 | ||
| 682 | if (test_mode) { | 612 | if (test_mode) { |
| 683 | err = imx185_write_table(priv, | 613 | err = imx185_write_table(priv, |
| 684 | mode_table[IMX185_MODE_TEST_PATTERN]); | 614 | mode_table[IMX185_MODE_TEST_PATTERN]); |
| 685 | if (err) | 615 | if (err) |
| 686 | goto exit; | 616 | return err; |
| 687 | } | 617 | } |
| 688 | 618 | ||
| 689 | err = imx185_write_table(priv, mode_table[IMX185_MODE_START_STREAM]); | 619 | err = imx185_write_table(priv, |
| 620 | mode_table[IMX185_MODE_START_STREAM]); | ||
| 690 | if (err) | 621 | if (err) |
| 691 | goto exit; | 622 | return err; |
| 692 | 623 | ||
| 693 | return 0; | 624 | return 0; |
| 694 | exit: | ||
| 695 | dev_err(dev, "%s: error setting stream\n", __func__); | ||
| 696 | return err; | ||
| 697 | } | 625 | } |
| 698 | 626 | ||
| 699 | static int imx185_g_input_status(struct v4l2_subdev *sd, u32 *status) | 627 | static int imx185_stop_streaming(struct tegracam_device *tc_dev) |
| 700 | { | 628 | { |
| 701 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 629 | struct camera_common_data *s_data = tc_dev->s_data; |
| 702 | struct camera_common_data *s_data = to_camera_common_data(&client->dev); | 630 | struct imx185 *priv = (struct imx185 *)tegracam_get_privdata(tc_dev); |
| 703 | struct camera_common_power_rail *pw = s_data->power; | 631 | int err; |
| 704 | |||
| 705 | *status = pw->state == SWITCH_ON; | ||
| 706 | return 0; | ||
| 707 | } | ||
| 708 | |||
| 709 | static struct v4l2_subdev_video_ops imx185_subdev_video_ops = { | ||
| 710 | .s_stream = imx185_s_stream, | ||
| 711 | .g_mbus_config = camera_common_g_mbus_config, | ||
| 712 | .g_input_status = imx185_g_input_status, | ||
| 713 | }; | ||
| 714 | |||
| 715 | static struct v4l2_subdev_core_ops imx185_subdev_core_ops = { | ||
| 716 | .s_power = camera_common_s_power, | ||
| 717 | }; | ||
| 718 | 632 | ||
| 719 | static int imx185_get_fmt(struct v4l2_subdev *sd, | 633 | err = imx185_write_table(priv, mode_table[IMX185_MODE_STOP_STREAM]); |
| 720 | struct v4l2_subdev_pad_config *cfg, | 634 | if (err) |
| 721 | struct v4l2_subdev_format *format) | 635 | return err; |
| 722 | { | ||
| 723 | return camera_common_g_fmt(sd, &format->format); | ||
| 724 | } | ||
| 725 | 636 | ||
| 726 | static int imx185_set_fmt(struct v4l2_subdev *sd, | 637 | /* SW_RESET will have no ACK */ |
| 727 | struct v4l2_subdev_pad_config *cfg, | 638 | imx185_write_reg(s_data, IMX185_SW_RESET_ADDR, 0x01); |
| 728 | struct v4l2_subdev_format *format) | ||
| 729 | { | ||
| 730 | int ret; | ||
| 731 | 639 | ||
| 732 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) | 640 | /* |
| 733 | ret = camera_common_try_fmt(sd, &format->format); | 641 | * Wait for one frame to make sure sensor is set to |
| 734 | else | 642 | * software standby in V-blank |
| 735 | ret = camera_common_s_fmt(sd, &format->format); | 643 | * |
| 644 | * delay = frame length rows * Tline (10 us) | ||
| 645 | */ | ||
| 646 | usleep_range(priv->frame_length * 10, priv->frame_length * 10 + 1000); | ||
| 736 | 647 | ||
| 737 | return ret; | 648 | return 0; |
| 738 | } | 649 | } |
| 739 | 650 | ||
