Commit 81559b1f authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

changes for mux and mux broadcast address

parent e5bb1292
...@@ -45,10 +45,10 @@ struct sensor_port_config_t *pSensorPortConfig; ...@@ -45,10 +45,10 @@ struct sensor_port_config_t *pSensorPortConfig;
// removed static to export // removed static to export
static struct sensor_port_config_t sensorPortConfig[] = { static struct sensor_port_config_t sensorPortConfig[] = {
{.mux=SENSOR_NONE,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}}, {.mux=SENSOR_NONE,.broadcast_addr=0,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}},
{.mux=SENSOR_NONE,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}}, {.mux=SENSOR_NONE,.broadcast_addr=0,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}},
{.mux=SENSOR_NONE,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}}, {.mux=SENSOR_NONE,.broadcast_addr=0,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}},
{.mux=SENSOR_NONE,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}} {.mux=SENSOR_NONE,.broadcast_addr=0,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}}
}; };
static const struct of_device_id elphel393_detect_sensors_of_match[]; static const struct of_device_id elphel393_detect_sensors_of_match[];
...@@ -126,6 +126,11 @@ sens_iface_t get_iface_by_code(int code, ///< sensor code ...@@ -126,6 +126,11 @@ sens_iface_t get_iface_by_code(int code, ///< sensor code
return NONE; return NONE;
} }
/** Get sensor port multiplexer type */
int set_broadcast_address(int port,int value){
sensorPortConfig[port & 3].broadcast_addr = value;
return 0;
}
/** Get sensor port multiplexer type */ /** Get sensor port multiplexer type */
int get_detected_mux_code(int port) ///< Sensor port number (0..3) int get_detected_mux_code(int port) ///< Sensor port number (0..3)
...@@ -398,7 +403,7 @@ static int elphel393_detect_sensors_sysfs_register(struct platform_device *pdev) ...@@ -398,7 +403,7 @@ static int elphel393_detect_sensors_sysfs_register(struct platform_device *pdev)
* @param table - pointer to the global struct * @param table - pointer to the global struct
* @return 0 * @return 0
*/ */
static int par2addr_fill(const unsigned short *par2addr, u16 *table){ static int par2addr_fill(const unsigned short *par2addr, u32 *table){
int i=0; int i=0;
...@@ -407,7 +412,7 @@ static int par2addr_fill(const unsigned short *par2addr, u16 *table){ ...@@ -407,7 +412,7 @@ static int par2addr_fill(const unsigned short *par2addr, u16 *table){
// reset // reset
for(i=0;i<MAX_SENSOR_REGS;i++){ for(i=0;i<MAX_SENSOR_REGS;i++){
table[i] = 0; table[i] = 0xffffffff;
} }
i=0; i=0;
......
...@@ -25,11 +25,18 @@ ...@@ -25,11 +25,18 @@
#define MAX_SENSOR_REGS 256 #define MAX_SENSOR_REGS 256
#define MAX_FPGA_RECS 256 #define MAX_FPGA_RECS 256
#define MUX_BROADCAST_INDEX 3
struct sensor_port_config_t { struct sensor_port_config_t {
u32 mux; ///< Sensor multiplexer, currently 0 (SENSOR_DETECT, SENSOR_MUX_10359 or SENSOR_NONE) u32 mux; ///< Sensor multiplexer, currently 0 (SENSOR_DETECT, SENSOR_MUX_10359 or SENSOR_NONE)
u32 broadcast_addr; ///< For MUX: broadcast address for connected sensors, for single sensor it's 0, for mux: 3
u32 sensor[MAX_SENSORS]; ///< Without mux only [0] is used, with 10359 - 0..2 are used (i2c addressing is shifted so 0 is broadcast) u32 sensor[MAX_SENSORS]; ///< Without mux only [0] is used, with 10359 - 0..2 are used (i2c addressing is shifted so 0 is broadcast)
u16 par2addr[MAX_SENSORS][MAX_SENSOR_REGS]; ///< Big LUT. SENSOR_REGSxxx par to sensor reg 'yyy' internal address: haddr+laddr for 16 bit //u16 par2addr[MAX_SENSORS][MAX_SENSOR_REGS]; ///< Big LUT. SENSOR_REGSxxx par to sensor reg 'yyy' internal address: haddr+laddr for 16 bit
u8 haddr2rec[MAX_SENSORS][MAX_FPGA_RECS]; ///< Big LUT (but almost empty). Sensor's page address (haddr of reg addr) to fpga i2c record number (fpga line#) // u32 for error handling
u32 par2addr[MAX_SENSORS][MAX_SENSOR_REGS]; ///< Big LUT. SENSOR_REGSxxx par to sensor reg 'yyy' internal address: haddr+laddr for 16 bit
//u8 haddr2rec[MAX_SENSORS][MAX_FPGA_RECS]; ///< Big LUT (but almost empty). Sensor's page address (haddr of reg addr) to fpga i2c record number (fpga line#)
// u32 is for error handling
u32 haddr2rec[MAX_SENSORS][MAX_FPGA_RECS]; ///< Big LUT (but almost empty). Sensor's page address (haddr of reg addr) to fpga i2c record number (fpga line#)
unsigned short *pages_ptr[MAX_SENSORS]; unsigned short *pages_ptr[MAX_SENSORS];
}; };
...@@ -42,6 +49,7 @@ const char * get_name_by_code(int code, int type); ...@@ -42,6 +49,7 @@ const char * get_name_by_code(int code, int type);
sens_iface_t get_iface_by_code(int code, int type); sens_iface_t get_iface_by_code(int code, int type);
int get_detected_mux_code(int port); int get_detected_mux_code(int port);
int set_broadcast_address(int port,int value);
int get_detected_sensor_code(int port, int sub_chn); int get_detected_sensor_code(int port, int sub_chn);
int get_subchannels(int port); int get_subchannels(int port);
int set_detected_mux_code(int port, int mux_type); int set_detected_mux_code(int port, int mux_type);
......
...@@ -82,6 +82,11 @@ const unsigned short mt9f002_par2addr[] = { ...@@ -82,6 +82,11 @@ const unsigned short mt9f002_par2addr[] = {
P_MT9F002_ANALOG_GAIN_CODE_RED, P_REG_MT9F002_ANALOG_GAIN_CODE_RED, P_MT9F002_ANALOG_GAIN_CODE_RED, P_REG_MT9F002_ANALOG_GAIN_CODE_RED,
P_MT9F002_ANALOG_GAIN_CODE_BLUE, P_REG_MT9F002_ANALOG_GAIN_CODE_BLUE, P_MT9F002_ANALOG_GAIN_CODE_BLUE, P_REG_MT9F002_ANALOG_GAIN_CODE_BLUE,
P_MT9F002_COARSE_INTEGRATION_TIME, P_REG_MT9F002_COARSE_INTEGRATION_TIME, P_MT9F002_COARSE_INTEGRATION_TIME, P_REG_MT9F002_COARSE_INTEGRATION_TIME,
P_MT9F002_Y_ADDR_START, P_REG_MT9F002_Y_ADDR_START,
P_MT9F002_Y_ADDR_END, P_REG_MT9F002_Y_ADDR_END,
P_MT9F002_X_ADDR_START, P_REG_MT9F002_X_ADDR_START,
P_MT9F002_X_ADDR_END, P_REG_MT9F002_X_ADDR_END,
P_MT9F002_READ_MODE, P_REG_MT9F002_READ_MODE,
0xffff // END indicator 0xffff // END indicator
}; };
...@@ -123,10 +128,8 @@ struct sensor_t mt9f002 = { ...@@ -123,10 +128,8 @@ struct sensor_t mt9f002 = {
.imageHeight = 3288, ///< nominal image height for final images .imageHeight = 3288, ///< nominal image height for final images
.clearWidth = 4608, ///< maximal clear image width .clearWidth = 4608, ///< maximal clear image width
.clearHeight = 3288, ///< maximal clear image height; .clearHeight = 3288, ///< maximal clear image height;
.clearTop = 32, ///< top margin to the first clear pixel .clearTop = 32-MT9F002_VACT_DELAY, ///< top margin to the first clear pixel
.clearLeft = 144, ///< left margin to the first clear pixel .clearLeft = 144, ///< left margin to the first clear pixel
//.clearTop = 106, ///< top margin to the first clear pixel
//.clearLeft = 114, ///< left margin to the first clear pixel
.arrayWidth = 4640, ///< total image array width (including black and boundary) .arrayWidth = 4640, ///< total image array width (including black and boundary)
.arrayHeight = 3320, ///< total image array height (including black and boundary) .arrayHeight = 3320, ///< total image array height (including black and boundary)
.minWidth = 2, ///< minimal WOI width .minWidth = 2, ///< minimal WOI width
...@@ -176,16 +179,16 @@ static bool init_done[4] = {false,false,false,false}; ...@@ -176,16 +179,16 @@ static bool init_done[4] = {false,false,false,false};
/** Initial register writes for MT9F002 */ /** Initial register writes for MT9F002 */
static unsigned short mt9f002_inits[]= static unsigned short mt9f002_inits[]=
{ {
P_MT9F002_HISPI_TIMING, 0x8000, // P_REG_MT9F002_HISPI_TIMING, 0x8000, //
P_MT9F002_SMIA_PLL_MULTIPLIER, 0x00b4, // P_REG_MT9F002_SMIA_PLL_MULTIPLIER, 0x00b4, //
P_MT9F002_HISPI_CONTROL_STATUS, 0x8400, // P_REG_MT9F002_HISPI_CONTROL_STATUS, 0x8400, //
P_MT9F002_DATAPATH_SELECT, 0x9280, // P_REG_MT9F002_DATAPATH_SELECT, 0x9280, //
//P_MT9F002_RESET_REGISTER, 0x001c, //P_REG_MT9F002_RESET_REGISTER, 0x001c,
//P_MT9F002_TEST_PATTERN, 0x0002, // color bars //P_REG_MT9F002_TEST_PATTERN, 0x0002, // color bars
P_MT9F002_ANALOG_GAIN_CODE_GLOBAL, 0x000a, P_REG_MT9F002_ANALOG_GAIN_CODE_GLOBAL, 0x000a,
P_MT9F002_ANALOG_GAIN_CODE_RED, 0x000d, P_REG_MT9F002_ANALOG_GAIN_CODE_RED, 0x000d,
P_MT9F002_ANALOG_GAIN_CODE_BLUE, 0x0010, P_REG_MT9F002_ANALOG_GAIN_CODE_BLUE, 0x0010,
P_MT9F002_COARSE_INTEGRATION_TIME, 0x0100 P_REG_MT9F002_COARSE_INTEGRATION_TIME, 0x0100
}; };
/** Specifying sensor registers to be controlled individually in multi-sensor applications, MT9P006 */ /** Specifying sensor registers to be controlled individually in multi-sensor applications, MT9P006 */
...@@ -206,9 +209,10 @@ static unsigned short mt9f002_inits[]= ...@@ -206,9 +209,10 @@ static unsigned short mt9f002_inits[]=
int mt9f002_pgm_detectsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16); int mt9f002_pgm_detectsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9f002_pgm_initsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16); int mt9f002_pgm_initsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
//int mt9f002_pgm_window (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16); int mt9f002_pgm_sensorin (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
//int mt9f002_pgm_window_safe (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16); int mt9f002_pgm_window (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
//int mt9f002_pgm_window_common(int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16); int mt9f002_pgm_window_safe (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9f002_pgm_window_common(int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
//int mt9f002_pgm_limitfps (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16); //int mt9f002_pgm_limitfps (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
//int mt9f002_pgm_exposure (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16); //int mt9f002_pgm_exposure (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
//int mt9f002_pgm_gains (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16); //int mt9f002_pgm_gains (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
...@@ -318,9 +322,10 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -318,9 +322,10 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port
add_sensor_proc(sensor_port,onchange_detectsensor,&mt9f002_pgm_detectsensor); // detect sensor type, sets sensor structure (capabilities), function pointers NOTE: will be called directly, not through pointers add_sensor_proc(sensor_port,onchange_detectsensor,&mt9f002_pgm_detectsensor); // detect sensor type, sets sensor structure (capabilities), function pointers NOTE: will be called directly, not through pointers
add_sensor_proc(sensor_port,onchange_initsensor, &mt9f002_pgm_initsensor); // resets sensor, reads sensor registers, schedules "secret" manufacturer's corrections to the registers (stops/re-enables hardware i2c) add_sensor_proc(sensor_port,onchange_initsensor, &mt9f002_pgm_initsensor); // resets sensor, reads sensor registers, schedules "secret" manufacturer's corrections to the registers (stops/re-enables hardware i2c)
add_sensor_proc(sensor_port,onchange_sensorin, &mt9f002_pgm_sensorin); // currently: VACT delay hack
//add_sensor_proc(sensor_port,onchange_exposure, &mt9x001_pgm_exposure); // program exposure //add_sensor_proc(sensor_port,onchange_exposure, &mt9x001_pgm_exposure); // program exposure
//add_sensor_proc(sensor_port,onchange_window, &mt9x001_pgm_window); // program sensor WOI and mirroring (flipping) add_sensor_proc(sensor_port,onchange_window, &mt9f002_pgm_window); // program sensor WOI and mirroring (flipping)
//add_sensor_proc(sensor_port,onchange_window_safe, &mt9x001_pgm_window_safe); // program sensor WOI and mirroring (flipping) - now - only flipping? with lower latency add_sensor_proc(sensor_port,onchange_window_safe, &mt9f002_pgm_window_safe); // program sensor WOI and mirroring (flipping) - now - only flipping? with lower latency
//add_sensor_proc(sensor_port,onchange_limitfps, &mt9x001_pgm_limitfps); // check compressor will keep up, limit sensor FPS if needed //add_sensor_proc(sensor_port,onchange_limitfps, &mt9x001_pgm_limitfps); // check compressor will keep up, limit sensor FPS if needed
//add_sensor_proc(sensor_port,onchange_gains, &mt9x001_pgm_gains); // program analog gains //add_sensor_proc(sensor_port,onchange_gains, &mt9x001_pgm_gains); // program analog gains
//add_sensor_proc(sensor_port,onchange_triggermode, &mt9x001_pgm_triggermode); // program sensor trigger mode //add_sensor_proc(sensor_port,onchange_triggermode, &mt9x001_pgm_triggermode); // program sensor trigger mode
...@@ -345,18 +350,17 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -345,18 +350,17 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port
//NOTE 353: hardware i2c is turned off (not needed in 393) //NOTE 353: hardware i2c is turned off (not needed in 393)
} }
// write to sensor's i2c register, test read
int mt9f002_phases_program_phase(int sensor_port, int phase){ int mt9f002_phases_program_phase(int sensor_port, int phase){
int i;
int read_phase = 0; 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;
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);
X3X3_I2C_SEND2_ASAP(sensor_port,0x0,P_MT9F002_HISPI_TIMING,phase); X3X3_I2C_SEND2_LUT_ASAP(sensor_port,0x0,P_REG_MT9F002_HISPI_TIMING,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){
...@@ -366,6 +370,7 @@ int mt9f002_phases_program_phase(int sensor_port, int phase){ ...@@ -366,6 +370,7 @@ int mt9f002_phases_program_phase(int sensor_port, int phase){
return 0; return 0;
} }
// read hact_alive bit from x393_status_sens_io_t
int mt9f002_phases_read_flags(int sensor_port,int shift){ int mt9f002_phases_read_flags(int sensor_port,int shift){
int res = 0; int res = 0;
...@@ -380,7 +385,6 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){ ...@@ -380,7 +385,6 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){
for(i=0;i<HACT_TIMEOUT;i++){ for(i=0;i<HACT_TIMEOUT;i++){
status = x393_sensio_status(sensor_port); status = x393_sensio_status(sensor_port);
if (status.hact_alive){ if (status.hact_alive){
//if (i>1) dev_dbg(g_dev_ptr,"{%d} hact recovered after %d\n",sensor_port,i);
break; break;
} }
if (i==(HACT_TIMEOUT-1)){ if (i==(HACT_TIMEOUT-1)){
...@@ -403,7 +407,8 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){ ...@@ -403,7 +407,8 @@ int mt9f002_phases_read_flags(int sensor_port,int shift){
} }
int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){ // phase adjustment for a single lane
int mt9f002_phases_adjust_lane(int sensor_port, int phase, int shift){
int i; int i;
int status; int status;
...@@ -480,7 +485,8 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){ ...@@ -480,7 +485,8 @@ int mt9f002_phases_scan_lane(int sensor_port, int phase, int shift){
return target_phase; return target_phase;
} }
int mt9f002_phases_adjust(int sensor_port){ // phase adjustment for port (all 4 lanes)
int mt9f002_phases_adjust_port(int sensor_port){
// insert phase adjustment here - find middle // insert phase adjustment here - find middle
// status: x393_status_sens_io_t status = x393_sensio_status(port) - read barrel - bits[21:14] // status: x393_status_sens_io_t status = x393_sensio_status(port) - read barrel - bits[21:14]
...@@ -519,7 +525,7 @@ int mt9f002_phases_adjust(int sensor_port){ ...@@ -519,7 +525,7 @@ int mt9f002_phases_adjust(int sensor_port){
// 4 data lanes - prior knowledge // 4 data lanes - prior knowledge
for(i=0;i<4;i++){ for(i=0;i<4;i++){
phase = mt9f002_phases_scan_lane(sensor_port,phase,i); phase = mt9f002_phases_adjust_lane(sensor_port,phase,i);
} }
dev_dbg(g_dev_ptr,"{%d} Adjusted phase is 0x%04x\n",sensor_port,phase); dev_dbg(g_dev_ptr,"{%d} Adjusted phase is 0x%04x\n",sensor_port,phase);
...@@ -548,6 +554,7 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -548,6 +554,7 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port
int i; int i;
int n; int n;
x393_sens_sync_mult_t dis_sof = {.d32=0}; x393_sens_sync_mult_t dis_sof = {.d32=0};
//u32 i2c_read_data_dw[256];
//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
...@@ -564,19 +571,19 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -564,19 +571,19 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port
for(i=0;i<n;i++){ for(i=0;i<n;i++){
// sa7 is not used // sa7 is not used
X3X3_I2C_SEND2_ASAP(sensor_port,0x0,mt9f002_inits[2*i],mt9f002_inits[2*i+1]); X3X3_I2C_SEND2_LUT_ASAP(sensor_port,0x0,mt9f002_inits[2*i],mt9f002_inits[2*i+1]);
} }
// soft reset // soft reset
// sa7 is not used // sa7 is not used
X3X3_I2C_SEND2_ASAP(sensor_port,0x0,P_MT9F002_RESET_REGISTER,MT9F002_RESET_REGISTER_VALUE); X3X3_I2C_SEND2_LUT_ASAP(sensor_port,0x0,P_REG_MT9F002_RESET_REGISTER,MT9F002_RESET_REGISTER_VALUE);
// delay (needed?) // delay (needed?)
udelay(100); 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_port(sensor_port);
// restore SOF (disabled in pgm_detect) // restore SOF (disabled in mt9f002_pgm_detectsensor)
dis_sof.dis_sof = 0; dis_sof.dis_sof = 0;
x393_sens_sync_mult(dis_sof,sensor_port); x393_sens_sync_mult(dis_sof,sensor_port);
...@@ -585,6 +592,250 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -585,6 +592,250 @@ int mt9f002_pgm_initsensor (int sensor_port, ///< sensor port
return 0; return 0;
} }
/**
* Program sensor input in FPGA (Bayer, 8/16 bits, FPN, test mode, number of lines).
*/
int mt9f002_pgm_sensorin (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities)
struct framepars_t * thispars, ///< sensor current parameters
struct framepars_t * prevpars, ///< sensor previous parameters (not used here)
int frame16) ///< 4-bit (hardware) frame number parameters should
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
x393_sensio_width_t sensio_width = {.d32=0};
// this is a hack because there's no delay after SOF in HISPI proto
sensio_width.sensor_width = MT9F002_VACT_DELAY;
X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_width, sensio_width);
return 0;
}
/** Program sensor WOI and mirroring
* Validating, changing related parameters/scheduling actions, scheduling i2c commands
* As different sensors may produce "bad frames" for different WOI changes (i.e. MT9P001 seems to do fine with FLIP, but not WOI_WIDTH)
* pgm_window and pgm_window_safe will do the same - they will just be called with different latencies and with compressor stopped)*/
int mt9f002_pgm_window (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities)
struct framepars_t * thispars, ///< sensor current parameters
struct framepars_t * prevpars, ///< sensor previous parameters (not used here)
int frame16) ///< 4-bit (hardware) frame number parameters should
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
return mt9f002_pgm_window_common(sensor_port, sensor, thispars, prevpars, frame16);
}
/** Program sensor WOI and mirroring in safe mode (now does the same as mt9x001_pgm_window)
* Validating, changing related parameters/scheduling actions, scheduling i2c commands */
int mt9f002_pgm_window_safe (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities)
struct framepars_t * thispars, ///< sensor current parameters
struct framepars_t * prevpars, ///< sensor previous parameters (not used here)
int frame16) ///< 4-bit (hardware) frame number parameters should
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
return mt9f002_pgm_window_common(sensor_port, sensor, thispars, prevpars, frame16);
}
/** Common part of programming sensor WOI */
int mt9f002_pgm_window_common (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities)
struct framepars_t * thispars, ///< sensor current parameters
struct framepars_t * prevpars, ///< sensor previous parameters (not used here)
int frame16) ///< 4-bit (hardware) frame number parameters should
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
int i,dv,dh,bv,bh,ww,wh,wl,wt,flip,flipX,flipY,d, v;
int wws,wwe,whs,whe;
int compressor_margin; // 0 for JP4, 2 for JPEG
struct frameparspair_t pars_to_update[29];
int nupdate=0;
int styp = sensor->sensorType & 7;
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dh= thispars->pars[P_DCM_HOR];
dv= thispars->pars[P_DCM_VERT];
bh= thispars->pars[P_BIN_HOR];
bv= thispars->pars[P_BIN_VERT];
//wws = sensor->clearLeft;
ww = thispars->pars[P_SENSOR_PIXH] * dh;
//wwe = ww + wws - 1;
//whs = sensor->clearTop;
wh = thispars->pars[P_SENSOR_PIXV] * dv;
//whe = whs + wh + MT9F002_VACT_DELAY * dv - 1;
compressor_margin = (thispars->pars[P_SENSOR_PIXH] - thispars->pars[P_WOI_WIDTH]) >> 1; // assuming same for H and V
// 10338 is _not_ flipped (as the other boards, but for legacy compatibility....)
flip=((thispars->pars[P_FLIPH] & 1) | ((thispars->pars[P_FLIPV] & 1) << 1 )) ^ sensor->init_flips;
flipX = flip & 1;
flipY = (flip & 2)? 1:0;
d = 2 * bh * (ww / (2 * bh));
// correct window width if needed
// is this needed?
if (unlikely(d != ww)) {
SETFRAMEPARS_SET(P_SENSOR_PIXH, d / dh);
ww = d;
//wwe = ww + wws - 1;
}
// height
d = (wh+1) & 0xfffe; // round up to even
// correct window height if needed
// is this needed?
if (unlikely(d != wh)) {
SETFRAMEPARS_SET(P_SENSOR_PIXV, d / dv);
wh = d;
//whe = whs + wh + MT9F002_VACT_DELAY * dv - 1;
}
// Margins
wl = thispars->pars[P_WOI_LEFT] - compressor_margin;
wt = thispars->pars[P_WOI_TOP] - compressor_margin;
dev_dbg(g_dev_ptr,"{%d} wl =0x%x, wt=0x%x, ww=0x%x, wh=0x%x, compressor_margin=0x%x\n",sensor_port, wl, wt, ww, wh, compressor_margin);
// flip margins for mirrored images (except oversized, not to rely on sensor->clearWidth/sensor->clearHeight
// get back to this
if (!thispars->pars[P_OVERSIZE]) {
if(flipX) {
wl = sensor->clearWidth - ww - wl - (2 * COLOR_MARGINS) * dh;
if(wl < 0) wl = 0;
}
if(flipY) {
wt = sensor->clearHeight - wh - wt - (2 * COLOR_MARGINS) * dv;
if(wt < 0) wt = 0;
}
// apply clearTop/clearLeft
wt = (wt + sensor->clearTop) & 0xfffe;
wl = (wl + sensor->clearLeft) & 0xfffe;
dev_dbg(g_dev_ptr,"{%d} wl =0x%x, wt=0x%x\n",sensor_port, wl, wt);
// apply binning restrictions
d = (bh > 1) ? ((bh > 2) ? 16 : 8) : 4;
if(flipX)
i = d * ((wl - 2) / d) + 2;
else
i = d * (wl / d);
if(i < wl)
i += d;
wl = i;
}
wws = wl;
wwe = wws + ww - 1;
whs = wt; // wt already got sensor->clearTop-MT9F002_VACT_DELAY
whe = whs + wh + MT9F002_VACT_DELAY*(dv+1) - 1;
// program sensor width
if (wws != thispars->pars[P_SENSOR_REGS+P_MT9F002_X_ADDR_START]) {
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_X_ADDR_START, wws);
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9F002_X_ADDR_START, (int) wws);
}
if (wwe != thispars->pars[P_SENSOR_REGS+P_MT9F002_X_ADDR_END]) {
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_MT9F002_X_ADDR_END, wwe);
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9F002_X_ADDR_END, (int) wwe);
}
// program sensor height
if (whs!= thispars->pars[P_SENSOR_REGS+P_MT9F002_Y_ADDR_START]) {
SET_SENSOR_MBPAR_LUT(sensor_port, frame16 ,P_MT9F002_Y_ADDR_START, whs);
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_SENSOR_REGS+P_MT9F002_Y_ADDR_START, (int) whs);
}
if (whe!= thispars->pars[P_SENSOR_REGS+P_MT9F002_Y_ADDR_END]) {
SET_SENSOR_MBPAR_LUT(sensor_port, frame16 ,P_MT9F002_Y_ADDR_END, whe);
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_SENSOR_REGS+P_MT9F002_Y_ADDR_END, (int) whe);
}
// write flips and skips
// reg 0x3040 = P_REG_MT9F002_READ_MODE
//P_MT9F002_READ_MODE
// bits
// [15] - vertical flip, 0 - normal, 1 - vertical flip, starts from y_addr_end
// [14] - horizontal flip, 0 - normal, 1 - horizontal flip, start from x_addr_end
// [13:12] - reserved
// [11] - X dir analog binning enable - when set:
// y_odd_inc must be set to 1
// x_odd_inc must be set to 3 for col binning
// 7 for col skipping and binning, along with other register changes
// [10] - X and Y dir binning enable - when set:
// y_odd_inc & x_odd_inc must be set to 3 for binning
// 7 for binning and skipping
// [9] - reserved
// [8:6] - read_mode_x_odd_inc: 1 - normal,
// 3 - read out alternate px pairs to halve horizontal data in a frame
// 7 - read out 1 of 4 pixel pairs to reduce readout 1/4 the amout of pixels
//
// [5:0] - read_mode_y_odd_inc: 1 - normal,
// 3 - read out alternate px pairs to halve vertical amount of pixels in a frame
// 7 - 1/4
// 15 - 1/8
// 31 - 1/16
// 63 - 1/32
// the fields that should not change in non-stop will not change, so it is OK to write them always
/*
if((styp == MT9T_TYP) || (styp == MT9P_TYP)) { // 3MPix and 5MPix sensors
v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM] & 0xff88) | ((bv - 1) << 4) | (dv - 1) ;
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM]) {
SET_SENSOR_PAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RAM, v);
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_PAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RAM, (int) v);
}
v=(thispars->pars[P_SENSOR_REGS+P_MT9X001_CAM] & 0xff88) | ((bh - 1) << 4) | (dh - 1);
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_CAM]) {
SET_SENSOR_PAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_CAM, v);
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_PAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_CAM, (int) v);
}
v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2] & 0x3fff) | // preserve other bits from shadows
(flipX ? (1 << 14) : 0) | // FLIPH - will control just alternative rows
(flipY ? (1 << 15) : 0) ; // FLIPV
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RMODE2, v);
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE2, (int) v);
}
} else { // 1.3 and 2 MPix sensors
v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1] & 0xffc3) | // preserve other bits from shadows (trigger mode moved to other function)
((dh == 4) ? (1 << 2) : 0) | // Column skip 4
((dv == 4) ? (1 << 3) : 0) | // Row skip 4
((dh == 8) ? (1 << 4) : 0) | // Column skip 8
((dv == 8) ? (1 << 5) : 0) ; // Row skip 8
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RMODE1, v);
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE1, (int) v);
}
v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2] & 0x3fe7) | // preserve other bits from shadows
((dh == 2) ? (1 << 3) : 0) | // Column skip 2
((dv == 2) ? (1 << 4) : 0) | // Row skip 2
(flipX ? (1 << 14) : 0) | // FLIPH - will control just alternative rows
(flipY ? (1 << 15) : 0) ; // FLIPV
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RMODE2, v);
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE2, (int) v);
}
}
*/
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
return 0;
}
// SysFS interface to mt9f002 // SysFS interface to mt9f002
#define SYSFS_PERMISSIONS 0644 /* default permissions for sysfs files */ #define SYSFS_PERMISSIONS 0644 /* default permissions for sysfs files */
......
...@@ -14,10 +14,15 @@ ...@@ -14,10 +14,15 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/ *******************************************************************************/
#ifndef _MT9F002_H
#define _MT9F002_H
#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 #define MT9F002_RESET_REGISTER_VALUE 0x001c
// number of lines to sacrifice before generating Frame Valid
#define MT9F002_VACT_DELAY 2
/* ON Semi MT9F002 i2c register addresses */ /* ON Semi MT9F002 i2c register addresses */
...@@ -556,6 +561,13 @@ ...@@ -556,6 +561,13 @@
#define P_MT9F002_ANALOG_GAIN_CODE_BLUE 18 #define P_MT9F002_ANALOG_GAIN_CODE_BLUE 18
#define P_MT9F002_COARSE_INTEGRATION_TIME 19 #define P_MT9F002_COARSE_INTEGRATION_TIME 19
#define P_MT9F002_Y_ADDR_START 20
#define P_MT9F002_Y_ADDR_END 21
#define P_MT9F002_X_ADDR_START 22
#define P_MT9F002_X_ADDR_END 23
#define P_MT9F002_READ_MODE 24
//#define P_REG(x) x //#define P_REG(x) x
//#define P_MT9F002_MODEL_ID 4 //#define P_MT9F002_MODEL_ID 4
...@@ -586,3 +598,5 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -586,3 +598,5 @@ int mt9f002_pgm_detectsensor (int sensor_port, ///< sensor port
///< @return 0 - OK, negative - error ///< @return 0 - OK, negative - error
; ;
void mt9f002_set_device(struct device *dev); void mt9f002_set_device(struct device *dev);
#endif
...@@ -1044,7 +1044,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -1044,7 +1044,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
/** Program sensor WOI and mirroring /** Program sensor WOI and mirroring
* Validating, changing related parameters/scheduling actions, scheduling i2c commands * Validating, changing related parameters/scheduling actions, scheduling i2c commands
* As different sensors may produce "bad frames" for differnt WOI changes (i.e. MT9P001 seems to do fine with FLIP, but not WOI_WIDTH) * As different sensors may produce "bad frames" for different WOI changes (i.e. MT9P001 seems to do fine with FLIP, but not WOI_WIDTH)
* pgm_window and pgm_window_safe will do the same - they will just be called with different latencies and with compressor stopped)*/ * pgm_window and pgm_window_safe will do the same - they will just be called with different latencies and with compressor stopped)*/
int mt9x001_pgm_window (int sensor_port, ///< sensor port number (0..3) int mt9x001_pgm_window (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities) struct sensor_t * sensor, ///< sensor static parameters (capabilities)
......
...@@ -404,6 +404,9 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number ( ...@@ -404,6 +404,9 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
GLOBALPARS(sensor_port, G_SUBCHANNELS) = get_subchannels(sensor_port); GLOBALPARS(sensor_port, G_SUBCHANNELS) = get_subchannels(sensor_port);
mux = get_detected_mux_code(sensor_port); // none/detect/10359 mux = get_detected_mux_code(sensor_port); // none/detect/10359
// set broadcast address here, default is 0 for no-mux, MUX_BROADCAST_INDEX is for mux
if (mux != SENSOR_NONE) set_broadcast_address(sensor_port,MUX_BROADCAST_INDEX);
dev_dbg(g_dev_ptr,"port = %d, mux = %d, sens= %d\n",sensor_port, mux, sens); dev_dbg(g_dev_ptr,"port = %d, mux = %d, sens= %d\n",sensor_port, mux, sens);
//if ((mux == SENSOR_NONE) && (thispars->pars[P_SENSOR] == SENSOR_NONE)) //if ((mux == SENSOR_NONE) && (thispars->pars[P_SENSOR] == SENSOR_NONE))
...@@ -744,7 +747,7 @@ int pgm_afterinit (int sensor_port, ///< sensor port number ( ...@@ -744,7 +747,7 @@ int pgm_afterinit (int sensor_port, ///< sensor port number (
SETFRAMEPARS_UPDATE_SET(P_BIN_HOR | FRAMEPAIR_FORCE_NEW, 1); SETFRAMEPARS_UPDATE_SET(P_BIN_HOR | FRAMEPAIR_FORCE_NEW, 1);
SETFRAMEPARS_UPDATE_SET(P_BIN_VERT | FRAMEPAIR_FORCE_NEW, 1); SETFRAMEPARS_UPDATE_SET(P_BIN_VERT | FRAMEPAIR_FORCE_NEW, 1);
// Set analog gains to 1.0 if not set otherwise // Set analog gains to 1.0 if not set otherwise
// FIXME: Without those 3 lines it is not initialaized (or immediately reset) from the parameters in autocampars.xml. GAING=0x10000, all the rest - 0 // FIXME: Without those 3 lines it is not initialized (or immediately reset) from the parameters in autocampars.xml. GAING=0x10000, all the rest - 0
/* /*
if (!(GLOBALPARS(G_DEBUG) & (1 <<28))) { // debugging here ! *********************************** if (!(GLOBALPARS(G_DEBUG) & (1 <<28))) { // debugging here ! ***********************************
SETFRAMEPARS_UPDATE_SET(P_GAINR | FRAMEPAIR_FORCE_NEW, 0x20000); ///gain ==1.0 SETFRAMEPARS_UPDATE_SET(P_GAINR | FRAMEPAIR_FORCE_NEW, 0x20000); ///gain ==1.0
...@@ -1043,12 +1046,12 @@ int pgm_window_common (int sensor_port, ///< sensor port number ( ...@@ -1043,12 +1046,12 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
} }
// flips changed? // flips changed?
if (FRAMEPAR_MODIFIED(P_FLIPH)) { if (FRAMEPAR_MODIFIED(P_FLIPH)) {
if (unlikely((thispars->pars[P_FLIPH] & sensor->flips & 1)!=thispars->pars[P_FLIPH])) { // remove unsupoported flips if (unlikely((thispars->pars[P_FLIPH] & sensor->flips & 1)!=thispars->pars[P_FLIPH])) { // remove unsupported flips
SETFRAMEPARS_SET(P_FLIPH, (thispars->pars[P_FLIPH] & sensor->flips & 1)); SETFRAMEPARS_SET(P_FLIPH, (thispars->pars[P_FLIPH] & sensor->flips & 1));
} }
} }
if (FRAMEPAR_MODIFIED(P_FLIPV)) { if (FRAMEPAR_MODIFIED(P_FLIPV)) {
if (unlikely((thispars->pars[P_FLIPV] & (sensor->flips>>1) & 1)!=thispars->pars[P_FLIPV])) { // remove unsupoported flips if (unlikely((thispars->pars[P_FLIPV] & (sensor->flips>>1) & 1)!=thispars->pars[P_FLIPV])) { // remove unsupported flips
SETFRAMEPARS_SET(P_FLIPV, (thispars->pars[P_FLIPV] & (sensor->flips >> 1 ) & 1)); SETFRAMEPARS_SET(P_FLIPV, (thispars->pars[P_FLIPV] & (sensor->flips >> 1 ) & 1));
} }
} }
...@@ -1432,7 +1435,6 @@ int pgm_triggermode(int sensor_port, ///< sensor port number (0..3 ...@@ -1432,7 +1435,6 @@ int pgm_triggermode(int sensor_port, ///< sensor port number (0..3
/** Program sensor input in FPGA (Bayer, 8/16 bits, FPN, test mode, number of lines). /** Program sensor input in FPGA (Bayer, 8/16 bits, FPN, test mode, number of lines).
* TODO: implement for 393 (program_sensor()) * TODO: implement for 393 (program_sensor())
*/ */
int pgm_sensorin (int sensor_port, ///< sensor port number (0..3) int pgm_sensorin (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities) struct sensor_t * sensor, ///< sensor static parameters (capabilities)
struct framepars_t * thispars, ///< sensor current parameters struct framepars_t * thispars, ///< sensor current parameters
...@@ -1490,10 +1492,12 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3 ...@@ -1490,10 +1492,12 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
sensio_width.sensor_width = thispars->pars[P_ACTUAL_WIDTH]+(2 * margins); sensio_width.sensor_width = thispars->pars[P_ACTUAL_WIDTH]+(2 * margins);
} }
// fix for MT9F002 /*
// fix for MT9F002 (moved to the sensor driver)
if ((sens & SENSOR_MASK) == SENSOR_MT9F002){ if ((sens & SENSOR_MASK) == SENSOR_MT9F002){
sensio_width.sensor_width = 2; sensio_width.sensor_width = MT9F002_VACT_DELAY;
} }
*/
X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_width, sensio_width); X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_width, sensio_width);
......
...@@ -90,6 +90,26 @@ extern struct sensor_port_config_t *pSensorPortConfig; ...@@ -90,6 +90,26 @@ extern struct sensor_port_config_t *pSensorPortConfig;
pars_to_update[nupdate++].val=(data);\ pars_to_update[nupdate++].val=(data);\
X3X3_I2C_SEND2((port),(frame), (sa7), (reg), (data));\ X3X3_I2C_SEND2((port),(frame), (sa7), (reg), (data));\
} }
/**
* Set parameter for the sensor register and send to hardware i2c sequencer
* @param port sensor port number
* @param frame frame number to apply, <0 - ASAP
* @param reg sensor register address (8-bit)
* @param data value to set (16 bits)
*/
#define SET_SENSOR_PAR_LUT(port,frame,reg,data) {\
pars_to_update[nupdate ].num= P_SENSOR_REGS+(reg);\
pars_to_update[nupdate++].val=(data);\
int _I = 0;\
int _ADDR = pSensorPortConfig[(port)].par2addr[_I][(reg)];\
if (!(_ADDR&0xffff0000)) {\
X3X3_I2C_SEND2_LUT((port),(frame), _I, _ADDR, (data));\
}\
}
/**Set parameter for the same register in multiple multiplexed sensors and send to hardware i2c sequencer /**Set parameter for the same register in multiple multiplexed sensors and send to hardware i2c sequencer
* Similar to SET_SENSOR_PAR, but broadcast set for parameters with individual values. * Similar to SET_SENSOR_PAR, but broadcast set for parameters with individual values.
* Updates both "parent" parameter (used without multiplexer) and the individual ones * Updates both "parent" parameter (used without multiplexer) and the individual ones
...@@ -127,6 +147,53 @@ extern struct sensor_port_config_t *pSensorPortConfig; ...@@ -127,6 +147,53 @@ extern struct sensor_port_config_t *pSensorPortConfig;
} \ } \
} \ } \
} }
/**Set parameter for the same register in multiple multiplexed sensors and send to hardware i2c sequencer
* Similar to SET_SENSOR_PAR_LUT, but broadcast set for parameters with individual values.
* Updates both "parent" parameter (used without multiplexer) and the individual ones
* (can use 4 elements in pars_to_update array, increase size where needed!).
* Relies on the fact that individual parameters are processed later, so it verifies that broadcast
* does not modify individual if they are also modified and scheduled to be applied.
* @param p - sensor port number
* @param f - frame number to apply, <0 - ASAP
* @param r - sensor register address (8-bit)
* @param v - value to set (16 bits)
* @see SET_SENSOR_PAR_LUT */
#define SET_SENSOR_MBPAR_LUT(p,f,r,v) {\
int _I = pSensorPortConfig[(p)].broadcast_addr;\
int _ADDR = pSensorPortConfig[(p)].par2addr[_I][(r)];\
if (!(_ADDR&0xffff0000)) {\
X3X3_I2C_SEND2_LUT((p), (f), _I, _ADDR, (v));\
}\
pars_to_update[nupdate ].num= P_SENSOR_REGS+(r) ;\
pars_to_update[nupdate++].val=(v);\
{\
int _MINDEX= MULTIREG(p,P_SENSOR_REGS+(r),0); \
if (_MINDEX) { \
EDBG(if (GLOBALPARS(G_DEBUG) & (1 <<4)) printk("%s:%d:%s _MINDEX=0x%x, v=0x%x, FRAMEPAR_MODIFIED(_MINDEX)=0x%x\n",\
__FILE__,__LINE__,__FUNCTION__, _MINDEX, (int) (v), (int) FRAMEPAR_MODIFIED(_MINDEX) ));\
if (!FRAMEPAR_MODIFIED(_MINDEX)) { \
pars_to_update[nupdate ].num= _MINDEX;\
pars_to_update[nupdate++].val=(v);\
}\
_MINDEX++;\
EDBG(if (GLOBALPARS(G_DEBUG) & (1 <<4)) printk("%s:%d:%s _MINDEX=0x%x, v=0x%x, FRAMEPAR_MODIFIED(_MINDEX)=0x%x\n",\
__FILE__,__LINE__,__FUNCTION__, _MINDEX, (int) (v), (int) FRAMEPAR_MODIFIED(_MINDEX) ));\
if (!FRAMEPAR_MODIFIED(_MINDEX)) {\
pars_to_update[nupdate ].num= _MINDEX;\
pars_to_update[nupdate++].val=(v);\
}\
_MINDEX++;\
EDBG(if (GLOBALPARS(G_DEBUG) & (1 <<4)) printk("%s:%d:%s _MINDEX=0x%x, v=0x%x, FRAMEPAR_MODIFIED(_MINDEX)=0x%x\n",\
__FILE__,__LINE__,__FUNCTION__, _MINDEX, (int) (v), (int) FRAMEPAR_MODIFIED(_MINDEX) ));\
if (!FRAMEPAR_MODIFIED(_MINDEX)) {\
pars_to_update[nupdate ].num= _MINDEX;\
pars_to_update[nupdate++].val=(v);\
}\
}\
}\
}
/**Set parameter for the same register in multiple multiplexed sensors and send to hardware i2c sequencer /**Set parameter for the same register in multiple multiplexed sensors and send to hardware i2c sequencer
* Similar to SET_SENSOR_MBPAR, but it does not update "parent" parameter, only individual ones. * Similar to SET_SENSOR_MBPAR, but it does not update "parent" parameter, only individual ones.
* (can use 4 elements in pars_to_update array, increase size where needed!). * (can use 4 elements in pars_to_update array, increase size where needed!).
...@@ -163,6 +230,48 @@ extern struct sensor_port_config_t *pSensorPortConfig; ...@@ -163,6 +230,48 @@ extern struct sensor_port_config_t *pSensorPortConfig;
} \ } \
} }
/**Set parameter for the same register in multiple multiplexed sensors and send to hardware i2c sequencer
* Similar to SET_SENSOR_MBPAR, but it does not update "parent" parameter, only individual ones.
* (can use 4 elements in pars_to_update array, increase size where needed!).
* Relies on the fact that individual parameters are processed later, so it verifies that broadcast
* does not modify individual if they are also modified and scheduled to be applied.
* @param p sensor port number
* @param f frame number to apply, <0 - ASAP
* @param r sensor register address (8-bit)
* @param v value to set (16 bits)
* @see SET_SENSOR_MBPAR */
#define SET_SENSOR_MBOPAR_LUT(p,f,r,v) {\
int _I = pSensorPortConfig[(p)].broadcast_addr;\
int _ADDR = pSensorPortConfig[(p)].par2addr[_I][(r)];\
if (!(_ADDR&0xffff0000)) {\
X3X3_I2C_SEND2_LUT((p), (f), _I, _ADDR, (v));\
}\
{\
int _MINDEX= MULTIREG(p,P_SENSOR_REGS+(r),0); \
EDBG(if (GLOBALPARS(G_DEBUG) & (1 <<4)) printk("%s:%d:%s _MINDEX=0x%x, v=0x%x, FRAMEPAR_MODIFIED(_MINDEX)=0x%x\n",\
__FILE__,__LINE__,__FUNCTION__, _MINDEX, (int) (v), (int) FRAMEPAR_MODIFIED(_MINDEX) ));\
if (_MINDEX) { \
if (!FRAMEPAR_MODIFIED(_MINDEX)) { \
pars_to_update[nupdate ].num= _MINDEX ;\
pars_to_update[nupdate++].val=(v);\
} \
_MINDEX++ ;\
EDBG(if (GLOBALPARS(G_DEBUG) & (1 <<4)) printk("%s:%d:%s _MINDEX=0x%x, v=0x%x, FRAMEPAR_MODIFIED(_MINDEX)=0x%x\n",\
__FILE__,__LINE__,__FUNCTION__, _MINDEX, (int) (v), (int) FRAMEPAR_MODIFIED(_MINDEX) ));\
if (!FRAMEPAR_MODIFIED(_MINDEX)) { \
pars_to_update[nupdate ].num= _MINDEX ;\
pars_to_update[nupdate++].val=(v);\
}\
_MINDEX++ ;\
EDBG(if (GLOBALPARS(G_DEBUG) & (1 <<4)) printk("%s:%d:%s _MINDEX=0x%x, v=0x%x, FRAMEPAR_MODIFIED(_MINDEX)=0x%x\n",\
__FILE__,__LINE__,__FUNCTION__, _MINDEX, (int) (v), (int) FRAMEPAR_MODIFIED(_MINDEX) ));\
if (!FRAMEPAR_MODIFIED(_MINDEX)) { \
pars_to_update[nupdate ].num= _MINDEX ;\
pars_to_update[nupdate++].val=(v);\
} \
} \
} \
}
/**Set individual (multiplexed) sensor parameter (and send to hardware i2c sequencer) /**Set individual (multiplexed) sensor parameter (and send to hardware i2c sequencer)
* Do nothing if there is no individual parameter reserved * Do nothing if there is no individual parameter reserved
...@@ -180,6 +289,27 @@ extern struct sensor_port_config_t *pSensorPortConfig; ...@@ -180,6 +289,27 @@ extern struct sensor_port_config_t *pSensorPortConfig;
X3X3_I2C_SEND2((p), (f), ( s )+( I2C359_INC * ( i )), ( r ), ( v )); \ X3X3_I2C_SEND2((p), (f), ( s )+( I2C359_INC * ( i )), ( r ), ( v )); \
} \ } \
} }
/**Set individual (multiplexed) sensor parameter (and send to hardware i2c sequencer)
* Do nothing if there is no individual parameter reserved
* @param p Sensor port number
* @param f Frame number to apply, <0 - ASAP
* @param i mux sensor index: 0..2 - individual, 3 - broadcast
* @param r sensor register address (8-bit)
* @param v value to set (16 bits)
*/
#define SET_SENSOR_MIPAR_LUT(p,f,i,r,v) {\
int _MINDEX= MULTIREG(p,P_SENSOR_REGS+(r),(i)); \
if (_MINDEX) { \
pars_to_update[nupdate ].num= _MINDEX ;\
pars_to_update[nupdate++].val=(v);\
int _ADDR = pSensorPortConfig[(p)].par2addr[(i)][(r)];\
if (!(_ADDR&0xffff0000)) {\
X3X3_I2C_SEND2_LUT((p), (f), (i), _ADDR, (v));\
}\
} \
}
/**Set individual (multiplexed) sensor parameter if the new value is different from the shadow /**Set individual (multiplexed) sensor parameter if the new value is different from the shadow
* (and send to hardware i2c sequencer). * (and send to hardware i2c sequencer).
* Do nothing if there is no individual parameter reserved * Do nothing if there is no individual parameter reserved
...@@ -201,6 +331,29 @@ extern struct sensor_port_config_t *pSensorPortConfig; ...@@ -201,6 +331,29 @@ extern struct sensor_port_config_t *pSensorPortConfig;
} \ } \
} }
/**
* Set individual (multiplexed) sensor parameter if the new value is different from the shadow
* (and send to hardware i2c sequencer).
* Do nothing if there is no individual parameter reserved
* @param p Sensor port number
* @param f Frame number to apply, <0 - ASAP
* @param i mux sensor index: 0..2 - individual, 3 - broadcast
* @param r sensor register address (8-bit)
* @param v value to set (16 bits)
*/
#define SET_SENSOR_MIPAR_COND_LUT (p,f,i,r,v) {\
int _MINDEX= MULTIREG(p,P_SENSOR_REGS+(r),(i)); \
if ((_MINDEX) && ((v) != thispars->pars[_MINDEX])) { \
pars_to_update[nupdate ].num= _MINDEX ;\
pars_to_update[nupdate++].val=(v);\
int _ADDR = pSensorPortConfig[(p)].par2addr[(i)][(r)];\
if (!(_ADDR&0xffff0000)) {\
X3X3_I2C_SEND2_LUT((p), (f), (i), _ADDR, (v));\
}\
EDBG(if (GLOBALPARS(G_DEBUG) & (1 <<4)) printk("%s:%d:%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n"\
,__FILE__,__LINE__,__FUNCTION__,(int)(f),(int)(i),(int)_ADDR,(int)(v) )); \
} \
}
/**Set individual (multiplexed) sensor parameter (and send to hardware i2c sequencer) /**Set individual (multiplexed) sensor parameter (and send to hardware i2c sequencer)
* Fall back to common parameter if no individual exists * Fall back to common parameter if no individual exists
...@@ -222,6 +375,33 @@ extern struct sensor_port_config_t *pSensorPortConfig; ...@@ -222,6 +375,33 @@ extern struct sensor_port_config_t *pSensorPortConfig;
} \ } \
} }
/**Set individual (multiplexed) sensor parameter (and send to hardware i2c sequencer)
* Fall back to common parameter if no individual exists
* @param p Sensor port number
* @param f Frame number to apply, <0 - ASAP
* @param i mux sensor index: 0..2 - individual, 3 - broadcast
* @param r sensor register address (8-bit) - looked up to 16 bit
* @param v value to set (16 bits)
* */
#define SET_SENSOR_MIBPAR_LUT(p,f,i,r,v) {\
int _MINDEX= MULTIREG(p,P_SENSOR_REGS+(r),(i)); \
int _I = (i);\
if (_MINDEX) { \
pars_to_update[nupdate ].num= _MINDEX ;\
pars_to_update[nupdate++].val=(v);\
}else{ \
pars_to_update[nupdate ].num= P_SENSOR_REGS+(r) ;\
pars_to_update[nupdate++].val=(v);\
_I = MUX_BROADCAST_INDEX;\
} \
int _ADDR = pSensorPortConfig[(p)].par2addr[_I][(r)];\
if (!(_ADDR&0xffff0000)) {\
X3X3_I2C_SEND2_LUT((p), (f), _I, _ADDR, (v));\
}\
}
/// same, but only if different from the shadow /// same, but only if different from the shadow
/**Set individual (multiplexed) sensor parameter (and send to hardware i2c sequencer) /**Set individual (multiplexed) sensor parameter (and send to hardware i2c sequencer)
* only if the new value is different from the current one. * only if the new value is different from the current one.
...@@ -229,7 +409,7 @@ extern struct sensor_port_config_t *pSensorPortConfig; ...@@ -229,7 +409,7 @@ extern struct sensor_port_config_t *pSensorPortConfig;
* @param p Sensor port number * @param p Sensor port number
* @param f Frame number to apply, <0 - ASAP * @param f Frame number to apply, <0 - ASAP
* @param s I2C slave address, 7 bit * @param s I2C slave address, 7 bit
* @param i sensor index (1..3) * @param i sensor index (1..3) - actually 0..2, then slave address = (s) + I2C359_INC*(i+1), normal (s) is broadcast
* @param r sensor register address (8-bit) * @param r sensor register address (8-bit)
* @param v value to set (16 bits) * @param v value to set (16 bits)
* @see SET_SENSOR_MIBPAR */ * @see SET_SENSOR_MIBPAR */
...@@ -254,4 +434,40 @@ extern struct sensor_port_config_t *pSensorPortConfig; ...@@ -254,4 +434,40 @@ extern struct sensor_port_config_t *pSensorPortConfig;
} \ } \
} }
/// same, but only if different from the shadow
/**
* - Set individual (muxed) sensor parameter (and send to hardware i2c sequencer)
* only if the new value is different from the current one.
* - Fall back to common parameter if no individual exists
* @param p sensor port number
* @param f frame number to apply, <0 - ASAP
* @param i mux sensor index: 0..2 - individual, 3 - broadcast
* @param r sensor register address, 8 bits are looked up to 16 bits
* @param v value to set - 16 bits
* @see SET_SENSOR_MIBPAR_LUT
* */
#define SET_SENSOR_MIBPAR_COND_LUT(p,f,i,r,v) {\
int _MINDEX= MULTIREG(p,P_SENSOR_REGS+(r),(i));\
int _I = (i);\
if (_MINDEX) { \
if ((v) != thispars->pars[_MINDEX]) { \
pars_to_update[nupdate ].num= _MINDEX ;\
pars_to_update[nupdate++].val=(v);\
}\
}else{\
if ((v) != thispars->pars[P_SENSOR_REGS+(r)]) { \
pars_to_update[nupdate ].num= P_SENSOR_REGS+(r) ;\
pars_to_update[nupdate++].val=(v);\
_I = pSensorPortConfig[(p)].broadcast_addr;\
} \
} \
int _ADDR = pSensorPortConfig[(p)].par2addr[_I][(r)];\
if (!(_ADDR&0xffff0000)) {\
X3X3_I2C_SEND2_LUT((p), (f), _I, _ADDR, (v));\
}\
EDBG(if (GLOBALPARS(G_DEBUG) & (1 <<4)) printk("%s:%d:%s X3X3_I2C_SEND2_LUT(0x%x, 0x%x, 0x%x, 0x%x)\n",\
__FILE__,__LINE__,__FUNCTION__,(int)(f),(int)_I,(int)_ADDR,(int)(v) )); \
}
#endif #endif
...@@ -1147,7 +1147,7 @@ int image_acq_stop(struct platform_device *pdev) ...@@ -1147,7 +1147,7 @@ int image_acq_stop(struct platform_device *pdev)
} }
/** /**
* Register i2c pages equal to slave address * Register i2c pages
* @param port * @param port
* @param sub_chn * @param sub_chn
* @param i2c_dev * @param i2c_dev
...@@ -1161,13 +1161,14 @@ int fpga_register_i2c_pages(int port, int sub_chn, x393_i2c_device_t i2c_dev){ ...@@ -1161,13 +1161,14 @@ int fpga_register_i2c_pages(int port, int sub_chn, x393_i2c_device_t i2c_dev){
int haddr; int haddr;
u16 *table = pSensorPortConfig[port].pages_ptr[sub_chn]; u16 *table = pSensorPortConfig[port].pages_ptr[sub_chn];
u8 *h2r = pSensorPortConfig[port].haddr2rec[sub_chn]; u32 *h2r = pSensorPortConfig[port].haddr2rec[sub_chn];
bool used_page[256]; bool used_haddr[256];
// init // init
for(i=0;i<256;i++){ for(i=0;i<256;i++){
used_page[i] = false; used_haddr[i] = false;
h2r[i] = 0xffffffff;
} }
// loop through pages table // loop through pages table
...@@ -1183,8 +1184,8 @@ int fpga_register_i2c_pages(int port, int sub_chn, x393_i2c_device_t i2c_dev){ ...@@ -1183,8 +1184,8 @@ int fpga_register_i2c_pages(int port, int sub_chn, x393_i2c_device_t i2c_dev){
break; break;
} }
if(!used_page[haddr]){ if(!used_haddr[haddr]){
used_page[haddr] = true; used_haddr[haddr] = true;
line_num = i2c_page_alloc(port); line_num = i2c_page_alloc(port);
if (line_num<0){ if (line_num<0){
......
...@@ -110,9 +110,26 @@ long long get_frame_pos(unsigned int chn, unsigned int pos); ...@@ -110,9 +110,26 @@ long long get_frame_pos(unsigned int chn, unsigned int pos);
* @param reg sensor register address (8-bit) * @param reg sensor register address (8-bit)
* @param data value to set (16 bits) */ * @param data value to set (16 bits) */
#define X3X3_I2C_SEND2(port,frame,sa7,reg,data) {\ #define X3X3_I2C_SEND2(port,frame,sa7,reg,data) {\
int _ADDR = pSensorPortConfig[(port)].par2addr[0][(reg)];\ write_xi2c_reg16_abs_asap((port),(sa7),(frame),(reg),(data));\
int _PAGE = pSensorPortConfig[(port)].haddr2rec[0][(_ADDR>>8)&0xff];\ }
write_xi2c_reg16_abs_asap((port),_PAGE,(frame),_ADDR&0xff,(data));\
/** Perform I2C write (8 bits address, 16 bits data in "legacy" mode,
* pages matching slave address should be registered.
*
* TODO: Add registering single sensors as in multi10359. Registering twice is OK.
* Slave address is now 7-bit,old was 8-bit, change (10359 already done)
* @param port - sensor port
* @param frame Frame number to apply, <0 - ASAP
* @param si - slave device index (for mux board)
* @param reg sensor register address (16-bit)
* @param data value to set (16 bits) */
//int _ADDR = pSensorPortConfig[(port)].par2addr[si][(reg)];
#define X3X3_I2C_SEND2_LUT(port,frame,si,reg,data) {\
int _PAGE = pSensorPortConfig[(port)].haddr2rec[(si)][((reg)>>8)&0xff];\
BUG_ON(!(_PAGE&0xffffff00));\
write_xi2c_reg16_abs_asap((port),_PAGE,(frame),(reg)&0xff,(data));\
} }
/** Perform I2C write in immediate mode (8 bits address, 16 bits data in "legacy" mode, /** Perform I2C write in immediate mode (8 bits address, 16 bits data in "legacy" mode,
...@@ -129,6 +146,22 @@ long long get_frame_pos(unsigned int chn, unsigned int pos); ...@@ -129,6 +146,22 @@ long long get_frame_pos(unsigned int chn, unsigned int pos);
write_xi2c_reg16((port),_PAGE,_ADDR&0xff,(data));\ write_xi2c_reg16((port),_PAGE,_ADDR&0xff,(data));\
} }
/** Perform I2C write in immediate mode (8 bits address, 16 bits data in "legacy" mode,
* pages matching slave address should be registered.
*
* Slave address is now 7-bit,old was 8-bit, change (10359 already done)
* @param port - sensor port
* @param si - slave device index (for mux board)
* @param reg sensor register address (8-bit)
* @param data value to set (16 bits) */
#define X3X3_I2C_SEND2_LUT_ASAP(port,si,reg,data) {\
int _PAGE = pSensorPortConfig[(port)].haddr2rec[(si)][((reg)>>8)&0xff];\
BUG_ON(!(_PAGE&0xffffff00));\
write_xi2c_reg16((port),_PAGE,(reg)&0xff,(data));\
}
/** Perform I2C read (8 bits address, 16 bits data in "legacy" mode (sensors and 10359), /** Perform I2C read (8 bits address, 16 bits data in "legacy" mode (sensors and 10359),
* page LEGACY_READ_PAGE2 (==0xff) should be registered - legacy_i2c. * page LEGACY_READ_PAGE2 (==0xff) should be registered - legacy_i2c.
* *
......
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