Hi nvidia developvers
I use csi without i2c to get the streaming from FPGA.
The format is 1920*1080 30fps, RGB888, 4lanes
I change the driver - imx185.c to adapt.
Now ,i can get the capture from fpga, but the program working few seconds then report error about vi.
I remove the code all about the i2c in imx185.c
Below i will show all my dts and demsg
my verision is
root@dev-desktop:~/lab# cat /etc/nv_tegra_release
# R32 (release), REVISION: 5.1, GCID: 26202423, BOARD: t186ref, EABI: aarch64, DATE: Fri Feb 19 16:50:29 UTC 2021
1 - tegra194-camera-imx185-a00.dtsi
/ {
host1x {
vi@15c10000 {
num-channels = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
liimx185_vi_in0: endpoint {
port-index = <0>;
bus-width = <4>;
remote-endpoint = <&liimx185_csi_out0>;
};
};
};
};
nvcsi@15a00000 {
num-channels = <1>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
liimx185_csi_in0: endpoint@0 {
port-index = <0>;
bus-width = <4>;
remote-endpoint = <&liimx185_imx185_out0>;
};
};
port@1 {
reg = <1>;
liimx185_csi_out0: endpoint@1 {
remote-endpoint = <&liimx185_vi_in0>;
};
};
};
};
};
};
i2c@3180000 {
tca9546@70 {
i2c@0 {
imx185_a@1a {
compatible = "nvidia,imx185";
reg = <0x1a>;
devnode = "video0";
/* Physical dimensions of sensor */
physical_w = "15.0";
physical_h = "12.5";
sensor_model ="imx185";
/* Define any required hw resources needed by driver */
/* ie. clocks, io pins, power sources */
/* Defines number of frames to be dropped by driver internally after applying */
/* sensor crop settings. Some sensors send corrupt frames after applying */
/* crop co-ordinates */
post_crop_frame_drop = "0";
/* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
use_decibel_gain = "true";
/* if true, delay gain setting by one frame to be in sync with exposure */
delayed_gain = "true";
/* enable CID_SENSOR_MODE_ID for sensor modes selection */
use_sensor_mode_id = "true";
/* WAR to prevent banding by reducing analog gain. Bug 2229902 */
limit_analog_gain = "true";
mode0 {/*mode IMX185_MODE_1920X1080_CROP_30FPS*/
mclk_khz = "37125";
num_lanes = "4";
tegra_sinterface = "serial_a";
phy_mode = "DPHY";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
//dynamic_pixel_bit_depth = "12";
//csi_pixel_bit_depth = "12";
//mode_type = "bayer";
//pixel_phase = "rggb";
pixel_t = "rgb_rgb88824";
active_w = "1920";
active_h = "1080";
readout_orientation = "0";
line_length = "2200";
inherent_gain = "1";
mclk_multiplier = "2";
pix_clk_hz = "74250000";
gain_factor = "10";
min_gain_val = "0"; /* 0dB */
max_gain_val = "480"; /* 48dB */
step_gain_val = "3"; /* 0.3 */
default_gain = "0";
min_hdr_ratio = "1";
max_hdr_ratio = "1";
framerate_factor = "1000000";
min_framerate = "1500000"; /* 1.5 */
max_framerate = "30000000"; /* 30 */
step_framerate = "1";
default_framerate= "30000000";
exposure_factor = "1000000";
min_exp_time = "30"; /* us */
max_exp_time = "660000"; /* us */
step_exp_time = "1";
default_exp_time = "33334";/* us */
embedded_metadata_height = "1";
};
mode1 {/*mode IMX185_MODE_1920X1080_CROP_10BIT_30FPS*/
mclk_khz = "37125";
num_lanes = "4";
tegra_sinterface = "serial_a";
phy_mode = "DPHY";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
dynamic_pixel_bit_depth = "10";
csi_pixel_bit_depth = "10";
mode_type = "bayer";
pixel_phase = "rggb";
active_w = "1920";
active_h = "1080";
readout_orientation = "0";
line_length = "2640";
inherent_gain = "1";
mclk_multiplier = "2.4";
pix_clk_hz = "89100000";
gain_factor = "10";
min_gain_val = "0"; /* 0dB */
max_gain_val = "480"; /* 48dB */
step_gain_val = "3"; /* 0.3 */
default_gain = "0";
min_hdr_ratio = "1";
max_hdr_ratio = "1";
framerate_factor = "1000000";
min_framerate = "1500000"; /* 1.5 */
max_framerate = "30000000"; /* 30 */
step_framerate = "1";
default_framerate= "30000000";
exposure_factor = "1000000";
min_exp_time = "30"; /* us */
max_exp_time = "660000"; /* us */
step_exp_time = "1";
default_exp_time = "33334";/* us */
embedded_metadata_height = "1";
};
mode2 {/*mode IMX185_MODE_1920X1080_CROP_60FPS*/
mclk_khz = "37125";
num_lanes = "4";
tegra_sinterface = "serial_a";
phy_mode = "DPHY";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
dynamic_pixel_bit_depth = "12";
csi_pixel_bit_depth = "12";
mode_type = "bayer";
pixel_phase = "rggb";
active_w = "1920";
active_h = "1080";
readout_orientation = "0";
line_length = "2200";
inherent_gain = "1";
mclk_multiplier = "4";
pix_clk_hz = "148500000";
gain_factor = "10";
min_gain_val = "0"; /* 0dB */
max_gain_val = "480"; /* 48dB */
step_gain_val = "3"; /* 0.3 */
default_gain = "0";
min_hdr_ratio = "1";
max_hdr_ratio = "1";
framerate_factor = "1000000";
min_framerate = "1500000"; /* 1.5 */
max_framerate = "60000000"; /* 60 */
step_framerate = "1";
default_framerate= "60000000";
exposure_factor = "1000000";
min_exp_time = "30"; /* us */
max_exp_time = "660000"; /* us */
step_exp_time = "1";
default_exp_time = "16667";/* us */
embedded_metadata_height = "1";
};
mode3 {/*mode IMX185_MODE_1920X1080_CROP_10BIT_60FPS*/
mclk_khz = "37125";
num_lanes = "4";
tegra_sinterface = "serial_a";
phy_mode = "DPHY";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
dynamic_pixel_bit_depth = "10";
csi_pixel_bit_depth = "10";
mode_type = "bayer";
pixel_phase = "rggb";
active_w = "1920";
active_h = "1080";
readout_orientation = "0";
line_length = "2640";
inherent_gain = "1";
mclk_multiplier = "4.8";
pix_clk_hz = "178200000";
gain_factor = "10";
min_gain_val = "0"; /* 0dB */
max_gain_val = "480"; /* 48dB */
step_gain_val = "3"; /* 0.3 */
default_gain = "0";
min_hdr_ratio = "1";
max_hdr_ratio = "1";
framerate_factor = "1000000";
min_framerate = "1500000"; /* 1.5 */
max_framerate = "60000000"; /* 60 */
step_framerate = "1";
default_framerate= "60000000";
exposure_factor = "1000000";
min_exp_time = "30"; /* us */
max_exp_time = "660000"; /* us */
step_exp_time = "1";
default_exp_time = "16667";/* us */
embedded_metadata_height = "1";
};
mode4 {/*mode IMX185_MODE_1920X1080_CROP_HDR_30FPS*/
mclk_khz = "37125";
num_lanes = "4";
tegra_sinterface = "serial_a";
phy_mode = "DPHY";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
dynamic_pixel_bit_depth = "16";
csi_pixel_bit_depth = "12";
mode_type = "bayer_wdr_pwl";
pixel_phase = "rggb";
active_w = "1920";
active_h = "1080";
readout_orientation = "0";
line_length = "2200";
inherent_gain = "1";
mclk_multiplier = "2";
pix_clk_hz = "74250000";
gain_factor = "10";
min_gain_val = "0"; /* 0dB */
max_gain_val = "120"; /* 12dB */
step_gain_val = "3"; /* 0.3 */
default_gain = "0";
min_hdr_ratio = "16";
max_hdr_ratio = "16";
framerate_factor = "1000000";
min_framerate = "1500000"; /* 1.5 */
max_framerate = "30000000"; /* 30 */
step_framerate = "1";
default_framerate= "30000000";
exposure_factor = "1000000";
min_exp_time = "2433"; /* us */
max_exp_time = "660000"; /* us */
step_exp_time = "1";
default_exp_time = "33334";/* us */
embedded_metadata_height = "1";
/* WDR related settings */
num_control_point = "4";
control_point_x_0 = "0";
control_point_x_1 = "2048";
control_point_x_2 = "16384";
control_point_x_3 = "65536";
control_point_y_0 = "0";
control_point_y_1 = "2048";
control_point_y_2 = "2944";
control_point_y_3 = "3712";
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
liimx185_imx185_out0: endpoint {
port-index = <0>;
bus-width = <4>;
remote-endpoint = <&liimx185_csi_in0>;
};
};
};
};
};
};
};
};
/ {
tegra-camera-platform {
compatible = "nvidia, tegra-camera-platform";
num_csi_lanes = <4>;
max_lane_speed = <1500000>;
min_bits_per_pixel = <10>;
vi_peak_byte_per_pixel = <2>;
vi_bw_margin_pct = <25>;
isp_peak_byte_per_pixel = <5>;
isp_bw_margin_pct = <25>;
modules {
module0 {
badge = "imx185_bottom_liimx185";
position = "bottom";
orientation = "0";
drivernode0 {
/* Declare PCL support driver (classically known as guid) */
pcl_id = "v4l2_sensor";
/* Driver v4l2 device name */
devname = "imx185 30-001a";
/* Declare the device-tree hierarchy to driver instance */
proc-device-tree = "/proc/device-tree/i2c@3180000/tca9546@70/i2c@0/imx185_a@1a";
};
};
};
};
};
2 - tegra194-p2822-0000-camera-imx185-a00.dtsi
#include <t19x-common-modules/tegra194-camera-imx185-a00.dtsi>
#include "dt-bindings/clock/tegra194-clock.h"
#define CAM0_RST_L TEGRA194_MAIN_GPIO(H, 3)
#define CAMERA_I2C_MUX_BUS(x) (0x1E + x)
/* camera control gpio definitions */
/ {
gpio@2200000 {
camera-control-output-low {
gpio-hog;
output-low;
gpios = <CAM0_RST_L 0>;
label = "cam0-rst";
};
};
i2c@3180000 {
tca9546@70 {
compatible = "nxp,pca9546";
reg = <0x70>;
#address-cells = <1>;
#size-cells = <0>;
skip_mux_detect = "yes";
vcc-supply = <&p2822_vdd_1v8_cvb>;
vcc_lp = "vcc";
force_bus_start = <CAMERA_I2C_MUX_BUS(0)>;
i2c@0 {
reg = <0>;
i2c-mux,deselect-on-exit;
#address-cells = <1>;
#size-cells = <0>;
pca9570_a@24 {
compatible = "nvidia,pca9570";
reg = <0x24>;
channel = "a";
drive_ic = "DRV8838";
};
imx185_a@1a {
/* Define any required hw resources needed by driver */
/* ie. clocks, io pins, power sources */
clocks = <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>,
<&bpmp_clks TEGRA194_CLK_EXTPERIPH1>;
clock-names = "extperiph1", "pllp_grtba";
mclk = "extperiph1";
reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_HIGH>;
};
};
};
};
};
3 - use the command
gst-launch-1.0 v4l2src device=/dev/video0 ! 'video/x-raw, width=(int)1920, height=(int)1080, format=(string)BGRA, framerate=(fraction)30/1' ! videoconvert ! ximagesink
4-imx185.c
/*
* imx185.c - imx185 sensor driver
*/
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <media/tegra_v4l2_camera.h>
#include <media/tegracam_core.h>
#include "imx185_mode_tbls.h"
#define CREATE_TRACE_POINTS
#include <trace/events/imx185.h>
#define label "imx185: zp: "
#define pri_fmt(fmt) label fmt
#define pri_line() \
printk(label "func[%s] line[%d]\n", __FUNCTION__, __LINE__)
#define pri_ok(fmt, ...) \
printk(KERN_ERR label "[OK]: " "func[%s] line[%d]->|OK| " fmt,\
__FUNCTION__, __LINE__, ##__VA_ARGS__)
#define pri_err(fmt, ...) \
printk(KERN_ERR label "[ERR]: " "func[%s] line[%d]->|ERR| " fmt,\
__FUNCTION__, __LINE__, ##__VA_ARGS__)
#define pri_all(fmt, ...) \
printk(label " func[%s] line[%d]->|| " fmt ,\
__FUNCTION__, __LINE__, ##__VA_ARGS__)
#define IMX185_MIN_FRAME_LENGTH (1125)
#define IMX185_MAX_FRAME_LENGTH (0x1FFFF)
#define IMX185_MIN_SHS1_1080P_HDR (5)
#define IMX185_MIN_SHS2_1080P_HDR (82)
#define IMX185_MAX_SHS2_1080P_HDR (IMX185_MAX_FRAME_LENGTH - 5)
#define IMX185_MAX_SHS1_1080P_HDR (IMX185_MAX_SHS2_1080P_HDR / 16)
#define IMX185_FRAME_LENGTH_ADDR_MSB 0x301A
#define IMX185_FRAME_LENGTH_ADDR_MID 0x3019
#define IMX185_FRAME_LENGTH_ADDR_LSB 0x3018
#define IMX185_COARSE_TIME_SHS1_ADDR_MSB 0x3022
#define IMX185_COARSE_TIME_SHS1_ADDR_MID 0x3021
#define IMX185_COARSE_TIME_SHS1_ADDR_LSB 0x3020
#define IMX185_COARSE_TIME_SHS2_ADDR_MSB 0x3025
#define IMX185_COARSE_TIME_SHS2_ADDR_MID 0x3024
#define IMX185_COARSE_TIME_SHS2_ADDR_LSB 0x3023
#define IMX185_GAIN_ADDR 0x3014
#define IMX185_GROUP_HOLD_ADDR 0x3001
#define IMX185_SW_RESET_ADDR 0x3003
#define IMX185_ANALOG_GAIN_LIMIT_ADDR 0x3012
#define IMX185_ANALOG_GAIN_LIMIT_VALUE 0x0f
#define IMX185_FUSE_ID_ADDR 0x3382
#define IMX185_FUSE_ID_SIZE 6
#define IMX185_FUSE_ID_STR_SIZE (IMX185_FUSE_ID_SIZE * 2)
static const struct of_device_id imx185_of_match[] = {
{ .compatible = "nvidia,imx185",},
{ },
};
MODULE_DEVICE_TABLE(of, imx185_of_match);
static const u32 ctrl_cid_list[] = {
TEGRA_CAMERA_CID_GAIN,
TEGRA_CAMERA_CID_EXPOSURE,
TEGRA_CAMERA_CID_FRAME_RATE,
TEGRA_CAMERA_CID_FUSE_ID,
TEGRA_CAMERA_CID_HDR_EN,
TEGRA_CAMERA_CID_SENSOR_MODE_ID,
};
struct imx185 {
struct i2c_client *i2c_client;
struct v4l2_subdev *subdev;
u8 fuse_id[IMX185_FUSE_ID_SIZE];
u32 frame_length;
s64 last_wdr_et_val;
struct camera_common_data *s_data;
struct tegracam_device *tc_dev;
};
static const struct regmap_config sensor_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.use_single_rw = true,
};
static inline void imx185_get_frame_length_regs(imx185_reg *regs,
u32 frame_length)
{
regs->addr = IMX185_FRAME_LENGTH_ADDR_MSB;
regs->val = (frame_length >> 16) & 0x01;
(regs + 1)->addr = IMX185_FRAME_LENGTH_ADDR_MID;
(regs + 1)->val = (frame_length >> 8) & 0xff;
(regs + 2)->addr = IMX185_FRAME_LENGTH_ADDR_LSB;
(regs + 2)->val = (frame_length) & 0xff;
}
static inline void imx185_get_coarse_time_regs_shs1(imx185_reg *regs,
u32 coarse_time)
{
regs->addr = IMX185_COARSE_TIME_SHS1_ADDR_MSB;
regs->val = (coarse_time >> 16) & 0x01;
(regs + 1)->addr = IMX185_COARSE_TIME_SHS1_ADDR_MID;
(regs + 1)->val = (coarse_time >> 8) & 0xff;
(regs + 2)->addr = IMX185_COARSE_TIME_SHS1_ADDR_LSB;
(regs + 2)->val = (coarse_time) & 0xff;
}
static inline void imx185_get_coarse_time_regs_shs2(imx185_reg *regs,
u32 coarse_time)
{
regs->addr = IMX185_COARSE_TIME_SHS2_ADDR_MSB;
regs->val = (coarse_time >> 16) & 0x01;
(regs + 1)->addr = IMX185_COARSE_TIME_SHS2_ADDR_MID;
(regs + 1)->val = (coarse_time >> 8) & 0xff;
(regs + 2)->addr = IMX185_COARSE_TIME_SHS2_ADDR_LSB;
(regs + 2)->val = (coarse_time) & 0xff;
}
static inline void imx185_get_gain_reg(imx185_reg *regs,
u8 gain)
{
regs->addr = IMX185_GAIN_ADDR;
regs->val = (gain) & 0xff;
}
static int test_mode;
module_param(test_mode, int, 0644);
static inline int imx185_read_reg(struct camera_common_data *s_data,
u16 addr, u8 *val)
{
return 0;
}
static int imx185_write_reg(struct camera_common_data *s_data,
u16 addr, u8 val)
{
return 0;
}
static int imx185_write_table(struct imx185 *priv,
const imx185_reg table[])
{
#if 0
struct camera_common_data *s_data = priv->s_data;
return regmap_util_write_table_8(s_data->regmap,
table,
NULL, 0,
IMX185_TABLE_WAIT_MS,
IMX185_TABLE_END);
#endif
return 0;
}
static int imx185_set_group_hold(struct tegracam_device *tc_dev, bool val)
{
#if 0
struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev;
int err;
err = imx185_write_reg(s_data,
IMX185_GROUP_HOLD_ADDR, val);
if (err) {
dev_dbg(dev,
"%s: Group hold control error\n", __func__);
return err;
}
#endif
return 0;
}
static int imx185_set_gain(struct tegracam_device *tc_dev, s64 val)
{
return 0;
}
static int imx185_set_coarse_time(struct imx185 *priv, s64 val)
{
return 0;
}
static int imx185_set_coarse_time_hdr(struct imx185 *priv, s64 val)
{
return 0;
}
static int imx185_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct imx185 *priv = (struct imx185 *)tc_dev->priv;
struct device *dev = tc_dev->dev;
imx185_reg reg_list[3];
int err;
u32 frame_length;
const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode_prop_idx];
struct v4l2_control control;
int hdr_en;
int i = 0;
frame_length = mode->signal_properties.pixel_clock.val *
mode->control_properties.framerate_factor /
mode->image_properties.line_length / val;
priv->frame_length = frame_length;
if (priv->frame_length > IMX185_MAX_FRAME_LENGTH)
priv->frame_length = IMX185_MAX_FRAME_LENGTH;
dev_dbg(dev, "%s: val: %lld, , frame_length: %d\n", __func__,
val, priv->frame_length);
imx185_get_frame_length_regs(reg_list, priv->frame_length);
for (i = 0; i < 3; i++) {
err = imx185_write_reg(priv->s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
/* check hdr enable ctrl */
control.id = TEGRA_CAMERA_CID_HDR_EN;
err = camera_common_g_ctrl(s_data, &control);
if (err < 0) {
dev_err(dev, "could not find device ctrl.\n");
pri_err();
return err;
}
hdr_en = switch_ctrl_qmenu[control.value];
if ((hdr_en == SWITCH_ON) && (priv->last_wdr_et_val != 0)) {
err = imx185_set_coarse_time_hdr(priv, priv->last_wdr_et_val);
if (err)
dev_dbg(dev,
"%s: error coarse time SHS1 SHS2 override\n", __func__);
}
return 0;
fail:
dev_dbg(dev, "%s: FRAME_LENGTH control error\n", __func__);
return err;
}
static int imx185_set_exposure(struct tegracam_device *tc_dev, s64 val)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct imx185 *priv = (struct imx185 *)tc_dev->priv;
struct device *dev = tc_dev->dev;
int err;
struct v4l2_control control;
int hdr_en;
dev_dbg(dev, "%s: val: %lld\n", __func__, val);
/* check hdr enable ctrl */
control.id = TEGRA_CAMERA_CID_HDR_EN;
err = camera_common_g_ctrl(s_data, &control);
if (err < 0) {
pri_err();
dev_err(dev, "could not find device ctrl.\n");
return err;
}
hdr_en = switch_ctrl_qmenu[control.value];
if (hdr_en == SWITCH_ON) {
err = imx185_set_coarse_time_hdr(priv, val);
if (err)
dev_dbg(dev,
"%s: error coarse time SHS1 SHS2 override\n", __func__);
} else {
err = imx185_set_coarse_time(priv, val);
if (err)
dev_dbg(dev,
"%s: error coarse time SHS1 override\n", __func__);
}
return err;
}
static int imx185_fill_string_ctrl(struct tegracam_device *tc_dev,
struct v4l2_ctrl *ctrl)
{
return 0;
}
static struct tegracam_ctrl_ops imx185_ctrl_ops = {
.numctrls = ARRAY_SIZE(ctrl_cid_list),
.ctrl_cid_list = ctrl_cid_list,
.string_ctrl_size = {0, IMX185_FUSE_ID_STR_SIZE},
.set_gain = imx185_set_gain,
.set_exposure = imx185_set_exposure,
.set_frame_rate = imx185_set_frame_rate,
.set_group_hold = imx185_set_group_hold,
.fill_string_ctrl = imx185_fill_string_ctrl,
};
static int imx185_power_on(struct camera_common_data *s_data)
{
int err = 0;
struct camera_common_power_rail *pw = s_data->power;
struct camera_common_pdata *pdata = s_data->pdata;
struct device *dev = s_data->dev;
dev_dbg(dev, "%s: power on\n", __func__);
if (pdata && pdata->power_on) {
err = pdata->power_on(pw);
if (err)
dev_err(dev, "%s failed.\n", __func__);
else
pw->state = SWITCH_ON;
return err;
}
/*exit reset mode: XCLR */
if (pw->reset_gpio) {
gpio_set_value(pw->reset_gpio, 0);
usleep_range(30, 50);
gpio_set_value(pw->reset_gpio, 1);
usleep_range(30, 50);
}
pw->state = SWITCH_ON;
pri_ok();
return 0;
}
static int imx185_power_off(struct camera_common_data *s_data)
{
int err = 0;
struct camera_common_power_rail *pw = s_data->power;
struct camera_common_pdata *pdata = s_data->pdata;
struct device *dev = s_data->dev;
dev_dbg(dev, "%s: power off\n", __func__);
if (pdata && pdata->power_off) {
err = pdata->power_off(pw);
if (!err)
goto power_off_done;
else
dev_err(dev, "%s failed.\n", __func__);
return err;
}
/* enter reset mode: XCLR */
usleep_range(1, 2);
if (pw->reset_gpio)
gpio_set_value(pw->reset_gpio, 0);
power_off_done:
pw->state = SWITCH_OFF;
pri_ok();
return 0;
}
static int imx185_power_get(struct tegracam_device *tc_dev)
{
struct device *dev = tc_dev->dev;
struct camera_common_data *s_data = tc_dev->s_data;
struct camera_common_power_rail *pw = s_data->power;
struct camera_common_pdata *pdata = s_data->pdata;
const char *mclk_name;
struct clk *parent;
int err = 0;
mclk_name = pdata->mclk_name ?
pdata->mclk_name : "extperiph1";
pw->mclk = devm_clk_get(dev, mclk_name);
if (IS_ERR(pw->mclk)) {
dev_err(dev, "unable to get clock %s\n", mclk_name);
return PTR_ERR(pw->mclk);
}
parent = devm_clk_get(dev, "pllp_grtba");
if (IS_ERR(parent))
dev_err(dev, "devm_clk_get failed for pllp_grtba");
else
clk_set_parent(pw->mclk, parent);
pw->reset_gpio = pdata->reset_gpio;
pw->state = SWITCH_OFF;
if(err)
pri_err();
else
pri_ok();
return err;
}
static int imx185_power_put(struct tegracam_device *tc_dev)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct camera_common_power_rail *pw = s_data->power;
if (unlikely(!pw))
return -EFAULT;
else
pri_err();
pri_ok();
return 0;
}
static struct camera_common_pdata *imx185_parse_dt(struct tegracam_device *tc_dev)
{
struct device *dev = tc_dev->dev;
struct device_node *np = dev->of_node;
struct camera_common_pdata *board_priv_pdata;
const struct of_device_id *match;
struct camera_common_pdata *ret = NULL;
int err;
int gpio;
if (!np)
return NULL;
match = of_match_device(imx185_of_match, dev);
if (!match) {
dev_err(dev, "Failed to find matching dt id\n");
return NULL;
}
board_priv_pdata = devm_kzalloc(dev,
sizeof(*board_priv_pdata), GFP_KERNEL);
if (!board_priv_pdata)
return NULL;
err = of_property_read_string(np, "mclk",
&board_priv_pdata->mclk_name);
if (err)
dev_err(dev, "mclk not in DT\n");
gpio = of_get_named_gpio(np, "reset-gpios", 0);
if (gpio < 0) {
if (gpio == -EPROBE_DEFER)
ret = ERR_PTR(-EPROBE_DEFER);
dev_err(dev, "reset-gpios not found %d\n", err);
goto error;
}
board_priv_pdata->reset_gpio = (unsigned int)gpio;
return board_priv_pdata;
error:
devm_kfree(dev, board_priv_pdata);
return ret;
}
static int imx185_set_mode(struct tegracam_device *tc_dev)
{
struct imx185 *priv = (struct imx185 *)tegracam_get_privdata(tc_dev);
struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev;
struct device_node *np = dev->of_node;
bool limit_analog_gain = false;
const struct of_device_id *match;
int err;
match = of_match_device(imx185_of_match, dev);
if (!match) {
dev_err(dev, "Failed to find matching dt id\n");
return -EINVAL;
}
limit_analog_gain = of_property_read_bool(np, "limit_analog_gain");
err = imx185_write_table(priv, mode_table[s_data->mode_prop_idx]);
if (err){
pri_err("mode = %d\n", s_data->mode_prop_idx);
return err;
}
else
pri_ok("mode = %d\n", s_data->mode_prop_idx);
if (limit_analog_gain) {
err = imx185_write_reg(priv->s_data,
IMX185_ANALOG_GAIN_LIMIT_ADDR,
IMX185_ANALOG_GAIN_LIMIT_VALUE);
if (err)
return err;
}
pri_ok();
return 0;
}
static int imx185_start_streaming(struct tegracam_device *tc_dev)
{
struct imx185 *priv = (struct imx185 *)tegracam_get_privdata(tc_dev);
int err;
if (test_mode) {
err = imx185_write_table(priv,
mode_table[IMX185_MODE_TEST_PATTERN]);
if (err)
return err;
}
err = imx185_write_table(priv,
mode_table[IMX185_MODE_START_STREAM]);
if (err)
return err;
pri_ok();
return 0;
}
static int imx185_stop_streaming(struct tegracam_device *tc_dev)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct imx185 *priv = (struct imx185 *)tegracam_get_privdata(tc_dev);
int err;
err = imx185_write_table(priv, mode_table[IMX185_MODE_STOP_STREAM]);
if (err)
return err;
/* SW_RESET will have no ACK */
imx185_write_reg(s_data, IMX185_SW_RESET_ADDR, 0x01);
/*
* Wait for one frame to make sure sensor is set to
* software standby in V-blank
*
* delay = frame length rows * Tline (10 us)
*/
usleep_range(priv->frame_length * 10, priv->frame_length * 10 + 1000);
pri_ok();
return 0;
}
static struct camera_common_sensor_ops imx185_common_ops = {
.numfrmfmts = ARRAY_SIZE(imx185_frmfmt),
.frmfmt_table = imx185_frmfmt,
.power_on = imx185_power_on,
.power_off = imx185_power_off,
.write_reg = imx185_write_reg,
.read_reg = imx185_read_reg,
.parse_dt = imx185_parse_dt,
.power_get = imx185_power_get,
.power_put = imx185_power_put,
.set_mode = imx185_set_mode,
.start_streaming = imx185_start_streaming,
.stop_streaming = imx185_stop_streaming,
};
static int imx185_fuse_id_setup(struct imx185 *priv)
{
return 0;
}
static int imx185_board_setup(struct imx185 *priv)
{
struct camera_common_data *s_data = priv->s_data;
struct device *dev = s_data->dev;
int err = 0;
dev_dbg(dev, "%s++\n", __func__);
err = camera_common_mclk_enable(s_data);
if (err) {
dev_err(dev,
"Error %d turning on mclk\n", err);
return err;
}
err = imx185_power_on(s_data);
if (err) {
dev_err(dev,
"Error %d during power on sensor\n", err);
return err;
}
err = imx185_fuse_id_setup(priv);
if (err) {
dev_err(dev,
"Error %d reading fuse id data\n", err);
goto error;
}
error:
imx185_power_off(s_data);
camera_common_mclk_disable(s_data);
return err;
}
static int imx185_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
dev_dbg(&client->dev, "%s:\n", __func__);
return 0;
}
static const struct v4l2_subdev_internal_ops imx185_subdev_internal_ops = {
.open = imx185_open,
};
static int imx185_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct tegracam_device *tc_dev;
struct imx185 *priv;
int err;
dev_info(dev, "probing v4l2 sensor\n");
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
return -EINVAL;
priv = devm_kzalloc(dev,
sizeof(struct imx185), GFP_KERNEL);
if (!priv)
return -ENOMEM;
tc_dev = devm_kzalloc(dev,
sizeof(struct tegracam_device), GFP_KERNEL);
if (!tc_dev)
return -ENOMEM;
priv->i2c_client = tc_dev->client = client;
tc_dev->dev = dev;
strncpy(tc_dev->name, "imx185", sizeof(tc_dev->name));
tc_dev->dev_regmap_config = &sensor_regmap_config;
tc_dev->sensor_ops = &imx185_common_ops;
tc_dev->v4l2sd_internal_ops = &imx185_subdev_internal_ops;
tc_dev->tcctrl_ops = &imx185_ctrl_ops;
err = tegracam_device_register(tc_dev);
if (err) {
dev_err(dev, "tegra camera driver registration failed\n");
return err;
}
priv->tc_dev = tc_dev;
priv->s_data = tc_dev->s_data;
priv->subdev = &tc_dev->s_data->subdev;
tegracam_set_privdata(tc_dev, (void *)priv);
err = imx185_board_setup(priv);
if (err) {
tegracam_device_unregister(tc_dev);
dev_err(dev, "board setup failed\n");
return err;
}
err = tegracam_v4l2subdev_register(tc_dev, true);
if (err) {
dev_err(dev, "tegra camera subdev registration failed\n");
return err;
}
dev_info(dev, "Detected IMX185 sensor\n");
return 0;
}
static int imx185_remove(struct i2c_client *client)
{
struct camera_common_data *s_data = to_camera_common_data(&client->dev);
struct imx185 *priv = (struct imx185 *)s_data->priv;
tegracam_v4l2subdev_unregister(priv->tc_dev);
tegracam_device_unregister(priv->tc_dev);
return 0;
}
static const struct i2c_device_id imx185_id[] = {
{ "imx185", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, imx185_id);
static struct i2c_driver imx185_i2c_driver = {
.driver = {
.name = "imx185",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(imx185_of_match),
},
.probe = imx185_probe,
.remove = imx185_remove,
.id_table = imx185_id,
};
module_i2c_driver(imx185_i2c_driver);
MODULE_DESCRIPTION("Media Controller driver for Sony IMX185");
MODULE_AUTHOR("NVIDIA Corporation");
MODULE_LICENSE("GPL v2");
5 - error dmesg
[ 2.036120] imx185 30-001a: probing v4l2 sensor
[ 2.036577] imx185: zp: [OK]: func[imx185_power_get] line[425]->|OK|
[ 2.037000] imx185 30-001a: tegracam sensor driver:imx185_v2.0.6
[ 2.037479] imx185: zp: [OK]: func[imx185_power_on] line[360]->|OK|
[ 2.037637] imx185: zp: [OK]: func[imx185_power_off] line[390]->|OK|
[ 2.038031] imx185 30-001a: Detected IMX185 sensor
..........
[ 5.769203] tegra194-vi5 15c10000.vi: subdev imx185 30-001a bound
..........
[ 7.362862] Could not create tracefs 'imx185_s_stream' directory
[ 7.363218] imx185: module is already loaded
..........
[ 295.830880] imx185: zp: [OK]: func[imx185_power_on] line[360]->|OK|
[ 295.842189] imx185: zp: [OK]: func[imx185_power_off] line[390]->|OK|
[ 296.011184] imx185: zp: [OK]: func[imx185_power_on] line[360]->|OK|
[ 296.011428] imx185: zp: [OK]: func[imx185_power_off] line[390]->|OK|
[ 296.051544] imx185: zp: [OK]: func[imx185_power_on] line[360]->|OK|
[ 296.093400] imx185: zp: [OK]: func[imx185_set_mode] line[513]->|OK| mode = 0
[ 296.093608] imx185: zp: [OK]: func[imx185_set_mode] line[523]->|OK|
[ 296.093723] imx185: zp: [OK]: func[imx185_start_streaming] line[544]->|OK|
[ 296.094059] [RCE] vi5_hwinit: firmware CL2018101701 protocol version 2.2
[ 298.574079] tegra194-vi5 15c10000.vi: no reply from camera processor
[ 298.574287] tegra194-vi5 15c10000.vi: uncorr_err: request timed out after 2500 ms
[ 298.574444] tegra194-vi5 15c10000.vi: err_rec: attempting to reset the capture channel
[ 298.577082] tegra-capture-ivc ivc-bc00000.rtcpu:ivccontrol@3: No callback found for msg id: 0x39
[ 298.577304] tegra-capture-ivc ivc-bc00000.rtcpu:ivccontrol@3: No callback found for msg id: 0x41
[ 298.577455] tegra-capture-ivc ivc-bc00000.rtcpu:ivccontrol@3: No callback found for msg id: 0x37
[ 298.577700] tegra194-vi5 15c10000.vi: err_rec: successfully reset the capture channel
[ 301.134056] tegra194-vi5 15c10000.vi: no reply from camera processor
[ 301.134216] tegra194-vi5 15c10000.vi: uncorr_err: request timed out after 2500 ms
[ 301.134361] tegra194-vi5 15c10000.vi: err_rec: attempting to reset the capture channel
[ 301.137003] tegra194-vi5 15c10000.vi: err_rec: successfully reset the capture channel
[ 303.694009] tegra194-vi5 15c10000.vi: no reply from camera processor
[ 303.694172] tegra194-vi5 15c10000.vi: uncorr_err: request timed out after 2500 ms
[ 303.694348] tegra194-vi5 15c10000.vi: err_rec: attempting to reset the capture channel
[ 303.697229] tegra194-vi5 15c10000.vi: err_rec: successfully reset the capture channel
[ 303.766724] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 38, err_data 160
[ 303.799973] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
[ 303.833385] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 32, err_data 160
[ 303.833596] tegra194-vi5 15c10000.vi: corr_err: discarding frame 1, flags: 0, err_data 131072
[ 303.866612] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
[ 303.966596] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
[ 303.999932] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
[ 304.033256] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
........
[ 313.466160] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
[ 313.499633] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
[ 313.532835] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
[ 313.566156] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
[ 313.599499] tegra194-vi5 15c10000.vi: corr_err: discarding frame 0, flags: 160, err_data 160
[ 313.600737] imx185: zp: [OK]: func[imx185_stop_streaming] line[569]->|OK|
[ 313.652769] imx185: zp: [OK]: func[imx185_power_off] line[390]->|OK|
6-trace log
echo 1 > /sys/kernel/debug/tracing/tracing_on
echo 30720 > /sys/kernel/debug/tracing/buffer_size_kb
echo 1 > /sys/kernel/debug/tracing/events/tegra_rtcpu/enable
echo 1 > /sys/kernel/debug/tracing/events/freertos/enable
echo 2 > /sys/kernel/debug/camrtc/log-level
echo 1 > /sys/kernel/debug/tracing/events/camera_common/enable
echo > /sys/kernel/debug/tracing/trace
cat /sys/kernel/debug/tracing/trace
6.a - upload the trace log below
trace.log (910.0 KB)
maybe it’s big , please download to see
I found the error about Lost FE means Xavier didn’t receive Frame End package.
But i’m not sure if there are any other errors.
7 - put up the clock also have this problem
echo 1 > /sys/kernel/debug/bpmp/debug/clk/vi/mrq_rate_locked
echo 1 > /sys/kernel/debug/bpmp/debug/clk/isp/mrq_rate_locked
echo 1 > /sys/kernel/debug/bpmp/debug/clk/nvcsi/mrq_rate_locked
cat /sys/kernel/debug/bpmp/debug/clk/vi/max_rate
cat /sys/kernel/debug/bpmp/debug/clk/isp/max_rate
cat /sys/kernel/debug/bpmp/debug/clk/nvcsi/max_rate
echo 998400000 > /sys/kernel/debug/bpmp/debug/clk/vi/rate
echo 1190400000 > /sys/kernel/debug/bpmp/debug/clk/isp/rate
echo 400000000 > /sys/kernel/debug/bpmp/debug/clk/nvcsi/rate
Any advice all be helpful for me.
I doubt my dts has some problems, but i am not sure, please help me.
Thank you so much.
zhou