Commit 6405f029 authored by Andrey Filippov's avatar Andrey Filippov

debugging Boson driver, other warnings cleanup

parent 384c0d4b
......@@ -278,8 +278,8 @@
"sensor_temp 0x18 1 2 100",
"cy22393 0x69 1 1 100",
"lepton35 0x2a 2 2 500",
/*Update elphel393-sensor-i2c to support uart instead of the i2c */
"boson640 0x2a 2 2 500";
/*Update elphel393-sensor-i2c to support uart instead of the i2c. 0x81 - 80 - extif/!i2c, 1 - extif mode,rah:2lsbs - bytes */
"boson640 0x81 2 2 500";
} ;
framepars_operations: elphel393-framepars@0 {
compatible = "elphel,elphel393-framepars-1.00";
......
......@@ -28,6 +28,7 @@ obj-$(CONFIG_ELPHEL393) += pgm_functions.o
obj-$(CONFIG_ELPHEL393) += mt9x001.o
obj-$(CONFIG_ELPHEL393) += mt9f002.o
obj-$(CONFIG_ELPHEL393) += lepton.o
obj-$(CONFIG_ELPHEL393) += boson640.o
obj-$(CONFIG_ELPHEL393) += multi10359.o
obj-$(CONFIG_ELPHEL393) += imu_log393.o
......
/***************************************************************************//**
* @file boson640.c
* @brief
* image sensors
* @copyright Copyright 2004-2016 (C) Elphel, Inc.
* @par <b>License</b>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
//#define DEBUG // should be before linux/module.h - enables dev_dbg at boot in this file (needs "debug" in bootarg)
/****************** INCLUDE FILES SECTION ***********************************/
#include <linux/types.h> // for div 64
#include <asm/div64.h> // for div 64
#include <asm/byteorder.h> // endians
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
//#include <linux/platform_device.h>
#include <linux/device.h> // for dev_dbg, platform_device.h is OK too
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <uapi/elphel/c313a.h>
#include <uapi/elphel/x393_devices.h> // For sysfs
#include <linux/platform_device.h> // For sysfs
#include <linux/errno.h> //ETIMEDOUT
#include <linux/of.h>
#include <linux/jiffies.h>
//#include "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr
//#include "x3x3.h" // detect sensor
//#include "cci2c.h"
#include "boson640.h"
//#include "multi10359.h"
#include "framepars.h" // parameters manipulation
#include "sensor_common.h"
#include "pgm_functions.h"
#include "x393.h"
#include "sensor_i2c.h"
#undef LOCK_BH_SENSORIO
/**
* \def D(x) optional debug output
*/
#if ELPHEL_DEBUG
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
#define MDF4(x) { if (GLOBALPARS(G_DEBUG) & (1 <<4)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
#define ELPHEL_DEBUG_THIS 0
// #define ELPHEL_DEBUG_THIS 1
#else
#define MDF(x)
#define MDF4(x)
#define ELPHEL_DEBUG_THIS 0
#endif
#if ELPHEL_DEBUG_THIS
#define MDF1(x) printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x
#define MDD1(x) printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__); x ; udelay (ELPHEL_DEBUG_DELAY)
#define D(x) printk("%s:%d:",__FILE__,__LINE__);x
#define D1(x) x
#define MD7(x) printk("%s:%d:",__FILE__,__LINE__);x
#define MD9(x) printk("%s:%d:",__FILE__,__LINE__);x
#else
#define MDF1(x)
#define MDD1(x)
#define D(x)
#define D1(x)
#define MD7(x)
#define MD9(x)
#endif
/**
LUT to map SENSOR_REGSxxx to internal sensor register addresses
* needed for any sensor
* For better manual mapping:
- even elements are SENSOR_REGSxxx,
- odd elements are sensor's register addresses.
* has to be at least 16-bit/entry for 16 bit addresses
* (for MT9X001 it's a 1-to-1 mapping)
*/
const unsigned short boson640_par2addr[] = {
P_BOSON_GAO_GAIN, P_BOSON640_REG_gaoSetGainState,
P_BOSON_GAO_FFC, P_BOSON640_REG_gaoSetFfcState,
P_BOSON_GAO_TEMP_CORRECTION, P_BOSON640_REG_gaoSetTempCorrectionState,
P_BOSON_GAO_AVERAGER, P_BOSON640_REG_gaoSetAveragerState,
P_BOSON_GAO_NUM_FFC_FRAMES, P_BOSON640_REG_gaoSetNumFFCFrames,
P_BOSON_GAO_RNS, P_BOSON640_REG_gaoSetRnsState,
P_BOSON_GAO_TEST_RAMP, P_BOSON640_REG_gaoSetTestRampState,
P_BOSON_GAO_SFFC, P_BOSON640_REG_gaoSetSffcState,
P_BOSON_GAO_RPM, P_BOSON640_REG_gaoSetRpmState,
P_BOSON_GAO_FFC_ZERO_MEAN, P_BOSON640_REG_gaoSetFfcZeroMeanState,
P_BOSON_GAO_RNS_POP_THRESHOLD, P_BOSON640_REG_gaoSetRnsPopThreshold,
P_BOSON_GAO_RNS_CLOSE_THRESHOLD, P_BOSON640_REG_gaoSetRnsCloseThreshold,
P_BOSON_GAO_RNS_TOO_FEW, P_BOSON640_REG_gaoSetRnsTooFew,
P_BOSON_GAO_RNS_MIN_CORRECTION, P_BOSON640_REG_gaoSetRnsMinCorrection,
P_BOSON_GAO_RNS_DAMPING, P_BOSON640_REG_gaoSetRnsDamping,
P_BOSON_GAO_RNS_FRAME_HYSTERESIS, P_BOSON640_REG_gaoSetRnsFrameHysteresis,
P_BOSON_GAO_RNS_BAD_DAMPING, P_BOSON640_REG_gaoSetRnsBadDamping,
P_BOSON_GAO_RNS_NUM_GOOD_DAMPING, P_BOSON640_REG_gaoSetRnsNumGoodDampingThreshold,
P_BOSON_ROIC_FPA_RAMP, P_BOSON640_REG_roicSetFPARampState,
P_BOSON_ROIC_FPA_TEMP_OFFSET, P_BOSON640_REG_roicSetFPATempOffset,
P_BOSON_ROIC_FPA_TEMP_MODE, P_BOSON640_REG_roicSetFPATempMode,
P_BOSON_ROIC_FPA_TEMP_VALUE, P_BOSON640_REG_roicSetFPATempValue,
P_BOSON_BPR, P_BOSON640_REG_bprSetState,
P_BOSON_TELEMETRY, P_BOSON640_REG_telemetrySetState,
P_BOSON_TELEMETRY_LOCATION, P_BOSON640_REG_telemetrySetLocation,
P_BOSON_TELEMETRY_PACKING, P_BOSON640_REG_telemetrySetPacking,
P_BOSON_BOSON_RUN_FFC, P_BOSON640_REG_bosonRunFFC, // No matchin read!
P_BOSON_BOSON_SET_FFC_TEMP, P_BOSON640_REG_bosonSetFFCTempThreshold,
P_BOSON_BOSON_SET_FFC_FRAME, P_BOSON640_REG_bosonSetFFCFrameThreshold,
P_BOSON_BOSON_FFC_MODE, P_BOSON640_REG_bosonSetFFCMode,
P_BOSON_BOSON_GAIN_MODE, P_BOSON640_REG_bosonSetGainMode,
P_BOSON_BOSON_FFC_WARN_TIME, P_BOSON640_REG_bosonSetFFCWarnTimeInSecx10,
P_BOSON_BOSON_OVER_TEMP_TIME, P_BOSON640_REG_bosonSetOverTempTimerInSec,
P_BOSON_BOSON_FFC_QUICK_TIME, P_BOSON640_REG_bosonSetTimeForQuickFFCsInSecs,
P_BOSON_BOSON_EXT_SYNC_MODE, P_BOSON640_REG_bosonSetExtSyncMode,
P_BOSON_DVO_DISPLAY_MODE, P_BOSON640_REG_dvoSetDisplayMode,
P_BOSON_SCNR, P_BOSON640_REG_scnrSetEnableState,
P_BOSON_SCNR_TH_COL_SUM, P_BOSON640_REG_scnrSetThColSum,
P_BOSON_SCNR_TH_PIXEL, P_BOSON640_REG_scnrSetThPixel,
P_BOSON_SCNR_MAX_CORR, P_BOSON640_REG_scnrSetMaxCorr,
P_BOSON_SCNR_TH_PIXEL_SAFE, P_BOSON640_REG_scnrSetThPixelSafe,
P_BOSON_SCNR_MAX_CORR_SAFE, P_BOSON640_REG_scnrSetMaxCorrSafe,
P_BOSON_TF, P_BOSON640_REG_tfSetEnableState,
P_BOSON_TF_DELTA_NF, P_BOSON640_REG_tfSetDelta_nf,
P_BOSON_TF_TH_DELTA_MOTION, P_BOSON640_REG_tfSetTHDeltaMotion,
P_BOSON_TF_MOTION_THRESHOLD, P_BOSON640_REG_tfSetMotionThreshold,
P_BOSON_SPNR, P_BOSON640_REG_spnrSetEnableState,
P_BOSON_SPNR_FRAME_DELAY, P_BOSON640_REG_spnrSetFrameDelay,
P_BOSON_SYSCTRL_FREEZE, P_BOSON640_REG_sysctrlSetFreezeState,
P_BOSON_TEST_RAMP_MOTION, P_BOSON640_REG_testRampSetMotionState,
P_BOSON_TEST_RAMP_INDEX, P_BOSON640_REG_testRampSetIndex,
P_BOSON_SRNR, P_BOSON640_REG_srnrSetEnableState,
P_BOSON_SRNR_TH_ROW_SUM, P_BOSON640_REG_srnrSetThRowSum,
P_BOSON_SRNR_TH_PIXEL, P_BOSON640_REG_srnrSetThPixel,
P_BOSON_SRNR_MAX_CORR, P_BOSON640_REG_srnrSetMaxCorr,
// Registers that are not i2c (see if it will register pages)
//Next (P_BOSON640_GP3VSYNC) is the first non-i2c register
// P_BOSON640_GP3VSYNC, P_REG_BOSON640_GP3VSYNC, // 0x0854
// P_BOSON640_TELEN, P_REG_BOSON640_TELEN, // 0x0218
// P_BOSON640_TELLOC, P_REG_BOSON640_TELLOC, // 0x021c
// P_BOSON640_FFC_RUN, P_REG_BOSON640_FFC_RUN,
0xffff // END indicator
};
//#define FIRST_BOSON640_INT P_BOSON640_GP3VSYNC
/**
* get at least one parameter for a page
*/
const unsigned short boson640_pages[] = {
P_BOSON640_REG_gaoSetRnsBadDamping, // 1 byte
P_BOSON640_REG_gaoSetNumFFCFrames, // 2 bytes
P_BOSON640_REG_gaoSetGainState, // 4 bytes
P_BOSON640_REG_roicSetFPATempOffset, // 2 bytes
P_BOSON640_REG_roicSetFPARampState, // 4 bytes
P_BOSON640_REG_bprSetState, // 4 bytes
P_BOSON640_REG_telemetrySetState, // 4 bytes
P_BOSON640_REG_bosonRunFFC, // 0 bytes (no matching read)
P_BOSON640_REG_bosonSetFFCTempThreshold, // 2 bytes
P_BOSON640_REG_bosonSetFFCMode, // 4 bytes
P_BOSON640_REG_dvoSetDisplayMode, // 4 bytes
P_BOSON640_REG_scnrSetThColSum, // 2 bytes
P_BOSON640_REG_scnrSetEnableState, // 4 bytes
P_BOSON640_REG_tfSetDelta_nf, // 2 bytes
P_BOSON640_REG_spnrSetEnableState, // 4 bytes
P_BOSON640_REG_sysctrlSetFreezeState, // 4 bytes
P_BOSON640_REG_testRampSetIndex, // 1 byte
P_BOSON640_REG_testRampSetMotionState, // 4 bytes
P_BOSON640_REG_srnrSetThRowSum, // 2 bytes
P_BOSON640_REG_srnrSetEnableState, // 4 bytes
0xffff // END indicator
};
/**
* pgm_functions latencies table
*/
// ASAP - ASAP
// C,S - continuous/safe TRIG&4=0 SAFE=0 (visa versa?)
// C,NS - continuous/no skip TRIG&4=0 SAFE=1
// A,S - async/safe TRIG&4=4 SAFE=0 (visa versa?)
// A,NS - async/no skip TRIG&4=4 SAFE=1
// NOL - nooverlap TRIG&8=8
// array size is AHEAD_TAB_FUNCS_COUNT
const unsigned short boson640_ahead_tab[] = // copied from mt9x001
{ /// function ASAP C,S C,NS, A,S A,NS NOL
onchange_recalcseq, 0, 0, 0, 0, 0, 0, /// recalculate sequences/latencies, according to P_SKIP, P_TRIG
onchange_detectsensor, 1, 0, 0, 0, 0, 0, /// detect sensor type, sets sensor structure (capabilities), function pointers
onchange_sensorphase, 1, 0, 0, 0, 0, 0, /// program sensor clock/phase (do immediately)
onchange_i2c, 0, 0, 0, 0, 0, 0, /// program i2c
onchange_initsensor, 1, 0, 0, 0, 0, 0, /// resets sensor, reads sensor registers, schedules "secret" manufacturer's corrections to the registers (stops/re-enables hardware i2c)
onchange_afterinit, 0, 0, 0, 0, 0, 0, /// restore image size, decimation,... after sensor reset or set them according to sensor capabilities if none were specified
onchange_multisens, 0, 2, 1, 1, 1, 0, /// chnages related to multiplexed sensors
onchange_window, 0, 2, 1, 1, 1, 0, /// program sensor WOI and mirroring (flipping) - NOTE: 1 bad frame to skip
onchange_window_safe, 0, 1, 1, 1, 1, 0, /// program sensor WOI and mirroring (flipping) - NOTE: no bad frames
onchange_exposure, 0, 2, 1, 1, 1, 0, /// program exposure
onchange_gains, 0, 1, 1, 1, 1, 0, /// program analog gains
onchange_triggermode, 0, 2, 1, 1, 1, 0, /// program sensor trigger mode TODO: does it have any sense here?
onchange_sensorin, 0, 0, 0, 0, 0, 0, /// program sensor input in FPGA (Bayer, 8/16 bits, ??), stop sensor (if needed)
onchange_sensorstop, 0, 0, 0, 0, 0, 0, /// Stop acquisition from the sensor to the FPGA (start has latency of 2)
onchange_sensorrun, 0, 1, 1, 1, 1, 0, /// Start/single acquisition from the sensor to the FPGA (stop has latency of 1)
onchange_gamma, 0, 1, 1, 1, 1, 0, /// program gamma table - make sure table is calculated, maybe send all but last word)
onchange_hist, 0, 0, 0, 0, 0, 0, /// program histogram window TODO: fix FPGA - (now pos_top will be read too early - will use previous ) and add latency
onchange_aexp, 0, 0, 0, 0, 0, 0, /// program autoexposure mode TODO: look what exactly is changed here
onchange_quality, 0, 0, 0, 0, 0, 0, /// program quantization table(s)
onchange_memsensor, 0, 0, 0, 0, 0, 0, /// program memory channels 0 (sensor->memory) and 1 (memory->FPN)
onchange_memcompressor, 0, 0, 0, 0, 0, 0, /// program memory channel 2 (memory->compressor) (delays programming until onchange_comprestart if needed)
/// For Micron sensors limitfps should have the same latency as changing window height, otherwise when WOI_HEIGHT 0x3c0->0x790 and next frame VBLANK 0x13e->0x284
/// sensor waits till the counter overflows (>10 seconds) without any frame sync pulses
onchange_limitfps, 0, 2, 1, 1, 1, 0, /// check compressor will keep up, limit sensor FPS if needed
onchange_compmode, 0, 0, 0, 0, 0, 0, /// program compressor modes
onchange_focusmode, 1, 0, 0, 0, 0, 0, /// program focus modes (through writing the tables, so no sequencer)
onchange_trigseq, 0, 2, 1, 1, 1, 0, /// NC393: OK to program through the sequencer (full 32 bits)
onchange_irq, 0, 0, 0, 0, 0, 0, /// program smart IRQ mode
onchange_comprestart, 0, 0, 0, 0, 0, 0, /// restart after changing geometry (recognizes ASAP and programs memory channel 2 then)
// onchange_compstop should have the same latency as onchange_window
// NC393 - triggered mode wants onchange_compstop==2, while onchange_window == 1?
// TODO: NC393 now comstop is used when changing color modes does not need two cycles - just 1
onchange_compstop, 0, 2, 2, 2, 2, 0, /// stop compressor when changing geometry
onchange_compctl, 0, 0, 1, 1, 1, 0, /// only start/stop/single (after explicitly changed, not when geometry was changed)
onchange_gammaload, 1, 1, 1, 1, 1, 0, /// write gamma tables (should be prepared). Maybe - just last byte, to activate?
onchange_sensorregs, 0, 1, 1, 1, 1, 0, /// write sensor registers (only changed from outside the driver as they may have different latencies)?
onchange_prescal, 0, 0, 0, 0, 0, 0 /// change scales for per-color digital gains, apply vignetting correction
};
static struct device *g_dev_ptr=NULL; ///< Global pointer to basic device structure. This pointer is used in debugfs output functions
void boson640_set_device(struct device *dev) // do nothing, now it has it's own device
{
//g_dev_ptr = dev;
}
/** Capabilities of MT9M001 1.3 MPix */
struct sensor_t boson640={
// sensor constants
.imageWidth = 640, ///< nominal image width for final images
.imageHeight = 512, ///< nominal image height for final images
.clearWidth = 640, ///< maximal clear image width
.clearHeight = 512, ///< maximal clear image height;
.clearTop = 0, ///< top margin to the first clear pixel
.clearLeft = 0, ///< left margin to the first clear pixel
.arrayWidth = 640, ///< total image array width (including black and boundary)
.arrayHeight = 513, ///< total image array height (including black and boundary)
.minWidth = 640, ///< minimal WOI width
.minHeight = 512, ///< minimal WOI height
.minHorBlank = 0, ///< minimal horizontal blanking, in pixels in no-decimation, no-binning mode.
.minLineDur = 640, ///< minimal total line duration, in pixels in no-decimation, no-binning mode.
.maxHorBlank = 640, ///< maximal horizontal blanking/Virtual frame width (depends on sensor type)
.minVertBlank= 0, ///< minimal vertical blanking
.maxVertBlank= 513, ///< maximal vertical blanking/Virtual frame height (depends on sensor type)
.maxShutter = 513, ///< Maximal shutter duration (in lines)
.flips = 0, ///< bit mask bit 0 - flipX, 1 - flipY
.init_flips = 0, ///< normal orientation flips bit mask bit 0 - flipX, 1 - flipY
.bayer = 0, ///< bayer shift for flips==0
.dcmHor = 0x0, ///< available horizontal decimation values 1,2,4,8
.dcmVert = 0x0, ///< available vertical decimation values 1,2,4,8
.binHor = 0x00, ///< available horizontal binning values 1
.binVert = 0x00, ///< vailable vertical binning values 1
.maxGain256 = 0x100, ///< (15.75) maximal analog gain times 0x100
.minGain256 = 0x100, ///< 1.5 times 0x100
.minClockFreq= 27000000, ///< Minimal clock frequency (remove - not needed?)
.maxClockFreq= 27000000, ///< Maximal clock frequency
.nomClockFreq= 27000000, ///< nominal clock frequency
.sensorType = SENSOR_BOSON640, ///< sensor type (for Elphel cameras)
.i2c_addr = BOSON640_I2C_ADDR,///< sensor i2c slave address (7 bits)
.i2c_period = 1000, ///< SCL period in ns, (standard i2c - 2500)
.i2c_bytes = 2, ///< number of bytes/ register
.hact_delay = 0, ///< delay in ps, TBD
.sensorDelay = 0, ///< Dealy from sensor clock at FPGA output to pixel data transition (FPGA input), short cable (ps)
.needReset= SENSOR_NEED_RESET_CLK | SENSOR_NEED_RESET_PHASE ///< bit 0 - need reset after clock frequency change, bit 1 - need reset after phase change
};
// Sysfs Interface for debugging the driver
static int first_sensor_sa7 [SENSOR_PORTS] = {0,0,0,0};
/*
static unsigned int debug_delays = 0x0; // 0x6464; // udelay() values for mrst (low 8 - mrst on), [15:8] - after mrst
static unsigned int debug_modes = 3;
*/
static unsigned short sensor_reg_copy[SENSOR_PORTS][256]; ///< Read all 256 sensor registers here - during initialization and on demand
///< Later may increase to include multiple subchannels on 10359
// a place to add some general purpose register writes to sensors during init
/** Register initial writes for BOSON640 */
/*
static unsigned short boson640_inits[]=
{
};
*/
/*
P_BOSON640_GP3VSYNC, P_REG_BOSON640_GP3VSYNC_VAL, // Enable VSYNC to GPIO3
P_BOSON640_TELEN, 0,
P_BOSON640_TELLOC, 1 // 0 // default is 1, 0 - to check that no wait is needed
// TODO: if needed - add dummy writes?
};
*/
static DEFINE_SPINLOCK(sensorio_lock_0); ///<
static DEFINE_SPINLOCK(sensorio_lock_1); ///<
static DEFINE_SPINLOCK(sensorio_lock_2); ///<
static DEFINE_SPINLOCK(sensorio_lock_3); ///<
/** Define array of pointers to locks - hardware allows concurrent writes to different ports tables */
spinlock_t * sensorio_locks[4] = {&sensorio_lock_0, &sensorio_lock_1, &sensorio_lock_2, &sensorio_lock_3};
//static struct device *sdev = NULL; ///< store this device here -> g_dev_ptr
static u32 uart_seq_number[4]; ///< 0x0000xxxx are used by extif (sequencer module)
static u32 uart_rec_seq_number[4]; ///< last received sequence number
static u32 uart_status[4]; ///< last received status
static u16 uart_cs16[4]; ///< last received checksum
//static int uart_extif_en[4]; ///< extif enabled (set initially to -1,-1,-1,-1
static int uart_extif_en[] = {-1,-1,-1,-1}; ///< extif enabled (set initially to -1,-1,-1,-1
static int uart_length[4]; ///< received/transmitted packet length
static u8 uart_data[4][BOSON_PACKET_MAX_DATA]; ///< received/transmitted packet data
void boson640_reset_release (int sensor_port); // should be called during boson640_pgm_detectsensor
//int boson640_is_booted (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_is_booted (int sensor_port, struct framepars_t * thispars);
int boson640_pgm_detectsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_initsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_sensorin (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_window (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_window_safe (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_window_common (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_limitfps (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_exposure (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_gains (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_triggermode (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int boson640_pgm_sensorregs (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
void io_autoupdate_status (int chn);
void set_sensor_uart_ctl_boson (int chn, int uart_extif_en, int uart_xmit_rst, int uart_recv_rst, int uart_xmit_start, int uart_recv_next);
void set_sensor_uart_start_send (int chn);
void set_sensor_uart_recv_next (int chn);
void set_sensor_uart_set_extif (int chn, int en);
void uart_send_packet (int chn, u32 command, int len, u8 * data);
int uart_receive_packet (int chn, u8* channel, u32* sequence, u32* command, u32* status, int max_bytes, u8* data, u16* cs);
int uart_receive_byte (int chn);
int uart_skip_byte (int chn);
int uart_wait_receive (int chn);
int uart_wait_transmit (int chn);
// SysFS interface functions
static int get_channel_from_name(struct device_attribute *attr);
static ssize_t store_uart_seq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
static ssize_t show_uart_seq(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t store_uart_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
static ssize_t show_uart_status(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t show_uart_cs16(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t store_extif(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
static ssize_t show_extif(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t store_uart_packet(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
static ssize_t show_uart_packet(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t get_uart_help(struct device *dev, struct device_attribute *attr, char *buf);
/* Sysfs functionality */
//======== UART interface ==========
// reset and enable UART communications
/**'
* Control UART
* @param chn sensor port
* @param uart_extif_en 1 - enable sequencer commands, 0 - disable sequencer commands, < 0 - no change
* @param uart_xmit_rst 1 - persistent reset software packet transmission, 0 - normal operation, <0 - no change
* @param uart_recv_rst 1 - persistent reset packet receive, 0 - normal operation, <0 - no change
* @param uart_xmit_start 1 - start transmiting prepared packet (self-clearing)
* @param uart_recv_next 1 - advance receive FIFO to next byte (self-clearing)
*/
void set_sensor_uart_ctl_boson (int chn,
int uart_extif_en,
int uart_xmit_rst,
int uart_recv_rst,
int uart_xmit_start,
int uart_recv_next)
{
x393_sensio_tim1_t uart_ctrl = {.d32=0};
if (uart_extif_en >= 0) {
uart_ctrl.uart_extif_en = uart_extif_en;
uart_ctrl.uart_extif_en_set = 1;
}
if (uart_xmit_rst >= 0) {
uart_ctrl.uart_xmit_rst = uart_xmit_rst;
uart_ctrl.uart_xmit_rst_set = 1;
}
if (uart_recv_rst >= 0) {
uart_ctrl.uart_recv_rst = uart_recv_rst;
uart_ctrl.uart_recv_rst_set = 1;
}
uart_ctrl.uart_xmit_start = uart_xmit_start;
uart_ctrl.uart_recv_next = uart_recv_next;
set_x393_sensio_tim1 (uart_ctrl, chn);
dev_dbg(g_dev_ptr,"set_sensor_uart_ctl_boson(): {%d} uart_ctrl = 0x%x\n", chn, uart_ctrl.d32);
}
void set_sensor_uart_start_send (int chn){ set_sensor_uart_ctl_boson (chn, -1, -1, -1, 1, 0);}
void set_sensor_uart_recv_next (int chn){ set_sensor_uart_ctl_boson (chn, -1, -1, -1, 0, 1);}
void set_sensor_uart_set_extif (int chn,
int en)
{
if (uart_extif_en[chn] != en) {
uart_extif_en[chn] = en;
set_sensor_uart_ctl_boson (chn, en, -1, -1, 0, 0);
}
}
// No control bits but uart_xmit_start, no waiting for completion
void uart_send_packet (int chn, ///< Sensor port
u32 command, ///< module/funcion to send
int len, ///< number of data bytes to send
u8 * data) ///< data to send
{
x393_sensio_tim0_t uart_data;
int i;
uart_data.uart_txd = 0; // channel number == 0
set_x393_sensio_tim0 (uart_data, chn);
dev_dbg(g_dev_ptr,"uart_send_packet(){%d}:channel byte = 0x%x\n", chn, uart_data.d32);
uart_seq_number[chn] += 1;
if (!(uart_seq_number[chn] & 0xffff000)) uart_seq_number[chn] = 0x10000; // skip 16-bit sequnece numbers reserved for extif (sequencer) module
for (i = 24; i >=0; i-=8){ // send sequence number, big endian
uart_data.uart_txd = uart_seq_number[chn] >> i;
set_x393_sensio_tim0 (uart_data, chn);
dev_dbg(g_dev_ptr,"uart_send_packet(){%d}:sequence byte = 0x%x\n", chn, uart_data.d32);
}
for (i = 24; i >=0; i-=8){ // send command, big endian
uart_data.uart_txd = command >> i;
set_x393_sensio_tim0 (uart_data, chn);
dev_dbg(g_dev_ptr,"uart_send_packet(){%d}:command byte = 0x%x\n", chn, uart_data.d32);
}
uart_data.uart_txd = 0xff;
for (i = 0; i < 4; i++){ // send 0xffffffff
set_x393_sensio_tim0 (uart_data, chn);
dev_dbg(g_dev_ptr,"uart_send_packet(){%d}:status byte = 0x%x\n", chn, uart_data.d32);
}
for (i = 0; i < len; i++){
uart_data.uart_txd = data[i];
set_x393_sensio_tim0 (uart_data, chn);
dev_dbg(g_dev_ptr,"uart_send_packet(){%d}:data byte = 0x%x\n", chn, uart_data.d32);
}
set_sensor_uart_start_send (chn);
}
/**
* Read one byte from the UART read FIFO, advance pointer if it was data byte, not EOP
* EOP will need to advance FIFO with an additional call to uart_skip_byte()
* @param chn sensor channel
* @return data byte, -1 for the EOP and -ETIMEDOUT for timeout
*/
int uart_receive_byte (int chn) ///< Sensor port
///< @return byte in 8 LSBs or -1 if EOP (FIFO with EOP will not be advanced!)
{
x393_status_sens_io_t io_status;
int rslt, data;
io_autoupdate_status(chn);
io_status = x393_sensio_status (chn);
if (io_status.recv_eop){
return -1; // does not advance to the next byte !
}
data = io_status.recv_data;
if ((rslt = uart_skip_byte(chn))) return rslt;
return data;
}
/**
* Advance UART read FIFO pointer, check for timeout. Called from uart_receive_byte() and from uart_receive_packet()
* to advance pointer after end of packet
* @param chn sensor channel
* @return 0 - OK, -ETIMEDOUT for timeout
*/
int uart_skip_byte (int chn) ///< Sensor port
///< @return 0 - OK, <0 - error (-ETIMEDOUT)
{
x393_status_sens_io_t io_status, io_status0;
int timeout_duration = 2; // == 1/50 sec
unsigned long timeout_end;
io_autoupdate_status(chn);
io_status0 = x393_sensio_status (chn);
set_sensor_uart_recv_next(chn);
// now wait for either .recv_odd_even toggles or recv_pav is zero
timeout_end = jiffies + timeout_duration;
while (jiffies < timeout_end){
io_status = x393_sensio_status (chn);
if ((!io_status.recv_pav) || (io_status.recv_odd_even != io_status0.recv_odd_even)) return 0;
}
return -ETIMEDOUT;
}
/**
* TODO: add length limit for data (for u32 reasout)
* @param chn
* @param channel
* @param sequence
* @param command
* @param status
* @param max_bytes
* @param data
* @return
*/
int uart_receive_packet (int chn, ///< Sensor port
u8 * channel, ///< if not null, will return packet channel
u32 * sequence, ///< if not null, will return sequence number
u32 * command, ///< if not null, will return command number
u32 * status, ///< if not null, will return status
int max_bytes, ///< maximal number of payload bytes, <0 - use BOSON_PACKET_MAX_DATA
u8 * data, ///< if not null, will return data (up to 756 bytes)
u16* cs) ///< if not null, will return 16-bit checksum
/// < @return number of received data bytes, -1 - packet not available, -2 - packet > 756 (needs reset)
{
x393_status_sens_io_t io_status;
int i;
int recv_data;
int data_len;
if (max_bytes <0){
max_bytes = BOSON_PACKET_MAX_DATA + 2; // 2-byte checksum
}
io_autoupdate_status(chn);
io_status = x393_sensio_status (chn);
dev_dbg(g_dev_ptr,"uart_receive_packet(): {%d} max_bytes = %d, io_status.d32=0x%x\n", chn, max_bytes,io_status.d32);
if (io_status.recv_pav == 0) return -BOSON_ERR_NO_PACKET;
// get packet 1-byte channel
recv_data = uart_receive_byte(chn);
dev_dbg(g_dev_ptr,"uart_receive_packet(): {%d} byte 1 recv_data=0x%x\n", chn, recv_data);
if (channel) *channel = recv_data;
if (recv_data < 0) {
uart_skip_byte (chn); // skip EOP
return -BOSON_ERR_FBP_FORMAT;
}
// get packet 4-byte channel (big endian)
if (sequence) *sequence = 0;
for (i = 24; i >= 0; i-=8){
recv_data = uart_receive_byte(chn);
dev_dbg(g_dev_ptr,"uart_receive_packet(): {%d} bytes seq recv_data=0x%x\n", chn, recv_data);
if (recv_data < 0) {
uart_skip_byte (chn); // skip EOP
return -BOSON_ERR_FBP_FORMAT;
}
if (sequence) *sequence |= (recv_data << i);
}
// get packet 4-byte command (big endian)
if (command) *command = 0;
for (i = 24; i >= 0; i-=8){
recv_data = uart_receive_byte(chn);
dev_dbg(g_dev_ptr,"uart_receive_packet(): {%d} bytes command recv_data=0x%x\n", chn, recv_data);
if (recv_data < 0) {
uart_skip_byte (chn); // skip EOP
return -BOSON_ERR_FBP_FORMAT;
}
if (command) *command |= (recv_data << i);
}
// get packet 4-byte status (big endian)
if (status) *status = 0;
for (i = 24; i >= 0; i-=8){
recv_data = uart_receive_byte(chn);
dev_dbg(g_dev_ptr,"uart_receive_packet(): {%d} bytes status recv_data=0x%x\n", chn, recv_data);
if (recv_data < 0) {
uart_skip_byte (chn); // skip EOP
return -BOSON_ERR_FBP_FORMAT;
}
if (status) *status |= (recv_data << i);
}
// get variable-length (0...756( +2) bytes, optionally limited to provided max_bytes parameter) packet data
for (data_len = 0; data_len < max_bytes; data_len++){
recv_data = uart_receive_byte(chn);
dev_dbg(g_dev_ptr,"uart_receive_packet(): {%d} bytes data recv_data=0x%x\n", chn, recv_data);
if (recv_data < 0) break; // EOP - prematurely, should only happen with "unlimited" data length
if (data) data [data_len] = recv_data;
if (cs) *cs = (*cs << 8) + recv_data;
}
if (recv_data < 0) {
if (max_bytes < (BOSON_PACKET_MAX_DATA + 2)){
uart_skip_byte (chn); // skip EOP
return -BOSON_ERR_FBP_FORMAT;
}
data_len -= 2;
} else { // read 2 bytes to *cs
for (i = 8; i >= 0; i-=8){
recv_data = uart_receive_byte(chn);
dev_dbg(g_dev_ptr,"uart_receive_packet(): {%d} cs recv_data=0x%x\n", chn, recv_data);
if (recv_data < 0) {
uart_skip_byte (chn); // skip EOP
return -BOSON_ERR_FBP_FORMAT;
}
if (cs) *cs |= (*cs << i);
}
}
// Try reading 1 byte - it should be EOP (error if not)
recv_data = uart_receive_byte(chn);
dev_dbg(g_dev_ptr,"uart_receive_packet(): {%d} bytes EOP recv_data=0x%x\n", chn, recv_data);
if (recv_data != -1){
return -BOSON_ERR_NO_EOP;
}
uart_skip_byte (chn); // skip EOP
dev_dbg(g_dev_ptr,"uart_receive_packet(): {%d} data_len = %d\n", chn, data_len);
return data_len;
}
/**
* Wait received packet (as a response to transmitted) with timeout (1/50 sec)
*
* @param chn sensor port
* @return 0 - OK, -ETIMEDOUT - timeout
*/
int uart_wait_receive (int chn)
{
int timeout_duration = 2; // == 1/50 sec
unsigned long timeout_end;
x393_status_sens_io_t io_status;
io_autoupdate_status(chn);
timeout_end = jiffies + timeout_duration;
while (jiffies < timeout_end){
io_autoupdate_status(chn);
io_status = x393_sensio_status (chn);
if (io_status.recv_pav) break;
}
if (io_status.recv_pav == 0) {
dev_dbg(g_dev_ptr, "Timeout waiting for uart recieved packet for channel %d\n",chn);
return -ETIMEDOUT;
}
return 0; // OK
}
int uart_wait_transmit (int chn)
{
int timeout_duration = 2; // == 1/50 sec
unsigned long timeout_end;
x393_status_sens_io_t io_status;
io_autoupdate_status(chn);
timeout_end = jiffies + timeout_duration;
while (jiffies < timeout_end){
io_autoupdate_status(chn);
io_status = x393_sensio_status (chn);
if (io_status.xmit_busy == 0) break;
}
if (io_status.xmit_busy != 0) {
dev_dbg(g_dev_ptr, "Timeout waiting for uart to transmit a packet for channel %d\n",chn);
return -ETIMEDOUT;
}
return 0; // OK
}
void io_autoupdate_status(int chn) ///< Sensor port
{
#ifndef LOCK_BH_SENSORIO
unsigned long flags;
#endif
x393_status_sens_io_t status;
x393_status_ctrl_t status_ctrl = get_x393_sensio_status_cntrl(chn); // last written data to status_cntrl
if (status_ctrl.mode != 3){
#ifdef LOCK_BH_SENSORIO
spin_lock_bh(sensorio_locks[chn]);
#else
spin_lock_irqsave(sensorio_locks[chn],flags);
#endif
status = x393_sensio_status (chn);
status_ctrl.mode = 3;
status_ctrl.seq_num = status.seq_num ^ 0x20;
set_x393_sensio_status_cntrl(status_ctrl, chn);
{
int i;
for (i = 0; i < 10; i++) {
status = x393_sensio_status(chn);
if (likely(status.seq_num = status_ctrl.seq_num)) break;
}
}
#ifdef LOCK_BH_SENSORIO
spin_unlock_bh(sensorio_locks[chn]);
#else
spin_unlock_irqrestore(sensorio_locks[chn],flags);
#endif
dev_dbg(g_dev_ptr, "io_autoupdate_status(%d): mode set to 3, status updated to 0x%08x\n",chn, (int) status.d32);
}
}
/**
* Wait sensor is booted and ready: TODO - use timer interrupts to avoid blocking CPU by multiple channels waiting for i2c (add interrupts?)
*/
/*
int boson640_wait_ready(int sensor_port, ///< sensor port number (0..3)
int sa7, ///< I2C slave address
int num_retries ){ ///< number of retries, 0 - forever
*/ ///< @return > 0 number of retries0 - OK, negative - error
/*
int ntry;
u32 i2c_read_dataw;
boson640_status_t * status = (boson640_status_t *) &i2c_read_dataw;
dev_dbg(g_dev_ptr,"boson640_wait_ready(%d), sa7 =0x%x, P_BOSON640_STATUS= 0x%x\n",sensor_port, sa7, P_BOSON640_STATUS);
// If Lepton is not booted, reading status each ~600ms or sooner delays boot status indefinitely, so if not booted - shut up for 2 seconds
// See if that influences frame times, if yes - delay silently.
X3X3_I2C_RCV2(sensor_port, sa7, P_BOSON640_STATUS, &i2c_read_dataw);
if ((status->boot_mode == 0) || (status->boot_status == 0)) {
dev_dbg(g_dev_ptr,"Lepton on port %d is not booted, wait 1.5 s silently\n",sensor_port);
udelay1000(1500);
} else if (status->rsv5 != 0){
dev_dbg(g_dev_ptr,"Lepton on port %d returned invalid status 0x%x, probably it does not exist - giving up\n",sensor_port, i2c_read_dataw);
return -ENODEV;
}
for (ntry = num_retries; (ntry > 0) || (num_retries == 0); ntry--){
X3X3_I2C_RCV2(sensor_port, sa7, P_BOSON640_STATUS, &i2c_read_dataw);
if ((status->busy == 0) && (status->boot_mode == 1) && (status->boot_status == 1)){
dev_dbg(g_dev_ptr,"boson640_wait_ready(%d) = 0x%x, ntry = %d (of %d)\n",sensor_port, i2c_read_dataw, (num_retries - ntry), num_retries);
return (num_retries - ntry) & 0x7ffffff;
}
udelay1000(1); // wait 1 ms
}
dev_dbg(g_dev_ptr,"boson640_wait_ready(%d) = 0x%x, timeout (%d tries)\n",sensor_port, i2c_read_dataw, num_retries);
*/
// return -ETIMEDOUT;
//}
/**
* Get single internal Lepton register (data length = 1), wait no longer than specified (in ms)
*/
int boson640_read_reg (int sensor_port, ///< sensor port number (0..3)
u8 reg, ///< sensor register index (0..255)
u32 * data ///< will return data
){
// int wait_ms){ ///< milliseconds to wait for ready (if >0)
// assume read register command is next one after set (with the exception of zero-length), same data length
struct sensor_port_config_t *pcfg;
const char *name;
int i;
int sensor_num = 0; // no mux, always 0 sub-channel
int bytes_code, num_bytes, num_received;
u32 command;
u32 function_code; // boson640 combined bytes,module and function
///x393_i2c_device_t * dc;
int extif_en_old, rslt;
u8 rec_bytes[4];
// psensor= &boson640;
pcfg = &pSensorPortConfig[sensor_port];
name = get_name_by_code(pcfg->sensor[0],DETECT_SENSOR); // "boson640"
function_code = pcfg->par2addr[sensor_num][reg];
if (function_code & 0xffff0000){
return -ENOENT; // no such register defined
}
bytes_code = (function_code >> 14) & 3;
if (!bytes_code){
return -EPERM; // Zero bytes in data - nothing to read
}
num_bytes = (bytes_code==3)? 4 : bytes_code;
command = (function_code & 0x3fff) + 1; // here assuming read to be next form swrite!
// disable extif (save if it was enabled)
extif_en_old = uart_extif_en[sensor_port];
set_sensor_uart_set_extif (sensor_port, 0); // disable
// wait uart ready (what about response form Boson???)
if ((rslt=uart_wait_transmit (sensor_port))){
set_sensor_uart_set_extif (sensor_port, extif_en_old); // optionally re-enable
return rslt; // timeout
}
// reset uart transmit and receive
set_sensor_uart_ctl_boson (sensor_port, -1, 1, 1, 0, 0);
set_sensor_uart_ctl_boson (sensor_port, -1, 0, 0, 0, 0);
// update uart_send_packet() to limit number of bytes received
uart_send_packet (sensor_port, command, 0, uart_data[sensor_port]);
if ((rslt = uart_wait_receive (sensor_port)) < 0){ // wait receive packet done, return on timeout
set_sensor_uart_set_extif (sensor_port, extif_en_old); // optionally re-enable
return rslt;
}
num_received = uart_receive_packet (sensor_port,
0, // u8 * channel, // in not null, will return packet channel
uart_rec_seq_number + sensor_port, // u32 * sequence, ///< in not null, will return sequence number
&command, // u32 * command, ///< in not null, will return command number
uart_status + sensor_port, // if not null, will status
-1, // int max_bytes, ///< maximal number of payload bytes, <0 - use BOSON_PACKET_MAX_DATA
rec_bytes, // if not null, will return data (up to 756
uart_cs16 + sensor_port);
if (num_received < 0) {
set_sensor_uart_set_extif (sensor_port, extif_en_old); // optionally re-enable
return num_received; // error
}
if (num_received != num_bytes){
set_sensor_uart_set_extif (sensor_port, extif_en_old); // optionally re-enable
return -EBADF; // different received data length than expected
}
if (data){ // not a null pointer
*data = 0;
for (i = 0; i < num_bytes; i++){
*data = (*data << 8) + rec_bytes[i];
}
}
set_sensor_uart_set_extif (sensor_port, extif_en_old); // optionally re-enable
return 0;
}
/**
* Check is sensor is fully booted and initiate initialization if it first access after frames passed
* Verify before any access to sensor registers
* @param sensor_port
* @param thispars
* @return 0 - too early, 1 - just booted, 2 - booted
*/
int boson640_is_booted ( int sensor_port,
struct framepars_t * thispars) ///< sensor current parameters
{
int cframe;
if (thispars->pars[P_BOOTED]){
return 2; // already booted
}
cframe = getThisFrameNumber(sensor_port); // was cframe16?
if (cframe < BOSON640_BOOT_FRAME){
// dev_warn(g_dev_ptr,"boson640_is_booted(): Not yet fully booted{%d}, frame %d < %d\n",sensor_port, cframe, BOSON640_BOOT_FRAME);
dev_warn(g_dev_ptr,"boson640_is_booted(): Not yet fully booted{%d}, frame %d < %d, P_COLOR =%ld\n",sensor_port, cframe, BOSON640_BOOT_FRAME,thispars->pars[P_COLOR]);
return 0; // too early
}
setFramePar(sensor_port, thispars, P_BOOTED, 1); // should initiate pgm_initsensor and others?
// dev_warn(g_dev_ptr,"boson640_is_booted(): Just fully booted{%d}\n",sensor_port);
dev_warn(g_dev_ptr,"boson640_is_booted(): Just fully booted{%d}, P_COLOR =%ld\n",sensor_port,thispars->pars[P_COLOR]);
return 1; // first time
}
/**
* Detect and initialize sensor and related data structures
* - detect sensor type.
* - if successful, proceed to:,
* -- copy sensor static structure
* -- setup appropriate pgm_* functions
* -- read sensor registers to shadows
* -- initialize appropriate P_* registers (including sensor register shadows) - that initialization will schedule related pgm_* functions
*
* TODO: when is P_CLK_FPGA initialized? Needs to be done before this
* hardware i2c is expected to be reset and initialized - no wrong, it will be programmed in
* onchange_i2c should be the first after init sensor (even before onchange_sensorphase)
* onchange_sensorphase will be triggered after this
* hardware i2c after this function will be disabled, will need onchange_sensorphase to initialize/start it.
*/
int boson640_pgm_detectsensor (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
{
struct sensor_t * psensor; // current sensor
// temporary
struct sensor_port_config_t *pcfg;
const char *name;
x393_i2c_device_t * dc;
dev_info(g_dev_ptr,"**boson640_pgm_detectsensor**: {%d} frame16=%d, thispars->pars[P_SENSOR]= 0x%lx\n",sensor_port,frame16, thispars->pars[P_SENSOR]);
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
// MDD1(printk("sensor=0x%x\n", (int)sensor));
if (thispars->pars[P_SENSOR]!=0) { ///already initialized - called second time after common pgm_detectsensor(), first time is inside pgm_detectsensor()
dev_info(g_dev_ptr,"{%d} sensor 0x%x already detected, exiting\n",sensor_port,(int) thispars->pars[P_SENSOR]);
return sensor->sensorType;
}
psensor= &boson640;
// temporary solution
pcfg = &pSensorPortConfig[sensor_port];
name = get_name_by_code(pcfg->sensor[0],DETECT_SENSOR);
dc = xi2c_dev_get(name);
if (dc){
dev_info(g_dev_ptr,"{%d} setting i2c_addr to 0x%02x\n",sensor_port,dc->slave7);
//pr_info("{%d} Setting i2c_addr to 0x%02x\n",sensor_port,dc->slave7);
psensor->i2c_addr = dc->slave7;
}
// activate + deactivate resets, Boson starts to boot (some 12 seconds). Should be no "i2c" sequencer commands
// or register reads until fully booted
boson640_reset_release (sensor_port);
// Sensor recognized, go on
// memcpy(&sensor, psensor, sizeof(mt9p001)); // copy sensor definitions
memcpy(sensor, psensor, sizeof(boson640)); // copy sensor definitions
// MDD1(dev_dbg(g_dev_ptr,"sensor=0x%x\n", (int)sensor));
dev_dbg(g_dev_ptr,"{%d} copied %d bytes of sensor static parameters\n",sensor_port,sizeof(boson640));
add_sensor_proc(sensor_port,onchange_detectsensor,&boson640_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, &boson640_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, &boson640_pgm_sensorin); // see mt9f002
add_sensor_proc(sensor_port,onchange_exposure, &boson640_pgm_exposure); // program exposure
add_sensor_proc(sensor_port,onchange_window, &boson640_pgm_window); // program sensor WOI and mirroring (flipping)
add_sensor_proc(sensor_port,onchange_window_safe, &boson640_pgm_window_safe); // program sensor WOI and mirroring (flipping) - now - only flipping? with lower latency
add_sensor_proc(sensor_port,onchange_limitfps, &boson640_pgm_limitfps); // check compressor will keep up, limit sensor FPS if needed
add_sensor_proc(sensor_port,onchange_gains, &boson640_pgm_gains); // program analog gains
add_sensor_proc(sensor_port,onchange_triggermode, &boson640_pgm_triggermode); // program sensor trigger mode
add_sensor_proc(sensor_port,onchange_sensorregs, &boson640_pgm_sensorregs); // write sensor registers (only changed from outside the driver as they may have different latencies)?
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType); // should cause other actions - delay for Boson?
setFramePar(sensor_port, thispars, P_BOOTED, 0);
setFramePar(sensor_port, thispars, P_COLOR, COLORMODE_RAW);
setFramePar(sensor_port, thispars, P_BITS, 16);
common_pars->sensors[sensor_port] = sensor->sensorType;
// reset is inactive, acquisition is still off
dev_info(g_dev_ptr,"boson640_pgm_detectsensor()#%d -> = %ld\n",sensor_port, sensor->sensorType);
return sensor->sensorType;
}
/** Reset and initialize sensor
* resets sensor, reads sensor registers, schedules "secret" manufacturer's corrections to the registers (stops/re-enables hardware i2c - 353 only)
* i2c is supposed to be already programmed.
*/
int boson640_pgm_initsensor (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
{
struct frameparspair_t pars_to_update[10]; // for all the sensor registers. Other P_* values will reuse the same ones
int reg;
int nupdate=0;
///x393_sensio_ctl_t sensio_ctl = {.d32=0};
///x393_sensio_tim1_t uart_ctl = {.d32=0};
u32 data32;
int i, rslt; // ,color;
dev_dbg(g_dev_ptr,"boson640_pgm_initsensor(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
if (frame16 >= 0) return -1; // should be ASAP
if (boson640_is_booted (sensor_port, thispars) < 2){ // not yet booted
return -1; // Not yet fully booted.
}
// Was disabled
#if 1
// reset both sequencers to frame 0
sequencer_stop_run_reset(sensor_port, SEQ_CMD_RESET);
sequencer_stop_run_reset(sensor_port, SEQ_CMD_RUN); // also programs status update
i2c_stop_run_reset (sensor_port, I2C_CMD_RUN); // also programs status update
#endif
// boson640_par2addr
// read shadows from the sensor, ignore errors
for (reg = 0; reg < (sizeof(boson640_par2addr)-1)/2; reg++) { // unsigned short data!
data32=0;
rslt = boson640_read_reg(sensor_port, i, &data32); // ignore errors
dev_dbg(g_dev_ptr,"{%d} Reading Boson register (index= %d), data = 0x%x, rslt = %d\n",
sensor_port, reg, data32, rslt);
sensor_reg_copy[sensor_port][reg] = data32; // discarding bits above u16
}
// apply required register overwrites
#if 0
// Can not read shadows in the future, so write only. If needed more registers - manually read defaults
// consider only updating shadows (no actual i2c commands) if the defaults are OK
dev_dbg(g_dev_ptr,"{%d} Programming Lepton registers to take effect during next frame (frame 1 = 0x%x), now 0x%x, frame16=0x%x\n",
sensor_port, first_frame, GLOBALPARS(sensor_port,G_THIS_FRAME), frame16 );
// GLOBALPARS(p,G_THIS_FRAME)
// thisFrameNumber(sensor_port)
// set to empty, nothing will be done for registers (Boson should wait some 70 frames) before communicating
for (i=0; i< sizeof(boson640_inits)/ 4;i++ ) { // unconditionally set those registers NOTE: Should be < 63 of them!
// set in immediate mode (with waits), update shadows
// SET_BOSON640_PAR_IMMED(sensor_port, sensor->i2c_addr, boson640_inits[2*i], boson640_inits[2*i + 1],wait_ms);
// first wtritten, 3rd - not. ANd no images - trying 1 command/frame
SET_BOSON640_PAR_NOWAIT(sensor_port, first_frame, boson640_inits[2*i], boson640_inits[2*i + 1]); // assuming frame reset, so next frame == 1
dev_dbg(g_dev_ptr,"{%d} ****SET_BOSON640_PAR_NOWAIT(0x%x,0x%x,0x%x,0x%x)\n",sensor_port,sensor_port, first_frame, P_SENSOR_REGS+boson640_inits[2*i],boson640_inits[2*i+1]);
sensor_reg_copy[sensor_port][boson640_inits[2*i]] = boson640_inits[2*i + 1];
}
#endif
// next was for lepton
#if 0
pars_to_update[nupdate ].num= P_OVERSIZE; // does not work? - comes from autocampars
pars_to_update[nupdate++].val= 1;
pars_to_update[nupdate ].num= P_WOI_HEIGHT;
#endif
/*
if (sensor_reg_copy[sensor_port][P_BOSON640_TELEN]) {
sensio_ctl.vsync_use = 0;
dev_dbg(g_dev_ptr,"Using %ld rows frame to include telemetry data on port=%d\n",boson640.arrayHeight, sensor_port);
pars_to_update[nupdate++].val= boson640.arrayHeight;
sensio_ctl.telemetry = 1;
} else {
dev_dbg(g_dev_ptr,"Using just %ld rows frame, do not include telemetry data on port=%d\n",boson640.clearHeight, sensor_port);
pars_to_update[nupdate++].val= boson640.clearHeight;
sensio_ctl.telemetry = 0;
}
x393_sensio_ctrl(sensio_ctl,sensor_port);
*/
/*
* boson640.arrayHeight
boson640.clearHeight
*
pars_to_update[nupdate ].num= P_SENSOR_REGS+(reg);\
pars_to_update[nupdate++].val=(data);\
// NC393: both sequencers started in pgm_detectsensor
if (debug_delays & 0xff00) {
udelay ((debug_delays >> 8) & 0xff); // 100);
}
first_sensor_i2c=sensor->i2c_addr;
// TODO: get rid of first_sensor_i2c, leave only mux index
if (GLOBALPARS(sensor_port, G_SENS_AVAIL)) {
first_sensor_i2c+= I2C359_INC * ((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 1)?1:((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 2)?2:3));
}
dev_dbg(g_dev_ptr,"Reading sensor (port=%d) registers to the shadows, sa7=0x%x:\n",sensor_port,first_sensor_i2c);
first_sensor_sa7[sensor_port] = first_sensor_i2c;
for (i=0; i<256; i++) { // read all registers, one at a time (slower than in 353)
X3X3_I2C_RCV2(sensor_port, first_sensor_i2c, i, &(i2c_read_data_dw[i]));
}
dev_dbg(g_dev_ptr,"Read 256 registers (port=%d) ID=0x%x:\n",sensor_port,i2c_read_data_dw[0]);
for (i=0; i<256; i++) { // possible to modify register range to save (that is why nupdate is separate from i)
regval=i2c_read_data_dw[i];
regnum=P_SENSOR_REGS+i;
SETFRAMEPARS_SET(regnum,regval);
if ((mreg=MULTIREG(sensor_port,regnum,0))) for (j=0;j<MAX_SENSORS; j++) {
SETFRAMEPARS_SET(mreg+j,regval);
}
}
for (i=0;i<256;i++) {
sensor_reg_copy[sensor_port][i] = i2c_read_data_dw[i];
}
// if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
if (nupdate) setFrameParsStatic(sensor_port, nupdate, pars_to_update); // save changes to sensor register shadows for all frames
dev_dbg(g_dev_ptr,"Initializing BOSON640 registers with default values:\n");
sensor_register_overwrites= (unsigned short *) &boson640_inits; // why casting is needed?
sensor_register_overwrites_number= sizeof(boson640_inits)/4;
// enable hardware i2c - NOTE: the only place where the i2c controller is enabled.
// dev_dbg(g_dev_ptr,"Starting hardware sequencers\n");
nupdate=0; // Second pass over the registers to set
//#define SET_SENSOR_MBPAR(p,f,s,r,v)
for (i=0; i<sensor_register_overwrites_number;i++ ) { // unconditionally set those registers NOTE: Should be < 63 of them!
SET_SENSOR_MBPAR_LUT(sensor_port,
frame16, // == -1 (immediate)
sensor_register_overwrites[2*i],
sensor_register_overwrites[2*i+1]);
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) sensor_register_overwrites[2*i], (int) sensor_register_overwrites[2*i+1]);
}
SETFRAMEPARS_SET(P_GAIN_MIN, (sensor->minGain256)<<8); // less than that may not saturate sensor and confuse autoexposure/white balancing
SETFRAMEPARS_SET(P_GAIN_MAX, (sensor->maxGain256)<<8);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
// G_* parameters - can write directly
for (color=0;color<4;color++){
for (i=0;i<81;i++) {
GLOBALPARS(sensor_port, G_SENSOR_CALIB+(color<<8)+i)=(i>32)?((i -16)<<14): (i<<13); // one extra
}
}
MDF4(for (i=0; i<1023; i++) {if ((i & 0x1f)==0) dev_dbg(g_dev_ptr,"\n"); dev_dbg(g_dev_ptr," 0x%06lx",GLOBALPARS (sensor_port, G_SENSOR_CALIB+i));});
*/
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to gains and sensor register shadows
return 0;
}
void boson640_reset_release (int sensor_port) ///< sensor port number (0..3)
{
x393_sensio_ctl_t sensio_ctl = {.d32=0};
x393_sensio_tim1_t uart_ctl = {.d32=0};
// int i; // ,color;
sensio_ctl.mrst = 0; // active
sensio_ctl.mrst_set = 1;
sensio_ctl.mmcm_rst = 1;
sensio_ctl.mmcm_rst_set = 1;
sensio_ctl.gp0 = 0; // input (tristate)
sensio_ctl.gp0_set = 1;
sensio_ctl.gp1 = 0; // input (tristate)
sensio_ctl.gp1_set = 1;
sensio_ctl.gp2 = 0; // input (tristate)
sensio_ctl.gp2_set = 1;
sensio_ctl.gp3 = 0; // input (tristate)
sensio_ctl.gp3_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
uart_ctl.uart_extif_en = 0;
uart_ctl.uart_extif_en_set = 1;
uart_ctl.uart_xmit_rst = 1;
uart_ctl.uart_xmit_rst_set = 1;
uart_ctl.uart_recv_rst = 1;
uart_ctl.uart_recv_rst_set = 1;
set_x393_sensio_tim1(uart_ctl, sensor_port);
udelay1000(1); // wait 1 ms
// release master reset and all other resets
sensio_ctl.mrst = 1; // deassert
sensio_ctl.mrst_set = 1;
sensio_ctl.mmcm_rst = 0;
sensio_ctl.mmcm_rst_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
uart_ctl.uart_xmit_rst = 0;
uart_ctl.uart_xmit_rst_set = 1;
uart_ctl.uart_recv_rst = 0;
uart_ctl.uart_recv_rst_set = 1;
uart_ctl.uart_extif_en = 0; // enable extif
uart_ctl.uart_extif_en_set = 1;
set_x393_sensio_tim1(uart_ctl, sensor_port);
}
/**
* Program sensor input in FPGA (Bayer, 8/16 bits, FPN, test mode, number of lines).
*/
int boson640_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
{
// dev_dbg(g_dev_ptr,"boson640_pgm_sensorin(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
if (boson640_is_booted (sensor_port, thispars) < 2){ // not yet booted
return -1; // Not yet fully booted.
}
dev_dbg(g_dev_ptr,"boson640_pgm_sensorin(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
#if 0
x393_sensio_width_t sensio_width = {.d32=0};
int cframe16 = getThisFrameNumber(sensor_port);
dev_dbg(g_dev_ptr,"{%d} s_i cframe16=0x%08x frame16=%d\n",sensor_port,cframe16,frame16);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// mt9f002 needed MT9F002_VACT_DELAY here, but mt9x001 needs 0 - has no real effect probably
if (!(thispars->pars[P_FRAMESYNC_DLY] & 0x10000)){
sensio_width.sensor_width = 0;
X393_SEQ_SEND1(sensor_port, frame16, x393_sensio_width, sensio_width);
}
#endif
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 boson640_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,"boson640_pgm_window(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
return boson640_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
/** Program sensor WOI and mirroring in safe mode (now does the same as boson640_pgm_window)
* Validating, changing related parameters/scheduling actions, scheduling i2c commands */
int boson640_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,"boson640_pgm_window_safe(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
return boson640_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
/** PCommon part of programming sensor WOI */
int boson640_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 ww,wh; // ,wl,wt;
int need_telemetry;
// x393_sensio_ctl_t sensio_ctl = {.d32=0};
struct frameparspair_t pars_to_update[8];
int nupdate=0;
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
if (boson640_is_booted (sensor_port, thispars) < 2){ // not yet booted
return -1; // Not yet fully booted.
}
dev_dbg(g_dev_ptr,"boson640_pgm_window_common(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
dev_dbg(g_dev_ptr,"boson640_pgm_window_common(): {%d} thispars->pars[P_COLOR]=%ld thispars->pars[P_BITS]=%ld\n", sensor_port,thispars->pars[P_COLOR], thispars->pars[P_BITS]);
dev_dbg(g_dev_ptr,"boson640_pgm_window_common(entry): {%d} thispars->pars[P_WOI_HEIGHT]=%ld thispars->pars[P_WOI_WIDTH]=%ld\n", sensor_port,thispars->pars[P_WOI_HEIGHT], thispars->pars[P_WOI_WIDTH]);
dev_dbg(g_dev_ptr,"boson640_pgm_window_common(entry): {%d} thispars->pars[P_SENSOR_PIXV]=%ld thispars->pars[P_SENSOR_PIXH]=%ld\n", sensor_port,thispars->pars[P_SENSOR_PIXV], thispars->pars[P_SENSOR_PIXH]);
ww =sensor->imageWidth;
wh = thispars->pars[P_SENSOR_PIXV];
if (wh > sensor-> imageHeight){ // 512
wh = sensor -> arrayHeight; // with telemetry, 513
need_telemetry = 1;
} else {
wh = sensor -> imageHeight; // without telemetry
need_telemetry = 0;
}
if (unlikely(thispars->pars[P_SENSOR_PIXH] != ww)) { // correct window width if needed
SETFRAMEPARS_SET(P_SENSOR_PIXH, ww);
SETFRAMEPARS_SET(P_WOI_WIDTH, ww);
}
dev_dbg(g_dev_ptr,"boson640_pgm_window_common() {%d} wh=0x%x thispars->pars[P_SENSOR_PIXV]=0x%lx\n",sensor_port, wh, thispars->pars[P_SENSOR_PIXV]);
// if window hight = 513 - enable telemetry, if 512 - disable
if (unlikely(thispars->pars[P_SENSOR_REGS + P_BOSON_TELEMETRY] != need_telemetry)) {
SETFRAMEPARS_SET(P_SENSOR_PIXV, wh); // probably already set by pgm_window_common
SETFRAMEPARS_SET(P_WOI_HEIGHT, wh); // probably already set by pgm_window_common
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_BOSON_TELEMETRY, need_telemetry); // set sensor register and parameter
dev_dbg(g_dev_ptr,"boson640_pgm_window_common() SET_SENSOR_MBPAR_LUT(%d, %d, P_BOSON_TELEMETRY, %d)\n",sensor_port, frame16, need_telemetry);
}
dev_dbg(g_dev_ptr,"boson640_pgm_window_common(exit): {%d} thispars->pars[P_WOI_HEIGHT]=%lx thispars->pars[P_WOI_WIDTH]=%lx\n", sensor_port,thispars->pars[P_WOI_HEIGHT], thispars->pars[P_WOI_WIDTH]);
dev_dbg(g_dev_ptr,"boson640_pgm_window_common(exit): {%d} thispars->pars[P_SENSOR_PIXV]=%lx thispars->pars[P_SENSOR_PIXH]=%lx\n", sensor_port,thispars->pars[P_SENSOR_PIXV], thispars->pars[P_SENSOR_PIXH]);
/*// from Lepton
if (unlikely(thispars->pars[P_SENSOR_REGS + P_BOSON640_TELEN] != need_telemetry)) {
// if (unlikely(thispars->pars[P_SENSOR_PIXV] != wh)) {
SETFRAMEPARS_SET(P_SENSOR_PIXV, wh); // probably already set by pgm_window_common
SETFRAMEPARS_SET(P_WOI_HEIGHT, wh); // probably already set by pgm_window_common
SET_BOSON640_PAR_NOWAIT(sensor_port, frame16, P_BOSON640_TELEN, need_telemetry);
sensio_ctl.telemetry = (wh > sensor -> imageHeight);
sensio_ctl.telemetry_set = 1; // change it later by WINDOEW_HEIGHT?
X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_ctrl, sensio_ctl);
dev_dbg(g_dev_ptr," X393_SEQ_SEND1 (%d, 0x%x, x393_sensio_ctrl, 0x%x)\n",sensor_port, frame16, (int) sensio_ctl.d32);
}
*/
// Margins - set 0
// Program sensor left margin
if (unlikely(thispars->pars[P_WOI_LEFT] != 0)) { // correct window width if needed
SETFRAMEPARS_SET(P_WOI_LEFT, 0);
}
// Program sensor top margin
if (unlikely(thispars->pars[P_WOI_TOP] != 0)) { // correct window width if needed
SETFRAMEPARS_SET(P_WOI_TOP, 0);
}
// 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);
dev_dbg(g_dev_ptr,"{%d} ww =0x%x, wh=0x%x\n",sensor_port, ww, wh);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
return 0;
}
/** Check if compressor can keep up, limit sensor FPS if needed
* FPS is limited by increasing verical blanking, it can not be be made too big, so this method does not work to make time lapse rate. horisontal blanking
* is kept at minimum (to reduce ERS effect) if not specified. If it is specified (>minimal) - it will be used instead.
* calculate line period.
*
* FIXME - uses P_VIRTUAL_WIDTH w/o decreasing it when changing image size? Replace VIRT_WIDTH with HOR_BANK?
* Or require always set them to zero when chnaging WOI?
* FIXME for multisensor - needs per-sensor individual parameters. This uses sensor registers, not the general parameters (i.e. height) */
int boson640_pgm_limitfps (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
{
// nothing to do here?
struct frameparspair_t pars_to_update[2]; // maximum 7 registers updated (need to recount)
int nupdate=0;
// dev_dbg(g_dev_ptr,"boson640_pgm_limitfps(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
dev_dbg(g_dev_ptr,"boson640_pgm_limitfps(): {%d} frame16=%d frame=%ld, P_COLOR =%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port),thispars->pars[P_COLOR]);
if (boson640_is_booted (sensor_port, thispars) < 2){ // not yet booted
return -1; // Not yet fully booted.
}
SETFRAMEPARS_SET(P_FP1000S, 60000);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to gains and sensor register shadows
return 0;
}
/** Program sensor exposure */
int boson640_pgm_exposure (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,"boson640_pgm_exposure(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
dev_dbg(g_dev_ptr,"boson640_pgm_exposure(): {%d} frame16=%d frame=%ld, P_COLOR =%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port),thispars->pars[P_COLOR]);
if (boson640_is_booted (sensor_port, thispars) < 2){ // not yet booted
return -1; // Not yet fully booted.
}
// nothing to do here
return 0;
}
///#define SHIFT_DGAIN 1 // shift digital gain right, so 1.0 is 0x8000 an the full range is 4:1 - make it a parameter?
/** Program analog gains
* program analog gains TODO: Make separate read-only P_ACTUAL_GAIN** ?
* apply sensor-specific restrictions on the allowed gain values
* includes sensor test mode on/off/selection */
//(FRAMEPAR_MODIFIED(P_VEXPOS)
//#define CSCALES_CTL_NORMAL 0 // USE P_*SCALE as is
//#define CSCALES_CTL_RECALC 1 // Recalculate P_*SCALE from P_GAIN*, P_GAING, then use it (will change to CSCALES_CTL_NORMAL when applied)
//#define CSCALES_CTL_FOLLOW 2 // Don't apply P_*SCALE to P_GAIN*, but update it from the current P_*SCALE from P_GAIN*/P_GAING
//#define CSCALES_CTL_DISABLE 3 // Disable P_*SCALE - don't apply P_*SCALE to P_GAIN*, don't update P_*SCALE from P_GAIN*, P_GAING
///#define MAX_DIGITAL_GAIN 0x300 //integer x256 (0x300 ~3.0)
int boson640_pgm_gains (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,"boson640_pgm_gains(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
if (boson640_is_booted (sensor_port, thispars) < 2){ // not yet booted
return -1; // Not yet fully booted.
}
// nothing to do here - add high/low gain of Boson?
return 0;
}
/** Program trigger mode as sensor-specific */
int boson640_pgm_triggermode (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
{
///TODO: Implement for Boson
struct frameparspair_t pars_to_update[4]; ///
int nupdate=0;
dev_dbg(g_dev_ptr,"boson640_pgm_triggermode(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
if (boson640_is_booted (sensor_port, thispars) < 2){ // not yet booted
return -1; // Not yet fully booted.
}
if (thispars->pars[P_TRIG] & 4) { // turn external
if (thispars->pars[P_SENSOR_REGS + P_BOSON_DVO_DISPLAY_MODE] != 1){
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_BOSON_DVO_DISPLAY_MODE, 1);
}
if (thispars->pars[P_SENSOR_REGS + P_BOSON_BOSON_EXT_SYNC_MODE] != 2){
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_BOSON_BOSON_EXT_SYNC_MODE, 2);
}
} else { // turn internal
if (thispars->pars[P_SENSOR_REGS + P_BOSON_BOSON_EXT_SYNC_MODE] != 0){
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_BOSON_BOSON_EXT_SYNC_MODE, 0);
}
}
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to gains and sensor register shadows
return 0;
//P_BOSON_DVO_DISPLAY_MODE : 0 - continuous, 1 - one-shot (can be used always?) - try it manually
//P_BOSON_BOSON_EXT_SYNC_MODE: 0 - internal, 2 - external (treat all !=0 as 2)
// if external - require one-shot, if continuous - allow any
}
/** Program sensor registers (probably just those that are manually set)
* NOTE: all modes but ASAP are limited to 64 registers/frame, no overflow checks are performed! */
int boson640_pgm_sensorregs (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
{
unsigned long bmask32= ((thispars->mod32) >> (P_SENSOR_REGS>>5)) & (( 1 << (P_SENSOR_NUMREGS >> 5))-1) ;
unsigned long mask;
int index,index32, reg_index;
struct frameparspair_t pars_to_update[sizeof(boson640_par2addr)/sizeof(short)/2]; ///
int nupdate=0;
dev_dbg(g_dev_ptr,"boson640_pgm_sensorregs(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
if (boson640_is_booted (sensor_port, thispars) < 2){ // not yet booted
return -1; // Not yet fully booted.
}
dev_dbg(g_dev_ptr,"{%d} bmask32=0x%lx, thispars->mod32=0x%lx, P_SENSOR_REGS=0x%x, P_SENSOR_NUMREGS=0x%x\n",sensor_port,bmask32,thispars->mod32,P_SENSOR_REGS,P_SENSOR_NUMREGS);
if (bmask32) {
for (index32=(P_SENSOR_REGS>>5); bmask32; index32++, bmask32 >>= 1) {
dev_dbg(g_dev_ptr,"{%d} index32=0x%x, bmask32=0x%lx\n",sensor_port,index32,bmask32);
if (bmask32 & 1) {
mask=thispars->mod[index32];
dev_dbg(g_dev_ptr,"{%d} mask=0x%lx\n",sensor_port,mask);
for (index=(index32<<5); mask; index++, mask >>= 1) {
reg_index = (index-P_SENSOR_REGS);
if (mask & 1) {
X3X3_I2C_SEND2(sensor_port, frame16, sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]);
dev_dbg(g_dev_ptr,"Boson640 {%d} X3X3_I2C_SEND2(0x%x, 0x%x, 0x%lx,0x%x,0x%lx)\n",sensor_port,sensor_port, frame16,sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]);
/*// from lepton (disabled)
if (reg_index >= FIRST_BOSON640_INT) {
// X3X3_I2C_SEND2(sensor_port, frame16, sensor->i2c_addr,reg_index,thispars->pars[index]);
SET_BOSON640_PAR_NOWAIT(sensor_port, frame16, reg_index, thispars->pars[index]);
dev_dbg(g_dev_ptr,"{%d} SET_BOSON640_PAR_NOWAIT(0x%x, 0x%x, 0x%lx,0x%lx)\n",
sensor_port,sensor_port, frame16,reg_index,thispars->pars[index]);
}else {
X3X3_I2C_SEND2(sensor_port, frame16, sensor->i2c_addr,reg_index,thispars->pars[index]);
dev_dbg(g_dev_ptr,"{%d} X3X3_I2C_SEND2(0x%x, 0x%x, 0x%lx,0x%x,0x%lx)\n",sensor_port,sensor_port, frame16,sensor->i2c_addr,reg_index,thispars->pars[index]);
}
*/
}
}
thispars->mod[index32]=0;
}
}
thispars->mod32=0;
}
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
// send all parameters marked as "needed to be processed" to the sensor, clear those flags
// mask out all non sensor pars
// unsigned long bmask32= ((thispars->mod32) >> (P_SENSOR_REGS>>5)) & (P_SENSOR_NUMREGS-1) ;
// It will be the first for the frame (before automatic sensor changes).
// Add testing for programmed sensor and move values to later frames (not here butin the pgm_functions)
// nothing to do here now, use similar approach to program non-i2c Lepton registers
return 0;
}
//static short sensor_reg_copy[SENSOR_PORTS][256]; // Read all 256 sensor registers here - during initialization and on demand
// // Later may increase to include multiple subchannels on 10359
// SysFS interface to Boson640
#define SYSFS_PERMISSIONS 0644 /* default permissions for sysfs files */
#define SYSFS_READONLY 0444
#define SYSFS_WRITEONLY 0222
/** Sysfs helper function - get channel number from the last character of the attribute name*/
static int get_channel_from_name(struct device_attribute *attr) ///< Linux kernel interface for exporting device attributes
///< @return channel number
{
int reg = 0;
sscanf(attr->attr.name + (strlen(attr->attr.name)-1), "%du", &reg);
return reg;
}
/**
* Sets transmit sequence number
*/
static ssize_t store_uart_seq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int chn = get_channel_from_name(attr);
int ni;
ni = sscanf(buf,"%i", uart_seq_number+chn);
if (ni < 0) {
return ni; // error
}
return count;
}
/**
* Prints received sequence number
*/
static ssize_t show_uart_seq(struct device *dev, struct device_attribute *attr, char *buf)
{
int chn = get_channel_from_name(attr);
return sprintf(buf,"%d\n", uart_rec_seq_number[chn]);
}
/**
* Enables/disables uart commands from the sequencer
*/
static ssize_t store_uart_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int chn = get_channel_from_name(attr);
int ni;
ni = sscanf(buf,"%i", uart_status+chn);
if (ni < 0) {
return ni; // error
}
return count;
}
/**
* Prints received status
*/
static ssize_t show_uart_status(struct device *dev, struct device_attribute *attr, char *buf)
{
int chn = get_channel_from_name(attr);
return sprintf(buf,"%d\n", uart_status[chn]);
}
/**
* Prints received status
*/
static ssize_t show_uart_cs16(struct device *dev, struct device_attribute *attr, char *buf)
{
int chn = get_channel_from_name(attr);
return sprintf(buf,"%d\n", uart_cs16[chn]);
}
/**
* Enables/disables uart commands from the sequencer
*/
static ssize_t store_extif(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int chn = get_channel_from_name(attr);
int ni;
int en;
ni = sscanf(buf,"%i", &en);
if (ni < 0) {
return ni; // error
} else if (ni > 0) {
set_sensor_uart_set_extif(chn, en); // Will set shadow too
}
return count;
}
/**
* Prints extif enabled status
*/
static ssize_t show_extif(struct device *dev, struct device_attribute *attr, char *buf)
{
int chn = get_channel_from_name(attr);
return sprintf(buf,"%d\n", uart_extif_en[chn]);
}
/**
* Enables/disables uart commands from the sequencer
*/
static ssize_t store_uart_packet(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int chn = get_channel_from_name(attr);
int i, ni, np, nb;
u32 command;
u32 data32;
int d;
char char_nb; // 0,1,2,4 bytes or 'b' for byte sequence
char pair[2]; // a pair of characters for next byte (or '0x')
int rslt;
/// char * cp;
// dev_dbg(g_dev_ptr,"store_uart_packet(): {%d}\n", chn);
ni = sscanf(buf,"%i %c %n", &command, &char_nb, &np); // last is a pointer to number of consumed characters
dev_dbg(g_dev_ptr,"store_uart_packet(): {%d} command = 0x%x result = %d, consumed_bytes = %d\n", chn, command, ni, np);
if (ni < 0) {
return ni; // error
} else if (ni <2) {
return -EILSEQ;
}
switch (char_nb){
case '0':
case '1':
case '2':
case '4':
nb = char_nb - '0';
break;
case 'b':
case 'B':
nb = -1;
break;
default:
return -EINVAL;
}
if (nb >= 0){
ni = sscanf(buf+np,"%i", &data32);
for (i = 0; i < nb; i++){
uart_data[chn][i] = (data32 >> (8 * (nb - i -1))) & 0xff;
}
} else {
nb = 0;
for (; nb < BOSON_PACKET_MAX_DATA; nb++){
ni = sscanf(buf+np,"%2c", pair);
if (ni < 1){
break;
}
if ((nb == 0) && (pair[0] == '0') && ((pair[1] == 'x') || (pair[1] == 'X'))){
nb --; // skip optional leading 0x
} else {
ni = sscanf(pair,"%2x", &d);
if (ni < 1){
return -EILSEQ; // not a hex byte
}
uart_data[chn][nb] = d;
}
np+=2;
}
}
// reset uart transmit and receive
set_sensor_uart_ctl_boson (chn, -1, 1, 1, 0, 0);
set_sensor_uart_ctl_boson (chn, -1, 0, 0, 0, 0);
dev_dbg(g_dev_ptr,"store_uart_packet(): {%d} command = 0x%x nb = %d\n", chn, command, nb);
uart_send_packet (chn, command, nb, uart_data[chn]);
// if ((rslt = uart_wait_transmit (chn)) < 0){ // wait transmit done, return on timeout
// return rslt;
// }
if ((rslt = uart_wait_receive (chn)) < 0){ // wait transmit done, return on timeout
return rslt;
}
dev_dbg(g_dev_ptr,"store_uart_packet(): {%d} returned %d\n", chn, rslt);
uart_length[chn]= uart_receive_packet (chn,
0, // u8 * channel, // in not null, will return packet channel
uart_rec_seq_number + chn, // u32 * sequence, ///< in not null, will return sequence number
&command, // u32 * command, ///< in not null, will return command number
uart_status + chn, // if not null, will status
-1, // limited by BOSON_PACKET_MAX_DATA only
uart_data[chn], // if not null, will return data (up to 756 bytes)
uart_cs16 +chn);
dev_dbg(g_dev_ptr,"store_uart_packet(): uart_receive_packet() {%d} returned %d\n", chn, uart_length[chn]);
if (uart_length[chn] < 0) {
switch (uart_length[chn]){
case -BOSON_ERR_NO_PACKET: return -EPIPE;
case -BOSON_ERR_FBP_FORMAT: return -EINTR;
case -BOSON_ERR_NO_EOP: return -EMSGSIZE;
default: return -EINVAL; // not yet possible
}
return uart_length[chn] ; // error
}
if (uart_status[chn]){
return -EPROTO; // non-zero status
}
return count;
}
/**
* Prints received data (or status with 'ERR ' prefix if status !=0)
*/
static ssize_t show_uart_packet(struct device *dev, struct device_attribute *attr, char *buf)
{
u32 d;
int i;
char * cp;
int chn = get_channel_from_name(attr);
if (uart_status[chn]){
return sprintf(buf,"ERR %d (0x%x)\n", uart_status[chn], uart_status[chn]);
} else if (uart_length[chn] < 1){
return sprintf(buf,"None\n");
} else if (uart_length[chn] <= 4){
d = 0;
for (i = 0; i < uart_length[chn]; i++){
d <<= 8;
d+=uart_data[chn][i];
}
return sprintf(buf,"%d (0x%x)\n", d, d);
}
cp = buf;
cp += sprintf(cp,"0x");
for (i = 0; i < uart_length[chn]; i++){
cp += sprintf(cp,"%02x", uart_data[chn][i]);
}
cp += sprintf(cp,"\n");
return cp - buf;
}
/** Sysfs function - output instructions text of how to communicate with i2c devices attached to the sensor ports.
* Output buffer *buf will contain multi-line instructions text */
static ssize_t get_uart_help(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,"Numeric suffix in the file names selects sensor port\n"
"uart_seq: read - last received sequence number, write - next transmit sequence number (will skip lower 0x10000 for extif)\n"
"uart_status: read only - last received status\n"
"uart_cs: read only - last received checksum (16 bits)\n"
"extif_en: enable/disable extif (sequencer-generated uart commands)\n"
"uart: write command+data, read - last received data\n"
);
}
//============================================== end of sysfs functions =================
/*
// Dump 256 16-bit sensor registers
static ssize_t show_sensor_regs(struct device *dev, struct device_attribute *attr, char *buf)
{
int chn = get_channel_from_name(attr);
char * cp = buf;
int i,j, ij=0;
for (i=0; i < 16; i++){
cp += sprintf(cp,"%02x:",i*16);
for (j=0;j<16;j++) cp += sprintf(cp," %04x", sensor_reg_copy[chn][ij++]);
cp += sprintf(cp,"\n");
}
return cp - buf;
}
// Ignore data, re-read 256 sensor registers
static ssize_t store_sensor_regs(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int chn = get_channel_from_name(attr);
u32 datai2c;
int i;
if (first_sensor_sa7[chn]) for (i = 0; i< 256;i++) {
X3X3_I2C_RCV2(chn, first_sensor_sa7[chn], i, &datai2c);
sensor_reg_copy[chn][i] = datai2c;
}
return count;
}
static ssize_t show_debug_delays(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"0x%08x\n", debug_delays);
}
static ssize_t store_debug_delays(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
if (!sscanf(buf, "%x", &debug_delays)) {
return - EINVAL;
}
return count;
}
static ssize_t show_debug_modes(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"0x%08x\n", debug_modes);
}
static ssize_t store_debug_modes(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
if (!sscanf(buf, "%x", &debug_modes)) {
return - EINVAL;
}
return count;
}
static DEVICE_ATTR(sensor_regs0, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs);
static DEVICE_ATTR(sensor_regs1, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs);
static DEVICE_ATTR(sensor_regs2, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs);
static DEVICE_ATTR(sensor_regs3, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs);
static DEVICE_ATTR(debug_delays, SYSFS_PERMISSIONS, show_debug_delays, store_debug_delays);
static DEVICE_ATTR(debug_modes, SYSFS_PERMISSIONS, show_debug_modes, store_debug_modes);
static struct attribute *root_dev_attrs[] = {
&dev_attr_sensor_regs0.attr,
&dev_attr_sensor_regs1.attr,
&dev_attr_sensor_regs2.attr,
&dev_attr_sensor_regs3.attr,
&dev_attr_debug_delays.attr,
&dev_attr_debug_modes.attr,
NULL
};
*/
static DEVICE_ATTR(uart_seq0, SYSFS_PERMISSIONS, show_uart_seq, store_uart_seq);
static DEVICE_ATTR(uart_seq1, SYSFS_PERMISSIONS, show_uart_seq, store_uart_seq);
static DEVICE_ATTR(uart_seq2, SYSFS_PERMISSIONS, show_uart_seq, store_uart_seq);
static DEVICE_ATTR(uart_seq3, SYSFS_PERMISSIONS, show_uart_seq, store_uart_seq);
static DEVICE_ATTR(uart_status0, SYSFS_PERMISSIONS, show_uart_status, store_uart_status);
static DEVICE_ATTR(uart_status1, SYSFS_PERMISSIONS, show_uart_status, store_uart_status);
static DEVICE_ATTR(uart_status2, SYSFS_PERMISSIONS, show_uart_status, store_uart_status);
static DEVICE_ATTR(uart_status3, SYSFS_PERMISSIONS, show_uart_status, store_uart_status);
static DEVICE_ATTR(uart_cs0,SYSFS_PERMISSIONS & SYSFS_READONLY, show_uart_cs16, store_uart_status);
static DEVICE_ATTR(uart_cs1,SYSFS_PERMISSIONS & SYSFS_READONLY, show_uart_cs16, store_uart_status);
static DEVICE_ATTR(uart_cs2,SYSFS_PERMISSIONS & SYSFS_READONLY, show_uart_cs16, store_uart_status);
static DEVICE_ATTR(uart_cs3,SYSFS_PERMISSIONS & SYSFS_READONLY, show_uart_cs16, store_uart_status);
static DEVICE_ATTR(extif_en0, SYSFS_PERMISSIONS, show_extif, store_extif);
static DEVICE_ATTR(extif_en1, SYSFS_PERMISSIONS, show_extif, store_extif);
static DEVICE_ATTR(extif_en2, SYSFS_PERMISSIONS, show_extif, store_extif);
static DEVICE_ATTR(extif_en3, SYSFS_PERMISSIONS, show_extif, store_extif);
static DEVICE_ATTR(uart0, SYSFS_PERMISSIONS, show_uart_packet, store_uart_packet);
static DEVICE_ATTR(uart1, SYSFS_PERMISSIONS, show_uart_packet, store_uart_packet);
static DEVICE_ATTR(uart2, SYSFS_PERMISSIONS, show_uart_packet, store_uart_packet);
static DEVICE_ATTR(uart3, SYSFS_PERMISSIONS, show_uart_packet, store_uart_packet);
static DEVICE_ATTR(help, SYSFS_PERMISSIONS & SYSFS_READONLY, get_uart_help, NULL);
static struct attribute *root_dev_attrs[] = {
&dev_attr_uart_seq0.attr,
&dev_attr_uart_seq1.attr,
&dev_attr_uart_seq2.attr,
&dev_attr_uart_seq3.attr,
&dev_attr_uart_status0.attr,
&dev_attr_uart_status1.attr,
&dev_attr_uart_status2.attr,
&dev_attr_uart_status3.attr,
&dev_attr_uart_cs0.attr,
&dev_attr_uart_cs1.attr,
&dev_attr_uart_cs2.attr,
&dev_attr_uart_cs3.attr,
&dev_attr_extif_en0.attr,
&dev_attr_extif_en1.attr,
&dev_attr_extif_en2.attr,
&dev_attr_extif_en3.attr,
&dev_attr_uart0.attr,
&dev_attr_uart1.attr,
&dev_attr_uart2.attr,
&dev_attr_uart3.attr,
&dev_attr_help.attr,
NULL
};
static const struct attribute_group dev_attr_root_group = {
.attrs = root_dev_attrs,
.name = NULL,
};
static int elphel393_boson640_sysfs_register(struct platform_device *pdev)
{
int retval=0;
struct device *dev = &pdev->dev;
if (&dev->kobj) {
if (((retval = sysfs_create_group(&dev->kobj, &dev_attr_root_group)))<0) return retval;
}
return retval;
}
int boson640_init(struct platform_device *pdev)
{
// int res;
struct device *dev = &pdev->dev;
// const struct of_device_id *match;
int sensor_port;
for (sensor_port = 0; sensor_port < SENSOR_PORTS; sensor_port++) {
first_sensor_sa7[sensor_port] = 0;
}
elphel393_boson640_sysfs_register(pdev);
dev_info(dev, DEV393_NAME(DEV393_BOSON640)": registered sysfs\n");
g_dev_ptr = dev;
return 0;
}
int boson640_remove(struct platform_device *pdev)
{
unregister_chrdev(DEV393_MAJOR(DEV393_BOSON640), DEV393_NAME(DEV393_BOSON640));
return 0;
}
static const struct of_device_id elphel393_boson640_of_match[] = {
{ .compatible = "elphel,elphel393-boson640-1.00" },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, elphel393_boson640_of_match);
static struct platform_driver elphel393_boson640 = {
.probe = boson640_init,
.remove = boson640_remove,
.driver = {
.name = DEV393_NAME(DEV393_BOSON640),
.of_match_table = elphel393_boson640_of_match,
},
};
module_platform_driver(elphel393_boson640);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION("Driver for BOSON640 interface (Boson640)* in Elphel cameras");
/***************************************************************************//**
* @file boson640.h
* @brief sopport for boson640 sesnor (currently just a copy of boson640)
* @copyright Copyright 2021 (C) Elphel, Inc.
* @par <b>License</b>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
#ifndef _BOSON640_H
#define _BOSON640_H
#define BOSON640_I2C_ADDR 0x81 ///< Boson UART ext mode = 1 instead of the I2C slave address (7 bit)
#define BOSON640_BOOT_FRAME 75 ///< do not communicate with the sensor if frame number is less than this
// encoding number of data bytes in 2 msb of the 16-bit register address, will be encoded in sa field
#define BOSON640_0BYTES 0x000 ///< add to rah for zero data length
#define BOSON640_1BYTES 0x4000 ///< add to rah for 1-byte data
#define BOSON640_2BYTES 0x8000 ///< add to rah for 2-byte data
#define BOSON640_4BYTES 0xc000 ///< add to rah for 4-byte data
// Boson modules
#define BOSON640_GAO 0x0000
#define BOSON640_ROIC 0x0200
#define BOSON640_BPR 0x0300
#define BOSON640_TELEMETRY 0x0400
#define BOSON640_BOSON 0x0500
#define BOSON640_DVO 0x0600
#define BOSON640_SCNR 0x0800
#define BOSON640_TNR 0x0a00
#define BOSON640_SPNR 0x0c00
#define BOSON640_SYSCTL 0x0e00
#define BOSON640_TESTRAMP 0x1000
#define BOSON640_SRNR 0x2800
// Boson functions: MSB - number of bytes in 2 msb, module (6 bits), function - LSB (stars - how needed is it to implement)
#define P_BOSON640_REG_gaoSetGainState (BOSON640_4BYTES + BOSON640_GAO + 0x01) // **
#define P_BOSON640_REG_gaoSetFfcState (BOSON640_4BYTES + BOSON640_GAO + 0x03) // **
#define P_BOSON640_REG_gaoSetTempCorrectionState (BOSON640_4BYTES + BOSON640_GAO + 0x05) // *
#define P_BOSON640_REG_gaoSetIConstL (BOSON640_2BYTES + BOSON640_GAO + 0x07)
#define P_BOSON640_REG_gaoSetIConstM (BOSON640_2BYTES + BOSON640_GAO + 0x09)
#define P_BOSON640_REG_gaoSetAveragerState (BOSON640_4BYTES + BOSON640_GAO + 0x0b) // *
#define P_BOSON640_REG_gaoSetNumFFCFrames (BOSON640_2BYTES + BOSON640_GAO + 0x0d) // **
#define P_BOSON640_REG_gaoSetRnsState (BOSON640_4BYTES + BOSON640_GAO + 0x11) // *
#define P_BOSON640_REG_gaoSetTestRampState (BOSON640_4BYTES + BOSON640_GAO + 0x13) // **
#define P_BOSON640_REG_gaoSetSffcState (BOSON640_4BYTES + BOSON640_GAO + 0x17) // *
#define P_BOSON640_REG_gaoSetRpmState (BOSON640_4BYTES + BOSON640_GAO + 0x19) // *
#define P_BOSON640_REG_gaoSetFfcZeroMeanState (BOSON640_4BYTES + BOSON640_GAO + 0x25) // *
#define P_BOSON640_REG_gaoSetRnsPopThreshold (BOSON640_2BYTES + BOSON640_GAO + 0x2b) // *
#define P_BOSON640_REG_gaoSetRnsCloseThreshold (BOSON640_2BYTES + BOSON640_GAO + 0x2d) // *
#define P_BOSON640_REG_gaoSetRnsTooFewQuit (BOSON640_2BYTES + BOSON640_GAO + 0x2f) // *
#define P_BOSON640_REG_gaoSetRnsTooFew (BOSON640_2BYTES + BOSON640_GAO + 0x31) // *
#define P_BOSON640_REG_gaoSetRnsMinCorrection (BOSON640_2BYTES + BOSON640_GAO + 0x33) // *
#define P_BOSON640_REG_gaoSetRnsDamping (BOSON640_2BYTES + BOSON640_GAO + 0x35) // *
#define P_BOSON640_REG_gaoSetRnsFrameHysteresis (BOSON640_2BYTES + BOSON640_GAO + 0x37) // *
#define P_BOSON640_REG_gaoSetRnsBadDamping (BOSON640_1BYTES + BOSON640_GAO + 0x39) // *
#define P_BOSON640_REG_gaoSetRnsNumGoodDampingThreshold (BOSON640_2BYTES + BOSON640_GAO + 0x3b) // *
#define P_BOSON640_REG_roicSetFPARampState (BOSON640_4BYTES + BOSON640_ROIC + 0x14) // **
#define P_BOSON640_REG_roicSetFPATempOffset (BOSON640_2BYTES + BOSON640_ROIC + 0x1b) // *
#define P_BOSON640_REG_roicSetFPATempMode (BOSON640_4BYTES + BOSON640_ROIC + 0x1d) // *
#define P_BOSON640_REG_roicSetFPATempValue (BOSON640_2BYTES + BOSON640_ROIC + 0x22) // *
#define P_BOSON640_REG_bprSetState (BOSON640_4BYTES + BOSON640_BPR + 0x02) // **
#define P_BOSON640_REG_telemetrySetState (BOSON640_4BYTES + BOSON640_TELEMETRY + 0x01) // *****
#define P_BOSON640_REG_telemetrySetLocation (BOSON640_4BYTES + BOSON640_TELEMETRY + 0x03) // *****
#define P_BOSON640_REG_telemetrySetPacking (BOSON640_4BYTES + BOSON640_TELEMETRY + 0x05) // **
#define P_BOSON640_REG_bosonRunFFC (BOSON640_0BYTES + BOSON640_BOSON + 0x07) // *****
#define P_BOSON640_REG_bosonSetFFCTempThreshold (BOSON640_2BYTES + BOSON640_BOSON + 0x08) // ***
#define P_BOSON640_REG_bosonSetFFCFrameThreshold (BOSON640_4BYTES + BOSON640_BOSON + 0x0b) // ***
#define P_BOSON640_REG_bosonReboot (BOSON640_0BYTES + BOSON640_BOSON + 0x10) // *
#define P_BOSON640_REG_bosonSetFFCMode (BOSON640_4BYTES + BOSON640_BOSON + 0x12) // ***
#define P_BOSON640_REG_bosonSetGainMode (BOSON640_4BYTES + BOSON640_BOSON + 0x14) // ***
#define P_BOSON640_REG_bosonSetFFCWarnTimeInSecx10 (BOSON640_2BYTES + BOSON640_BOSON + 0x74) // *
#define P_BOSON640_REG_bosonSetOverTempTimerInSec (BOSON640_2BYTES + BOSON640_BOSON + 0x77) // *
#define P_BOSON640_REG_bosonSetTimeForQuickFFCsInSecs (BOSON640_4BYTES + BOSON640_BOSON + 0x7a) // *
#define P_BOSON640_REG_bosonSetExtSyncMode (BOSON640_4BYTES + BOSON640_BOSON + 0x98) // *****
#define P_BOSON640_REG_dvoSetDisplayMode (BOSON640_4BYTES + BOSON640_DVO + 0x0d) // ***** (single/continuous)
#define P_BOSON640_REG_dvoSetType (BOSON640_4BYTES + BOSON640_DVO + 0x0f) // (mono16/....)
#define P_BOSON640_REG_scnrSetEnableState (BOSON640_4BYTES + BOSON640_SCNR + 0x01) // **
#define P_BOSON640_REG_scnrSetThColSum (BOSON640_2BYTES + BOSON640_SCNR + 0x03) // *
#define P_BOSON640_REG_scnrSetThPixel (BOSON640_2BYTES + BOSON640_SCNR + 0x05) // *
#define P_BOSON640_REG_scnrSetMaxCorr (BOSON640_2BYTES + BOSON640_SCNR + 0x07) // *
#define P_BOSON640_REG_scnrSetThPixelSafe (BOSON640_2BYTES + BOSON640_SCNR + 0x0e) // *
#define P_BOSON640_REG_scnrSetMaxCorrSafe (BOSON640_2BYTES + BOSON640_SCNR + 0x10) // *
#define P_BOSON640_REG_tfSetEnableState (BOSON640_4BYTES + BOSON640_TNR + 0x01) // **
#define P_BOSON640_REG_tfSetDelta_nf (BOSON640_2BYTES + BOSON640_TNR + 0x03) // *
#define P_BOSON640_REG_tfSetTHDeltaMotion (BOSON640_2BYTES + BOSON640_TNR + 0x05) // *
#define P_BOSON640_REG_tfSetMotionThreshold (BOSON640_4BYTES + BOSON640_TNR + 0x0e) // *
#define P_BOSON640_REG_spnrSetEnableState (BOSON640_4BYTES + BOSON640_SPNR + 0x01) // **
#define P_BOSON640_REG_spnrSetFrameDelay (BOSON640_4BYTES + BOSON640_SPNR + 0x05) // *
// All others in SPNR require FLOAT values that are not supported in the sequencer
#define P_BOSON640_REG_sysctrlSetFreezeState (BOSON640_4BYTES + BOSON640_SYSCTL + 0x01) // **
// Not all test ramp commands fit
#define P_BOSON640_REG_testRampSetMotionState (BOSON640_4BYTES + BOSON640_TESTRAMP + 0x04) // *
#define P_BOSON640_REG_testRampSetIndex (BOSON640_1BYTES + BOSON640_TESTRAMP + 0x06) // *
#define P_BOSON640_REG_srnrSetEnableState (BOSON640_4BYTES + BOSON640_SRNR + 0x01) // **
#define P_BOSON640_REG_srnrSetThRowSum (BOSON640_2BYTES + BOSON640_SRNR + 0x03) // *
#define P_BOSON640_REG_srnrSetThPixel (BOSON640_2BYTES + BOSON640_SRNR + 0x05) // *
#define P_BOSON640_REG_srnrSetMaxCorr (BOSON640_2BYTES + BOSON640_SRNR + 0x07) // *
/**
* SENSOR_REGSxx
*/
#define P_BOSON_GAO_GAIN 0 ///< Enables / disables application of per-pixel gain coefficients
#define P_BOSON_GAO_FFC 1 ///< Enables / disables application of per-pixel Flat-Field Correction (FFC) coefficients
#define P_BOSON_GAO_TEMP_CORRECTION 2 ///< Enables / disables application of per-pixel temperature corrections
#define P_BOSON_GAO_AVERAGER 3 ///< Enables / disables a smart-averager function which cuts frame rate in half
#define P_BOSON_GAO_NUM_FFC_FRAMES 4 ///< Specifies the number of frames (2, 4, 8, or 16) to be integrated during flat-field correction (FFC)
#define P_BOSON_GAO_RNS 5 ///< Overrides the availability of the row-noise suppression (RNS) algorithm
#define P_BOSON_GAO_TEST_RAMP 6 ///< Enables / disables a test ramp generated by internal electronics (in lieu of data from the sensor array)
#define P_BOSON_GAO_SFFC 7 ///< Enables / disables supplemental flat-field correction (SFFC)
#define P_BOSON_GAO_RPM 8 ///< RPM (?) enable
#define P_BOSON_GAO_FFC_ZERO_MEAN 9 ///< (?)
#define P_BOSON_GAO_RNS_POP_THRESHOLD 10 ///< (?)
#define P_BOSON_GAO_RNS_CLOSE_THRESHOLD 11 ///< (?)
#define P_BOSON_GAO_RNS_TOO_FEW 12 ///< (?)
#define P_BOSON_GAO_RNS_MIN_CORRECTION 13 ///< (?)
#define P_BOSON_GAO_RNS_DAMPING 14 ///< (?)
#define P_BOSON_GAO_RNS_FRAME_HYSTERESIS 15 ///< (?)
#define P_BOSON_GAO_RNS_BAD_DAMPING 16 ///< (?)
#define P_BOSON_GAO_RNS_NUM_GOOD_DAMPING 17 ///< (?)
#define P_BOSON_ROIC_FPA_RAMP 18 ///< Enables / disables a test ramp generated by the sensor array
#define P_BOSON_ROIC_FPA_TEMP_OFFSET 19 ///< Specifies an override of or an offset applied to the camera's internal temperature sensor
#define P_BOSON_ROIC_FPA_TEMP_MODE 20 ///< Specifies the FPA temp mode (normal, fixed/override, or offset)
#define P_BOSON_ROIC_FPA_TEMP_VALUE 21 ///< Sets the value of the FPA temp when the FPA temp mode is set to fixed
#define P_BOSON_BPR 22 ///< Enables / disables the bad-pixel replace (BPR) algorithm
#define P_BOSON_TELEMETRY 23 ///< Set the telemetry state to Enabled or Disabled
#define P_BOSON_TELEMETRY_LOCATION 24 ///< Set the telemetry to before(top) or after(bottom) the image
#define P_BOSON_TELEMETRY_PACKING 25 ///< Sets the type of packing that the telemetry data is preseneted - 16 Bit, Color or 8 -Bit
#define P_BOSON_BOSON_RUN_FFC 26 ///< Performs an FFC operation *** No matching read !! ***
#define P_BOSON_BOSON_SET_FFC_TEMP 27 ///< Sets the temperature threshold (in degC*10) for the FFC desired flag
#define P_BOSON_BOSON_SET_FFC_FRAME 28 ///< Sets the time threshold (in seconds) for the FFC desired flag
#define P_BOSON_BOSON_FFC_MODE 29 ///< Sets the mode of the camera's FFC operation (0 - manual, 1 - auto, 2 - external, 3- shutter test...)
#define P_BOSON_BOSON_GAIN_MODE 30 ///< Sets the mode of the camera's temperature compensation operation (0 - high, 1 - low, 2 - auto, ...)
#define P_BOSON_BOSON_FFC_WARN_TIME 31 ///< Sets the amount of time in 10ths of a second before the occurrence of FFC that the warn time symbol ...
#define P_BOSON_BOSON_OVER_TEMP_TIME 32 ///< Sets the time is seconds that we want to wait before setting the camera in low power state after an overTemp event
#define P_BOSON_BOSON_FFC_QUICK_TIME 33 ///< Sets the number of seconds after startup that FFC trigger params are 'reduced' to produce FFC events more often
#define P_BOSON_BOSON_EXT_SYNC_MODE 34 ///< Set the external sync mode for the camera
#define P_BOSON_DVO_DISPLAY_MODE 35 ///< Sets the display mode to continuous (0) or one shot (1)
#define P_BOSON_SCNR 36 ///< Enable or disable Spatial Column Noise Reduction (scnr)
#define P_BOSON_SCNR_TH_COL_SUM 37 ///< Set the threshold that determines if a column should increment or decrement by 1
#define P_BOSON_SCNR_TH_PIXEL 38 ///< Set the (base) threshold that determines if a neighboring pixel is within range to affect the correction of the center
#define P_BOSON_SCNR_MAX_CORR 39 ///< Set the (base) maximum correction amount that will be applied
#define P_BOSON_SCNR_TH_PIXEL_SAFE 40 ///< Set the (base) threshold (for Safe Mode) that determines if a neighboring pixel is within range to correct the center
#define P_BOSON_SCNR_MAX_CORR_SAFE 41 ///< Set the (base) maximum correction amount (for Safe Mode) that will be applied
#define P_BOSON_TF 42 ///< Enable or disable Temporal Noise Reduction (tnr)
#define P_BOSON_TF_DELTA_NF 43 ///< Sets the Delta NF value. The delta_nf modifies the filter behavior by scaling the index into the table of weights
#define P_BOSON_TF_TH_DELTA_MOTION 44 ///< Sets the Delta Motion threshold to determine if there was motion in the scene enough to trigger the SPNR algorithm
#define P_BOSON_TF_MOTION_THRESHOLD 45 ///< Sets the motion detection threshold - the number of pixels in a frame moved to trigger SPNR execution
#define P_BOSON_SPNR 46 ///< Enable/disable Spatial Pattern Noise Reduction (SPNR) correction
#define P_BOSON_SPNR_FRAME_DELAY 47 ///< Sets the frame delay parameter. This determines how many frames it takes between SPNR iterations
#define P_BOSON_SYSCTRL_FREEZE 48 ///< Sets the state of the pipeline freeze parameter (enable/disable)
#define P_BOSON_TEST_RAMP_MOTION 49 ///< Enable or disable looping through the test ramp buffers
#define P_BOSON_TEST_RAMP_INDEX 50 ///< Display the selected ramp buffer on the next frame
#define P_BOSON_SRNR 51 ///< SRNR On/off
#define P_BOSON_SRNR_TH_ROW_SUM 52 ///< (?)
#define P_BOSON_SRNR_TH_PIXEL 53 ///< (?)
#define P_BOSON_SRNR_MAX_CORR 54 ///< (?)
/* Boson640 "i2c" (uart actually) registers will be defined here */
/**
#define P_BOSON640_POWER 0x00 ///< Power On/Off register
#define P_BOSON640_STATUS 0x02 ///< Status register
#define P_BOSON640_COMMAND_ID 0x04 ///< Command ID register
#define P_BOSON640_DATA_LENGTH 0x06 ///< Data length register
#define P_BOSON640_DATA00 0x08 ///< Data0
#define P_BOSON640_DATA01 0x0a ///< Data1
#define P_BOSON640_DATA02 0x0c ///< Data2
#define P_BOSON640_DATA03 0x0e ///< Data3
#define P_BOSON640_DATA04 0x10 ///< Data4
#define P_BOSON640_DATA05 0x12 ///< Data5
#define P_BOSON640_DATA06 0x14 ///< Data6
#define P_BOSON640_DATA07 0x16 ///< Data7
#define P_BOSON640_DATA08 0x18 ///< Data8
#define P_BOSON640_DATA09 0x1a ///< Data9
#define P_BOSON640_DATA10 0x1c ///< Data10
#define P_BOSON640_DATA11 0x1e ///< Data11
#define P_BOSON640_DATA12 0x20 ///< Data12
#define P_BOSON640_DATA13 0x22 ///< Data13
#define P_BOSON640_DATA14 0x24 ///< Data14
#define P_BOSON640_DATA15 0x26 ///< Data15
*/
// Data model for Lepton does not match 393 convention (1 page for "important" registers,
// so just 1 register of each of the 256-words is registered
/*
#define P_BOSON640_DATAF8 0x28 ///< 0xf800 to 0xf8ff
#define P_BOSON640_DATAF9 0x29 ///< 0xf900 to 0xf9ff
#define P_BOSON640_DATAFA 0x2a ///< 0xfa00 to 0xfaff
#define P_BOSON640_DATAFB 0x2b ///< 0xfb00 to 0xfbff
#define P_BOSON640_DATAFC 0x2c ///< 0xfc00 to 0xfcff
#define P_BOSON640_DATAFD 0x2d ///< 0xfd00 to 0xfdff
#define P_BOSON640_DATAFE 0x2e ///< 0xfe00 to 0xfeff
#define P_BOSON640_DATAFF 0x2f ///< 0xff00 to 0xffff
// actual values for registers (when reading)
#define P_REG_BOSON640_GP3VSYNC 0x0854
#define P_REG_BOSON640_GP3VSYNC_VAL 0x0005
#define P_REG_BOSON640_TELEN 0x0218
#define P_REG_BOSON640_TELLOC 0x021c
#define P_REG_BOSON640_FFC_RUN 0x0242 // "2" in 2 lower bits mean that it is just run, no parameters set
// Actual register address ranges (probably, only even are used too?)
#define P_REG_BOSON640_DATAF8 0xf800 ///< 0xf800 to 0xf8ff
#define P_REG_BOSON640_DATAF9 0xf900 ///< 0xf900 to 0xf9ff
#define P_REG_BOSON640_DATAFA 0xfa00 ///< 0xfa00 to 0xfaff
#define P_REG_BOSON640_DATAFB 0xfb00 ///< 0xfb00 to 0xfbff
#define P_REG_BOSON640_DATAFC 0xfc00 ///< 0xfc00 to 0xfcff
#define P_REG_BOSON640_DATAFD 0xfd00 ///< 0xfd00 to 0xfdff
#define P_REG_BOSON640_DATAFE 0xfe00 ///< 0xfe00 to 0xfeff
#define P_REG_BOSON640_DATAFF 0xff00 ///< 0xff00 to 0xffff
*/
#define BOSON_PACKET_MAX_DATA 756 ///< Maximal length of Boson packet data length
#define BOSON_ERR_NO_PACKET 1 ///< UART read packet not available
#define BOSON_ERR_FBP_FORMAT 2 ///< UART read packet ended prematurely
#define BOSON_ERR_NO_EOP 3 ///< UART read packet > 765 bytes
/**
* Just set parameter for the Boson640 related register, do not write to sensor
* @param port sensor port number
* @param reg relative register to fit 256 values page
* @param data value to set (16 bits)
*/
#define SET_BOSON640_PAR_DRY(port,reg,data) {\
pars_to_update[nupdate ].num= P_SENSOR_REGS+(reg);\
pars_to_update[nupdate++].val=(data);\
}
/**
* Set parameter for the Boson640 related register and send related commands to hardware i2c sequencer in immediate mode
* Only immediate mode allows waiting
* @param port sensor port number
* @param sa7 7-bit i2c slave address
* @param reg relative register to fit 256 values page
* @param data value to set (16 bits)
* @param wait_ms - maximal numer of milliseconds to wait Lepton ready
*/
#define SET_BOSON640_PAR_IMMED(port,sa7,reg,data,wait_ms) {\
int _BOSON640REG = pSensorPortConfig[(port)].par2addr[0][(reg)];\
pars_to_update[nupdate ].num= P_SENSOR_REGS+(reg);\
pars_to_update[nupdate++].val=(data);\
if (!(_BOSON640REG&0xffff0000)) {\
boson640_set_reg((port), (sa7), _BOSON640REG, (wait_ms), (data));\
}\
}
// .pare2addr[0] - 256 of32-bit register addresses, or 0xffffffff for missing ones
/**
* 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 relative register to fit 256 values page
* @param data value to set (16 bits)
*/
#define SET_BOSON640_PAR_NOWAIT(port, frame, reg, data) {\
int _BOSON640REG = pSensorPortConfig[(port)].par2addr[0][(reg)];\
pars_to_update[nupdate ].num= P_SENSOR_REGS+(reg);\
pars_to_update[nupdate++].val=(data);\
if (!(_BOSON640REG&0xffff0000)) {\
boson640_set_reg_nowait ((port), (frame), _BOSON640REG, (data));\
}\
}
/*
typedef union {
struct {
u32 busy: 1; // [ 0] BUSY bit (should be zero before issuing commands)
u32 boot_mode: 1; // [ 1] Boot Mode (should be 1 - booted from internal ROM)
u32 boot_status: 1; // [ 2] 1 - booted, 0 - in progress
u32 rsv5: 5; // [ 7: 3] Reserved, should read zero
u32 error: 8; // [15 8] Error code
};
struct {
u32 d32:16; // [15: 0] (0) cast to u32
};
} boson640_status_t;
typedef union {
struct {
u32 type: 2; // [ 1: 0] 0 - get, 1 - set, 2 - run, 3 - invalid
u32 id: 6; // [ 7: 2] command ID
u32 module: 4; // [11: 8] module: 1-AGC, 2-SYS, 3-VID, 8-OEM, 0xe - RAD
u32 : 2; // [13:12] Reserved
u32 protection: 1; // [ 14] OEM bit, set for modules: RAD and OEM
u32 : 1; // [ 15] Reserved
};
struct {
u32 d32:16; // [15: 0] (0) cast to u32
};
} boson640_command_t;
*/
/*
#define BOSON640_MODULE(x) (((x) >> 8) & 0x3f)
typedef enum BOSON640_MODULES {
BOSON640_AGC = 1,
BOSON640_SYS = 2,
BOSON640_VID = 3,
BOSON640_OEM = 8,
BOSON640_RAD = 14
} boson640_modules_t;
typedef enum BOSON640_TYPES {
BOSON640_GET = 0,
BOSON640_SET = 1,
BOSON640_RUN = 2
} boson640_types_t;
*/
// large segments - 0xf800-0xfbff, 0xfc00 -0xffff not yet supported
/**
LUT to map SENSOR_REGSxxx to internal sensor register addresses
* needed for any sensor
* For better manual mapping:
- even elements are SENSOR_REGSxxx,
- odd elements are sensor's register addresses.
* has to be at least 16-bit/entry for 16 bit addresses
* (for MT9X001 it's a 1-to-1 mapping)
*/
extern const unsigned short boson640_par2addr[];
extern const unsigned short boson640_pages[];
extern const unsigned short boson640_ahead_tab[];
int boson640_pgm_detectsensor (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
;
void boson640_set_device(struct device *dev);
/*
int boson640_wait_ready (int sensor_port, int sa7, int num_retries);
int boson640_get_reg (int sensor_port, int sa7, int cmd, int wait_ms);
int boson640_set_reg (int sensor_port, int sa7, int cmd, int wait_ms, int data);
void boson640_set_reg_nowait (int sensor_port, int frame, int cmd, int data);
// Maybe not needed?
int boson640_run_cmd (int sensor_port, int sa7, int cmd, int wait_ms);
void boson640_run_cmd_nowait (int sensor_port, int sa7, int cmd);
*/
#endif
......@@ -489,9 +489,9 @@ int detect_sensors_par2addr_init(int port,int sub_chn){
break;
case SENSOR_BOSON640: // temporary, set later to actual one
dev_warn(g_dev_ptr,"FIX temporary data in detect_sensors for Boson640\n");
par2addr = lepton_par2addr;
pages = lepton_pages;
atab = lepton_ahead_tab;
par2addr = boson640_par2addr;
pages = boson640_pages;
atab = boson640_ahead_tab;
break;
}
if (par2addr){
......
......@@ -4,6 +4,7 @@
#ifndef _JPEGHEAD
#define _JPEGHEAD
#include <linux/platform_device.h>
struct huffman_fpga_code_t {
unsigned short value; /// code value
......
......@@ -159,6 +159,10 @@ const unsigned long param_depend_tab[]=
P_SENSOR, ONCHANGE_DETECTSENSOR | ONCHANGE_RECALCSEQ | ONCHANGE_INITSENSOR | ONCHANGE_AFTERINIT | ONCHANGE_MULTISENS | \
ONCHANGE_WINDOW | ONCHANGE_EXPOSURE | ONCHANGE_HIST | ONCHANGE_AEXP | ONCHANGE_FOCUSMODE | ONCHANGE_LIMITFPS | ONCHANGE_HIST | \
ONCHANGE_MEMSENSOR | ONCHANGE_MEMCOMPRESSOR | ONCHANGE_COMPMODE | ONCHANGE_COMPSTOP | ONCHANGE_COMPRESTART ,
P_BOOTED, ONCHANGE_RECALCSEQ | ONCHANGE_INITSENSOR | ONCHANGE_AFTERINIT | ONCHANGE_MULTISENS | \
ONCHANGE_WINDOW | ONCHANGE_EXPOSURE | ONCHANGE_HIST | ONCHANGE_AEXP | ONCHANGE_FOCUSMODE | ONCHANGE_LIMITFPS | ONCHANGE_HIST | \
ONCHANGE_MEMSENSOR | ONCHANGE_MEMCOMPRESSOR | ONCHANGE_COMPMODE | ONCHANGE_COMPSTOP | ONCHANGE_COMPRESTART ,
P_BAYER , ONCHANGE_SENSORIN, // | ONCHANGE_COMPMODE , // ONCHANGE_COMPMODE added for NC393
P_CLK_FPGA, ONCHANGE_I2C | ONCHANGE_LIMITFPS | ONCHANGE_HIST | \
ONCHANGE_MEMSENSOR | ONCHANGE_MEMCOMPRESSOR | ONCHANGE_COMPMODE | ONCHANGE_COMPSTOP | ONCHANGE_COMPRESTART ,
......
......@@ -181,6 +181,7 @@
// TODO:remove unneeded
//#define DEBUG // should be before linux/module.h - enables dev_dbg at boot in this file (needs "debug" in bootarg)
#include <linux/types.h> // for div 64
#include <asm/div64.h> // for div 64
......@@ -209,6 +210,7 @@
#include "mt9x001.h"
#include "mt9f002.h"
#include "lepton.h"
#include "boson640.h"
#include "gamma_tables.h"
#include "quantization_tables.h"
//#include "latency.h"
......@@ -510,6 +512,8 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
if (check_senspgmin_state(sensor_port)==1){
dev_info(g_dev_ptr,"No sensors connected to port %d \n",sensor_port);
// added new line to distinguish no sensor from not yet detected for Boson, avoiding triggerin on change for P_SENSOR
sensor->sensorType=SENSOR_NONE; // to prevent from initializing again
return 0;
}
}
......@@ -554,6 +558,16 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
lepton_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16);
}
if ( (fpga_interface == FPGA_BOSON640) &&
(thispars->pars[P_SENSOR]==0) &&
((sens & SENSOR_MASK) == SENSOR_BOSON640)){
dev_dbg(g_dev_ptr,"trying Boson-640, port=%d\n",sensor_port);
dev_info(g_dev_ptr,"trying Boson-640, port=%d\n",sensor_port);
MDP(DBGB_PADD, sensor_port,"trying Boson-640, port=%d\n",sensor_port)
boson640_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // just remove mrst? Do not wait for ready (12s)
}
//setFramePar(sensor_port, thispars, P_CLK_FPGA, 200000000); // FIXME: NC393
setFramePar(sensor_port, thispars, P_CLK_FPGA, 240000000);
......@@ -573,9 +587,9 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
MDP(DBGB_PADD, sensor_port,"No image sensor found%s\n","")
}
// is it all OK for Boson?
setFramePar(sensor_port, thispars, P_SENSOR_WIDTH, sensor->imageWidth); // Maybe get rid of duplicates?
setFramePar(sensor_port, thispars, P_SENSOR_HEIGHT, sensor->imageHeight); // Maybe get rid of duplicates?
if (sensor->i2c_period==0) sensor->i2c_period=2500; // SCL period in ns, (standard i2c - 2500)
qperiod=thispars->pars[P_I2C_QPERIOD];
if (qperiod==0) qperiod=(sensor->i2c_period * (thispars->pars[P_CLK_FPGA]/1000))/4000000;
......@@ -630,7 +644,7 @@ int pgm_initsensor (int sensor_port, ///< sensor port number (
x393_sens_mode_t sens_mode = {.d32=0};
x393_camsync_mode_t camsync_mode = {.d32=0};
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_initsensor(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
status_ctrl.mode = 3; // mode auto
set_x393_cmprs_status(status_ctrl, sensor_port);
......@@ -765,7 +779,7 @@ int pgm_afterinit (int sensor_port, ///< sensor port number (
struct frameparspair_t pars_to_update[24]; // 20 needed, increase if more entries will be added
int nupdate=0;
int woi_width, woi_height;
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_afterinit(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
// If this is a multisensor camera, update composite sensor dimensions (will trigger other related changes)
......@@ -832,6 +846,7 @@ int pgm_sensorphase (int sensor_port, ///< sensor port number (
{
#ifndef NC353
int fpga_interface = x393_sensor_interface();
x393_sensio_ctl_t sensio_ctl = {.d32=0};
x393_sensio_tim0_t sensio_tim0 = {.d32=0};
x393_sensio_tim1_t sensio_tim1 = {.d32=0};
......@@ -840,21 +855,23 @@ int pgm_sensorphase (int sensor_port, ///< sensor port number (
// TODO: Temporary for NC393 - just applying SENSOR_IFACE_TIM0 - SENSOR_IFACE_TIM3 to FPGA, no calculations
// Actual functionality should be moved to separate modules as they are different for parallel and hispi (may be more in the future)
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (FRAMEPAR_MODIFIED(P_SENSOR_IFACE_TIM0)) {
sensio_tim0.d32 = thispars->pars[P_SENSOR_IFACE_TIM0];
// X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_tim0, sensio_tim0);
set_x393_sensio_tim0 (sensio_tim0, sensor_port); // write directly, sequencer may be not operational
sensio_ctl.set_dly = 1;
dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim0, 0x%x)\n",sensor_port, sensor_port, frame16, sensio_tim0.d32);
MDP(DBGB_PADD, sensor_port,"X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim0, 0x%x)\n", sensor_port, frame16, sensio_tim0.d32)
}
if (FRAMEPAR_MODIFIED(P_SENSOR_IFACE_TIM1)) {
sensio_tim1.d32 = thispars->pars[P_SENSOR_IFACE_TIM1];
// X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_tim1, sensio_tim1);
set_x393_sensio_tim1 (sensio_tim1, sensor_port); // write directly, sequencer may be not operational
sensio_ctl.set_dly = 1;
dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim1, 0x%x)\n",sensor_port, sensor_port, frame16, sensio_tim1 .d32);
MDP(DBGB_PADD, sensor_port,"X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim1, 0x%x)\n", sensor_port, frame16, sensio_tim1 .d32)
if (fpga_interface != FPGA_BOSON640) { // for Boson640 the 2 timing registers are used for the UART instead
if (FRAMEPAR_MODIFIED(P_SENSOR_IFACE_TIM0)) {
sensio_tim0.d32 = thispars->pars[P_SENSOR_IFACE_TIM0];
// X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_tim0, sensio_tim0);
set_x393_sensio_tim0 (sensio_tim0, sensor_port); // write directly, sequencer may be not operational
sensio_ctl.set_dly = 1;
dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim0, 0x%x)\n",sensor_port, sensor_port, frame16, sensio_tim0.d32);
MDP(DBGB_PADD, sensor_port,"X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim0, 0x%x)\n", sensor_port, frame16, sensio_tim0.d32)
}
if (FRAMEPAR_MODIFIED(P_SENSOR_IFACE_TIM1)) {
sensio_tim1.d32 = thispars->pars[P_SENSOR_IFACE_TIM1];
// X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_tim1, sensio_tim1);
set_x393_sensio_tim1 (sensio_tim1, sensor_port); // write directly, sequencer may be not operational
sensio_ctl.set_dly = 1;
dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim1, 0x%x)\n",sensor_port, sensor_port, frame16, sensio_tim1 .d32);
MDP(DBGB_PADD, sensor_port,"X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim1, 0x%x)\n", sensor_port, frame16, sensio_tim1 .d32)
}
}
if (FRAMEPAR_MODIFIED(P_SENSOR_IFACE_TIM2)) {
sensio_tim2.d32 = thispars->pars[P_SENSOR_IFACE_TIM2];
......@@ -1000,7 +1017,7 @@ int pgm_exposure (int sensor_port, ///< sensor port number (0..3
///< be applied to, negative - ASAP
///< @return always 0
{
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_exposure(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
return 0;
}
......@@ -1014,7 +1031,7 @@ int pgm_i2c (int sensor_port, ///< sensor port number (0..3
///< be applied to, negative - ASAP
///< @return always 0
{
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_i2c(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d (do nothing here?)\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
#ifdef NC353
......@@ -1039,7 +1056,7 @@ int pgm_window (int sensor_port, ///< sensor port number (0..3
///< @return always 0
{
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_window(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
return pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
......@@ -1054,7 +1071,7 @@ int pgm_window_safe (int sensor_port, ///< sensor port number (0..
///< @return always 0
{
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_window_safe(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
return pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
......@@ -1075,8 +1092,10 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
int nupdate=0;
int clearHeight;
int tile_vert = X393_TILEVERT;
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n", sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} thispars->pars[P_WOI_HEIGHT]=%lx thispars->pars[P_WOI_WIDTH]=%lx\n", sensor_port,thispars->pars[P_WOI_HEIGHT], thispars->pars[P_WOI_WIDTH]);
dev_dbg(g_dev_ptr,"pgm_window_common(): {%d} frame16=%d\n", sensor_port,frame16);
dev_dbg(g_dev_ptr,"pgm_window_common(): {%d} thispars->pars[P_WOI_HEIGHT]=%lx thispars->pars[P_WOI_WIDTH]=%lx\n", sensor_port,thispars->pars[P_WOI_HEIGHT], thispars->pars[P_WOI_WIDTH]);
dev_dbg(g_dev_ptr,"pgm_window_common(): {%d} thispars->pars[P_SENSOR_PIXV]=%lx thispars->pars[P_SENSOR_PIXH]=%lx\n", sensor_port,thispars->pars[P_SENSOR_PIXV], thispars->pars[P_SENSOR_PIXH]);
dev_dbg(g_dev_ptr,"pgm_window_common(): {%d} thispars->pars[P_COLOR]=%lx thispars->pars[P_BITS]=%lx\n", sensor_port,thispars->pars[P_COLOR], thispars->pars[P_BITS]);
// if (GLOBALPARS(G_SENS_AVAIL) ) multisensor_pgm_window_common0 (sensor, thispars, prevpars, frame16);
sensor_width= thispars->pars[P_SENSOR_WIDTH];
......@@ -1240,6 +1259,9 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
dev_dbg(g_dev_ptr,"{%d} SETFRAMEPARS_SET(P_WOI_TOP, 0x%x)\n", sensor_port, top);
MDP(DBGB_PADD, sensor_port,"SETFRAMEPARS_SET(P_WOI_TOP, 0x%x)\n", top)
}
dev_dbg(g_dev_ptr,"pgm_window_common(exit): {%d} thispars->pars[P_WOI_HEIGHT]=%lx thispars->pars[P_WOI_WIDTH]=%lx\n", sensor_port,thispars->pars[P_WOI_HEIGHT], thispars->pars[P_WOI_WIDTH]);
dev_dbg(g_dev_ptr,"pgm_window_common(exit): {%d} thispars->pars[P_SENSOR_PIXV]=%lx thispars->pars[P_SENSOR_PIXH]=%lx\n", sensor_port,thispars->pars[P_SENSOR_PIXV], thispars->pars[P_SENSOR_PIXH]);
if (nupdate) setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions
return 0;
}
......@@ -1298,7 +1320,7 @@ int pgm_limitfps (int sensor_port, ///< sensor port number (0..3
uint64_t ull_period;
#endif
if (!clk_fpga) clk_fpga = 240000000; // 240MHz
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_limitfps(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
cycles=thispars->pars[P_TILES]; // number of tiles nc393: [P_TILES] == 0!
......@@ -1439,7 +1461,7 @@ int pgm_gains (int sensor_port, ///< sensor port number (
///< be applied to, negative - ASAP
///< @return always 0
{
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_gains(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
return 0;
}
......@@ -1521,9 +1543,9 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
int margins;
x393_mcntrl_frame_start_dly_t start_dly ={.d32=0};
int sens = get_detected_sensor_code(sensor_port, -1);
// int sens = get_detected_sensor_code(sensor_port, -1);
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
/// dev_dbg(g_dev_ptr,"{%d} pgm_sensorin(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
margins = 0;
......@@ -1537,8 +1559,8 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
sens_mode.bit16 = (thispars->pars[P_BITS] > 8);
sens_mode.bit16_set = 1;
X393_SEQ_SEND1 (sensor_port, frame16, x393_sens_mode, sens_mode);
dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sens_mode, 0x%x)\n",
sensor_port, sensor_port, frame16, sens_mode.d32);
/// dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sens_mode, 0x%x)\n",
/// sensor_port, sensor_port, frame16, sens_mode.d32);
MDP(DBGB_PADD, sensor_port,"X393_SEQ_SEND1(0x%x, 0x%x, x393_sens_mode, 0x%x)\n",
sensor_port, frame16, sens_mode.d32)
......@@ -1565,8 +1587,8 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
}
*/
dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_width, 0x%x)\n",
sensor_port, sensor_port, frame16, sensio_width.d32);
/// dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_width, 0x%x)\n",
/// sensor_port, sensor_port, frame16, sensio_width.d32);
MDP(DBGB_PADD, sensor_port,"X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_width, 0x%x)\n",
sensor_port, frame16, sensio_width.d32)
......@@ -1583,8 +1605,8 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
n_scan_lines= thispars->pars[P_ACTUAL_HEIGHT]+(2 * margins)+thispars->pars[P_OVERLAP];
}
X393_SEQ_SEND1 (sensor_port, frame16, x393_sens_sync_mult, sync_mult);
dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sens_sync_mult, 0x%x)\n",
sensor_port, sensor_port, frame16, sync_mult.d32);
/// dev_dbg(g_dev_ptr,"{%d} X393_SEQ_SEND1(0x%x, 0x%x, x393_sens_sync_mult, 0x%x)\n",
/// sensor_port, sensor_port, frame16, sync_mult.d32);
MDP(DBGB_PADD, sensor_port,"X393_SEQ_SEND1(0x%x, 0x%x, x393_sens_sync_mult, 0x%x)\n",
sensor_port, frame16, sync_mult.d32)
......@@ -1599,13 +1621,13 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
flips=(thispars->pars[P_FLIPH] & 1) | ((thispars->pars[P_FLIPV] & 1)<<1);
bayer_modified=FRAMEPAR_MODIFIED(P_BAYER) || FRAMEPAR_MODIFIED(P_FLIPH) || FRAMEPAR_MODIFIED(P_FLIPV) || FRAMEPAR_MODIFIED(P_MULTI_MODE);
dev_dbg(g_dev_ptr,"{%d} flips=%x\n",sensor_port, flips);
/// dev_dbg(g_dev_ptr,"{%d} flips=%x\n",sensor_port, flips);
MDP(DBGB_PADD, sensor_port,"flips=%x\n",flips)
if (thispars->pars[P_MULTI_MODE]) { // Modify flips in composite mode - should match flips of the top (direct) channel
int this_bit=(1<<thispars->pars[P_MULTI_TOPSENSOR]);
if (thispars->pars[P_MULTI_FLIPH] & this_bit) flips^=1;
if (thispars->pars[P_MULTI_FLIPV] & this_bit) flips^=2;
dev_dbg(g_dev_ptr,"{%d} composite mode - adjusted flips=%x\n",sensor_port, flips);
/// dev_dbg(g_dev_ptr,"{%d} composite mode - adjusted flips=%x\n",sensor_port, flips);
MDP(DBGB_PADD, sensor_port,"composite mode - adjusted flips=%x\n",flips)
bayer_modified= bayer_modified || FRAMEPAR_MODIFIED(P_MULTI_FLIPH) || FRAMEPAR_MODIFIED(P_MULTI_FLIPV) || FRAMEPAR_MODIFIED(P_MULTI_TOPSENSOR);
}
......@@ -1763,7 +1785,7 @@ int pgm_sensorrun (int sensor_port, ///< sensor port number (0..3
{
int reset_frame;
#ifndef NC353
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_sensorrun(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -EINVAL; // wrong frame
reset_frame = ((prevpars->pars[P_SENSOR_RUN]==0) && (thispars->pars[P_SENSOR_RUN]!=0))? 1:0;
......@@ -1815,7 +1837,7 @@ int pgm_sensorstop (int sensor_port, ///< sensor port number (0..3
{
#ifndef NC353
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_sensorstop(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -EINVAL; // wrong frame
// Do we need to filter for stop only ( if ((thispars->pars[P_SENSOR_RUN] & 3)==0){... ) ?
......@@ -1950,7 +1972,7 @@ int pgm_hist (int sensor_port, ///< sensor port number (0..3
{P_HISTWND_HEIGHT, 0}
};
*/
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_hist(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
for (sub_chn =0; sub_chn < MAX_SENSORS; sub_chn++) if (GLOBALPARS(sensor_port, G_SUBCHANNELS) & (1 << sub_chn)){
......@@ -2043,7 +2065,7 @@ int pgm_aexp (int sensor_port, ///< sensor port number (0..3
///< @return OK - 0, <0 - error
{
//TODO:
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_aexp(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
return 0;
}
......@@ -2063,7 +2085,7 @@ int pgm_quality (int sensor_port, ///< sensor port number (0..3
int c_coring_index;
int qtab = 0;
int composite_quality=(thispars->pars[P_QUALITY] & 0xff7f) | ((thispars->pars[P_PORTRAIT] & 1)<<7);
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_quality(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
......@@ -2110,7 +2132,7 @@ int pgm_memsensor (int sensor_port, ///< sensor port number (
{
#ifndef NC353
int width_marg, height_marg, width_bursts;
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_memsensor(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
width_marg = thispars->pars[P_ACTUAL_WIDTH];
......@@ -2390,7 +2412,7 @@ int pgm_compmode (int sensor_port, ///< sensor port number (0..3
x393_cmprs_mode_t cmprs_mode = {.d32=0};
x393_cmprs_colorsat_t cmprs_colorsat = {.d32=0};
x393_cmprs_coring_mode_t cmprs_coring_mode = {.d32=0};
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_compmode(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (!jpeg_htable_is_programmed(sensor_port)) jpeg_htable_fpga_pgm (sensor_port);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
......@@ -2605,7 +2627,7 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
{P_FOCUS_TOP, 0},
{P_FOCUS_HEIGHT, 0}
};
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_focusmode(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= 0) return -1; // now can only programm in immediate mode by writing the table
focus_setup_data.totalwidth=(thispars->pars[P_ACTUAL_WIDTH]& 0xfff0) -0x10; // anyway should be 16x
......@@ -2708,7 +2730,7 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
x393_camsync_io_t camsync_dst = {.d32=0};
x393_gpio_set_pins_t gpio_set_pins = {.d32=0};
x393_camsync_mode_t camsync_mode = {.d32=0};
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_trigseq(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// See if master channel is set to this channel directly
......@@ -2856,7 +2878,7 @@ int pgm_irq (int sensor_port, ///< sensor port number (0..3)
///< @return OK - 0, <0 - error
{
x393_i2c_ctltbl_t i2c_ctl = {.d32=0};
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_irq(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d,\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
#ifdef NC353
......@@ -2908,7 +2930,7 @@ int pgm_recalcseq (int sensor_port, ///< sensor port number (0..3
{G_CALLNEXT+4,0},
{G_CALLNASAP,0}};
dev_dbg(g_dev_ptr,"{%d} frame16=%d, safe=%d, async=%d, nooverlap=%d\n",sensor_port,frame16, safe, async, nooverlap);
dev_dbg(g_dev_ptr,"{%d} pgm_recalcseq(): frame16=%d, safe=%d, async=%d, nooverlap=%d\n",sensor_port,frame16, safe, async, nooverlap);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
// not null is guaranteed
......@@ -2958,7 +2980,7 @@ int pgm_comprestart(int sensor_port, ///< sensor port number (0..3
int reset_frame;
int raw_mode;
x393_cmprs_mode_t cmprs_mode = {.d32=0};
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_comprestart: frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// does it need to be be started (nothing do be done to stop)
......@@ -3072,7 +3094,7 @@ int pgm_compstop (int sensor_port, ///< sensor port number (0..3
int raw_mode;
int disable_need = 1; // TODO: Use some G_* parameter
x393_cmprs_mode_t cmprs_mode = {.d32=0};
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_compstop(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -EINVAL; // wrong frame
switch(thispars->pars[P_COLOR]){
......@@ -3145,7 +3167,7 @@ int pgm_compctl (int sensor_port, ///< sensor port number (0..3
int reset_frame = 0;
int raw_mode;
// int just_started = 0;
dev_dbg(g_dev_ptr,"{%d} frame16=%d, prevpars->pars[P_COMPRESSOR_RUN]=%d, thispars->pars[P_COMPRESSOR_RUN]=%d \n",
dev_dbg(g_dev_ptr,"{%d} pgm_compctl(): frame16=%d, prevpars->pars[P_COMPRESSOR_RUN]=%d, thispars->pars[P_COMPRESSOR_RUN]=%d \n",
sensor_port,frame16, (int) prevpars->pars[P_COMPRESSOR_RUN], (int) thispars->pars[P_COMPRESSOR_RUN]);
MDP(DBGB_PSFN, sensor_port,"frame16=%d, prevpars->pars[P_COMPRESSOR_RUN]=%d, thispars->pars[P_COMPRESSOR_RUN]=%d \n",
frame16, (int) prevpars->pars[P_COMPRESSOR_RUN], (int) thispars->pars[P_COMPRESSOR_RUN])
......@@ -3269,7 +3291,7 @@ int pgm_gammaload (int sensor_port, ///< sensor port number (0..3
int need_pgm=0;
int fpga_result=0;
dev_dbg(g_dev_ptr,"{%d} frame16=%d, (getThisFrameNumber() & PARS_FRAMES_MASK)= %ld, thispars->pars[P_GTAB_R]=0x%lx, thispars->pars[P_FRAME]=0x%lx\n",
dev_dbg(g_dev_ptr,"{%d} pgm_gammaload(): frame16=%d, (getThisFrameNumber() & PARS_FRAMES_MASK)= %ld, thispars->pars[P_GTAB_R]=0x%lx, thispars->pars[P_FRAME]=0x%lx\n",
sensor_port, frame16, getThisFrameNumber(sensor_port) & PARS_FRAMES_MASK, thispars->pars[P_GTAB_R], thispars->pars[P_FRAME]);
MDP(DBGB_PSFN, sensor_port,"frame16=%d, (getThisFrameNumber() & PARS_FRAMES_MASK)= %ld, thispars->pars[P_GTAB_R]=0x%lx, thispars->pars[P_FRAME]=0x%lx\n",
frame16, getThisFrameNumber(sensor_port) & PARS_FRAMES_MASK, thispars->pars[P_GTAB_R], thispars->pars[P_FRAME])
......@@ -3337,7 +3359,7 @@ int pgm_sensorregs (int sensor_port, ///< sensor port number (0..3
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_sensorregs(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
return 0;
}
......@@ -3380,7 +3402,7 @@ int pgm_prescal (int sensor_port, ///< sensor port number (
// In 393 there can be multiple subchannels, with proportional offsets. Initially offset == 0, so the same parameters will
// be applied to all active subchannels.
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} pgm_prescal(): frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
for (sub_chn = 0; sub_chn < MAX_SENSORS; sub_chn++) if (GLOBALPARS(sensor_port, G_SUBCHANNELS) & (1 << sub_chn)){
......
......@@ -62,7 +62,7 @@ unsigned long sensor_to_camsync(unsigned long pixel_time, unsigned long sensor_c
* @param p parameter index (all high bits/attributes will be removed, only 12 LSBs preserved)
* @param v parameter value(32 bits) */
#define SETFRAMEPARS_UPDATE_SET(p,v) { pars_to_update[nupdate ].num= (p) ; pars_to_update[nupdate++].val=thispars->pars[(p) & 0xffff]?thispars->pars[(p) & 0xffff]:(v);}
/** Adds new parameter/value pair to the modification queue only if it is different from tghe current
/** Adds new parameter/value pair to the modification queue only if it is different from the current
* @param p parameter index (all high bits/attributes will be removed, only 12 LSBs preserved)
* @param v parameter value(32 bits) */
#define SETFRAMEPARS_COND(p,v) { if (unlikely((v)!=thispars->pars[(p) & 0xffff])) { pars_to_update[nupdate ].num= (p) ; pars_to_update[nupdate++].val=(v);} }
......@@ -99,6 +99,7 @@ extern struct sensor_port_config_t *pSensorPortConfig;
* @param reg sensor register address (8-bit)
* @param data value to set (16 bits)
*/
// is _ADDR&0xffff0000 for Lepton?
#define SET_SENSOR_PAR_LUT(port,frame,reg,data) {\
int _I = pSensorPortConfig[(port)].broadcast_addr;\
int _ADDR = pSensorPortConfig[(port)].par2addr[_I][(reg)];\
......
/// @file quantization_tables.h
#ifndef _QUANTIZATION_TABLES_H
#define _QUANTIZATION_TABLES_H
#include <linux/platform_device.h>
/** @brief Quantization tables cache usage policy */
enum {
// @brief Use common cache for all compressors
......
......@@ -6,6 +6,7 @@
#define _SENSOR_COMMON_H
#include "detect_sensors.h"
#include <linux/platform_device.h>
//extern struct sensor_t sensor; // current sensor (will be copied to by sensor driver), made external for the cc353.c to read/write i2c
extern struct sensorproc_t * asensorproc;
......@@ -98,6 +99,7 @@ long long get_frame_pos(unsigned int chn, unsigned int pos);
#define name_mt9p006 "mt9p006" // Get name from DT (together with port mask)
#define name_mt9f002 "mt9f002" // Get name from DT (together with port mask)
#define name_lepton35 "lepton35" // Get name from DT (together with port mask)
#define name_boson640 "boson640" // Get name from DT (together with port mask)
#define I2C359_INC 2 ///< slave address increment between sensors in 10359A board (broadcast, 1,2,3) (7 bits SA)
......@@ -115,15 +117,15 @@ long long get_frame_pos(unsigned int chn, unsigned int pos);
write_xi2c_reg16_abs_asap((port),(sa7),(frame),(reg),(data));\
}
/** Perform I2C write (8 bits address, 16 bits data in "legacy" mode,
* pages matching slave address should be registered.
/** Perform I2C write (8/16 bits address, 16 bits data in LUT mode,
* pages matching MSB(reg) 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 reg sensor register address (16-bit, high byte uses tables)
* @param data value to set (16 bits) */
//int _ADDR = pSensorPortConfig[(port)].par2addr[si][(reg)];
......@@ -139,7 +141,7 @@ long long get_frame_pos(unsigned int chn, unsigned int pos);
*
* Slave address is now 7-bit,old was 8-bit, change (10359 already done)
* @param port - sensor port
* @param sa7 I2C slave address, 7 bit
* @param sa7 I2C slave address, 7 bit: NOT used
* @param reg sensor register address (8-bit)
* @param data value to set (16 bits) */
#define X3X3_I2C_SEND2_ASAP(port,sa7,reg,data) {\
......@@ -149,13 +151,13 @@ long long get_frame_pos(unsigned int chn, unsigned int pos);
}
/** Perform I2C write in immediate mode (8 bits address, 16 bits data in "legacy" mode,
* pages matching slave address should be registered.
/** Perform I2C write in immediate mode (16 bits address, 16 bits data in LUT mode,
* pages matching MSB of the 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 si - slave device index (for mux board, otherwise 0)
* @param reg sensor register address (16-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];\
......
......@@ -392,7 +392,13 @@ void set_xi2c_wrc( x393_i2c_device_t * dc, ///< device class
tb_data.nbwr = dc -> address_bytes + dc -> data_bytes;
tb_data.dly = get_bit_delay(dc -> scl_khz);
tb_data.tbl_mode = 2;
dev_dbg(sdev, "device name %s : port= %d, page = 0x%x, rah = 0x%x\n",dc->name, chn, page,rah);
tb_data.extif_mode = 0;
if (tb_data.sa & 0x80){ // using external interface (currently Boson640 UART)
tb_data.extif_mode = tb_data.sa & 3;
tb_data.sa = (tb_data.rah >> 6) & 3; // number of bytes in uart command (later use (rah >> 8) after changing sensor_port_config_t.pages_ptr to 32 bits)
tb_data.rah &= 0x3f; // later &= 0xff
}
dev_dbg(sdev, "device name %s : port= %d, page = 0x%x, rah = 0x%x, sa = 0x%x, extif_mode=0x%x\n",dc->name, chn, page, tb_data.rah, tb_data.sa, tb_data.extif_mode);
/* Table address and data should not interleave with others */
#ifdef LOCK_BH_SENSORI2C
spin_lock_bh(sensori2c_locks[chn]);
......@@ -408,7 +414,7 @@ void set_xi2c_wrc( x393_i2c_device_t * dc, ///< device class
#endif
// i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
i2c_pages_shadow[chn][page] =tb_data.d32;
dev_dbg(sdev, "DONE: device name %s : port= %d, page = 0x%x, rah = 0x%x\n",dc->name, chn, page,rah);
dev_dbg(sdev, "DONE: device name %s : port= %d, page = 0x%x, rah = 0x%x, sa = 0x%x, extif_mode=0x%x\n",dc->name, chn, page, tb_data.rah, tb_data.sa, tb_data.extif_mode);
}
EXPORT_SYMBOL_GPL(set_xi2c_wrc);
/** Set i2c table entry for read operation using known devices
......@@ -716,6 +722,10 @@ void read_xi2c (x393_i2c_device_t * dc, ///< device class
int page, ///< Table index (8 bits)
int addr) ///< 8/16 bit register address
{
if ((dc -> slave7) & 0x80){
dev_warn(sdev, "Read not implemented for extif");
return;
}
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);
......@@ -732,6 +742,10 @@ void read_xi2c_sa7 (int chn, ///< sensor port
int sa7, ///< 7-bit i2c slave address
int addr) ///< 8/16 bit register address
{
if (sa7 & 0x80){
dev_warn(sdev, "Read not implemented for extif 2");
return;
}
u32 dw = ((page & 0xff) << 24) | (sa7 << 17) | (addr & 0xffff);
dev_dbg(sdev, "read_xi2c_sa7(%d,0x%x,0x%x,0x%x): 0x%08x\n",chn,page,sa7,addr,(int) dw);
x393_sensi2c_rel (dw, chn, 0);
......@@ -865,7 +879,8 @@ int x393_xi2c_read_reg( const char * cname, ///< device class name
/* Initiate i2c read */
read_xi2c_sa7 (chn,
page & 0xff, // page (8 bits)
(dc->slave7 + sa7_offs) & 0x7f, // 7-bit i2c slave address
// (dc->slave7 + sa7_offs) & 0x7f, // 7-bit i2c slave address
(dc->slave7 + sa7_offs) & 0xff, // 7-bit i2c slave address -> 8 bit for extif
reg_addr & 0xffff); // 8/16 bit address
/* Now read required number of bytes with timeout */
......@@ -957,7 +972,8 @@ int legacy_read_i2c_reg( int chn, ///< sensor port number
/* Initiate i2c read */
read_xi2c_sa7 (chn,
page & 0xff, // page (8 bits)
sa7 & 0x7f, // 7-bit i2c slave address
// sa7 & 0x7f, // 7-bit i2c slave address
sa7 & 0xff, // 7-bit i2c slave address -> 8 bits for extif
reg_addr & 0xffff); // 8/16 bit address
/* Now read required number of bytes with timeout */
......@@ -1106,7 +1122,7 @@ static ssize_t i2c_class_store(struct device *dev, ///< Linux kerne
char * dname;
ni = sscanf(buf,"%31s %i %i %i %i", name, &sa7, &num_addr, &num_data, &khz);
if (ni < 5) {
dev_err(dev, "Requires 5 parameters: name, slave addr (7 bit), address width (bytes), data width (bytes), max SCL frequency (kHz)\n");
dev_err(dev, "Requires 5 parameters: name, slave addr (7/8 bit), address width (bytes), data width (bytes), max SCL frequency (kHz)\n");
return -EINVAL;
}
dl = i2c_dev_get(name);
......@@ -1285,8 +1301,13 @@ static ssize_t get_i2c_tbl_human(struct device *dev, ///< Linux ker
return sprintf(buf,"Read entry: chn=%d page=%d(0x%x) two_byte_addr=%d number bytes to read=%d bit_duration=%d\n",
chn, page,page, tb_data.nabrd,tb_data.nbrd, tb_data.dly);
} else {
return sprintf(buf,"Write entry: chn=%d page=%d(0x%x) sa=0x%02x rah=0x%02x nbw=%d bit_duration=%d\n",
chn, page,page,tb_data.sa,tb_data.rah,tb_data.nbwr, tb_data.dly);
if (tb_data.extif_mode) {
return sprintf(buf,"Write entry: chn=%d page=%d(0x%x) extif=0x%x extif_byte_mode=%d rah=0x%02x nbw=%d bit_duration=%d\n",
chn, page,page,tb_data.extif_mode, tb_data.sa, (tb_data.rah & 0x3f),tb_data.nbwr, tb_data.dly);
} else {
return sprintf(buf,"Write entry: chn=%d page=%d(0x%x) sa=0x%02x rah=0x%02x nbw=%d bit_duration=%d\n",
chn, page,page, tb_data.sa,tb_data.rah,tb_data.nbwr, tb_data.dly);
}
}
}
......@@ -1320,7 +1341,8 @@ static ssize_t set_i2c_tbl_wr_human(struct device *dev, ///< Linux
}
set_xi2c_wr(chn,
page & 0xff, // index in lookup table
sa7 & 0x7f, // slave address (7 bit)
// sa7 & 0x7f, // slave address (7 bit)
sa7 & 0xff, // slave address (7 bit -> 8 bits for extif)
rah & 0xff, // High byte of the i2c register address
nbwr & 0xf, // Number of bytes to write (1..10)
dly & 0xff); // Bit delay - number of mclk periods in 1/4 of the SCL period
......
......@@ -814,7 +814,7 @@ int membridge_start(int sensor_port, unsigned long target_frame){
width_bursts = (width_marg >> 4) + ((width_marg & 0xf) ? 1 : 0);
pr_debug("VIDEOMEM: frame_num=%d width_marg=%d height_marg=%d width_burts=%d", frame_num, width_marg, height_marg, width_bursts);
pr_debug("VIDEOMEM: frame_num=%ld width_marg=%d height_marg=%d width_burts=%d", frame_num, width_marg, height_marg, width_bursts);
setup_membridge_memory(sensor_port, ///< sensor port number (0..3)
0, ///< 0 - from fpga mem to system mem, 1 - otherwise
......@@ -1165,7 +1165,7 @@ static ssize_t show_frames_in_buffer(struct device *dev, struct device_attribute
static ssize_t get_membridge_status(struct device *dev, struct device_attribute *attr, char *buf)
{
x393_status_membridge_t status = x393_membridge_status();
return sprintf(buf,"0x%08x\n", status);
return sprintf(buf,"0x%08x\n", status.d32);
}
static ssize_t get_video_frame_num(struct device *dev, struct device_attribute *attr, char *buf)
......@@ -1194,7 +1194,7 @@ static ssize_t get_raw_frame_info(struct device *dev, struct device_attribute *a
buf += sprintf(buf,"width = %d\n" ,raw_info.width[sensor_port]);
buf += sprintf(buf,"height = %d\n" ,raw_info.height[sensor_port]);
buf += sprintf(buf,"bits per pixel = %d\n" ,raw_info.bpp[sensor_port]);
buf += sprintf(buf,"buffer offset = 0x%08x\n" ,raw_info.offset[sensor_port]);
buf += sprintf(buf,"buffer offset = 0x%08llx\n" ,raw_info.offset[sensor_port]);
return buf-buf0;
}
......@@ -1212,13 +1212,13 @@ static ssize_t get_mctrl_status_chn(struct device *dev, struct device_attribute
case 4: status = x393_mcntrl_chn4_status(); break;
}
return sprintf(buf,"0x%08x\n", status);
return sprintf(buf,"0x%08x\n", status.d32);
}
static ssize_t get_cmprs_status(struct device *dev, struct device_attribute *attr, char *buf)
{
x393_cmprs_status_t status = x393_cmprs_status(get_channel_from_name(attr));
return sprintf(buf,"0x%08x\n", status);
return sprintf(buf,"0x%08x\n", status.d32);
}
static ssize_t store_frame_start(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
......@@ -1250,8 +1250,7 @@ static ssize_t set_membridge_status_reg(struct device *dev, struct device_attrib
d.d32 = in;
set_x393_membridge_status_cntrl(d);
d = get_x393_membridge_status_cntrl();
pr_info("Set membridge status register to 0x%08x, status: 0x%08x\n",in,d);
pr_info("Set membridge status register to 0x%08x, status: 0x%08x\n",in,d.d32);
return count;
}
......
......@@ -282,7 +282,7 @@
#define SENSORWIDTH_IBIS51300 1280 ///< FillFactory IBIS51300 width
#define SENSORHEIGHT_IBIS51300 1024 ///< FillFactory IBIS51300 height
#define P_TRIG_MASTER 3 ///< Master channel for setting trigger para,eters
#define P_TRIG_MASTER 3 ///< Master channel for setting trigger parameters
#define P_SENSOR_RUN 4 ///< Sensor acquisition mode 0 - stop, 1 - single, 2 - run
#define SENSOR_RUN_STOP 0 ///< Sensor acquisition mode: STOP
#define SENSOR_RUN_SINGLE 1 ///< Sensor acquisition mode: SINGLE FRAME
......@@ -296,7 +296,8 @@
#define COMPRESSOR_RUN_RESET 3 ///< Compressor mode: RESET
#define P_BAYER 6 ///< filter number at (0,0) 0-R, 1-G(R), 2-G(B), 3 - B. Write enabled at first, move to WindowSize later
#define P_TRIGGERED 7 ///< when trigger occured - 4 LSBs - pixel in DMA word, higher bits - number of DMA word OBSOLETE
//#define P_TRIGGERED 7 ///< when trigger occurred - 4 LSBs - pixel in DMA word, higher bits - number of DMA word OBSOLETE
#define P_BOOTED 7 ///< sensor is fully booted (for Boson640) and ready to accept commands
#define P_PERIOD 8 ///< Frame period in pixel clocks (read only)
#define P_FP1000SLIM 9 ///< FPS limit, frames per 1000 sec
#define P_FPSFLAGS 10 //v FPS limit mode - bit 0 - limit fps (not higher than), bit 1 - maintain fps (not lower than)
......@@ -1115,6 +1116,7 @@ struct p_names_t {
P_NAME_ENTRY(ACTUAL_WIDTH), \
P_NAME_ENTRY(ACTUAL_HEIGHT), \
P_NAME_ENTRY(BAYER), \
P_NAME_ENTRY(BOOTED), \
P_NAME_ENTRY(PERIOD), \
P_NAME_ENTRY(FP1000SLIM), \
P_NAME_ENTRY(FRAME), \
......@@ -1736,9 +1738,10 @@ struct __attribute__((__packed__)) sensor_t {
#define SENSOR_NEED_RESET_PHASE 2
typedef enum FPGA_INTERFACES {
FPGA_PAR12 = 0,
FPGA_HISPI = 1,
FPGA_VOSPI = 2
FPGA_PAR12 = 0,
FPGA_HISPI = 1,
FPGA_VOSPI = 2,
FPGA_BOSON640 = 3
} fpga_interfaces_t;
......
......@@ -126,6 +126,7 @@
#define DEV393_MT9X001 ("", "elphel393-mt9x001", -1, -1, "0666", "c") ///< Used only in sysfs, no character device (yet?)
#define DEV393_MT9F002 ("", "elphel393-mt9f002", -1, -1, "0666", "c") ///< Used only in sysfs, no character device (yet?)
#define DEV393_LEPTON ("", "elphel393-lepton", -1, -1, "0666", "c") ///< Used only in sysfs, no character device (yet?)
#define DEV393_BOSON640 ("", "elphel393-boson640", -1, -1, "0666", "c") ///< Used only in sysfs, no character device (yet?)
#define DEV393_KLOGGER ("klogger_393", "klogger_393",144, 1, "0666", "c") ///< kernel event logger to memory (no i/o)
#define _DEV393_DEVNAME(n, ...) n
......
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