Linux v4l2子系统(4):I2C&OV13850
关键词:ov13850、subdev、media entity pad等等。
1 OV13850原理图
由原理图可知,Camera接口分为三部分:
- 4 Lane MIPI信号接口。
- I2C控制接口。
- Powerdown,Reset,供电接口。
2 I2C总线dts配置和初始化
i2c3总线:
i2c3: i2c@feab0000 {
compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
reg = <0x0 0xfeab0000 0x0 0x1000>;
clocks = <&cru CLK_I2C3>, <&cru PCLK_I2C3>;
clock-names = "i2c", "pclk";
interrupts = <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&i2c3m0_xfer>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
i2c3总线初始化:
rk3x_i2c_driver
rk3x_i2c_probe
i2c_add_numbered_adapter
3 OV13850 dts配置和初始化
ov13850挂载在i2c3上面设备:
&i2c3 {
status = "okay";
clock-frequency = <100000>;
pinctrl-0 = <&i2c3m0_xfer>;
...
ov13850_3: ov13850@10 {
status = "okay";
compatible = "otvi,ov13850";
reg = <0x10>;
clocks = <&cru CLK_MIPI_CAMARAOUT_M3>;
clock-names = "xvclk";
power-domains = <&power RK3588_PD_VI>;
pinctrl-names = "default";
pinctrl-0 = <&mipim0_camera3_clk>;
reset-gpios = <&gpio1 RK_PD3 GPIO_ACTIVE_HIGH>;
pwdn-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>;
rockchip,camera-module-index = <2>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "CMK-CT0116"; //"ZC-OV13850R2A-V1";
rockchip,camera-module-lens-name = "Largan-50013A1"; //"Largan-50064B31";
port {
ov13850_out_3: endpoint {
remote-endpoint = <&mipidphy0_in_ucam0_ov13850>;--输出到csi2_dphy0的mipidphy0_in_ucam0_ov13850。
data-lanes = <1 2 3 4>;
};
};
};
};
注册ov13850设备:
- 初始化v4l2_subdev设备。
- 获取dts配置。
- 初始化ov13850 v4l2 Control。
- 上电,检查ID。
- 创建ov13850对应的Media Entity和Pad。
- 创建v4l2子系统v4l2_subdev对应的设备节点。
sensor_mod_init
->ov13850_i2c_driver
->ov13850_probe
->分配struct ov13850结构体,从dts中读取参数进行初始化。flags置位V4L2_SUBDEV_FL_HAS_DEVNODE。
->v4l2_i2c_subdev_init--初始化subdev,操作函数为ov13850_subdev_ops。
->v4l2_subdev_init--初始化v4l2_subdev设备。
->ov13850_initialize_controls--初始化ov13850支持的Control。
->V4L2_CID_PIXEL_RATE/V4L2_CID_HBLANK/V4L2_CID_VBLANK/V4L2_CID_EXPOSURE/V4L2_CID_ANALOGUE_GAIN/V4L2_CID_TEST_PATTERN。
->__ov13850_power_on--对ov13850进行上电初始化。
->ov13850_check_sensor_id--校验ID。
->media_entity_pads_init--初始化并创建Pad,仅有一个Source Pad。
->v4l2_async_register_subdev_sensor_common--注册v4l2_subdev设备,创建ov13850对应的Media Entity,创建设备节点。
OV13850 subdev操作函数集,其中的操作函数多被v4l2_subdev_call()调用:
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API static const struct v4l2_subdev_internal_ops ov13850_internal_ops = { .open = ov13850_open, }; #endif static const struct v4l2_subdev_core_ops ov13850_core_ops = { .s_power = ov13850_s_power, .ioctl = ov13850_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl32 = ov13850_compat_ioctl32, #endif }; static const struct v4l2_subdev_video_ops ov13850_video_ops = { .s_stream = ov13850_s_stream, .g_frame_interval = ov13850_g_frame_interval, }; static const struct v4l2_subdev_pad_ops ov13850_pad_ops = { .enum_mbus_code = ov13850_enum_mbus_code,--被subdev_do_ioctl的VIDIOC_SUBDEV_ENUM_MBUS_CODE调用。 .enum_frame_size = ov13850_enum_frame_sizes,--被subdev_do_ioctl的VIDIOC_SUBDEV_ENUM_FRAME_SIZE调用。 .enum_frame_interval = ov13850_enum_frame_interval,--被subdev_do_ioctl的VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL调用。 .get_fmt = ov13850_get_fmt,--被subdev_do_ioctl的VIDIOC_SUBDEV_G_FMT调用。 .set_fmt = ov13850_set_fmt,--被subdev_do_ioctl的VIDIOC_SUBDEV_S_FMT调用。 .get_mbus_config = ov13850_g_mbus_config, }; static const struct v4l2_subdev_ops ov13850_subdev_ops = { .core = &ov13850_core_ops, .video = &ov13850_video_ops, .pad = &ov13850_pad_ops, };
ov13850设备:
- 对应的v4l2设备为/dev/v4l-subdev2。
- 在Media子系统中对应的Entity为m02_b_ov13850 3-0010,Entity仅包含一个Source Pad。
联系方式:arnoldlu@qq.com