Commit 5414b1d7 authored by Andrey Filippov's avatar Andrey Filippov

more debugging

parent 406266d1
......@@ -37,6 +37,7 @@
//#include <linux/autoconf.h>
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
//#include <asm/system.h>
......@@ -122,7 +123,7 @@
/* 393: sFrameParsAll is an array of 4per-port structures */
static struct framepars_all_t sFrameParsAll[SENSOR_PORTS] __attribute__ ((aligned(PAGE_SIZE))); ///< Sensor Parameters, currently 16 pages all and 2048 pages some, static struct
unsigned long frameParsInitialized[SENSOR_PORTS]; // set to 0 at startup, 1 after initialization that is triggered by setParsAtomic()
unsigned int frameParsInitialized[SENSOR_PORTS]; // set to 0 at startup, 1 after initialization that is triggered by setParsAtomic()
#define thisFrameNumber(p) GLOBALPARS(p,G_THIS_FRAME) // Current frame number (may lag from the hardware)
#define thisCompressorFrameNumber(p) GLOBALPARS(p,G_COMPRESSOR_FRAME) // Current compressed frame number (lags from thisFrameNumber)
......@@ -146,6 +147,16 @@ unsigned long *amultiSensIndex[SENSOR_PORTS]; // index for per-se
unsigned long *amultiSensRvrsIndex[SENSOR_PORTS]; // reverse index (to parent) for the multiSensIndex
wait_queue_head_t aframepars_wait_queue[SENSOR_PORTS];// used to wait for the frame to be acquired
static DEFINE_SPINLOCK(framepars_lock_0); ///<
static DEFINE_SPINLOCK(framepars_lock_1); ///<
static DEFINE_SPINLOCK(framepars_lock_2); ///<
static DEFINE_SPINLOCK(framepars_lock_3); ///<
/** Define array of pointers to locks - hardware allows concurrent writes to different ports tables */
spinlock_t * framepars_locks[4] = {&framepars_lock_0, &framepars_lock_1, &framepars_lock_2, &framepars_lock_3};
/* Remove after compilation OK */
//struct sensorproc_t * sensorproc = NULL;
//void compressor_interrupts (int on) {}
......@@ -184,7 +195,7 @@ struct framepars_pd {
// something else to be added here?
};
static u32 debug_flags = 0;
/**
* @brief assign non-static pointers to static data to be used as extern
......@@ -232,7 +243,6 @@ void resetFrameNumber(int sensor_port, ///< sensor_port sensor port number (0..3
int hreset) ///< Reset hardware sequencer itself
{
int i;
// Setup update mode for
x393_cmdseqmux_status_t stat;
x393_status_ctrl_t stat_ctrl;
x393_cmdframeseq_mode_t cmdframeseq_mode = {.d32=0};
......@@ -245,6 +255,7 @@ void resetFrameNumber(int sensor_port, ///< sensor_port sensor port number (0..3
cmdframeseq_mode.d32 = 0;
cmdframeseq_mode.run_cmd = 3; // Run
x393_cmdframeseq_ctrl(cmdframeseq_mode, sensor_port);
dev_dbg(g_devfp_ptr,"Reset command sequencer (all channels !): port= %d, thisFrameNumber=0x%lx\n", sensor_port, thisFrameNumber(sensor_port));
}
/* Check if the status update mode for command sequencer is not 3 (auto), set/wait if needed */
......@@ -274,7 +285,7 @@ void resetFrameNumber(int sensor_port, ///< sensor_port sensor port number (0..3
#ifdef NC353
thisFrameNumber(sensor_port) = X3X3_I2C_FRAME;
#endif
dev_dbg(g_devfp_ptr,"%s : port= %d, thisFrameNumber=0x%lx\n",__func__, sensor_port, thisFrameNumber(sensor_port));
dev_dbg(g_devfp_ptr,"Resetting frame number, port= %d, thisFrameNumber=0x%lx\n", sensor_port, thisFrameNumber(sensor_port));
// write absolute frame numbers
// for (i = thisFrameNumber(sensor_port); i < (thisFrameNumber(sensor_port) + PARS_FRAMES); i++) aframepars[sensor_port][i & PARS_FRAMES_MASK].pars[P_FRAME] = i;
for (i = 0; i < PARS_FRAMES; i++) aframepars[sensor_port][(i+frame16) & PARS_FRAMES_MASK].pars[P_FRAME] = thisFrameNumber(sensor_port) + i;
......@@ -287,6 +298,7 @@ void resetFrameNumber(int sensor_port, ///< sensor_port sensor port number (0..3
void initFramePars(int sensor_port)
{
int i;
spin_lock_bh(framepars_locks[sensor_port]);
memset(aframepars[sensor_port], 0, sizeof(struct framepars_t) * PARS_FRAMES);
resetFrameNumber(sensor_port, 0, 1);
// initialize frameParsDeps.pars masks:
......@@ -300,7 +312,8 @@ void initFramePars(int sensor_port)
initMultiPars(sensor_port); // initialize structures for individual per-sensor parameters. Now only works for sensor registers using G_MULTI_REGSM. Should be called after/during sensor detection
frameParsInitialized[sensor_port] = 1;
dev_dbg(g_devfp_ptr,"%s port %d: DONE, frameParsInitialized[%d]=%d\n",__func__, sensor_port, sensor_port, frameParsInitialized[sensor_port]);
spin_unlock_bh(framepars_locks[sensor_port]);
dev_dbg(g_devfp_ptr,"%s port %d: DONE, frameParsInitialized[%d]=%ld\n",__func__, sensor_port, sensor_port, frameParsInitialized[sensor_port]);
}
/**
......@@ -437,20 +450,21 @@ inline void set_imageParamsR_all(int sensor_port, int n, unsigned long
* @param interframe_pars
*/
void updateInterFrame(int sensor_port, ///< Sensor port number (0..3)
int frame16, ///< number of frame just compressed (lower 4 bits, from FPGA), always >= sensor frame number,
///< interrupt should be processed after frame sync interrupt
void updateInterFrame(int sensor_port, ///< Sensor port number (0..3)
u32 compressed_frame, ///< number of frame just compressed
///< interrupt should be processed after frame sync interrupt
struct interframe_params_t * interframe_pars) ///< pointer to the area in circbuf to save parameters
{
int findex_this, findex_prev, findex_future, findex_next;
int index, index32;
unsigned long bmask, bmask32;
// int findex_this, findex_prev, findex_future, findex_next;
// int index;
// int index32;
// unsigned long bmask, bmask32;
int pastParsIndex;
struct framepars_t *framepars = aframepars[sensor_port];
u32 compressed_frame; ///< absolute number of compressed frame , matching frame16
compressed_frame = (thisFrameNumber(sensor_port) & ~PARS_FRAMES_MASK) | (frame16 & PARS_FRAMES_MASK);
if (compressed_frame > thisFrameNumber(sensor_port)) // compressor frame number can never be higher than sesnor one
compressed_frame -= PARS_FRAMES;
// struct framepars_t *framepars = aframepars[sensor_port];
// u32 compressed_frame; ///< absolute number of compressed frame , matching frame16
// compressed_frame = (thisFrameNumber(sensor_port) & ~PARS_FRAMES_MASK) | (frame16 & PARS_FRAMES_MASK);
// if (compressed_frame > thisFrameNumber(sensor_port)) // compressor frame number can never be higher than sesnor one
// compressed_frame -= PARS_FRAMES;
thisCompressorFrameNumber(sensor_port) = compressed_frame;
// pastParsIndex = (thisFrameNumber(sensor_port) - 1) & PASTPARS_SAVE_ENTRIES_MASK; // copying from what was past frame that might include histogram data
pastParsIndex = compressed_frame & PASTPARS_SAVE_ENTRIES_MASK; // copying from what was past frame that might include histogram data
......@@ -566,14 +580,12 @@ void updateFramePars(int sensor_port, int frame16)
}
}
/**
* @brief process parameters that are overdue or due in ASAP mode (not through the sequencer)
/** Process parameters that are overdue or due in ASAP mode (not through the sequencer)
* Called twice from processPars - at the beginning and at the end to finish off any derivatives (needed?)
* @param sensor_port sensor port number (0..3)
* @param sensorproc
* @param frame16
*/
inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, int frame16)
* Should never be called from outside processPars() where there is a per-port lock */
inline void _processParsASAP(int sensor_port, ///< sensor port number (0..3)
struct sensorproc_t * sensorproc, ///< per-port array of sensor capabilities and 32+32 on-change functions
int frame16) ///< Hardware sequencer frame number, or -1 for ASAP
{
unsigned long todo, mask, remain;
int pars_ahead; // considering parameter "pars_ahead" of the (frame16+job_ahead) mod 8
......@@ -591,9 +603,13 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
framepars[1].functions, framepars[2].functions, framepars[3].functions, framepars[4].functions, framepars[5].functions,
framepars[6].functions, framepars[7].functions));
#endif
dev_dbg(g_devfp_ptr,"%s port=%d frame16=%d\n", __func__, sensor_port, frame16);
if (debug_flags)
dev_dbg(g_devfp_ptr,"ASAP: port=%d frame16=%d\n", sensor_port, frame16);
else
dev_dbg(g_devfp_ptr,"ASAP: port=%d frame16=%d\n", sensor_port, frame16);
if (!sensorproc){
dev_err(g_devfp_ptr,"%s port=%d frame16=%d sensorproc==NULL !!!! \n", __func__, sensor_port, frame16);
dev_err(g_devfp_ptr,"sensorproc==NULL !!!! port=%d frame16=%d \n", sensor_port, frame16);
return;
}
......@@ -606,6 +622,20 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
i = 0;
mask = 1;
remain = 0xffffffff;
if (debug_flags) {
todo = (pars_ahead) ?
(p_nasap[pars_ahead] & (procpars->functions) & remain) :
(procpars->functions & remain);
dev_dbg(g_devfp_ptr,"port=%d frame16=%d todo=0x%08lx,p_nasap[%d]=0x%08x procpars->functions=0x%08lx\n",
sensor_port, frame16, todo, pars_ahead, procpars->functions);
} else {
todo = (pars_ahead) ?
(p_nasap[pars_ahead] & (procpars->functions) & remain) :
(procpars->functions & remain);
dev_dbg(g_devfp_ptr,"port=%d frame16=%d todo=0x%08lx,p_nasap[%d]=0x%08x procpars->functions=0x%08lx\n",
sensor_port, frame16, todo, pars_ahead, procpars->functions);
}
while ((todo = (pars_ahead) ?
(p_nasap[pars_ahead] & (procpars->functions) & remain) :
(procpars->functions & remain) )) { //none, *1, *2,*3,*4
......@@ -616,13 +646,23 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
remain <<= 1;
}
// now (todo & mask) !=0
dev_dbg(g_devfp_ptr,"port= %d, todo=0x%08lx (curr=0x%08lx) frame16=%d, pars_ahead=%d, frame_proc=%d i=%d, mask=0x%08lx func=0x%08x\n",
sensor_port, todo, procpars->functions, frame16, pars_ahead, frame_proc, i, mask, (int)sensorproc->pgm_func[i]);
dev_dbg(g_devfp_ptr,"port= %d, %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
sensor_port,
framepars[0].functions, framepars[1].functions, framepars[2].functions, framepars[3].functions,
framepars[4].functions, framepars[5].functions, framepars[6].functions, framepars[7].functions);
if (debug_flags) {
dev_dbg(g_devfp_ptr,"port= %d, todo=0x%08lx (curr=0x%08lx) frame16=%d, pars_ahead=%d, frame_proc=%d i=%d, mask=0x%08lx func=0x%08x\n",
sensor_port, todo, procpars->functions, frame16, pars_ahead, frame_proc, i, mask, (int)sensorproc->pgm_func[i]);
dev_dbg(g_devfp_ptr,"port= %d, %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
sensor_port,
framepars[0].functions, framepars[1].functions, framepars[2].functions, framepars[3].functions,
framepars[4].functions, framepars[5].functions, framepars[6].functions, framepars[7].functions);
} else {
dev_dbg(g_devfp_ptr,"port= %d, todo=0x%08lx (curr=0x%08lx) frame16=%d, pars_ahead=%d, frame_proc=%d i=%d, mask=0x%08lx func=0x%08x\n",
sensor_port, todo, procpars->functions, frame16, pars_ahead, frame_proc, i, mask, (int)sensorproc->pgm_func[i]);
dev_dbg(g_devfp_ptr,"port= %d, %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
sensor_port,
framepars[0].functions, framepars[1].functions, framepars[2].functions, framepars[3].functions,
framepars[4].functions, framepars[5].functions, framepars[6].functions, framepars[7].functions);
}
if (sensorproc->pgm_func[i]) {
dev_dbg(g_devfp_ptr,"port= %d, Calling GENERIC pgm_func[%d] ASAP\n",sensor_port,i);
rslt = sensorproc->pgm_func[i] (sensor_port, &(sensorproc->sensor), procpars, prevpars, -1);
......@@ -649,8 +689,14 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
//#define G_CALLNEXT3 122 // bitmask of actions to be three or more frames ahead of the programmed one (OR-ed with G_CALLNEXT4)
//#define G_CALLNEXT4 123 // bitmask of actions to be four or more frames ahead of the programmed one
/** Process parameters that are overdue or due in ASAP mode (not through the sequencer)
* Called twice from processPars - at the beginning and at the end to finish off any derivatives (needed?)
* Should never be called from outside processPars() where there is a per-port lock */
inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, int frame16, int maxahead)
inline void _processParsSeq(int sensor_port, ///< sensor port number (0..3)
struct sensorproc_t * sensorproc, ///< per-port array of sensor capabilities and 32+32 on-change functions
int frame16, ///< Hardware sequencer frame number, or -1 for ASAP
int maxahead) ///< Maximal number of frames ahead to process. TODO NC393: Set G_MAXAHEAD >0 (max latency, was 2 in NC353!),
{
unsigned long todo, mask, remain;
int job_ahead; // doing job "job_ahead" ahead of needed
......@@ -665,14 +711,14 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
int rslt;
int max_par_ahead;
int this_ahead;
dev_dbg(g_devfp_ptr,"%s port=%d frame16=%d, maxahead=0 %d\n", __func__, sensor_port, frame16, maxahead);
dev_dbg(g_devfp_ptr,"%s port=%d frame16=%d, maxahead=%d\n", __func__, sensor_port, frame16, maxahead);
if (maxahead > (PARS_FRAMES - 3)) maxahead = PARS_FRAMES - 3; // use 5 if maxahead >5
// commands that use FPGA queues for the i2c/sequencer commands, executed at frame syncs
// Modifying - as soon as found the frame to process with non-zero masked .functions - process all functions for that
// frame with appropriate sequencer frame.
// For now - scan p_nasap[i] to find latency - improve that later
for (job_ahead = 0; job_ahead <= maxahead; job_ahead++ ) {
for (job_ahead = 0; job_ahead <= maxahead; job_ahead++ ) { // If have some time - do future job (not required just now)
max_par_ahead = min(5, (PARS_FRAMES - 3) - job_ahead);
for (pars_ahead = 0; pars_ahead < max_par_ahead; pars_ahead++ ) {
frame_proc = (frame16 + job_ahead + pars_ahead + 1) & PARS_FRAMES_MASK; //
......@@ -730,7 +776,7 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
/**
* @brief Program image acquisition, according to the parameters changed
* Called from ISR?
* Called from tasklet and user (setFrameParsAtomic) and LSEEK_SENSORPROC
* @param sensor_port sensor port number (0..3)
* @param sensorproc pointer to sensor static parameters and functions
* @param frame16 current hardware frame number
......@@ -739,31 +785,62 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
*/
//TODO: "Do it later" should be the only reason not to erase todo bit
//#define P_CALLASAP 107 // bitmask - what functions work only in the current frame (ASAP) mode
void processPars(int sensor_port, struct sensorproc_t * sensorproc, int frame16, int maxahead)
void _processPars(int sensor_port, struct sensorproc_t * sensorproc, int frame16, int maxahead)
{
frame16 &= PARS_FRAMES_MASK;
dev_dbg(g_devfp_ptr,"%s : port= %d, frame16=%d, maxahead=%d\n",__func__, sensor_port, frame16, maxahead);
frame16 &= PARS_FRAMES_MASK;
dev_dbg(g_devfp_ptr,"port= %d, frame16=%d, maxahead=%d\n", sensor_port, frame16, maxahead);
if (!sensorproc){
dev_err(g_devfp_ptr,"%s port=%d frame16=%d sensorproc==NULL !!!! \n", __func__, sensor_port, frame16);
return;
}
// int spin_trylock(spinlock_t *lock);
// first - do all ASAP tasks (they should not be done ahead of the corresponding interrupt!)
// dev_dbg(g_devfp_ptr,"%s before first processParsASAP\n",__func__);
processParsASAP(sensor_port, sensorproc, frame16);
dev_dbg(g_devfp_ptr,"%s : port= %d (after first processParsASAP), frame16=%d, maxahead=%d\n",__func__, sensor_port, frame16, maxahead);
// dev_dbg(g_devfp_ptr,"%s before first _processParsASAP\n",__func__);
_processParsASAP(sensor_port, sensorproc, frame16); // NC393: never gets here ? Only after _processParsSeq?
dev_dbg(g_devfp_ptr,"%s : port= %d (after first _processParsASAP), frame16=%d, maxahead=%d\n",__func__, sensor_port, frame16, maxahead);
// now - the rest commands that use FPGA queues for the i2c/sequencer commands, executed at frame syncs
// for jobahead =0 it is still possible to have some functions in ASAP mode with non-zero latency
// dev_dbg(g_devfp_ptr,"%s before processParsSeq\n",__func__);
processParsSeq(sensor_port, sensorproc, frame16, maxahead);
dev_dbg(g_devfp_ptr,"%s : port= %d (after processParsSeq), frame16=%d, maxahead=%d\n",__func__, sensor_port, frame16, maxahead);
// dev_dbg(g_devfp_ptr,"%s before _processParsSeq\n",__func__);
_processParsSeq(sensor_port, sensorproc, frame16, maxahead);
dev_dbg(g_devfp_ptr,"%s : port= %d (after _processParsSeq), frame16=%d, maxahead=%d\n",__func__, sensor_port, frame16, maxahead);
// re-test ASAP tasks - they might appear as a result of other commands executed
// dev_dbg(g_devfp_ptr,"%s before second processParsASAP\n",__func__);
processParsASAP(sensor_port, sensorproc, frame16);
dev_dbg(g_devfp_ptr,"%s : port= %d (after second processParsASAP), frame16=%d, maxahead=%d\n",__func__, sensor_port, frame16, maxahead);
// dev_dbg(g_devfp_ptr,"%s before second _processParsASAP\n",__func__);
_processParsASAP(sensor_port, sensorproc, frame16);
dev_dbg(g_devfp_ptr,"%s : port= %d (after second _processParsASAP), frame16=%d, maxahead=%d\n",__func__, sensor_port, frame16, maxahead);
if (debug_flags) debug_flags--;
}
#undef LOCK_BH_PROCESSPARS
void processPars(int sensor_port, struct sensorproc_t * sensorproc, int frame16, int maxahead)
{
frame16 &= PARS_FRAMES_MASK;
dev_dbg(g_devfp_ptr,"port= %d, frame16=%d, maxahead=%d\n", sensor_port, frame16, maxahead);
if (!sensorproc){
dev_err(g_devfp_ptr,"%s port=%d frame16=%d sensorproc==NULL !!!! \n", __func__, sensor_port, frame16);
return;
}
#ifdef LOCK_BH_PROCESSPARS
spin_lock_bh(framepars_locks[sensor_port]);
// WARNING: CPU: 1 PID: 2329 at /home/eyesis/git/elphel393/poky/build/tmp/work-shared/elphel393/kernel-source/kernel/softirq.c:150 __local_bh_enable_ip+0xb0/0x100()
#else
// Here we can get from both a tasklet and from LSEEK_SENSORPROC. We do not need to do this twice - if processPars() is ran by
// somebody else - that is OK not to do it again (what about maxahead?)
if (!spin_trylock(framepars_locks[sensor_port])) {
dev_dbg(g_devfp_ptr,"framepars_locks[%d] is locked, we do not need to re-run it. frame16=%d maxahead=%d \n", sensor_port, frame16, maxahead);
return;
}
#endif
_processPars(sensor_port, sensorproc, frame16, maxahead);
#ifdef LOCK_BH_PROCESSPARS
spin_unlock_bh(framepars_locks[sensor_port]); // removed, see above
#else
spin_unlock(framepars_locks[sensor_port]);
#endif
}
/**
* @brief schedule pgm_func to be executed for selected frame (frame16)
* @param sensor_port sensor port number (0..3)
......@@ -823,18 +900,16 @@ int setFrameParsStatic(int sensor_port, int numPars, struct frameparspair_t * pa
return 0;
}
/**
* @brief set parameters for the specified frame (atomic, with interrupts off). Used from applications through driver write
* @param sensor_port sensor port number (0..3)
* @param frameno absolute (full) frame number parameters should be applied to
* @param maxLatency maximal command latency (parameters should be set not less than maxLatency ahead of the current frame)
* maxLatency < 0 - don't check latency (i.e.only commands that are not releted to particular frames)
* @param numPars number of parameters to set (0 is OK to just test if it is too early/too late)
* @param pars array of parameters (number/value pairs). FRAMEPAIR_FORCE_NEW modifier to parameter number
* @return 0 - OK, -ERR_FRAMEPARS_TOOEARLY, -ERR_FRAMEPARS_TOOLATE
*/
//TODO: Check that writes never to the future or past frame (only 6 of 8 are allowed). Have seen just_this to flood all
int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, int numPars, struct frameparspair_t * pars)
/** Set parameters for the specified frame (atomic, with interrupts off). Used from applications through driver write */
//TODO: Check that writes never to the future or past frame (only 6 of 8 are allowed -> 14 of 16). Have seen just_this to flood all
int setFrameParsAtomic(int sensor_port, ///< sensor port number (0..3)
unsigned long frameno, ///< absolute (full) frame number parameters should be applied to
int maxLatency, ///< maximal command latency (parameters should be set not less than maxLatency ahead of the current frame)
///< maxLatency < 0 - don't check latency (i.e. only commands that are not releted to particular frames),
///< with negative and frameno< current frame will make it current, to use with ASAP
int numPars, ///< number of parameters to set (0 is OK to just test if it is too early/too late)
struct frameparspair_t * pars) ///< array of parameters (number/value pairs). FRAMEPAIR_FORCE_NEW modifier to parameter number
///< @return 0 - OK, -ERR_FRAMEPARS_TOOEARLY, -ERR_FRAMEPARS_TOOLATE
{
unsigned long flags;
int npar, nframe;
......@@ -843,37 +918,52 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
struct framepars_t *framepars = aframepars[sensor_port];
unsigned long *funcs2call =afuncs2call[sensor_port];
int findex_this, findex_prev, findex_future, frame16;
dev_dbg(g_devfp_ptr,"%s : port= %d, frameno=0x%lx, findex_this=%d (0x%lx) maxLatency=%d, numPars=%d, frameParsInitialized[%d]=%d\n",
__func__, sensor_port, frameno, findex_this, thisFrameNumber(sensor_port), maxLatency, numPars, sensor_port, frameParsInitialized[sensor_port]);
dev_dbg(g_devfp_ptr,"port= %d, frameno=0x%lx, findex_this=%ld (0x%lx) maxLatency=%d, numPars=%d, frameParsInitialized[%d]=%d\n",
sensor_port, frameno, findex_this, thisFrameNumber(sensor_port), maxLatency, numPars, sensor_port, frameParsInitialized[sensor_port]);
if (!frameParsInitialized[sensor_port]) {
initSequencers(sensor_port); // Will call initFramePars(); and initialize functions
}
findex_this = thisFrameNumber(sensor_port) & PARS_FRAMES_MASK;
findex_prev = (findex_this - 1) & PARS_FRAMES_MASK;
findex_future = (findex_this - 2) & PARS_FRAMES_MASK; // actually - fartherst in the future??
D1I(local_irq_save(flags));
// D1I(local_irq_save(flags));
spin_lock_irqsave(framepars_locks[sensor_port], flags);
PROFILE_NOW(5); // Was 6, but no 7 in NC393
if (maxLatency >= 0) {
if (frameno <= (thisFrameNumber(sensor_port) + maxLatency)) {
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
dev_dbg(g_devfp_ptr,"port=%d, ERR_FRAMEPARS_TOOLATE, frameno = 0x%x\n",sensor_port, (int)frameno);
return -ERR_FRAMEPARS_TOOLATE;
}else if (frameno >= (thisFrameNumber(sensor_port) + (PARS_FRAMES - 1))) {
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
dev_dbg(g_devfp_ptr,"port=%d, ERR_FRAMEPARS_TOOEARLY, frameno = 0x%x\n",sensor_port, (int)frameno);
return -ERR_FRAMEPARS_TOOEARLY;
}
} else {
dev_dbg(g_devfp_ptr,"port=%d, Using negative maxLatency, frameno = 0x%x, thisFrameNumber(%d) = 0x%x\n",
sensor_port, (int)frameno, sensor_port, (int) thisFrameNumber(sensor_port));
if (frameno < thisFrameNumber(sensor_port)){
dev_dbg(g_devfp_ptr,"port=%d, Replacing earlier supplied frame number = 0x%x with the current one= 0x%x\n",
sensor_port, (int)frameno, (int) thisFrameNumber(sensor_port));
frameno = thisFrameNumber(sensor_port);
}
}
// not too late, not too early, go ahead
// not too late, not too early, go ahead (or maxlatency <0 - ASAP only)
for (npar = 0; npar < numPars; npar++) {
D5(printk(" --pars[%d].num=0x%lx, pars[%d].val=0x%lx", npar, pars[npar].num, npar, pars[npar].val));
dev_dbg(g_devfp_ptr,"port= %d, --pars[%d].num=0x%lx, pars[%d].val=0x%lx", sensor_port, npar, pars[npar].num, npar, pars[npar].val);
// frame16= (pars[npar].num & FRAMEPAR_GLOBALS)? -1: (frameno & PARS_FRAMES_MASK);
frame16 = frameno & PARS_FRAMES_MASK;
val = pars[npar].val;
index = pars[npar].num & 0xffff;
if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) {
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
dev_dbg(g_devfp_ptr,"port=%d, ERR_FRAMEPARS_BADINDEX, frameno = 0x%x\n",sensor_port, (int)frameno);
return -ERR_FRAMEPARS_BADINDEX;
}
D5(printk(" index=0x%x, val=0x%lx", index, val));
dev_dbg(g_devfp_ptr,"port= %d, ndex=0x%x, val=0x%lx", index, val, sensor_port);
if (index >= FRAMEPAR_GLOBALS) { // ignore frame logic, set "static" parameters to frame 0
if (pars[npar].num & FRAMEPAIR_MASK_BYTES) { // combine new value with the old one
val = FRAMEPAIR_FRAME_MASK_NEW(pars[npar].num, GLOBALPARS(sensor_port,index), val);
......@@ -882,14 +972,14 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
D5(printk(" set GLOBALPARS(0x%x)=0x%lx\n", index, val));
} else if (pars[npar].num & FRAMEPAIR_FRAME_FUNC) {
funcs2call[index] = val;
D5(printk(" set funcs2call[0x%x]=0x%lx\n", index, val));
dev_dbg(g_devfp_ptr,"port= %d, set funcs2call[0x%x]=0x%lx\n", index, val, sensor_port);
// } else if ((frameno !=findex_prev) && (frameno != findex_future)) { // do not write parameters in the future otherwise
} else if ((frame16 != findex_future) || ((pars[npar].num & FRAMEPAIR_JUST_THIS) == 0)) { // do not write "JUST_THIS" parameters in the future otherwise they'll stick
if (pars[npar].num & FRAMEPAIR_MASK_BYTES) { // combine new value with the old one
val = FRAMEPAIR_FRAME_MASK_NEW(pars[npar].num, framepars[frame16].pars[index], val);
}
//TODO: optimize to use mask several parameters together
D5(printk(" frame16=0x%x\n", frame16));
dev_dbg(g_devfp_ptr,"port= %d, frame16=0x%x\n", frame16, sensor_port);
if ((framepars[frame16].pars[index] != val) || (pars[npar].num & FRAMEPAIR_FORCE_NEW)) {
bmask = 1 << (index & 31);
bindex = index >> 5;
......@@ -899,16 +989,16 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
framepars[frame16].mod[bindex] |= bmask;
framepars[frame16].mod32 |= bmask32;
framepars[frame16].functions |= funcs2call[index]; //Mark which functions will be needed to process the parameters
D5(printk(" bindex=0x%x, bmask=0x%08lx, bmask32=0x%08lx, functions=0x%08lx\n", bindex, bmask, bmask32, framepars[frame16].functions));
dev_dbg(g_devfp_ptr,"port= %d, bindex=0x%x, bmask=0x%08lx, bmask32=0x%08lx, functions=0x%08lx\n", sensor_port, bindex, bmask, bmask32, framepars[frame16].functions);
// Write parameter to the next frames up to the one that have the same parameter already modified (only if not FRAMEPAIR_JUST_THIS)
if ((pars[npar].num & FRAMEPAIR_JUST_THIS) == 0) {
MDF5(printk(": --- setting next frames"));
dev_dbg(g_devfp_ptr,"port= %d, --- setting next frames\n",sensor_port);
for (nframe = (frame16 + 1) & PARS_FRAMES_MASK; (nframe != findex_prev) && (!(framepars[nframe].mod[bindex] & bmask)); nframe = (nframe + 1) & PARS_FRAMES_MASK) {
framepars[nframe].pars[index] = val;
D5(printk(" %d", nframe));
dev_dbg(g_devfp_ptr,"port= %d, %d", sensor_port, nframe);
}
frame16 = (frame16 - 1) & PARS_FRAMES_MASK; // for " regular parameters "modified since" do not include the target frame itself, for "JUST_THIS" - does
D5(printk("\n"));
// D5(printk("\n"));
}
// Mark this parameter in all previous frames as "modified since"
// TODO: consider alternative way - first iterate through all parameters, build masks, then apply them
......@@ -918,38 +1008,46 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
}
}
} else { // error - trying to write "just this" to the "future" - that would stick if allowed
D1I(local_irq_restore(flags));
ELP_KERR(printk("Tried to write JUST_THIS parameter (0x%lx) too far in the future", pars[npar].num));
// D1I(local_irq_restore(flags));
spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
dev_dbg(g_devfp_ptr,"port= %d, Tried to write JUST_THIS parameter (0x%lx) too far in the future", sensor_port, pars[npar].num);
dev_err(g_devfp_ptr,"port= %d, Tried to write JUST_THIS parameter (0x%lx) too far in the future", sensor_port, pars[npar].num);
return -ERR_FRAMEPARS_TOOEARLY;
}
}
// Try to process parameters immediately after written. If 0, only non-ASAP will be processed to prevent
// effects of uncertainty of when was it called relative to frame sync
// Changed to all (don't care about uncertainty - they will trigger only if it is too late or during sensor detection/initialization)
debug_flags = 5; // enable debug print several times
if (!(get_globalParam(sensor_port, G_TASKLET_CTL) & (1 << TASKLET_CTL_NOSAME))) {
// processParsSeq (sensorproc, thisFrameNumber & PARS_FRAMES_MASK, 0); //maxahead=0, the rest will be processed after frame sync, from the tasklet
dev_dbg(g_devfp_ptr,"%s port=%d, G_TASKLET_CTL -> 0x%x \n",__func__, sensor_port, (int) get_globalParam(sensor_port, G_TASKLET_CTL));
processPars(sensor_port, &asensorproc[sensor_port], thisFrameNumber(sensor_port) & PARS_FRAMES_MASK, 0); //maxahead=0, the rest will be processed after frame sync, from the tasklet
// _processParsSeq (sensorproc, thisFrameNumber & PARS_FRAMES_MASK, 0); //maxahead=0, the rest will be processed after frame sync, from the tasklet
dev_dbg(g_devfp_ptr,"G_TASKLET_CTL -> 0x%x (port = %d )\n", (int) get_globalParam(sensor_port, G_TASKLET_CTL),sensor_port);
// processPars(sensor_port, &asensorproc[sensor_port], thisFrameNumber(sensor_port) & PARS_FRAMES_MASK, 0); //maxahead=0, the rest will be processed after frame sync, from the tasklet
// Already having lock, call inner function. When called from tasklet, it will have to acquire lock
_processPars(sensor_port, &asensorproc[sensor_port], thisFrameNumber(sensor_port) & PARS_FRAMES_MASK, 0); //maxahead=0, the rest will be processed after frame sync, from the tasklet
dev_dbg(g_devfp_ptr,"kthread _processPars(%d, .., 0x%x) DONE\n",sensor_port, thisFrameNumber(sensor_port));
} else {
dev_dbg(g_devfp_ptr,"kthread: NOT calling _processPars(%d, .., 0x%lx) DONE\n",sensor_port, thisFrameNumber(sensor_port));
}
PROFILE_NOW(6); // 7); // no (7) in NC393
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
return 0;
}
//#define FRAMEPAIR_JUST_THIS 0x40000 // write only to this frame, don't propagate
// (like "single frame" - compressor, sensor) first write "stop", then - "single" with FRAMEPAIR_JUST_THIS
/**
* @brief set a single output (calculated) parameter for the frame referenced by this_framepars structure.
/** Set a single output (calculated) parameter for the frame referenced by this_framepars structure.
* Schedules action only if the FRAMEPAIR_FORCE_PROC modifier bit is set in mindex
* @param sensor_port sensor port number (0..3)
* @param this_framepars pointer to the current parameters structure
* @param mindex parameter number (with optional modifiers in high bits)
* @param val parameter value to set
* @return 0 - OK, -ERR_FRAMEPARS_BADINDEX
*/
int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned long mindex, unsigned long val)
* Should only be called when IRQ (just bh preferrably) is off and lock on framepars_locks[sensor_port] (all pgm_* have that) */
int setFramePar(int sensor_port, ///< sensor port number (0..3)
struct framepars_t * this_framepars, ///< pointer to the current parameters structure
unsigned long mindex, ///< parameter number (with optional modifiers in high bits)
unsigned long val) ///< parameter value to set
///< @return 0 - OK, -ERR_FRAMEPARS_BADINDEX
{
int frame16 = (this_framepars->pars[P_FRAME]) & PARS_FRAMES_MASK;
unsigned long flags;
// unsigned long flags; should only be called when interruypts disabled and lock obtained
int nframe;
unsigned long bmask, bmask32, bindex;
int findex_this = thisFrameNumber(sensor_port) & PARS_FRAMES_MASK;
......@@ -960,10 +1058,13 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l
unsigned long *funcs2call =afuncs2call[sensor_port];
dev_dbg(g_devfp_ptr, "%s: port=%d, thisFrameNumber=0x%lx frame16=%d index= %d (0x%lx), val=0x%lx\n",__func__, sensor_port, thisFrameNumber(sensor_port), frame16, index, mindex, val);
D1I(local_irq_save(flags));
// D1I(local_irq_save(flags));
// spin_lock_irqsave(framepars_locks[sensor_port], flags);
// if (index > P_MAX_PAR) {
if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) {
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
// spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
return -ERR_FRAMEPARS_BADINDEX;
}
//TODO: optimize to use mask several parameters together
......@@ -1015,26 +1116,52 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l
D8(printk("\n"));
}
} else { // error - trying to write "just this" to the "future" - that would stick if allowed
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
// spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
dev_dbg(g_devfp_ptr, "Tried to write JUST_THIS parameter (0x%lx) too far in the future", mindex);
dev_err(g_devfp_ptr, "Tried to write JUST_THIS parameter (0x%lx) too far in the future", mindex);
return -ERR_FRAMEPARS_TOOEARLY;
}
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
// spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
return 0;
}
/**
* @brief set multiple output (calculated) parameters for the frame referenced by this_framepars structure.
/** Set a single output (calculated) parameter for the frame referenced by this_framepars structure from the user program
* Obtain lock, disable IRQ and call setFramePar
* Schedules action only if the FRAMEPAIR_FORCE_PROC modifier bit is set in mindex
* Should only be called when IRQ (just bh preferrably) is off and lock on framepars_locks[sensor_port] (all pgm_* have that) */
int setFrameParLocked(int sensor_port, ///< sensor port number (0..3)
struct framepars_t * this_framepars, ///< pointer to the current parameters structure
unsigned long mindex, ///< parameter number (with optional modifiers in high bits)
unsigned long val) ///< parameter value to set
///< @return 0 - OK, -ERR_FRAMEPARS_BADINDEX
{
unsigned long flags;
int rslt;
spin_lock_irqsave(framepars_locks[sensor_port], flags);
rslt = setFramePar(sensor_port, // sensor port number (0..3)
this_framepars, // pointer to the current parameters structure
mindex, // parameter number (with optional modifiers in high bits)
val); // parameter value to set
// @return 0 - OK, -ERR_FRAMEPARS_BADINDEX
spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
return rslt;
}
/** Set multiple output (calculated) parameters for the frame referenced by this_framepars structure.
* Schedules action only if the FRAMEPAIR_FORCE_PROC modifier bit is set in the particular parameter index
* @param sensor_port sensor port number (0..3)
* @param this_framepars pointer to the current parameters structure
* @param numPars number of parameters to set
* @param pars array of parameters (number/value pairs). Parameter numbers accept modifiers
* @return 0 - OK, -ERR_FRAMEPARS_BADINDEX
*/
int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPars, struct frameparspair_t * pars)
* Called from tasklets (while executing (*_)pgm_* functions
* Should only be called when IRQ (just bh preferrably) is off and lock on framepars_locks[sensor_port] (all pgm_* have that) */
int setFramePars(int sensor_port, ///< sensor port number (0..3)
struct framepars_t * this_framepars, ///< this_framepars pointer to the current parameters structure
int numPars, ///< number of parameters to set
struct frameparspair_t * pars) ///<array of parameters (number/value pairs). Parameter numbers accept modifiers
///< @return 0 - OK, -ERR_FRAMEPARS_BADINDEX
{
int frame16;
unsigned long flags;
// unsigned long flags; should only be called when interruypts disabled and lock obtained
int npar, nframe;
unsigned long val, bmask, bmask32;
int index, bindex;
......@@ -1045,7 +1172,8 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa
unsigned long *funcs2call =afuncs2call[sensor_port];
dev_dbg(g_devfp_ptr, "%s : port= %d, this_framepars=0x%x numPars=%d\n",__func__, sensor_port, (int)this_framepars, numPars);
D1I(local_irq_save(flags));
// D1I(local_irq_save(flags));
// spin_lock_irqsave(framepars_locks[sensor_port], flags);
for (npar = 0; npar < numPars; npar++) {
frame16 = (this_framepars->pars[P_FRAME]) & PARS_FRAMES_MASK;
val = pars[npar].val;
......@@ -1053,7 +1181,8 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa
dev_dbg(g_devfp_ptr, ": --- frame16=%d index=%d (0x%x) val=0x%x\n", frame16, index, (int)pars[npar].num, (int)val);
// remark: code below looks similar to setFramePar function, call it instead
if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) {
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
// spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
dev_err(g_devfp_ptr, " bad index=%d > %d\n", index, P_MAX_PAR);
return -ERR_FRAMEPARS_BADINDEX;
}
......@@ -1100,12 +1229,14 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa
}
}
} else { // error - trying to write "just this" to the "future" - that would stick if allowed
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
// spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
dev_err(g_devfp_ptr, "Tried to write JUST_THIS parameter (0x%lx) too far in the future", pars[npar].num);
return -ERR_FRAMEPARS_TOOEARLY;
}
}
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
// spin_unlock_irqrestore(framepars_locks[sensor_port], flags);
return 0;
}
......@@ -1371,9 +1502,9 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff
}
last = first + 1;
while ((last < count) && ((pars[last].num & 0xff00) != 0xff00)) last++; // skip to the end or next special instructions
dev_dbg(g_devfp_ptr, "%s 0x%x: setFrameParsAtomic(%ld, %d, %d)\n",
__func__, (int) privData->minor, frame, latency, last - first);
result = setFrameParsAtomic(sensor_port,frame, latency, last - first, &pars[first]);
dev_dbg(g_devfp_ptr, "%s 0x%x: setFrameParsAtomic(%ld, %d, %d)\n",
__func__, (int) privData->minor, frame, latency, last - first);
if (result < 0) {
if (count > sizeof(pars_static)) kfree(pars);
return -EFAULT;
......@@ -1385,7 +1516,7 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff
return count << 3; // *sizeof(struct frameparspair_t);
default: return -EINVAL;
}
}
} // the frame size of 2080 bytes is larger than 1024 bytes [-Wframe-larger-than=]
/**
* @brief Driver MMAP method (should be used read only)
......@@ -1461,9 +1592,9 @@ static ssize_t store_fpga_time(struct device *dev, struct device_attribute *attr
{
sec_usec_t sec_usec={.sec=0, .usec=0};
// avoiding floating point calcualtions in the kernel
char *cp;
char *cp = buf;
int i;
if (sscanf(buf, "%u.%s", &sec_usec.sec, cp)>0){
if (sscanf(buf, "%lu.%s", &sec_usec.sec, cp)>0){
sscanf(cp,"%lu",&sec_usec.usec);
for (i=strlen(cp); i<6;i++)
sec_usec.usec *=10;
......
......@@ -30,7 +30,7 @@ unsigned long get_globalParam (int sensor_port, int n);
void set_globalParam (int sensor_port, int n, unsigned long d);
void set_imageParamsR_all(int sensor_port, int n, unsigned long d);
//Next 2 called from ISR
void updateInterFrame(int sensor_port, int frame16, struct interframe_params_t * interframe_pars);
void updateInterFrame(int sensor_port, u32 compressed_frame, struct interframe_params_t * interframe_pars);
void updateFramePars (int sensor_port, int frame16);
int setFrameParsStatic (int sensor_port, int numPars, struct frameparspair_t * pars);
......@@ -40,28 +40,32 @@ unsigned long getThisFrameNumber (int sensor_port); /// just return current thi
/// Return - 0 if OK, -ERR_FRAMEPARS_TOOEARLY or -ERR_FRAMEPARS_TOOLATE if it is too early or too late to set parameters (numPars may be 0 to just test)
///
/// NOTE: When writing parameter to P_SENSOR_RUN or P_COMPRESSOR_RUN "*_RUN_SINGLE", first write "*SENSOR_RUN_STOP" (it will propagate to all next frames) and then
/// write "*_RUN_SINGLE", to (P_*_RUN | FRAMEPAIR_JUST_THIS) - then this *_RUN_SINGLE will not propagate to the next frames (they will stay stopped)
// write "*_RUN_SINGLE", to (P_*_RUN | FRAMEPAIR_JUST_THIS) - then this *_RUN_SINGLE will not propagate to the next frames (they will stay stopped)
/// TODO: Make (an "unlimited") future commands que based on lists and a tree frame index
// TODO: Make (an "unlimited") future commands que based on lists and a tree frame index
int setFrameParsAtomic (int sensor_port, unsigned long frameno, int maxLatency, int numPars, struct frameparspair_t * pars);
/// set output/calculated parameter and propagate changes - will not trigger any actions
// set output/calculated parameter and propagate changes - will not trigger any actions
int setFramePar (int sensor_port, struct framepars_t * this_framepars, unsigned long mindex, unsigned long val);
// Same, but adds lock to call from user thread
int setFrameParLocked (int sensor_port, struct framepars_t * this_framepars, unsigned long mindex, unsigned long val);
///same for several pars at once
int setFramePars (int sensor_port, struct framepars_t * this_framepars, int numPars, struct frameparspair_t * pars);
/// schedule pgm_func to be executed for selected frame
void schedule_pgm_func (int sensor_port, int frame8, int func_num);
/// schedule pgm_func to be executed for the current frame
// schedule pgm_func to be executed for the current frame
void schedule_this_pgm_func (int sensor_port, struct framepars_t * this_framepars, int func_num);
/// program acquisition, according to the parameters changed.
/// maxahead - how many frames ahead of time (start with most urgent, then 1 ahead, ...)
/// make maxahead - P_* parameter?
/* 393: See if sesnor port is needed here */
inline void processParsASAP (int sensor_port, struct sensorproc_t * sensorproc, int frame8);
inline void processParsSeq (int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead);
// program acquisition, according to the parameters changed.
// maxahead - how many frames ahead of time (start with most urgent, then 1 ahead, ...)
// make maxahead - P_* parameter?
/* 393: See if sensor port is needed here */
/* NC393: Removed, should not be called from outside the lock-ed processPars() */
//inline void _processParsASAP (int sensor_port, struct sensorproc_t * sensorproc, int frame8);
//inline void _processParsSeq (int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead);
void processPars (int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead);
///*** TODO: Add option (flag?) to write "single" (like single compress, single sensor) so it will not make all the next frames "single"
......
......@@ -173,10 +173,7 @@ static DEFINE_SPINLOCK(gamma_lock_1); ///<
static DEFINE_SPINLOCK(gamma_lock_2); ///<
static DEFINE_SPINLOCK(gamma_lock_3); ///<
/** Define array of pointers to locks - hardware allows concurrent writes to different ports tables */
spinlock_t * gamma_locks[4] = {&gamma_lock_0,
&gamma_lock_1,
&gamma_lock_2,
&gamma_lock_3};
spinlock_t * gamma_locks[4] = {&gamma_lock_0, &gamma_lock_1, &gamma_lock_2, &gamma_lock_3};
static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE)));
struct gamma_stuct_t * gammas_p; // to use with mmap
......
......@@ -622,11 +622,11 @@ loff_t histograms_lseek (struct file * file,
}
// request histogram(s)
// setFramePar(&framepars[reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(privData->port, &aframepars[privData->port][reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
setFrameParLocked(privData->port, &aframepars[privData->port][reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
// make sure (harmful) interrupt did not happen since getThisFrameNumber()
if (reqFrame < getThisFrameNumber(privData->port)) {
// setFramePar(&framepars[getThisFrameNumber() & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(privData->port, &aframepars[privData->port][getThisFrameNumber(privData->port) & PARS_FRAMES_MASK], reqAddr, 1);
setFrameParLocked(privData->port, &aframepars[privData->port][getThisFrameNumber(privData->port) & PARS_FRAMES_MASK], reqAddr, 1);
}
}
......
......@@ -344,6 +344,9 @@
#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 "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr
//#include "x3x3.h" // detect sensor
//#include "cci2c.h"
......@@ -388,9 +391,9 @@
#endif
static struct device *g_dev_ptr=NULL; ///< Global pointer to basic device structure. This pointer is used in debugfs output functions
void mt9x001_set_device(struct device *dev)
void mt9x001_set_device(struct device *dev) // do nothing, now it has it's own device
{
g_dev_ptr = dev;
//g_dev_ptr = dev;
}
......@@ -548,6 +551,14 @@ struct sensor_t mt9p001={
.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 MT9M001 */
......@@ -885,7 +896,6 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
int nupdate=0;
int i,color;
int regval, regnum, mreg, j;
dev_dbg(g_dev_ptr,"Resetting MT9X001 sensor\n");
// reset sensor by applying MRST (low):
#ifdef NC353
CCAM_MRST_ON;
......@@ -918,24 +928,31 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
}
#else
// CCAM_MRST_ON;
sensio_ctl.mrst = 0;
sensio_ctl.mrst_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
udelay (100);
// CCAM_MRST_OFF;
sensio_ctl.mrst = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
sensio_ctl.d32=0;
if (debug_delays & 0xff) {
dev_dbg(g_dev_ptr,"Resetting MT9X001 sensor, port=%d\n",sensor_port);
sensio_ctl.mrst = 0;
sensio_ctl.mrst_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
udelay (debug_delays & 0xff) ; // 100);
// CCAM_MRST_OFF;
sensio_ctl.mrst = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
sensio_ctl.d32=0;
}
// NC393: both sequencers started in pgm_detectsensor
udelay (100);
dev_dbg(g_dev_ptr,"Reading sensor registers to the shadows:\n");
if (debug_delays & 0xff00) {
udelay ((debug_delays >> 8) & 0xff); // 100);
}
first_sensor_i2c=sensor->i2c_addr;
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;
......@@ -944,6 +961,10 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
SETFRAMEPARS_SET(mreg+j,regval);
}
}
for (i=0;i<256;i++) {
sensor_reg_copy[sensor_port][i] = i2c_read_data_dw[i];
}
#endif
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
dev_dbg(g_dev_ptr,"Initializing MT9X001 registers with default values:\n");
......@@ -2070,10 +2091,147 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
return 0;
}
//#define MAX_SENSORS 3 // maximal number of sensor attached (modify some hard-wired constants below if this to be changed)
//#define G_MULTI_NUM (FRAMEPAR_GLOBALS + 34) // Actual number of parameters that are individual for different channels (limited by P_MULTI_NUMREGS)
//#define P_MULTI_NUMREGS 32 // up to 32 sensor register may have individual values
//#define P_MULTI_REGS (P_SENSOR_REGS + P_SENSOR_NUMREGS) // 32-words aligned
//I2C359_INC
//#define FRAMEPAR_MODIFIED(x) (thispars->mod[(x) >> 5] & (1<<((x) & 0x1f)))
// #define MULTIRVRSREG(x) (multiSensRvrsIndex[x])
//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 mt9x001
#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;
}
// 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 const struct attribute_group dev_attr_root_group = {
.attrs = root_dev_attrs,
.name = NULL,
};
static int elphel393_mt9x001_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 mt9x001_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_mt9x001_sysfs_register(pdev);
dev_info(dev, DEV393_NAME(DEV393_MT9X001)": registered sysfs\n");
g_dev_ptr = dev;
return 0;
}
int mt9x001_remove(struct platform_device *pdev)
{
unregister_chrdev(DEV393_MAJOR(DEV393_MT9X001), DEV393_NAME(DEV393_MT9X001));
return 0;
}
static const struct of_device_id elphel393_mt9x001_of_match[] = {
{ .compatible = "elphel,elphel393-mt9x001-1.00" },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, elphel393_mt9x001_of_match);
static struct platform_driver elphel393_mt9x001 = {
.probe = mt9x001_init,
.remove = mt9x001_remove,
.driver = {
.name = DEV393_NAME(DEV393_MT9X001),
.of_match_table = elphel393_mt9x001_of_match,
},
};
module_platform_driver(elphel393_mt9x001);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION("Driver for parallel interface image sensors Micron/Aptina/On Semi MT9M*, MT9D*, MT9T* and MT9P* in Elphel cameras");
......@@ -131,11 +131,3 @@ each dibit:
//#define I2C359_CLK_NUMBER 4 // system clock number for the 10359A on-board clock generator
void multi10359_set_device(struct device *dev);
int multisensor_pgm_detectsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
//int legacy_i2c (int ports);
/*
struct frameparspair_t pars_to_update[8];
int nupdate=0;
...
if (nupdate) setFramePars(thispars, nupdate, pars_to_update); /// save changes to sensor register shadows
*/
......@@ -391,7 +391,7 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
dev_dbg(g_dev_ptr,"Setting i2c drive mode for port %d\n",sensor_port);
i2c_drive_mode (sensor_port, SDA_DRIVE_HIGH, SDA_RELEASE);
i2c_stop_run_reset (sensor_port, I2C_CMD_RUN); // also programs status update
legacy_i2c(1<<sensor_port);// Setup i2c pages for legacy i2c commands. TODO NC393: update for compatibility with 14MPix
camsync_mode.trig = 0;
camsync_mode.trig_set = 1;
camsync_mode.ext = 1; // use external timestamp (default)
......
......@@ -209,7 +209,8 @@ struct sensorproc_t * asensorproc = NULL;
//wait_queue_head_t image_acq_wait_queue; // queue for the sensor frame interrupts
void tasklet_fpga_function(unsigned long arg);
void tasklet_cmdseq_function(unsigned long arg);
void tasklet_compressor_function(unsigned long arg);
/**
* @brief Copy #sensorproc structure, needed for multisensor board to be able
......@@ -241,12 +242,18 @@ struct sensorproc_t * copy_sensorproc (int sensor_port, struct sensorproc_t * co
//
int init_acq_sensor(void); // Never used?
//DECLARE_TASKLET(tasklet_fpga, tasklet_fpga_function, 0); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_fpga_0, tasklet_fpga_function, 0); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_fpga_1, tasklet_fpga_function, 1); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_fpga_2, tasklet_fpga_function, 2); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_fpga_3, tasklet_fpga_function, 3); // 0 - no arguments for now
static struct tasklet_struct *tasklets[SENSOR_PORTS] = {&tasklet_fpga_0, &tasklet_fpga_1, &tasklet_fpga_2, &tasklet_fpga_3};
//DECLARE_TASKLET(tasklet_cmdseq, tasklet_cmdseq_function, 0); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_cmdseq_0, tasklet_cmdseq_function, 0); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_cmdseq_1, tasklet_cmdseq_function, 1); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_cmdseq_2, tasklet_cmdseq_function, 2); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_cmdseq_3, tasklet_cmdseq_function, 3); // 0 - no arguments for now
static struct tasklet_struct *tasklet_cmdseq[SENSOR_PORTS] = {&tasklet_cmdseq_0, &tasklet_cmdseq_1, &tasklet_cmdseq_2, &tasklet_cmdseq_3};
DECLARE_TASKLET(tasklet_compressor_0, tasklet_compressor_function, 0); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_compressor_1, tasklet_compressor_function, 1); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_compressor_2, tasklet_compressor_function, 2); // 0 - no arguments for now
DECLARE_TASKLET(tasklet_compressor_3, tasklet_compressor_function, 3); // 0 - no arguments for now
static struct tasklet_struct *tasklets_compressor[SENSOR_PORTS] = {&tasklet_compressor_0, &tasklet_compressor_1, &tasklet_compressor_2, &tasklet_compressor_3};
/**
......@@ -363,18 +370,17 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
}
/**
* @brief Calculate/update CIRCBUF parameters available after compressor interrupt
* Calculate/update CIRCBUF parameters available after compressor interrupt
*/
inline void update_irq_circbuf(struct jpeg_ptr_t *jptr) {
/*set_globalParam (G_CIRCBUFWP, JPEG_wp<<2);
set_globalParam (G_FREECIRCBUF, (((get_globalParam (G_CIRCBUFRP) <= get_globalParam (G_CIRCBUFWP))? get_globalParam (G_CIRCBUFSIZE):0)+
/*set_globalParam (G_CIRCBUFWP, JPEG_wp<<2);set_globalParam (G_FREECIRCBUF, (((get_globalParam (G_CIRCBUFRP) <= get_globalParam (G_CIRCBUFWP))? get_globalParam (G_CIRCBUFSIZE):0)+
get_globalParam (G_CIRCBUFRP)) - get_globalParam (G_CIRCBUFWP));*/
/* the concept of global parameters will be changed, use one channel only for testing */
set_globalParam(jptr->chn_num, G_CIRCBUFWP, jptr->jpeg_wp);
set_globalParam (jptr->chn_num, G_FREECIRCBUF, (((get_globalParam (jptr->chn_num, G_CIRCBUFRP) <= get_globalParam (jptr->chn_num, G_CIRCBUFWP))? get_globalParam (jptr->chn_num, G_CIRCBUFSIZE):0)+
set_globalParam (jptr->chn_num, G_FREECIRCBUF,
(((get_globalParam (jptr->chn_num, G_CIRCBUFRP) <= get_globalParam (jptr->chn_num, G_CIRCBUFWP))?get_globalParam (jptr->chn_num, G_CIRCBUFSIZE):0)+
get_globalParam (jptr->chn_num, G_CIRCBUFRP)) - get_globalParam (jptr->chn_num, G_CIRCBUFWP));
}
/**
* @brief Calculate/update focus parameters available after compressor interrupt
* NOTE: currently global (latest), not per-frame
......@@ -432,7 +438,7 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr)
interframe->signffff = 0xffff;
/* debug code follows */
set_default_interframe(interframe);
set_default_interframe(interframe); // TODO: Production NC393: should be removed?
/* end of debug code */
set_globalParam(jptr->chn_num, G_FRAME_SIZE, jpeg_len);
......@@ -588,7 +594,7 @@ inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, ///< pointer
}
PROFILE_NOW(1);
wake_up_interruptible(&framepars_wait_queue); // all interrupts, not just frames acquired
tasklet_schedule(&tasklet_fpga); // trigger software interrupt
tasklet_schedule(&tasklet_cmdseq); // trigger software interrupt
EN_INTERRUPT(SMART);
......@@ -616,8 +622,8 @@ static irqreturn_t frame_sync_irq_handler(int irq, void *dev_id)
updateFramePars (jptr->chn_num,
frame16);
wake_up_interruptible(&aframepars_wait_queue[jptr->chn_num]);
// tasklet_schedule(&tasklet_fpga);
tasklet_schedule(tasklets[jptr->chn_num]);
// tasklet_schedule(&tasklet_cmdseq);
tasklet_schedule(tasklet_cmdseq[jptr->chn_num]);
x393_cmdframeseq_ctrl(cmdframeseq_mode, jptr->chn_num);
local_irq_restore(flags);
return IRQ_HANDLED;
......@@ -640,21 +646,27 @@ static irqreturn_t compressor_irq_handler(int irq, void *dev_id)
unsigned long flags;
local_irq_save(flags);
if (updateIRQJPEG_wp(jptr)) {
update_irq_circbuf(jptr);
updateIRQFocus(jptr);
interframe = updateIRQ_interframe(jptr);
updateIRQ_Exif(jptr, interframe);
if (updateIRQJPEG_wp(jptr)) { // Updates write pointer, invalidates cache, calculates absolute frame number (compressed)
update_irq_circbuf(jptr); // Update global parameters (accessible over mmap): G_CIRCBUFWP, G_FREECIRCBUF (depends on user-set G_CIRCBUFRP)
updateIRQFocus(jptr); // Reads FPGA and updates both G_GFOCUS_VALUE and P_FOCUS_VALUE
interframe = updateIRQ_interframe(jptr); // updates SOME data in the 32-byte gaps between the images:
// Calculates frame size, adds 0xffff signature to detect buffer overrun
// invalidates cache
updateIRQ_Exif(jptr, interframe); // Updates Exif data for compressed frame (separate ring buffer), extending interframe data
frame16 = getHardFrameNumber(jptr->chn_num, 1); // Use compressor frame number
// Updarte G_COMPRESSOR_FRAME (from jptr->frame, set other interframe data from past parameters (subset of all parameters preserved after the frame)
updateInterFrame(jptr->chn_num, // Sensor port number (0..3)
frame16, // number of frame just compressed (lower 4 bits, from FPGA), always >= sensor frame number,
jptr->frame, // absolute compressed frame number, updated in updateIRQJPEG_wp
// interrupt should be processed after frame sync interrupt
interframe); // pointer to the area in circbuf to save parameters
wake_up_interruptible(&circbuf_wait_queue);
tasklet_schedule(tasklets_compressor[jptr->chn_num]);
// wake_up_interruptible(&circbuf_wait_queue); // should be done in tasklet (after cache invalidation)
}
//wake_up_interruptible(&framepars_wait_queue);
// tasklet_schedule(&tasklet_fpga);
tasklet_schedule(tasklets[jptr->chn_num]);
// tasklet_schedule(&tasklet_cmdseq);
// tasklet_schedule(tasklets_compressor[jptr->chn_num]);
irq_ctrl.interrupt_cmd = IRQ_CLEAR;
x393_cmprs_interrupts(irq_ctrl, jptr->chn_num);
local_irq_restore(flags);
......@@ -668,6 +680,35 @@ static irqreturn_t compressor_irq_handler(int irq, void *dev_id)
* @param arg not used
*/
void tasklet_compressor_function(unsigned long arg)
{
dma_addr_t phys_addr_start, phys_addr_end;
void *virt_addr_start;
int sensor_port = image_acq_priv.jpeg_ptr[arg].chn_num; // == arg & 3
const struct jpeg_ptr_t *jptr = &image_acq_priv.jpeg_ptr[arg];
unsigned int sz;
/* invalidate L2 cache lines in the beginning of current frame */
phys_addr_start = circbuf_priv_ptr[jptr->chn_num].phys_addr + DW2BYTE(jptr->fpga_cntr_prev);
virt_addr_start = circbuf_priv_ptr[jptr->chn_num].buf_ptr + jptr->fpga_cntr_prev;
sz = DW2BYTE(jptr->fpga_cntr_prev) + L2_INVAL_SIZE;
if (sz < CCAM_DMA_SIZE) {
phys_addr_end = phys_addr_start + L2_INVAL_SIZE - 1;
outer_inv_range(phys_addr_start, phys_addr_end);
__cpuc_flush_dcache_area(virt_addr_start, L2_INVAL_SIZE);
} else {
phys_addr_end = phys_addr_start + (CCAM_DMA_SIZE - DW2BYTE(jptr->fpga_cntr_prev) - 1);
outer_inv_range(phys_addr_start, phys_addr_end);
__cpuc_flush_dcache_area(virt_addr_start, CCAM_DMA_SIZE - DW2BYTE(jptr->fpga_cntr_prev));
phys_addr_start = circbuf_priv_ptr[jptr->chn_num].phys_addr;
phys_addr_end = phys_addr_start + (sz - CCAM_DMA_SIZE - 1);
virt_addr_start = circbuf_priv_ptr[jptr->chn_num].buf_ptr;
outer_inv_range(phys_addr_start, phys_addr_end);
__cpuc_flush_dcache_area(virt_addr_start, sz - CCAM_DMA_SIZE);
}
wake_up_interruptible(&circbuf_wait_queue); // should be done in here (after cache invalidation), not in ISR
}
/*!TODO:
implement 2 modes of controlling when to calculate histograms:
......@@ -686,7 +727,7 @@ For displaying histograms - try use latest available - not waiting fro a particu
// HISTOGRAMS_WAKEUP_ALWAYS if 0 will only wakeup processes waiting for histograms when they become available, maybe never if they are disabled
// if defined 1 - will wakeup each frame, regardless of the availability of the histograms
//#define HISTOGRAMS_WAKEUP_ALWAYS 0
void tasklet_fpga_function(unsigned long arg)
void tasklet_cmdseq_function(unsigned long arg)
{
// int is_compressor_irq = 1; // TODO: add interrupts from frame sync if compressor is off
int hist_en;
......@@ -696,31 +737,12 @@ void tasklet_fpga_function(unsigned long arg)
unsigned long prevFrameNumber=thisFrameNumber-1;
unsigned long * hash32p=&(aframepars[sensor_port][(thisFrameNumber-1) & PARS_FRAMES_MASK].pars[P_GTAB_R]); // same gamma for all sub-channels
unsigned long * framep= &(aframepars[sensor_port][(thisFrameNumber-1) & PARS_FRAMES_MASK].pars[P_FRAME]);
const struct jpeg_ptr_t *jptr = &image_acq_priv.jpeg_ptr[arg];
dma_addr_t phys_addr_start, phys_addr_end;
void *virt_addr_start;
unsigned int sz;
// const struct jpeg_ptr_t *jptr = &image_acq_priv.jpeg_ptr[arg];
// dma_addr_t phys_addr_start, phys_addr_end;
// void *virt_addr_start;
// unsigned int sz;
int subchn,hist_indx;
/* invalidate L2 cache lines in the beginning of current frame */
phys_addr_start = circbuf_priv_ptr[jptr->chn_num].phys_addr + DW2BYTE(jptr->fpga_cntr_prev);
virt_addr_start = circbuf_priv_ptr[jptr->chn_num].buf_ptr + jptr->fpga_cntr_prev;
sz = DW2BYTE(jptr->fpga_cntr_prev) + L2_INVAL_SIZE;
if (sz < CCAM_DMA_SIZE) {
phys_addr_end = phys_addr_start + L2_INVAL_SIZE - 1;
outer_inv_range(phys_addr_start, phys_addr_end);
__cpuc_flush_dcache_area(virt_addr_start, L2_INVAL_SIZE);
} else {
phys_addr_end = phys_addr_start + (CCAM_DMA_SIZE - DW2BYTE(jptr->fpga_cntr_prev) - 1);
outer_inv_range(phys_addr_start, phys_addr_end);
__cpuc_flush_dcache_area(virt_addr_start, CCAM_DMA_SIZE - DW2BYTE(jptr->fpga_cntr_prev));
phys_addr_start = circbuf_priv_ptr[jptr->chn_num].phys_addr;
phys_addr_end = phys_addr_start + (sz - CCAM_DMA_SIZE - 1);
virt_addr_start = circbuf_priv_ptr[jptr->chn_num].buf_ptr;
outer_inv_range(phys_addr_start, phys_addr_end);
__cpuc_flush_dcache_area(virt_addr_start, sz - CCAM_DMA_SIZE);
}
// Time is out?
if ((getThisFrameNumber(sensor_port) ^ getHardFrameNumber(sensor_port, 0)) & PARS_FRAMES_MASK) {
......@@ -878,7 +900,7 @@ void compressor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt e
x393_cmprs_interrupts_t irq_ctrl = {.d32=0};
//MDF2(printk ("compressor_interrupts(%d)\n",on));
dev_dbg(g_dev_ptr, "set camera interrupts status: %d\n", on);
dev_dbg(g_dev_ptr, "Set compressor interrupts for channel %d: %d\n",chn, on);
#ifdef TEST_DISABLE_CODE
if (on) {
EN_INTERRUPT(SMART);
......@@ -1054,7 +1076,6 @@ int image_acq_stop(struct platform_device *pdev)
{
return 0;
}
//#define I2C359_INC 2 ///< slave address increment between sensors in 10359A board (broadcast, 1,2,3)
/** Register i2c pages equal to slave address,
* Use to convert 353 code */
......@@ -1068,7 +1089,9 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
class_sensor= xi2c_dev_get(name_sensor);
BUG_ON(!class_sensor);
memcpy(&dev_sensor, class_sensor, sizeof(x393_i2c_device_t));
for (sensor_port=1; sensor_port< SENSOR_PORTS; sensor_port++) if (ports & (1 << sensor_port)) {
dev_dbg(g_dev_ptr, "Initializing sensor i2c for legacy commands, ports bit-mask= 0x%x\n",ports);
for (sensor_port=0; sensor_port< SENSOR_PORTS; sensor_port++) if (ports & (1 << sensor_port)) {
i2c_page_alloc_init(sensor_port); // reset all pages allocation
i2c_page_register(sensor_port, class_10359->slave7);
set_xi2c_wrc(class_10359, sensor_port, class_10359->slave7, 0);
for (subchn = 0; subchn <4; subchn++){ // subchn == 0 - broadcast
......@@ -1078,9 +1101,12 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
}
// Now register one page for reading 10359 and the sensor using sensor speed data
memcpy(&dev_sensor, class_sensor, sizeof(x393_i2c_device_t)); // dev_sensor));
i2c_page_register(sensor_port, LEGACY_READ_PAGE2);
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE2);
i2c_page_register(sensor_port, LEGACY_READ_PAGE4);
dev_sensor.data_bytes=4; // for reading 10359 in 32-bit mode
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4);
dev_dbg(g_dev_ptr, "Initialized sensor i2c for legacy commands, sensor_port= 0x%x\n",sensor_port);
}
return 0;
/*
......@@ -1092,9 +1118,6 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
invalid type argument of unary '*' (have 'x393_i2c_device_t {aka struct <anonymous>}')
*/
}
//static const struct of_device_id elphel393_sensor_of_match[] = {
// { .compatible = "elphel,elphel393-sensor-1.00" },
// { /* end of list */ }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -34,7 +34,7 @@ typedef struct{
u8 data_bytes; ///< Number of data bytes (1..10), for writes it includes register address bytes
int scl_khz; ///< maximal SCL frequency in KHz (currently limited by 200KHz slowest)
} x393_i2c_device_t;
void i2c_page_alloc_init( int chn); // reset page allocation for selscted channel
int i2c_stop_run_reset(int chn, int cmd);
int i2c_drive_mode (int chn, int sda_drive_high, int sda_release);
int read_xi2c_frame (int chn);
......
......@@ -79,6 +79,9 @@ int setup_sensor_memory (int num_sensor, ///< sensor port number (0..3)
window_width_height.height = window_height;
window_left_top.left = window_left;
window_left_top.top = window_top;
dev_dbg(g_dev_ptr,"{%d} frame16=%d, command=%d\n",num_sensor,frame16, (int) x393cmd);
dev_dbg(g_dev_ptr,"sa=0x%08x sa_inc=0x%08x lfn=0x%08x fw=0x%08x wh=0x%08x lt=0x%08x\n",
window_frame_sa.d32,window_frame_sa_inc.d32, window_last_frame_num, window_full_width.d32,window_width_height.d32,window_left_top.d32);
switch (x393cmd){
case ASAP:
......@@ -210,6 +213,10 @@ int setup_compressor_memory (int num_sensor, ///< sensor port number (0..3
window_tile_whs.vert_step = tile_vstep;
window_tile_whs.tile_height = tile_height;
dev_dbg(g_dev_ptr,"{%d} frame16=%d, command=%d\n",num_sensor,frame16, (int) x393cmd);
dev_dbg(g_dev_ptr,"sa=0x%08x sa_inc=0x%08x lfn=0x%08x fw=0x%08x wh=0x%08x lt=0x%08x whs=0x%08x\n",
window_frame_sa.d32,window_frame_sa_inc.d32, window_last_frame_num.d32, window_full_width.d32,window_width_height.d32,window_left_top.d32, window_tile_whs.d32);
switch (x393cmd){
case ASAP:
frame16 = 0;
......
......@@ -90,6 +90,7 @@
#define DEV393_DETECT_SENSORS ("detect_sensors", "detect_sensors",143, 1, "0666", "c") ///< Probably not needed, only sysfs is used
#define DEV393_I2C_SENSORS ("", "elphel393-sensor-i2c",-1, -1, "0666", "c") ///< Used only in sysfs, no character device (yet?)
#define DEV393_MT9X001 ("", "elphel393-mt9x001", -1, -1, "0666", "c") ///< Used only in sysfs, no character device (yet?)
#define _DEV393_PATH(n, ...) "/dev/"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