Commit e5bb1292 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

1. fixed i2c discover

2. fixed phase adjustment - requires bitstream 0x100
3. tested phase adjustment
parent b59b7efd
...@@ -180,7 +180,7 @@ static unsigned short mt9f002_inits[]= ...@@ -180,7 +180,7 @@ static unsigned short mt9f002_inits[]=
P_MT9F002_SMIA_PLL_MULTIPLIER, 0x00b4, // P_MT9F002_SMIA_PLL_MULTIPLIER, 0x00b4, //
P_MT9F002_HISPI_CONTROL_STATUS, 0x8400, // P_MT9F002_HISPI_CONTROL_STATUS, 0x8400, //
P_MT9F002_DATAPATH_SELECT, 0x9280, // P_MT9F002_DATAPATH_SELECT, 0x9280, //
P_MT9F002_RESET_REGISTER, 0x001c, //P_MT9F002_RESET_REGISTER, 0x001c,
//P_MT9F002_TEST_PATTERN, 0x0002, // color bars //P_MT9F002_TEST_PATTERN, 0x0002, // color bars
P_MT9F002_ANALOG_GAIN_CODE_GLOBAL, 0x000a, P_MT9F002_ANALOG_GAIN_CODE_GLOBAL, 0x000a,
P_MT9F002_ANALOG_GAIN_CODE_RED, 0x000d, P_MT9F002_ANALOG_GAIN_CODE_RED, 0x000d,
...@@ -251,6 +251,8 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -251,6 +251,8 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port
struct sensor_port_config_t *pcfg; struct sensor_port_config_t *pcfg;
const char *name; const char *name;
x393_i2c_device_t * dc; x393_i2c_device_t * dc;
// disable SOF
x393_sens_sync_mult_t dis_sof = {.d32=0};
//struct sensor_port_config_t pcfg; //struct sensor_port_config_t pcfg;
//pcfg = pSensorPortConfig[sensor_port]; //pcfg = pSensorPortConfig[sensor_port];
...@@ -277,6 +279,9 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -277,6 +279,9 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port
psensor->i2c_addr = dc->slave7; psensor->i2c_addr = dc->slave7;
} }
dis_sof.dis_sof = 1;
x393_sens_sync_mult(dis_sof,sensor_port);
// set control lines // set control lines
sensio_ctl.mrst = 1; sensio_ctl.mrst = 1;
sensio_ctl.mrst_set = 1; sensio_ctl.mrst_set = 1;
...@@ -293,8 +298,8 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -293,8 +298,8 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port
sensio_ctl.mmcm_rst = 0; sensio_ctl.mmcm_rst = 0;
x393_sensio_ctrl(sensio_ctl,sensor_port); x393_sensio_ctrl(sensio_ctl,sensor_port);
// what's this? commented out and it still works. 2018/02/13 // delay until sensor gets responsive to i2c commands
udelay(50); // is it needed? udelay(100);
X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_REG_MT9F002_MODEL_ID, &i2c_read_dataw); 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); 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);
...@@ -343,7 +348,7 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -343,7 +348,7 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port
int mt9f002_phases_program_phase(int sensor_port, int phase){ int mt9f002_phases_program_phase(int sensor_port, int phase){
int i; int i;
int read_phase = 0x5555; int read_phase = 0;
struct sensor_port_config_t *pcfg; struct sensor_port_config_t *pcfg;
const char *name; const char *name;
int wr_full; int wr_full;
...@@ -351,38 +356,13 @@ int mt9f002_phases_program_phase(int sensor_port, int phase){ ...@@ -351,38 +356,13 @@ int mt9f002_phases_program_phase(int sensor_port, int phase){
pcfg = &pSensorPortConfig[sensor_port]; pcfg = &pSensorPortConfig[sensor_port];
name = get_name_by_code(pcfg->sensor[0],DETECT_SENSOR); name = get_name_by_code(pcfg->sensor[0],DETECT_SENSOR);
//x393_xi2c_write_reg(name,sensor_port,0,P_REG_MT9F002_HISPI_TIMING,phase);
// sa7 is not used anymore
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);
}
X3X3_I2C_SEND2_ASAP(sensor_port,0x0,P_MT9F002_HISPI_TIMING,phase); X3X3_I2C_SEND2_ASAP(sensor_port,0x0,P_MT9F002_HISPI_TIMING,phase);
x393_xi2c_wait_wr(sensor_port);
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);
}
X3X3_I2C_RCV2(sensor_port, 0x10, P_REG_MT9F002_HISPI_TIMING, &read_phase); X3X3_I2C_RCV2(sensor_port, 0x10, P_REG_MT9F002_HISPI_TIMING, &read_phase);
if (read_phase==phase){ if (read_phase!=phase){
break; pr_err("{%d} i2c write error, target value = 0x%04x, read value = 0x%04x \n",sensor_port,phase,read_phase);
}
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; return 0;
} }
...@@ -425,41 +405,36 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){ ...@@ -425,41 +405,36 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){
int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){
int i,j; int i;
int status; int status;
const int clk_half_phase = 0x4000; const int clk_half_phase = 0x4000;
int value = 0; int value = 0;
bool switched = false; bool switched = false;
// i where switched, 1 - first 8 steps, 2 - second 8 steps // i where switched, 1 - first 8 steps (and it's the middle phase),
// 2 - second 8 steps
int i1 = 0; int i1 = 0;
int i2 = 0;//8 int i2 = 8;
int im = 0;
int old_phase = phase;
int target_phase; int target_phase;
int s[16];
// 16 values: 8 for CLK phase 0 position CLK, 8 - for CLK phase 4 position // 16 values: 8 for CLK phase 0 position CLK, 8 - for CLK phase 4 position
for(i=0;i<16;i++){ for(i=0;i<16;i++){
// clk phase // support clk phase range
if (i==0){ if (i==0){
phase += clk_half_phase; phase += clk_half_phase;
} }
// main clk range
if (i==8){ if (i==8){
phase -= clk_half_phase; phase -= clk_half_phase;
} }
target_phase = phase + ((i&0x7)<<(3*shift)); target_phase = phase + ((i&0x7)<<(3*shift));
mt9f002_phases_program_phase(sensor_port,target_phase); mt9f002_phases_program_phase(sensor_port,target_phase);
old_phase = target_phase;
// read status
status = mt9f002_phases_read_flags(sensor_port,shift); status = mt9f002_phases_read_flags(sensor_port,shift);
s[i] = status;
if ((i==0)||(i==8)){ if ((i==0)||(i==8)){
value = status; value = status;
...@@ -472,7 +447,7 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){ ...@@ -472,7 +447,7 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){
value = status; value = status;
i1 = i; i1 = i;
}else{ }else{
pr_err("{%d} Unexpected phase shift at %d",sensor_port,i); pr_err("{%d} Lane D%d: unexpected phase shift at %d\n",sensor_port,shift,i);
} }
}else{ }else{
if (!switched){ if (!switched){
...@@ -480,28 +455,24 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){ ...@@ -480,28 +455,24 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){
value = status; value = status;
i2 = i; i2 = i;
}else{ }else{
pr_err("{%d} Unexpected phase shift at %d",sensor_port,i); pr_err("{%d} Lane D%d: unexpected phase shift at %d\n",sensor_port,shift,i);
} }
} }
} }
} }
} }
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]); i1 = i1&0x7;
dev_dbg(g_dev_ptr,"i1 = %d, i2 = %d\n",i1,i2); i2 = i2&0x7;
//i2 = i2&0x7; // just a check
/* if (abs(i2-i1)<2){
if (i2<i1){ pr_err("{%d} Warning: optimal phase shift (lane D%d) is probably not correct (difference = %d)",sensor_port,shift,i2);
i2 += 8;
} }
*/
im = ((i1+i2)>>1)&0x7;
//im = (i2-4)&0x7;
target_phase = phase + (im<<(3*shift)); target_phase = phase + (i1<<(3*shift));
dev_dbg(g_dev_ptr,"mid phase: %d (target phase = 0x%04x)",im,target_phase); dev_dbg(g_dev_ptr,"{%d} lane D%d mid phase = %d (target phase = 0x%04x)",sensor_port,shift,i1,target_phase);
// apply center phase // apply center phase
mt9f002_phases_program_phase(sensor_port,target_phase); mt9f002_phases_program_phase(sensor_port,target_phase);
...@@ -576,8 +547,7 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -576,8 +547,7 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port
{ {
int i; int i;
int n; int n;
u8 page, haddr, laddr; x393_sens_sync_mult_t dis_sof = {.d32=0};
u16 data;
//dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16); //dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
// sensor is silent before init - this check is redundant // sensor is silent before init - this check is redundant
...@@ -593,24 +563,22 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -593,24 +563,22 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port
n = sizeof(mt9f002_inits)/4; // 4 bytes per pair n = sizeof(mt9f002_inits)/4; // 4 bytes per pair
for(i=0;i<n;i++){ for(i=0;i<n;i++){
// sa7 is not used
//haddr = (mt9f002_inits[2*i]>>8)&0xff; X3X3_I2C_SEND2_ASAP(sensor_port,0x0,mt9f002_inits[2*i],mt9f002_inits[2*i+1]);
//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);
X3X3_I2C_SEND2_ASAP(sensor_port,sensor->i2c_addr,mt9f002_inits[2*i],mt9f002_inits[2*i+1]);
} }
// soft reset
// sa7 is not used
X3X3_I2C_SEND2_ASAP(sensor_port,0x0,P_MT9F002_RESET_REGISTER,MT9F002_RESET_REGISTER_VALUE);
// delay (needed?)
udelay(100);
// sensor is supposed to be streaming by now // sensor is supposed to be streaming by now
mt9f002_phases_adjust(sensor_port); mt9f002_phases_adjust(sensor_port);
// extra reset? // restore SOF (disabled in pgm_detect)
//X3X3_I2C_SEND2_ASAP(sensor_port,sensor->i2c_addr,P_MT9F002_RESET_REGISTER,0x001c); dis_sof.dis_sof = 0;
x393_sens_sync_mult(dis_sof,sensor_port);
// init register shadows here // init register shadows here
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#define MT9F002_PARTID 0x2E01 ///< MT9F002 PartID register value #define MT9F002_PARTID 0x2E01 ///< MT9F002 PartID register value
#define MT9F002_I2C_ADDR 0x10 ///< MT9P I2C slave address (7 bit) #define MT9F002_I2C_ADDR 0x10 ///< MT9P I2C slave address (7 bit)
#define MT9F002_RESET_REGISTER_VALUE 0x001c
/* ON Semi MT9F002 i2c register addresses */ /* ON Semi MT9F002 i2c register addresses */
/* /*
......
...@@ -1176,8 +1176,10 @@ int fpga_register_i2c_pages(int port, int sub_chn, x393_i2c_device_t i2c_dev){ ...@@ -1176,8 +1176,10 @@ int fpga_register_i2c_pages(int port, int sub_chn, x393_i2c_device_t i2c_dev){
haddr = (table[i]>>8)&0xff; haddr = (table[i]>>8)&0xff;
dev_dbg(g_dev_ptr,"Registering page %d for haddr= 0x%02x, sa7= 0x%02x\n",line_num, haddr, i2c_dev.slave7);
if ((table[i]==0xffff)||(i>255)){ if ((table[i]==0xffff)||(i>255)){
dev_dbg(g_dev_ptr,"haddr2rec table registered (number of entries: %d)\n",i); dev_dbg(g_dev_ptr,"haddr2rec (entries: %d)\n",i);
break; break;
} }
...@@ -1186,16 +1188,16 @@ int fpga_register_i2c_pages(int port, int sub_chn, x393_i2c_device_t i2c_dev){ ...@@ -1186,16 +1188,16 @@ int fpga_register_i2c_pages(int port, int sub_chn, x393_i2c_device_t i2c_dev){
line_num = i2c_page_alloc(port); line_num = i2c_page_alloc(port);
if (line_num<0){ if (line_num<0){
pr_err("{%d} Error registering page %d (haddr = 0x%02x)\n",port,line_num,haddr);
return line_num; return line_num;
} }
dev_dbg(g_dev_ptr,"Registering page %d for haddr=0x%02x. slave7= 0x%02x\n",line_num, haddr, i2c_dev.slave7);
//line_num = i2c_dev.slave7; //line_num = i2c_dev.slave7;
//haddr = 0; //haddr = 0;
h2r[haddr] = line_num; h2r[haddr] = line_num;
i2c_page_register(port,line_num); // i2c_page_alloc does it
//i2c_page_register(port,line_num);
set_xi2c_wrc(&i2c_dev,port,line_num,haddr); set_xi2c_wrc(&i2c_dev,port,line_num,haddr);
} }
i++; i++;
...@@ -1255,7 +1257,6 @@ int register_i2c_sensor(int ports_mask) ///< bitmask of the sensor ports to use ...@@ -1255,7 +1257,6 @@ int register_i2c_sensor(int ports_mask) ///< bitmask of the sensor ports to use
class_mux = xi2c_dev_get(name); class_mux = xi2c_dev_get(name);
// TODO: request a line# from fpga table and register it (not class_mux->slave7) // TODO: request a line# from fpga table and register it (not class_mux->slave7)
dev_dbg(g_dev_ptr,"Registering page %d for haddr=0x%02x. slave7= 0x%02x\n",class_mux->slave7, 0, class_mux->slave7);
i2c_page_register(port, class_mux->slave7); i2c_page_register(port, class_mux->slave7);
set_xi2c_wrc(class_mux, port, class_mux->slave7, 0); set_xi2c_wrc(class_mux, port, class_mux->slave7, 0);
} }
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#define SYSFS_WRITEONLY 0222 #define SYSFS_WRITEONLY 0222
//#define DRV_NAME "elphel_sensor_i2c" //#define DRV_NAME "elphel_sensor_i2c"
// FIXME: Warnoings in softtirq.c, do not understand why. using LOCK_BH_SENSORI2C to enable spin_lock_bh, otherwise use spin_lock_irqsave // FIXME: Warnings in softtirq.c, do not understand why. using LOCK_BH_SENSORI2C to enable spin_lock_bh, otherwise use spin_lock_irqsave
#undef LOCK_BH_SENSORI2C #undef LOCK_BH_SENSORI2C
struct x393_i2c_device_list { struct x393_i2c_device_list {
x393_i2c_device_t i2c_dev; x393_i2c_device_t i2c_dev;
...@@ -755,6 +755,8 @@ int read_xi2c_fifo(int chn) ///< sensor port ...@@ -755,6 +755,8 @@ int read_xi2c_fifo(int chn) ///< sensor port
int fifo_lsb, rslt,i; int fifo_lsb, rslt,i;
x393_i2c_ctltbl_t i2c_cmd; x393_i2c_ctltbl_t i2c_cmd;
x393_status_sens_i2c_t status; x393_status_sens_i2c_t status;
x393_cmdseqmux_status_t status2;
i2c_autoupdate_status(chn); i2c_autoupdate_status(chn);
status = x393_sensi2c_status (chn); status = x393_sensi2c_status (chn);
// dev_dbg(sdev, "read_xi2c_fifo(%d): status = 0x%08x\n",chn, (int) status.d32); // dev_dbg(sdev, "read_xi2c_fifo(%d): status = 0x%08x\n",chn, (int) status.d32);
...@@ -771,6 +773,7 @@ int read_xi2c_fifo(int chn) ///< sensor port ...@@ -771,6 +773,7 @@ int read_xi2c_fifo(int chn) ///< sensor port
if (likely(status.i2c_fifo_lsb != fifo_lsb)) break; if (likely(status.i2c_fifo_lsb != fifo_lsb)) break;
} }
dev_dbg(sdev, "read_xi2c_fifo(%d): new status = 0x%08x\n",chn, (int) status.d32); dev_dbg(sdev, "read_xi2c_fifo(%d): new status = 0x%08x\n",chn, (int) status.d32);
status2 = x393_cmdseqmux_status();
return rslt; return rslt;
} }
EXPORT_SYMBOL_GPL(read_xi2c_fifo); EXPORT_SYMBOL_GPL(read_xi2c_fifo);
...@@ -946,7 +949,7 @@ int legacy_read_i2c_reg( int chn, ///< sensor port number ...@@ -946,7 +949,7 @@ int legacy_read_i2c_reg( int chn, ///< sensor port number
/* Flush channel i2c read FIFO to make sure it is empty, status mode will be set, if needed */ /* Flush channel i2c read FIFO to make sure it is empty, status mode will be set, if needed */
// Seems after sensor re-init it was getting some stray data? // Seems after sensor re-init it was getting some stray data?
while (read_xi2c_fifo(chn) >= 0) ; // includes waiting for status propagate while (read_xi2c_fifo(chn) >= 0); // includes waiting for status propagate
dev_dbg(sdev, "Flushed i2c read fifo for channel %d\n",chn); dev_dbg(sdev, "Flushed i2c read fifo for channel %d\n",chn);
/* Initiate i2c read */ /* Initiate i2c read */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment