Commit 8b4b7b64 authored by Andrey Filippov's avatar Andrey Filippov

debugging with 10359 multiplexer (Eyesis mode)

parent 11d96e51
......@@ -265,7 +265,10 @@
elphel393-sensor-i2c,i2c_devices = "mt9f002 0x10 2 2 500",
"mt9p006 0x48 1 2 500",
"el10359 0x08 1 2 500",
"el10359_32 0x08 1 4 500",
"pca9500_eeprom 0x50 1 1 100",
"sensor_eeprom 0x50 1 1 100",
"sensor_temp 0x18 1 2 100",
"cy22393 0x69 1 1 100";
} ;
......@@ -285,6 +288,10 @@
compatible = "elphel,elphel393-mt9x001-1.00";
};
elphel393_clock10359:elphel393-clock10359@0{
compatible = "elphel,elphel393_clock10359-1.00";
};
klogger_393: klogger-393@0 {
compatible = "elphel,klogger-393-1.00";
klogger-393,buffer_size = <1048576>;
......
......@@ -84,25 +84,25 @@ int calc_pll_params (unsigned int f, t_pll_params * pars) { // f -in Hz
unsigned int fpmx= CY22393_XTAL * (CY22393_PMAX + 6);
int divmn, divmx, err1,err, div,q,qmn,qmx,qmx1,fdv,p, e,fdvq;
pars->rslt=3; // other error
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX);
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d\n",f0,f,CY22393_OUTMAX);
f/=CY22393_SCALE; // to fit into 32-bit calculations
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX);
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d\n",f0,f,CY22393_OUTMAX);
if (f>CY22393_OUTMAX) {
pars->rslt=2;
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX);
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d\n",f0,f,CY22393_OUTMAX);
return pars->rslt;
}
if (f <=0 ) {
pars->rslt=1;
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d\r\n",f0,f,CY22393_OUTMAX);
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d\n",f0,f,CY22393_OUTMAX);
return pars->rslt;
}
divmx=CY22393_PLLMAX/f; if (divmx > 127) divmx=127; // could not be <1
divmn=CY22393_PLLMIN/f; if (divmn < 1) divmn=1;
if (divmn >127) {
pars->rslt=1;
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d, divmn=%d\r\n",f0,f,CY22393_OUTMAX,divmn);
dev_dbg(sdev, "f0=%d,f=%d, CY22393_OUTMAX=%d, divmn=%d\n",f0,f,CY22393_OUTMAX,divmn);
return pars->rslt;
}
err1=f;
......@@ -113,7 +113,7 @@ int calc_pll_params (unsigned int f, t_pll_params * pars) { // f -in Hz
qmn=fpmn/fdv-2; if (qmn < 0) qmn=0;
qmx=fpmx/fdv-2; if (qmx >255) qmx=255;
// recalculate qmn to avoid same div*qmn as already tried with lover div
dev_dbg(sdev, "div=%d,qmn=%d, qmx=%d\r\n",div,qmn,qmx);
dev_dbg(sdev, "div=%d,qmn=%d, qmx=%d\n",div,qmn,qmx);
if (div==1) qmx1=qmx;
else if ((qmn*div) < qmx1) qmn=qmx1/div;
for (q=qmn+2;q<=qmx+2; q++) {
......@@ -127,10 +127,10 @@ int calc_pll_params (unsigned int f, t_pll_params * pars) { // f -in Hz
pars->dv=div;
err1=e/q/div;
err=err1*div;
dev_dbg(sdev, "f=%d, div=%d, p=%d,q=%d, err1=%d\r\n", (f0*p)/q/div, div,p, q, err1);
dev_dbg(sdev, "f=%d, div=%d, p=%d,q=%d, err1=%d\n", (f0*p)/q/div, div,p, q, err1);
if (err1==0) {
pars->corr=(pars->p<226)?0:((pars->p<621)?1:((pars->p<829)?2:((pars->p<1038)?3:4)));
dev_dbg(sdev, "f=%d, div=%d, p=%d,q=%d, err1=%d, rslt=%d\r\n",
dev_dbg(sdev, "f=%d, div=%d, p=%d,q=%d, err1=%d, rslt=%d\n",
(f0*(pars->p+6))/(pars->q+2)/pars->dv,
pars->dv,
(pars->p+6),
......@@ -142,7 +142,7 @@ int calc_pll_params (unsigned int f, t_pll_params * pars) { // f -in Hz
}
}
}
dev_dbg(sdev, "f=%d, div=%d, p=%d,q=%d, err1=%d, rslt=%d\r\n",
dev_dbg(sdev, "f=%d, div=%d, p=%d,q=%d, err1=%d, rslt=%d\n",
(f0*(pars->p+6))/(pars->q+2)/pars->dv,
pars->dv,
(pars->p+6),
......@@ -156,6 +156,7 @@ int calc_pll_params (unsigned int f, t_pll_params * pars) { // f -in Hz
int setCYField (int sensor_port, int reg_addr, int mask, int value) {
int error;
int reg_data;
dev_dbg(sdev,"setCYField(%d, 0x%x, 0x%x,0x%x)\n",sensor_port, reg_addr, mask, value);
if ((error = x393_xi2c_read_reg(CLOCK_NAME, // device class name
sensor_port, // sensor port number
0, // slave address (7-bit) offset from the class defined slave address
......@@ -165,6 +166,7 @@ int setCYField (int sensor_port, int reg_addr, int mask, int value) {
sensor_port, reg_addr, mask, value);
return error;
}
dev_dbg(sdev,"setCYField(%d, 0x%x, 0x%x,0x%x)=>0x%x\n",sensor_port, reg_addr, mask, value,reg_data);
reg_data ^= (reg_data ^ value) & mask;
if ((error = x393_xi2c_write_reg(CLOCK_NAME, // device class name
sensor_port, // sensor port number
......@@ -181,22 +183,43 @@ int setCYField (int sensor_port, int reg_addr, int mask, int value) {
int x393_getClockFreq(int sensor_port, int nclock) {
if ((sensor_port < 0) || (sensor_port > 3) || (nclock < 0) || (nclock > 3))return -EINVAL; // bad clock number
else {
return clock_frequency[(sensor_port << 2) || nclock];
dev_dbg(sdev, "clock_frequency[%d]\n",(sensor_port << 2) + nclock);
return clock_frequency[(sensor_port << 2) + nclock];
}
}
EXPORT_SYMBOL_GPL(x393_getClockFreq);
int x393_setClockFreq(int sensor_port, int nclock, int freq)
{ // freq now in Hz
int err=0;
int i,bp,bq,bdiv,pllc,fact;
t_pll_params pll_params;
sensor_port &= 3;
nclock &= 3;
t_pll_params pll_params;
int i,bp,bq,bdiv,pllc,fact;
bp=0; bq=0; bdiv=0; pllc= 0; // just to make gcc happy
fact=0;
dev_dbg(sdev, "setClockFreq(%d,%d,%d)\r\n",sensor_port,nclock,freq);
dev_dbg(sdev, "setClockFreq(%d,%d,%d)\n",sensor_port,nclock,freq);
// Just temporary debug:
#if 1
for (i = 0; i< 24; i++) {
int reg_data;
// dev_dbg(sdev,"setCYField(%d, 0x%x, 0x%x,0x%x)\n",sensor_port, reg_addr, mask, value);
if ((err = x393_xi2c_read_reg(CLOCK_NAME, // device class name
sensor_port, // sensor port number
0, // slave address (7-bit) offset from the class defined slave address
i, // register address (width is defined by class)
&reg_data)) <0) { // pointer to a data receiver (read data width is defined by class)
dev_err(sdev,"x393_xi2c_read_reg(%d, 0, 0x%x, 0x%x) failed reading i2c register\n", sensor_port, i, reg_data);
break;
}
dev_err(sdev,"CY22393 port %d: [0x%x] => 0x%x\n", sensor_port, i, reg_data);
}
#endif
if ((freq!=0) && (nclock!=3) ){
if ( (i=calc_pll_params (freq, &pll_params)) !=0) {
dev_err(sdev, "bad frequency for clock %d - %d Hz, err=%d\n",nclock,freq,i);
......@@ -255,7 +278,7 @@ int x393_setClockFreq(int sensor_port, int nclock, int freq)
break;
case 3:
if ((freq!=0) && (freq!=CY22393_SCALE*CY22393_XTAL)) {
dev_err(sdev, "Only frequency 0 (off) and %d Hz (xtal) are allowed for channel 3\r\n",CY22393_SCALE*CY22393_XTAL);
dev_err(sdev, "Only frequency 0 (off) and %d Hz (xtal) are allowed for channel 3\n",CY22393_SCALE*CY22393_XTAL);
return -EINVAL;
} else {
// int setCYField (sensor_port,int devfd, int addr, int mask, int value) O_RDWR
......@@ -275,6 +298,7 @@ int x393_setClockFreq(int sensor_port, int nclock, int freq)
return err;
}
clock_frequency[(sensor_port << 2) + nclock] = fact;
dev_dbg(sdev, "clock_frequency[%d]\n",(sensor_port << 2) + nclock);
return fact;
}
EXPORT_SYMBOL_GPL(x393_setClockFreq);
......@@ -400,7 +424,7 @@ static void elphel393_clock10359_init_of(struct platform_device *pdev)
static int elphel393_clock10359_probe(struct platform_device *pdev)
{
sdev =&pdev->dev;
dev_dbg(&pdev->dev,"Probing elphel_clock10359\n");
dev_info(&pdev->dev,"Probing elphel_clock10359\n");
elphel393_clock10359_sysfs_register(pdev);
dev_dbg(&pdev->dev,"elphel393_clock10359_sysfs_register() done\n");
......
......@@ -1219,7 +1219,7 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
{
struct frameparspair_t pars_to_update[16]; // maximum 7 registers updated (need to recount)
int nupdate=0;
int dh= thispars->pars[P_DCM_HOR];
int dh= thispars->pars[P_DCM_HOR]?thispars->pars[P_DCM_HOR]:1;
int ww= thispars->pars[P_SENSOR_PIXH] * dh;
int binning_cost = 0;
int width,i;
......
......@@ -213,15 +213,15 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
#ifdef NC353 // to hide old code
#define MULTISENSOR_WRITE_I2C(sa,ra,v,sz) \
{rslt |= multisensor_write_i2c((sa),(ra),(v),(sz)) ; \
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",__func__,(int)(sa),(int)(ra),(int)(v),(int)(sz),rslt);}
dev_dbg(g_dev_ptr,"multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",(int)(sa),(int)(ra),(int)(v),(int)(sz),rslt);}
#define MULTISENSOR_WRITE_I2C16(ra,v) \
{rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(ra),(v),2) ; \
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",__func__,(int)(I2C359_SLAVEADDR),(int)(ra),(int)(v),2,rslt);}
dev_dbg(g_dev_ptr,"multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",(int)(I2C359_SLAVEADDR),(int)(ra),(int)(v),2,rslt);}
#define MULTISENSOR_WRITE_I2C32(ra,v) \
{rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(I2C359_MSW),(v)>>16,2) ; \
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",__func__,(int)(I2C359_SLAVEADDR),I2C359_MSW,(int)(v)>>16,2,rslt); \
dev_dbg(g_dev_ptr,"multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",(int)(I2C359_SLAVEADDR),I2C359_MSW,(int)(v)>>16,2,rslt); \
rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(ra),(v) & 0xffff,2) ; \
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",__func__,(int)(I2C359_SLAVEADDR),(int)(ra),(int)(v)&0xffff,2,rslt); \
dev_dbg(g_dev_ptr,"multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",(int)(I2C359_SLAVEADDR),(int)(ra),(int)(v)&0xffff,2,rslt); \
}
#else
// using new access in immediate mode by class name
......@@ -257,7 +257,7 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
{ pars_to_update[nupdate ].num= P_M10359_REGS+(r) ;\
pars_to_update[nupdate++].val=(v);\
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v)); \
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v));\
dev_dbg(g_dev_ptr,"X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v));\
}
#define SET_10359_PAR32(p,f,r,v) \
......@@ -268,8 +268,8 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (I2C359_MSW), (v)>>16); \
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v) & 0xffff); \
local_irq_restore(flags); \
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(I2C359_MSW),(int)(v)>>16);\
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v) & 0xffff);\
dev_dbg(g_dev_ptr,"X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(I2C359_MSW),(int)(v)>>16);\
dev_dbg(g_dev_ptr,"X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v) & 0xffff);\
}
#define SET_10359_PAR(p, f,r,v) \
......@@ -285,7 +285,7 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
// same functions, but do not schedule updating parameter shadows, just send i2c
#define SET_10359_REG16(p, f,r,v) \
{ X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v)); \
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v));\
dev_dbg(g_dev_ptr,"X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v));\
}
#define SET_10359_REG32(p, f,r,v) \
......@@ -294,8 +294,8 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (I2C359_MSW), (v)>>16); \
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v) & 0xffff); \
local_irq_restore(flags); \
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(I2C359_MSW),(int)(v)>>16);\
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v) & 0xffff);\
dev_dbg(g_dev_ptr,"X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(I2C359_MSW),(int)(v)>>16);\
dev_dbg(g_dev_ptr,"X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v) & 0xffff);\
}
#define SET_10359_REG(p,f,r,v) \
......@@ -337,9 +337,10 @@ int multisensor_pgm_window_safe (int sensor_port, struct sensor_t * sensor,
int multisensor_pgm_window_common (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16) ;
// These two parameters are copied from sensor
static int multi_phases_initialized;
static struct sensorproc_t s_sensorproc_phys; // physical sensor parameters and functions to call
struct sensorproc_t * sensorproc_phys = &s_sensorproc_phys;
static int multi_phases_initialized;
static struct sensorproc_t s_sensorproc_phys; // physical sensor parameters and functions to call
struct sensorproc_t * sensorproc_phys = &s_sensorproc_phys;
// test feature - reading i2c after certain writes to prevent FIFO over (should be unneded with FPGA status bit, just testing)
/** program sensor WOI and mirroring
* Validating, changing related parameters/scheduling actions, scheduling i2c commands
......@@ -354,7 +355,7 @@ int multisensor_pgm_window (int sensor_port, ///< sensor port
///< @return always 0
{
int rslt;
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
dev_dbg(g_dev_ptr,"frame16=%d\n",frame16);
rslt = multisensor_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
return rslt;
......@@ -373,7 +374,7 @@ int multisensor_pgm_window_safe (int sensor_port, ///< sensor port
///< @return always 0
{
int rslt;
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
dev_dbg(g_dev_ptr,"frame16=%d\n",frame16);
rslt = multisensor_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
return rslt;
}
......@@ -486,7 +487,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
dev_dbg(g_dev_ptr,"frame16=%d\n",frame16);
if (composite && (!async)) {
printk("*** ERROR (Should be disabled in multisensor_pgm_multisens() ) CANNOT USE COMPOSITE MODE WITH FREE RUNNING SENSOR ***\n");
dev_err(g_dev_ptr,"*** ERROR (Should be disabled in multisensor_pgm_multisens() ) CANNOT USE COMPOSITE MODE WITH FREE RUNNING SENSOR ***\n");
composite=0;
SETFRAMEPARS_SET(P_MULTI_MODE,0); // Do we need to force anything here? If it was async->free transition? Or just TRIG mode should have all the dependencies of P_MULTI_MODE
}
......@@ -502,13 +503,17 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
sFlipY[i]=flipY ^ (composite ?((thispars->pars[P_MULTI_FLIPV] & (1<<i))?1:0):0); // in single (non -composite) mode use just flipY
}
//sFlip* are now per-sensor absolute flips
dev_dbg(g_dev_ptr,"%s selected=%x flipX=%x flipY=%x sFlipX[0]=%x sFlipY[0]=%x sFlipX[1]=%x sFlipY[1]=%x sFlipX[2]=%x sFlipY[2]=%x\n",__func__, selected, flipX,flipY,sFlipX[0],sFlipY[0],sFlipX[1],sFlipY[1],sFlipX[2],sFlipY[2]);
dev_dbg(g_dev_ptr,"selected=%x flipX=%x flipY=%x sFlipX[0]=%x sFlipY[0]=%x sFlipX[1]=%x sFlipY[1]=%x sFlipX[2]=%x sFlipY[2]=%x\n", selected, flipX,flipY,sFlipX[0],sFlipY[0],sFlipX[1],sFlipY[1],sFlipX[2],sFlipY[2]);
// calculations valid for individual and composite frames
styp = sensor->sensorType & 7;
dh= thispars->pars[P_DCM_HOR];
dv= thispars->pars[P_DCM_VERT];
bh= thispars->pars[P_BIN_HOR];
bv= thispars->pars[P_BIN_VERT];
dh = dh?dh:1;
dv = dv?dv:1;
bh = bh?bh:1;
bv = bv?bv:1;
ww= thispars->pars[P_SENSOR_PIXH] * dh;
// SETFRAMEPARS_SET(P_SENSOR_PIXV, height+(2 * COLOR_MARGINS)); // full height for the sensor (after decimation), including margins
wh= thispars->pars[P_SENSOR_PIXV] * dv; // number of scan lines read from the sensor multipled by decimation
......@@ -528,7 +533,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
wt = thispars->pars[P_WOI_TOP];
// flip margins for mirrored images (except oversized, not to rely on sensor->clearWidth/sensor->clearHeight
//-------------------------
dev_dbg(g_dev_ptr,"%s dv=0x%x dh=0x%x ww=0x%x wh=0x%x wl=0x%x wt=0x%x \n",__func__,dv,dh,ww,wh,wl,wt);
dev_dbg(g_dev_ptr,"dv=0x%x dh=0x%x ww=0x%x wh=0x%x wl=0x%x wt=0x%x \n",dv,dh,ww,wh,wl,wt);
memcpy(wois, &(thispars->pars[P_MULTI_WOI]), sizeof(wois)); // copy WOI parameters for 3 sensors
if (composite && flipY) { // reverse sequence
......@@ -596,7 +601,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
}
}
for (i=0; (v=SENSOR_IN_SEQ(i,sequence))>=0;i++) active |= (1<<v);
dev_dbg(g_dev_ptr,"%s height1=0x%x height2=0x%x height3=0x%x\n",__func__,height1, height2, height3);
dev_dbg(g_dev_ptr,"height1=0x%x height2=0x%x height3=0x%x\n",height1, height2, height3);
......@@ -613,19 +618,19 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
}
}
// multiFlip* are set in the sub-frame sequence (accounting for the global FLIP_V, bit 0 - top subframe,1 - middle, 2 - last
dev_dbg(g_dev_ptr,"%s multiFlipX=0x%x multiFlipY=0x%x\n",__func__,multiFlipX, multiFlipY);
dev_dbg(g_dev_ptr,"multiFlipX=0x%x multiFlipY=0x%x\n",multiFlipX, multiFlipY);
// modify - multiFlipX,multiFlipY applies to sensors, not frames ???? No, they apply to sub-frames
relFlipX= (multiFlipX ^ (multiFlipX>>1))& 3;
relFlipY= (multiFlipY ^ (multiFlipY>>1))& 3;
dev_dbg(g_dev_ptr,"%s relFlipX=0x%x relFlipY=0x%x\n",__func__,relFlipX, relFlipY);
dev_dbg(g_dev_ptr,"relFlipX=0x%x relFlipY=0x%x\n",relFlipX, relFlipY);
if (relFlipY & 1) vblank2+=dv;
if (relFlipY & 2) vblank3+=((vblank3>=dv) && (vblank2>vblank3))?-dv:dv; // Keep the total height constant, if possible. If not possible - increase
hactDelay=(relFlipX ^ (relFlipX << 1)) & 3;
dev_dbg(g_dev_ptr,"%s hactDelay=0x%x vblank2=0x%x, vblank3=0x%x\n",__func__,hactDelay, vblank2, vblank3);
dev_dbg(g_dev_ptr,"hactDelay=0x%x vblank2=0x%x, vblank3=0x%x\n",hactDelay, vblank2, vblank3);
// Apply height1, height2, height3
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(0,sequence)]=height1; // always on,>= other frame heights
if ((SENSOR_IN_SEQ(1,sequence)>=0) && (SENSOR_IN_SEQ(1,sequence)!=SENSOR_IN_SEQ(0,sequence))) {
......@@ -649,10 +654,10 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+0]=ww; // all channels - same width, include margins (before decimation)
wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+1]=ww;
wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+2]=ww;
dev_dbg(g_dev_ptr,"%s wois[LEFT1]=0x%lx, wois[LEFT2]=0x%lx, wois[LEFT3]=0x%lx\n",__func__, wois[(P_MULTI_LEFT1-P_MULTI_WOI)+0],wois[(P_MULTI_LEFT1-P_MULTI_WOI)+1],wois[(P_MULTI_LEFT1-P_MULTI_WOI)+2] );
dev_dbg(g_dev_ptr,"%s wois[WIDTH1]=0x%lx\n",__func__, wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+0] );
dev_dbg(g_dev_ptr,"%s wois[TOP1]=0x%lx, wois[TOP2]=0x%lx, wois[TOP3]=0x%lx\n",__func__, wois[(P_MULTI_TOP1-P_MULTI_WOI)+0],wois[(P_MULTI_TOP1-P_MULTI_WOI)+1],wois[(P_MULTI_TOP1-P_MULTI_WOI)+2] );
dev_dbg(g_dev_ptr,"%s wois[HEIGHT1]=0x%lx, wois[HEIGHT2]=0x%lx, wois[HEIGHT3]=0x%lx\n",__func__, wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0],wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1],wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2] );
dev_dbg(g_dev_ptr,"wois[LEFT1]=0x%lx, wois[LEFT2]=0x%lx, wois[LEFT3]=0x%lx\n", wois[(P_MULTI_LEFT1-P_MULTI_WOI)+0],wois[(P_MULTI_LEFT1-P_MULTI_WOI)+1],wois[(P_MULTI_LEFT1-P_MULTI_WOI)+2] );
dev_dbg(g_dev_ptr,"wois[WIDTH1]=0x%lx\n", wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+0] );
dev_dbg(g_dev_ptr,"wois[TOP1]=0x%lx, wois[TOP2]=0x%lx, wois[TOP3]=0x%lx\n", wois[(P_MULTI_TOP1-P_MULTI_WOI)+0],wois[(P_MULTI_TOP1-P_MULTI_WOI)+1],wois[(P_MULTI_TOP1-P_MULTI_WOI)+2] );
dev_dbg(g_dev_ptr,"wois[HEIGHT1]=0x%lx, wois[HEIGHT2]=0x%lx, wois[HEIGHT3]=0x%lx\n", wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0],wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1],wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2] );
// TODO: Apply required height to the channels. If nothing but the direct channel is needed - apply it to sensor parameters
......@@ -660,14 +665,14 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
// Modify first sensor height even if it is increased to include part of the gap and minHeight
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(0,sequence)]= wh;
sequence &= 3; // turn off frames 2, 3
dev_dbg(g_dev_ptr,"%s sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",__func__,sequence, height1, vblank2, height2, vblank3 ,height3 );
dev_dbg(g_dev_ptr,"sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",sequence, height1, vblank2, height2, vblank3 ,height3 );
} else if ((wt+wh-height1-vblank2) < (height2+vblank3+(sensor->minHeight*dv))) { // Only first 2 sensors are needed - reduce second frame (10359, not the sensor)
height2=wh+wt-height1-vblank2; // only 10359, not the sensor
sequence &= 0xf; // turn off frame 3
dev_dbg(g_dev_ptr,"%s sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",__func__,sequence, height1, vblank2, height2, vblank3 ,height3 );
dev_dbg(g_dev_ptr,"sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",sequence, height1, vblank2, height2, vblank3 ,height3 );
} else { // all 3 sensors needed, adjust height3 to make sure 10359 sends out exactly wh/dv lines (vblank* could be adjusted to compensate for Bayer when flipping)
height3=wh+wt-height1-vblank2-height2-vblank3;
dev_dbg(g_dev_ptr,"%s sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",__func__,sequence, height1, vblank2, height2, vblank3 ,height3 );
dev_dbg(g_dev_ptr,"sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",sequence, height1, vblank2, height2, vblank3 ,height3 );
}
// zero out unused frames/blanks before them
......@@ -687,7 +692,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
vblank3/=dv;
height3/=dv;
}
dev_dbg(g_dev_ptr,"%s height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",__func__,height1, vblank2, height2, vblank3 ,height3 );
dev_dbg(g_dev_ptr,"height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",height1, vblank2, height2, vblank3 ,height3 );
// un-apply dh from ww - number of pixels to be read in a line in frames2,3
if (dh>1) ww/=dh;
w359=ww;
......@@ -698,7 +703,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
((multiFlipY & 1)<<1) | ((multiFlipY & 2) << 2) | ((multiFlipY & 4) << 3) | 0x40; // 0x40 as a composite frame mark (test with &0xc0!=0 - future)
if (flipX) multi_mode_flips ^= 0x15;
if (flipY) multi_mode_flips ^= 0x2a;
dev_dbg(g_dev_ptr,"%s sequence=0x%x flipX=%x flipY=%x multi_mode_flips=0x%x \n",__func__,sequence,flipX,flipY,multi_mode_flips );
dev_dbg(g_dev_ptr,"sequence=0x%x flipX=%x flipY=%x multi_mode_flips=0x%x \n",sequence,flipX,flipY,multi_mode_flips );
SETFRAMEPARS_COND(P_MULTI_MODE_FLIPS, multi_mode_flips);
// subtract (2 * COLOR_MARGINS) from the first and last frame
......@@ -902,7 +907,7 @@ int multisensor_write_i2c(unsigned char theSlave, unsigned char theRegister, uns
return 0;
}
#else
/** Write (2 bytes) to 10359 board or sensor*/
/** Write (2 bytes) to 10359 board or sensor in ASAP mode*/
int multisensor_write_i2c(int sensor_port,///< sensor port number
const char * class_name, ///< device class name ("el10359", "mt9p006")
int sa7_offs, ///< 0 for 10359 and sensor broadcast, 2/4/6 for sensor channels
......@@ -910,14 +915,56 @@ int multisensor_write_i2c(int sensor_port,///< sensor port number
u32 reg_data) ///< data to send (2 bytes)
///< @return 0: success, negative - error
{
return x393_xi2c_write_reg(class_name, // device class name
int rslt;
inc_unbalanced_writes(sensor_port);
rslt = x393_xi2c_write_reg(class_name, // device class name
sensor_port, // sensor port number
sa7_offs, // slave address (7-bit) offset from the class defined slave address
reg_addr, // register address (width is defined by class)
reg_data); // data to write (width is defined by class)
if (rslt <0) return rslt;
if (check_unbalanced_writes(sensor_port)){
unsigned long bitstream_version;
// X3X3_I2C_RCV4(sensor_port, I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version);
X3X3_I2C_RCV2(sensor_port, I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version); // just 2 bytes, not 4
dev_dbg(g_dev_ptr,"Exceeded number of unbalanced writes on port %d: (%d > %d), reading i2c, got 0x%lx\n",sensor_port, get_unbalanced_writes(sensor_port) ,i2c_get_max_unbalanced_writes(),bitstream_version);
}
// wait for the write buffer to have some room
if (!x393_xi2c_ready_wr (sensor_port)){
dev_dbg(g_dev_ptr,"Had to wait for the i2c sequencer while multisensor_write_i2c(%d, %s, 0x%x, 0x%x, 0x%x)\n",
sensor_port, class_name, sa7_offs,reg_addr, reg_data);
return x393_xi2c_wait_wr(sensor_port);
}
return 0;
}
#endif
/*
* unsigned long bitstream_version;
unsigned long sensor_id[MAX_SENSORS];
int rslt=0; // or-ed by MULTISENSOR_WRITE_I2C(sa,ra,v,sz)
int i;
int this_sensor_type;
long * multiOutDelay;
// .hact_delay = -2500, // -2.5ns delay in ps
// .sensorDelay = 2460, // Delay from sensor clock at FPGA output to pixel data transition (FPGA input), short cable (ps)
multi_unitialized=0; // reset this static variable - it will prevent copying individual flips to multiple until composite mode is used
dev_dbg(g_dev_ptr,"frame16=%d\n",frame16);
GLOBALPARS(sensor_port,G_SENS_AVAIL)=0; // no 10359A board present
if (frame16 >= 0) return -1; // can only work in ASAP mode
if (thispars->pars[P_SENSOR]) return 0; // Sensor is already detected - do not bother (to re-detect it P_SENSOR should be set to 0)
#ifdef NC353
dev_dbg(g_dev_ptr,"Probing 10359 board, i2c bitdelays=0x%08x, hardware_i2c_running=%d\n",i2c_delays(0),i2s_running());
if (multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version, 4)<0) return -1;
#else
if (X3X3_I2C_RCV4(sensor_port, I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version)<0) return -1;
#endif
*
unbalanced_writes[sensor_port]=0;
// int unbalanced_writes [SENSOR_PORTS];
// #define MAX_UNBALANCED_WRITES 32
*/
static int multi_unitialized=0; ///< temporary hack to resolve race between individual and multi_ flips at startup
......@@ -958,12 +1005,12 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
// .hact_delay = -2500, // -2.5ns delay in ps
// .sensorDelay = 2460, // Delay from sensor clock at FPGA output to pixel data transition (FPGA input), short cable (ps)
multi_unitialized=0; // reset this static variable - it will prevent copying individual flips to multiple until composite mode is used
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
dev_dbg(g_dev_ptr,"frame16=%d\n",frame16);
GLOBALPARS(sensor_port,G_SENS_AVAIL)=0; // no 10359A board present
if (frame16 >= 0) return -1; // can only work in ASAP mode
if (thispars->pars[P_SENSOR]) return 0; // Sensor is already detected - do not bother (to re-detect it P_SENSOR should be set to 0)
#ifdef NC353
dev_dbg(g_dev_ptr,"%s Probing 10359 board, i2c bitdelays=0x%08x, hardware_i2c_running=%d\n",__func__,i2c_delays(0),i2s_running());
dev_dbg(g_dev_ptr,"Probing 10359 board, i2c bitdelays=0x%08x, hardware_i2c_running=%d\n",i2c_delays(0),i2s_running());
if (multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version, 4)<0) return -1;
#else
if (X3X3_I2C_RCV4(sensor_port, I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version)<0) return -1;
......@@ -975,18 +1022,18 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
add_sensor_proc(sensor_port,onchange_sensorphase, &multisensor_pgm_sensorphase); // set clock/phase for the 10359A
if ((((bitstream_version ^ I2C359_MINVERSION) & 0xffff0000)!=0) || ((bitstream_version & 0xffff) < (I2C359_MINVERSION & 0xffff))) {
printk ("invalid 10359 bitstream version, found 0x%08lx, required >= 0x%08x\n",bitstream_version, I2C359_MINVERSION );
dev_err(g_dev_ptr,"invalid 10359 bitstream version, found 0x%08lx, required >= 0x%08x\n",bitstream_version, I2C359_MINVERSION );
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType);
return -1;
}
printk("10359 bitstream version =0x%08lx\n",bitstream_version);
dev_dbg(g_dev_ptr,"10359 bitstream version =0x%08lx\n",bitstream_version);
// now set sensor clock in both system board and 10359A to 96MHz - currently we support only 5MPix in thias mode
#ifdef NC353
setFramePar(sensor_port, thispars, P_CLK_FPGA, getClockFreq(0)); // just in case - read the actual fpga clock frequency and store it (no actions)
setFramePar(sensor_port, thispars, P_CLK_SENSOR, 96000000);
setClockFreq(sensor_port, 1, thispars->pars[P_CLK_SENSOR]);
#endif
printk("10353 sensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]);
dev_info(g_dev_ptr,"10353 sensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]);
udelay (100);// 0.0001 sec to stabilize clocks
// X3X3_RSTSENSDCM; // FPGA DCM can fail after clock change, needs to be reset
......@@ -1018,11 +1065,11 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
}
#endif
rslt=multisensor_set_freq (sensor_port, 1, thispars); // first time (1)
if (rslt>0) printk("10359A sensor clock set to %d\n", rslt);
else if (rslt==0) printk("10359A sensors are using 10353 system clock, as set in configuration\n");
else printk("10359 sensor clock failure, will use system clock from 10353 board\n");
if (rslt>0) dev_info(g_dev_ptr,"10359A sensor clock set to %d\n", rslt);
else if (rslt==0) dev_info(g_dev_ptr,"10359A sensors are using 10353 system clock, as set in configuration\n");
else dev_info(g_dev_ptr,"10359 sensor clock failure, will use system clock from 10353 board\n");
// Try to read chip version from each of the 3 possible sensors
printk("removing MRST from the sensor\n");
dev_info(g_dev_ptr,"removing MRST from the sensor\n");
//
sensio_ctl.d32 = 0;
sensio_ctl.mrst = 1;
......@@ -1036,9 +1083,10 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
udelay (100);
GLOBALPARS(sensor_port,G_SENS_AVAIL) |= 1<< (GLOBALPARS(sensor_port,G_SENS_AVAIL)); // temporary to indicate sensor detection functions that they need to initialize multisensor registers
for (i=0;i<MAX_SENSORS;i++) {
// for (i=0;i<MAX_SENSORS;i++) {
for (i=0;i<3;i++) { // 10359 only supports 3 sesnors, not 4
#ifdef NC353
dev_dbg(g_dev_ptr,"%s Probing sensor port %d, i2c bitdelays=0x%08x\n",__func__,i,i2c_delays(0));
dev_dbg(g_dev_ptr,"Probing sensor port %d, i2c bitdelays=0x%08x\n",i,i2c_delays(0));
rslt= multisensor_read_i2c(sensor_port,
MT9P001_I2C_ADDR + ((i+1) * I2C359_INC),
P_MT9X001_CHIPVER,
......@@ -1050,35 +1098,37 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
P_MT9X001_CHIPVER,
&sensor_id[i]);
#endif
// dev_dbg(g_dev_ptr,"%s Probing sensor port %d, i2c bitdelays=0x%08x, rslt=0x%x\n",__func__,i,i2c_delays(0),rslt);
// dev_dbg(g_dev_ptr,"Probing sensor port %d, i2c bitdelays=0x%08x, rslt=0x%x\n",i,i2c_delays(0),rslt);
if (rslt==0) {
if (((sensor_id[i] ^ MT9P001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9P001 2592x1944 sensor on 10359A port %d, chip ID=%lx\n",(i+1), sensor_id[i]);
dev_info(g_dev_ptr,"Found MT9P001 2592x1944 sensor on 10359A port %d, chip ID=%lx\n",(i+1), sensor_id[i]);
GLOBALPARS(sensor_port,G_SENS_AVAIL) |= 1<<i;
} else if (sensor_id[i] == 0xffff){
sensor_id[i]=0;
} else {
printk("Found UNSUPPORTED sensor on port %d, chip ID=0x%lx\n",(i+1),sensor_id[i]);
dev_warn(g_dev_ptr,"Found UNSUPPORTED sensor on port %d, chip ID=0x%lx\n",(i+1),sensor_id[i]);
}
} else sensor_id[i]=0;
}
GLOBALPARS(sensor_port,G_SENS_AVAIL) &= (1<< (GLOBALPARS(sensor_port,G_SENS_AVAIL)))-1; // remove flag used to indicate sensor detection functions that they need to initialize multisesnor registers
if (GLOBALPARS(sensor_port,G_SENS_AVAIL)==0) {
printk ("No supported sensors connected to 10359A board\n");
dev_warn(g_dev_ptr,"No supported sensors connected to 10359A board\n");
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
return 0;
}
printk ("Setting internal HACT generation\n");
dev_info(g_dev_ptr,"Setting internal HACT generation\n");
MULTISENSOR_WRITE_I2C16_SHADOW(sensor_port, I2C359_HACT_MODE, 7);
// At least one MT9P0X1 sensor found, initializing them in broadcast mode (will still need to modify phases - both 10353 and 10359
this_sensor_type=mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
// for (i=0;i<8;i++) {
// dev_dbg(g_dev_ptr,"%s i=%d, m=0x%lx\n",__func__,i,GLOBALPARS(G_MULTI_REGSM+i));
// dev_dbg(g_dev_ptr,"i=%d, m=0x%lx\n",i,GLOBALPARS(G_MULTI_REGSM+i));
// }
initMultiPars(sensor_port); // this time the registors that need to have individual shadows are known, initialize the corresponding data structures
// memcpy(psensor, sensor, sizeof(struct sensor_t)); // copy physical sensor definitions to the save area (so some can be replaced by modified ones)
// dev_dbg(g_dev_ptr,"%s before: sensorproc_phys->sensor.sensorDelay=0x%x\n",__func__, sensorproc_phys->sensor.sensorDelay);
// dev_dbg(g_dev_ptr,"before: sensorproc_phys->sensor.sensorDelay=0x%x\n", sensorproc_phys->sensor.sensorDelay);
copy_sensorproc(sensor_port, sensorproc_phys); // save physical sensor functions
// dev_dbg(g_dev_ptr,"%s after: sensorproc_phys->sensor.sensorDelay=0x%x\n",__func__, sensorproc_phys->sensor.sensorDelay);
// dev_dbg(g_dev_ptr,"after: sensorproc_phys->sensor.sensorDelay=0x%x\n", sensorproc_phys->sensor.sensorDelay);
// Now calculate phases, swap ones from the sensor
multiOutDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_OUT);
......@@ -1086,7 +1136,7 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
sensor->hact_delay=0; // No hact delay on 10359 output
sensor->sensorDelay=multiOutDelay[0];
dev_dbg(g_dev_ptr,"%s replaced: sensor->sensorDelay=0x%x\n",__func__, sensor->sensorDelay);
dev_dbg(g_dev_ptr,"replaced: sensor->sensorDelay=0x%x\n", sensor->sensorDelay);
//sensorproc_phys->sensor
/*
Now overwrite sensor functions with it's own (originals (physical sensor ones) are already copied to the local structure
......@@ -1218,20 +1268,20 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
int new_sensor=selected-1; // >=0
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
dev_dbg(g_dev_ptr,"frame16=%d\n",frame16);
if (!sensor_mask) sensor_mask=GLOBALPARS(sensor_port, G_SENS_AVAIL) ;// if none sensors were enabled - enable all what is available (same as with WOI size)
if (composite && (!async)) {
printk("*** CANNOT USE COMPOSITE MODE WITH FREE RUNNING SENSOR ***\n");
dev_err(g_dev_ptr,"*** CANNOT USE COMPOSITE MODE WITH FREE RUNNING SENSOR ***\n");
composite=0;
SETFRAMEPARS_SET(P_MULTI_MODE,0); // Do we need to force anything here? If it was async->free transition? Or just TRIG mode should have all the dependencies of P_MULTI_MODE
}
// TODO: recalculate sequence when MULTISENS_EN is chnaged (tried 5 - did not modify sequence, showed first frame only)
// Here - only recalculate SENSOR_HEIGHT, skipping disabled sensors. in multisensor_pgm_window() will need to skip disabled also
// No above is not really needed, sequence+enable can be handled by application software
dev_dbg(g_dev_ptr,"%s composite=0x%x\n",__func__,composite);
dev_dbg(g_dev_ptr,"%s sequence=0x%x\n",__func__, sequence);
dev_dbg(g_dev_ptr,"composite=0x%x\n",composite);
dev_dbg(g_dev_ptr,"sequence=0x%x\n", sequence);
// if sequence is zero, put "1-2-3"
if (sequence==0) {
j=1;
......@@ -1262,9 +1312,9 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
}
if ((selected==0) || !((1 << (selected-1)) & GLOBALPARS(sensor_port, G_SENS_AVAIL))) selected=sequence & 3; // if not set or invalid - set to first in sequence
dev_dbg(g_dev_ptr,"%s selected=0x%x, thispars->pars[P_MULTI_SELECTED]=0x%x\n",__func__, selected, (int) thispars->pars[P_MULTI_SELECTED]);
dev_dbg(g_dev_ptr,"%s sequence=0x%x\n",__func__, sequence);
dev_dbg(g_dev_ptr,"%s sensor_mask=0x%x\n",__func__, sensor_mask);
dev_dbg(g_dev_ptr,"selected=0x%x, thispars->pars[P_MULTI_SELECTED]=0x%x\n", selected, (int) thispars->pars[P_MULTI_SELECTED]);
dev_dbg(g_dev_ptr,"sequence=0x%x\n", sequence);
dev_dbg(g_dev_ptr,"sensor_mask=0x%x\n", sensor_mask);
SETFRAMEPARS_COND(P_MULTI_SELECTED, selected);
SETFRAMEPARS_COND(P_MULTI_SEQUENCE, sequence);
SETFRAMEPARS_COND(P_MULTISENS_EN, sensor_mask);
......@@ -1274,14 +1324,14 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
// int old_sensor=prev_selected-1; // may be <0
// int new_sensor=selected-1; // >=0
if (multi_unitialized && (!prev_composite) && (old_sensor>=0)) { // was single-sensor mode, copy P_WOI_* to individual sensor WOI and FLIPS
dev_dbg(g_dev_ptr,"%s multi_unitialized=%d old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, multi_unitialized, old_sensor, multi_fliph,multi_flipv);
dev_dbg(g_dev_ptr,"multi_unitialized=%d old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", multi_unitialized, old_sensor, multi_fliph,multi_flipv);
wois[(P_MULTI_WIDTH1- P_MULTI_WOI)+old_sensor]= prevpars->pars[P_WOI_WIDTH];
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+old_sensor]= prevpars->pars[P_WOI_HEIGHT];
wois[(P_MULTI_LEFT1- P_MULTI_WOI)+old_sensor]= prevpars->pars[P_WOI_LEFT];
wois[(P_MULTI_TOP1- P_MULTI_WOI)+old_sensor]= prevpars->pars[P_WOI_TOP];
multi_fliph= (multi_fliph & (~(1<<old_sensor))) | ((prevpars->pars[P_FLIPH] & 1) << old_sensor);
multi_flipv= (multi_flipv & (~(1<<old_sensor))) | ((prevpars->pars[P_FLIPV] & 1) << old_sensor);
dev_dbg(g_dev_ptr,"%s multi_unitialized=%d old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, multi_unitialized, old_sensor, multi_fliph,multi_flipv);
dev_dbg(g_dev_ptr,"multi_unitialized=%d old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", multi_unitialized, old_sensor, multi_fliph,multi_flipv);
}
if (multi_unitialized && (!composite) && (prev_composite || ((new_sensor>=0) && (old_sensor!=new_sensor)))) { // now single-sensor mode, set P_WOI* from saved parameters
if ((wois[(P_MULTI_WIDTH1- P_MULTI_WOI)+new_sensor]==0) || (wois[(P_MULTI_HEIGHT1- P_MULTI_WOI)+new_sensor]==0)) {
......@@ -1295,7 +1345,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
wois[(P_MULTI_LEFT1- P_MULTI_WOI)+new_sensor]= 0;
wois[(P_MULTI_TOP1- P_MULTI_WOI)+new_sensor]= 0;
multi_fliph= (multi_fliph & (~(1<<new_sensor))); // =0
dev_dbg(g_dev_ptr,"%s new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, new_sensor, old_sensor, multi_fliph,multi_flipv);
dev_dbg(g_dev_ptr,"new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", new_sensor, old_sensor, multi_fliph,multi_flipv);
multi_flipv= (multi_flipv & (~(1<<new_sensor))); // =0
} else { // was one single channel, now the different (not initialized window) one - copy window parameters
wois[(P_MULTI_WIDTH1- P_MULTI_WOI)+new_sensor]= prevpars->pars[P_WOI_WIDTH];
......@@ -1304,7 +1354,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
wois[(P_MULTI_TOP1- P_MULTI_WOI)+new_sensor]= prevpars->pars[P_WOI_TOP];
multi_fliph= (multi_fliph & (~(1<<new_sensor))) | ((prevpars->pars[P_FLIPH] & 1) << new_sensor);
multi_flipv= (multi_flipv & (~(1<<new_sensor))) | ((prevpars->pars[P_FLIPV] & 1) << new_sensor);
dev_dbg(g_dev_ptr,"%s new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, new_sensor, old_sensor, multi_fliph,multi_flipv);
dev_dbg(g_dev_ptr,"new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", new_sensor, old_sensor, multi_fliph,multi_flipv);
}
}
// saved sensor WOI are OK (or just fixed), use them
......@@ -1314,7 +1364,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
SETFRAMEPARS_COND(P_WOI_TOP, wois[(P_MULTI_TOP1- P_MULTI_WOI)+new_sensor] );
SETFRAMEPARS_COND(P_FLIPH, (multi_fliph>>new_sensor) & 1);
SETFRAMEPARS_COND(P_FLIPV, (multi_flipv>>new_sensor) & 1);
dev_dbg(g_dev_ptr,"%s new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, new_sensor, old_sensor, multi_fliph,multi_flipv);
dev_dbg(g_dev_ptr,"new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", new_sensor, old_sensor, multi_fliph,multi_flipv);
}
// Validate hights for all enabled channels (OK to skip disabled here)
oversize=thispars->pars[P_OVERSIZE];
......@@ -1330,30 +1380,30 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
else if ((!oversize) && (height1 > sensor->imageHeight)) height1=sensor->imageHeight; // use clearHeight here?
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(0,sequence)]=height1;
total_height=height1;
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
dev_dbg(g_dev_ptr,"total_height=0x%x\n",total_height);
// is there frame 2 enabled?
multi_frame=0;
if (composite && SENSOR_IN_SEQ_EN(1,sequence,sensor_mask)) { // specified in sequence is enabled
multi_frame=1;
total_height+=(vblank+(2 * COLOR_MARGINS))*dv;
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
dev_dbg(g_dev_ptr,"total_height=0x%x\n",total_height);
if (!height2) height2=sensor->imageHeight;
if (height2 < sensor->minHeight) height2=sensor->minHeight;
else if (height2 > sensor->arrayHeight) height2=sensor->arrayHeight;
else if ((!oversize) && (height2 > sensor->imageHeight)) height2=sensor->imageHeight; // use clearHeight here?
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(1,sequence)]=height2;
total_height+=height2;
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
dev_dbg(g_dev_ptr,"total_height=0x%x\n",total_height);
if (SENSOR_IN_SEQ_EN(2,sequence,sensor_mask)) {
total_height+=(vblank+(2 * COLOR_MARGINS))*dv;
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
dev_dbg(g_dev_ptr,"total_height=0x%x\n",total_height);
if (!height3) height3=sensor->imageHeight;
if (height3 < sensor->minHeight) height3=sensor->minHeight;
else if (height3 > sensor->arrayHeight) height3=sensor->arrayHeight;
else if ((!oversize) && (height2 > sensor->imageHeight)) height3=sensor->imageHeight; // use clearHeight here?
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(2,sequence)]=height3;
total_height+=height3;
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
dev_dbg(g_dev_ptr,"total_height=0x%x\n",total_height);
}
}
if (composite) {
......@@ -1393,7 +1443,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
}
SETFRAMEPARS_COND(P_MULTI_FLIPH, multi_fliph);
SETFRAMEPARS_COND(P_MULTI_FLIPV, multi_flipv);
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
dev_dbg(g_dev_ptr,"total_height=0x%x\n",total_height);
SETFRAMEPARS_COND(P_SENSOR_HEIGHT, total_height);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes, schedule functions
......@@ -1414,10 +1464,10 @@ int calcThisPhase(int clk_period, ///< cklock period (Hz)
{
int px_delay=-(clk_period/2 - FPGADelay- cableDelay - sensorDelay) ; // static int sensorDelay
int px_delay90=(4*px_delay+clk_period/2)/clk_period;
MDF16(printk ("cableDelay1=%ld, FPGADelay1=%ld, clk_period=%d\r\n",cableDelay, FPGADelay, clk_period));
MDF16(printk ("px_delay1=%d\r\n",px_delay));
MDF16(printk ("cableDelay1=%ld, FPGADelay1=%ld, clk_period=%d\n",cableDelay, FPGADelay, clk_period));
MDF16(printk ("px_delay1=%d\n",px_delay));
px_delay -= (px_delay90*clk_period)/4; // -clk_period/8<= now px_delay <= +clk_period/8
MDF16(printk ("px_delay=%d, px_delay90=%d\r\n",px_delay,px_delay90));
MDF16(printk ("px_delay=%d, px_delay90=%d\n",px_delay,px_delay90));
px_delay/= FPGA_DCM_STEP; // in DCM steps
return (px_delay & 0xffff) | ((px_delay90 & 3) <<16) | 0x80000;
}
......@@ -1444,41 +1494,46 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
int thisPhase1= thispars->pars[P_MULTI_PHASE1];
int thisPhase2= thispars->pars[P_MULTI_PHASE2];
int thisPhase3= thispars->pars[P_MULTI_PHASE3];
unsigned long sensor_clk = 90000000; // just deafult if not yet set up
uint64_t ull_result = 1000000000000LL;
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
dev_dbg(g_dev_ptr,"frame16=%d\n",frame16);
if (frame16 >= 0) return -1; // can only work in ASAP mode
//changed (just set) clock frequency initiates calculation of phase settings
if (!multi_phases_initialized || (thispars->pars[P_CLK_SENSOR] != prevpars->pars[P_CLK_SENSOR])) { // system clock is already set to the new frequency
if (thispars->pars[P_CLK_SENSOR] == prevpars->pars[P_CLK_SENSOR]) {
printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__); printk ("WARNING: ((thispars->pars[P_CLK_SENSOR] == prevpars->pars[P_CLK_SENSOR])) but multi_phases_initialized is not yet set (re-init?)\n");
dev_warn(g_dev_ptr,"WARNING: ((thispars->pars[P_CLK_SENSOR] == prevpars->pars[P_CLK_SENSOR])) but multi_phases_initialized is not yet set (re-init?)\n");
}
multisensor_set_freq (sensor_port, 0, thispars); // not the first time. Assuming no clock chip if clock4 is not set
reset=1;
// TODO: put here calculation of the sensor phases in 10359 from bitstream data and clock rate
// clk_period= 1000000000000.0f/thispars->pars[P_CLK_SENSOR]; // period in ps
if (!thispars->pars[P_CLK_SENSOR]){
dev_warn(g_dev_ptr,"Sensor clock is not set, using default 0x%lx\n",sensor_clk);
} else {
sensor_clk = thispars->pars[P_CLK_SENSOR];
}
do_div(ull_result,thispars->pars[P_CLK_SENSOR]);
clk_period= ull_result;
// Now for each of 3 sensor ports of the 10359
cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C1);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P1);
thisPhase1=calcThisPhase(clk_period, FPGADelay[0], cableDelay[0], sensorproc_phys->sensor.sensorDelay) | 0x80000;
dev_dbg(g_dev_ptr,"%s cableDelay1=0x%lx FPGADelay1= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase1=0x%x\n",__func__,cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase1);
dev_dbg(g_dev_ptr,"cableDelay1=0x%lx FPGADelay1= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase1=0x%x\n",cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase1);
cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C2);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P2);
thisPhase2=calcThisPhase(clk_period, FPGADelay[0], cableDelay[0], sensorproc_phys->sensor.sensorDelay) | 0x80000;
dev_dbg(g_dev_ptr,"%s cableDelay2=0x%lx FPGADelay2= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase3=0x%x\n",__func__,cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase2);
dev_dbg(g_dev_ptr,"cableDelay2=0x%lx FPGADelay2= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase3=0x%x\n",cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase2);
cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C3);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P3);
thisPhase3=calcThisPhase(clk_period, FPGADelay[0], cableDelay[0], sensorproc_phys->sensor.sensorDelay) | 0x80000;
dev_dbg(g_dev_ptr,"%s cableDelay3=0x%lx FPGADelay3= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase3=0x%x\n",__func__,cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase3);
dev_dbg(g_dev_ptr,"cableDelay3=0x%lx FPGADelay3= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase3=0x%x\n",cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase3);
// TODO: calculate SDRAM phase here too.
adjustSDRAMNeed=1;
multi_phases_initialized=1;
}
if (reset) {
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_DCM_SYSTEM, I2C359_DCM_RESET | I2C359_DCM_RESET90);
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_DCM_SDRAM, I2C359_DCM_RESET | I2C359_DCM_RESET90);
......@@ -1489,24 +1544,23 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
thisPhaseSDRAM=multisensor_adjustSDRAM (sensor_port, FPGA_DCM_RANGE);
if (thisPhaseSDRAM>=0) {
SETFRAMEPARS_SET(P_MULTI_PHASE_SDRAM, thisPhaseSDRAM);
printk("10359 SDRAM clock phase is set to %d/%s%d\n",
dev_info(g_dev_ptr,"10359 SDRAM clock phase is set to %d/%s%d\n",
90*((thisPhaseSDRAM>>16) & 3),
(thisPhaseSDRAM & 0x8000)?"-":"+",
(thisPhaseSDRAM & 0x8000)?(0x10000-(thisPhaseSDRAM & 0xffff)):(thisPhaseSDRAM & 0xffff));
} else {
printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);
printk ("**** ERROR adjusting SDRAM clock phase in %s:%d:%s, result=0x%x\n",__FILE__,__LINE__,__FUNCTION__,thisPhaseSDRAM);
dev_warn (g_dev_ptr,"**** ERROR adjusting SDRAM clock phase in %s:%d:%s, result=0x%x\n",__FILE__,__LINE__,__FUNCTION__,thisPhaseSDRAM);
}
} else {
resetThisDCM=reset || (thisPhaseSDRAM & 0x80000);
rslt= multisensor_set_phase (sensor_port, I2C359_DCM_SDRAM, resetThisDCM, thisPhaseSDRAM, prevpars->pars[P_MULTI_PHASE_SDRAM]);
if ((rslt>=0) && (rslt != thisPhaseSDRAM)) SETFRAMEPARS_SET(P_MULTI_PHASE_SDRAM, rslt);
if (resetThisDCM) {
dev_dbg(g_dev_ptr,"%s re-initializing SDRAM on 10359 after DCM reset\n",__func__);
dev_dbg(g_dev_ptr,"re-initializing SDRAM on 10359 after DCM reset\n");
multisensor_initSDRAM(sensor_port, thispars); // init 10359 SDRAM
}
// Test memory phase here
printk ("\nMULTI_PHASE_SDRAM=%01x %04x\n", (rslt>>16), rslt & 0xffff);
dev_dbg(g_dev_ptr,"\nMULTI_PHASE_SDRAM=%01x %04x\n", (rslt>>16), rslt & 0xffff);
if (thisPhaseSDRAM & 0x100000) {
for (rslt=0;rslt<16;rslt++) {
multisensor_memphase_debug(sensor_port, -1);
......@@ -1557,22 +1611,27 @@ int multisensor_set_freq (int sensor_port, ///< sensor port numb
int rslt=0;
int i;
int was_sensor_freq=0;
if (!(GLOBALPARS(sensor_port, G_MULTI_CFG) && (1<<G_MULTI_CFG_SYSCLK))) { // skip local clock if disabled in configuration
// was_sensor_freq=getClockFreq(I2C359_CLK_NUMBER);
int clock_src= (GLOBALPARS(sensor_port, G_MULTI_CFG) && (1<<G_MULTI_CFG_SYSCLK))?I2C359_CLKSRC_SYSTEM:I2C359_CLKSRC_LOCAL;
was_sensor_freq=x393_getClockFreq(sensor_port, I2C359_CLK_NUMBER & 3); // clock 0
dev_dbg(g_dev_ptr,"GLOBALPARS(%d, G_MULTI_CFG) = 0x%lx, was_sensor_freq=%d\n",sensor_port, GLOBALPARS(sensor_port, G_MULTI_CFG),was_sensor_freq);
if (first || (was_sensor_freq !=0)) { // Otherwise it is likely rev 0 - no clock
// was_sensor_freq=getClockFreq(1);
// was_sensor_freq=getClockFreq(1);
was_sensor_freq=90000000; // TODO: Find out how to read actual clock frequency for sensor ports
// i=setClockFreq(I2C359_CLK_NUMBER, was_sensor_freq);
// i=setClockFreq(I2C359_CLK_NUMBER, was_sensor_freq);
// CY22393 probably has insufficient voltage to operate, bypassing it completely
if (clock_src == I2C359_CLKSRC_LOCAL) {
i=x393_setClockFreq(sensor_port, I2C359_CLK_NUMBER & 3, was_sensor_freq);
} else {
i=was_sensor_freq;
}
if (i>0) {
MULTISENSOR_WRITE_I2C16_SHADOW(sensor_port, I2C359_CLKSRC, I2C359_CLKSRC_LOCAL);
MULTISENSOR_WRITE_I2C16_SHADOW(sensor_port, I2C359_CLKSRC, clock_src);
mdelay (50); // 0.05 sec to stabilize clocks - will miss multiple frames
} else {
was_sensor_freq=-1; // error
}
}
}
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_DCM_SENSOR1, I2C359_DCM_RESET | I2C359_DCM_RESET90 | I2C359_DCM_HACT_RESET);
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_DCM_SENSOR2, I2C359_DCM_RESET | I2C359_DCM_RESET90 | I2C359_DCM_HACT_RESET);
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_DCM_SENSOR3, I2C359_DCM_RESET | I2C359_DCM_RESET90 | I2C359_DCM_HACT_RESET);
......@@ -1673,7 +1732,7 @@ int multisensor_set_phase_recover(int sensor_port, ///< sensor port nu
else goodPhase = newPhase;
}
rslt=goodPhase;
dev_dbg(g_dev_ptr,"%s Reduced NewPhase, goodPhase= 0x%lx oldPhase= 0x%lx\r\n",__func__, goodPhase, oldPhase );
dev_dbg(g_dev_ptr,"Reduced NewPhase, goodPhase= 0x%lx oldPhase= 0x%lx\n", goodPhase, oldPhase );
}
return rslt;
}
......@@ -1697,14 +1756,14 @@ int multisensor_set_phase (int sensor_port, ///< sensor port number (0
int diff_phase90;
int rslt=0;
int i;
MDF24(printk("reg_addr=0x%x resetDCM=%d newPhase90=0x%lx newPhase= 0x%lx oldPhase= 0x%lx\r\n",\
MDF24(printk("reg_addr=0x%x resetDCM=%d newPhase90=0x%lx newPhase= 0x%lx oldPhase= 0x%lx\n",\
reg_addr, resetDCM, newPhase>>16, newPhase & 0xffff, oldPhase ));
if (resetDCM || (newPhase & 0x8000)) {
MULTISENSOR_WRITE_I2C16(sensor_port, reg_addr, I2C359_DCM_RESET | I2C359_DCM_RESET90);
oldPhase=0;
}
if (newPhase!=oldPhase) {
dev_dbg(g_dev_ptr,"%s newPhase= 0x%lx oldPhase= 0x%lx\r\n",__func__, newPhase, oldPhase );
dev_dbg(g_dev_ptr,"newPhase= 0x%lx oldPhase= 0x%lx\n", newPhase, oldPhase );
old_phase= oldPhase & 0xffff; if (old_phase>=0x8000) old_phase-=0x10000; // make it signed
old_phase90= (oldPhase >> 16) & 3;
if ((old_phase > 255) || (old_phase < -255)) {
......@@ -1720,9 +1779,9 @@ int multisensor_set_phase (int sensor_port, ///< sensor port number (0
diff_phase90=phase90-old_phase90;
if (diff_phase90>2) diff_phase90-=4;
else if (diff_phase90<-1)diff_phase90+=4;
dev_dbg(g_dev_ptr,"%s old_phase= 0x%x old_phase90= 0x%x\r\n",__func__, old_phase, old_phase90 );
dev_dbg(g_dev_ptr,"%s phase= 0x%x phase90= 0x%x\r\n",__func__, phase, phase90 );
dev_dbg(g_dev_ptr,"%s diff_phase=0x%x diff_phase90=0x%x\r\n",__func__, diff_phase, diff_phase90 );
dev_dbg(g_dev_ptr,"old_phase= 0x%x old_phase90= 0x%x\n", old_phase, old_phase90 );
dev_dbg(g_dev_ptr,"phase= 0x%x phase90= 0x%x\n", phase, phase90 );
dev_dbg(g_dev_ptr,"diff_phase=0x%x diff_phase90=0x%x\n", diff_phase, diff_phase90 );
if (diff_phase > 0) for (i=diff_phase; i > 0; i--) MULTISENSOR_WRITE_I2C16(sensor_port, reg_addr, I2C359_DCM_INC )
else if (diff_phase < 0) for (i=diff_phase; i < 0; i++) MULTISENSOR_WRITE_I2C16(sensor_port, reg_addr, I2C359_DCM_DEC )
if (diff_phase90 > 0) for (i=diff_phase90; i > 0; i--) MULTISENSOR_WRITE_I2C16(sensor_port, reg_addr, I2C359_DCM_INC90 )
......@@ -1803,17 +1862,17 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
}
}
if (low90 < 0){
printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);
printk ("**** ERROR adjusting SDRAM clock phase in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
printk ("oks90=%d, ok90=0x%x, centroids90=0x%x 0x%x 0x%x 0x%x\n",oks90,ok90,centroids90[0],centroids90[1],centroids90[2],centroids90[3]);
dev_err(g_dev_ptr,"%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);
dev_err(g_dev_ptr,"**** ERROR adjusting SDRAM clock phase in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
dev_err(g_dev_ptr,"oks90=%d, ok90=0x%x, centroids90=0x%x 0x%x 0x%x 0x%x\n",oks90,ok90,centroids90[0],centroids90[1],centroids90[2],centroids90[3]);
return -1;
}
break;
// was: fall through to default branch
default:
printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);
printk ("**** ERROR adjusting SDRAM clock phase in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
printk ("oks90=%d, ok90=0x%x, centroids90=0x%x 0x%x 0x%x 0x%x\n",oks90,ok90,centroids90[0],centroids90[1],centroids90[2],centroids90[3]);
dev_err(g_dev_ptr,"%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);
dev_err(g_dev_ptr,"**** ERROR adjusting SDRAM clock phase in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
dev_err(g_dev_ptr,"oks90=%d, ok90=0x%x, centroids90=0x%x 0x%x 0x%x 0x%x\n",oks90,ok90,centroids90[0],centroids90[1],centroids90[2],centroids90[3]);
return -1;
}
// now find low margin
......@@ -1835,7 +1894,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
i=(low_l+low_h)/2;
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
dev_dbg(g_dev_ptr," DCM error=%d\n",-oldPhase);
needReset=1;
if ((oldPhase!=-I2C359_DCM_ERR_OVFL) && (oldPhase!=-I2C359_DCM_ERR_NODONE)) return oldPhase; // other errors fatal
else low_l=i; // bad
......@@ -1860,7 +1919,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
i=(high_h+high_l)/2;
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
dev_dbg(g_dev_ptr," DCM error=%d\n",-oldPhase);
needReset=1;
if ((oldPhase!=-I2C359_DCM_ERR_OVFL) && (oldPhase!=-I2C359_DCM_ERR_NODONE)) return oldPhase; // other errors fatal
else high_h=i; // bad
......@@ -1870,20 +1929,20 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
else high_h=i; // bad
}
}
MDF24 (printk(" low90=%d, low=%d, high90=%d, high=%d\n",low90,low_h,high90,high_l));
dev_dbg(g_dev_ptr,"low90=%d, low=%d, high90=%d, high=%d\n",low90,low_h,high90,high_l);
if (high90==low90) { // 0,1 OK phases
if (high_l>low_h) { // 0,1 OK phases
i= (high90<<16) | (((high_l+low_h)>>1) & 0xffff);
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
if (oldPhase<0) return oldPhase;
// Verify that final phase is OK
// Verify that final phase is OK
if (multisensor_memphase (sensor_port,NULL)==0) return i;
printk ("**** ERROR adjusting SDRAM clock phase (bad between two good points) in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
printk ("low90=%d, low_l=%d, high90=%d, high_l=%d, i=0x%x\n",low90, low_l, high90, high_l,i);
dev_err(g_dev_ptr,"**** ERROR adjusting SDRAM clock phase (bad between two good points) in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
dev_err(g_dev_ptr,"low90=%d, low_l=%d, high90=%d, high_l=%d, i=0x%x\n",low90, low_l, high90, high_l,i);
return -10;
} else {
printk ("**** ERROR adjusting SDRAM clock phase in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
printk ("low90=%d, low_l=%d, high90=%d, high_l=%d\n",low90, low_l, high90, high_l);
dev_err(g_dev_ptr,"**** ERROR adjusting SDRAM clock phase in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
dev_err(g_dev_ptr,"low90=%d, low_l=%d, high90=%d, high_l=%d\n",low90, low_l, high90, high_l);
return -1;
}
}
......@@ -1902,7 +1961,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
i=(low_l+low_h)/2;
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
dev_dbg(g_dev_ptr,"DCM error=%d\n",-oldPhase);
needReset=1;
if ((oldPhase!=-I2C359_DCM_ERR_OVFL) && (oldPhase!=-I2C359_DCM_ERR_NODONE)) return oldPhase; // other errors fatal
else low_l=i; // bad
......@@ -1923,7 +1982,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
i=(high_h+high_l)/2;
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
dev_dbg(g_dev_ptr,"DCM error=%d\n",-oldPhase);
needReset=1;
if ((oldPhase!=-I2C359_DCM_ERR_OVFL) && (oldPhase!=-I2C359_DCM_ERR_NODONE)) return oldPhase; // other errors fatal
else high_h=i; // bad
......@@ -1934,16 +1993,16 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
}
}
}
MDF24 (printk("Re-measured to the same 90-degree phase low90=%d, low=%d, high90=%d, high=%d\n",low90,low_h,high90,high_l));
dev_dbg(g_dev_ptr,"Re-measured to the same 90-degree phase low90=%d, low=%d, high90=%d, high=%d\n",low90,low_h,high90,high_l);
if (high_l>low_h) { // 0,1 OK phases
i= (high90<<16) | (((high_l+low_h)>>1) & 0xffff);
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
return oldPhase; // (both >=0 or error (<0)
} else { // something strange - should not get here
printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);
printk ("**** BUG - should not get here (there were two good 90-degree phases, now none)\n");
printk ("ERROR adjusting SDRAM clock phase in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
printk ("low90=%d, low_l=%d, high90=%d, high_l=%d\n",low90, low_l, high90, high_l);
dev_err(g_dev_ptr,"%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);
dev_err(g_dev_ptr,"**** BUG - should not get here (there were two good 90-degree phases, now none)\n");
dev_err(g_dev_ptr,"ERROR adjusting SDRAM clock phase in %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__);
dev_err(g_dev_ptr,"low90=%d, low_l=%d, high90=%d, high_l=%d\n",low90, low_l, high90, high_l);
return -1;
}
}
......@@ -1962,7 +2021,7 @@ int multisensor_memphase (int sensor_port, ///< Sensor port
MULTISENSOR_WRITE_I2C32(sensor_port, I2C359_SDRAM_CHEN, I2C359_SDRAM_STOP(4) | I2C359_SDRAM_STOP(5)); // initialize write and read channels, reset SDRAM and buffer addresses
MULTISENSOR_WRITE_I2C32(sensor_port, I2C359_SDRAM_CHEN, I2C359_SDRAM_RUN(4) | I2C359_SDRAM_RUN(5)); // enable write and read channels
for (i=0; i<64;i++) {
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_DATA, (((i&7)==3) || ((i&7)==4) || ((i&7)==5))?0xffff:0); // pattern of 5 zeores, 3 ffff-s
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_DATA, (((i&7)==3) || ((i&7)==4) || ((i&7)==5))?0xffff:0); // pattern of 5 zeros, 3 ffff-s
}
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_PAGE_WR, 0); // start page write
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_PAGE_RD, 0); // start page read (expecting i2c to be much slower than page wr/rd
......@@ -1990,7 +2049,7 @@ int multisensor_memphase (int sensor_port, ///< Sensor port
// for (i=0; i<8;i++) printk (" %03x ",setbits[i]); printk("\n");
n=(0x10000*sx)/s;
if (centroid0x10000) centroid0x10000[0]=n;
MDF24 (printk("centroid=0x%x, OK=%d\n",n,OK));
dev_err(g_dev_ptr,"centroid=0x%x, OK=%d\n",n,OK);
return OK?0:(n?n:1); // so if !OK but n=0 - return n=1 (1/0x10000, actually)
}
......@@ -2074,16 +2133,16 @@ int multisensor_pgm_sensorregs (int sensor_port, ///< sensor port
unsigned long bmask32= ((thispars->mod32) >> (P_M10359_REGS>>5)) & (( 1 << (P_M10359_NUMREGS >> 5))-1) ;
unsigned long mask;
int index,index32;
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
dev_dbg(g_dev_ptr,"frame16=%d\n",frame16);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
dev_dbg(g_dev_ptr,"%s bmask32=0x%lx, thispars->mod32=0x%lx, P_M10359_REGS=0x%x, P_M10359_NUMREGS=0x%x\n",__func__,bmask32,thispars->mod32,P_M10359_REGS,P_M10359_NUMREGS);
dev_dbg(g_dev_ptr,"bmask32=0x%lx, thispars->mod32=0x%lx, P_M10359_REGS=0x%x, P_M10359_NUMREGS=0x%x\n",bmask32,thispars->mod32,P_M10359_REGS,P_M10359_NUMREGS);
if (bmask32) {
for (index32=(P_M10359_REGS>>5); bmask32; index32++, bmask32 >>= 1) {
dev_dbg(g_dev_ptr,"%s index32=0x%x, bmask32=0x%lx\n",__func__,index32,bmask32);
dev_dbg(g_dev_ptr,"index32=0x%x, bmask32=0x%lx\n",index32,bmask32);
if (bmask32 & 1) {
mask=thispars->mod[index32];
dev_dbg(g_dev_ptr,"%s mask=0x%lx\n",__func__,mask);
dev_dbg(g_dev_ptr,"mask=0x%lx\n",mask);
for (index=(index32<<5); mask; index++, mask >>= 1) {
if (mask & 1) {
SET_10359_REG (sensor_port, fpga_addr, (index-P_M10359_REGS), thispars->pars[index]);
......
......@@ -51,7 +51,7 @@
//#define I2C359_I2CMUX 0x07
// #define I2C359_I2CMUX_2MEM 0x1
// #define I2C359_I2CMUX_2SENSORS 0x0
#define I2C359_CLKSRC 0x08 ///< register address: clock source
#define I2C359_CLKSRC 0x08 ///< register address: clock source // does not read back
#define I2C359_CLKSRC_SYSTEM 0x00 ///< clock source: system (from the system board over)
#define I2C359_CLKSRC_LOCAL 0x01 ///< clock source: local (clock generator on the 10359 board
#define I2C359_MODE 0x09 ///< register address: mode register
......
......@@ -1096,6 +1096,7 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
}
// dh (decimation changed)?
dh = thispars->pars[P_DCM_HOR];
dh = dh?dh:1;
if (FRAMEPAR_MODIFIED(P_DCM_HOR)) {
if (dh<1) dh=1; else if (dh>32) dh=32;
while ((dh>1) && !(sensor->dcmHor & (1 << (dh-1)))) dh--; // adjust decimation to maximal supported (if requested is not supported)
......@@ -1103,6 +1104,7 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
}
// dv (decimation changed)?
dv = thispars->pars[P_DCM_VERT];
dv = dv?dv:1;
if (FRAMEPAR_MODIFIED(P_DCM_VERT)) {
if (dv<1) dv=1; else if (dv>32) dv=32;
while ((dv>1) && !(sensor->dcmVert & (1 << (dv-1)))) dv--; // adjust decimation to maximal supported (if requested is not supported)
......@@ -1110,6 +1112,7 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
}
// bh (binning changed)?
bh = thispars->pars[P_BIN_HOR];
dv = dv?dv:1;
if (FRAMEPAR_MODIFIED(P_BIN_HOR)) {
if (bh<1) bh=1; else if (bh>dh) bh=dh;
while ((bh>1) && !(sensor->binHor & (1 << (bh-1)))) bh--; // adjust binning to maximal supported (if requested is not supported)
......@@ -1117,6 +1120,7 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
}
// bv (binning changed)?
bv = thispars->pars[P_BIN_VERT];
bv = bv?bv:1;
if (FRAMEPAR_MODIFIED(P_BIN_VERT)) {
if (bv<1) bv=1; else if (bv>dv) bv=dv;
while ((bv>1) && !(sensor->binVert & (1 << (bv-1)))) bv--; // adjust binning to maximal supported (if requested is not supported)
......
......@@ -1141,16 +1141,21 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
for (sensor_port=0; sensor_port< SENSOR_PORTS; sensor_port++) if (ports & (1 << sensor_port)) {
i2c_page_alloc_init(sensor_port); // reset all pages allocation
i2c_page_register(sensor_port, class_10359->slave7);
dev_dbg(g_dev_ptr, "Reset previously allocated pages for port= %d\n",sensor_port);
dev_dbg(g_dev_ptr, "Setting 10359 page for port %d, slave= 0x%x\n",sensor_port,class_10359->slave7);
set_xi2c_wrc(class_10359, sensor_port, class_10359->slave7, 0);
for (subchn = 0; subchn <4; subchn++){ // subchn == 0 - broadcast
dev_sensor.slave7 = class_sensor->slave7 + I2C359_INC * subchn;
dev_dbg(g_dev_ptr, "Setting sensor page for port %d, slave= 0x%x\n",sensor_port,dev_sensor.slave7);
i2c_page_register(sensor_port, dev_sensor.slave7);
set_xi2c_wrc(&dev_sensor, sensor_port, dev_sensor.slave7, 0);
}
// Now register one page for reading 10359 and the sensor using sensor speed data
memcpy(&dev_sensor, class_sensor, sizeof(x393_i2c_device_t)); // dev_sensor));
dev_dbg(g_dev_ptr, "Registering page to read senors 16-bit on port %d, page= 0x%x\n",sensor_port,LEGACY_READ_PAGE2);
i2c_page_register(sensor_port, LEGACY_READ_PAGE2);
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE2);
dev_dbg(g_dev_ptr, "Registering page to read 32-bit data for 10359 on port %d, page= 0x%x\n",sensor_port,LEGACY_READ_PAGE4);
i2c_page_register(sensor_port, LEGACY_READ_PAGE4);
dev_sensor.data_bytes=4; // for reading 10359 in 32-bit mode
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4);
......
......@@ -75,6 +75,9 @@ static u32 i2c_pages_shadow[4][256]; ///< Mostly for debugging to analyze i2c pa
static int sysfs_page[4]; ///< when positive - page locked for exclusive access
static struct device *sdev = NULL; ///< store this device here
static u32 i2c_read_data[4]; ///< last data read from i2c device
static int scale_i2c_speed = 256; // scale i2c speed for all devices, coefficint is scale_i2c_speed/256
static int max_unbalanced_writes = 32; // debug feature used in multi10359 - maximal writes to i2c w/o read
static int unbalanced_writes [SENSOR_PORTS] = {0,0,0,0};
//static DEFINE_SPINLOCK(lock);
static DEFINE_SPINLOCK(sensori2c_lock_0); ///<
......@@ -84,6 +87,39 @@ static DEFINE_SPINLOCK(sensori2c_lock_3); ///<
/** Define array of pointers to locks - hardware allows concurrent writes to different ports tables */
spinlock_t * sensori2c_locks[4] = {&sensori2c_lock_0, &sensori2c_lock_1, &sensori2c_lock_2, &sensori2c_lock_3};
/** Set status to autoupdate mode and wait for updated result (if it was not in autoupdate mode yet) */
void i2c_autoupdate_status(int chn) ///< Sensor port
{
#ifndef LOCK_BH_SENSORI2C
unsigned long flags;
#endif
x393_status_sens_i2c_t status;
x393_status_ctrl_t status_ctrl = get_x393_sensi2c_status_ctrl(chn); // last written data to status_cntrl
if (status_ctrl.mode != 3){
#ifdef LOCK_BH_SENSORI2C
spin_lock_bh(sensori2c_locks[chn]);
#else
spin_lock_irqsave(sensori2c_locks[chn],flags);
#endif
status = x393_sensi2c_status (chn);
status_ctrl.mode = 3;
status_ctrl.seq_num = status.seq_num ^ 0x20;
set_x393_sensi2c_status_ctrl(status_ctrl, chn);
{
int i;
for (i = 0; i < 10; i++) {
status = x393_sensi2c_status(chn);
if (likely(status.seq_num = status_ctrl.seq_num)) break;
}
}
#ifdef LOCK_BH_SENSORI2C
spin_unlock_bh(sensori2c_locks[chn]);
#else
spin_unlock_irqrestore(sensori2c_locks[chn],flags);
#endif
dev_dbg(sdev, "read_xi2c_fifo(%d): mode set to 3, status updated to 0x%08x\n",chn, (int) status.d32);
}
}
/** I2C sequencer stop/run/reset (also programs status if run)*/
int i2c_stop_run_reset(int chn, ///< Sensor port
......@@ -190,7 +226,7 @@ int i2c_page_alloc(int chn)
#else
spin_unlock_irqrestore(sensori2c_locks[chn],flags);
#endif
dev_dbg(sdev, "Allocated page= %d for port %d, is RESET(group= 0x%08x bits = 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x )\n",
dev_dbg(sdev, "Allocated page= %d for port %d, (group= 0x%08x bits = 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x )\n",
(g << 5) + b, chn,free_i2c_groups[chn],
free_i2c_pages[chn][0],free_i2c_pages[chn][1],free_i2c_pages[chn][2],free_i2c_pages[chn][3],
free_i2c_pages[chn][4],free_i2c_pages[chn][5],free_i2c_pages[chn][6],free_i2c_pages[chn][7]);
......@@ -277,7 +313,9 @@ void i2c_page_free(int chn, int page)
#else
spin_unlock_irqrestore(sensori2c_locks[chn],flags);
#endif
dev_dbg(sdev, "Freed chn=%d, page=%d\n", chn, page);
}
EXPORT_SYMBOL_GPL(i2c_page_free);
/** Calculate value of SCLK 1/4 period delay from maximal SCL frequency
......@@ -288,7 +326,10 @@ int get_bit_delay(int khz)
int dly;
if (!khz)
return 0;
dly = (1000 * mclk_mhz / 4)/khz;
// Modified FPGA - added extra division
// dly = (1000 * mclk_mhz / 4)/khz;
// dly = (1000 * mclk_mhz / 8 )/khz; //
dly = (32000 * mclk_mhz / scale_i2c_speed )/khz; //
if (dly > 255)
dly = 255;
return dly;
......@@ -322,6 +363,8 @@ void set_xi2c_raw(int chn, ///< Sensor port number
#endif
// i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
i2c_pages_shadow[chn][page] =tb_data.d32;
dev_dbg(sdev, "Channel = %d, page = %d, raw data = 0x%08x\n", chn, page, tb_data.d32);
}
EXPORT_SYMBOL_GPL(set_xi2c_raw);
......@@ -446,6 +489,8 @@ void set_xi2c_wr(int chn, ///< sensor port
#endif
// i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
i2c_pages_shadow[chn][page] =tb_data.d32;
dev_dbg(sdev, "chn=%d, page = %d, tb_addr.d32=0x%08x, tb_data.d32 = 0x%08x\n",chn,page,tb_addr.d32,tb_data.d32);
}
EXPORT_SYMBOL_GPL(set_xi2c_wr);
......@@ -485,6 +530,7 @@ void set_xi2c_rd(int chn, ///< sensor port
#endif
// i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
i2c_pages_shadow[chn][page] =tb_data.d32;
dev_dbg(sdev, "chn=%d, page = %d, tb_addr.d32=0x%08x, tb_data.d32 = 0x%08x\n",chn,page,tb_addr.d32,tb_data.d32);
}
EXPORT_SYMBOL_GPL(set_xi2c_rd);
......@@ -540,6 +586,7 @@ int write_xi2c_rel (int chn, ///< sensor port
} else {
x393_sensi2c_rel (data[0], chn, offs);
}
dev_dbg(sdev, "chn=%d, offs = %d, data[0] = 0x%08x\n",chn,offs,data[0]);
return 0;
}
EXPORT_SYMBOL_GPL(write_xi2c_rel);
......@@ -582,18 +629,37 @@ int write_xi2c_abs (int chn, ///< sensor port
} else {
x393_sensi2c_abs (data[0], chn, offs);
}
dev_dbg(sdev, "chn=%d, offs = %d, data[0] = 0x%08x\n",chn,offs,data[0]);
return 0;
}
EXPORT_SYMBOL_GPL(write_xi2c_abs);
u32 i2c_combine_page_addr_data8_16( int chn, ///< sensor port
int page, ///< index in the table (8 bits)
int addr, ///< register address (single byte for 8-bit data, LSB for 16 bit data)
int data) ///< 8/16 bit data to write
///< @ return combined page/address/data
{
x393_i2c_ctltbl_t i2c_ctltbl = {.d32= i2c_pages_shadow[chn][page]};
// i2c_ctltbl.d32 = i2c_pages_shadow[chn][page];
// if ((((x393_i2c_ctltbl_t) i2c_pages_shadow[chn][page]).nbwr > 2))
if (i2c_ctltbl.nbwr > 2)
return ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
else
return ((page & 0xff) << 24) | ((addr & 0xff) << 8) | (data & 0xff);
}
/** Write sensor 16 bit (or 8 bit as programmed in the table) data in immediate mode */
void write_xi2c_reg16 (int chn, ///< sensor port
int page, ///< index in the table (8 bits)
int addr, ///< low byte of the register address (high is in the table), 8 bits
u32 data) ///< 16 or 8-bit data (LSB aligned)
u32 data) ///< 16 or 8-bit data (LSB aligned), 16 address only for 16 bit data
{
u32 dw = ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
// u32 dw = ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
u32 dw = i2c_combine_page_addr_data8_16(chn, page, addr, data);
x393_sensi2c_rel (dw, chn, 0);
dev_dbg(sdev, "i2c_pages_shadow[%d][0x%x]= 0x%08x addr=0x%x data=0x%x dw=0x%08x\n",
chn,page,i2c_pages_shadow[chn][page], addr,data, (int) dw);
}
EXPORT_SYMBOL_GPL(write_xi2c_reg16);
......@@ -602,9 +668,10 @@ void write_xi2c_reg16_rel (int chn, ///< sensor port
int page, ///< index in the table (8 bits)
int frame, ///< relative frame number modulo PARS_FRAMES
int addr, ///< low byte of the register address (high is in the table), 8 bits
u32 data) ///< 16 or 8-bit data (LSB aligned)
u32 data) ///< 16 or 8-bit data (LSB aligned), 16 address only for 16 bit data
{
u32 dw = ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
// u32 dw = ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
u32 dw = i2c_combine_page_addr_data8_16(chn, page, addr, data);
x393_sensi2c_rel (dw, chn, frame & PARS_FRAMES_MASK);
}
EXPORT_SYMBOL_GPL(write_xi2c_reg16_rel);
......@@ -614,9 +681,10 @@ void write_xi2c_reg16_abs (int chn, ///< sensor port
int page, ///< index in the table (8 bits)
int frame, ///< absolute frame number modulo PARS_FRAMES
int addr, ///< low byte of the register address (high is in the table), 8 bits
u32 data) ///< 16 or 8-bit data (LSB aligned)
u32 data) ///< 16 or 8-bit data (LSB aligned), 16 address only for 16 bit data
{
u32 dw = ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
// u32 dw = ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
u32 dw = i2c_combine_page_addr_data8_16(chn, page, addr, data);
x393_sensi2c_abs (dw, chn, frame & PARS_FRAMES_MASK);
}
EXPORT_SYMBOL_GPL(write_xi2c_reg16_abs);
......@@ -627,9 +695,10 @@ void write_xi2c_reg16_abs_asap (int chn, ///< sensor port
int page, ///< index in the table (8 bits)
int frame, ///< absolute frame number modulo PARS_FRAMES
int addr, ///< low byte of the register address (high is in the table), 8 bits
u32 data) ///< 16 or 8-bit data (LSB aligned)
u32 data) ///< 16 or 8-bit data (LSB aligned), 16 address only for 16 bit data
{
u32 dw = ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
// u32 dw = ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
u32 dw = i2c_combine_page_addr_data8_16(chn, page, addr, data);
if (frame<0) x393_sensi2c_rel (dw, chn, 0);
else x393_sensi2c_abs (dw, chn, frame & PARS_FRAMES_MASK);
}
......@@ -646,10 +715,13 @@ void read_xi2c (x393_i2c_device_t * dc, ///< device class
{
u32 dw = ((page & 0xff) << 24) | (dc -> slave7 << 17) | (addr & 0xffff);
x393_sensi2c_rel (dw, chn, 0);
dev_dbg(sdev, "chn=%d, page = %d, addr = %d\n",chn,page, addr);
}
EXPORT_SYMBOL_GPL(read_xi2c);
/** Initiate sensor i2c read in immediate mode, specify 7-bit slave address
* (data itself has to be read from FIFO with read_xi2c_fifo) */
void read_xi2c_sa7 (int chn, ///< sensor port
......@@ -667,33 +739,8 @@ EXPORT_SYMBOL_GPL(read_xi2c_sa7);
int read_xi2c_frame(int chn) ///< sensor port number
///< @return i2c sequencer frame number (4 bits)
{
#ifndef LOCK_BH_SENSORI2C
unsigned long flags;
#endif
int i;
x393_status_sens_i2c_t status;
x393_status_ctrl_t status_ctrl = get_x393_sensi2c_status_ctrl(chn); /* last written data to status_cntrl */
if (status_ctrl.mode != 3){
#ifdef LOCK_BH_SENSORI2C
spin_lock_bh(sensori2c_locks[chn]);
#else
spin_lock_irqsave(sensori2c_locks[chn],flags);
#endif
status = x393_sensi2c_status (chn);
status_ctrl.mode = 3;
status_ctrl.seq_num = status.seq_num ^ 0x20;
set_x393_sensi2c_status_ctrl(status_ctrl, chn);
for (i = 0; i < 10; i++) {
status = x393_sensi2c_status(chn);
if (likely(status.seq_num = status_ctrl.seq_num)) break;
}
#ifdef LOCK_BH_SENSORI2C
spin_unlock_bh(sensori2c_locks[chn]);
#else
spin_unlock_irqrestore(sensori2c_locks[chn],flags);
#endif
dev_dbg(sdev, "read_xi2c_frame(%d): mode set to 3, status updated to 0x%08x\n",chn, (int) status.d32);
}
i2c_autoupdate_status(chn);
status = x393_sensi2c_status (chn);
return (int) status.frame_num;
}
......@@ -704,34 +751,10 @@ EXPORT_SYMBOL_GPL(read_xi2c_frame);
int read_xi2c_fifo(int chn) ///< sensor port
///< @return byte or -1 if no data available, -EIO - error
{
#ifndef LOCK_BH_SENSORI2C
unsigned long flags;
#endif
int fifo_lsb, rslt,i;
x393_i2c_ctltbl_t i2c_cmd;
x393_status_sens_i2c_t status;
x393_status_ctrl_t status_ctrl = get_x393_sensi2c_status_ctrl(chn); /* last written data to status_cntrl */
if (status_ctrl.mode != 3){
#ifdef LOCK_BH_SENSORI2C
spin_lock_bh(sensori2c_locks[chn]);
#else
spin_lock_irqsave(sensori2c_locks[chn],flags);
#endif
status = x393_sensi2c_status (chn);
status_ctrl.mode = 3;
status_ctrl.seq_num = status.seq_num ^ 0x20;
set_x393_sensi2c_status_ctrl(status_ctrl, chn);
for (i = 0; i < 10; i++) {
status = x393_sensi2c_status(chn);
if (likely(status.seq_num = status_ctrl.seq_num)) break;
}
#ifdef LOCK_BH_SENSORI2C
spin_unlock_bh(sensori2c_locks[chn]);
#else
spin_unlock_irqrestore(sensori2c_locks[chn],flags);
#endif
dev_dbg(sdev, "read_xi2c_fifo(%d): mode set to 3, status updated to 0x%08x\n",chn, (int) status.d32);
}
i2c_autoupdate_status(chn);
status = x393_sensi2c_status (chn);
// dev_dbg(sdev, "read_xi2c_fifo(%d): status = 0x%08x\n",chn, (int) status.d32);
if (!status.i2c_fifo_nempty) return -1; // No data available
......@@ -831,7 +854,7 @@ int x393_xi2c_read_reg( const char * cname, ///< device class name
/* Flush channel i2c read FIFO to make sure it is empty, status mode will be set, if needed */
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, running read_xi2c_sa7(%d,0x%x,0x%x, 0x%x)\n",chn, page & 0xff, (dc->slave7 + sa7_offs) & 0x7f, reg_addr & 0xffff);
/* Initiate i2c read */
read_xi2c_sa7 (chn,
......@@ -859,12 +882,52 @@ int x393_xi2c_read_reg( const char * cname, ///< device class name
}
/* Free table page */
dev_dbg(sdev, "Freeing i2c page %d\n",page);
dev_dbg(sdev, "Freeing i2c page %d, got data 0x%x\n",page, datap[0]);
i2c_page_free(chn, page);
return 0;
}
EXPORT_SYMBOL_GPL(x393_xi2c_read_reg);
/** Test if i2c sequencer can accept more data (valid only for the same frame as last written
* In ASAP mode ready means that at least 64/4=16 locations is empty, this can be used when sequencer
* is stopped (no frame pulses) and data to be written is >64 items (i.e. programming 10359)
* in non-ASAP mode can be tested only after writing if needs to write more to the same page
* It will be ready again only if writing to a different page */
int x393_xi2c_ready_wr(int chn) ///< sensor port number
///< @return - 1 - ready, 0 - busy
{
x393_status_sens_i2c_t status;
i2c_autoupdate_status(chn);
status = x393_sensi2c_status (chn);
return status.wr_full? 0 : 1;
}
EXPORT_SYMBOL_GPL(x393_xi2c_ready_wr);
/** Wait for channel sequencer ready to accept more data
* It is valid for the same page as last written, most useful when writing ~>64 times in ASAP mode */
int x393_xi2c_wait_wr(int chn) ///< sensor port number
///< @return - OK, <0 -ETIMEDOUT
{
int rdy;
unsigned long timeout_end;
dev_dbg(sdev, "Waitoing i2c sequencer ready for channel %d\n",chn);
timeout_end = jiffies + tenth_sec;
while (jiffies < timeout_end){
if ((rdy=x393_xi2c_ready_wr( chn)))
break;
}
if (!rdy) {
dev_dbg(sdev, "Timeout waiting for i2c sequencer channel %d ready to accept more data\n",chn);
return -ETIMEDOUT;
}
return 0;
}
EXPORT_SYMBOL_GPL(x393_xi2c_wait_wr);
/** Single-command i2c read register compatible with legacy code. Device class(es) should already be registered, len parameter should
* match pre-programmed length */
int legacy_read_i2c_reg( int chn, ///< sensor port number
......@@ -906,6 +969,7 @@ int legacy_read_i2c_reg( int chn, ///< sensor port number
}
*datap = (*datap <<8) | (db & 0xff);
}
reset_unbalanced_writes(chn);
return 0;
}
EXPORT_SYMBOL_GPL(legacy_read_i2c_reg);
......@@ -1344,7 +1408,8 @@ static ssize_t set_i2c_tbl_rd_human(struct device *dev, ///< Linux
* - device register address,
*
* Additional parameter
* - data to write identifies write operation, if it is missing i2c read will be issued */
* - data to write identifies write operation, if it is missing i2c read will be issued
* This command wait for sequencer ready after writing */
static ssize_t i2c_store(struct device *dev, ///< Linux kernel basic device structure
struct device_attribute *attr, ///< Linux kernel interface for exporting device attributes
const char *buf, ///< 4K buffer with what was written
......@@ -1381,6 +1446,8 @@ static ssize_t i2c_store(struct device *dev, ///< Linux kernel basi
sa7_offset, // slave address (7-bit) offset from the class defined slave address
reg_addr, // register address (width is defined by class)
reg_data); // data to write (width is defined by class)
if (rslt < 0) return rslt;
if ((rslt = x393_xi2c_wait_wr(chn)) < 0) return rslt;
}
return count;
}
......@@ -1459,12 +1526,69 @@ static ssize_t i2c_frame_store(struct device *dev, ///< Linux kerne
default:
return - EINVAL;
}
}
return count;
}
//scale_i2c_speed
/** Show i2c speed scale (256 - normal speed, 128 - 1/2, 512 - 2x) */
static ssize_t i2c_speed_show(struct device *dev, ///< Linux kernel basic device structure
struct device_attribute *attr, ///< Linux kernel interface for exporting device attributes
char *buf) ///< 4K buffer to receive response
///< @return offset to the end of the output data in the *buf buffer
{
return sprintf(buf,"%d\n",scale_i2c_speed);
}
static ssize_t i2c_speed_store(struct device *dev, ///< Linux kernel basic device structure
struct device_attribute *attr, ///< Linux kernel interface for exporting device attributes
const char *buf, ///< 4K buffer with what was written
size_t count) ///< offset to the end of buffer data
///< @return new offset to the end of buffer data
{
if (sscanf(buf, "%i", &scale_i2c_speed)> 0) {
if (scale_i2c_speed<1) scale_i2c_speed = 1;
}
return count;
}
/** Show i2c speed scale (256 - normal speed, 128 - 1/2, 512 - 2x) */
static ssize_t i2c_max_unbalanced_writes_show(struct device *dev, ///< Linux kernel basic device structure
struct device_attribute *attr, ///< Linux kernel interface for exporting device attributes
char *buf) ///< 4K buffer to receive response
///< @return offset to the end of the output data in the *buf buffer
{
return sprintf(buf,"%d\n",max_unbalanced_writes);
}
static ssize_t i2c_max_unbalanced_writes_store(struct device *dev, ///< Linux kernel basic device structure
struct device_attribute *attr, ///< Linux kernel interface for exporting device attributes
const char *buf, ///< 4K buffer with what was written
size_t count) ///< offset to the end of buffer data
///< @return new offset to the end of buffer data
{
sscanf(buf, "%i", &max_unbalanced_writes);
return count;
}
int i2c_get_max_unbalanced_writes(void) // ///@return - maximal number of unbalanced writes (w/o reads) - debug feature
{
return max_unbalanced_writes;
}
void reset_unbalanced_writes(int chn)
{
unbalanced_writes[chn]=0;
}
void inc_unbalanced_writes(int chn)
{
unbalanced_writes[chn]++;
}
int check_unbalanced_writes(int chn)
{
return unbalanced_writes[chn] > max_unbalanced_writes;
}
int get_unbalanced_writes(int chn)
{
return unbalanced_writes[chn];
}
//max_unbalanced_writes
// Sysfs top
/* alloc*: read - allocate and return page, write (any data) - free page */
static DEVICE_ATTR(i2c_all , SYSFS_PERMISSIONS , i2c_class_show , i2c_class_store);
......@@ -1497,6 +1621,8 @@ static DEVICE_ATTR(i2c_frame0 , SYSFS_PERMISSIONS , i2c_fr
static DEVICE_ATTR(i2c_frame1 , SYSFS_PERMISSIONS , i2c_frame_show, i2c_frame_store);
static DEVICE_ATTR(i2c_frame2 , SYSFS_PERMISSIONS , i2c_frame_show, i2c_frame_store);
static DEVICE_ATTR(i2c_frame3 , SYSFS_PERMISSIONS , i2c_frame_show, i2c_frame_store);
static DEVICE_ATTR(i2c_speed, SYSFS_PERMISSIONS , i2c_speed_show, i2c_speed_store);
static DEVICE_ATTR(max_unbalanced_writes, SYSFS_PERMISSIONS , i2c_max_unbalanced_writes_show,i2c_max_unbalanced_writes_store);
static DEVICE_ATTR(help, SYSFS_PERMISSIONS & SYSFS_READONLY, get_i2c_help, NULL);
/** Contains entries for the root node (directory) of the sysfs representation for sensor-port i2c devices */
......@@ -1530,6 +1656,8 @@ static struct attribute *root_dev_attrs[] = {
&dev_attr_i2c_frame1.attr,
&dev_attr_i2c_frame2.attr,
&dev_attr_i2c_frame3.attr,
&dev_attr_i2c_speed.attr,
&dev_attr_max_unbalanced_writes.attr,
&dev_attr_help.attr,
NULL
};
......@@ -1665,7 +1793,7 @@ static int elphel393_sensor_i2c_remove(struct platform_device *pdev) ///< Platfo
dev_info(&pdev->dev,"Removing elphel393-sensor-i2c");
return 0;
}
/** Compatible records in Device Tree fro this driver */
/** Compatible records in Device Tree for this driver */
static struct of_device_id elphel393_sensor_i2c_of_match[] = {
{ .compatible = "elphel,elphel393-sensor-i2c-1.00", }, ///< Compatibility data
{ /* end of table */}
......
......@@ -42,7 +42,7 @@ int read_xi2c_frame (int chn);
int i2c_page_alloc (int chn);
int i2c_page_register(int chn, int page);
void i2c_page_free (int chn, int page);
x393_i2c_device_t * xi2c_dev_get(const char * name);
//x393_i2c_device_t * xi2c_dev_get(const char * name);
void set_xi2c_raw (int chn, int page, u32 data);
void set_xi2c_wr (int chn,int page, int sa7, int rah, int num_bytes, int bit_delay);
void set_xi2c_wrc (x393_i2c_device_t * dc, int chn, int page, int rah);
......@@ -60,5 +60,13 @@ int read_xi2c_fifo (int chn);
x393_i2c_device_t * xi2c_dev_get(const char * name);
int x393_xi2c_write_reg(const char * cname, int chn, int sa7_offs, int reg_addr, int data);
int x393_xi2c_read_reg (const char * cname, int chn, int sa7_offs, int reg_addr, int * datap);
int x393_xi2c_ready_wr(int chn);
int x393_xi2c_wait_wr(int chn);
int legacy_read_i2c_reg(int chn, int page, int sa7, int reg_addr, int len, int * datap);
int i2c_get_max_unbalanced_writes(void);
void reset_unbalanced_writes(int chn);
void inc_unbalanced_writes(int chn);
int check_unbalanced_writes(int chn);
int get_unbalanced_writes(int chn);
#endif
......@@ -213,7 +213,7 @@ int setup_compressor_memory (int num_sensor, ///< sensor port number (0..3
int frame_full_width = buffer_settings.frame_full_width[num_sensor] >> 4;
int frame_sa_inc = frame_full_width * (buffer_settings.frame_height[num_sensor] >>3);
int last_frame_num = buffer_settings.frames_in_buffer[num_sensor] - 1;
int byte32 = 1; ///< 1 - 32-byte columns (currently used), 0 - 16 byte columns
// int byte32 = 1; ///< 1 - 32-byte columns (currently used), 0 - 16 byte columns
x393_mcntrl_window_frame_sa_t window_frame_sa = {.d32=0};
x393_mcntrl_window_frame_sa_inc_t window_frame_sa_inc = {.d32=0};
......@@ -554,7 +554,7 @@ static int videomem_probe(struct platform_device *pdev)
int res;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
const __be32 *bufsize_be;
// const __be32 *bufsize_be;
struct device_node *node;
elphel393_videomem_sysfs_register(pdev);
......
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