diff options
| author | Bhanu Murthy V <bmurthyv@nvidia.com> | 2018-01-11 21:41:39 -0500 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-01-27 02:46:19 -0500 |
| commit | 033935acd9b1be2f71b2dd980e38d00e13ad29b2 (patch) | |
| tree | 8274520e6c907130b2b78d3cb1c5ea3794e759f6 | |
| parent | 70c30190e53891039793d32a9270bd8c0279a504 (diff) | |
drivers: camera: CPHY calibration support
Add proper phy mode read support from device tree
to distinguish CPHY and DPHY sensor modes.
Fix CPHY calibration flow to write CPHY mode
and complete calibration.
Bug 1946718
Change-Id: I801965207a6777aa71cc5fc24fcb0a7e0c487093
Signed-off-by: Bhanu Murthy V <bmurthyv@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1639635
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
| -rw-r--r-- | drivers/media/platform/tegra/camera/csi/csi.c | 65 | ||||
| -rw-r--r-- | drivers/media/platform/tegra/camera/csi/csi4_fops.c | 53 | ||||
| -rw-r--r-- | drivers/media/platform/tegra/camera/nvcsi/csi5_fops.c | 15 | ||||
| -rw-r--r-- | drivers/media/platform/tegra/camera/sensor_common.c | 17 | ||||
| -rw-r--r-- | drivers/media/platform/tegra/mipical/mipi_cal.c | 18 | ||||
| -rw-r--r-- | include/media/csi.h | 4 | ||||
| -rw-r--r-- | include/media/tegra-v4l2-camera.h | 8 |
7 files changed, 124 insertions, 56 deletions
diff --git a/drivers/media/platform/tegra/camera/csi/csi.c b/drivers/media/platform/tegra/camera/csi/csi.c index bf7bb744f..c140b1b5e 100644 --- a/drivers/media/platform/tegra/camera/csi/csi.c +++ b/drivers/media/platform/tegra/camera/csi/csi.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * NVIDIA Tegra CSI Device | 2 | * NVIDIA Tegra CSI Device |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2015-2018, NVIDIA CORPORATION. All rights reserved. |
| 5 | * | 5 | * |
| 6 | * Author: Bryan Wu <pengw@nvidia.com> | 6 | * Author: Bryan Wu <pengw@nvidia.com> |
| 7 | * | 7 | * |
| @@ -72,6 +72,69 @@ static void update_blank_intervals(struct tegra_csi_channel *chan, | |||
| 72 | port->v_blank = tegra_csi_tpg_frmfmt[fmtindex].v_blank; | 72 | port->v_blank = tegra_csi_tpg_frmfmt[fmtindex].v_blank; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | static struct sensor_mode_properties* | ||
| 76 | read_mode_from_dt(struct camera_common_data *s_data) | ||
| 77 | { | ||
| 78 | struct sensor_mode_properties *mode = NULL; | ||
| 79 | |||
| 80 | if (s_data) { | ||
| 81 | int idx = s_data->mode_prop_idx; | ||
| 82 | |||
| 83 | if (idx < s_data->sensor_props.num_modes) | ||
| 84 | mode = &s_data->sensor_props.sensor_modes[idx]; | ||
| 85 | } | ||
| 86 | |||
| 87 | return mode; | ||
| 88 | } | ||
| 89 | |||
| 90 | u32 read_settle_time_from_dt(struct tegra_csi_channel *chan) | ||
| 91 | { | ||
| 92 | struct camera_common_data *s_data = chan->s_data; | ||
| 93 | struct sensor_mode_properties *mode = read_mode_from_dt(s_data); | ||
| 94 | struct device *dev = chan->csi->dev; | ||
| 95 | unsigned int cil_settletime = 0; | ||
| 96 | |||
| 97 | if (mode) { | ||
| 98 | dev_dbg(dev, "settle time reading from props\n"); | ||
| 99 | cil_settletime = mode->signal_properties.cil_settletime; | ||
| 100 | } else if (chan->of_node) { | ||
| 101 | int err = 0; | ||
| 102 | const char *str; | ||
| 103 | |||
| 104 | dev_dbg(dev, "settle time reading from of_node\n"); | ||
| 105 | err = of_property_read_string(chan->of_node, "cil_settletime", | ||
| 106 | &str); | ||
| 107 | if (!err) { | ||
| 108 | err = kstrtou32(str, 10, &cil_settletime); | ||
| 109 | if (err) { | ||
| 110 | dev_dbg(dev, | ||
| 111 | "no cil_settletime in of_node"); | ||
| 112 | cil_settletime = 0; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | return cil_settletime; | ||
| 118 | } | ||
| 119 | |||
| 120 | u32 read_phy_mode_from_dt(struct tegra_csi_channel *chan) | ||
| 121 | { | ||
| 122 | struct camera_common_data *s_data = chan->s_data; | ||
| 123 | struct sensor_mode_properties *mode = read_mode_from_dt(s_data); | ||
| 124 | struct device *dev = chan->csi->dev; | ||
| 125 | u32 phy_mode = 0; | ||
| 126 | |||
| 127 | if (mode) { | ||
| 128 | dev_dbg(dev, "settle time reading from props\n"); | ||
| 129 | phy_mode = mode->signal_properties.phy_mode; | ||
| 130 | } else { | ||
| 131 | dev_dbg(dev, "phy mode unavailable in props, use default\n"); | ||
| 132 | phy_mode = CSI_PHY_MODE_DPHY; | ||
| 133 | } | ||
| 134 | |||
| 135 | return phy_mode; | ||
| 136 | } | ||
| 137 | |||
| 75 | void set_csi_portinfo(struct tegra_csi_device *csi, | 138 | void set_csi_portinfo(struct tegra_csi_device *csi, |
| 76 | unsigned int port, unsigned int numlanes) | 139 | unsigned int port, unsigned int numlanes) |
| 77 | { | 140 | { |
diff --git a/drivers/media/platform/tegra/camera/csi/csi4_fops.c b/drivers/media/platform/tegra/camera/csi/csi4_fops.c index fee0f47d3..0e264e6fb 100644 --- a/drivers/media/platform/tegra/camera/csi/csi4_fops.c +++ b/drivers/media/platform/tegra/camera/csi/csi4_fops.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Tegra CSI4 device common APIs | 2 | * Tegra CSI4 device common APIs |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. |
| 5 | * | 5 | * |
| 6 | * Author: Frank Chen <frankc@nvidia.com> | 6 | * Author: Frank Chen <frankc@nvidia.com> |
| 7 | * | 7 | * |
| @@ -102,14 +102,11 @@ static void csi4_stream_config(struct tegra_csi_channel *chan, int port_num) | |||
| 102 | __func__, port_num, val); | 102 | __func__, port_num, val); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | |||
| 106 | static void csi4_phy_config( | 105 | static void csi4_phy_config( |
| 107 | struct tegra_csi_channel *chan, int csi_port, | 106 | struct tegra_csi_channel *chan, int csi_port, |
| 108 | int csi_lanes, bool enable) | 107 | int csi_lanes, bool enable) |
| 109 | { | 108 | { |
| 110 | struct tegra_csi_device *csi = chan->csi; | 109 | struct tegra_csi_device *csi = chan->csi; |
| 111 | struct camera_common_data *s_data = chan->s_data; | ||
| 112 | const struct sensor_mode_properties *mode = NULL; | ||
| 113 | int phy_num = (csi_port & 0x6) >> 1; | 110 | int phy_num = (csi_port & 0x6) >> 1; |
| 114 | bool cil_a = (csi_port & 0x1) ? false : true; | 111 | bool cil_a = (csi_port & 0x1) ? false : true; |
| 115 | int cil_config; | 112 | int cil_config; |
| @@ -117,12 +114,14 @@ static void csi4_phy_config( | |||
| 117 | const unsigned int cil_clk_mhz = TEGRA_CSICIL_CLK_MHZ; | 114 | const unsigned int cil_clk_mhz = TEGRA_CSICIL_CLK_MHZ; |
| 118 | const unsigned int csi_clk_mhz = csi->clk_freq / 1000000; | 115 | const unsigned int csi_clk_mhz = csi->clk_freq / 1000000; |
| 119 | /* Calculated clock settling times for cil and csi clocks */ | 116 | /* Calculated clock settling times for cil and csi clocks */ |
| 120 | unsigned int cil_settletime = 0; | 117 | unsigned int cil_settletime = read_settle_time_from_dt(chan); |
| 121 | unsigned int csi_settletime; | 118 | unsigned int csi_settletime; |
| 119 | u32 phy_mode = read_phy_mode_from_dt(chan); | ||
| 122 | 120 | ||
| 123 | dev_dbg(csi->dev, "%s\n", __func__); | 121 | dev_dbg(csi->dev, "%s\n", __func__); |
| 124 | 122 | ||
| 125 | if (csi_lanes == 3) /* set to CPHY */ | 123 | |
| 124 | if (phy_mode == CSI_PHY_MODE_CPHY) /* set to CPHY */ | ||
| 126 | csi4_phy_write(chan, phy_num, NVCSI_CIL_PHY_CTRL, CPHY); | 125 | csi4_phy_write(chan, phy_num, NVCSI_CIL_PHY_CTRL, CPHY); |
| 127 | else /* set to DPHY */ | 126 | else /* set to DPHY */ |
| 128 | csi4_phy_write(chan, phy_num, NVCSI_CIL_PHY_CTRL, DPHY); | 127 | csi4_phy_write(chan, phy_num, NVCSI_CIL_PHY_CTRL, DPHY); |
| @@ -186,36 +185,6 @@ static void csi4_phy_config( | |||
| 186 | /* power on de-serializer */ | 185 | /* power on de-serializer */ |
| 187 | csi4_phy_write(chan, phy_num, NVCSI_CIL_PAD_CONFIG, 0); | 186 | csi4_phy_write(chan, phy_num, NVCSI_CIL_PAD_CONFIG, 0); |
| 188 | 187 | ||
| 189 | /* Attempt to find the cil_settingtime from the device tree */ | ||
| 190 | if (s_data) { | ||
| 191 | int idx = s_data->mode_prop_idx; | ||
| 192 | |||
| 193 | dev_dbg(csi->dev, "cil_settingtime is pulled from device"); | ||
| 194 | if (idx < s_data->sensor_props.num_modes) { | ||
| 195 | mode = &s_data->sensor_props.sensor_modes[idx]; | ||
| 196 | cil_settletime = mode->signal_properties.cil_settletime; | ||
| 197 | } else { | ||
| 198 | dev_dbg(csi->dev, "mode not listed in DT, use default"); | ||
| 199 | cil_settletime = 0; | ||
| 200 | } | ||
| 201 | } else if (chan->of_node) { | ||
| 202 | int err = 0; | ||
| 203 | const char *str; | ||
| 204 | |||
| 205 | dev_dbg(csi->dev, | ||
| 206 | "cil_settletime is pulled from device of_node"); | ||
| 207 | err = of_property_read_string(chan->of_node, "cil_settletime", | ||
| 208 | &str); | ||
| 209 | if (!err) { | ||
| 210 | err = kstrtou32(str, 10, &cil_settletime); | ||
| 211 | if (err) { | ||
| 212 | dev_dbg(csi->dev, | ||
| 213 | "no cil_settletime in of_node"); | ||
| 214 | cil_settletime = 0; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | /* calculate MIPI settling times */ | 188 | /* calculate MIPI settling times */ |
| 220 | dev_dbg(csi->dev, "cil core clock: %u, csi clock: %u", cil_clk_mhz, | 189 | dev_dbg(csi->dev, "cil core clock: %u, csi clock: %u", cil_clk_mhz, |
