V851S tina linux ov5647 驱动程序没有 dmesg
-
大家好,
在修复了我的 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 };
-
@kanken6174 在 V851S tina linux ov5647 驱动程序没有 dmesg 中说:
我正在从头开始重写它。
你好
当我在 linux 中开发传感器驱动程序时,我使用特殊代码将 ioctl 添加到 V4l2 驱动程序、VIN 驱动程序和传感器驱动程序中。
此 ioctl 用于直接从用户空间写入和读取传感器寄存器。 这种方法大大加快了开发速度, 因为从用户程序测试传感器寄存器编程的各种选项比从驱动程序测试要容易得多。 -
@alb702 这是个好建议,我可能会这样做,因为传感器由于某种原因仍然没有发送其 mipi 帧......它至少会让调试更容易
-
ov5647 这个型号的摄像头并没有适配,SDK也没有支持。
请参考V85x的摄像头支持手册选择适配的摄像头。这里推荐已经量产的产品使用的GC2063,GC2083,GC4663这三款摄像头,已经经过严格的测试与调试,可以达到最佳画质和分辨率
-
@awwwwa 我知道 OV5647 不支持开箱即用,我想通过修改内核中已有的 OV5648 驱动程序来为其制作一个驱动程序。 我在驱动程序中仔细设置了 I2C 上每个必需的寄存器,其方式类似于 linux 内核 6.1 驱动程序处理它的方式(因为 linux 6.1 内置了 0V5647 驱动程序)。
我按照 allwinner 提供的在 tina-linux 下移植相机的指南进行操作,我的驱动程序成功加载、发送相机配置并正确报告。 mipi-csi 时钟和数据通道上也有活动(但它们太快了,我无法正确调试),这表明相机确实对其新配置做出了反应。
现在我当然可以选择支持更好的 GC 相机,但这不是目标,我正在尝试在这个平台上支持 rapsberry pi 1.3 相机。 我这样做是因为许多廉价模块都采用这种 15 针外形尺寸,但 GC 系列相机很难找到这种格式。
接下来我可能会尝试 IMX219(树莓派相机 V2),因为当前的 4.9 内核中已经有它的驱动程序,但目前 OV5647 仍然超时与camerademo,并且没有太多关于应该采取的行动过程的信息 在这种情况下,请参见 PDF 的常见问题解答。
您认为有什么东西可能会破坏我的 allwinner Eyesee 框架方面的驱动程序吗? 我还必须考虑硬件不兼容的可能性,并验证我猜的所有 mipi 逻辑级别...
-
@kanken6174 我之前尝试移植过,可以使用这个帖子中的驱动测试
Porject Yosemite - 基于全志V853的开发板
https://bbs.aw-ol.com/topic/1389/share/41 -
@yuzukitsuru 感谢该驱动程序,但我之前已经尝试过但没有成功,它有很多问题(如果您在本文中引用 ov5647_mipi.c 驱动程序),例如:
- 设备ID和传感器名称错误:
#define SENSOR_NAME "ov5648_mipi" #define V4L2_IDENT_SENSOR 0x5648
应该
#define SENSOR_NAME "ov5647_mipi" #define V4L2_IDENT_SENSOR 0x5647
- 读取CHIP_ID的方式也是错误的,导致读取的是0x5657而不是0x5647
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);
应该
data_type rdval, rdval2; unsigned int SENSOR_ID = 0; printk(KERN_WARNING "entering sensor_detect\n"); sensor_read(sd, CHIP_ID_ADDR, &rdval); sensor_read(sd, CHIP_ID_ADDR_L, &rdval2); SENSOR_ID = (rdval << 8) | rdval2; sensor_print("V4L2_IDENT_SENSOR = 0x%x\n", SENSOR_ID);
- 检测时似乎根本没有给相机加电,所以它永远找不到它(我必须在 INIT 函数中添加对传感器电源的调用才能检测到我的)
static int sensor_init(struct v4l2_subdev *sd, u32 val) { int ret = 0; struct sensor_info *info = to_state(sd); printk(KERN_WARNING "entering sensor_init\n"); sensor_print("sensor_init\n"); sensor_power(sd, PWR_ON); //added
总体而言,这个驱动程序似乎是基于 OV5648.c 的,该驱动程序已经存在所有这些问题,您是否真的让它在某个时刻与 OV5647 一起工作,或者它只是一个草案?
-
我已经购买了树莓派相机模块 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我还附上了主板的完整启动日志,有很多启动错误,但我怀疑它们实际上与当前问题有关,因为所有必需的模块都已加载。
也许有人能够发现我错过的明显的东西......
-
这是启动日志:
boot.log -
@kanken6174 在 V851S tina linux ov5647 驱动程序没有 dmesg 中说:
VIN_ERR
错误
[ 106.661031] [VIN_ERR]vin is not support this pixelformat
表示 VIN 驱动程序不支持为此传感器模式设置的像素格式
确保具有此名称的格式已在 VIN 驱动程序源中列出
-
@alb702 我在驱动程序源代码和camerademo命令中尝试了许多不同的像素格式,但它总是最终无法实际工作并给出某种形式的错误。 除了 RGGB8 之外,相机不支持其他格式,当我使用 RGGB8 时,camerademo 会查询传感器的图像,这意味着它至少可以工作到那时。
然后等待帧返回超时,我仍在尝试理解原因,但显然存在相机配置方式或 allwinner 驱动程序期望如何接收帧的问题。如果这是图像格式的问题,我不会收到这种特定类型的错误:
-
@kanken6174 你好,请问这个问题解决了吗?我在添加调试OV9734的摄像头驱动也遇到了这个问题?请问有什么调试的思路吗?
-
@j_biao 目前我还无法让它发挥作用,我仍然停留在与以前相同的位置。 我购买了一台高速逻辑分析仪来尝试看看 mipi 总线上发生了什么。
看起来 mipi 通道的行为根本不像 mipi 通道,这看起来像并行 csi 数据(如果有的话)(时钟通道应该是不同的,但它们不是?)...这很奇怪,因为我仔细检查了两次和三次 我的 i2c/CCI 配置和所有正确的配置应发送到 OV5647 以进入 mipi 模式,而不是并行 csi 模式。
我将尝试获取树莓派 3 来调试它如何设置相机并查看 I2C 和 MIPI 方面的任何差异。
-
@kanken6174 可以检查一下驱动端是不是正确设置为了mipi模式Tina_Linux_Camera_开发指南.pdf
-
@whycanservice 我完全遵循了 allwinner 提供的文档,我查看了您指出的指南以及专门关于 mipi-csi 的指南,我遵循了所需的所有步骤,甚至将逻辑分析仪连接到单独的树莓派 3 以通过 I2C 发送来收集它 数据来复制它,这至少应该在启用流的 mipi-csi 模式下生成一个配置,然后相应地配置驱动程序(分辨率、VTS/HTS...),但仍然超时并且主板未检测到任何内容。
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 struct sensor_win_size sensor_win_sizes[] = { { .width = 1296, //camerademo GBRG10 1296 972 15 bmp /tmp 5 .height = 972, .hoffset = 0, .voffset = 0, .hts = 1128, //Horizontal total size 1852 (unit pclk) .vts = 1200, //Vertical total size 0x1f8 (unit line) .pclk = 46.5*MHZ, .mipi_bps = 1296*972*10*30, .fps_fixed = 30, //fps = camera_clk /(hts * vts) .bin_factor = 1, .intg_min = 16, .intg_max = (1984-4)<<4, .gain_min = 1<<4, .gain_max = 64<<4, .regs = ov5647_rpi3, .regs_size = ARRAY_SIZE(ov5647_rpi3), .set_size = NULL, }, };
static struct regval_list ov5647_rpi3[] = { {0x3000, 0x0F}, {0x3001, 0xFF}, {0x3002, 0xE4}, {0x4800, 0x25}, {0x4202, 0x0F}, {0x300D, 0x01}, {0x0100, 0x00}, {0x0103, 0x01}, {0x3034, 0x1A}, {0x3035, 0x32}, {0x3036, 0x62}, {0x303C, 0x11}, {0x3106, 0xF5}, {0x3827, 0xEC}, {0x370C, 0x03}, {0x3612, 0x59}, {0x3618, 0x00}, {0x5000, 0x06}, //???? //0b01101100 001010000 000000100 010000010 // 6C 50 04 82 {0x5004, 0x82}, {0x5003, 0x08}, {0x5A00, 0x08}, {0x3000, 0x00}, {0x3001, 0x00}, {0x3002, 0x00}, {0x3016, 0x08}, {0x3017, 0xE0}, {0x3018, 0x44}, {0x301C, 0xF8}, {0x301D, 0xF0}, {0x3A18, 0x00}, {0x3A19, 0xF8}, {0x3C01, 0x80}, {0x3B07, 0x0C}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x00}, {0x3804, 0x0A}, {0x3805, 0x3F}, {0x3806, 0x07}, {0x3807, 0xA3}, {0x3808, 0x07}, {0x3809, 0xA3}, {0x380A, 0x03}, {0x380B, 0xCC}, {0x380C, 0x07}, {0x380D, 0x68}, {0x3811, 0x0C}, {0x3813, 0x06}, {0x3814, 0x31}, {0x3815, 0x31}, {0x3630, 0x2E}, {0x3632, 0xE2}, {0x3633, 0x23}, {0x3634, 0x44}, {0x3636, 0x06}, {0x3621, 0xE0}, {0x3600, 0x37}, {0x3704, 0xA0}, {0x3703, 0x5A}, {0x3715, 0x78}, {0x3717, 0x01}, {0x370B, 0x60}, {0x3705, 0x1A}, {0x3F05, 0x02}, {0x3F06, 0x10}, {0x3F01, 0x0A}, {0x3A08, 0x01}, {0x3A09, 0x28}, {0x3A0A, 0x00}, {0x3A0B, 0xF6}, {0x3A0D, 0x08}, {0x3A0E, 0x06}, {0x3A0F, 0x58}, {0x3A10, 0x50}, {0x3A1B, 0x58}, {0x3A1E, 0x50}, {0x3A11, 0x60}, {0x3A1F, 0x28}, {0x4001, 0x02}, {0x4004, 0x04}, {0x4000, 0x09}, {REG_DLY,70}, //wait 70ms {0x3500, 0x00}, //exposure {0x3501, 0x59}, {0x3502, 0x70}, {0x350A, 0x00}, //AGC {0x350B, 0x80}, {REG_DLY, 500}, {0x4800, 0x25}, {0x4202, 0x0F}, {0x300D, 0x01}, {0x3000, 0x00}, {0x3001, 0x00}, {0x3002, 0x00}, {0x0100, 0x00}, };
所有数据均正确读回
在 rpi 3 上,相机工作正常,因此相机没有任何问题。
我对 mipi 通道进行了连续性测试,所有通道都正确连接到处理器焊盘,因此没有焊接错误。 走线的阻抗应该足够好,能够像在 rpi 3 上一样工作,即使将飞线测试引线焊接到通道上也是如此。
我尝试了许多不同的配置、DTS、.fex、驱动程序的更改,无论我更改什么,我总是得到相同的结果。 对我来说,没有比这更好的调试方法了。 我已经订购了 yuzukilizard 板来尝试比较该板上的 mipi 信号并使用相机适配器测试我的代码,但这需要一些时间才能到达。
目前,我真的没有任何想法来使这个工作......如果我找不到这个驱动程序有什么问题,我可能会完全改变平台,因为对 V851S 的支持似乎非常有限。
MLCK 没有连接,因为 rpi 相机板上有一个内部时钟振荡器,并且它们的 MLCK 没有断开。
相机已正确开机并正确响应所有 i2c 命令。 -
请注意,对于上一篇带有图片的文章,有 4 层,因此 mipi 信号通过完整的接地层路由,具有正确的阻抗
-
使用 V3s SDK 提供VFE框架的驱动移植到VIN框架下抓图成功。但是图像非常暗,并且撕裂,抓raw数据查看也是一样,考虑可能mclk不同步导致。
sensor0:sensor@0 { device_type = "sensor0"; sensor0_mname = "ov5648_mipi"; sensor0_twi_cci_id = <0>; 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 = <>; sensor0_iovdd_vol = <1800000>; sensor0_avdd-supply = <>; sensor0_avdd_vol = <2800000>; sensor0_dvdd-supply = <>; sensor0_dvdd_vol = <1200000>; sensor0_power_en = <>; sensor0_reset = <&pio PA 18 1 0 1 0>; sensor0_pwdn = <&pio PA 19 1 0 1 0>; sensor0_sm_hs = <>; sensor0_sm_vs = <>; flash_handle = <>; act_handle = <>; status = "okay"; };
/* * A V4L2 driver for ov5647 Raw cameras. * * Copyright (c) 2022 by YuzukiTsuru <gloomyghost@gloomyghost.com> * Copyright (c) 2018 by Allwinnertech Co., Ltd. http://www.allwinnertech.com * * Authors: Zheng ZeQun <zequnzheng@allwinnertech.com> * Liang WeiJie <liangweijie@allwinnertech.com> * YuzukiTsuru <gloomyghost@gloomyghost.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. */ #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("YuzukiTsuru"); MODULE_DESCRIPTION("A low-level driver for ov5647 sensors"); MODULE_LICENSE("GPL"); #define MCLK (24*1000*1000) #define V4L2_IDENT_SENSOR 0x5648 /* * Our nominal (default) frame rate. */ #define SENSOR_FRAME_RATE 30 /* * The GC0310 i2c address */ #define I2C_ADDR 0x6c #define SENSOR_NAME "ov5648_mipi" /* * The default register settings */ static struct regval_list sensor_default_regs[] = { //Slave_ID=0x6c; {0x0100, 0x00},// ; software standby {0x0103, 0x01},// ; software reset {REG_DLY, 0x25}, {0x370c, 0x03},// ; analog control {0x5000, 0x06},// ; lens off, bpc on, wpc on {0x5003, 0x08},// ; buf_en {0x5a00, 0x08},// {0x3000, 0xff},// ; D[9:8] output {0x3001, 0xff},// ; D[7:0] output {0x3002, 0xff},// ; Vsync, Href, PCLK, Frex, Strobe, SDA, GPIO1, GPIO0 output {0x301d, 0xf0},// {0x3a18, 0x00},// ; gain ceiling = 15.5x {0x3a19, 0xf8},// ; gain ceiling {0x3c01, 0x80},// ; band detection manual mode {0x3b07, 0x0c},// ; strobe frex mode //; analog control {0x3630, 0x2e}, {0x3632, 0xe2}, {0x3633, 0x23}, {0x3634, 0x44}, {0x3620, 0x64}, {0x3621, 0xe0}, {0x3600, 0x37}, {0x3704, 0xa0}, {0x3703, 0x5a}, {0x3715, 0x78}, {0x3717, 0x01}, {0x3731, 0x02}, {0x370b, 0x60}, {0x3705, 0x1a}, {0x3f05, 0x02}, {0x3f06, 0x10}, {0x3f01, 0x0a}, //; AG/AE target {0x3a0f, 0x58},// ; stable in high {0x3a10, 0x50},// ; stable in low {0x3a1b, 0x58},// ; stable out high {0x3a1e, 0x50},// ; stable out low {0x3a11, 0x60},// ; fast zone high {0x3a1f, 0x28},// ; fast zone low {0x4001, 0x02},// ; BLC start line {0x4000, 0x09},// ; BLC enable {0x3000, 0x00},// ; D[9:8] input {0x3001, 0x00},// ; D[7:0] input {0x3002, 0x00},// ; Vsync, Href, PCLK, Frex, Strobe, SDA, GPIO1, GPIO0 input {0x3017, 0xe0},// ; MIPI PHY {0x301c, 0xfc},// {0x3636, 0x06},// ; analog control {0x3016, 0x08},// ; MIPI pad enable {0x3827, 0xec},// {0x3018, 0x44},// ; MIPI 2 lane, MIPI enable {0x3035, 0x21},// ; PLL {0x3106, 0xf5},// ; PLL {0x3034, 0x1a},// ; PLL {0x301c, 0xf8},// {0x3503, 0x03},// ; Gain has no latch delay, AGC manual, AEC {0x3501, 0x10},// ; exposure[15:8] {0x3502, 0x80},// ; exposure[7:0] {0x350a, 0x00},// ; gain[9:8] {0x350b, 0x7f},// ; gain[7:0] {0x5001, 0x01},// ; AWB on {0x5180, 0x08},// ; AWB manual gain enable {0x5186, 0x04},// ; manual red gain high {0x5187, 0x00},// ; manual red gain low {0x5188, 0x04},// ; manual green gain high {0x5189, 0x00},// ; manual green gain low {0x518a, 0x04},// ; manual blue gain high {0x518b, 0x00},// ; manual blue gain low {0x5000, 0x06},// ; lenc off, bpc on, wpc on }; static struct regval_list sensor_qsxga_regs[] = { //qsxga: 2592*1936@15fps {0x0100, 0x00},// ; software standby {0x3035, 0x21},// ; PLL {0x3036, 0x66},// ; PLL {0x303c, 0x11},// ; PLL {0x3821, 0x06},// ; ISP mirror on, Sensor mirror on {0x3820, 0x00},// ; ISP flip off, Sensor flip off {0x3612, 0x5b},// ; analog control {0x3618, 0x04},// ; analog control {0x380c, 0x0a},// ; HTS = 2752 {0x380d, 0xc0},// ; HTS {0x380e, 0x07},// ; VTS = 1974 {0x380f, 0xb6},// ; VTS {0x3814, 0x11},// ; X INC {0x3815, 0x11},// ; X INC {0x3708, 0x64},// ; analog control {0x3709, 0x12},// ; analog control {0x3808, 0x0a},// ; X OUTPUT SIZE = 2592 {0x3809, 0x20},// ; X OUTPUT SIZE {0x380a, 0x07},// ; Y OUTPUT SIZE = 1944 {0x380b, 0x98},// ; Y OUTPUT SIZE {0x3800, 0x00},// ; X Start {0x3801, 0x0c},// ; X Start {0x3802, 0x00},// ; Y Start {0x3803, 0x02},// ; Y Start {0x3804, 0x0a},// ; X End {0x3805, 0x33},// ; X End {0x3806, 0x07},// ; Y End {0x3807, 0xa1},// ; Y End ///////////; Banding filter {0x3a08, 0x01},// ; B50 {0x3a09, 0x28},// ; B50 {0x3a0a, 0x00},// ; B60 {0x3a0b, 0xf6},// ; B60 {0x3a0d, 0x07},// ; B60 max {0x3a0e, 0x06},// ; B50 max {0x4004, 0x04},// ; black line number {0x4837, 0x19},// ; MIPI pclk period {0x0100, 0x01},// ; wake up from software standby }; static struct regval_list sensor_720p_regs[] = { //720: 1280*720@30fps {0x0100, 0x00},// ; software standby {0x3035, 0x21},// ; PLL {0x3036, 0x46},// ; PLL {0x303c, 0x11},// ; PLL {0x3821, 0x07},// ; ISP mirror on, Sensor mirror on, bin on {0x3820, 0x41},// ; ISP flip off, Sensor flip off, bin on {0x3612, 0x59},// ; analog control {0x3618, 0x00},// ; analog control {0x380c, 0x07},// ; HTS = 1896 {0x380d, 0x68},// ; HTS {0x380e, 0x03},// ; VTS = 984 {0x380f, 0xd8},// ; VTS {0x3814, 0x31},// ; X INC {0x3815, 0x31},// ; Y INC {0x3708, 0x64},// ; analog control {0x3709, 0x52},// ; analog control {0x3808, 0x05},// ; X OUTPUT SIZE = 1280 {0x3809, 0x00},// ; X OUTPUT SIZE {0x380a, 0x03},// ; Y OUTPUT SIZE = 960 {0x380b, 0xc0},// ; Y OUTPUT SIZE {0x3800, 0x00},// ; X Start {0x3801, 0x18},// ; X Start {0x3802, 0x00},// ; Y Start {0x3803, 0x0e},// ; Y Start {0x3804, 0x0a},// ; X End {0x3805, 0x27},// ; X End {0x3806, 0x07},// ; Y End {0x3807, 0x95},// ; Y End // banding filter {0x3a08, 0x01},// ; B50 {0x3a09, 0x27},// ; B50 {0x3a0a, 0x00},// ; B60 {0x3a0b, 0xf6},// ; B60 {0x3a0d, 0x04},// ; B50 max {0x3a0e, 0x03},// ; B60 max {0x4004, 0x02},// ; black line number {0x4837, 0x24},// ; MIPI pclk period {0x0100, 0x01},// ; wake up from software standby }; 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_print("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; sensor_write(sd, 0x3208, 0x00);//enter group write sensor_write(sd, 0x3503, 0x13); exphigh = (unsigned char) ( (0x0f0000&exp_val)>>16); expmid = (unsigned char) ( (0x00ff00&exp_val)>>8); explow = (unsigned char) ( (0x0000ff&exp_val) ); //sensor_write(sd, 0x3208, 0x00);//enter group write 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 sensor_print("ov5647_mipi sensor_set_exp = %d, Done!\n", exp_val); 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_print("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, 0x3208, 0x00);//enter group write sensor_write(sd, 0x3503, 0x13); sensor_write(sd, 0x350b, gainlow); sensor_write(sd, 0x350a, gainhigh); sensor_write(sd, 0x3208, 0x10);//end group write sensor_write(sd, 0x3208, 0xa0);//init group write //printk("ov5647_mipi sensor_set_gain = %d, Done!\n", gain_val); info->gain = gain_val; return 0; } static int ov5648_sensor_vts; 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,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; sensor_print("ov5648_sensor_vts = %d\n",ov5648_sensor_vts); if(shutter > ov5648_sensor_vts- 4) frame_length = shutter + 4; else frame_length = ov5648_sensor_vts; sensor_write(sd, 0x3503, 0x07); sensor_write(sd, 0x380f, (frame_length & 0xff)); sensor_write(sd, 0x380e, (frame_length >> 8)); sensor_print("exp_val = %d,gain_val = %d\n",exp_val,gain_val); sensor_write(sd, 0x3208, 0x00);//enter group write 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; sensor_print("ov5648 sensor_power\n"); switch (on) { case STBY_ON: 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("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("PWR_ON!100\n"); cci_lock(sd); vin_gpio_set_status(sd, PWDN, 1); vin_gpio_write(sd, RESET, CSI_GPIO_HIGH); vin_gpio_set_status(sd, POWER_EN, 1); vin_gpio_write(sd, PWDN, CSI_GPIO_LOW); vin_gpio_write(sd, RESET, CSI_GPIO_LOW); 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); 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_HIGH); 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); 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; 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; } static int sensor_init(struct v4l2_subdev *sd, u32 val) { 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) { sensor_err("chip found is not an target chip.\n"); return ret; } info->focus_status = 0; info->low_speed = 0; info->width = QSXGA_WIDTH; info->height = QSXGA_HEIGHT; 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[] = { { .width = QSXGA_WIDTH, .height = QSXGA_HEIGHT, .hoffset = 0, .voffset = 4, .hts = 2752, .vts = 1974, .pclk = 81486720, .mipi_bps = 408*1000*1000, .fps_fixed = 2, .bin_factor = 1, .intg_min = 1, .intg_max = (1974)<<4, .gain_min = 1<<4, .gain_max = 12<<4, .regs = sensor_qsxga_regs, .regs_size = ARRAY_SIZE(sensor_qsxga_regs), .set_size = NULL, }, { .width = HD720_WIDTH, .height = HD720_HEIGHT, .hoffset = 0, .voffset = 120, .hts = 1896, .vts = 984, .pclk = 56*1000*1000, .mipi_bps = 280*1000*1000, .fps_fixed = 1, .bin_factor = 1, .intg_min = 1, .intg_max = 984<<4, .gain_min = 1<<4, .gain_max = 12<<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; 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; ov5648_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; 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; 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);
另外建议使用支持列表中的摄像头,例如gc2053,gc2063,这些摄像头已经适配量产完成并且调整ISP后画质更佳,也支持aiisp实现低照度全彩画质,树莓派的摄像头不推荐使用,因为他是外挂mclk的会引起芯片处于错误的模式,另外原厂也没有相应的支持(2017年前的芯片才有这个支持)
IMX219 同样可以使用,但是请注意4lane的摄像头不可适配2lane的数据
-
@awwwwa 我已经研究过 @YuzukiTsuru 制作的这个特定驱动程序,它存在一些问题:
- 未正确配置与 OV5647 的接口,V4L2_IDENT_SENSOR 不正确,因为它是 0x5648 而不是 0x5647,如果按原样使用,则永远不会检测到相机,因为在sensor_detect() 中进行了此检查:
#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; }
- 驱动程序将其传感器报告为“ov5648_mipi”,如果您将相同的内容放入 DTS 中,这并不是什么大问题,但它仍然具有误导性。
#define SENSOR_NAME "ov5648_mipi"
一旦这些基本问题得到解决,驱动程序就会加载并创建 /dev/video 节点,就像我的驱动程序一样。 但我们最终在camerademo应用程序上遇到了完全相同的错误:
唯一的区别是由于缺少配置文件而导致 ISP 上出现一些错误行,但由于我们的错误与超时相关,因此它不应受到任何“像素格式”或 ISP 错误的影响。 因此,即使有了这个驱动程序,我们还是回到了原点。我想知道 MLCK 位于相机内部并且未连接到 V851S 是否会导致问题...
-
@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:/#
-
这是执行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 重要
-
我发现 allwinner 提供的文档之一在常见问题解答中提供了有关我所面临的确切问题的信息。 所以我现在会尝试按照其中的说明进行操作。 我似乎需要 mipi 寄存器偏移量才能正确调试,但他们不为 V851S 提供这些偏移量,只为其他芯片提供这些偏移量,而且我在芯片的数据表中没有找到它们,知道我可以从哪里获得它们吗?
-
@kanken6174 在 V851S tina linux ov5647 驱动程序没有 dmesg 中说:
相机加电,所以它永远找不到它
你好,我看了下你移植的 ov5647 sensor驱动过程。首先你是想基于ov5648 sensor驱动自己修改出来5647的驱动来尝试移植,如果按照已有的5648驱动框架来修改适配的话,应该是难度不大的。我看你上面已经i2c识别到了sensor,但是你用camera demo没有出图,log上面有提示是你camerademo出图的640*480?但你驱动里面只有720p和另一个分辨率,如果需要支持这个分辨率,需要用到你后面说的那一堆初始化寄存器,这个寄存器不建议自己一个个尝试得出来,最好找一份你买sensor的支持,要一份初始化参数过来,替换ov5648的初始化参数,然后你驱动里面配置的line什么的应该也没错,能成功识别到sensor上电时序和pwdn也都对,猜测没点亮重点在初始化参数的配置。我看你参考的文档,移植的应该是linux平台的驱动不是快起的,你可以参考这篇博客的流程,然后根据ov5648的驱动框架移植,希望对你有帮助
https://blog.csdn.net/weixin_45349811/article/details/132707827
-
@kanken6174 R853的偏移量可以用到V851上
-
@whycanservice 谢谢,这对调试很有用
-
@spr2023 谢谢,我将阅读这篇文章,尝试看看他们做了什么不同的事情。 请注意,分辨率不是camerademo的问题,就好像640x480不可用一样,它将使用它可以使用的第一个分辨率,在我的例子中是1296x972,这是树莓派3运行这些相机的标准分辨率。 我使用的寄存器正是树莓派针对该特定分辨率发送的寄存器。 我尝试了许多不同的分辨率和寄存器配置,但总是出现相同的超时错误,我什至尝试使用主线 OV5647 驱动程序 (https://github.com/torvalds/linux/blob/master/drivers/media/i2c/ov5647.c) 中的寄存器和配置。
我的驱动程序的基础已经是 ov5648 驱动程序,只是修改了开机顺序(我的相机所需)和寄存器/配置。 -
我发现了我的问题,我非常讨厌它......普遍的愚蠢
-
修复了翻转的通道并纠正了一些混乱的寄存器后,它起作用了! 最后! 感谢大家的帮助! 现在我必须正确设置 ISP 才能查看生成的 RAW 文件,但这已经是向前迈出的一大步了 ^^
-
我这里还有imx219的imx219.c ov5647_mipi.c ,你有ISP调试环境吗?灯箱色卡之类的
-
@zheng1 我确实没有正确的设置来调试芯片内的 Tiger ISP,但如果需要,我可以设置一个。 但现在校准颜色并不是我的主要问题,因为相机似乎仍然无法正常运行,看看这张捕获的“图像”:
我的大部分颜色是黑色,顶部有一点数据,该图像是使用 TigerISP 应用程序从 RAW 格式提取的。 我真的不确定这里可能出了什么问题,这不可能是曝光,因为我直接在相机上闪光,而没有对图像进行任何更改,并且由于数据是在单个 MIPI 通道上发送的,所以应该 不可能是时间问题吧?我将等待我的主板版本 2 修复 mipi 通道,看看这是否对官方驱动程序有帮助。 开发文档的常见问题解答并未涵盖这种特定情况,因此我现在只能尝试更改相机内的配置......
-
@kanken6174 camerademo抓图正常吗?如果camerademo抓图正常,那就是Tiger ISP的配置问题了。先确保camerademo能抓到正确的图
-
@zheng1 在 V851S tina linux ov5647 驱动程序没有 dmesg 中说:
@kanken6174 camerademo抓图正常吗?如果camerademo抓图正常,那就是Tiger ISP的配置问题了。先确保camerademo能抓到正确的图
我的平台camerademo能抓图了
Tiger ISP怎么调呢 -
@mysteryli 你有灯箱色卡之类的吗,没有的话建议直接放弃。有的话可以加个好友研究下
-
此回复已被删除! -
@kanken6174 我在v851s平台移植sensor驱动的话,成功点亮sensor的话,就算isp没有调试正确的效果文件,也应该会出图,颜色什么的不正常也不会全黑的才对
-
@zheng1 那没有,放弃了,谢谢劝谏
-
@kanken6174 请问你是否已经成功让v851s支持ov5647?
另外,请教各位,Linux主线已经包含了对ov5647支持,可以通过在v851s上运行主线来支持ov5647 吗?
Tina Linux 基于5.4内核的SDK也包含了ov5647 的驱动,有人试过吗?
-
@allspace123 不,我没有,我得到的只是黑屏和几条绿线,我放弃了并使用了 GC2053。 我也几乎放弃了 V851S 作为 mipi-csi 转 USB 平台,因为我无法让视频编码器工作,尽管社区已经以某种方式使其能够在 V851SE 上工作。 没有办法获得V851SE芯片,所以我的项目目前陷入困境。
您可以在此 github 页面上找到我对驱动程序的失败尝试。
https://github.com/Kanken6174/V851S-OV5647 -
@kanken6174 谢谢,哪里可以找到让v851se工作的方法?理论上,除了ephy部分,v851s应该和v851se是一样的。
Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号