驱动代码文件list:
kernel/kernel-4.9/Documentation/devicetree/bindings/video/max9291.txt
kernel/nvidia/include/media/max9296.h
kernel/nvidia/include/media/max9295.h
kernel/nvidia/drivers/media/i2c/max9295.c
kernel/nvidia/drivers/media/i2c/max9296.c
kernel/nvidia/drivers/media/i2c/max9295.c:541: { .compatible = "nvidia,max9295", },
kernel/nvidia/drivers/media/i2c/max9296.c:784: { .compatible = "nvidia,max9296", },
kernel/nvidia/drivers/media/platform/tegra/camera/camera_common.c
kernel/nvidia/drivers/video/tegra/camera/tegra_camera_platform.c
prj设备树配置:
hardware/nvidia/platform/t19x/mccoy/kernel-dts/common/tegra194-e3900-0000-camera-imx390-a00.dtsi
#define CAM0_RST_L TEGRA194_MAIN_GPIO(H, 3)
#define CAMERA_I2C_MUX_BUS(x) (0x1E + x)
i2c@3180000 {
tca9546@70 {
compatible = "nxp,pca9546";
reg = <0x70>;
force_bus_start = <CAMERA_I2C_MUX_BUS(0)>;
i2c@0 {
reg = <0>;
dser: max9296@48 {
compatible = "nvidia,max9296";
reg = <0x48>;
csi-mode = "2x4";
max-src = <2>;
reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_HIGH>;
};
ser_prim: max9295_prim@62 {
compatible = "nvidia,max9295";
reg = <0x62>;
is-prim-ser;
};
ser_a: max9295_a@40 {
compatible = "nvidia,max9295";
reg = <0x40>;
nvidia,gmsl-dser-device = <&dser>;
};
ser_b: max9295_b@60 {
compatible = "nvidia,max9295";
reg = <0x60>;
nvidia,gmsl-dser-device = <&dser>;
};
和英伟达平台对接以及注册:
kernel/nvidia/drivers/media/i2c/imx390.c
static const struct v4l2_subdev_internal_ops imx390_subdev_internal_ops = { //mark
.open = imx390_open,
};
static struct camera_common_sensor_ops imx390_common_ops = { //最终接口
.numfrmfmts = ARRAY_SIZE(imx390_frmfmt),
.frmfmt_table = imx390_frmfmt,
.power_on = imx390_power_on,
.power_off = imx390_power_off,
.write_reg = imx390_write_reg,
.read_reg = imx390_read_reg,
.parse_dt = imx390_parse_dt,
.power_get = imx390_power_get,
.power_put = imx390_power_put,
.set_mode = imx390_set_mode,
.start_streaming = imx390_start_streaming,
.stop_streaming = imx390_stop_streaming,
};
static struct tegracam_ctrl_ops imx390_ctrl_ops = {
.numctrls = ARRAY_SIZE(ctrl_cid_list),
.ctrl_cid_list = ctrl_cid_list,
.set_gain = imx390_set_gain,
.set_exposure = imx390_set_exposure,
.set_exposure_short = imx390_set_exposure,
.set_frame_rate = imx390_set_frame_rate,
.set_group_hold = imx390_set_group_hold,
};
tc_dev->dev = dev;
strncpy(tc_dev->name, "imx390", sizeof(tc_dev->name));
tc_dev->dev_regmap_config = &sensor_regmap_config;
tc_dev->sensor_ops = &imx390_common_ops;
tc_dev->v4l2sd_internal_ops = &imx390_subdev_internal_ops;
tc_dev->tcctrl_ops = &imx390_ctrl_ops;
//xcz
err = tegracam_device_register(tc_dev); //v4l2注册,平台已经封装了一个接口函数
tegracam_set_privdata
err = tegracam_v4l2subdev_register(tc_dev, true); //xcz mark
注册的dev接口定义:
./kernel/nvidia/include/media/tegracam_core.h
struct tegracam_device {
struct camera_common_data *s_data;
struct media_pad pad;
u32 version;
bool is_streaming;
/* variables to be filled by the driver to register */
char name[32];
struct i2c_client *client;
struct device *dev;
u32 numctrls;
const u32 *ctrl_cid_list;
const struct regmap_config *dev_regmap_config;
struct camera_common_sensor_ops *sensor_ops;
const struct v4l2_subdev_ops *v4l2sd_ops;
const struct v4l2_subdev_internal_ops *v4l2sd_internal_ops;
const struct media_entity_operations *media_ops;
const struct tegracam_ctrl_ops *tcctrl_ops;
void *priv;
};
多camera兼容的设计:
只有imx390.c中有 read_reg 接口
====》不读ID
sensor_ops->read 没有调用
err = imx390_board_setup(priv); //这个函数接口可以加
ser deser设计思路:
一路deser,2路ser,加上一路默认的ser,所以设备树中做了4个client来实现。
deser设计了一个驱动程序,2路ser和一路默认的ser设计了一个驱动程序。
max9295.c max9296.c 都是硬件spec相关的,看寄存器,这里就不分析了