这绝对是一种奇怪的锁定官方图像的方式......尤其是对于那些不流利中文的人 X')
感谢这篇文章,它有帮助。
大家好,
我是一名嵌入式系统的学生(来自法国),我正在围绕 V851S 制作这个小板。 它应该用于连接树莓派相机或 esp32-cam 相机,并使用 usb-uvc 将它们用作 USB 网络摄像头。
该项目仍处于早期阶段,我是这个论坛的新手,所以我想我只是将其作为介绍发布。
以下是该板的一些图片:
大家好,
我已经使用 yukilizard 项目的 BSP 以及 tina-V853 存储库成功为 V851S 构建了映像。 但现在我想为 V851S 构建 GCC。 当我在 Developpement->GCC 中启用该选项(它自己启用其他选项)并且我“make”时,它编译得很好,直到到达 GCC,此时我遇到了此错误:
make menuconfig options
error
有谁知道我如何/是否可以解决这个问题?
大家好,
我的 V851S (tina-linux) 上的 i2c/twi 总线似乎有问题,每次我尝试使用 i2cdump 或 i2cDetect 等 shell i2C 实用程序时,我都会收到以下错误 (i2cget 和 i2cwrite 也会发生这种情况):
root@TinaLinux:/sys/devices/platform/soc/pio/gpiochip0/gpio/gpio8# i2cdetect 1
[ 786.358195] i2c i2c-1: ioctl, cmd=0x705, arg=0xbea72c6c
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
0 1 2 3 4 5 6 7 8 [ 789.513384] i2c i2c-1: ioctl, cmd=0x703, arg=0x03
9 a b c d e f
00: [ 789.521510] i2c i2c-1: ioctl, cmd=0x720, arg=0xbea72c4c
[ 789.530134] i2c i2c-1: master_xfer[0] W, addr=0x03, len=0
[ 789.536525] twi_start()508 - [i2c1] START can't sendout!
[ 789.542553] sunxi_i2c_do_xfer()1951 - [i2c1] twi_regulator:
[ 789.549191] twi_start()508 - [i2c1] START can't sendout!
[ 789.555137] sunxi_i2c_do_xfer()1951 - [i2c1] twi_regulator:
[ 789.561763] twi_start()508 - [i2c1] START can't sendout!
[ 789.567722] sunxi_i2c_do_xfer()1951 - [i2c1] twi_regulator:
-- [ 789.574219] i2c i2c-1: ioctl, cmd=0x703, arg=0x04
[ 789.579759] i2c i2c-1: ioctl, cmd=0x720, arg=0xbea72c4c
[ 789.585615] i2c i2c-1: master_xfer[0] W, addr=0x04, len=0
[ 789.591919] twi_start()508 - [i2c1] START can't sendout!
[ 789.597882] sunxi_i2c_do_xfer()1951 - [i2c1] twi_regulator:
[ 789.604494] twi_start()508 - [i2c1] START can't sendout!
[ 789.610452] sunxi_i2c_do_xfer()1951 - [i2c1] twi_regulator:
[ 789.617068] twi_start()508 - [i2c1] START can't sendout!
[ 789.623016] sunxi_i2c_do_xfer()1951 - [i2c1] twi_regulator:
-- [ 789.629512] i2c i2c-1: ioctl, cmd=0x703, arg=0x05
[ 789.635030] i2c i2c-1: ioctl, cmd=0x720, arg=0xbea72c4c
[ 789.640964] i2c i2c-1: master_xfer[0] W, addr=0x05, len=0
[ 789.647206] twi_start()508 - [i2c1] START can't sendout!
[ 789.653155] sunxi_i2c_do_xfer()1951 - [i2c1] twi_regulator:
[ 789.659783] twi_start()508 - [i2c1] START can't sendout!
[ 789.665728] sunxi_i2c_do_xfer()1951 - [i2c1] twi_regulator:
[ 789.672352] twi_start()508 - [i2c1] START can't sendout!
[ 789.678309] sunxi_i2c_do_xfer()1951 - [i2c1] twi_regulator:
这是我的 I2C 内核配置:
和我的 i2c“menuconfig”:
我知道至少已经有一篇关于此问题的帖子,但这只是一条警告消息,在我的情况下,它无法正常工作,因为我在 I2C 1 的地址 0x36 上有一个未检测到的设备。
我怎样才能摆脱这些错误?
我的 twi DTS 配置如下:
twi0_pins_a: twi0@0 {
allwinner,pins = "PA16", "PA17";
allwinner,pname = "twi0_scl", "twi0_sda";
allwinner,function = "twi0";
allwinner,muxsel = <4>;
allwinner,drive = <0>;
allwinner,pull = <1>;
};
twi0_pins_b: twi0@1 {
allwinner,pins = "PA16", "PA17";
allwinner,function = "io_disabled";
allwinner,muxsel = <0xf>;
allwinner,drive = <0>;
allwinner,pull = <0>;
};
twi1_pins_a: twi1@0 {
allwinner,pins = "PA6", "PA7";
allwinner,pname = "twi1_scl", "twi1_sda";
allwinner,function = "twi1";
allwinner,muxsel = <4>;
allwinner,drive = <0>;
allwinner,pull = <1>;
};
twi1_pins_b: twi1@1 {
allwinner,pins = "PA6", "PA7";
allwinner,function = "io_disabled";
allwinner,muxsel = <0xf>;
allwinner,drive = <0>;
allwinner,pull = <0>;
};
twi2_pins_a: twi2@0 {
allwinner,pins = "PH11", "PH12";
allwinner,pname = "twi2_scl", "twi2_sda";
allwinner,function = "twi2";
allwinner,muxsel = <5>;
allwinner,drive = <0>;
allwinner,pull = <1>;
};
twi2_pins_b: twi2@1 {
allwinner,pins = "PH11", "PH12";
allwinner,function = "io_disabled";
allwinner,muxsel = <0xf>;
allwinner,drive = <0>;
allwinner,pull = <0>;
};
twi3_pins_a: twi3@0 {
allwinner,pins = "PI3", "PI4";
allwinner,pname = "twi3_scl", "twi3_sda";
allwinner,function = "twi6";
allwinner,muxsel = <6>;
allwinner,drive = <0>;
allwinner,pull = <1>;
};
twi3_pins_b: twi3@1 {
allwinner,pins = "PI3", "PI4";
allwinner,function = "io_disabled";//io_disabled
allwinner,muxsel = <0xf>;
allwinner,drive = <0>;
allwinner,pull = <0>;
};
twi4_pins_a: twi4@0 {
allwinner,pins = "PI1", "PI2";
allwinner,pname = "twi4_scl", "twi4_sda";
allwinner,function = "twi4";
allwinner,muxsel = <5>;
allwinner,drive = <0>;
allwinner,pull = <1>;
};
twi4_pins_b: twi4@1 {
allwinner,pins = "PI1", "PI2";
allwinner,function = "io_disabled";
allwinner,muxsel = <0xf>;
allwinner,drive = <0>;
allwinner,pull = <0>;
};
大家好,我目前正在为 V851S 构建映像,并且我总是在“make”期间看到弹出这些警告:
Check Vendor Package...
CreateSoftLink /home/kanken/code/tina-v853-open/openwrt/openwrt/package/subpackage link to /home/kanken/code/tina-v853-open/openwrt/package
end
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-libav/Makefile' has a build dependency on 'libgstreamer1', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-libav/Makefile' has a build dependency on 'gstreamer1-plugins-base', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-omx/Makefile' has a dependency on 'libgst1gl', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-aw/Makefile' has a build dependency on 'libgstreamer1', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-aw/Makefile' has a build dependency on 'gstreamer1-plugins-base', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-aw/Makefile' has a build dependency on 'gstreamer1-plugins-good', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-bad/Makefile' has a dependency on 'wayland', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-bad/Makefile' has a dependency on 'wayland-protocols', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-bad/Makefile' has a dependency on 'libgst1badvideo', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-bad/Makefile' has a dependency on 'libgst1gl', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-bad/Makefile' has a build dependency on 'libgstreamer1', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-bad/Makefile' has a build dependency on 'gstreamer1-plugins-base', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-base/Makefile' has a build dependency on 'libgstreamer1', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-good/Makefile' has a build dependency on 'libgstreamer1', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-good/Makefile' has a build dependency on 'gstreamer1-plugins-base', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-ugly/Makefile' has a build dependency on 'libgstreamer1', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/multimedia/gstreamer/gst1-plugins-ugly/Makefile' has a build dependency on 'gstreamer1-plugins-base', which does not exist
WARNING: Makefile 'package/kernel/linux/Makefile' has a dependency on 'kmod-sunxi-rf-wlan', which does not exist
WARNING: Makefile 'package/subpackage/allwinner/eyesee-mpp/middleware/Makefile' has a dependency on 'awsystrace', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/gui/qt/qt5/Makefile' has a dependency on 'weston', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/gui/qt/qt5/Makefile' has a dependency on 'wayland', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/gui/qt/qt5/Makefile' has a dependency on 'qt5-multimediawidgets', which does not exist
WARNING: Makefile 'package/subpackage/thirdparty/gui/qt/qt5/Makefile' has a build dependency on 'libstdcpp', which does not exist
copy from /home/kanken/code/tina-v853-open/openwrt/target/v851s/v851s-lizard/defconfig
它们引用了我已经安装在我的电脑上的软件包,但它们不会消失,这是正常的还是我错过了这里的一个步骤?我应该忽略这些警告吗?
事实证明 .ko 文件确实是由“make”命令构建的,但它们只是没有被发送到图像:
为了能够将它们包含在图像中,我必须编辑 openwrt/target/v851S/<board_name> 中的文件:
添加我需要的各种 ov 驱动程序并注释掉我不需要的 gc2053 驱动程序
这仍然有点奇怪,这不是自动配置的,需要您手动编辑这些 makefile...感觉很笨重
大家好,
在修复了我的 i2c 并使用 i2cDetect 和手动 GPIO 选择手动检测到我的相机后,我正在尝试为相机制作一个驱动程序。
我将它基于已经存在的 OV5468 mipi 驱动程序。 我更改了所有必需的标识符和寄存器/值,以使其符合 ov5647 的要求,我编辑了必要的 makefile 来构建它,并为新传感器配置了板的 DTS。
我的问题是这样的:
当我使用 insmod 加载 ov5647_mipi.ko 内核模块时,没有任何反应。 即使我将日志级别设置为 8,并且我在驱动程序中放置了各种 printk() 调用,但 dmesg 中根本没有出现任何消息,但这些调用实际上都没有显示在日志中。 你们知道我可能错过了什么吗? 也许是某个特定的配置使日志静音? DTS 错误?
root@TinaLinux:/lib/modules/4.9.191# ls
ov5640.ko soc_camera.ko videobuf-core.ko
ov5647_mipi.ko soc_camera_platform.ko videobuf2-dma-contig.ko
ov5648_mipi.ko soc_mediabus.ko vin_io.ko
ov5658.ko uvcvideo.ko vin_v4l2.ko
root@TinaLinux:/lib/modules/4.9.191# lsmod
Module Size Used by
vin_v4l2 176157 0
vin_io 19952 1 vin_v4l2
videobuf2_dma_contig 8632 1 vin_v4l2
root@TinaLinux:/lib/modules/4.9.191# insmod ov5647_mipi.ko
root@TinaLinux:/lib/modules/4.9.191# lsmod
Module Size Used by
ov5647_mipi 6469 0
vin_v4l2 176157 0
vin_io 19952 2 ov5647_mipi,vin_v4l2
videobuf2_dma_contig 8632 1 vin_v4l2
root@TinaLinux:/lib/modules/4.9.191# dmesg | tail
root@TinaLinux:/lib/modules/4.9.191#
我的DTS:
soc@03000000 {
/*wlan: wlan@0 {
compatible = "allwinner,sunxi-wlan";
pinctrl-names = "default";
clock-names = "32k-fanout0";
clocks = <&clk_fanout0>;
wlan_busnum = <0x1>;
wlan_regon = <&pio PE 6 1 0x1 0x2 0>;
wlan_hostwake = <&pio PE 7 14 0x1 0x2 0>;
chip_en;
power_en;
status = "io_disabled";
wakeup-source;
};*/
vind0:vind@0 {
vind0_clk = <200000000>;
status = "okay";
csi2:csi@2 {
pinctrl-names = "default","sleep";
pinctrl-0 = <&ncsi_pins_a>;
pinctrl-1 = <&ncsi_pins_b>;
status = "okay";
};
tdm0:tdm@0 {
work_mode = <0>;
};
isp00:isp@0 {
work_mode = <0>;
};
scaler00:scaler@0 {
work_mode = <0>;
};
scaler10:scaler@4 {
work_mode = <0>;
};
scaler20:scaler@8 {
work_mode = <0>;
};
scaler30:scaler@12 {
work_mode = <0>;
};
actuator0:actuator@0 {
device_type = "actuator0";
actuator0_name = "ad5820_act";
actuator0_slave = <0x18>;
actuator0_af_pwdn = <>;
actuator0_afvdd = "afvcc-csi";
actuator0_afvdd_vol = <2800000>;
status = "disabled";
};
flash0:flash@0 {
device_type = "flash0";
flash0_type = <2>;
flash0_en = <>;
flash0_mode = <>;
flash0_flvdd = "";
flash0_flvdd_vol = <>;
status = "disabled";
};
sensor0:sensor@0 {
device_type = "sensor0";
sensor0_mname = "ov5647_mipi";
sensor0_twi_cci_id = <1>;
sensor0_twi_addr = <0x6c>;
sensor0_mclk_id = <0>;
sensor0_pos = "rear";
sensor0_isp_used = <1>;
sensor0_fmt = <1>;
sensor0_stby_mode = <0>;
sensor0_vflip = <0>;
sensor0_hflip = <0>;
sensor0_iovdd-supply = <1800000>;
sensor0_iovdd_vol = <>;
sensor0_avdd-supply = <2800000>;
sensor0_avdd_vol = <>;
sensor0_dvdd-supply = <1200000>;
sensor0_dvdd_vol = <>;
sensor0_reset = <>;
//sensor0_power_en = <>;
//sensor0_pwdn = <>;
sensor0_power_en = <&pio PA 9 1 0 1 0>;
sensor0_pwdn = <&pio PA 8 1 0 1 0>;
/*sensor0_sm_hs = <&pio PE 2 1 0 1 0>;*/
/*sensor0_sm_vs = <&pio PE 3 1 0 1 0>;*/
flash_handle = <&flash0>; //&flash0
act_handle = <&actuator0>; //&actuator0
status = "okay";
};
sensor1:sensor@1 {
device_type = "sensor1";
sensor1_mname = "ov5640";
sensor1_twi_cci_id = <2>;
sensor1_twi_addr = <0x30>;
sensor1_mclk_id = <1>;
sensor1_pos = "front";
sensor1_isp_used = <1>;
sensor1_fmt = <1>;
sensor1_stby_mode = <0>;
sensor1_vflip = <0>;
sensor1_hflip = <0>;
sensor1_iovdd-supply = <>;
sensor1_iovdd_vol = <1800000>;
sensor1_avdd-supply = <>;
sensor1_avdd_vol = <2800000>;
sensor1_dvdd-supply = <>;
sensor1_dvdd_vol = <1200000>;
sensor1_power_en = <>;
sensor1_reset = <>;
sensor1_pwdn = <>;
sensor1_sm_hs = <&pio PE 2 1 0 1 0>;
sensor1_sm_vs = <&pio PE 3 1 0 1 0>;
flash_handle = <>;
act_handle = <>;
status = "disabled";
};
vinc00:vinc@0 {
vinc0_csi_sel = <0>;
vinc0_mipi_sel = <0>;
vinc0_isp_sel = <0>;
vinc0_isp_tx_ch_ = <0>;
vinc0_tdm_rx_sel = <0>;
vinc0_rear_sensor_sel = <0>;
vinc0_front_sensor_sel = <0>;
vinc0_sensor_list = <0>;
work_mode = <0x0>;
status = "okay";
};
vinc01:vinc@1 {
vinc1_csi_sel = <2>;
vinc1_mipi_sel = <0xff>;
vinc1_isp_sel = <1>;
vinc1_isp_tx_ch = <1>;
vinc1_tdm_rx_sel = <1>;
vinc1_rear_sensor_sel = <0>;
vinc1_front_sensor_sel = <0>;
vinc1_sensor_list = <0>;
status = "disabled";
};
vinc02:vinc@2 {
vinc2_csi_sel = <2>;
vinc2_mipi_sel = <0xff>;
vinc2_isp_sel = <2>;
vinc2_isp_tx_ch_ = <2>;
vinc2_tdm_rx_sel = <2>;
vinc2_rear_sensor_sel = <0>;
vinc2_front_sensor_sel = <0>;
vinc2_sensor_list = <0>;
status = "disabled";
};
vinc03:vinc@3 {
vinc3_csi_sel = <0>;
vinc3_mipi_sel = <0xff>;
vinc3_isp_sel = <0>;
vinc3_isp_tx_ch_ = <0>;
vinc3_tdm_rx_sel = <0>;
vinc3_rear_sensor_sel = <1>;
vinc3_front_sensor_sel = <1>;
vinc3_sensor_list = <0>;
status = "disabled";
};
vinc10:vinc@4 {
vinc4_csi_sel = <0>;
vinc4_mipi_sel = <0>;
vinc4_isp_sel = <0>;
vinc4_isp_tx_ch = <0>;
vinc4_tdm_rx_sel = <0>;
vinc4_rear_sensor_sel = <0>;
vinc4_front_sensor_sel = <0>;
vinc4_sensor_list = <0>;
work_mode = <0x0>;
status = "okay";
};
vinc11:vinc@5 {
vinc5_csi_sel = <2>;
vinc5_mipi_sel = <0xff>;
vinc5_isp_sel = <1>;
vinc5_isp_tx_ch = <1>;
vinc5_tdm_rx_sel = <1>;
vinc5_rear_sensor_sel = <0>;
vinc5_front_sensor_sel = <0>;
vinc5_sensor_list = <0>;
status = "disabled";
};
vinc12:vinc@6 {
vinc6_csi_sel = <2>;
vinc6_mipi_sel = <0xff>;
vinc6_isp_sel = <0>;
vinc6_isp_tx_ch = <0>;
vinc6_tdm_rx_sel = <0>;
vinc6_rear_sensor_sel = <0>;
vinc6_front_sensor_sel = <0>;
vinc6_sensor_list = <0>;
status = "disabled";
};
vinc13:vinc@7 {
vinc7_csi_sel = <2>;
vinc7_mipi_sel = <0xff>;
vinc7_isp_sel = <0>;
vinc7_isp_tx_ch = <0>;
vinc7_tdm_rx_sel = <0>;
vinc7_rear_sensor_sel = <0>;
vinc7_front_sensor_sel = <0>;
vinc7_sensor_list = <0>;
status = "disabled";
};
vinc20:vinc@8 {
vinc8_csi_sel = <0>;
vinc8_mipi_sel = <0>;
vinc8_isp_sel = <0>;
vinc8_isp_tx_ch = <0>;
vinc8_tdm_rx_sel = <0>;
vinc8_rear_sensor_sel = <0>;
vinc8_front_sensor_sel = <0>;
vinc8_sensor_list = <0>;
work_mode = <0x0>;
status = "okay";
};
vinc21:vinc@9 {
vinc9_csi_sel = <2>;
vinc9_mipi_sel = <0xff>;
vinc9_isp_sel = <0>;
vinc9_isp_tx_ch = <0>;
vinc9_tdm_rx_sel = <0>;
vinc9_rear_sensor_sel = <0>;
vinc9_front_sensor_sel = <0>;
vinc9_sensor_list = <0>;
status = "disabled";
};
vinc22:vinc@10 {
vinc10_csi_sel = <2>;
vinc10_mipi_sel = <0xff>;
vinc10_isp_sel = <0>;
vinc10_isp_tx_ch = <0>;
vinc10_tdm_rx_sel = <0>;
vinc10_rear_sensor_sel = <0>;
vinc10_front_sensor_sel = <0>;
vinc10_sensor_list = <0>;
status = "disabled";
};
vinc23:vinc@11 {
vinc11_csi_sel = <2>;
vinc11_mipi_sel = <0xff>;
vinc11_isp_sel = <0>;
vinc11_isp_tx_ch = <0>;
vinc11_tdm_rx_sel = <0>;
vinc11_rear_sensor_sel = <0>;
vinc11_front_sensor_sel = <0>;
vinc11_sensor_list = <0>;
status = "disabled";
};
vinc30:vinc@12 {
vinc12_csi_sel = <0>;
vinc12_mipi_sel = <0>;
vinc12_isp_sel = <0>;
vinc12_isp_tx_ch = <0>;
vinc12_tdm_rx_sel = <0>;
vinc12_rear_sensor_sel = <0>;
vinc12_front_sensor_sel = <0>;
vinc12_sensor_list = <0>;
work_mode = <0x0>;
status = "okay";
};
vinc31:vinc@13 {
vinc13_csi_sel = <2>;
vinc13_mipi_sel = <0xff>;
vinc13_isp_sel = <0>;
vinc13_isp_tx_ch = <0>;
vinc13_tdm_rx_sel = <0>;
vinc13_rear_sensor_sel = <0>;
vinc13_front_sensor_sel = <0>;
vinc13_sensor_list = <0>;
status = "disabled";
};
vinc32:vinc@14 {
vinc14_csi_sel = <2>;
vinc14_mipi_sel = <0xff>;
vinc14_isp_sel = <0>;
vinc14_isp_tx_ch = <0>;
vinc14_tdm_rx_sel = <0>;
vinc14_rear_sensor_sel = <0>;
vinc14_front_sensor_sel = <0>;
vinc14_sensor_list = <0>;
status = "disabled";
};
vinc33:vinc@15 {
vinc15_csi_sel = <2>;
vinc15_mipi_sel = <0xff>;
vinc15_isp_sel = <0>;
vinc15_isp_tx_ch = <0>;
vinc15_tdm_rx_sel = <0>;
vinc15_rear_sensor_sel = <0>;
vinc15_front_sensor_sel = <0>;
vinc15_sensor_list = <0>;
status = "disabled";
};
};
};
最后是我的驱动程序,如您所见,它实现了各种日志:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <linux/clk.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mediabus.h>
#include <linux/io.h>
#include "camera.h"
#include "sensor_helper.h"
MODULE_AUTHOR("YG");
MODULE_DESCRIPTION("A low-level driver for OV5647 sensors");
MODULE_LICENSE("GPL");
#define MCLK (24*1000*1000)
#define V4L2_IDENT_SENSOR 0x5647
#define DEV_DBG_EN 1
/*
* Our nominal (default) frame rate.
*/
#define SENSOR_FRAME_RATE 30
/*
* The ov5647 i2c address
*/
#define I2C_ADDR 0x6c
#define SENSOR_NAME "ov5647_mipi"
/*
* The default register settings
*/
static struct regval_list sensor_default_regs[] = {
/*2lane initial*/
/*Slave_ID=0x6c*/
{0x0100, 0x00},
{0x0103, 0x01},
// delay(5ms)
{REG_DLY, 0x25},
{0x3001, 0x00},
{0x3002, 0x00},
{0x3011, 0x02},
{0x3018, 0x4c},
{0x3022, 0x00},
{0x3034, 0x1a},
{0x3035, 0x21},
{0x3036, 0x69},
{0x3037, 0x03},
{0x3038, 0x00},
{0x3039, 0x00},
{0x303a, 0x00},
{0x303b, 0x19},
{0x303c, 0x11},
{0x303d, 0x30},
{0x3105, 0x11},
{0x3106, 0x05},
{REG_DLY, 0x05},
{0x3304, 0x28},
{0x3305, 0x41},
{0x3306, 0x30},
{0x3308, 0x00},
{0x3309, 0xc8},
{0x330a, 0x01},
{0x330b, 0x90},
{0x330c, 0x02},
{0x330d, 0x58},
{0x330e, 0x03},
{0x330f, 0x20},
{0x3300, 0x00},
{0x3500, 0x00},
{0x3501, 0x3d},
{0x3502, 0x00},
{0x3503, 0x07},
{0x350a, 0x00},
{0x350b, 0x40},
{0x3601, 0x33},
{0x3602, 0x00},
{0x3611, 0x0e},
{0x3612, 0x2b},
{0x3614, 0x50},
{0x3620, 0x33},
{0x3622, 0x00},
{0x3630, 0xad},
{0x3631, 0x00},
{0x3632, 0x94},
{0x3633, 0x17},
{0x3634, 0x14},
{0x3704, 0xc0},
{0x3705, 0x2a},
{0x3708, 0x66},
{0x3709, 0x52},
{0x370b, 0x23},
{0x370c, 0xc3},
{0x370d, 0x00},
{0x370e, 0x00},
{0x371c, 0x07},
{0x3739, 0xd2},
{0x373c, 0x00},
{0x3800, 0x00},
{0x3801, 0x00},
{0x3802, 0x00},
{0x3803, 0x00},
{0x3804, 0x0a},
{0x3805, 0x3f},
{0x3806, 0x07},
{0x3807, 0xa3},
{0x3808, 0x05},
{0x3809, 0x10},
{0x380a, 0x03},
{0x380b, 0xcc},
{0x380c, 0x0b},
{0x380d, 0x00},
{0x380e, 0x03},
{0x380f, 0xe0},
{0x3810, 0x00},
{0x3811, 0x08},
{0x3812, 0x00},
{0x3813, 0x04},
{0x3814, 0x31},
{0x3815, 0x31},
{0x3817, 0x00},
{0x3820, 0x08},
{0x3821, 0x07},
{0x3826, 0x03},
{0x3829, 0x00},
{0x382b, 0x0b},
{0x3830, 0x00},
{0x3836, 0x00},
{0x3837, 0x00},
{0x3838, 0x00},
{0x3839, 0x04},
{0x383a, 0x00},
{0x383b, 0x01},
{0x3b00, 0x00},
{0x3b02, 0x08},
{0x3b03, 0x00},
{0x3b04, 0x04},
{0x3b05, 0x00},
{0x3b06, 0x04},
{0x3b07, 0x08},
{0x3b08, 0x00},
{0x3b09, 0x02},
{0x3b0a, 0x04},
{0x3b0b, 0x00},
{0x3b0c, 0x3d},
{0x3f01, 0x0d},
{0x3f0f, 0xf5},
{0x4000, 0x89},
{0x4001, 0x02},
{0x4002, 0x45},
{0x4004, 0x02},
{0x4005, 0x18},
{0x4006, 0x08},
{0x4007, 0x10},
{0x4008, 0x00},
{0x4300, 0xf8},
{0x4303, 0xff},
{0x4304, 0x00},
{0x4307, 0xff},
{0x4520, 0x00},
{0x4521, 0x00},
{0x4511, 0x22},
{0x4800, 0x14},
{0x481f, 0x3c},
{0x4826, 0x00},
{0x4837, 0x18},
{0x4b00, 0x06},
{0x4b01, 0x0a},
{0x5000, 0xff},
{0x5001, 0x00},
{0x5002, 0x41},
{0x5003, 0x0a},
{0x5004, 0x00},
{0x5043, 0x00},
{0x5013, 0x00},
{0x501f, 0x03},
{0x503d, 0x00},
{0x5180, 0x08},
{0x5a00, 0x08},
{0x5b00, 0x01},
{0x5b01, 0x40},
{0x5b02, 0x00},
{0x5b03, 0xf0},
{0x301a, 0xf0},
{0x0100, 0x01},
{0x4837, 0x17},
};
static struct regval_list sensor_qsxga_regs[] = {
/*2592x1944 15fps 2 lane MIPI 420Mbps/lane */
{0x0100, 0x00},
{0x3501, 0x7b},
{0x2502, 0x00},
{0x3708, 0x63},
{0x3709, 0x12},
{0x370c, 0xc0},
{0x3800, 0x00},
{0x3801, 0x00},
{0x3802, 0x00},
{0x3803, 0x00},
{0x3804, 0x0a},
{0x3805, 0x3f},
{0x3806, 0x07},
{0x3807, 0xa3},
{0x3808, 0x0a},
{0x3809, 0x20},
{0x380a, 0x07},
{0x380b, 0x98},
{0x380c, 0x0b},
{0x380d, 0x00},
{0x380e, 0x07},
{0x380f, 0xc0},
{0x3810, 0x00},
{0x3811, 0x10},
{0x3812, 0x00},
{0x3813, 0x06},
{0x3814, 0x11},
{0x3815, 0x11},
{0x3817, 0x00},
{0x3820, 0x40},
{0x3821, 0x06},
{0x4004, 0x04},
{0x4005, 0x1a},
{0x350b, 0x40},
{0x4837, 0x17},
{0x0100, 0x01},
};
static struct regval_list sensor_720p_regs[] = {
/* 1280x720 30fps 2 lane MIPI 420Mbps/lane */
{0x0100, 0x00},
{0x3501, 0x2d},
{0x3502, 0xc0},
{0x3708, 0x66},
{0x3709, 0x52},
{0x370c, 0xcf},
{0x3800, 0x00},
{0x3801, 0x10},
{0x3802, 0x00},
{0x3803, 0xfe},
{0x3804, 0x0a},
{0x3805, 0x2f},
{0x3806, 0x06},
{0x3807, 0xa5},
{0x3808, 0x05},
{0x3809, 0x00},
{0x380a, 0x02},
{0x380b, 0xd0},
{0x380c, 0x0e},
{0x380d, 0xc4},
{0x380e, 0x02},
{0x380f, 0xe6},
{0x3810, 0x00},
{0x3811, 0x08},
{0x3812, 0x00},
{0x3813, 0x02},
{0x3814, 0x31},
{0x3815, 0x31},
{0x3817, 0x00},
{0x3820, 0x08},
{0x3821, 0x07},
{0x4004, 0x02},
{0x4005, 0x18},
{0x3b0b, 0x80},
{0x4837, 0x17},
{0x0100, 0x01},
};
static struct regval_list sensor_fmt_raw[] = {
};
/*
* Code for dealing with controls.
* fill with different sensor module
* different sensor module has different settings here
* if not support the follow function ,retrun -EINVAL
*/
static int sensor_g_exp(struct v4l2_subdev *sd, __s32 *value)
{
struct sensor_info *info = to_state(sd);
*value = info->exp;
sensor_dbg("sensor_get_exposure = %d\n", info->exp);
return 0;
}
static int sensor_s_exp(struct v4l2_subdev *sd, unsigned int exp_val)
{
unsigned char explow, expmid, exphigh;
struct sensor_info *info = to_state(sd);
if (exp_val > 0xfffff)
exp_val = 0xfffff;
if (exp_val < 7)
exp_val = 7;
exphigh = (unsigned char)((0x0f0000 & exp_val) >> 16);
expmid = (unsigned char)((0x00ff00 & exp_val) >> 8);
explow = (unsigned char)(0x0000ff & exp_val);
sensor_write(sd, 0x3502, explow);
sensor_write(sd, 0x3501, expmid);
sensor_write(sd, 0x3500, exphigh);
info->exp = exp_val;
return 0;
}
static int sensor_g_gain(struct v4l2_subdev *sd, __s32 *value)
{
struct sensor_info *info = to_state(sd);
*value = info->gain;
sensor_dbg("sensor_get_gain = %d\n", info->gain);
return 0;
}
static int sensor_s_gain(struct v4l2_subdev *sd, unsigned int gain_val)
{
struct sensor_info *info = to_state(sd);
unsigned char gainlow = 0;
unsigned char gainhigh = 0;
if (gain_val < 1 * 16)
gain_val = 16;
if (gain_val > 64 * 16 - 1)
gain_val = 64 * 16 - 1;
gainlow = (unsigned char)(gain_val & 0xff);
gainhigh = (unsigned char)((gain_val >> 8) & 0x3);
sensor_write(sd, 0x350b, gainlow);
sensor_write(sd, 0x350a, gainhigh);
info->gain = gain_val;
return 0;
}
static int ov5647_sensor_vts;
static int sensor_s_exp_gain(struct v4l2_subdev *sd,
struct sensor_exp_gain *exp_gain)
{
int exp_val, gain_val, shutter, frame_length;
unsigned char explow = 0, expmid = 0, exphigh = 0;
unsigned char gainlow = 0, gainhigh = 0;
struct sensor_info *info = to_state(sd);
exp_val = exp_gain->exp_val;
gain_val = exp_gain->gain_val;
if (gain_val < 1*16)
gain_val = 16;
if (gain_val > 64*16-1)
gain_val = 64*16-1;
if (exp_val > 0xfffff)
exp_val = 0xfffff;
gainlow = (unsigned char)(gain_val & 0xff);
gainhigh = (unsigned char)((gain_val >> 8)&0x3);
exphigh = (unsigned char)((0x0f0000&exp_val) >> 16);
expmid = (unsigned char)((0x00ff00&exp_val) >> 8);
explow = (unsigned char)((0x0000ff&exp_val));
shutter = exp_val/16;
if (shutter > ov5647_sensor_vts - 4)
frame_length = shutter + 4;
else
frame_length = ov5647_sensor_vts;
sensor_write(sd, 0x3208, 0x00);//enter group write
sensor_write(sd, 0x3503, 0x07);
sensor_write(sd, 0x380f, (frame_length & 0xff));
sensor_write(sd, 0x380e, (frame_length >> 8));
sensor_write(sd, 0x350b, gainlow);
sensor_write(sd, 0x350a, gainhigh);
sensor_write(sd, 0x3502, explow);
sensor_write(sd, 0x3501, expmid);
sensor_write(sd, 0x3500, exphigh);
sensor_write(sd, 0x3208, 0x10);//end group write
sensor_write(sd, 0x3208, 0xa0);//init group write
info->exp = exp_val;
info->gain = gain_val;
return 0;
}
static void sensor_s_sw_stby(struct v4l2_subdev *sd, int on_off)
{
int ret = 0;
return ret;
}
/*
* Stuff that knows about the sensor.
*/
static int sensor_power(struct v4l2_subdev *sd, int on)
{
int ret = 0;
printk(KERN_WARNING "entering sensor_power\n");
sensor_dbg("zzz5648 sensor_power\n");
switch (on) {
case STBY_ON:
printk(KERN_WARNING "entering sensor_power STBY_ON\n");
sensor_print("STBY_ON!\n");
cci_lock(sd);
sensor_s_sw_stby(sd, STBY_ON);
usleep_range(1000, 1200);
cci_unlock(sd);
break;
case STBY_OFF:
printk(KERN_WARNING "entering sensor_power STBY_OFF\n");
sensor_print("STBY_OFF!\n");
cci_lock(sd);
usleep_range(1000, 1200);
sensor_s_sw_stby(sd, STBY_OFF);
cci_unlock(sd);
break;
case PWR_ON:
printk(KERN_WARNING "entering sensor_power PWR_ON, pins: %d %d\n",PWDN ,POWER_EN);
gpio_direction_output(GPIOA(8), 0); //led enable
gpio_direction_output(GPIOA(9), 0); //power enable
sensor_print("PWR_ON!100\n");
cci_lock(sd);
vin_gpio_set_status(sd, PWDN, 1);
//vin_gpio_write(sd, RESET, CSI_GPIO_HIGH); //not needed for the rpi ov5647 modules
vin_gpio_set_status(sd, POWER_EN, 1);
vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH); //special case, since PWDN is the led we power it ON
//vin_gpio_write(sd, RESET, CSI_GPIO_LOW); //ignore reset
vin_gpio_write(sd, POWER_EN, CSI_GPIO_HIGH);
usleep_range(7000, 8000);
vin_set_pmu_channel(sd, IOVDD, ON);
usleep_range(7000, 8000);
vin_set_pmu_channel(sd, AVDD, ON);
vin_set_pmu_channel(sd, AFVDD, ON);
usleep_range(7000, 8000);
vin_set_pmu_channel(sd, DVDD, ON);
usleep_range(7000, 8000);
vin_set_mclk_freq(sd, MCLK);
vin_set_mclk(sd, ON);
usleep_range(10000, 12000);
//vin_gpio_write(sd, RESET, CSI_GPIO_HIGH); //these calls are useless as well
//vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH);
vin_set_pmu_channel(sd, CAMERAVDD, ON);/*AFVCC ON*/
usleep_range(10000, 12000);
cci_unlock(sd);
break;
case PWR_OFF:
sensor_print("PWR_OFF!\n");
cci_lock(sd);
vin_gpio_write(sd, PWDN, CSI_GPIO_LOW); //LED off
//vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
vin_set_mclk(sd, OFF);
usleep_range(7000, 8000);
vin_set_pmu_channel(sd, DVDD, OFF);
//vin_gpio_write(sd, PWDN, CSI_GPIO_LOW);
//vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
vin_gpio_write(sd, POWER_EN, CSI_GPIO_LOW); //turn off power to the camera
vin_set_pmu_channel(sd, AVDD, OFF);
vin_set_pmu_channel(sd, IOVDD, OFF);
vin_set_pmu_channel(sd, AFVDD, OFF);
vin_set_pmu_channel(sd, CAMERAVDD, OFF);/*AFVCC ON*/
cci_unlock(sd);
break;
default:
return -EINVAL;
}
return 0;
}
static int sensor_reset(struct v4l2_subdev *sd, u32 val)
{
printk(KERN_WARNING "entering sensor_reset\n"); //this camera modules doesn't need to reset
/*
switch (val) {
case 0:
vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
usleep_range(100, 120);
break;
case 1:
vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
usleep_range(100, 120);
break;
default:
return -EINVAL;
}
*/
return 0;
}
static int sensor_detect(struct v4l2_subdev *sd)
{
printk(KERN_WARNING "entering sensor_detect\n");
data_type rdval;
unsigned int SENSOR_ID = 0;
sensor_read(sd, 0x300A, &rdval);
SENSOR_ID |= rdval;
SENSOR_ID |= (rdval << 8);
sensor_read(sd, 0x300B, &rdval);
SENSOR_ID |= (rdval);
sensor_print("V4L2_IDENT_SENSOR = 0x%x\n", SENSOR_ID);
if (SENSOR_ID != 0x5648) {
sensor_print("ov5647 %s error, chip found is not an target chip", __func__);
printk(KERN_WARNING "exiting sensor_detect, not found\n");
//return -ENODEV;
}
printk(KERN_WARNING "exiting sensor_detect, found\n");
return 0;
}
static int sensor_init(struct v4l2_subdev *sd, u32 val)
{
printk(KERN_WARNING "entering sensor_init\n");
int ret;
struct sensor_info *info = to_state(sd);
sensor_print("sensor_init\n");
/*Make sure it is a target sensor */
ret = sensor_detect(sd);
if (ret) {
printk(KERN_WARNING "exiting sensor_init, not found\n");
sensor_err("chip found is not an target chip.\n");
return ret;
}
info->focus_status = 0;
info->low_speed = 0;
info->width = 1280;
info->height = 720;
info->hflip = 0;
info->vflip = 0;
info->gain = 0;
info->tpf.numerator = 1;
info->tpf.denominator = 30; /* 30fps */
info->preview_first_flag = 1;
return 0;
}
static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
int ret = 0;
struct sensor_info *info = to_state(sd);
switch (cmd) {
case GET_CURRENT_WIN_CFG:
if (info->current_wins != NULL) {
memcpy(arg, info->current_wins,
sizeof(struct sensor_win_size));
ret = 0;
} else {
sensor_err("empty wins!\n");
ret = -1;
}
break;
case SET_FPS:
ret = 0;
break;
case VIDIOC_VIN_SENSOR_EXP_GAIN:
ret = sensor_s_exp_gain(sd, (struct sensor_exp_gain *)arg);
break;
case VIDIOC_VIN_SENSOR_CFG_REQ:
sensor_cfg_req(sd, (struct sensor_config *)arg);
break;
case VIDIOC_VIN_ACT_INIT:
ret = actuator_init(sd, (struct actuator_para *)arg);
break;
case VIDIOC_VIN_ACT_SET_CODE:
ret = actuator_set_code(sd, (struct actuator_ctrl *)arg);
break;
default:
return -EINVAL;
}
return ret;
}
/*
* Store information about the video data format.
*/
static struct sensor_format_struct sensor_formats[] = {
{
.desc = "Raw RGB Bayer",
.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
.regs = sensor_fmt_raw,
.regs_size = ARRAY_SIZE(sensor_fmt_raw),
.bpp = 1
},
};
#define N_FMTS ARRAY_SIZE(sensor_formats)
/*
* Then there is the issue of window sizes. Try to capture the info here.
*/
static struct sensor_win_size sensor_win_sizes[] = {
#if 0
/* 720p */
{
.width = HD720_WIDTH,
.height = HD720_HEIGHT,
.hoffset = 0,
.voffset = 0,
.hts = 3780,
.vts = 742,
.pclk = 84*1000*1000,
.mipi_bps = 420*1000*1000,
.fps_fixed = 30,
.bin_factor = 1,
.intg_min = 16,
.intg_max = (742-4)<<4,
.gain_min = 1<<4,
.gain_max = 64<<4,
.regs = sensor_720p_regs,//
.regs_size = ARRAY_SIZE(sensor_720p_regs),//
.set_size = NULL,
},
#endif
/* qsxga */
{
.width = QSXGA_WIDTH,
.height = QSXGA_HEIGHT,
.hoffset = 0,
.voffset = 0,
.hts = 2816,
.vts = 1984,
.pclk = 84*1000*1000,
.mipi_bps = 420*1000*1000,
.fps_fixed = 15,
.bin_factor = 1,
.intg_min = 16,
.intg_max = (1984-4)<<4,
.gain_min = 1<<4,
.gain_max = 64<<4,
.regs = sensor_qsxga_regs,
.regs_size = ARRAY_SIZE(sensor_qsxga_regs),
.set_size = NULL,
},
};
#define N_WIN_SIZES (ARRAY_SIZE(sensor_win_sizes))
static int sensor_reg_init(struct sensor_info *info)
{
int ret;
struct v4l2_subdev *sd = &info->sd;
struct sensor_format_struct *sensor_fmt = info->fmt;
struct sensor_win_size *wsize = info->current_wins;
ret = sensor_write_array(sd, sensor_default_regs,
ARRAY_SIZE(sensor_default_regs));
if (ret < 0) {
sensor_err("write sensor_default_regs error\n");
return ret;
}
sensor_print("sensor_reg_init\n");
sensor_write_array(sd, sensor_fmt->regs, sensor_fmt->regs_size);
if (wsize->regs)
sensor_write_array(sd, wsize->regs, wsize->regs_size);
if (wsize->set_size)
wsize->set_size(sd);
info->width = wsize->width;
info->height = wsize->height;
info->exp = 0;
info->gain = 0;
ov5647_sensor_vts = wsize->vts;
sensor_print("s_fmt set width = %d, height = %d\n", wsize->width,
wsize->height);
return 0;
}
static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
{
struct sensor_info *info = to_state(sd);
sensor_print("%s on = %d, %d*%d fps: %d code: %x\n", __func__, enable,
info->current_wins->width, info->current_wins->height,
info->current_wins->fps_fixed, info->fmt->mbus_code);
if (!enable)
return 0;
return sensor_reg_init(info);
}
static int sensor_g_mbus_config(struct v4l2_subdev *sd,
struct v4l2_mbus_config *cfg)
{
cfg->type = V4L2_MBUS_CSI2;
cfg->flags = 0 | V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0;
return 0;
}
static int sensor_g_ctrl(struct v4l2_ctrl *ctrl)
{
struct sensor_info *info = container_of(ctrl->handler,
struct sensor_info, handler);
struct v4l2_subdev *sd = &info->sd;
switch (ctrl->id) {
case V4L2_CID_GAIN:
return sensor_g_gain(sd, &ctrl->val);
case V4L2_CID_EXPOSURE:
return sensor_g_exp(sd, &ctrl->val);
}
return -EINVAL;
}
static int sensor_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct sensor_info *info = container_of(ctrl->handler,
struct sensor_info, handler);
struct v4l2_subdev *sd = &info->sd;
switch (ctrl->id) {
case V4L2_CID_GAIN:
return sensor_s_gain(sd, ctrl->val);
case V4L2_CID_EXPOSURE:
return sensor_s_exp(sd, ctrl->val);
}
return -EINVAL;
}
/* ----------------------------------------------------------------------- */
static const struct v4l2_ctrl_ops sensor_ctrl_ops = {
.g_volatile_ctrl = sensor_g_ctrl,
.s_ctrl = sensor_s_ctrl,
};
static const struct v4l2_subdev_core_ops sensor_core_ops = {
.reset = sensor_reset,
.init = sensor_init,
.s_power = sensor_power,
.ioctl = sensor_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl32 = sensor_compat_ioctl32,
#endif
};
static const struct v4l2_subdev_video_ops sensor_video_ops = {
.s_parm = sensor_s_parm,
.g_parm = sensor_g_parm,
.s_stream = sensor_s_stream,
.g_mbus_config = sensor_g_mbus_config,
};
static const struct v4l2_subdev_pad_ops sensor_pad_ops = {
.enum_mbus_code = sensor_enum_mbus_code,
.enum_frame_size = sensor_enum_frame_size,
.get_fmt = sensor_get_fmt,
.set_fmt = sensor_set_fmt,
};
static const struct v4l2_subdev_ops sensor_ops = {
.core = &sensor_core_ops,
.video = &sensor_video_ops,
.pad = &sensor_pad_ops,
};
/* ----------------------------------------------------------------------- */
static struct cci_driver cci_drv = {
.name = SENSOR_NAME,
.addr_width = CCI_BITS_16,
.data_width = CCI_BITS_8,
};
static const struct v4l2_ctrl_config sensor_custom_ctrls[] = {
{
.ops = &sensor_ctrl_ops,
.id = V4L2_CID_FRAME_RATE,
.name = "frame rate",
.type = V4L2_CTRL_TYPE_INTEGER,
.min = 15,
.max = 120,
.step = 1,
.def = 120,
},
};
static int sensor_init_controls(struct v4l2_subdev *sd,
const struct v4l2_ctrl_ops *ops)
{
struct sensor_info *info = to_state(sd);
struct v4l2_ctrl_handler *handler = &info->handler;
struct v4l2_ctrl *ctrl;
int i;
int ret = 0;
v4l2_ctrl_handler_init(handler, 2 + ARRAY_SIZE(sensor_custom_ctrls));
v4l2_ctrl_new_std(handler, ops, V4L2_CID_GAIN, 1 * 1600,
256 * 1600, 1, 1 * 1600);
ctrl = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 0,
65536 * 16, 1, 0);
if (ctrl != NULL)
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
for (i = 0; i < ARRAY_SIZE(sensor_custom_ctrls); i++)
v4l2_ctrl_new_custom(handler, &sensor_custom_ctrls[i], NULL);
if (handler->error) {
ret = handler->error;
v4l2_ctrl_handler_free(handler);
}
sd->ctrl_handler = handler;
return ret;
}
static int sensor_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct v4l2_subdev *sd;
struct sensor_info *info;
printk(KERN_WARNING "entering sensor_probe\n");
info = kzalloc(sizeof(struct sensor_info), GFP_KERNEL);
if (info == NULL)
return -ENOMEM;
sd = &info->sd;
cci_dev_probe_helper(sd, client, &sensor_ops, &cci_drv);
sensor_init_controls(sd, &sensor_ctrl_ops);
mutex_init(&info->lock);
#ifdef CONFIG_SAME_I2C
info->sensor_i2c_addr = I2C_ADDR >> 1;
#endif
info->fmt = &sensor_formats[0];
info->fmt_pt = &sensor_formats[0];
info->win_pt = &sensor_win_sizes[0];
info->fmt_num = N_FMTS;
info->win_size_num = N_WIN_SIZES;
info->sensor_field = V4L2_FIELD_NONE;
info->stream_seq = MIPI_BEFORE_SENSOR;
info->af_first_flag = 1;
info->exp = 0;
info->gain = 0;
return 0;
}
static int sensor_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd;
printk(KERN_WARNING "entering sensor_remove\n");
sd = cci_dev_remove_helper(client, &cci_drv);
kfree(to_state(sd));
return 0;
}
static const struct i2c_device_id sensor_id[] = {
{SENSOR_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(i2c, sensor_id);
static struct i2c_driver sensor_driver = {
.driver = {
.owner = THIS_MODULE,
.name = SENSOR_NAME,
},
.probe = sensor_probe,
.remove = sensor_remove,
.id_table = sensor_id,
};
static __init int init_sensor(void)
{
return cci_dev_init_helper(&sensor_driver);
}
static __exit void exit_sensor(void)
{
cci_dev_exit_helper(&sensor_driver);
}
module_init(init_sensor);
module_exit(exit_sensor);
我让它工作了,似乎驱动程序需要在启动时正确加载,否则 DTS 将传感器设置为“禁用”。
另一方面,我基于 ov5647 的 ov5648 官方 allwinner 驱动程序的寄存器似乎完全错误! 它是一个 mipi 驱动程序,它修改相机中与并行 csi 相关的寄存器,完全是废话......我正在从头开始重写它。
//these register maps are completely wrong, even for the ov5648 for which this driver was originally written
static struct regval_list sensor_qsxga_regs[] = {
/*2592x1944 15fps 2 lane MIPI 420Mbps/lane */
{0x0100, 0x00}, //start software sleep
{0x3501, 0x7b}, //exposure
{0x2502, 0x00}, //unknown?
{0x3708, 0x63}, //unknown?
{0x3709, 0x12}, //unknown?
{0x370c, 0xc0}, //unknown?
{0x3800, 0x00}, //TIMING_X_ADDR_START
{0x3801, 0x00}, //TIMING_X_ADDR_START
{0x3802, 0x00}, //TIMING_Y_ADDR_START
{0x3803, 0x00}, //TIMING_Y_ADDR_START
{0x3804, 0x0a}, //TIMING_X_ADDR_END
{0x3805, 0x3f}, //TIMING_X_ADDR_END
{0x3806, 0x07}, //TIMING_Y_ADDR_END
{0x3807, 0xa3}, //TIMING_Y_ADDR_END
{0x3808, 0x0a}, //TIMING_X_OUTPUT_SIZE
{0x3809, 0x20}, //TIMING_X_OUTPUT_SIZE
{0x380a, 0x07}, //TIMING_Y_OUTPUT_SIZE
{0x380b, 0x98}, //TIMING_Y_OUTPUT_SIZE
{0x380c, 0x0b}, //TIMING_HTS
{0x380d, 0x00}, //TIMING_HTS
{0x380e, 0x07}, //TIMING_VTS
{0x380f, 0xc0}, //TIMING_VTS
{0x3810, 0x00}, //TIMING_ISP_X_WIN
{0x3811, 0x10}, //TIMING_ISP_X_WIN
{0x3812, 0x00}, //TIMING_ISP_Y_WIN
{0x3813, 0x06}, //TIMING_ISP_Y_WIN
{0x3814, 0x11}, //TIMING_X_INC
{0x3815, 0x11}, //TIMING_Y_INC
//TIMING_HSYNCST is missing??
{0x3817, 0x00}, //TIMING_HSYNCST
{0x3820, 0x40}, //TIMING_TC_REG20
{0x3821, 0x06}, //TIMING_TC_REG21
{0x4004, 0x04}, //BLC CTRL04
{0x4005, 0x1a}, //BLC CTRL05
{0x350b, 0x40}, //AGC (gain)
{0x4837, 0x17}, //PCLK_PERIOD
{0x0100, 0x01}, //end software sleep
};
@bardi4567 repo init -u https://sdk.aw-ol.com/git_repo/V853Tina_Open/manifest.git -b master -m tina-v853-open.xml
然后
repo sync
非常适合我,要么您的存储库配置不正确,要么您有一些文件权限问题,无论哪种方式,您都应该为您的问题创建一个单独的主题,因为它与本主题(tinyvision 开发板)无关!
大家好,
当我在 kernel_menuconfig 中将 OV5640 和 OV5658 驱动程序设置为编译为模块 (M) 时(并且禁用 gc_2053):
我编辑 DTS 以反映更改:
并编译/运行,似乎没有考虑到更改。 menuconfig 中的其他更改确实适用于图像,但 kernel_menuconfig 中完成的某些更改则不然。 看这里,gc_2053 驱动程序仍然处于活动状态,而 OV 驱动程序却不见踪影:
知道为什么会出现这种情况吗?
我让它工作了!
我必须编辑 DTS 将驱动强度增加到 1,并将 1.8V 总线电压从 1.7V 提高到 2V 才能注册,现在我的相机出现了!
默认的 0 驱动强度永远不会起作用。 编辑 DTS 是关键。
@awwwwa 这确实消除了警告,所以感谢这一点,但是 i2cdetect 的结果仍然完全错过了总线上的任何 I2C 设备...所以根本问题仍然存在...
这是执行camerademo后调试FS的输出,您可以在这里清楚地看到驱动程序处于MIPI模式但尚未接收到任何数据。:
root@TinaLinux:/# cat /sys/kernel/debug/mpp/vi
*****************************************************
VIN hardware feature list:
mcsi 2, ncsi 1, parser 3, isp 1, vipp 4, dma 4
CSI_VERSION: CSI300_200, ISP_VERSION: ISP600_100
CSI_CLK: 200000000, ISP_CLK: 24000000
*****************************************************
vi0:
ov5647_mipi => mipi0 => csi0 => tdm_rx0 => isp0 => vipp0
input => hoff: 0, voff: 0, w: 1296, h: 972, fmt: GBRG10
output => width: 1296, height: 972, fmt: NV21
interface: MIPI, isp_mode: NORMAL, hflip: 0, vflip: 0
prs_in => x: 0, y: 0, hb: 0, hs: 0
bkbuf => cnt: 3 size: 1900544 rest: 3, work_mode: online
tdmbuf => cnt: 0 size: 0, cmp_ratio: 0
ispbuf => cnt: 4 size: 1991680/15552/15552/15552, cmp_ratio: 1024
frame => cnt: 0, lost_cnt: 0, error_cnt: 0
internal => avg: 0(ms), max: 0(ms), min: 0(ms)
*****************************************************
vi4:
(null) => mipi0 => csi0 => tdm_rx0 => isp0 => vipp4
input => hoff: 0, voff: 0, w: 0, h: 0, fmt: NULL
output => width: 0, height: 0, fmt: NULL
interface: PARALLEL, isp_mode: NORMAL, hflip: 0, vflip: 0
prs_in => x: 0, y: 0, hb: 0, hs: 0
bkbuf => cnt: 0 size: 0 rest: 0, work_mode: online
tdmbuf => cnt: 0 size: 0, cmp_ratio: 0
ispbuf => cnt: 4 size: 1991680/15552/15552/15552, cmp_ratio: 1024
frame => cnt: 0, lost_cnt: 0, error_cnt: 0
internal => avg: 0(ms), max: 0(ms), min: 0(ms)
*****************************************************
vi8:
(null) => mipi0 => csi0 => tdm_rx0 => isp0 => vipp8
input => hoff: 0, voff: 0, w: 0, h: 0, fmt: NULL
output => width: 0, height: 0, fmt: NULL
interface: PARALLEL, isp_mode: NORMAL, hflip: 0, vflip: 0
prs_in => x: 0, y: 0, hb: 0, hs: 0
bkbuf => cnt: 0 size: 0 rest: 0, work_mode: online
tdmbuf => cnt: 0 size: 0, cmp_ratio: 0
ispbuf => cnt: 4 size: 1991680/15552/15552/15552, cmp_ratio: 1024
frame => cnt: 0, lost_cnt: 0, error_cnt: 0
internal => avg: 0(ms), max: 0(ms), min: 0(ms)
*****************************************************
vi12:
(null) => mipi0 => csi0 => tdm_rx0 => isp0 => vipp12
input => hoff: 0, voff: 0, w: 0, h: 0, fmt: NULL
output => width: 0, height: 0, fmt: NULL
interface: PARALLEL, isp_mode: NORMAL, hflip: 0, vflip: 0
prs_in => x: 0, y: 0, hb: 0, hs: 0
bkbuf => cnt: 0 size: 0 rest: 0, work_mode: online
tdmbuf => cnt: 0 size: 0, cmp_ratio: 0
ispbuf => cnt: 4 size: 1991680/15552/15552/15552, cmp_ratio: 1024
frame => cnt: 0, lost_cnt: 0, error_cnt: 0
internal => avg: 0(ms), max: 0(ms), min: 0(ms)
*****************************************************
并行节点未使用,仅 VI0 重要
@awwwwa 我还尝试修改 IMX219 官方驱动程序以使用 2 通道模式,IMX219 确实支持该模式(因为它用于树莓派相机 V2,它使用两个通道)。
/*
* A V4L2 driver for IMX219 Raw cameras.
*
* Copyright (c) 2017 by Allwinnertech Co., Ltd. http://www.allwinnertech.com
*
* Authors: Zhao Wei <zhaowei@allwinnertech.com>
* Yang Feng <yangfeng@allwinnertech.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
//camerademo BGGR8 1280 720 30 bmp /tmp 5
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <linux/clk.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mediabus.h>
#include <linux/io.h>
#include "camera.h"
#include "sensor_helper.h"
MODULE_AUTHOR("Chomoly");
MODULE_DESCRIPTION("A low-level driver for IMX219 sensors");
MODULE_LICENSE("GPL");
#define MCLK (24*1000*1000)
#define V4L2_IDENT_SENSOR 0x0219//0x0219
#define DEBUG_FS 1
/*
* Our nominal (default) frame rate.
*/
#ifdef FPGA
#define SENSOR_FRAME_RATE 15
#else
#define SENSOR_FRAME_RATE 30
#endif
/*
* The IMX219 sits on i2c with ID 0x6c
*/
#define I2C_ADDR 0x20
#define SENSOR_NAME "imx219"
int imx219_sensor_vts;
#define ES_GAIN(a, b, c) ((unsigned short)(a * 160) < (c * 10) && (c*10) <= (unsigned short)(b * 160))
struct cfg_array { /* coming later */
struct regval_list *regs;
int size;
};
/*
* The default register settings
*
*/
static struct regval_list sensor_default_regs[] = { /*3280 x 2464_20fps 4lanes 720Mbps/lane */
{0x30EB, 0x05}, //manufacturer specific reg access sequence
{0x30EB, 0x0C}, //manufacturer specific reg access sequence
{0x300A, 0xFF}, //manufacturer specific reg access sequence
{0x300B, 0xFF}, //manufacturer specific reg access sequence
{0x30EB, 0x05}, //manufacturer specific reg access sequence
{0x30EB, 0x09}, //manufacturer specific reg access sequence
{0x0114, 0x01}, //two lane mode //03 quad
{0x0128, 0x00}, //auto mipi timing
{0x012A, 0x18}, //INCK frequency [MHz] default 0C
{0x012B, 0x00}, //INCK frequency [MHz]
{0x0160, 0x02}, //frame length lines (2*1lines)
{0x0161, 0x00}, //frame length lines (0*3lines)
{0x0162, 0x0D}, //line_length_plck in pixels (13)
{0x0163, 0xE8}, //line_length_plck in pixels (232) 3560
{0x0164, 0x03}, //X-address of the top left corner of the visible pixel data Units: Pixels
{0x0165, 0xE8}, //X-address of the top left corner of the visible pixel data Units: Pixels // 0x03E8 = 1000
{0x0166, 0x08}, //X-address of the bottom right corner of the visible pixel data Units: Pixels
{0x0167, 0xE7}, //X-address of the bottom right corner of the visible pixel data Units: Pixels //0x08E7 = 2279 -1000 = 1279
{0x0168, 0x03}, //Y-address of the top left corner of the visible pixel data Units: Lines
{0x0169, 0x68}, //Y-address of the top left corner of the visible pixel data Units: Lines //0x0368 = 872
{0x016A, 0x06}, //Y-address of the bottom right corner of the visible pixel data Units: Pixels
{0x016B, 0x37}, //Y-address of the bottom right corner of the visible pixel data Units: Pixels : 0x0637 = 1591 - 872 = 719 // 1280*720
{0x016C, 0x05}, //output size x
{0x016D, 0x00}, //output size x pixels
{0x016E, 0x02}, //output size y
{0x016F, 0xD0}, //output size y lines
{0x0170, 0x01}, //x_odd_inc Increment for odd pixels 1, 3; turns 1279 into 1280
{0x0171, 0x01}, //y_odd_inc Increment for odd pixels 1, 3; turns 719 into 720
{0x0174, 0x00}, //no binning
{0x0175, 0x00}, //no binning
{0x018C, 0x0A}, //CSI-2 data format (0x0A default)
{0x018D, 0x0A}, //CSI-2 data format (0x0A default)
{0x0301, 0x05}, //Video Timing Pixel Clock Divider Value
{0x0303, 0x01}, //Video Timing System Clock Divider Value
{0x0304, 0x03}, //Pre PLL clock Video Timing System Divider value //camerademo RGGB8 1280 720 30 bmp /tmp 5 |vin is not support this pixelformat
{0x0305, 0x03}, //Pre PLL clock Output System Divider Value
{0x0306, 0x00}, //PLL Video Timing System multiplier Value
{0x0307, 0x57}, //PLL Video Timing System multiplier Value
{0x0309, 0x05 /*0A */ }, //Output Pixel Clock Divider Value (0A default)
{0x030B, 0x01}, //Output System Clock Divider Value
{0x030C, 0x00}, //PLL Output System multiplier Value
{0x030D, 0x5A}, //PLL Output System multiplier Value
//{0x4767, 0x0F},
//{0x4750, 0x14},
//{0x47B4, 0x14}, //unk
{0x0100, 0x01}, //streaming mode on
};
static struct regval_list sensor_hxga_regs[] = {
{0x30EB, 0x05},
{0x30EB, 0x0C},
{0x300A, 0xFF},
{0x300B, 0xFF},
{0x30EB, 0x05},
{0x30EB, 0x09},
{0x0114, 0x01},
{0x0128, 0x00},
{0x012A, 0x18},
{0x012B, 0x00},
{0x0160, 0x0F},
{0x0161, 0xC5},
{0x0162, 0x0D},
{0x0163, 0x78},
{0x0164, 0x00},
{0x0165, 0x00},
{0x0166, 0x0C},
{0x0167, 0xCF},
{0x0168, 0x00},
{0x0169, 0x00},
{0x016A, 0x09},
{0x016B, 0x9F},
{0x016C, 0x0C},
{0x016D, 0xD0},
{0x016E, 0x09},
{0x016F, 0xA0},
{0x0170, 0x01},
{0x0171, 0x01},
{0x0174, 0x00},
{0x0175, 0x00},
{0x018C, 0x0A},
{0x018D, 0x0A},
{0x0301, 0x05},
{0x0303, 0x01},
{0x0304, 0x03},
{0x0305, 0x03},
{0x0306, 0x00},
{0x0307, 0x57},
{0x0309, 0x0A},
{0x030B, 0x01},
{0x030C, 0x00},
{0x030D, 0x5A},
{0x4767, 0x0F},
{0x4750, 0x14},
{0x47B4, 0x14},
{0x0100, 0x01},
};
static struct regval_list sensor_sxga_regs[] = {
{0x30EB, 0x05},
{0x30EB, 0x0C},
{0x300A, 0xFF},
{0x300B, 0xFF},
{0x30EB, 0x05},
{0x30EB, 0x09},
{0x0114, 0x01},
{0x0128, 0x00},
{0x012A, 0x18},
{0x012B, 0x00},
{0x0160, 0x0a},
{0x0161, 0x2f},
{0x0162, 0x0d},
{0x0163, 0xe8},
{0x0164, 0x03},
{0x0165, 0xe8},
{0x0166, 0x08},
{0x0167, 0xe7},
{0x0168, 0x02},
{0x0169, 0xf0},
{0x016A, 0x06},
{0x016B, 0xaF},
{0x016C, 0x05},
{0x016D, 0x00},
{0x016E, 0x03},
{0x016F, 0xc0},
{0x0170, 0x01},
{0x0171, 0x01},
{0x0174, 0x00},
{0x0175, 0x00},
{0x018C, 0x0A},
{0x018D, 0x0A},
{0x0301, 0x05},
{0x0303, 0x01},
{0x0304, 0x03},
{0x0305, 0x03},
{0x0306, 0x00},
{0x0307, 0x57},
{0x0309, 0x0A},
{0x030B, 0x01},
{0x030C, 0x00},
{0x030D, 0x5A},
{0x4767, 0x0F},
{0x4750, 0x14},
{0x47B4, 0x14},
{0x0100, 0x01},
};
static struct regval_list sensor_1080p_regs[] = {
{0x30EB, 0x05},
{0x30EB, 0x0C},
{0x300A, 0xFF},
{0x300B, 0xFF},
{0x30EB, 0x05},
{0x30EB, 0x09},
{0x0114, 0x01},
{0x0128, 0x00},
{0x012A, 0x18},
{0x012B, 0x00},
{0x0160, 0x0A},
{0x0161, 0x2F},
{0x0162, 0x0D},
{0x0163, 0xE8},
{0x0164, 0x02},
{0x0165, 0xA8},
{0x0166, 0x0A},
{0x0167, 0x27},
{0x0168, 0x02},
{0x0169, 0xB4},
{0x016A, 0x06},
{0x016B, 0xEB},
{0x016C, 0x07},
{0x016D, 0x80},
{0x016E, 0x04},
{0x016F, 0x38},
{0x0170, 0x01},
{0x0171, 0x01},
{0x0174, 0x00},
{0x0175, 0x00},
{0x018C, 0x0A},
{0x018D, 0x0A},
{0x0301, 0x05},
{0x0303, 0x01},
{0x0304, 0x03},
{0x0305, 0x03},
{0x0306, 0x00},
{0x0307, 0x57},
{0x0309, 0x0A},
{0x030B, 0x01},
{0x030C, 0x00},
{0x030D, 0x5A},
{0x4767, 0x0F},
{0x4750, 0x14},
{0x47B4, 0x14},
{0x0100, 0x01},
};
#define sensor_720p_regs sensor_default_regs
//static struct regval_list* sensor_720p_regs = sensor_default_regs;
/*
* Here we'll try to encapsulate the changes for just the output
* video format.
*
*/
static struct regval_list sensor_fmt_raw[] = {
};
static int sensor_s_exp_gain(struct v4l2_subdev *sd,
struct sensor_exp_gain *exp_gain)
{
int exp_val, gain_val, frame_length, shutter;
unsigned char explow = 0, exphigh = 0;
struct sensor_info *info = to_state(sd);
exp_val = exp_gain->exp_val;
gain_val = exp_gain->gain_val;
if (gain_val < 1 * 16)
gain_val = 16;
if (gain_val > 10 * 16 - 1)
gain_val = 10 * 16 - 1;
if (exp_val > 0xfffff)
exp_val = 0xfffff;
exp_val >>= 4;
exphigh = (unsigned char)((0x00ff00 & exp_val) >> 8);
explow = (unsigned char)((0x0000ff & exp_val));
sensor_write(sd, 0x015b, explow);
sensor_write(sd, 0x015a, exphigh);
shutter = exp_val;
if (shutter > imx219_sensor_vts - 4)
frame_length = shutter + 4;
else
frame_length = imx219_sensor_vts;
sensor_write(sd, 0x0161, frame_length & 0xff);
sensor_write(sd, 0x0160, frame_length >> 8);
if (gain_val == 16)
sensor_write(sd, 0x0157, 0x01);
if (ES_GAIN(1.0, 1.1, gain_val))
sensor_write(sd, 0x0157, 24);
else if (ES_GAIN(1.1, 1.2, gain_val))
sensor_write(sd, 0x0157, 42);
else if (ES_GAIN(1.2, 1.3, gain_val))
sensor_write(sd, 0x0157, 60);
else if (ES_GAIN(1.3, 1.4, gain_val))
sensor_write(sd, 0x0157, 73);
else if (ES_GAIN(1.4, 1.5, gain_val))
sensor_write(sd, 0x0157, 85);
else if (ES_GAIN(1.5, 1.6, gain_val))
sensor_write(sd, 0x0157, 96);
else if (ES_GAIN(1.6, 1.7, gain_val))
sensor_write(sd, 0x0157, 105);
else if (ES_GAIN(1.7, 1.8, gain_val))
sensor_write(sd, 0x0157, 114);
else if (ES_GAIN(1.8, 1.9, gain_val))
sensor_write(sd, 0x0157, 122);
else if (ES_GAIN(1.9, 2.0, gain_val))
sensor_write(sd, 0x0157, 0x80);
else if (ES_GAIN(2.0, 2.1, gain_val))
sensor_write(sd, 0x0157, 134);
else if (ES_GAIN(2.1, 2.2, gain_val))
sensor_write(sd, 0x0157, 140);
else if (ES_GAIN(2.2, 2.3, gain_val))
sensor_write(sd, 0x0157, 145);
else if (ES_GAIN(2.3, 2.4, gain_val))
sensor_write(sd, 0x0157, 150);
else if (ES_GAIN(2.4, 2.5, gain_val))
sensor_write(sd, 0x0157, 154);
else if (ES_GAIN(2.5, 2.6, gain_val))
sensor_write(sd, 0x0157, 158);
else if (ES_GAIN(2.6, 2.7, gain_val))
sensor_write(sd, 0x0157, 162);
else if (ES_GAIN(2.7, 2.8, gain_val))
sensor_write(sd, 0x0157, 165);
else if (ES_GAIN(2.8, 2.9, gain_val))
sensor_write(sd, 0x0157, 168);
else if (ES_GAIN(2.9, 3.0, gain_val))
sensor_write(sd, 0x0157, 0xab);
else if (ES_GAIN(3.0, 3.1, gain_val))
sensor_write(sd, 0x0157, 174);
else if (ES_GAIN(3.1, 3.2, gain_val))
sensor_write(sd, 0x0157, 176);
else if (ES_GAIN(3.2, 3.3, gain_val))
sensor_write(sd, 0x0157, 179);
else if (ES_GAIN(3.3, 3.4, gain_val))
sensor_write(sd, 0x0157, 181);
else if (ES_GAIN(3.4, 3.5, gain_val))
sensor_write(sd, 0x0157, 183);
else if (ES_GAIN(3.5, 3.6, gain_val))
sensor_write(sd, 0x0157, 185);
else if (ES_GAIN(3.6, 3.7, gain_val))
sensor_write(sd, 0x0157, 187);
else if (ES_GAIN(3.7, 3.8, gain_val))
sensor_write(sd, 0x0157, 189);
else if (ES_GAIN(3.8, 3.9, gain_val))
sensor_write(sd, 0x0157, 191);
else if (ES_GAIN(3.9, 4.0, gain_val))
sensor_write(sd, 0x0157, 192);
else if (ES_GAIN(4.0, 4.1, gain_val))
sensor_write(sd, 0x0157, 194);
else if (ES_GAIN(4.1, 4.2, gain_val))
sensor_write(sd, 0x0157, 195);
else if (ES_GAIN(4.2, 4.3, gain_val))
sensor_write(sd, 0x0157, 197);
else if (ES_GAIN(4.3, 4.4, gain_val))
sensor_write(sd, 0x0157, 198);
else if (ES_GAIN(4.4, 4.5, gain_val))
sensor_write(sd, 0x0157, 200);
else if (ES_GAIN(4.5, 4.6, gain_val))
sensor_write(sd, 0x0157, 201);
else if (ES_GAIN(4.6, 4.7, gain_val))
sensor_write(sd, 0x0157, 202);
else if (ES_GAIN(4.7, 4.8, gain_val))
sensor_write(sd, 0x0157, 203);
else if (ES_GAIN(4.8, 4.9, gain_val))
sensor_write(sd, 0x0157, 204);
else if (ES_GAIN(4.9, 5.0, gain_val))
sensor_write(sd, 0x0157, 205);
else if (ES_GAIN(5.0, 5.1, gain_val))
sensor_write(sd, 0x0157, 206);
else if (ES_GAIN(5.1, 5.2, gain_val))
sensor_write(sd, 0x0157, 207);
else if (ES_GAIN(5.2, 5.3, gain_val))
sensor_write(sd, 0x0157, 208);
else if (ES_GAIN(5.3, 5.4, gain_val))
sensor_write(sd, 0x0157, 209);
else if (ES_GAIN(5.4, 5.5, gain_val))
sensor_write(sd, 0x0157, 210);
else if (ES_GAIN(5.5, 5.7, gain_val))
sensor_write(sd, 0x0157, 211);
else if (ES_GAIN(5.7, 5.8, gain_val))
sensor_write(sd, 0x0157, 212);
else if (ES_GAIN(5.8, 5.9, gain_val))
sensor_write(sd, 0x0157, 213);
else if (ES_GAIN(5.9, 6.2, gain_val))
sensor_write(sd, 0x0157, 215);
else if (ES_GAIN(6.2, 6.4, gain_val))
sensor_write(sd, 0x0157, 216);
else if (ES_GAIN(6.4, 6.5, gain_val))
sensor_write(sd, 0x0157, 217);
else if (ES_GAIN(6.5, 6.7, gain_val))
sensor_write(sd, 0x0157, 218);
else if (ES_GAIN(6.7, 6.9, gain_val))
sensor_write(sd, 0x0157, 219);
else if (ES_GAIN(6.9, 7.1, gain_val))
sensor_write(sd, 0x0157, 220);
else if (ES_GAIN(7.1, 7.3, gain_val))
sensor_write(sd, 0x0157, 221);
else if (ES_GAIN(7.3, 7.5, gain_val))
sensor_write(sd, 0x0157, 222);
else if (ES_GAIN(7.5, 7.7, gain_val))
sensor_write(sd, 0x0157, 223);
else if (ES_GAIN(7.7, 8.0, gain_val))
sensor_write(sd, 0x0157, 224);
else if (ES_GAIN(8.0, 8.3, gain_val))
sensor_write(sd, 0x0157, 225);
else if (ES_GAIN(8.3, 8.5, gain_val))
sensor_write(sd, 0x0157, 226);
else if (ES_GAIN(8.5, 8.8, gain_val))
sensor_write(sd, 0x0157, 227);
else if (ES_GAIN(8.8, 9.1, gain_val))
sensor_write(sd, 0x0157, 228);
else if (ES_GAIN(9.1, 9.4, gain_val))
sensor_write(sd, 0x0157, 228);
else if (ES_GAIN(9.4, 9.8, gain_val))
sensor_write(sd, 0x0157, 230);
else if (ES_GAIN(9.8, 10.2, gain_val))
sensor_write(sd, 0x0157, 231);
else if (ES_GAIN(10.0, 10.6, gain_val))
sensor_write(sd, 0x0157, 232);
info->exp = exp_val;
info->gain = gain_val;
return 0;
}
static int sensor_g_exp(struct v4l2_subdev *sd, __s32 *value)
{
struct sensor_info *info = to_state(sd);
*value = info->exp;
sensor_dbg("sensor_get_exposure = %d\n", info->exp);
return 0;
}
static int sensor_s_exp(struct v4l2_subdev *sd, unsigned int exp_val)
{
unsigned char explow, exphigh;
struct sensor_info *info = to_state(sd);
if (exp_val > 0xfffff)
exp_val = 0xfffff;
exp_val >>= 4;
exphigh = (unsigned char)((0x00ff00 & exp_val) >> 8);
explow = (unsigned char)((0x0000ff & exp_val));
sensor_write(sd, 0x015b, explow);
sensor_write(sd, 0x015a, exphigh);
info->exp = exp_val;
return 0;
}
static int sensor_g_gain(struct v4l2_subdev *sd, __s32 *value)
{
struct sensor_info *info = to_state(sd);
*value = info->gain;
sensor_dbg("sensor_get_gain = %d\n", info->gain);
return 0;
}
static int sensor_s_gain(struct v4l2_subdev *sd, int gain_val)
{
struct sensor_info *info = to_state(sd);
if (gain_val < 1 * 16)
gain_val = 16;
if (gain_val > 0x1ff)
gain_val = 0x1ff;
if (gain_val == 16)
sensor_write(sd, 0x0157, 0x01);
if (ES_GAIN(1.0, 1.1, gain_val))
sensor_write(sd, 0x0157, 24);
else if (ES_GAIN(1.1, 1.2, gain_val))
sensor_write(sd, 0x0157, 42);
else if (ES_GAIN(1.2, 1.3, gain_val))
sensor_write(sd, 0x0157, 60);
else if (ES_GAIN(1.3, 1.4, gain_val))
sensor_write(sd, 0x0157, 73);
else if (ES_GAIN(1.4, 1.5, gain_val))
sensor_write(sd, 0x0157, 85);
else if (ES_GAIN(1.5, 1.6, gain_val))
sensor_write(sd, 0x0157, 96);
else if (ES_GAIN(1.6, 1.7, gain_val))
sensor_write(sd, 0x0157, 105);
else if (ES_GAIN(1.7, 1.8, gain_val))
sensor_write(sd, 0x0157, 114);
else if (ES_GAIN(1.8, 1.9, gain_val))
sensor_write(sd, 0x0157, 122);
else if (ES_GAIN(1.9, 2.0, gain_val))
sensor_write(sd, 0x0157, 0x80);
else if (ES_GAIN(2.0, 2.1, gain_val))
sensor_write(sd, 0x0157, 134);
else if (ES_GAIN(2.1, 2.2, gain_val))
sensor_write(sd, 0x0157, 140);
else if (ES_GAIN(2.2, 2.3, gain_val))
sensor_write(sd, 0x0157, 145);
else if (ES_GAIN(2.3, 2.4, gain_val))
sensor_write(sd, 0x0157, 150);
else if (ES_GAIN(2.4, 2.5, gain_val))
sensor_write(sd, 0x0157, 154);
else if (ES_GAIN(2.5, 2.6, gain_val))
sensor_write(sd, 0x0157, 158);
else if (ES_GAIN(2.6, 2.7, gain_val))
sensor_write(sd, 0x0157, 162);
else if (ES_GAIN(2.7, 2.8, gain_val))
sensor_write(sd, 0x0157, 165);
else if (ES_GAIN(2.8, 2.9, gain_val))
sensor_write(sd, 0x0157, 168);
else if (ES_GAIN(2.9, 3.0, gain_val))
sensor_write(sd, 0x0157, 0xab);
else if (ES_GAIN(3.0, 3.1, gain_val))
sensor_write(sd, 0x0157, 174);
else if (ES_GAIN(3.1, 3.2, gain_val))
sensor_write(sd, 0x0157, 176);
else if (ES_GAIN(3.2, 3.3, gain_val))
sensor_write(sd, 0x0157, 179);
else if (ES_GAIN(3.3, 3.4, gain_val))
sensor_write(sd, 0x0157, 181);
else if (ES_GAIN(3.4, 3.5, gain_val))
sensor_write(sd, 0x0157, 183);
else if (ES_GAIN(3.5, 3.6, gain_val))
sensor_write(sd, 0x0157, 185);
else if (ES_GAIN(3.6, 3.7, gain_val))
sensor_write(sd, 0x0157, 187);
else if (ES_GAIN(3.7, 3.8, gain_val))
sensor_write(sd, 0x0157, 189);
else if (ES_GAIN(3.8, 3.9, gain_val))
sensor_write(sd, 0x0157, 191);
else if (ES_GAIN(3.9, 4.0, gain_val))
sensor_write(sd, 0x0157, 192);
else if (ES_GAIN(4.0, 4.1, gain_val))
sensor_write(sd, 0x0157, 194);
else if (ES_GAIN(4.1, 4.2, gain_val))
sensor_write(sd, 0x0157, 195);
else if (ES_GAIN(4.2, 4.3, gain_val))
sensor_write(sd, 0x0157, 197);
else if (ES_GAIN(4.3, 4.4, gain_val))
sensor_write(sd, 0x0157, 198);
else if (ES_GAIN(4.4, 4.5, gain_val))
sensor_write(sd, 0x0157, 200);
else if (ES_GAIN(4.5, 4.6, gain_val))
sensor_write(sd, 0x0157, 201);
else if (ES_GAIN(4.6, 4.7, gain_val))
sensor_write(sd, 0x0157, 202);
else if (ES_GAIN(4.7, 4.8, gain_val))
sensor_write(sd, 0x0157, 203);
else if (ES_GAIN(4.8, 4.9, gain_val))
sensor_write(sd, 0x0157, 204);
else if (ES_GAIN(4.9, 5.0, gain_val))
sensor_write(sd, 0x0157, 205);
else if (ES_GAIN(5.0, 5.1, gain_val))
sensor_write(sd, 0x0157, 206);
else if (ES_GAIN(5.1, 5.2, gain_val))
sensor_write(sd, 0x0157, 207);
else if (ES_GAIN(5.2, 5.3, gain_val))
sensor_write(sd, 0x0157, 208);
else if (ES_GAIN(5.3, 5.4, gain_val))
sensor_write(sd, 0x0157, 209);
else if (ES_GAIN(5.4, 5.5, gain_val))
sensor_write(sd, 0x0157, 210);
else if (ES_GAIN(5.5, 5.7, gain_val))
sensor_write(sd, 0x0157, 211);
else if (ES_GAIN(5.7, 5.8, gain_val))
sensor_write(sd, 0x0157, 212);
else if (ES_GAIN(5.8, 5.9, gain_val))
sensor_write(sd, 0x0157, 213);
else if (ES_GAIN(5.9, 6.2, gain_val))
sensor_write(sd, 0x0157, 215);
else if (ES_GAIN(6.2, 6.4, gain_val))
sensor_write(sd, 0x0157, 216);
else if (ES_GAIN(6.4, 6.5, gain_val))
sensor_write(sd, 0x0157, 217);
else if (ES_GAIN(6.5, 6.7, gain_val))
sensor_write(sd, 0x0157, 218);
else if (ES_GAIN(6.7, 6.9, gain_val))
sensor_write(sd, 0x0157, 219);
else if (ES_GAIN(6.9, 7.1, gain_val))
sensor_write(sd, 0x0157, 220);
else if (ES_GAIN(7.1, 7.3, gain_val))
sensor_write(sd, 0x0157, 221);
else if (ES_GAIN(7.3, 7.5, gain_val))
sensor_write(sd, 0x0157, 222);
else if (ES_GAIN(7.5, 7.7, gain_val))
sensor_write(sd, 0x0157, 223);
else if (ES_GAIN(7.7, 8.0, gain_val))
sensor_write(sd, 0x0157, 224);
else if (ES_GAIN(8.0, 8.3, gain_val))
sensor_write(sd, 0x0157, 225);
else if (ES_GAIN(8.3, 8.5, gain_val))
sensor_write(sd, 0x0157, 226);
else if (ES_GAIN(8.5, 8.8, gain_val))
sensor_write(sd, 0x0157, 227);
else if (ES_GAIN(8.8, 9.1, gain_val))
sensor_write(sd, 0x0157, 228);
else if (ES_GAIN(9.1, 9.4, gain_val))
sensor_write(sd, 0x0157, 228);
else if (ES_GAIN(9.4, 9.8, gain_val))
sensor_write(sd, 0x0157, 230);
else if (ES_GAIN(9.8, 10.2, gain_val))
sensor_write(sd, 0x0157, 231);
else if (ES_GAIN(10.0, 10.6, gain_val))
sensor_write(sd, 0x0157, 232);
info->gain = gain_val;
return 0;
}
#if 0
static int sensor_s_sw_stby(struct v4l2_subdev *sd, int on_off)
{
int ret;
data_type rdval;
ret = sensor_read(sd, 0x0100, &rdval);
if (ret != 0)
return ret;
if (on_off == CSI_GPIO_LOW)
ret = sensor_write(sd, 0x0100, rdval & 0xfe);
else
ret = sensor_write(sd, 0x0100, rdval | 0x01);
return ret;
}
#endif
/*
* Stuff that knows about the sensor.
*/
static int sensor_power(struct v4l2_subdev *sd, int on)
{
sensor_print("entering sensor_power\n");
sensor_dbg("zzz5648 sensor_power\n");
switch (on) {
case STBY_ON:
/*sensor_print("entering sensor_power STBY_ON\n");
sensor_print("STBY_ON!\n");
cci_lock(sd);
sensor_s_sw_stby(sd, STBY_ON);
usleep_range(1000, 1200);
cci_unlock(sd);*/
break;
case STBY_OFF:
sensor_print("entering sensor_power STBY_OFF\n");
sensor_print("STBY_OFF!\n");
/*cci_lock(sd);
usleep_range(1000, 1200);
sensor_s_sw_stby(sd, STBY_OFF);
cci_unlock(sd);*/
break;
case PWR_ON:
sensor_print("entering sensor_power PWR_ON, pins: %d %d\n",PWDN ,POWER_EN);
gpio_direction_output(GPIOA(8), 0); //led enable
gpio_direction_output(GPIOA(9), 0); //power enable
sensor_print("PWR_ON!100\n");
cci_lock(sd);
vin_gpio_set_status(sd, PWDN, 1);
//vin_gpio_write(sd, RESET, CSI_GPIO_HIGH); //not needed for the rpi ov5647 modules
vin_gpio_set_status(sd, POWER_EN, 1);
vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH); //special case, since PWDN is the led we power it ON
//vin_gpio_write(sd, RESET, CSI_GPIO_LOW); //ignore reset
vin_gpio_write(sd, POWER_EN, CSI_GPIO_HIGH);
usleep_range(7000, 8000);
vin_set_pmu_channel(sd, IOVDD, ON);
usleep_range(7000, 8000);
vin_set_pmu_channel(sd, AVDD, ON);
vin_set_pmu_channel(sd, AFVDD, ON);
usleep_range(7000, 8000);
vin_set_pmu_channel(sd, DVDD, ON);
usleep_range(7000, 8000);
vin_set_mclk_freq(sd, MCLK);
vin_set_mclk(sd, ON);
usleep_range(10000, 12000);
//vin_gpio_write(sd, RESET, CSI_GPIO_HIGH); //these calls are useless as well
//vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH);
vin_set_pmu_channel(sd, CAMERAVDD, ON);/*AFVCC ON*/
usleep_range(10000, 12000);
cci_unlock(sd);
break;
case PWR_OFF:
/*sensor_print("PWR_OFF!\n");
cci_lock(sd);
vin_gpio_write(sd, PWDN, CSI_GPIO_LOW); //LED off
//vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
vin_set_mclk(sd, OFF);
usleep_range(7000, 8000);
vin_set_pmu_channel(sd, DVDD, OFF);
//vin_gpio_write(sd, PWDN, CSI_GPIO_LOW);
//vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
vin_gpio_write(sd, POWER_EN, CSI_GPIO_LOW); //turn off power to the camera
vin_set_pmu_channel(sd, AVDD, OFF);
vin_set_pmu_channel(sd, IOVDD, OFF);
vin_set_pmu_channel(sd, AFVDD, OFF);
vin_set_pmu_channel(sd, CAMERAVDD, OFF);/*AFVCC ON*/
//cci_unlock(sd);
break;
default:
return -EINVAL;
}
return 0;
}
static int sensor_reset(struct v4l2_subdev *sd, u32 val)
{
switch (val) {
case 0:
vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
usleep_range(10000, 12000);
break;
case 1:
vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
usleep_range(10000, 12000);
break;
default:
return -EINVAL;
}
return 0;
}
static int sensor_detect(struct v4l2_subdev *sd)
{
data_type rdval, rdval2;
unsigned int SENSOR_ID = 0;
printk(KERN_WARNING "entering sensor_detect\n");
sensor_read(sd, 0x0000, &rdval);
sensor_read(sd, 0x0001, &rdval2);
SENSOR_ID = (rdval << 8) | rdval2;
sensor_print("V4L2_IDENT_SENSOR = 0x%x\n", SENSOR_ID);
if (SENSOR_ID != V4L2_IDENT_SENSOR) {
sensor_print("imx219 %s error, chip found is not an target chip", __func__);
printk(KERN_WARNING "exiting sensor_detect, not found\n");
//return -ENODEV;
}
printk(KERN_WARNING "exiting sensor_detect, found\n");
return 0;
}
static int sensor_init(struct v4l2_subdev *sd, u32 val)
{
int ret;
sensor_power(sd, PWR_ON); //added
struct sensor_info *info = to_state(sd);
sensor_dbg("sensor_init\n");
sensor_power(sd, PWR_ON); //added
/*Make sure it is a target sensor */
ret = sensor_detect(sd);
if (ret) {
sensor_err("chip found is not an target chip.\n");
return ret;
}
info->focus_status = 0;
info->low_speed = 0;
info->width = HXGA_WIDTH;
info->height = HXGA_HEIGHT;
info->hflip = 0;
info->vflip = 0;
info->gain = 0;
info->tpf.numerator = 1;
info->tpf.denominator = 10; /* 30fps */
info->preview_first_flag = 1;
return 0;
}
static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
int ret = 0;
struct sensor_info *info = to_state(sd);
switch (cmd) {
case GET_CURRENT_WIN_CFG:
if (info->current_wins != NULL) {
memcpy(arg,
info->current_wins,
sizeof(struct sensor_win_size));
ret = 0;
} else {
sensor_err("empty wins!\n");
ret = -1;
}
break;
case SET_FPS:
break;
case VIDIOC_VIN_SENSOR_EXP_GAIN:
sensor_s_exp_gain(sd, (struct sensor_exp_gain *)arg);
break;
case VIDIOC_VIN_SENSOR_CFG_REQ:
sensor_cfg_req(sd, (struct sensor_config *)arg);
break;
default:
return -EINVAL;
}
return ret;
}
/*
* Store information about the video data format.
*/
static struct sensor_format_struct sensor_formats[] = {
{
.desc = "Raw RGB Bayer",
.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,//MEDIA_BUS_FMT_SRGGB10_1X10,
.regs = sensor_fmt_raw,
.regs_size = ARRAY_SIZE(sensor_fmt_raw),
.bpp = 1
}
};
#define N_FMTS ARRAY_SIZE(sensor_formats)
/*
* Then there is the issue of window sizes. Try to capture the info here.
*/
static struct sensor_win_size sensor_win_sizes[] = {
/* 3280*2464 */
/*{
.width = 3264,
.height = 2448,
.hoffset = (3280 - 3264) / 2,
.voffset = (2464 - 2448) / 2,
.hts = 3448,
.vts = 4037,
.pclk = (278 * 1000 * 1000),
.mipi_bps = 720 * 1000 * 1000,
.fps_fixed = 1,
.bin_factor = 1,
.intg_min = 1 << 4,
.intg_max = (4037 - 4) << 4,
.gain_min = 1 << 4,
.gain_max = 10 << 4,
.regs = sensor_hxga_regs,
.regs_size = ARRAY_SIZE(sensor_hxga_regs),
.set_size = NULL,
},*/
/* 1080P */
/*{
.width = HD1080_WIDTH,
.height = HD1080_HEIGHT,
.hoffset = 0,
.voffset = 0,
.hts = 3560,
.vts = 2607,
.pclk = (278 * 1000 * 1000),
.mipi_bps = 720 * 1000 * 1000,
.fps_fixed = 1,
.bin_factor = 2,
.intg_min = 1 << 4,
.intg_max = (2607 - 4) << 4,
.gain_min = 1 << 4,
.gain_max = 10 << 4,
.regs = sensor_1080p_regs,
.regs_size = ARRAY_SIZE(sensor_1080p_regs),
.set_size = NULL,
},*/
/* SXGA */
/*{
.width = SXGA_WIDTH,
.height = SXGA_HEIGHT,
.hoffset = 0,
.voffset = 0,
.hts = 3560,
.vts = 2607,
.pclk = (278 * 1000 * 1000),
.mipi_bps = 720 * 1000 * 1000,
.fps_fixed = 1,
.bin_factor = 2,
.intg_min = 1 << 4,
.intg_max = 2607 << 4,
.gain_min = 1 << 4,
.gain_max = 10 << 4,
.regs = sensor_sxga_regs,
.regs_size = ARRAY_SIZE(sensor_sxga_regs),
.set_size = NULL,
},*/
/* 720p */
{
.width = HD720_WIDTH,
.height = HD720_HEIGHT,
.hoffset = 0,
.voffset = 0,
.hts = 2560,
.vts = 1303,
.pclk = (200 * 1000 * 1000),
.mipi_bps = 720 * 1000 * 1000,
.fps_fixed = 1,
.bin_factor = 2,
.intg_min = 1 << 4,
.intg_max = (1303 - 4) << 4,
.gain_min = 1 << 4,
.gain_max = 10 << 4,
.regs = sensor_720p_regs,
.regs_size = ARRAY_SIZE(sensor_720p_regs),
.set_size = NULL,
},
};
#define N_WIN_SIZES (ARRAY_SIZE(sensor_win_sizes))
static int sensor_reg_init(struct sensor_info *info)
{
int ret = 0;
struct v4l2_subdev *sd = &info->sd;
struct sensor_format_struct *sensor_fmt = info->fmt;
struct sensor_win_size *wsize = info->current_wins;
ret = sensor_write_array(sd, sensor_default_regs,
ARRAY_SIZE(sensor_default_regs));
if (ret < 0) {
sensor_err("write sensor_default_regs error\n");
return ret;
}
ret = sensor_read_array(sd, sensor_default_regs, ARRAY_SIZE(sensor_default_regs));
if (ret < 0) {
sensor_err("read-back ov5647_640x480_10bpp error\n");
return ret;
}
sensor_write_array(sd, sensor_fmt->regs, sensor_fmt->regs_size);
if (wsize->regs)
sensor_write_array(sd, wsize->regs, wsize->regs_size);
if (wsize->set_size)
wsize->set_size(sd);
info->width = wsize->width;
info->height = wsize->height;
imx219_sensor_vts = wsize->vts;
sensor_print("s_fmt set width = %d, height = %d\n", wsize->width,
wsize->height);
return 0;
}
static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
{
struct sensor_info *info = to_state(sd);
sensor_print("%s on = %d, %d*%d %x\n", __func__, enable,
info->current_wins->width,
info->current_wins->height, info->fmt->mbus_code);
if (!enable)
return 0;
return sensor_reg_init(info);
}
static int sensor_g_mbus_config(struct v4l2_subdev *sd,
struct v4l2_mbus_config *cfg)
{
cfg->type = V4L2_MBUS_CSI2;
cfg->flags = 0 | V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0;
return 0;
}
static int sensor_g_ctrl(struct v4l2_ctrl *ctrl)
{
struct sensor_info *info =
container_of(ctrl->handler, struct sensor_info, handler);
struct v4l2_subdev *sd = &info->sd;
switch (ctrl->id) {
case V4L2_CID_GAIN:
return sensor_g_gain(sd, &ctrl->val);
case V4L2_CID_EXPOSURE:
return sensor_g_exp(sd, &ctrl->val);
}
return -EINVAL;
}
static int sensor_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct sensor_info *info =
container_of(ctrl->handler, struct sensor_info, handler);
struct v4l2_subdev *sd = &info->sd;
switch (ctrl->id) {
case V4L2_CID_GAIN:
return sensor_s_gain(sd, ctrl->val);
case V4L2_CID_EXPOSURE:
return sensor_s_exp(sd, ctrl->val);
}
return -EINVAL;
}
/* ----------------------------------------------------------------------- */
static const struct v4l2_ctrl_ops sensor_ctrl_ops = {
.g_volatile_ctrl = sensor_g_ctrl,
.s_ctrl = sensor_s_ctrl,
};
static const struct v4l2_subdev_core_ops sensor_core_ops = {
.reset = sensor_reset,
.init = sensor_init,
.s_power = sensor_power,
.ioctl = sensor_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl32 = sensor_compat_ioctl32,
#endif
};
static const struct v4l2_subdev_video_ops sensor_video_ops = {
.s_parm = sensor_s_parm,
.g_parm = sensor_g_parm,
.s_stream = sensor_s_stream,
.g_mbus_config = sensor_g_mbus_config,
};
static const struct v4l2_subdev_pad_ops sensor_pad_ops = {
.enum_mbus_code = sensor_enum_mbus_code,
.enum_frame_size = sensor_enum_frame_size,
.get_fmt = sensor_get_fmt,
.set_fmt = sensor_set_fmt,
};
static const struct v4l2_subdev_ops sensor_ops = {
.core = &sensor_core_ops,
.video = &sensor_video_ops,
.pad = &sensor_pad_ops,
};
/* ----------------------------------------------------------------------- */
static struct cci_driver cci_drv = {
.name = SENSOR_NAME,
.addr_width = CCI_BITS_16,
.data_width = CCI_BITS_8,
};
static const struct v4l2_ctrl_config sensor_custom_ctrls[] = {
{
.ops = &sensor_ctrl_ops,
.id = V4L2_CID_FRAME_RATE,
.name = "frame rate",
.type = V4L2_CTRL_TYPE_INTEGER,
.min = 15,
.max = 120,
.step = 1,
.def = 120,
},
};
static int sensor_init_controls(struct v4l2_subdev *sd, const struct v4l2_ctrl_ops *ops)
{
struct sensor_info *info = to_state(sd);
struct v4l2_ctrl_handler *handler = &info->handler;
struct v4l2_ctrl *ctrl;
int i;
int ret = 0;
v4l2_ctrl_handler_init(handler, 2 + ARRAY_SIZE(sensor_custom_ctrls));
ctrl = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 0,
65536 * 16, 1, 0);
if (ctrl != NULL)
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
v4l2_ctrl_new_std(handler, ops, V4L2_CID_GAIN, 1 * 1600,
256 * 1600, 1, 1 * 1600);
for (i = 0; i < ARRAY_SIZE(sensor_custom_ctrls); i++)
v4l2_ctrl_new_custom(handler, &sensor_custom_ctrls[i], NULL);
if (handler->error) {
ret = handler->error;
v4l2_ctrl_handler_free(handler);
}
sd->ctrl_handler = handler;
return ret;
}
static int sensor_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct v4l2_subdev *sd;
struct sensor_info *info;
info = kzalloc(sizeof(struct sensor_info), GFP_KERNEL);
if (info == NULL)
return -ENOMEM;
sd = &info->sd;
cci_dev_probe_helper(sd, client, &sensor_ops, &cci_drv);
sensor_init_controls(sd, &sensor_ctrl_ops);
mutex_init(&info->lock);
info->fmt = &sensor_formats[0];
info->fmt_pt = &sensor_formats[0];
info->win_pt = &sensor_win_sizes[0];
info->fmt_num = N_FMTS;
info->win_size_num = N_WIN_SIZES;
info->sensor_field = V4L2_FIELD_NONE;
info->af_first_flag = 1;
return 0;
}
static int sensor_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd;
sd = cci_dev_remove_helper(client, &cci_drv);
kfree(to_state(sd));
return 0;
}
static const struct i2c_device_id sensor_id[] = {
{SENSOR_NAME, 0},
{}
};
MODULE_DEVICE_TABLE(i2c, sensor_id);
static struct i2c_driver sensor_driver = {
.driver = {
.owner = THIS_MODULE,
.name = SENSOR_NAME,
},
.probe = sensor_probe,
.remove = sensor_remove,
.id_table = sensor_id,
};
static __init int init_sensor(void)
{
return cci_dev_init_helper(&sensor_driver);
}
static __exit void exit_sensor(void)
{
cci_dev_exit_helper(&sensor_driver);
}
module_init(init_sensor);
module_exit(exit_sensor);
修改后的驱动程序的工作原理与我尝试过的其他所有操作相同,捕获帧超时。
root@TinaLinux:/# camerademo BGGR8 1280 720 30 bmp /tmp 5
[CAMERA]************************[ 193.743051] [imx219]entering sensor_power
********************************[ 193.749768] [imx219]entering sensor_power PWR_ON, pins: 1 0
**
[CAMERA]* [ 193.758780] [imx219]PWR_ON!100
*
[CAMERA]* this is camera test. *
[CAMERA]* [ 193.773171] [VIN_ERR]imx219 cannot find the match sensor_helper
*
[CAMERA]****************************************[ 193.790703] [VIN_ERR]imx219 cannot find the match sensor_helper
******************
[CAMERA]****[ 193.797641] [VIN_ERR]imx219 cannot find the match sensor_helper
******************************************************
[CAMERA] open /dev/video0!
[CAMERA]****[ 193.814747] [VIN_ERR]imx219 cannot find the match sensor_helper
******************************************************
[CAMERA]**********************************************************
[CAMERA] The path to data saving is /tmp.
[CAMERA] The number of captured photos is 5.
[CAMERA] save bmp format
[ 193.842052] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 193.861353] [imx219]entering sensor_power
[ 193.865910] [imx219]entering sensor_power PWR_ON, pins: 1 0
[ 193.872154] [imx219]PWR_ON!100
[ 193.883647] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 193.898305] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 193.904951] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 193.919592] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 193.946278] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 193.964736] entering sensor_detect
[ 193.969158] [imx219]V4L2_IDENT_SENSOR = 0x219
[ 193.974040] exiting sensor_detect, found
[ 193.979674] [VIN_ERR]vin is not support this pixelformat
[ 193.985673] [VIN_ERR]sensor pixelformat is 3001
[ 193.990940] [VIN_ERR]vin is not support this pixelformat
[ 193.996918] [VIN_ERR]sensor pixelformat is 3001
[ 194.002195] [VIN_ERR]vin is not support this pixelformat
[ 194.008161] [VIN_ERR]sensor pixelformat is 3001
[ 194.013424] [VIN_ERR]vin is not support this pixelformat
[ 194.019478] [VIN_ERR]sensor pixelformat is 3001
[ 194.024792] [VIN_ERR]vin is not support this pixelformat
[ 194.030743] [VIN_ERR]sensor pixelformat is 3001
[ 194.036038] [VIN_ERR]vin is not support this pixelformat
[ 194.041987] [VIN_ERR]sensor pixelformat is 3001
[ 194.047283] [VIN_ERR]vin is not support this pixelformat
[ 194.053234] [VIN_ERR]sensor pixelformat is 3001
[ 194.058514] [VIN_ERR]vin is not support this pixelformat
[ 194.064461] [VIN_ERR]sensor pixelformat is 3001
[ 194.069812] [VIN_ERR]vin is not support this pixelformat
[ 194.075786] [VIN_ERR]sensor pixelformat is 3001
[ 194.081055] [VIN_ERR]vin is not support this pixelformat
[ 194.087025] [VIN_ERR]sensor pixelformat is 3001
[ 194.092299] [VIN_ERR]vin is not support this pixelformat
[ 194.098266] [VIN_ERR]sensor pixelformat is 3001
[ 194.103530] [VIN_ERR]vin is not support this pixelformat
[ 194.109497] [VIN_ERR]sensor pixelformat is 3001
[CAMERA]********************************************************[ 194.118170] [imx219]sensor_s_stream on = 1, 1280*720 3001
**
[CAMERA] Using format parameters BGGR8.
[CAMERA] camera pix[ 194.131226] [VIN_DEV_I2C_ERR]read from imx219 addr is 0x30eb, data is 0x0, but should be 0x5
elformat: BGGR8
[CAMERA] Resolu[ 194.141789] [VIN_DEV_I2C_ERR]read from imx219 addr is 0x30eb, data is 0x0, but should be 0xc
tion size : 1280 * 720
[CAMERA][ 194.154018] [VIN_DEV_I2C]read from imx219 addr is 0x300a, data is 0xff
The photo save path is /tmp.
[[ 194.164104] [VIN_DEV_I2C]read from imx219 addr is 0x300b, data is 0xff
CAMERA] The number of photos tak[ 194.174288] [VIN_DEV_I2C_ERR]read from imx219 addr is 0x30eb, data is 0x0, but should be 0x5
en is 5.
[ 194.186439] [VIN_DEV_I2C_ERR]read from imx219 addr is 0x30eb, data is 0x0, but should be 0x9
pid: 883, g_alloc_context = 0xb[ 194.198671] [VIN_DEV_I2C]read from imx219 addr is 0x114, data is 0x1
6db3360
[CAMERA] Camera captur[ 194.208567] [VIN_DEV_I2C]read from imx219 addr is 0x128, data is 0x0
e framerate is 1/1
[CAMERA] VID[ 194.218526] [VIN_DEV_I2C]read from imx219 addr is 0x12a, data is 0x18
IOC_S_FMT succeed
[CAMERA] fmt.[ 194.228466] [VIN_DEV_I2C]read from imx219 addr is 0x12b, data is 0x0
type = 9
[CAMERA] fmt.fmt.pix_m[ 194.238365] [VIN_DEV_I2C]read from imx219 addr is 0x160, data is 0x2
p.width = 1280
[CAMERA] fmt.fmt[ 194.248258] [VIN_DEV_I2C]read from imx219 addr is 0x161, data is 0x0
.pix_mp.height = 720
[CAMERA] f[ 194.258149] [VIN_DEV_I2C]read from imx219 addr is 0x162, data is 0xd
mt.fmt.pix_mp.pixelformat = BGGR[ 194.268092] [VIN_DEV_I2C]read from imx219 addr is 0x163, data is 0xe8
8
[CAMERA] fmt.fmt.pix_mp.field[ 194.278044] [VIN_DEV_I2C]read from imx219 addr is 0x164, data is 0x3
= 1
[ 194.287929] [VIN_DEV_I2C]read from imx219 addr is 0x165, data is 0xe8
[ 194.295659] [VIN_DEV_I2C]read from imx219 addr is 0x166, data is 0x8
[ 194.303039] [VIN_DEV_I2C]read from imx219 addr is 0x167, data is 0xe7
[ 194.310529] [VIN_DEV_I2C]read from imx219 addr is 0x168, data is 0x3
[ 194.317967] [VIN_DEV_I2C]read from imx219 addr is 0x169, data is 0x68
[ 194.325461] [VIN_DEV_I2C]read from imx219 addr is 0x16a, data is 0x6
[ 194.332841] [VIN_DEV_I2C]read from imx219 addr is 0x16b, data is 0x37
[ 194.340333] [VIN_DEV_I2C]read from imx219 addr is 0x16c, data is 0x5
[ 194.347726] [VIN_DEV_I2C]read from imx219 addr is 0x16d, data is 0x0
[ 194.355113] [VIN_DEV_I2C]read from imx219 addr is 0x16e, data is 0x2
[ 194.362489] [VIN_DEV_I2C]read from imx219 addr is 0x16f, data is 0xd0
[ 194.370021] [VIN_DEV_I2C]read from imx219 addr is 0x170, data is 0x1
[ 194.377423] [VIN_DEV_I2C]read from imx219 addr is 0x171, data is 0x1
[ 194.384804] [VIN_DEV_I2C]read from imx219 addr is 0x174, data is 0x0
[ 194.392184] [VIN_DEV_I2C]read from imx219 addr is 0x175, data is 0x0
[ 194.399578] [VIN_DEV_I2C]read from imx219 addr is 0x18c, data is 0xa
[ 194.406965] [VIN_DEV_I2C]read from imx219 addr is 0x18d, data is 0xa
[ 194.414343] [VIN_DEV_I2C]read from imx219 addr is 0x301, data is 0x5
[ 194.421774] [VIN_DEV_I2C]read from imx219 addr is 0x303, data is 0x1
[ 194.429173] [VIN_DEV_I2C]read from imx219 addr is 0x304, data is 0x3
[ 194.436568] [VIN_DEV_I2C]read from imx219 addr is 0x305, data is 0x3
[ 194.443947] [VIN_DEV_I2C]read from imx219 addr is 0x306, data is 0x0
[ 194.451344] [VIN_DEV_I2C]read from imx219 addr is 0x307, data is 0x57
[ 194.458830] [VIN_DEV_I2C]read from imx219 addr is 0x309, data is 0x5
[ 194.466260] [VIN_DEV_I2C]read from imx219 addr is 0x30b, data is 0x1
[ 194.473640] [VIN_DEV_I2C]read from imx219 addr is 0x30c, data is 0x0
[ 194.481032] [VIN_DEV_I2C]read from imx219 addr is 0x30d, data is 0x5a
[ 194.488574] [VIN_DEV_I2C]read from imx219 addr is 0x100, data is 0x1
[ 194.500109] [imx219]s_fmt set width = 1280, height = 720
[CAMERA] stream on succeed
[CAMERA] camera0 capture num is [0]
[CAMERA_ERR] camera0[ 196.509907] [imx219]sensor_s_stream on = 0, 1280*720 3001
select timeout,end capture thread!
[CAMERA] Capture thread finish
[CAMERA] close /dev/video0
[CAMERA_ERR] capture_photo return error
root@TinaLinux:/#
@baiwen 鉴于板上存在 wifi 收发器并且也没有 CE 标记,这是有道理的...祝您获得认证好运,以便您可以恢复业务... 我会通过电子邮件与您联系.
@YuzukiTsuru 非常好的项目,这正是我一直在努力实现的目标,您使用的是 NDA 下的专有 sdk,而不是开源 tina linux sdk,不是吗? 否则你如何让视频编码器工作?
@yuzukitsuru 这是一块非常好的板,您认为这个版本的 SDK 可以适应在 V851S(非 SE)上以同样的方式工作吗?
@yuzukitsuru 您是说,如果我只是覆盖适用于 V851S 的 .img 文件的 squashfs 分区,它将与您提供的 V851SE 特定 iamge 文件一起使用? 因为我尝试过,它导致了内核恐慌...
[ 3.507007] sunxi-mmc sdc1: sdc set ios:clk 0Hz bm PP pm OFF vdd 0 width 1 timing LEGACY(SDR12) dt B
[ 3.618963] remoteproc0: Direct firmware load for melis-elf failed with error -2
[ 3.629611] get det_vbus is fail, 84
[ 3.634517] get id is fail, 84
[ 3.639115] sunxi-rtc rtc: setting system clock to 1970-01-01 00:01:42 UTC (102)
[ 3.648833] clk: Not disabling unused clocks
[ 3.653760] ALSA device list:
[ 3.657088] #0: audiocodec
[ 3.660466] #1: snddaudio0
[ 3.670653] VFS: Mounted root (squashfs filesystem) readonly on device 179:4.
[ 3.682504] devtmpfs: mounted
[ 3.687970] Freeing unused kernel memory: 1024K
[ 3.693329] will run init ...
[ 3.696755] Kernel panic - not syncing: Requested init /init failed (error -2).
[ 3.704937] CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.191 #1
[ 3.711457] Hardware name: sun8iw21
[ 3.715390] [<c010d5a0>] (unwind_backtrace) from [<c010a694>] (show_stack+0x10/0x14)
[ 3.724060] [<c010a694>] (show_stack) from [<c017050c>] (panic+0xac/0x2b8)
[ 3.731758] [<c017050c>] (panic) from [<c0680854>] (kernel_init+0x98/0x118)
[ 3.739553] [<c0680854>] (kernel_init) from [<c0106e08>] (ret_from_fork+0x14/0x2c)
[ 3.748027] ---[ end Kernel panic - not syncing: Requested init /init failed (error -2).
[ 3.757074] sunxi dump enabled
[ 3.760484] dump regs done
[ 3.763544] flush cache done
[ 3.766782] crashdump enter
该映像是使用默认设置 (squashfs) 的 yuzukilizard BSP/openwrt 从默认的 V853 sdk 编译的(按原样使用时有效),我使用该命令来替换 rootfs squashfs:
sudo dd if=/dev/sdf4 of=/dev/sdi4 bs=4M conv=fsync
或者这不是您所说的“替换rootfs”的意思?
感谢您的帖子,我忘记对 SD 卡执行“pack -d”操作,这会在 SD 卡中使用时导致损坏,现在它可以工作了。
我已经购买了树莓派相机模块 V2 (IMX219),我尝试使用提供的驱动程序模块,很明显它无法像现在一样工作。 我必须将通道设置更改为 2 通道和相应的寄存器,因为驱动程序默认配置为 4 通道 mipi csi 操作。
经过几次测试后,我遇到了同样的问题,camerademo 超时并且不保存任何帧。 正如您在日志中看到的那样,I2C 配置已完美发送,它与我发送的配置匹配,寄存器有意义,数据格式应为 RGB8 位。
root@TinaLinux:/# camerademo RGGB8 1280 720 30 bmp /tmp 5
[CAMERA]************************[ 106.325471] [imx219]entering sensor_power
********************************[ 106.332158] [imx219]entering sensor_power PWR_ON, pins: 1 0
**
[CAMERA]* [ 106.341204] [imx219]PWR_ON!100
*
[CAMERA]* this is camera test. [ 106.355469] [VIN_ERR]imx219 cannot find the match sensor_helper
*
[CAMERA]* *
[CAMERA]********[ 106.370358] [VIN_ERR]imx219 cannot find the match sensor_helper
********************************[ 106.377305] [VIN_ERR]imx219 cannot find the match sensor_helper
******************
[CAMERA]**********************************************************
[CAMERA][ 106.394725] [VIN_ERR]imx219 cannot find the match sensor_helper
open /dev/video0!
[CAMERA]**********************************************************
[CAMERA]**********************************************************
[CAMERA] The path to data saving is /tmp.
[CAMERA] The number of captured photos is 5.
[CAMERA] sa[ 106.421709] [VIN_ERR]imx219 cannot find the match sensor_helper
ve bmp format
[ 106.442489] [imx219]entering sensor_power
[ 106.446997] [imx219]entering sensor_power PWR_ON, pins: 1 0
[ 106.453243] [imx219]PWR_ON!100
[ 106.464759] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 106.479407] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 106.486050] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 106.500689] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 106.526778] [VIN_ERR]imx219 cannot find the match sensor_helper
[ 106.546028] [imx219]IMX219 found: 0x19
[ 106.550783] [VIN_ERR]vin is not support this pixelformat
[ 106.556950] [VIN_ERR]vin is not support this pixelformat
[ 106.563035] [VIN_ERR]vin is not support this pixelformat
[ 106.569236] [VIN_ERR]vin is not support this pixelformat
[ 106.575351] [VIN_ERR]vin is not support this pixelformat
[ 106.581437] [VIN_ERR]vin is not support this pixelformat
[ 106.587540] [VIN_ERR]vin is not support this pixelformat
[ 106.593920] [VIN_ERR]vin is not support this pixelformat
[ 106.600029] [VIN_ERR]vin is not support this pixelformat
[ 106.606125] [VIN_ERR]vin is not support this pixelformat
[ 106.612205] [VIN_ERR]vin is not support this pixelformat
[ 106.618370] [VIN_ERR]vin is not support this pixelformat
[ 106.624458] [VIN_ERR]vin is not support this pixelformat
[ 106.630563] [VIN_ERR]vin is not support this pixelformat
[ 106.636660] [VIN_ERR]vin is not support this pixelformat
[ 106.642741] [VIN_ERR]vin is not support this pixelformat
[ 106.648841] [VIN_ERR]vin is not support this pixelformat
[ 106.654949] [VIN_ERR]vin is not support this pixelformat
[ 106.661031] [VIN_ERR]vin is not support this pixelformat
[CAMERA]********************************************************[ 106.670585] [imx219]sensor_s_stream on = 1, 1280*720 31384142
**
[CAMERA] Using format parameters RGGB8.
[CAMERA] camera pix[ 106.684056] [VIN_DEV_I2C]read from imx219 addr is 0x30eb, data is 0x0
elformat: RGGB8
[CAMERA] Resolu[ 106.692344] [VIN_DEV_I2C]read from imx219 addr is 0x30eb, data is 0x0
tion size : 1280 * 720
[CAMERA][ 106.702334] [VIN_DEV_I2C]read from imx219 addr is 0x300a, data is 0xff
The photo save path is /tmp.
[[ 106.712417] [VIN_DEV_I2C]read from imx219 addr is 0x300b, data is 0xff
CAMERA] The number of photos tak[ 106.722584] [VIN_DEV_I2C]read from imx219 addr is 0x30eb, data is 0x0
en is 5.
[ 106.732510] [VIN_DEV_I2C]read from imx219 addr is 0x30eb, data is 0x0
pid: 863, g_alloc_context = 0x2[ 106.742495] [VIN_DEV_I2C]read from imx219 addr is 0x114, data is 0x1
ecd0
[CAMERA] Camera capture f[ 106.752394] [VIN_DEV_I2C]read from imx219 addr is 0x128, data is 0x0
ramerate is 1/1
[CAMERA] VIDIOC[ 106.762271] [VIN_DEV_I2C]read from imx219 addr is 0x12a, data is 0x18
_S_FMT succeed
[CAMERA] fmt.typ[ 106.772314] [VIN_DEV_I2C]read from imx219 addr is 0x12b, data is 0x0
e = 9
[CAMERA] fmt.fmt.pix_mp.w[ 106.782168] [VIN_DEV_I2C]read from imx219 addr is 0x160, data is 0x2
idth = 1280
[CAMERA] fmt.fmt.pi[ 106.792056] [VIN_DEV_I2C]read from imx219 addr is 0x161, data is 0x0
x_mp.height = 720
[CAMERA] fmt.[ 106.801948] [VIN_DEV_I2C]read from imx219 addr is 0x162, data is 0xd
fmt.pix_mp.pixelformat = RGGB8
[ 106.811838] [VIN_DEV_I2C]read from imx219 addr is 0x163, data is 0xe8
[CAMERA] fmt.fmt.pix_mp.field = [ 106.821877] [VIN_DEV_I2C]read from imx219 addr is 0x164, data is 0x3
1
[ 106.831726] [VIN_DEV_I2C]read from imx219 addr is 0x165, data is 0xe8
[ 106.839218] [VIN_DEV_I2C]read from imx219 addr is 0x166, data is 0x8
[ 106.846610] [VIN_DEV_I2C]read from imx219 addr is 0x167, data is 0xe7
[ 106.854086] [VIN_DEV_I2C]read from imx219 addr is 0x168, data is 0x3
[ 106.861477] [VIN_DEV_I2C]read from imx219 addr is 0x169, data is 0x68
[ 106.869015] [VIN_DEV_I2C]read from imx219 addr is 0x16a, data is 0x6
[ 106.876410] [VIN_DEV_I2C]read from imx219 addr is 0x16b, data is 0x37
[ 106.883888] [VIN_DEV_I2C]read from imx219 addr is 0x16c, data is 0x5
[ 106.891284] [VIN_DEV_I2C]read from imx219 addr is 0x16d, data is 0x0
[ 106.898679] [VIN_DEV_I2C]read from imx219 addr is 0x16e, data is 0x2
[ 106.906067] [VIN_DEV_I2C]read from imx219 addr is 0x16f, data is 0xd0
[ 106.913540] [VIN_DEV_I2C]read from imx219 addr is 0x170, data is 0x1
[ 106.920972] [VIN_DEV_I2C]read from imx219 addr is 0x171, data is 0x1
[ 106.928369] [VIN_DEV_I2C]read from imx219 addr is 0x174, data is 0x0
[ 106.935760] [VIN_DEV_I2C]read from imx219 addr is 0x175, data is 0x0
[ 106.943138] [VIN_DEV_I2C]read from imx219 addr is 0x18c, data is 0xa
[ 106.950531] [VIN_DEV_I2C]read from imx219 addr is 0x18d, data is 0xa
[ 106.957922] [VIN_DEV_I2C]read from imx219 addr is 0x301, data is 0x5
[ 106.965353] [VIN_DEV_I2C]read from imx219 addr is 0x303, data is 0x1
[ 106.972733] [VIN_DEV_I2C]read from imx219 addr is 0x304, data is 0x3
[ 106.980134] [VIN_DEV_I2C]read from imx219 addr is 0x305, data is 0x3
[ 106.987531] [VIN_DEV_I2C]read from imx219 addr is 0x306, data is 0x0
[ 106.994916] [VIN_DEV_I2C]read from imx219 addr is 0x307, data is 0x57
[ 107.002397] [VIN_DEV_I2C]read from imx219 addr is 0x309, data is 0x5
[ 107.009786] [VIN_DEV_I2C]read from imx219 addr is 0x30b, data is 0x1
[ 107.017220] [VIN_DEV_I2C]read from imx219 addr is 0x30c, data is 0x0
[ 107.024601] [VIN_DEV_I2C]read from imx219 addr is 0x30d, data is 0x5a
[ 107.032102] [VIN_DEV_I2C]read from imx219 addr is 0x100, data is 0x1
[ 107.043636] [imx219]s_fmt set width = 1280, height = 720
[CAMERA] stream on succeed
[CAMERA] camera0 capture num is [0]
[CAMERA_ERR] camera0[ 109.053436] [imx219]sensor_s_stream on = 0, 1280*720 31384142
select timeout,end capture thread!
[CAMERA] Capture thread finish
[CAMERA] close /dev/video0
[CAMERA_ERR] capture_photo return error
root@TinaLinux:/#
目前,要么是我的内核配置有问题,要么是我的 mipi 线路上的主板出现硬件问题……但这两者似乎都不明显,对于如此低的数据速率,我的路由应该“足够好”。
这些“VIN 格式不支持”错误也很奇怪,因为我似乎使用了正确的格式。
我附上了我的IMX219.C驱动程序的修改版本,如果有人想看一下,我现在唯一尝试支持的设置是720P。
imx219.c
ov5647_mipi.c
我还附上了主板的完整启动日志,有很多启动错误,但我怀疑它们实际上与当前问题有关,因为所有必需的模块都已加载。
也许有人能够发现我错过的明显的东西......
@awwwwa 我已经研究过 @YuzukiTsuru 制作的这个特定驱动程序,它存在一些问题:
#define V4L2_IDENT_SENSOR 0x5648
static int sensor_detect(struct v4l2_subdev *sd)
{
data_type rdval;
unsigned int SENSOR_ID = 0;
sensor_read(sd, 0x300A, &rdval);
SENSOR_ID |= rdval;
SENSOR_ID |= (rdval << 8);
sensor_read(sd, 0x300B, &rdval);
SENSOR_ID |= (rdval);
sensor_print("V4L2_IDENT_SENSOR = 0x%x\n", SENSOR_ID);
if (SENSOR_ID != V4L2_IDENT_SENSOR) {
sensor_print("ov5648 %s error, chip found is not an target chip", __func__);
//return -ENODEV;
}
return 0;
}
#define SENSOR_NAME "ov5648_mipi"
一旦这些基本问题得到解决,驱动程序就会加载并创建 /dev/video 节点,就像我的驱动程序一样。 但我们最终在camerademo应用程序上遇到了完全相同的错误:
唯一的区别是由于缺少配置文件而导致 ISP 上出现一些错误行,但由于我们的错误与超时相关,因此它不应受到任何“像素格式”或 ISP 错误的影响。 因此,即使有了这个驱动程序,我们还是回到了原点。
我想知道 MLCK 位于相机内部并且未连接到 V851S 是否会导致问题...
我发现 allwinner 提供的文档之一在常见问题解答中提供了有关我所面临的确切问题的信息。 所以我现在会尝试按照其中的说明进行操作。 我似乎需要 mipi 寄存器偏移量才能正确调试,但他们不为 V851S 提供这些偏移量,只为其他芯片提供这些偏移量,而且我在芯片的数据表中没有找到它们,知道我可以从哪里获得它们吗?