Loading src/drivers/elphel/mt9f002.c +139 −90 Original line number Diff line number Diff line Loading @@ -51,6 +51,9 @@ #include "sensor_i2c.h" //#include "detect_sensors.h" // hact timeout in udelay(100)s #define HACT_TIMEOUT 8192 /** LUT to map SENSOR_REGSxxx to internal sensor register addresses * needed for any sensor Loading @@ -70,6 +73,15 @@ const unsigned short mt9f002_par2addr[] = { P_MT9F002_GAINR, P_REG_MT9F002_ANALOG_GAIN_CODE_RED, P_MT9F002_GAINB, P_REG_MT9F002_ANALOG_GAIN_CODE_BLUE, P_MT9F002_GAINGB, P_REG_MT9F002_ANALOG_GAIN_CODE_GREENB, P_MT9F002_HISPI_TIMING, P_REG_MT9F002_HISPI_TIMING, P_MT9F002_SMIA_PLL_MULTIPLIER, P_REG_MT9F002_SMIA_PLL_MULTIPLIER, P_MT9F002_HISPI_CONTROL_STATUS, P_REG_MT9F002_HISPI_CONTROL_STATUS, P_MT9F002_DATAPATH_SELECT, P_REG_MT9F002_DATAPATH_SELECT, P_MT9F002_RESET_REGISTER, P_REG_MT9F002_RESET_REGISTER, P_MT9F002_ANALOG_GAIN_CODE_GLOBAL, P_REG_MT9F002_ANALOG_GAIN_CODE_GLOBAL, P_MT9F002_ANALOG_GAIN_CODE_RED, P_REG_MT9F002_ANALOG_GAIN_CODE_RED, P_MT9F002_ANALOG_GAIN_CODE_BLUE, P_REG_MT9F002_ANALOG_GAIN_CODE_BLUE, P_MT9F002_COARSE_INTEGRATION_TIME, P_REG_MT9F002_COARSE_INTEGRATION_TIME, 0xffff // END indicator }; Loading Loading @@ -164,15 +176,16 @@ static bool init_done[4] = {false,false,false,false}; /** Initial register writes for MT9F002 */ static unsigned short mt9f002_inits[]= { P_REG_MT9F002_HISPI_TIMING, 0x8000, // P_REG_MT9F002_SMIA_PLL_MULTIPLIER, 0x00b4, // P_REG_MT9F002_HISPI_CONTROL_STATUS, 0x8400, // P_REG_MT9F002_DATAPATH_SELECT, 0x9280, // P_REG_MT9F002_RESET_REGISTER, 0x001c, P_REG_MT9F002_ANALOG_GAIN_CODE_GLOBAL, 0x000a, P_REG_MT9F002_ANALOG_GAIN_CODE_RED, 0x000d, P_REG_MT9F002_ANALOG_GAIN_CODE_BLUE, 0x0010, P_REG_MT9F002_COARSE_INTEGRATION_TIME, 0x0060 P_MT9F002_HISPI_TIMING, 0x8000, // P_MT9F002_SMIA_PLL_MULTIPLIER, 0x00b4, // P_MT9F002_HISPI_CONTROL_STATUS, 0x8400, // P_MT9F002_DATAPATH_SELECT, 0x9280, // P_MT9F002_RESET_REGISTER, 0x001c, //P_MT9F002_TEST_PATTERN, 0x0002, // color bars P_MT9F002_ANALOG_GAIN_CODE_GLOBAL, 0x000a, P_MT9F002_ANALOG_GAIN_CODE_RED, 0x000d, P_MT9F002_ANALOG_GAIN_CODE_BLUE, 0x0010, P_MT9F002_COARSE_INTEGRATION_TIME, 0x0100 }; /** Specifying sensor registers to be controlled individually in multi-sensor applications, MT9P006 */ Loading Loading @@ -281,7 +294,7 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port x393_sensio_ctrl(sensio_ctl,sensor_port); // what's this? commented out and it still works. 2018/02/13 //udelay(50); // is it needed? udelay(50); // is it needed? X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_REG_MT9F002_MODEL_ID, &i2c_read_dataw); dev_dbg(g_dev_ptr,"Read i2c (port = %d, sa7=0x%lx, reg=0x%x) chip ID=%x\n",sensor_port, psensor->i2c_addr, P_REG_MT9F002_MODEL_ID, i2c_read_dataw); Loading Loading @@ -330,35 +343,47 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port int mt9f002_phases_program_phase(int sensor_port, int phase){ int i; int read_phase; int read_phase = 0x5555; struct sensor_port_config_t *pcfg; const char *name; int wr_full; pcfg = &pSensorPortConfig[sensor_port]; name = get_name_by_code(pcfg->sensor[0],DETECT_SENSOR); x393_xi2c_write_reg(name,sensor_port,0,P_REG_MT9F002_HISPI_TIMING,phase); //x393_xi2c_write_reg(name,sensor_port,0,P_REG_MT9F002_HISPI_TIMING,phase); // sa7 is not used anymore for(i=0;i<32;i++){ wr_full = x393_xi2c_ready_wr(sensor_port); if (wr_full==0){ pr_err("{%d} I2C sequencer is FULL1 for target 0x%04x\n",sensor_port,phase); } x393_xi2c_read_reg(name,sensor_port,0,P_REG_MT9F002_HISPI_TIMING,&read_phase); X3X3_I2C_SEND2_ASAP(sensor_port,0x0,P_MT9F002_HISPI_TIMING,phase); x393_xi2c_wait_wr(sensor_port); if (read_phase!=phase){ pr_err("{%d} write error, target value = 0x%04x, read value = 0x%04x \n",sensor_port,read_phase,phase); // write retry if ((i&0x7)==0) { x393_xi2c_write_reg(name,sensor_port,0,P_REG_MT9F002_HISPI_TIMING,phase); for(i=0;i<32;i++){ wr_full = x393_xi2c_ready_wr(sensor_port); if (wr_full==0){ pr_err("{%d} I2C sequencer is FULL2 for target 0x%04x\n",sensor_port,phase); } }else{ X3X3_I2C_RCV2(sensor_port, 0x10, P_REG_MT9F002_HISPI_TIMING, &read_phase); if (read_phase==phase){ break; } // i2c is slow udelay(1000); pr_err("{%d} write error, target value = 0x%04x, read value = 0x%04x \n",sensor_port,phase,read_phase); // write retry if ((i&0x7)==0x7) { pr_err("{%d} write retry: 0x%04x\n",sensor_port,phase); X3X3_I2C_SEND2_ASAP(sensor_port,0x0,P_MT9F002_HISPI_TIMING,phase); x393_xi2c_wait_wr(sensor_port); } udelay(100); } return 0; } int mt9f002_phases_read_flags(int sensor_port,int shift){ Loading @@ -372,16 +397,16 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){ set_x393_sensio_tim2(reset_flags,sensor_port); // wait for hact for(i=0;i<4000;i++){ for(i=0;i<HACT_TIMEOUT;i++){ status = x393_sensio_status(sensor_port); if (status.hact_alive){ if (i>1) dev_dbg(g_dev_ptr,"{%d} hact recovered after %d\n",sensor_port,i); //if (i>1) dev_dbg(g_dev_ptr,"{%d} hact recovered after %d\n",sensor_port,i); break; } udelay(100); if (i==3999){ if (i==(HACT_TIMEOUT-1)){ dev_dbg(g_dev_ptr,"{%d} hact never went up after reset\n",sensor_port); } udelay(100); } // read flags Loading @@ -398,7 +423,7 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){ } int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift, int result[]){ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){ int i,j; int status; Loading @@ -406,16 +431,16 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift, int result[] int value = 0; bool switched = false; int start = 0; int count = 0; // i where switched, 1 - first 8 steps, 2 - second 8 steps int i1 = 0; int i2 = 0;//8 int im = 0; int old_phase = phase; int target_phase; int read_phase; int s[16]; pr_info("{%d} Base phase: 0x%04x\n",sensor_port,phase); // 16 values: 8 for CLK phase 0 position CLK, 8 - for CLK phase 4 position for(i=0;i<16;i++){ Loading @@ -428,56 +453,60 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift, int result[] phase -= clk_half_phase; } // set phase target_phase = phase + ((i&0x7)<<(3*shift)); mt9f002_phases_program_phase(sensor_port,target_phase); old_phase = target_phase; // read status status = mt9f002_phases_read_flags(sensor_port,shift); s[i] = status; if (i==0){ if ((i==0)||(i==8)){ value = status; count = 1; } if (i==8){ if (!switched){ start = 0; count = i; }else{ switched = false; } } if ((i<8)&&(i!=0)){ }else{ if (value!=status){ if (i<8){ if (!switched){ switched = true; value = status; i1 = i; }else{ pr_err("{%d} Unexpected phase shift at %d",sensor_port,i); } }else{ if (!switched){ count += 1; switched = true; value = status; i2 = i; }else{ pr_err("{%d} Unexpected phase shift at %d",sensor_port,i); } } } if (i>=8){ if (value==status){ count += 1; } } dev_dbg(g_dev_ptr,"%d %d %d %d %d %d %d %d | %d %d %d %d %d %d %d %d\n",s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8],s[9],s[10],s[11],s[12],s[13],s[14],s[15]); dev_dbg(g_dev_ptr,"i1 = %d, i2 = %d\n",i1,i2); //i2 = i2&0x7; /* if (i2<i1){ i2 += 8; } */ im = ((i1+i2)>>1)&0x7; //im = (i2-4)&0x7; pr_info("%d %d %d %d %d %d %d %d | %d %d %d %d %d %d %d %d\n",s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8],s[9],s[10],s[11],s[12],s[13],s[14],s[15]); pr_info("start = %d, count = %d\n",start,count); target_phase = phase + (im<<(3*shift)); result[0] = start; result[1] = count; dev_dbg(g_dev_ptr,"mid phase: %d (target phase = 0x%04x)",im,target_phase); return 0; // apply center phase mt9f002_phases_program_phase(sensor_port,target_phase); return target_phase; } int mt9f002_phases_adjust(int sensor_port){ Loading @@ -493,7 +522,6 @@ int mt9f002_phases_adjust(int sensor_port){ int phase = 0x8000; int i; int result[2]; x393_status_sens_io_t status; // read it first ? Loading @@ -506,34 +534,31 @@ int mt9f002_phases_adjust(int sensor_port){ set_x393_sensio_status_cntrl(status_ctrl, sensor_port); // wait for hact (usually alive after 254) for(i=0;i<1024;i++){ for(i=0;i<HACT_TIMEOUT;i++){ status = x393_sensio_status(sensor_port); if (status.hact_alive){ dev_dbg(g_dev_ptr,"{%d} HACT alive at %d\n",sensor_port,i); //dev_dbg(g_dev_ptr,"{%d} HACT alive at %d\n",sensor_port,i); break; } if (i==(HACT_TIMEOUT-1)){ dev_dbg(g_dev_ptr,"{%d} HACT never went live\n",sensor_port); } udelay(100); } // 4 data lanes - prior knowledge for(i=0;i<4;i++){ mt9f002_phases_scan_lane(sensor_port,phase,i,result); // &0x7 = %8 phase += ((result[0]+(result[1]>>1))&0x7)<<(3*i); if (result[1]<2){ dev_dbg(g_dev_ptr,"{%d} Error scanning D%d lane, count=%d\n",sensor_port,i,result[1]); } phase = mt9f002_phases_scan_lane(sensor_port,phase,i); } dev_dbg(g_dev_ptr,"{%d} Adjusted phase is 0x%04x\n",sensor_port,phase); // apply final phase mt9f002_phases_program_phase(sensor_port,phase); //mt9f002_phases_program_phase(sensor_port,phase,0,false); // disable status updates status_ctrl.mode = 0x0; set_x393_sensio_status_cntrl(status_ctrl, sensor_port); //status_ctrl.mode = 0x0; //set_x393_sensio_status_cntrl(status_ctrl, sensor_port); return 0; } Loading Loading @@ -569,18 +594,24 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port for(i=0;i<n;i++){ haddr = (mt9f002_inits[2*i]>>8)&0xff; laddr = mt9f002_inits[2*i]&0xff; data = mt9f002_inits[2*i+1]; page = pSensorPortConfig[sensor_port].haddr2rec[0][haddr]; //haddr = (mt9f002_inits[2*i]>>8)&0xff; //laddr = mt9f002_inits[2*i]&0xff; //data = mt9f002_inits[2*i+1]; //page = pSensorPortConfig[sensor_port].haddr2rec[0][haddr]; // write immediately //dev_dbg(g_dev_ptr,"{%d} init sensor: writing 0x%04x to register 0x%02x%02x\n",sensor_port,data,haddr,laddr); write_xi2c_reg16(sensor_port,page,laddr,data); //write_xi2c_reg16(sensor_port,page,laddr,data); X3X3_I2C_SEND2_ASAP(sensor_port,sensor->i2c_addr,mt9f002_inits[2*i],mt9f002_inits[2*i+1]); } // sensor is supposed to be streaming by now mt9f002_phases_adjust(sensor_port); // extra reset? //X3X3_I2C_SEND2_ASAP(sensor_port,sensor->i2c_addr,P_MT9F002_RESET_REGISTER,0x001c); // init register shadows here return 0; Loading Loading @@ -654,12 +685,29 @@ static ssize_t store_debug_modes(struct device *dev, struct device_attribute *at return count; } static ssize_t show_status_flags(struct device *dev, struct device_attribute *attr, char *buf) { int i,j; int s[16]; for(i=0;i<4;i++){ for(j=0;j<4;j++){ s[4*i+j] = mt9f002_phases_read_flags(i,j); } } return sprintf(buf,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8],s[9],s[10],s[11],s[12],s[13],s[14],s[15]); } static DEVICE_ATTR(sensor_regs0, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs); static DEVICE_ATTR(sensor_regs1, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs); static DEVICE_ATTR(sensor_regs2, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs); static DEVICE_ATTR(sensor_regs3, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs); static DEVICE_ATTR(debug_delays, SYSFS_PERMISSIONS, show_debug_delays, store_debug_delays); static DEVICE_ATTR(debug_modes, SYSFS_PERMISSIONS, show_debug_modes, store_debug_modes); static DEVICE_ATTR(frame_status, SYSFS_PERMISSIONS, show_status_flags, NULL); static struct attribute *root_dev_attrs[] = { &dev_attr_sensor_regs0.attr, Loading @@ -668,6 +716,7 @@ static struct attribute *root_dev_attrs[] = { &dev_attr_sensor_regs3.attr, &dev_attr_debug_delays.attr, &dev_attr_debug_modes.attr, &dev_attr_frame_status.attr, NULL }; Loading Loading @@ -711,7 +760,7 @@ int mt9f002_remove(struct platform_device *pdev) // TODO: add elphel,elphel393-mt9f002-1.00 to device tree static const struct of_device_id elphel393_mt9f002_of_match[] = { { .compatible = "elphel,elphel393-mt9x001-1.00" }, { .compatible = "elphel,elphel393-mt9f002-1.00" }, { /* end of list */ } }; MODULE_DEVICE_TABLE(of, elphel393_mt9f002_of_match); Loading src/drivers/elphel/mt9f002.h +10 −0 Original line number Diff line number Diff line Loading @@ -544,6 +544,16 @@ #define P_MT9F002_TEST_PATTERN 10 #define P_MT9F002_HISPI_TIMING 11 #define P_MT9F002_SMIA_PLL_MULTIPLIER 12 #define P_MT9F002_HISPI_CONTROL_STATUS 13 #define P_MT9F002_DATAPATH_SELECT 14 #define P_MT9F002_RESET_REGISTER 15 #define P_MT9F002_ANALOG_GAIN_CODE_GLOBAL 16 #define P_MT9F002_ANALOG_GAIN_CODE_RED 17 #define P_MT9F002_ANALOG_GAIN_CODE_BLUE 18 #define P_MT9F002_COARSE_INTEGRATION_TIME 19 //#define P_REG(x) x //#define P_MT9F002_MODEL_ID 4 Loading src/drivers/elphel/mt9x001.c +1 −1 Original line number Diff line number Diff line Loading @@ -1175,7 +1175,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%0x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_ROWSTART,(int) wt); } ///TODO:Get rid of get_sensor_i2c_regs16 !!! // the fields that should not chnage in non-stop will not change, so it is OK to write them always // the fields that should not change in non-stop will not change, so it is OK to write them always if((styp == MT9T_TYP) || (styp == MT9P_TYP)) { // 3MPix and 5MPix sensors v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM] & 0xff88) | ((bv - 1) << 4) | (dv - 1) ; if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM]) { Loading src/drivers/elphel/pgm_functions.c +0 −2 Original line number Diff line number Diff line Loading @@ -379,8 +379,6 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number ( int i2cbytes; int mux,sens; pr_info("{%d} pgm_detectsensor\n",sensor_port); dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16); MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16) Loading src/drivers/elphel/sensor_common.c +1 −1 Original line number Diff line number Diff line Loading @@ -1223,7 +1223,7 @@ int register_i2c_sensor(int ports_mask) ///< bitmask of the sensor ports to use bool mux; pr_info("register_i2c_sensor()\n"); dev_dbg(g_dev_ptr,"register_i2c_sensor()\n"); for(port=0;port<SENSOR_PORTS;port++) if ((1<<port)&ports_mask) { Loading Loading
src/drivers/elphel/mt9f002.c +139 −90 Original line number Diff line number Diff line Loading @@ -51,6 +51,9 @@ #include "sensor_i2c.h" //#include "detect_sensors.h" // hact timeout in udelay(100)s #define HACT_TIMEOUT 8192 /** LUT to map SENSOR_REGSxxx to internal sensor register addresses * needed for any sensor Loading @@ -70,6 +73,15 @@ const unsigned short mt9f002_par2addr[] = { P_MT9F002_GAINR, P_REG_MT9F002_ANALOG_GAIN_CODE_RED, P_MT9F002_GAINB, P_REG_MT9F002_ANALOG_GAIN_CODE_BLUE, P_MT9F002_GAINGB, P_REG_MT9F002_ANALOG_GAIN_CODE_GREENB, P_MT9F002_HISPI_TIMING, P_REG_MT9F002_HISPI_TIMING, P_MT9F002_SMIA_PLL_MULTIPLIER, P_REG_MT9F002_SMIA_PLL_MULTIPLIER, P_MT9F002_HISPI_CONTROL_STATUS, P_REG_MT9F002_HISPI_CONTROL_STATUS, P_MT9F002_DATAPATH_SELECT, P_REG_MT9F002_DATAPATH_SELECT, P_MT9F002_RESET_REGISTER, P_REG_MT9F002_RESET_REGISTER, P_MT9F002_ANALOG_GAIN_CODE_GLOBAL, P_REG_MT9F002_ANALOG_GAIN_CODE_GLOBAL, P_MT9F002_ANALOG_GAIN_CODE_RED, P_REG_MT9F002_ANALOG_GAIN_CODE_RED, P_MT9F002_ANALOG_GAIN_CODE_BLUE, P_REG_MT9F002_ANALOG_GAIN_CODE_BLUE, P_MT9F002_COARSE_INTEGRATION_TIME, P_REG_MT9F002_COARSE_INTEGRATION_TIME, 0xffff // END indicator }; Loading Loading @@ -164,15 +176,16 @@ static bool init_done[4] = {false,false,false,false}; /** Initial register writes for MT9F002 */ static unsigned short mt9f002_inits[]= { P_REG_MT9F002_HISPI_TIMING, 0x8000, // P_REG_MT9F002_SMIA_PLL_MULTIPLIER, 0x00b4, // P_REG_MT9F002_HISPI_CONTROL_STATUS, 0x8400, // P_REG_MT9F002_DATAPATH_SELECT, 0x9280, // P_REG_MT9F002_RESET_REGISTER, 0x001c, P_REG_MT9F002_ANALOG_GAIN_CODE_GLOBAL, 0x000a, P_REG_MT9F002_ANALOG_GAIN_CODE_RED, 0x000d, P_REG_MT9F002_ANALOG_GAIN_CODE_BLUE, 0x0010, P_REG_MT9F002_COARSE_INTEGRATION_TIME, 0x0060 P_MT9F002_HISPI_TIMING, 0x8000, // P_MT9F002_SMIA_PLL_MULTIPLIER, 0x00b4, // P_MT9F002_HISPI_CONTROL_STATUS, 0x8400, // P_MT9F002_DATAPATH_SELECT, 0x9280, // P_MT9F002_RESET_REGISTER, 0x001c, //P_MT9F002_TEST_PATTERN, 0x0002, // color bars P_MT9F002_ANALOG_GAIN_CODE_GLOBAL, 0x000a, P_MT9F002_ANALOG_GAIN_CODE_RED, 0x000d, P_MT9F002_ANALOG_GAIN_CODE_BLUE, 0x0010, P_MT9F002_COARSE_INTEGRATION_TIME, 0x0100 }; /** Specifying sensor registers to be controlled individually in multi-sensor applications, MT9P006 */ Loading Loading @@ -281,7 +294,7 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port x393_sensio_ctrl(sensio_ctl,sensor_port); // what's this? commented out and it still works. 2018/02/13 //udelay(50); // is it needed? udelay(50); // is it needed? X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_REG_MT9F002_MODEL_ID, &i2c_read_dataw); dev_dbg(g_dev_ptr,"Read i2c (port = %d, sa7=0x%lx, reg=0x%x) chip ID=%x\n",sensor_port, psensor->i2c_addr, P_REG_MT9F002_MODEL_ID, i2c_read_dataw); Loading Loading @@ -330,35 +343,47 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port int mt9f002_phases_program_phase(int sensor_port, int phase){ int i; int read_phase; int read_phase = 0x5555; struct sensor_port_config_t *pcfg; const char *name; int wr_full; pcfg = &pSensorPortConfig[sensor_port]; name = get_name_by_code(pcfg->sensor[0],DETECT_SENSOR); x393_xi2c_write_reg(name,sensor_port,0,P_REG_MT9F002_HISPI_TIMING,phase); //x393_xi2c_write_reg(name,sensor_port,0,P_REG_MT9F002_HISPI_TIMING,phase); // sa7 is not used anymore for(i=0;i<32;i++){ wr_full = x393_xi2c_ready_wr(sensor_port); if (wr_full==0){ pr_err("{%d} I2C sequencer is FULL1 for target 0x%04x\n",sensor_port,phase); } x393_xi2c_read_reg(name,sensor_port,0,P_REG_MT9F002_HISPI_TIMING,&read_phase); X3X3_I2C_SEND2_ASAP(sensor_port,0x0,P_MT9F002_HISPI_TIMING,phase); x393_xi2c_wait_wr(sensor_port); if (read_phase!=phase){ pr_err("{%d} write error, target value = 0x%04x, read value = 0x%04x \n",sensor_port,read_phase,phase); // write retry if ((i&0x7)==0) { x393_xi2c_write_reg(name,sensor_port,0,P_REG_MT9F002_HISPI_TIMING,phase); for(i=0;i<32;i++){ wr_full = x393_xi2c_ready_wr(sensor_port); if (wr_full==0){ pr_err("{%d} I2C sequencer is FULL2 for target 0x%04x\n",sensor_port,phase); } }else{ X3X3_I2C_RCV2(sensor_port, 0x10, P_REG_MT9F002_HISPI_TIMING, &read_phase); if (read_phase==phase){ break; } // i2c is slow udelay(1000); pr_err("{%d} write error, target value = 0x%04x, read value = 0x%04x \n",sensor_port,phase,read_phase); // write retry if ((i&0x7)==0x7) { pr_err("{%d} write retry: 0x%04x\n",sensor_port,phase); X3X3_I2C_SEND2_ASAP(sensor_port,0x0,P_MT9F002_HISPI_TIMING,phase); x393_xi2c_wait_wr(sensor_port); } udelay(100); } return 0; } int mt9f002_phases_read_flags(int sensor_port,int shift){ Loading @@ -372,16 +397,16 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){ set_x393_sensio_tim2(reset_flags,sensor_port); // wait for hact for(i=0;i<4000;i++){ for(i=0;i<HACT_TIMEOUT;i++){ status = x393_sensio_status(sensor_port); if (status.hact_alive){ if (i>1) dev_dbg(g_dev_ptr,"{%d} hact recovered after %d\n",sensor_port,i); //if (i>1) dev_dbg(g_dev_ptr,"{%d} hact recovered after %d\n",sensor_port,i); break; } udelay(100); if (i==3999){ if (i==(HACT_TIMEOUT-1)){ dev_dbg(g_dev_ptr,"{%d} hact never went up after reset\n",sensor_port); } udelay(100); } // read flags Loading @@ -398,7 +423,7 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){ } int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift, int result[]){ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){ int i,j; int status; Loading @@ -406,16 +431,16 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift, int result[] int value = 0; bool switched = false; int start = 0; int count = 0; // i where switched, 1 - first 8 steps, 2 - second 8 steps int i1 = 0; int i2 = 0;//8 int im = 0; int old_phase = phase; int target_phase; int read_phase; int s[16]; pr_info("{%d} Base phase: 0x%04x\n",sensor_port,phase); // 16 values: 8 for CLK phase 0 position CLK, 8 - for CLK phase 4 position for(i=0;i<16;i++){ Loading @@ -428,56 +453,60 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift, int result[] phase -= clk_half_phase; } // set phase target_phase = phase + ((i&0x7)<<(3*shift)); mt9f002_phases_program_phase(sensor_port,target_phase); old_phase = target_phase; // read status status = mt9f002_phases_read_flags(sensor_port,shift); s[i] = status; if (i==0){ if ((i==0)||(i==8)){ value = status; count = 1; } if (i==8){ if (!switched){ start = 0; count = i; }else{ switched = false; } } if ((i<8)&&(i!=0)){ }else{ if (value!=status){ if (i<8){ if (!switched){ switched = true; value = status; i1 = i; }else{ pr_err("{%d} Unexpected phase shift at %d",sensor_port,i); } }else{ if (!switched){ count += 1; switched = true; value = status; i2 = i; }else{ pr_err("{%d} Unexpected phase shift at %d",sensor_port,i); } } } if (i>=8){ if (value==status){ count += 1; } } dev_dbg(g_dev_ptr,"%d %d %d %d %d %d %d %d | %d %d %d %d %d %d %d %d\n",s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8],s[9],s[10],s[11],s[12],s[13],s[14],s[15]); dev_dbg(g_dev_ptr,"i1 = %d, i2 = %d\n",i1,i2); //i2 = i2&0x7; /* if (i2<i1){ i2 += 8; } */ im = ((i1+i2)>>1)&0x7; //im = (i2-4)&0x7; pr_info("%d %d %d %d %d %d %d %d | %d %d %d %d %d %d %d %d\n",s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8],s[9],s[10],s[11],s[12],s[13],s[14],s[15]); pr_info("start = %d, count = %d\n",start,count); target_phase = phase + (im<<(3*shift)); result[0] = start; result[1] = count; dev_dbg(g_dev_ptr,"mid phase: %d (target phase = 0x%04x)",im,target_phase); return 0; // apply center phase mt9f002_phases_program_phase(sensor_port,target_phase); return target_phase; } int mt9f002_phases_adjust(int sensor_port){ Loading @@ -493,7 +522,6 @@ int mt9f002_phases_adjust(int sensor_port){ int phase = 0x8000; int i; int result[2]; x393_status_sens_io_t status; // read it first ? Loading @@ -506,34 +534,31 @@ int mt9f002_phases_adjust(int sensor_port){ set_x393_sensio_status_cntrl(status_ctrl, sensor_port); // wait for hact (usually alive after 254) for(i=0;i<1024;i++){ for(i=0;i<HACT_TIMEOUT;i++){ status = x393_sensio_status(sensor_port); if (status.hact_alive){ dev_dbg(g_dev_ptr,"{%d} HACT alive at %d\n",sensor_port,i); //dev_dbg(g_dev_ptr,"{%d} HACT alive at %d\n",sensor_port,i); break; } if (i==(HACT_TIMEOUT-1)){ dev_dbg(g_dev_ptr,"{%d} HACT never went live\n",sensor_port); } udelay(100); } // 4 data lanes - prior knowledge for(i=0;i<4;i++){ mt9f002_phases_scan_lane(sensor_port,phase,i,result); // &0x7 = %8 phase += ((result[0]+(result[1]>>1))&0x7)<<(3*i); if (result[1]<2){ dev_dbg(g_dev_ptr,"{%d} Error scanning D%d lane, count=%d\n",sensor_port,i,result[1]); } phase = mt9f002_phases_scan_lane(sensor_port,phase,i); } dev_dbg(g_dev_ptr,"{%d} Adjusted phase is 0x%04x\n",sensor_port,phase); // apply final phase mt9f002_phases_program_phase(sensor_port,phase); //mt9f002_phases_program_phase(sensor_port,phase,0,false); // disable status updates status_ctrl.mode = 0x0; set_x393_sensio_status_cntrl(status_ctrl, sensor_port); //status_ctrl.mode = 0x0; //set_x393_sensio_status_cntrl(status_ctrl, sensor_port); return 0; } Loading Loading @@ -569,18 +594,24 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port for(i=0;i<n;i++){ haddr = (mt9f002_inits[2*i]>>8)&0xff; laddr = mt9f002_inits[2*i]&0xff; data = mt9f002_inits[2*i+1]; page = pSensorPortConfig[sensor_port].haddr2rec[0][haddr]; //haddr = (mt9f002_inits[2*i]>>8)&0xff; //laddr = mt9f002_inits[2*i]&0xff; //data = mt9f002_inits[2*i+1]; //page = pSensorPortConfig[sensor_port].haddr2rec[0][haddr]; // write immediately //dev_dbg(g_dev_ptr,"{%d} init sensor: writing 0x%04x to register 0x%02x%02x\n",sensor_port,data,haddr,laddr); write_xi2c_reg16(sensor_port,page,laddr,data); //write_xi2c_reg16(sensor_port,page,laddr,data); X3X3_I2C_SEND2_ASAP(sensor_port,sensor->i2c_addr,mt9f002_inits[2*i],mt9f002_inits[2*i+1]); } // sensor is supposed to be streaming by now mt9f002_phases_adjust(sensor_port); // extra reset? //X3X3_I2C_SEND2_ASAP(sensor_port,sensor->i2c_addr,P_MT9F002_RESET_REGISTER,0x001c); // init register shadows here return 0; Loading Loading @@ -654,12 +685,29 @@ static ssize_t store_debug_modes(struct device *dev, struct device_attribute *at return count; } static ssize_t show_status_flags(struct device *dev, struct device_attribute *attr, char *buf) { int i,j; int s[16]; for(i=0;i<4;i++){ for(j=0;j<4;j++){ s[4*i+j] = mt9f002_phases_read_flags(i,j); } } return sprintf(buf,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8],s[9],s[10],s[11],s[12],s[13],s[14],s[15]); } static DEVICE_ATTR(sensor_regs0, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs); static DEVICE_ATTR(sensor_regs1, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs); static DEVICE_ATTR(sensor_regs2, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs); static DEVICE_ATTR(sensor_regs3, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs); static DEVICE_ATTR(debug_delays, SYSFS_PERMISSIONS, show_debug_delays, store_debug_delays); static DEVICE_ATTR(debug_modes, SYSFS_PERMISSIONS, show_debug_modes, store_debug_modes); static DEVICE_ATTR(frame_status, SYSFS_PERMISSIONS, show_status_flags, NULL); static struct attribute *root_dev_attrs[] = { &dev_attr_sensor_regs0.attr, Loading @@ -668,6 +716,7 @@ static struct attribute *root_dev_attrs[] = { &dev_attr_sensor_regs3.attr, &dev_attr_debug_delays.attr, &dev_attr_debug_modes.attr, &dev_attr_frame_status.attr, NULL }; Loading Loading @@ -711,7 +760,7 @@ int mt9f002_remove(struct platform_device *pdev) // TODO: add elphel,elphel393-mt9f002-1.00 to device tree static const struct of_device_id elphel393_mt9f002_of_match[] = { { .compatible = "elphel,elphel393-mt9x001-1.00" }, { .compatible = "elphel,elphel393-mt9f002-1.00" }, { /* end of list */ } }; MODULE_DEVICE_TABLE(of, elphel393_mt9f002_of_match); Loading
src/drivers/elphel/mt9f002.h +10 −0 Original line number Diff line number Diff line Loading @@ -544,6 +544,16 @@ #define P_MT9F002_TEST_PATTERN 10 #define P_MT9F002_HISPI_TIMING 11 #define P_MT9F002_SMIA_PLL_MULTIPLIER 12 #define P_MT9F002_HISPI_CONTROL_STATUS 13 #define P_MT9F002_DATAPATH_SELECT 14 #define P_MT9F002_RESET_REGISTER 15 #define P_MT9F002_ANALOG_GAIN_CODE_GLOBAL 16 #define P_MT9F002_ANALOG_GAIN_CODE_RED 17 #define P_MT9F002_ANALOG_GAIN_CODE_BLUE 18 #define P_MT9F002_COARSE_INTEGRATION_TIME 19 //#define P_REG(x) x //#define P_MT9F002_MODEL_ID 4 Loading
src/drivers/elphel/mt9x001.c +1 −1 Original line number Diff line number Diff line Loading @@ -1175,7 +1175,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%0x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_ROWSTART,(int) wt); } ///TODO:Get rid of get_sensor_i2c_regs16 !!! // the fields that should not chnage in non-stop will not change, so it is OK to write them always // the fields that should not change in non-stop will not change, so it is OK to write them always if((styp == MT9T_TYP) || (styp == MT9P_TYP)) { // 3MPix and 5MPix sensors v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM] & 0xff88) | ((bv - 1) << 4) | (dv - 1) ; if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM]) { Loading
src/drivers/elphel/pgm_functions.c +0 −2 Original line number Diff line number Diff line Loading @@ -379,8 +379,6 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number ( int i2cbytes; int mux,sens; pr_info("{%d} pgm_detectsensor\n",sensor_port); dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16); MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16) Loading
src/drivers/elphel/sensor_common.c +1 −1 Original line number Diff line number Diff line Loading @@ -1223,7 +1223,7 @@ int register_i2c_sensor(int ports_mask) ///< bitmask of the sensor ports to use bool mux; pr_info("register_i2c_sensor()\n"); dev_dbg(g_dev_ptr,"register_i2c_sensor()\n"); for(port=0;port<SENSOR_PORTS;port++) if ((1<<port)&ports_mask) { Loading