Commit 406266d1 authored by Andrey Filippov's avatar Andrey Filippov

just debugging

parent 9f42f3da
......@@ -706,7 +706,18 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
case LSEEK_CIRC_UTIME:
return get_rtc_usec();
break;
default:
// New in NC393 - separate comressor interrupts
case LSEEK_INTERRUPT_OFF: // disable camera interrupts
dev_dbg(g_dev_ptr, "LSEEK_INTERRUPT_OFF\n");
compressor_interrupts(0,chn);
break;
case LSEEK_INTERRUPT_ON: // enable camera interrupts
dev_dbg(g_dev_ptr, "LSEEK_INTERRUPT_ON\n");
compressor_interrupts(1,chn);
break;
default: // offset >=32
if ((offset & ~0x1f)==LSEEK_DAEMON_CIRCBUF) {
wait_event_interruptible(circbuf_wait_queue, get_imageParamsThis(chn, P_DAEMON_EN) & (1<<(offset & 0x1f)));
}
......
......@@ -153,7 +153,7 @@ int get_detected_sensor_code(int port, ///< Sensor port number (0..3)
return SENSOR_NONE;
}
/** Gert configured sensorport subchannels */
/** Get configured sensor port subchannels */
int get_subchannels(int port) ///< Sensor port
///< @return bitmask of available channels
{
......
......@@ -21,11 +21,10 @@
//copied from cxi2c.c - 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> // div for 64
#include <asm/div64.h> // div for 64
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/sched.h>
......@@ -38,6 +37,7 @@
//#include <linux/autoconf.h>
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
//#include <asm/system.h>
//#include <asm/byteorder.h> // endians
......@@ -64,7 +64,7 @@
//#include "cci2c.h" // to use void i2c_reset_wait(void), reset shadow static 'i2c_hardware_on'
#include "x393_macro.h"
#include "x393.h"
#include "sensor_i2c.h" // read_xi2c_frame()
/**
* \def MDF1(x) optional debug output
*/
......@@ -122,8 +122,9 @@
/* 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; // set to 0 at startup, 1 after initialization that is triggered by setParsAtomic()
unsigned long 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)
#ifdef NC353
struct framepars_all_t *frameparsall = NULL; // - will be mmap-ed
......@@ -146,7 +147,7 @@ unsigned long *amultiSensRvrsIndex[SENSOR_PORTS]; // reverse index (t
wait_queue_head_t aframepars_wait_queue[SENSOR_PORTS];// used to wait for the frame to be acquired
/* Remove after compilation OK */
struct sensorproc_t * sensorproc = NULL;
//struct sensorproc_t * sensorproc = NULL;
//void compressor_interrupts (int on) {}
#if 0
#define wait_event_interruptible(wq, condition) \
......@@ -214,27 +215,38 @@ void initSequencers(int sensor_port)
{
unsigned long flags;
MDF2(printk("\n"));
printk("initSequencers:resetting both sequencers\n");
dev_dbg(g_devfp_ptr,"%s \n",__func__);
dev_dbg(g_devfp_ptr,"%s : port= %d,initSequencers:resetting both sequencers (not really?)\n",__func__, sensor_port);
#ifdef TEST_DISABLE_CODE
local_irq_save(flags);
X3X3_SEQ_RESET;
i2c_reset_wait();
local_irq_restore(flags);
initFramePars();
#endif
initFramePars(sensor_port);
}
/**
* @brief reset absolute frame number \b thisFrameNumber to \b frame8
* @param sensor_port sensor port number (0..3)
*/
void resetFrameNumber(int sensor_port)
/** Reset absolute frame number \b thisFrameNumber to \b frame16, optionally reset/restart sequencer */
void resetFrameNumber(int sensor_port, ///< sensor_port sensor port number (0..3)
u32 aframe, ///< absolute frame number to set (lower 4 bits will be set from hardware)
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};
u32 frame16;
// TODO: Add locking for sequence reset?
if (hreset){
cmdframeseq_mode.reset = 1;
x393_cmdframeseq_ctrl(cmdframeseq_mode, sensor_port);
udelay(2);
cmdframeseq_mode.d32 = 0;
cmdframeseq_mode.run_cmd = 3; // Run
x393_cmdframeseq_ctrl(cmdframeseq_mode, sensor_port);
}
/* Check if the status update mode for command sequencer is not 3 (auto), set/wait if needed */
stat_ctrl = get_x393_cmdseqmux_status_ctrl();
if (stat_ctrl.mode !=3) {
......@@ -251,17 +263,21 @@ void resetFrameNumber(int sensor_port)
stat = x393_cmdseqmux_status();
}
switch (sensor_port) {
case 0: thisFrameNumber(sensor_port) = stat.frame_num0; break;
case 1: thisFrameNumber(sensor_port) = stat.frame_num1; break;
case 2: thisFrameNumber(sensor_port) = stat.frame_num2; break;
case 3: thisFrameNumber(sensor_port) = stat.frame_num3; break;
// case 0: thisFrameNumber(sensor_port) = stat.frame_num0; break;
case 0: frame16 = stat.frame_num0; break;
case 1: frame16 = stat.frame_num1; break;
case 2: frame16 = stat.frame_num2; break;
default:
frame16 = stat.frame_num3; break;
}
thisFrameNumber(sensor_port) = (aframe & PARS_FRAMES_MASK) | frame16;
#ifdef NC353
thisFrameNumber(sensor_port) = X3X3_I2C_FRAME;
#endif
MDF2(printk(" thisFrameNumber=0x%lx\n", thisFrameNumber(sensor_port)));
dev_dbg(g_devfp_ptr,"%s : port= %d, thisFrameNumber=0x%lx\n",__func__, 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 = 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;
}
/**
......@@ -271,20 +287,20 @@ void resetFrameNumber(int sensor_port)
void initFramePars(int sensor_port)
{
int i;
memset(aframepars[sensor_port], 0, sizeof(struct framepars_t) * PARS_FRAMES);
resetFrameNumber(sensor_port);
resetFrameNumber(sensor_port, 0, 1);
// initialize frameParsDeps.pars masks:
for (i = 0; i < (sizeof(param_depend_tab) / 8); i++) {
afuncs2call[sensor_port][param_depend_tab[2 * i] & 0xffff] = param_depend_tab[2 * i + 1]; // remove possible flags
MDF2(printk("funcs2call[0x%lx]=0x%08lx\n", param_depend_tab[2 * i] & 0xffff, param_depend_tab[2 * i + 1]));
dev_dbg(g_devfp_ptr,"%s : port= %d, funcs2call[0x%lx]=0x%08lx\n",__func__, sensor_port, param_depend_tab[2 * i] & 0xffff, param_depend_tab[2 * i + 1]);
}
for (i = 0; i < P_SENSOR_NUMREGS; i++) afuncs2call[sensor_port][P_SENSOR_REGS + i] = ONCHANGE_SENSORREGS; // by default each "manual" write to any of 256 registers will trigger pgm_sensorreg function
// Same for 10359 registers - will not change anything if there is no 10359 - these registers will not be changed, and if will be it wil cause no action
for (i = 0; i < P_M10359_NUMREGS; i++) afuncs2call[sensor_port][P_M10359_REGS + i] = ONCHANGE_SENSORREGS; // by default each "manual" write to any of 256 registers will trigger pgm_sensorreg function
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 = 1;
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]);
}
/**
......@@ -295,7 +311,7 @@ void initGlobalPars(int sensor_port)
{
memset(&aglobalPars[sensor_port][GLOBALS_PRESERVE], 0, (NUM_GPAR - GLOBALS_PRESERVE) * sizeof(unsigned long));
// MDF(GLOBALPARS(G_DEBUG) = ELPHEL_DEBUG_STARTUP;// removed - add write to fpga init script
MDF(printk("GLOBALPARS(0,G_DEBUG)=%lx\n", GLOBALPARS(0,G_DEBUG)));
dev_dbg(g_devfp_ptr,"%s : port= %d, GLOBALPARS(0,G_DEBUG)=%lx\n",__func__, sensor_port, GLOBALPARS(0,G_DEBUG));
}
/**
......@@ -316,11 +332,11 @@ int initMultiPars(int sensor_port)
GLOBALPARS(sensor_port,G_MULTI_NUM) = 0;
for (i = 0; i < 8; i++) {
m = GLOBALPARS(sensor_port, G_MULTI_REGSM + i); // 1 bit per register that need individual shadows
// MDF(printk("i=%d, m=0x%lx\n",i,m));
// dev_dbg(g_devfp_ptr,"%s i=%d, m=0x%lx\n",__func__,i,m);
for (j = P_SENSOR_REGS + (i << 5); m && (GLOBALPARS(sensor_port,G_MULTI_NUM) < P_MULTI_NUMREGS); j++, m >>= 1) {
if (m & 1) {
amultiSensIndex[j] = ireg;
// MDF(printk("j=0x%x ireg=0x%x\n",j,ireg));
amultiSensIndex[sensor_port][j] = ireg;
// dev_dbg(g_devfp_ptr,"%s j=0x%x ireg=0x%x\n",__func__,j,ireg);
for (n = 0; n < MAX_SENSORS; n++) {
afuncs2call[sensor_port][ireg] = ONCHANGE_SENSORREGS; // by default each "manual" write to any of these registers will trigger pgm_sensorreg function
amultiSensRvrsIndex[sensor_port][ireg++] = j | ((n + 1) << 16);
......@@ -331,7 +347,7 @@ int initMultiPars(int sensor_port)
}
// remark: the line below is called from initFramePars, consider removing it
for (i = 0; i < P_SENSOR_NUMREGS; i++) afuncs2call[sensor_port][P_SENSOR_REGS + i] = ONCHANGE_SENSORREGS; // by default each "manual" write to any of 256 registers will trigger pgm_sensorreg function
MDF(printk("GLOBALPARS(G_MULTI_NUM)=%lx\n", GLOBALPARS(sensor_port, G_MULTI_NUM)));
dev_dbg(g_devfp_ptr,"%s : port= %d, GLOBALPARS(G_MULTI_NUM)=%lx\n",__func__, sensor_port, GLOBALPARS(sensor_port, G_MULTI_NUM));
return GLOBALPARS(sensor_port, G_MULTI_NUM);
}
......@@ -414,10 +430,40 @@ inline void set_imageParamsR_all(int sensor_port, int n, unsigned long
int i;
for (i = 0; i < PARS_FRAMES; i++) aframepars[sensor_port][i].pars[n] = d;
}
/**
* Update "interframe" parameters (inside the circular buffer). Called from ISR (comressor done)
* @param sensor_port - sensor
* @param frame16
* @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
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 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;
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
// memcpy(interframe_pars, &framepars[findex_this].pars[P_GTAB_R], 24); // will leave some gaps, but copy [P_ACTUAL_WIDTH]
memcpy(interframe_pars, &apastpars[sensor_port][pastParsIndex].past_pars[P_GTAB_R-PARS_SAVE_FROM], 24); // will leave some gaps, but copy [P_ACTUAL_WIDTH]
interframe_pars->height = apastpars[sensor_port][pastParsIndex].past_pars[P_ACTUAL_HEIGHT-PARS_SAVE_FROM]; // NOTE: P_ACTUAL_WIDTH,P_QUALITY copied with memcpy
interframe_pars->color = apastpars[sensor_port][pastParsIndex].past_pars[P_COLOR-PARS_SAVE_FROM];
interframe_pars->byrshift = apastpars[sensor_port][pastParsIndex].past_pars[P_COMPMOD_BYRSH-PARS_SAVE_FROM];
interframe_pars->quality2 |= (apastpars[sensor_port][pastParsIndex].past_pars[P_PORTRAIT-PARS_SAVE_FROM] & 1) << 7;
}
//++++++++++++++++++++++++++++++++++++++++++
/*!
* @brief called from ISR - advance thisFrameNumber to match hardware frame8, copy parameters as needed.
/** Called from ISR (sensor frame interrupt)- advance thisFrameNumber to match hardware frame16, copy parameters as needed.
* before: (thisFrameNumber mod8 pointed to current (for the software) parameters frame (now behind by at least 1, maybe 2)
* (thisFrameNumber-1) mod 8 - oldest with parameters preserved, also containes histograms results (+image timestamp, size?)
* subset of that frame data is copied to pastpars
......@@ -427,23 +473,29 @@ inline void set_imageParamsR_all(int sensor_port, int n, unsigned long
* @param interframe_pars pointer to structure (between frames in the frame buffer) to save a pointer to past parameters
* pass NULL if compressor was off (or no time to copy?)
*/
void updateFramePars(int sensor_port, int frame8, struct interframe_params_t * interframe_pars)
//TODO: Remove interframe, handle it with compressor interrupts (above)
void updateFramePars(int sensor_port, int frame16)
{
int findex_this, findex_prev, findex_future, findex_next;
int index, index32;
unsigned long bmask, bmask32;
int pastParsIndex;
struct framepars_t *framepars = aframepars[sensor_port];
// If interrupt was from compression done (circbuf advanced, interframe_pars!=null), the frame8 (hardware) maybe not yet advanced
// If interrupt was from compression done (circbuf advanced, interframe_pars!=null), the frame16 (hardware) maybe not yet advanced
// We can fix it here, but it will not work if some frames were not processed in time
if ((interframe_pars != NULL) && (((frame8 ^ thisFrameNumber(sensor_port)) & PARS_FRAMES_MASK) == 0)) {
findex_this = frame8 & PARS_FRAMES_MASK;
#ifdef NC353
if ((interframe_pars != NULL) && (((frame16 ^ thisFrameNumber(sensor_port)) & PARS_FRAMES_MASK) == 0)) {
findex_this = frame16 & PARS_FRAMES_MASK;
/* 393 TODO: Check what to do with P_IRQ_SMART */
if (framepars[findex_this].pars[P_IRQ_SMART] & 4) frame8 = (frame8 + 1) & PARS_FRAMES_MASK; // verify that this mode is enabled (together with bit0)
if (framepars[findex_this].pars[P_IRQ_SMART] & 4) frame16 = (frame16 + 1) & PARS_FRAMES_MASK; // verify that this mode is enabled (together with bit0)
}
while ((frame8 ^ thisFrameNumber(sensor_port)) & PARS_FRAMES_MASK) {
#endif
dev_dbg(g_devfp_ptr,"%s : port= %d, frame16=%d\n",__func__, sensor_port, frame16);
while ((frame16 ^ thisFrameNumber(sensor_port)) & PARS_FRAMES_MASK) {
dev_dbg(g_devfp_ptr,"%s : port= %d, frame16=%d, thisFrameNumber(sensor_port)\n",__func__, sensor_port, frame16, (int)thisFrameNumber(sensor_port));
// before update:
// framepars[findex_prev] holds previous frame data (oldest availble)
// framepars[findex_future] holds farthest in the future one
......@@ -461,6 +513,7 @@ void updateFramePars(int sensor_port, int frame8, struct interframe_params_t * i
// memcpy (pastpars[pastParsIndex].past_pars, &framepars[findex_prev].pars[PARS_SAVE_FROM], sizeof(pastpars[0].past_pars));
memcpy(apastpars[sensor_port][pastParsIndex].past_pars, &framepars[findex_prev].pars[PARS_SAVE_FROM], PARS_SAVE_COPY * sizeof(int));
// Now update interframe_pars (interframe area) used to create JPEG headers. Interframe area survives exactly as long as the frames themselves (not like pastpars)
#ifdef NC353
if (interframe_pars) { // frame was compressed, not just vsync
//TODO: get rid of *_prev, use it for the future.
memcpy(interframe_pars, &framepars[findex_this].pars[P_GTAB_R], 24); // will leave some gaps, but copy [P_ACTUAL_WIDTH]
......@@ -469,15 +522,16 @@ void updateFramePars(int sensor_port, int frame8, struct interframe_params_t * i
interframe_pars->byrshift = framepars[findex_this].pars[P_COMPMOD_BYRSH];
interframe_pars->quality2 |= (framepars[findex_this].pars[P_PORTRAIT] & 1) << 7;
}
#endif
// copy parameters from findex_future (old "farthest in the future") to findex_prev (new "fartherst in the future") if it was changed since
if ((bmask32 = framepars[findex_prev].modsince32)) {
MDF7(printk("framepars[%d].modsince32=0x%lx\n", findex_prev, bmask32));
dev_dbg(g_devfp_ptr,"%s framepars[%d].modsince32=0x%lx\n",__func__, findex_prev, bmask32);
for (index32 = 0; bmask32; index32++, bmask32 >>= 1) {
if (bmask32 & 1) {
for (index = (index32 << 5), bmask = framepars[findex_prev].modsince[index32]; bmask; index++, bmask >>= 1)
if (bmask & 1) {
framepars[findex_prev].pars[index] = framepars[findex_future].pars[index];
MDF7(printk("hw=%d framepars[%d].pars[%d]=framepars[%d].pars[%d]=0x%lx\n", frame8, findex_prev, index, findex_future, index, framepars[findex_future].pars[index]));
dev_dbg(g_devfp_ptr,"%s hw=%d framepars[%d].pars[%d]=framepars[%d].pars[%d]=0x%lx\n",__func__, frame16, findex_prev, index, findex_future, index, framepars[findex_future].pars[index]);
}
framepars[findex_prev].modsince[index32] = 0; // mark as not "modified since" (yet)
}
......@@ -503,9 +557,9 @@ void updateFramePars(int sensor_port, int frame8, struct interframe_params_t * i
framepars[findex_next].mod32 |= framepars[findex_this].mod32;
}
}
MDF7(printk("resubmitting past due functions = 0x%lx for frame=%ld (0x%x)\n", framepars[findex_this].functions, thisFrameNumber(sensor_port), findex_this));
dev_dbg(g_devfp_ptr,"%s resubmitting past due functions = 0x%lx for frame=%ld (0x%x)\n",__func__, framepars[findex_this].functions, thisFrameNumber(sensor_port), findex_this);
} else {
MDF(printk("Ignored past due functions = 0x%lx for frame=%ld (0x%x)\n", framepars[findex_this].functions, thisFrameNumber(sensor_port), findex_this));
dev_dbg(g_devfp_ptr,"%s Ignored past due functions = 0x%lx for frame=%ld (0x%x)\n",__func__, framepars[findex_this].functions, thisFrameNumber(sensor_port), findex_this);
}
}
thisFrameNumber(sensor_port)++;
......@@ -517,12 +571,12 @@ void updateFramePars(int sensor_port, int frame8, struct interframe_params_t * i
* 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 frame8
* @param frame16
*/
inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, int frame8)
inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, int frame16)
{
unsigned long todo, mask, remain;
int pars_ahead; // considering parameter "pars_ahead" of the (frame8+job_ahead) mod 8
int pars_ahead; // considering parameter "pars_ahead" of the (frame16+job_ahead) mod 8
int frame_proc; // current frame for which parameters are considered
struct framepars_t * procpars;
struct framepars_t * prevpars; // maybe - drop calculation for each function, move it to pgm_* where needed?
......@@ -533,14 +587,20 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
#if ELPHEL_DEBUG
unsigned long allfunctions = 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 (allfunctions) MDF6(printk("frame8=%d, functions: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", frame8, framepars[0].functions,
if (allfunctions) MDF6(printk("frame16=%d, functions: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", frame16, framepars[0].functions,
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 (!sensorproc){
dev_err(g_devfp_ptr,"%s port=%d frame16=%d sensorproc==NULL !!!! \n", __func__, sensor_port, frame16);
return;
}
// do all ASAP tasks (they should not be done ahead of the corresponding interrupt!)
// Now try overdue functions with latencies >=1 and try them in ASAP mode
for (pars_ahead = 0; pars_ahead <= 4; pars_ahead++ ) {
frame_proc = (frame8 + pars_ahead) & PARS_FRAMES_MASK;
frame_proc = (frame16 + pars_ahead) & PARS_FRAMES_MASK;
procpars = &framepars[frame_proc];
prevpars = &framepars[(frame_proc - 1) & PARS_FRAMES_MASK];
i = 0;
......@@ -556,28 +616,31 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
remain <<= 1;
}
// now (todo & mask) !=0
MDF6(printk(" todo=0x%08lx (curr=0x%08lx) frame8=%d, pars_ahead=%d, frame_proc=%d i=%d, mask=0x%08lx\n",
todo, procpars->functions, frame8, pars_ahead, frame_proc, i, mask));
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]);
MDF6(printk(" %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
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));
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);
} else rslt = 0; // only sensor-specific function, nothing to do common to all sensors
if ((rslt >= 0) && (sensorproc->pgm_func[i + 32])) { // sensor - specific functions, called after the main ones
dev_dbg(g_devfp_ptr,"port= %d, Calling SENSOR-SPECIFIC pgm_func[%d] ASAP\n",sensor_port,i);
rslt = sensorproc->pgm_func[i + 32] (sensor_port, &(sensorproc->sensor), procpars, prevpars, -1);
}
// Nothing to do with errors here - just report?
if (rslt < 0) printk("%s:%d:%s - error=%d", __FILE__, __LINE__, __FUNCTION__, rslt);
if (rslt < 0) dev_warn(g_devfp_ptr,"%s:%d:%s - error=%d", __FILE__, __LINE__, __FUNCTION__, rslt);// Nothing to do with errors here - just report?
procpars->functions &= ~mask;
MDF6(printk(".functions=0x%08lx)\n", procpars->functions));
dev_dbg(g_devfp_ptr,"%s : port= %d, .functions=0x%08lx)\n",__func__, sensor_port, procpars->functions);
i++;
mask <<= 1;
remain <<= 1;
}
}
dev_dbg(g_devfp_ptr,"%s port=%d DONE\n", __func__, sensor_port);
}
// Next 5 should go in that sequence
//#define G_CALLNASAP 119 // bitmask - what functions can be used not only in the current frame (ASAP) mode
......@@ -587,11 +650,11 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
//#define G_CALLNEXT4 123 // bitmask of actions to be four or more frames ahead of the programmed one
inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead)
inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, int frame16, int maxahead)
{
unsigned long todo, mask, remain;
int job_ahead; // doing job "job_ahead" ahead of needed
int pars_ahead; // considering parameter "pars_ahead" of the (frame8+job_ahead) mod 8
int pars_ahead; // considering parameter "pars_ahead" of the (frame16+job_ahead) mod 8
int frame_proc; // current frame for which parameters are considered
struct framepars_t * procpars;
struct framepars_t * prevpars; // maybe - drop calculation for each function, move it to pgm_* where needed?
......@@ -602,6 +665,7 @@ 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);
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
......@@ -611,14 +675,14 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
for (job_ahead = 0; job_ahead <= maxahead; job_ahead++ ) {
max_par_ahead = min(5, (PARS_FRAMES - 3) - job_ahead);
for (pars_ahead = 0; pars_ahead < max_par_ahead; pars_ahead++ ) {
frame_proc = (frame8 + job_ahead + pars_ahead + 1) & PARS_FRAMES_MASK; //
frame_proc = (frame16 + job_ahead + pars_ahead + 1) & PARS_FRAMES_MASK; //
procpars = &framepars[frame_proc];
// Check if at least one function is needed for frame_proc
if (procpars->functions &
p_nasap[pars_ahead] & //all, *1, *2,*3,*4 - for all will have G_CALLNASAP twice
p_nasap[0]) {
prevpars = &framepars[(frame_proc - 1) & PARS_FRAMES_MASK];
// seq_frame= (frame8+job_ahead+1) & PARS_FRAMES_MASK;
// seq_frame= (frame16+job_ahead+1) & PARS_FRAMES_MASK;
i = 0;
mask = 1;
remain = 0xffffffff;
......@@ -633,23 +697,27 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
// now (todo & mask) !=0
// find the right latency
for (this_ahead = 1; (p_nasap[this_ahead] & todo & mask) && (this_ahead <= 4); this_ahead++) ; // this_ahead==1..5
// seq_frame= (frame8 + job_ahead + this_ahead) & PARS_FRAMES_MASK;
// seq_frame= (frame16 + job_ahead + this_ahead) & PARS_FRAMES_MASK;
seq_frame = (frame_proc + 1 - this_ahead) & PARS_FRAMES_MASK;
MDF6(printk(" todo=0x%08lx (curr=0x%08lx) frame8=%d, frame_proc=%d, seq_frame=%d, i=%d, mask=0x%08lx\n", todo, procpars->functions, frame8, frame_proc, seq_frame, i, mask));
MDF6(printk(" %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", framepars[0].functions, framepars[1].functions, framepars[2].functions, framepars[3].functions, framepars[4].functions, framepars[5].functions, framepars[6].functions, framepars[7].functions));
dev_dbg(g_devfp_ptr,"%s port=%d todo=0x%08lx (curr=0x%08lx) frame16=%d, frame_proc=%d, seq_frame=%d, i=%d, mask=0x%08lx\n",
__func__, sensor_port, todo, procpars->functions, frame16, frame_proc, seq_frame, i, mask);
dev_dbg(g_devfp_ptr,"%s port=%d %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
__func__, 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]) {
// NOTE: Was (frame8+job_ahead +1) & PARS_FRAMES_MASK
// NOTE: Was (frame16+job_ahead +1) & PARS_FRAMES_MASK
dev_dbg(g_devfp_ptr,"port= %d, Calling GENERIC pgm_func[%d], seq_frame = %d\n",sensor_port,i,seq_frame);
rslt = sensorproc->pgm_func[i] (sensor_port, &(sensorproc->sensor), procpars, prevpars, seq_frame);
} else rslt = 0; // only sensor-specific function, nothing to do common to all sensors
if ((rslt >= 0) && (sensorproc->pgm_func[i + 32])) { // sensor - specific functions, called after the main ones
dev_dbg(g_devfp_ptr,"port= %d, Calling SENSOR-SPECIFIC pgm_func[%d], seq_frame = %d\n",sensor_port,i,seq_frame);
rslt = sensorproc->pgm_func[i + 32] (sensor_port, &(sensorproc->sensor), procpars, prevpars, seq_frame);
}
if (rslt >= 0) {
procpars->functions &= ~mask; // mark it done
} else {
MDF6(printk("Error - function result was %d\n", rslt));
dev_dbg(g_devfp_ptr,"%s port %d: Error - function result was %d\n",__func__, sensor_port, rslt);
}
i++;
mask <<= 1;
......@@ -665,38 +733,47 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
* Called from ISR?
* @param sensor_port sensor port number (0..3)
* @param sensorproc pointer to sensor static parameters and functions
* @param frame8 current hardware frame number
* @param frame16 current hardware frame number
* @param maxahead maximal number of frames to program ahead of the current (make it P_* parameter ?)
* @return always 0 ?
*/
//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 frame8, int maxahead)
void processPars(int sensor_port, struct sensorproc_t * sensorproc, int frame16, int maxahead)
{
frame8 &= PARS_FRAMES_MASK;
frame16 &= PARS_FRAMES_MASK;
dev_dbg(g_devfp_ptr,"%s : port= %d, frame16=%d, maxahead=%d\n",__func__, sensor_port, frame16, maxahead);
if (!sensorproc){
dev_err(g_devfp_ptr,"%s port=%d frame16=%d sensorproc==NULL !!!! \n", __func__, sensor_port, frame16);
return;
}
// first - do all ASAP tasks (they should not be done ahead of the corresponding interrupt!)
// MDF6(printk("before first processParsASAP\n"));
processParsASAP(sensor_port, sensorproc, frame8);
// 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);
// 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
// MDF6(printk("before processParsSeq\n"));
processParsSeq(sensor_port, sensorproc, frame8, 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
// MDF6(printk("before second processParsASAP\n"));
processParsASAP(sensor_port, sensorproc, frame8);
// 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);
}
/**
* @brief schedule pgm_func to be executed for selected frame (frame8)
* @brief schedule pgm_func to be executed for selected frame (frame16)
* @param sensor_port sensor port number (0..3)
* @param frame8 frame number (3-bit) to schedule a function for
* @param frame16 frame number (3-bit) to schedule a function for
* @param func_num function number to schedule
*/
void schedule_pgm_func(int sensor_port, int frame8, int func_num)
void schedule_pgm_func(int sensor_port, int frame16, int func_num)
{
MDF1(printk(" frame8=%d, func_num=%d\n", frame8, func_num));
aframepars[sensor_port][frame8 & PARS_FRAMES_MASK].functions |= 1 << func_num;
dev_dbg(g_devfp_ptr,"%s port= %d, frame16=%d, func_num=%d\n",__func__, sensor_port, frame16, func_num);
aframepars[sensor_port][frame16 & PARS_FRAMES_MASK].functions |= 1 << func_num;
}
/**
......@@ -707,10 +784,10 @@ void schedule_pgm_func(int sensor_port, int frame8, int func_num)
*/
void schedule_this_pgm_func(int sensor_port, struct framepars_t * this_framepars, int func_num)
{
int frame8 = this_framepars->pars[P_FRAME] & PARS_FRAMES_MASK;
int frame16 = this_framepars->pars[P_FRAME] & PARS_FRAMES_MASK;
MDF1(printk(" frame8=%d, func_num=%d\n", frame8, func_num));
aframepars[sensor_port][frame8].functions |= 1 << func_num;
dev_dbg(g_devfp_ptr,"%s port= %d, frame16=%d, func_num=%d\n",__func__, sensor_port, frame16, func_num);
aframepars[sensor_port][frame16].functions |= 1 << func_num;
}
......@@ -765,17 +842,17 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
int index, bindex;
struct framepars_t *framepars = aframepars[sensor_port];
unsigned long *funcs2call =afuncs2call[sensor_port];
if (!frameParsInitialized) {
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]);
if (!frameParsInitialized[sensor_port]) {
initSequencers(sensor_port); // Will call initFramePars(); and initialize functions
}
int findex_this = thisFrameNumber(sensor_port) & PARS_FRAMES_MASK;
int findex_prev = (findex_this - 1) & PARS_FRAMES_MASK;
int findex_future = (findex_this - 2) & PARS_FRAMES_MASK; // actually - fartherst in the future??
// int frame8= frameno & PARS_FRAMES_MASK;
int frame8;
MDF2(printk(": frameno=0x%lx, findex_this=%d (0x%lx) maxLatency=%d, numPars=%d\n", frameno, findex_this, thisFrameNumber(sensor_port), maxLatency, numPars));
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));
PROFILE_NOW(6);
PROFILE_NOW(5); // Was 6, but no 7 in NC393
if (maxLatency >= 0) {
if (frameno <= (thisFrameNumber(sensor_port) + maxLatency)) {
D1I(local_irq_restore(flags));
......@@ -788,8 +865,8 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
// not too late, not too early, go ahead
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));
// frame8= (pars[npar].num & FRAMEPAR_GLOBALS)? -1: (frameno & PARS_FRAMES_MASK);
frame8 = frameno & PARS_FRAMES_MASK;
// 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)) {
......@@ -807,35 +884,35 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
funcs2call[index] = val;
D5(printk(" set funcs2call[0x%x]=0x%lx\n", index, val));
// } else if ((frameno !=findex_prev) && (frameno != findex_future)) { // do not write parameters in the future otherwise
} else if ((frame8 != findex_future) || ((pars[npar].num & FRAMEPAIR_JUST_THIS) == 0)) { // do not write "JUST_THIS" parameters in the future otherwise they'll stick
} 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[frame8].pars[index], val);
val = FRAMEPAIR_FRAME_MASK_NEW(pars[npar].num, framepars[frame16].pars[index], val);
}
//TODO: optimize to use mask several parameters together
D5(printk(" frame8=0x%x\n", frame8));
if ((framepars[frame8].pars[index] != val) || (pars[npar].num & FRAMEPAIR_FORCE_NEW)) {
D5(printk(" frame16=0x%x\n", frame16));
if ((framepars[frame16].pars[index] != val) || (pars[npar].num & FRAMEPAIR_FORCE_NEW)) {
bmask = 1 << (index & 31);
bindex = index >> 5;
bmask32 = 1 << bindex;
// Set this parameter for specified frame
framepars[frame8].pars[index] = val;
framepars[frame8].mod[bindex] |= bmask;
framepars[frame8].mod32 |= bmask32;
framepars[frame8].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[frame8].functions));
framepars[frame16].pars[index] = val;
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));
// 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"));
for (nframe = (frame8 + 1) & PARS_FRAMES_MASK; (nframe != findex_prev) && (!(framepars[nframe].mod[bindex] & bmask)); nframe = (nframe + 1) & PARS_FRAMES_MASK) {
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));
}
frame8 = (frame8 - 1) & PARS_FRAMES_MASK; // for " regular parameters "modified since" do not include the target frame itself, for "JUST_THIS" - does
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"));
}
// Mark this parameter in all previous frames as "modified since"
// TODO: consider alternative way - first iterate through all parameters, build masks, then apply them
for (nframe = frame8; nframe != findex_future; nframe = (nframe - 1) & PARS_FRAMES_MASK) { //NOTE: frame8 is modified here
for (nframe = frame16; nframe != findex_future; nframe = (nframe - 1) & PARS_FRAMES_MASK) { //NOTE: frame16 is modified here
framepars[nframe].modsince[bindex] |= bmask;
framepars[nframe].modsince32 |= bmask32;
}
......@@ -851,10 +928,10 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
// Changed to all (don't care about uncertainty - they will trigger only if it is too late or during sensor detection/initialization)
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
MDF5(printk("\n"));
processPars(sensor_port, sensorproc, 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,"%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
}
PROFILE_NOW(7);
PROFILE_NOW(6); // 7); // no (7) in NC393
D1I(local_irq_restore(flags));
return 0;
}
......@@ -871,7 +948,7 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
*/
int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned long mindex, unsigned long val)
{
int frame8 = (this_framepars->pars[P_FRAME]) & PARS_FRAMES_MASK;
int frame16 = (this_framepars->pars[P_FRAME]) & PARS_FRAMES_MASK;
unsigned long flags;
int nframe;
unsigned long bmask, bmask32, bindex;
......@@ -882,7 +959,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l
struct framepars_t *framepars = aframepars[sensor_port];
unsigned long *funcs2call =afuncs2call[sensor_port];
dev_dbg(g_devfp_ptr, ": thisFrameNumber=0x%lx frame8=%d index= %d (0x%lx), val=0x%lx\n", thisFrameNumber(sensor_port), frame8, index, mindex, val);
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));
// if (index > P_MAX_PAR) {
if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) {
......@@ -899,38 +976,38 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l
funcs2call[index] = val;
// } else {
} else if ((frame8 != findex_future) || ((mindex & FRAMEPAIR_JUST_THIS) == 0)) { // do not write "JUST_THIS" parameters in the future otherwise they'll stick
} else if ((frame16 != findex_future) || ((mindex & FRAMEPAIR_JUST_THIS) == 0)) { // do not write "JUST_THIS" parameters in the future otherwise they'll stick
if (mindex & FRAMEPAIR_MASK_BYTES) { // combine new value with the old one
val = FRAMEPAIR_FRAME_MASK_NEW(mindex, framepars[frame8].pars[index], val);
val = FRAMEPAIR_FRAME_MASK_NEW(mindex, framepars[frame16].pars[index], val);
}
if ((framepars[frame8].pars[index] != val) || (mindex & (FRAMEPAIR_FORCE_NEW | FRAMEPAIR_FORCE_PROC))) {
if ((framepars[frame16].pars[index] != val) || (mindex & (FRAMEPAIR_FORCE_NEW | FRAMEPAIR_FORCE_PROC))) {
bmask = 1 << (index & 31);
bindex = index >> 5;
bmask32 = 1 << bindex;
// Set this parameter for specified frame, (for now - unconditionally mark as modified, even if the value is the same as it was - CHANGED!
framepars[frame8].pars[index] = val;
framepars[frame8].mod[bindex] |= bmask;
framepars[frame8].mod32 |= bmask32;
framepars[frame16].pars[index] = val;
framepars[frame16].mod[bindex] |= bmask;
framepars[frame16].mod32 |= bmask32;
if (mindex & FRAMEPAIR_FORCE_PROC) {
framepars[frame8].functions |= funcs2call[index]; //Mark which functions will be needed to process the parameters
framepars[frame16].functions |= funcs2call[index]; //Mark which functions will be needed to process the parameters
}
dev_dbg(g_devfp_ptr, " bindex=0x%lx, bmask=0x%08lx, bmask32=0x%08lx, functions=0x%08lx\n", bindex, bmask, bmask32, framepars[frame8].functions);
dev_dbg(g_devfp_ptr, " bindex=0x%lx, bmask=0x%08lx, bmask32=0x%08lx, functions=0x%08lx\n", bindex, bmask, bmask32, framepars[frame16].functions);
// Write parameter to the next frames up to the one that have the same parameter already modified
if ((mindex & FRAMEPAIR_JUST_THIS) == 0) {
MDF8(printk(": --- setting next frames"));
// for (nframe=(frame8+1) & PARS_FRAMES_MASK; (nframe != findex_prev) && (!(framepars[frame8].mod[bindex] & bmask)); nframe=(nframe+1) & PARS_FRAMES_MASK) {
for (nframe = (frame8 + 1) & PARS_FRAMES_MASK; (nframe != findex_prev) && (!(framepars[nframe].mod[bindex] & bmask)); nframe = (nframe + 1) & PARS_FRAMES_MASK) {
// for (nframe=(frame16+1) & PARS_FRAMES_MASK; (nframe != findex_prev) && (!(framepars[frame16].mod[bindex] & bmask)); nframe=(nframe+1) & PARS_FRAMES_MASK) {
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;
D8(printk(" %d", nframe));
}
frame8 = (frame8 - 1) & PARS_FRAMES_MASK; // for " regular parameters "modified since" do not include the target frame itself, for "JUST_THIS" - does
frame16 = (frame16 - 1) & PARS_FRAMES_MASK; // for " regular parameters "modified since" do not include the target frame itself, for "JUST_THIS" - does
}
// MDF1(printk("\n"));
// dev_dbg(g_devfp_ptr,"%s \n",__func__);
// Mark this parameter in all previous frames as "modified since"
// TODO: consider alternative way - first iterate through all parameters, build masks, then apply them
MDF8(printk(": >>> setting modsince"));
// for (nframe=(frame8-1) & PARS_FRAMES_MASK; nframe != findex_future; nframe=(nframe-1) & PARS_FRAMES_MASK) {
for (nframe = frame8; nframe != findex_future; nframe = (nframe - 1) & PARS_FRAMES_MASK) { //NOTE: frame8 is modified here
// for (nframe=(frame16-1) & PARS_FRAMES_MASK; nframe != findex_future; nframe=(nframe-1) & PARS_FRAMES_MASK) {
for (nframe = frame16; nframe != findex_future; nframe = (nframe - 1) & PARS_FRAMES_MASK) { //NOTE: frame16 is modified here
framepars[nframe].modsince[bindex] |= bmask;
framepars[nframe].modsince32 |= bmask32;
D8(printk(" %d", nframe));
......@@ -956,7 +1033,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l
*/
int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPars, struct frameparspair_t * pars)
{
int frame8;
int frame16;
unsigned long flags;
int npar, nframe;
unsigned long val, bmask, bmask32;
......@@ -967,13 +1044,13 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa
struct framepars_t *framepars = aframepars[sensor_port];
unsigned long *funcs2call =afuncs2call[sensor_port];
dev_dbg(g_devfp_ptr, ": this_framepars=0x%x numPars=%d\n", (int)this_framepars, numPars);
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));
for (npar = 0; npar < numPars; npar++) {
frame8 = (this_framepars->pars[P_FRAME]) & PARS_FRAMES_MASK;
frame16 = (this_framepars->pars[P_FRAME]) & PARS_FRAMES_MASK;
val = pars[npar].val;
index = pars[npar].num & 0xffff;
dev_dbg(g_devfp_ptr, ": --- frame8=%d index=%d (0x%x) val=0x%x\n", frame8, index, (int)pars[npar].num, (int)val);
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));
......@@ -988,36 +1065,36 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa
} else if (pars[npar].num & FRAMEPAIR_FRAME_FUNC) {
funcs2call[index] = val;
// } else {
} else if ((frame8 != findex_future) || ((pars[npar].num & FRAMEPAIR_JUST_THIS) == 0)) { // do not write "JUST_THIS" parameters in the future otherwise they'll stick
} 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[frame8].pars[index], val);
val = FRAMEPAIR_FRAME_MASK_NEW(pars[npar].num, framepars[frame16].pars[index], val);
}
//TODO: optimize to use mask several parameters together
if ((framepars[frame8].pars[index] != val) || (pars[npar].num & (FRAMEPAIR_FORCE_NEW | FRAMEPAIR_FORCE_PROC))) {
if ((framepars[frame16].pars[index] != val) || (pars[npar].num & (FRAMEPAIR_FORCE_NEW | FRAMEPAIR_FORCE_PROC))) {
bmask = 1 << (index & 31);
bindex = index >> 5;
bmask32 = 1 << bindex;
// Set this parameter for specified frame, (for now - unconditionally mark as modified, even if the value is the same as it was - CHANGED!
framepars[frame8].pars[index] = val;
framepars[frame8].mod[bindex] |= bmask;
framepars[frame8].mod32 |= bmask32;
framepars[frame16].pars[index] = val;
framepars[frame16].mod[bindex] |= bmask;
framepars[frame16].mod32 |= bmask32;
if (pars[npar].num & FRAMEPAIR_FORCE_PROC) {
framepars[frame8].functions |= funcs2call[index]; //Mark which functions will be needed to process the parameters
framepars[frame16].functions |= funcs2call[index]; //Mark which functions will be needed to process the parameters
}
// 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) {
MDF8(printk(": --- setting next frames"));
for (nframe = (frame8 + 1) & PARS_FRAMES_MASK; (nframe != findex_prev) && (!(framepars[nframe].mod[bindex] & bmask)); nframe = (nframe + 1) & PARS_FRAMES_MASK) {
for (nframe = (frame16 + 1) & PARS_FRAMES_MASK; (nframe != findex_prev) && (!(framepars[nframe].mod[bindex] & bmask)); nframe = (nframe + 1) & PARS_FRAMES_MASK) {
D8(printk(" %d", nframe));
framepars[nframe].pars[index] = val;
}
frame8 = (frame8 - 1) & PARS_FRAMES_MASK; // for " regular parameters "modified since" do not include the target frame itself, for "JUST_THIS" - does
frame16 = (frame16 - 1) & PARS_FRAMES_MASK; // for " regular parameters "modified since" do not include the target frame itself, for "JUST_THIS" - does
D8(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
// for (nframe=(frame8-1) & PARS_FRAMES_MASK; nframe != findex_future; nframe=(nframe-1) & PARS_FRAMES_MASK) {
for (nframe = frame8; nframe != findex_future; nframe = (nframe - 1) & PARS_FRAMES_MASK) { //NOTE: frame8 is modified here
// for (nframe=(frame16-1) & PARS_FRAMES_MASK; nframe != findex_future; nframe=(nframe-1) & PARS_FRAMES_MASK) {
for (nframe = frame16; nframe != findex_future; nframe = (nframe - 1) & PARS_FRAMES_MASK) { //NOTE: frame16 is modified here
framepars[nframe].modsince[bindex] |= bmask;
framepars[nframe].modsince32 |= bmask32;
}
......@@ -1069,7 +1146,7 @@ int framepars_open(struct inode *inode, struct file *filp)
if (!privData) return -ENOMEM;
filp->private_data = privData;
privData->minor = MINOR(inode->i_rdev);
MDF1(printk(": minor=0x%x\n", privData->minor));
dev_dbg(g_devfp_ptr,"%s : minor=0x%x\n",__func__, privData->minor);
switch (privData->minor) {
case DEV393_MINOR(DEV393_FRAMEPARS0):
case DEV393_MINOR(DEV393_FRAMEPARS1):
......@@ -1095,7 +1172,7 @@ int framepars_release(struct inode *inode, struct file *filp)
int res = 0;
int p = MINOR(inode->i_rdev);
MDF1(printk(": minor=0x%x\n", p));
dev_dbg(g_devfp_ptr,"%s : minor=0x%x\n",__func__, p);
switch ( p ) {
case DEV393_MINOR(DEV393_FRAMEPARS0):
case DEV393_MINOR(DEV393_FRAMEPARS1):
......@@ -1179,12 +1256,12 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig)
break;
case LSEEK_FRAME_RESET: // reset absolute frame number to avoid integer frame number overflow
dev_dbg(g_devfp_ptr, "LSEEK_FRAME_RESET\n");
resetFrameNumber(sensor_port);
resetFrameNumber(sensor_port, 0, 0 ); // just high bits, do not reset hardware
break;
case LSEEK_SENSORPROC: // process modified parameters in frame 0 (to start sensor detection)
dev_dbg(g_devfp_ptr, "LSEEK_SENSORPROC: aframepars[%d][0].functions=0x%08lx\n",
sensor_port, aframepars[sensor_port][0].functions);
processPars(sensor_port, sensorproc, 0, 8); //frame0, all 8 frames (maxAhead==8)
processPars(sensor_port, &asensorproc[sensor_port], 0, PARS_FRAMES); //frame0, all 8 frames (maxAhead==8)
break;
case LSEEK_DMA_INIT: // initialize ETRAX DMA (normally done in sensor_common.c at driver init
dev_dbg(g_devfp_ptr, "LSEEK_DMA_INIT\n");
......@@ -1244,8 +1321,9 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff
int last;
int result;
sec_usec_t sec_usec;
// MDF1(printk(": file->f_pos=0x%x, *off=0x%x, count=0x%x\n", (int)file->f_pos, (int)*off, (int)count));
dev_dbg(g_devfp_ptr, ": file->f_pos=0x%x, *off=0x%x, count=0x%x\n", (int)file->f_pos, (int)*off, (int)count);
// dev_dbg(g_devfp_ptr,"%s : file->f_pos=0x%x, *off=0x%x, count=0x%x\n",__func__, (int)file->f_pos, (int)*off, (int)count);
dev_dbg(g_devfp_ptr, "%s: file->f_pos=0x%x, *off=0x%x, count=0x%x, minor=0x%x\n",
__func__, (int)file->f_pos, (int)*off, (int)count, (int) privData->minor);
count &= ~7; // sizeof (struct frameparspair_t)==8
switch (privData->minor) {
case DEV393_MINOR(DEV393_FRAMEPARS0):
......@@ -1286,14 +1364,16 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff
GLOBALPARS(sensor_port,G_MICROSECONDS) = sec_usec.usec;
break;
default:
printk("framepars_write: invalid special instruction: 0x%x\n", (int)pars[first].num);
dev_err(g_devfp_ptr, "%s 0x%x: invalid special instruction: 0x%x\n",
__func__, (int) privData->minor, (int)pars[first].num);
}
first++;
}
last = first + 1;
while ((last < count) && ((pars[last].num & 0xff00) != 0xff00)) last++; // skip to the end or next special instructions
result = setFrameParsAtomic(sensor_port,frame, latency, last - first, &pars[first]);
dev_dbg(g_devfp_ptr, "setFrameParsAtomic(%ld, %d, %d)\n", frame, latency, last - 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;
......@@ -1321,7 +1401,7 @@ int framepars_mmap(struct file *file, struct vm_area_struct *vma)
struct framepars_pd * privData = (struct framepars_pd*)file->private_data;
int sensor_port = privData -> minor - DEV393_MINOR(DEV393_FRAMEPARS0);
MDF1(printk(": minor=0x%x\n", privData->minor));
dev_dbg(g_devfp_ptr,"%s : minor=0x%x\n",__func__, privData->minor);
switch (privData->minor) {
case DEV393_MINOR(DEV393_FRAMEPARS0):
case DEV393_MINOR(DEV393_FRAMEPARS1):
......@@ -1338,6 +1418,135 @@ int framepars_mmap(struct file *file, struct vm_area_struct *vma)
default: return -EINVAL;
}
}
// SysFS interface to framepars
#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;
}
static ssize_t show_this_frame(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%u\n", (int) GLOBALPARS(get_channel_from_name(attr), G_THIS_FRAME));
}
static ssize_t store_this_frame(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
u32 aframe;
if (sscanf(buf, "%u", &aframe)>0) {
resetFrameNumber(get_channel_from_name(attr),
aframe,
(aframe < PARS_FRAMES)?1:0); // reset hardware if aframe is small
} else {
return - EINVAL;
}
return count;
}
// sscanf(buf, "%i", &buffer_settings.frame_start[get_channel_from_name(attr)], &len);
static ssize_t show_fpga_time(struct device *dev, struct device_attribute *attr, char *buf)
{
sec_usec_t sec_usec;
get_fpga_rtc(&sec_usec);
return sprintf(buf,"%lu.%lu\n", sec_usec.sec, sec_usec.usec);
}
static ssize_t store_fpga_time(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
sec_usec_t sec_usec={.sec=0, .usec=0};
// avoiding floating point calcualtions in the kernel
char *cp;
int i;
if (sscanf(buf, "%u.%s", &sec_usec.sec, cp)>0){
sscanf(cp,"%lu",&sec_usec.usec);
for (i=strlen(cp); i<6;i++)
sec_usec.usec *=10;
set_fpga_rtc(sec_usec);
} else {
return - EINVAL;
}
return count;
}
static ssize_t show_all_frames(struct device *dev, struct device_attribute *attr, char *buf)
{
int chn;
int sensor_frame16[SENSOR_PORTS];
int compressor_frame16[SENSOR_PORTS];
int i2c_frame16[SENSOR_PORTS];
int sensor_aframe[SENSOR_PORTS];
int compressor_aframe[SENSOR_PORTS];
int compressor_gframe[SENSOR_PORTS];
char * buf0=buf;
for (chn = 0; chn < SENSOR_PORTS; chn++){
sensor_frame16[chn] = getHardFrameNumber(chn,0);
compressor_frame16[chn] = getHardFrameNumber(chn,1);
i2c_frame16[chn] = read_xi2c_frame(chn);
sensor_aframe[chn] = (int) GLOBALPARS(chn, G_THIS_FRAME);
compressor_aframe[chn] = (int) get_compressor_frame(chn);
compressor_gframe[chn] = (int) GLOBALPARS(chn, G_COMPRESSOR_FRAME);
}
buf += sprintf(buf," sensor_fram16 ");
for (chn = 0; chn < SENSOR_PORTS; chn++) buf += sprintf(buf," 0x%x ",sensor_frame16[chn]);
buf += sprintf(buf,"\n");
buf += sprintf(buf,"compressor_fram16 ");
for (chn = 0; chn < SENSOR_PORTS; chn++) buf += sprintf(buf," 0x%x ",compressor_frame16[chn]);
buf += sprintf(buf,"\n");
buf += sprintf(buf," i2c_frame16 ");
for (chn = 0; chn < SENSOR_PORTS; chn++) buf += sprintf(buf," 0x%x ",i2c_frame16[chn]);
buf += sprintf(buf,"\n");
buf += sprintf(buf," sensor_aframe ");
for (chn = 0; chn < SENSOR_PORTS; chn++) buf += sprintf(buf,"0x%08x ",sensor_aframe[chn]);
buf += sprintf(buf,"\n");
buf += sprintf(buf,"compressor_aframe ");
for (chn = 0; chn < SENSOR_PORTS; chn++) buf += sprintf(buf,"0x%08x ",compressor_aframe[chn]);
buf += sprintf(buf,"\n");
buf += sprintf(buf,"compressor_gframe ");
for (chn = 0; chn < SENSOR_PORTS; chn++) buf += sprintf(buf,"0x%08x ",compressor_gframe[chn]);
buf += sprintf(buf,"\n");
return buf-buf0;
}
static DEVICE_ATTR(this_frame0, SYSFS_PERMISSIONS, show_this_frame, store_this_frame);
static DEVICE_ATTR(this_frame1, SYSFS_PERMISSIONS, show_this_frame, store_this_frame);
static DEVICE_ATTR(this_frame2, SYSFS_PERMISSIONS, show_this_frame, store_this_frame);
static DEVICE_ATTR(this_frame3, SYSFS_PERMISSIONS, show_this_frame, store_this_frame);
static DEVICE_ATTR(all_frames, SYSFS_READONLY, show_all_frames, NULL);
static DEVICE_ATTR(fpga_time, SYSFS_PERMISSIONS, show_fpga_time, store_fpga_time);
static struct attribute *root_dev_attrs[] = {
&dev_attr_this_frame0.attr,
&dev_attr_this_frame1.attr,
&dev_attr_this_frame2.attr,
&dev_attr_this_frame3.attr,
&dev_attr_all_frames.attr,
&dev_attr_fpga_time.attr,
NULL
};
static const struct attribute_group dev_attr_root_group = {
.attrs = root_dev_attrs,
.name = NULL,
};
static int elphel393_framepars_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;
}
/**
* @brief framepars driver probing function
......@@ -1355,8 +1564,8 @@ int framepars_init(struct platform_device *pdev)
init_framepars_ptr(sensor_port);
initGlobalPars(sensor_port); // sets default debug if enabled - not anymore. Add here?
initMultiPars(sensor_port); // just clear - needs to be called again when sensor is recognized
frameParsInitialized[sensor_port] = 0;
}
frameParsInitialized = 0;
res = register_chrdev(DEV393_MAJOR(DEV393_FRAMEPARS0), DEV393_NAME(DEV393_FRAMEPARS0), &framepars_fops);
if (res < 0) {
dev_err(dev, "framepars_init: couldn't get a major number %d (DEV393_MAJOR(DEV393_FRAMEPARS0)).\n",
......@@ -1367,15 +1576,15 @@ int framepars_init(struct platform_device *pdev)
init_waitqueue_head(&aframepars_wait_queue[sensor_port]);
}
dev_info(dev, DEV393_NAME(DEV393_FRAMEPARS0)": registered MAJOR: %d\n", DEV393_MAJOR(DEV393_FRAMEPARS0));
elphel393_framepars_sysfs_register(pdev);
dev_info(dev, DEV393_NAME(DEV393_FRAMEPARS0)": registered sysfs\n");
g_devfp_ptr = dev;
return 0;
}
int framepars_remove(struct platform_device *pdev)
{
unregister_chrdev(DEV393_MAJOR(DEV393_FRAMEPARS0), DEV393_NAME(DEV393_FRAMEPARS0));
return 0;
}
......
......@@ -17,7 +17,7 @@ void initSequencers (int sensor_port); ///Move to sensorcommon? currently it
void initGlobalPars (int sensor_port); /// resets all global parameters but debug mask (if ELPHEL_DEBUG)
int initMultiPars (int sensor_port); /// initialize structures for individual per-sensor parameters. Now only works for sensor registers using G_MULTI_REGSM. Should be called aftre/during sensor detection
void initFramePars (int sensor_port); ///initialize all parameters, set thisFrameNumber to frame8 (read from hardware, usually 0 after resetting i2c and cmd_seq)
void resetFrameNumber (int sensor_port); /// reset this frame number (called from initFramePars(), also can be used to avoid frame number integer overflow)
void resetFrameNumber (int sensor_port, u32 aframe, int hreset); /// reset this frame number (called from initFramePars(), also can be used to avoid frame number integer overflow)
unsigned long get_imageParamsThis (int sensor_port, int n);
unsigned long get_imageParamsPrev (int sensor_port, int n);
......@@ -29,9 +29,9 @@ 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);
void updateFramePars (int sensor_port, int frame8, struct interframe_params_t * frame_pars); /// called from ISR - advance thisFrameNumber to match hardware frame8, copy parameters as needed.
/// frame8 usually is just next after thisFrameNumber
/// frame_pars - pointer to structure (between frames in the frame buffer) to save a pointer to past parameters
//Next 2 called from ISR
void updateInterFrame(int sensor_port, int frame16, struct interframe_params_t * interframe_pars);
void updateFramePars (int sensor_port, int frame16);
int setFrameParsStatic (int sensor_port, int numPars, struct frameparspair_t * pars);
unsigned long getThisFrameNumber (int sensor_port); /// just return current thisFrameNumber
......
......@@ -91,7 +91,7 @@
*/
//copied from cxi2c.c - 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/module.h>
#include <linux/mm.h>
#include <linux/sched.h>
......@@ -103,6 +103,8 @@
#include <linux/init.h>
//#include <linux/autoconf.h>
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
//#include <asm/system.h>
#include <asm/byteorder.h> // endians
......@@ -128,25 +130,28 @@
//#include "quantization_tables.h"
#include "gamma_tables.h"
#include "x393.h"
#include "detect_sensors.h"
#include "x393_fpga_functions.h" // to check bitsteram
/**
* @brief optional debug output
*/
#if ELPHEL_DEBUG
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
#define D10(x) { if (GLOBALPARS(G_DEBUG) & (1 <<10)) { x ;} }
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
#define D10(x) { if (GLOBALPARS(G_DEBUG) & (1 <<10)) { x ;} }
// #define MDD1(x) printk("%s:%d:",__FILE__,__LINE__); x ; udelay (ELPHEL_DEBUG_DELAY)
#define MDF10(x) { if (GLOBALPARS(G_DEBUG) & (1 <<10)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
#define MDF11(x) { if (GLOBALPARS(G_DEBUG) & (1 <<11)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
#define MDF10(x) { if (GLOBALPARS(G_DEBUG) & (1 <<10)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
#define MDF11(x) { if (GLOBALPARS(G_DEBUG) & (1 <<11)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
// #define MDD1(x)
#define D1I(x) x
#define D1I(x) x
#else
#define MDF(x)
#define D10(x)
#define D1I(x) x
#define MDF10(x)
#define MDF11(x)
#define MDF(x)
#define D10(x)
#define D1I(x) x
#define MDF10(x)
#define MDF11(x)
#endif
......@@ -159,9 +164,22 @@
* \n TODO: use P_*?
*/
#define GAMMA_THRESH (GAMMA_CACHE_NUMBER/16)
/** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */
static struct device *g_dev_ptr;
static DEFINE_SPINLOCK(gamma_lock); ///< Non port-specific lock
static DEFINE_SPINLOCK(gamma_lock_0); ///<
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};
static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE)));
struct gamma_stuct_t * gammas_p; // to use with mmap
struct gamma_stuct_t * gammas_p; // to use with mmap
struct gammas_pd {
int minor;
......@@ -169,7 +187,7 @@ struct gammas_pd {
unsigned short hash16;
unsigned char mode;
unsigned char color; // Does it need port/sub-channel?
// something else to be added here?
// something else to be added here?
};
int gammas_open (struct inode *inode, struct file *file);
......@@ -177,7 +195,8 @@ int gammas_release(struct inode *inode, struct file *file);
loff_t gammas_lseek (struct file * file, loff_t offset, int orig);
ssize_t gammas_write (struct file * file, const char * buf, size_t count, loff_t *off);
int gammas_mmap (struct file *file, struct vm_area_struct *vma);
static int __init gammas_init(void);
//static int __init gammas_init(void);
/**
......@@ -215,7 +234,7 @@ inline void remove_from_all (int index) { // always - in that chain - after
* @param index item index to remove
*/
inline void insert_first_nonscaled(int index) {
MDF11(printk("index=%d\n",index));
dev_dbg(g_dev_ptr,"insert_first_nonscaled(%d)\n",index);
gammas[gammas[0].newest_non_scaled].newer_non_scaled= index; // 1 ==[0].oldest_non_scaled
gammas[index].older_non_scaled= gammas[0].newest_non_scaled; // 4
gammas[0].newest_non_scaled=index; // 5
......@@ -233,14 +252,14 @@ inline void insert_first_nonscaled(int index) {
* @param index item index to remove
*/
inline void insert_first_scaled (int non_scaled, int index) {
MDF11(printk("non_scaled=%d, index=%d\n",non_scaled, index));
dev_dbg(g_dev_ptr,"insert_first_scaled(%d, %d)\n",non_scaled, index);
gammas[index].older_scaled= gammas[non_scaled].newest_scaled; //4
gammas[gammas[non_scaled].newest_scaled].newer_scaled= index; //1
// gammas[index].older_scaled= gammas[non_scaled].newest_scaled; //4
// gammas[index].older_scaled= gammas[non_scaled].newest_scaled; //4
gammas[index].newer_scaled= non_scaled; //6
gammas[non_scaled].newest_scaled= index; //5
// gammas[index].newer_scaled= non_scaled; //6
// gammas[index].newer_scaled= non_scaled; //6
gammas[index].this_non_scaled=non_scaled;
}
......@@ -259,20 +278,19 @@ inline void insert_first_all (int index) {
* @brief Initialize gamma tables data structures
*/
void init_gammas(void) {
unsigned long flags;
int i;
gammas_p=gammas;
// empty 2-d chain
local_irq_save(flags);
// empty 2-d chain
dev_dbg(g_dev_ptr,"init_gammas()\n");
spin_lock_bh(&gamma_lock);
gammas[0].oldest_non_scaled=0;
gammas[0].newest_non_scaled=0;
// all entries in a same
// all entries in a same
gammas[0].oldest_all=GAMMA_CACHE_NUMBER-1;
gammas[0].newest_all=1;
MDF10(printk("\n"));
for (i=1; i < GAMMA_CACHE_NUMBER;i++) {
gammas[i].this_non_scaled=-1; // no parent.FIXME: Where is it used? -1 if never used
// something else?
// something else?
gammas[i].newer_all=i-1;
gammas[i].older_all= (i==(GAMMA_CACHE_NUMBER-1))? 0: (i+1);
gammas[i].locked=0;
......@@ -282,10 +300,9 @@ void init_gammas(void) {
for (i=1; i < sizeof(gammas[0].locked_chn_color)/sizeof(gammas[0].locked_chn_color[0]);i++) {
gammas[0].locked_chn_color[i]=0;
}
local_irq_restore(flags);
spin_unlock_bh(&gamma_lock);
}
/**
* @brief verifies that index is current (points to specified hash and scale)
* @param hash16 - 16-bit unique hash for gamma table
......@@ -316,8 +333,8 @@ int is_gamma_valid (unsigned short hash16, unsigned short scale, int index) {
unsigned long get_locked_hash32(int color, ///< color channel 0..3
int sensor_port, ///< sensor port number (0..3)
int sensor_subchn) ///< sensor sub-channel (connected to the same port through 10359 mux) (0..3)
///< @return hash32 (combined gamma/black/scale) locked for a specified color,
///< port, sub-channel
///< @return hash32 (combined gamma/black/scale) locked for a specified color,
///< port, sub-channel
{
int index=gammas[0].locked_chn_color[PORT_CHN_COLOR(color,sensor_port,sensor_subchn)];
return index?gammas[index].hash32:0;
......@@ -345,33 +362,35 @@ inline void lock_gamma_node (int index, ///< gamma table index
int unlock_gamma_node (int color, ///< color channel 0..3
int sensor_port, ///< sensor port number (0..3)
int sensor_subchn) ///< sensor sub-channel (connected to the same port through 10359 mux) (0..3)
///< @return wrong data -1, nothing to unlock - 0, >0 - unlocked index
///< @return wrong data -1, nothing to unlock - 0, >0 - unlocked index
{
unsigned long flags;
// unsigned long flags;
int index;
int cps = PORT_CHN_COLOR(color,sensor_port,sensor_subchn);
MDF11(printk("color=0x%x\n",color));
local_irq_save(flags);
dev_dbg(g_dev_ptr,"color=0x%x\n",color);
// local_irq_save(flags);
spin_lock_bh(&gamma_lock);
index =gammas[0].locked_chn_color[cps];
if (index) {
gammas[index].locked &= ~(1ULL << color); // clear appropriate "locked" bit for this table
gammas[0].locked_chn_color[color]=0;
}
local_irq_restore(flags);
spin_lock_bh(&gamma_lock);
// local_irq_restore(flags);
return index;
}
/** Find a gamma table in FPGA format to be programmed (table should already be locked for this color) */
unsigned long * get_gamma_fpga (int color, ///< color channel 0..3
int sensor_port, ///< sensor port number (0..3)
int sensor_subchn) ///< sensor sub-channel (connected to the same port through 10359 mux) (0..3)
///< @return pointer to a gamma table (or NULL if table does not exist)
///< @return pointer to a gamma table (or NULL if table does not exist)
{ // NOTE: Not needed anymore?
int index;
int cps = PORT_CHN_COLOR(color,sensor_port,sensor_subchn);
// if (unlikely((color>=4) || (color<0))) return NULL; //
// if (unlikely((color>=4) || (color<0))) return NULL; //
index =gammas[0].locked_chn_color[cps];
MDF11(printk(" index=%d(0x%x)\n",index,index));
dev_dbg(g_dev_ptr," index=%d(0x%x)\n",index,index);
if (index) return gammas[index].fpga;
else return NULL;
}
......@@ -387,17 +406,17 @@ unsigned long * get_gamma_fpga (int color, ///< color channel 0..3
int gamma_new_node(void) {
int tmp_p;
if ((gammas[0].non_scaled_length > GAMMA_THRESH) && (gammas[gammas[0].oldest_non_scaled].newest_scaled == gammas[0].oldest_non_scaled)) { // no scaled for the oldest hash
// sacrifice oldest hash
// sacrifice oldest hash
tmp_p=gammas[0].oldest_non_scaled;
remove_from_nonscaled(tmp_p);
} else { // use oldest scaled
tmp_p=gammas[0].oldest_all;
// skip locked if any (should be unlikely to get any locked)
// skip locked if any (should be unlikely to get any locked)
while ((tmp_p!=0) && gammas[tmp_p].locked) tmp_p=gammas[tmp_p].newer_all;
if (tmp_p==0) return 0; // none (unlocked) nodes are found
// remove from "all" chain (should work for tmp_p being oldest or not
// remove from "all" chain (should work for tmp_p being oldest or not
remove_from_all (tmp_p);
// remove from "scaled chain"
// remove from "scaled chain"
remove_from_scaled (tmp_p);
}
gammas[tmp_p].valid=0;
......@@ -411,7 +430,7 @@ int gamma_new_node(void) {
*/
void gamma_encode_fpga(unsigned short * gamma_in, unsigned long * gamma_out) {
int i,base,diff;
MDF11(printk("\n"));
dev_dbg(g_dev_ptr,"gamma_encode_fpga()\n");
for (i=0;i<256;i++) {
base=(gamma_in[i] >> 6);
diff=(gamma_in[i+1] >> 6);
......@@ -435,7 +454,7 @@ void gamma_calc_scaled (unsigned short scale,unsigned short * gamma_in, unsigne
int i;
unsigned long d;
unsigned long max_scaled=0xffff << GAMMA_SCALE_SHIFT;
MDF11(printk("\n"));
dev_dbg(g_dev_ptr,"gamma_calc_scaled()\n");
for (i=0; i<257; i++) {
d= ((unsigned long) scale ) * ((unsigned long) gamma_in[i] ) + (1 <<(GAMMA_SCALE_SHIFT-1)); ///rounding, not truncating
if (d>max_scaled) d=max_scaled;
......@@ -455,10 +474,10 @@ void gamma_calc_reverse(unsigned short * gamma_in, unsigned char * gamma_out) {
unsigned long gcurr=0; // running value to be compared against direct gamma
int r=0; // current value of reverse gamma table
int x=0; // current indedx of reverse gamma table
MDF11(printk("\n"));
dev_dbg(g_dev_ptr,"gamma_calc_reverse()\n");
while ((r<256) && (x<256)) {
gamma_out[x]=r;
// if ((r<255) && (( gamma_in[r]<<8) <= gcurr)) {
// if ((r<255) && (( gamma_in[r]<<8) <= gcurr)) {
if ((r<255) && ( gamma_in[r] <= gcurr)) {
r++;
} else {
......@@ -482,9 +501,9 @@ int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scale
///< table for (if mode bit 4 is set), otherwise color, sensor_port, sensor_subchn are ignored
int sensor_port, ///< sensor port number (0..3)
int sensor_subchn) ///< sensor sub-channel (connected to the same port through 10359 mux) (0..3)
///< @return index for the specified table or 0 if none exists and prototype was not provided (gamma_proto==NULL)
///< @return index for the specified table or 0 if none exists and prototype was not provided (gamma_proto==NULL)
{
D1I(unsigned long flags);
// D1I(unsigned long flags);
int tmp_p, tmp_p1; //,tmp_p0;
int cps=PORT_CHN_COLOR(color,sensor_port,sensor_subchn);
unsigned short gamma_linear[257]=
......@@ -505,157 +524,165 @@ int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scale
0xe000,0xe100,0xe200,0xe300,0xe400,0xe500,0x0600,0xe700,0xe800,0xe900,0xea00,0xeb00,0xec00,0xed00,0xee00,0xef00,
0xf000,0xf100,0xf200,0xf300,0xf400,0xf500,0x0600,0xf700,0xf800,0xf900,0xfa00,0xfb00,0xfc00,0xfd00,0xfe00,0xff00,
0xffff};
MDF10(printk("hash16=0x%x scale=0x%x gamma_proto=0x%x mode =0x%x port/channel/color=%x\n", (int) hash16, (int) scale, (int) gamma_proto, (int) mode, cps));
dev_dbg(g_dev_ptr, "hash16=0x%x scale=0x%x gamma_proto=0x%x mode =0x%x port/channel/color=%x\n", (int) hash16, (int) scale, (int) gamma_proto, (int) mode, cps);
if (!gamma_proto & (hash16==0)) {
gamma_proto=gamma_linear;
MDF10(printk("Using linear table\n"));
dev_dbg(g_dev_ptr, "Using linear table\n");
} else {
MDF10(printk("Using non-linear table\n")); ///NOTE: here
dev_dbg(g_dev_ptr, "Using non-linear table\n"); ///NOTE: here
}
///disable interrupts here
D1I(local_irq_save(flags));
// look for the matching hash
///disable interrupts here
// D1I(local_irq_save(flags));
spin_lock_bh(&gamma_lock);
// look for the matching hash
tmp_p=gammas[0].newest_non_scaled;
// gammas[0].oldest_all=GAMMA_CACHE_NUMBER-1;
// gammas[0].newest_all=1;
// gammas[0].oldest_all=GAMMA_CACHE_NUMBER-1;
// gammas[0].newest_all=1;
MDF10(printk("gammas[0].oldest_all=%d\n", gammas[0].oldest_all)); ///NOTE: 253
dev_dbg(g_dev_ptr,"gammas[0].oldest_all=%d\n", gammas[0].oldest_all); ///NOTE: 253
MDF10(printk("gammas[0].newest_all=%d\n", gammas[0].newest_all));
MDF10(printk("tmp_p=0x%x gammas[tmp_p].hash16=0x%x hash16=0x%x\n", tmp_p, (int) gammas[tmp_p].hash16, (int) hash16 ));
dev_dbg(g_dev_ptr,"gammas[0].newest_all=%d\n", gammas[0].newest_all);
dev_dbg(g_dev_ptr,"tmp_p=0x%x gammas[tmp_p].hash16=0x%x hash16=0x%x\n", tmp_p, (int) gammas[tmp_p].hash16, (int) hash16 );
while ((tmp_p!=0) && (gammas[tmp_p].hash16 != hash16)) {
D10(printk(" --tmp_p=0x%x\n", tmp_p)); ///NOTE: never
dev_dbg(g_dev_ptr," --tmp_p=0x%x\n", tmp_p); ///NOTE: never
tmp_p=gammas[tmp_p].older_non_scaled;
}
MDF10(printk("tmp_p=0x%x\n", tmp_p)); ///NOTE: 0xff
// Got right hash?
dev_dbg(g_dev_ptr,"tmp_p=0x%x\n", tmp_p); ///NOTE: 0xff
// Got right hash?
if (tmp_p == 0) { // no luck
MDF10(printk("Need new table\n")); ///NOTE: never
dev_dbg(g_dev_ptr,"Need new table\n"); ///NOTE: never
if (!gamma_proto) { //
D1I(local_irq_restore(flags));
MDF10(printk("matching hash not found, new table is not provided\n")); ///NOTE: never
spin_unlock_bh(&gamma_lock);
// D1I(local_irq_restore(flags));
dev_dbg(g_dev_ptr,"matching hash not found, new table is not provided\n"); ///NOTE: never
return 0; // matching hash not found, new table is not provided - return 0;
}
// Create new proto table
// Create new proto table
tmp_p=gamma_new_node();
MDF10(printk("tmp_p=0x%x\n gamma_proto= 0x%x 0x%x 0x%x 0x%x\n", tmp_p, (int) gamma_proto[0], (int) gamma_proto[1], (int) gamma_proto[2], (int) gamma_proto[3]));
dev_dbg(g_dev_ptr,"tmp_p=0x%x\n gamma_proto= 0x%x 0x%x 0x%x 0x%x\n", tmp_p, (int) gamma_proto[0],
(int) gamma_proto[1], (int) gamma_proto[2], (int) gamma_proto[3]);
if (unlikely(!tmp_p)) { // could not allocate node
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_bh(&gamma_lock);
return 0; // failure: could not allocate node - return 0;
}
// fill it:
// fill it:
gammas[tmp_p].hash16=hash16;
gammas[tmp_p].scale=0;
gammas[tmp_p].oldest_scaled=tmp_p; // points to itself - no scaled versions yet
gammas[tmp_p].newest_scaled=tmp_p; // points to itself - no scaled versions yet
if ((mode & GAMMA_MODE_NOT_NICE)==0) {
// let interrupts to take place, and disable again
D1I(local_irq_restore(flags));
MDF10(printk("Interrupts reenabled, tmp_p=0x%x\n", tmp_p));
D1I(local_irq_save(flags));
// check if it is still there (likely so, but allow it to fail).
// let interrupts to take place, and disable again - not needed with a tasklet
// D1I(local_irq_restore(flags));
// MDF10(printk("Interrupts reenabled, tmp_p=0x%x\n", tmp_p));
// D1I(local_irq_save(flags));
// check if it is still there (likely so, but allow it to fail).
if (unlikely(!is_gamma_current (hash16, 0, tmp_p))) {
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_bh(&gamma_lock);
return 0; // failure: other code used this node - return 0; (try not_nice next time?)
}
}
// memcpy ((void *)...
// memcpy ((void *)...
memcpy (gammas[tmp_p].direct, gamma_proto, 257*2) ; ///copy the provided table (full 16 bits)
gammas[tmp_p].valid |= GAMMA_VALID_MASK;
// add it to the chain
MDF10(printk("insert_first_nonscaled(0x%x)\n", tmp_p));
// add it to the chain
dev_dbg(g_dev_ptr,"insert_first_nonscaled(0x%x)\n", tmp_p);
insert_first_nonscaled(tmp_p);
// matching hash found,make it newest (remove from the chain + add to the chain)
// matching hash found,make it newest (remove from the chain + add to the chain)
} else if (gammas[tmp_p].newer_non_scaled !=0) { // if 0 - it is already the newest
MDF10(printk("remove_from_nonscaled (0x%x)\n", tmp_p)); ///NOTE: 0xff
dev_dbg(g_dev_ptr,"remove_from_nonscaled (0x%x)\n", tmp_p); ///NOTE: 0xff
remove_from_nonscaled (tmp_p);
MDF10(printk("insert_first_nonscaled (0x%x)\n", tmp_p));///NOTE: 0xff
dev_dbg(g_dev_ptr,"insert_first_nonscaled (0x%x)\n", tmp_p);///NOTE: 0xff
insert_first_nonscaled(tmp_p);
}
MDF10(printk("0x%x\n", tmp_p)); ///NOTE: 0xff
dev_dbg(g_dev_ptr,"tmp_p= 0x%x\n", tmp_p); ///NOTE: 0xff
// now looking for the correct scale.
// now looking for the correct scale.
if (scale==0) {
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_bh(&gamma_lock);
return tmp_p; // wanted non-scaled, got it ///NOTE: returns here
}
tmp_p1=gammas[tmp_p].newest_scaled;
MDF10(printk("tmp_p1=0x%x\n", tmp_p1)); ///FIXME: 0xff
// while ((tmp_p1!=0) && (gammas[tmp_p1].scale != scale)){ ///FIXME: got stuck here
dev_dbg(g_dev_ptr,"tmp_p1=0x%x\n", tmp_p1); ///FIXME: 0xff
while ((tmp_p1!=tmp_p) && (gammas[tmp_p1].scale != scale)){ ///FIXME: got stuck here
D10(printk(" >>tmp_p1=0x%x)\n", tmp_p1));
dev_dbg(g_dev_ptr," >>tmp_p1=0x%x)\n", tmp_p1);
tmp_p1=gammas[tmp_p1].older_scaled;
}
// Got right scale?
// if (tmp_p1 == 0) { // no luck
// Got right scale?
// if (tmp_p1 == 0) { // no luck
if (tmp_p1 == tmp_p) { // no luck
MDF10(printk("create new scaled table\n"));
// create new scale
dev_dbg(g_dev_ptr,"create new scaled table\n");
// create new scale
tmp_p1=gamma_new_node();
if (unlikely(!tmp_p1)) { // could not allocate node
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_bh(&gamma_lock);
return 0; // failure: could not allocate node - return 0;
}
// fill it
// fill it
gammas[tmp_p1].hash16=hash16;
gammas[tmp_p1].scale= scale;
// insert into 2-d
// insert into 2-d
insert_first_scaled (tmp_p, tmp_p1);
// insert into 1-d (all)
// insert into 1-d (all)
insert_first_all (tmp_p1);
if ((mode & GAMMA_MODE_NOT_NICE)==0) {
// let interrupts to take place, and disable again
D1I(local_irq_restore(flags));
D1I(local_irq_save(flags));
// check if it is still there (likely so, but allow it to fail).
// let interrupts to take place, and disable again - not needed with tasklets
// D1I(local_irq_restore(flags));
// D1I(local_irq_save(flags));
// check if it is still there (likely so, but allow it to fail).
if (unlikely(!is_gamma_current (hash16, scale, tmp_p1))) {
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_bh(&gamma_lock);
return 0; // failure: other code used this node - return 0; (try not_nice next time?)
}
}
} else { // scaled table already exists, make it first in 2 chains:
MDF10(printk("reuse scaled table\n"));
// found right scale, make it newest in two chain (2d - hash/scale and 1-d - all scaled together, regardless of the hash
///2-d chain
dev_dbg(g_dev_ptr,"reuse scaled table\n");
// found right scale, make it newest in two chain (2d - hash/scale and 1-d - all scaled together, regardless of the hash
///2-d chain
if (gammas[tmp_p1].newer_scaled != tmp_p) { // not already the newest of scales for the same hash
remove_from_scaled (tmp_p1);
insert_first_scaled (tmp_p, tmp_p1);
}
///1-d chain
///1-d chain
if (gammas[tmp_p1].newer_all != 0) { // not already the newest from all scaled
remove_from_all (tmp_p1);
insert_first_all (tmp_p1);
}
}
// is the scaled version already calculated?
// is the scaled version already calculated?
if ((gammas[tmp_p1].valid & GAMMA_VALID_MASK) == 0) {
// calculate scaled version
// calculate scaled version
gamma_calc_scaled (scale, gammas[tmp_p].direct, gammas[tmp_p1].direct);
gammas[tmp_p1].valid |= GAMMA_VALID_MASK;
}
if (mode & GAMMA_MODE_HARDWARE) {
// is hardware-encoded array already calculated (do it if not)?
// is hardware-encoded array already calculated (do it if not)?
if ((gammas[tmp_p1].valid & GAMMA_FPGA_MASK)==0) {
gamma_encode_fpga(gammas[tmp_p1].direct, gammas[tmp_p1].fpga);
gammas[tmp_p1].valid |= GAMMA_FPGA_MASK;
}
}
if (mode & GAMMA_MODE_LOCK) {
// lock the node for the color/port/channel
// lock the node for the color/port/channel
lock_gamma_node (tmp_p1, color, sensor_port,sensor_subchn);
}
if (mode & GAMMA_MODE_NEED_REVERSE) {
if ((gammas[tmp_p1].valid & GAMMA_VALID_REVERSE)==0) {
if ((mode & GAMMA_MODE_NOT_NICE)==0) {
// let interrupts to take place, and disable again
D1I(local_irq_restore(flags));
D1I(local_irq_save(flags));
// check if it is still there (likely so, but allow it to fail).
// let interrupts to take place, and disable again // not needed with tasklets
// D1I(local_irq_restore(flags));
// D1I(local_irq_save(flags));
// check if it is still there (likely so, but allow it to fail).
if (unlikely(!is_gamma_current (hash16, 0, tmp_p))) {
D1I(local_irq_restore(flags));
// D1I(local_irq_restore(flags));
spin_unlock_bh(&gamma_lock);
return 0; // failure: other code used this node - return 0; (try not_nice next time?)
}
}
......@@ -663,39 +690,51 @@ int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scale
gammas[tmp_p1].valid |= GAMMA_VALID_REVERSE;
}
}
D1I(local_irq_restore(flags));
MDF10(printk("- return %d\n",tmp_p1));
// D1I(local_irq_restore(flags));
spin_unlock_bh(&gamma_lock);
dev_dbg(g_dev_ptr,"set_gamma_table(): return %d\n",tmp_p1);
return tmp_p1;
}
/** Writing gamma table to FPGA (1 color, 1 sub-channel) enabling IRQ after transferring each FPGA_TABLE_CHUNK DWORDs */
void fpga_gamma_write_nice(int color, ///< Color (0..3)
/** Writing gamma table to FPGA (1 color, 1 sub-channel) enabling IRQ after transferring each FPGA_TABLE_CHUNK DWORDs
*
* This code may be called from the IRQ context, and from the different CPU */
int fpga_gamma_write_nice(int color, ///< Color (0..3)
int sensor_port, ///< sensor port (0..3)
int sensor_subchn, ///< sensor sub-channel (when several are connected through a multiplexer)
u32 * gamma) ///< Gamma table (256 DWORDs) in encoded FPGA format
unsigned long * gamma) ///< Gamma table (256 DWORDs) in encoded FPGA format
///< @return 0 OK, -ENODEV - FPGA is not programmed
{
x393_gamma_tbl_t gamma_tbl_a = {.d32=0};
x393_gamma_tbl_t gamma_tbl_d = {.d32=0};
const int gamma_size=256; // 18-bit entries
unsigned long flags;
// unsigned long flags;
int addr32, len32, i;
if (is_fpga_programmed()<=0){
return -ENODEV;
}
gamma_tbl_a.a_n_d = 1;
gamma_tbl_a.color = color;
gamma_tbl_a.sub_chn = sensor_subchn;
spin_lock_bh(gamma_locks[sensor_port]);
for (addr32 = 0; addr32 < gamma_size; addr32 += FPGA_TABLE_CHUNK){
len32 = FPGA_TABLE_CHUNK;
if (unlikely(addr32 + len32 > gamma_size))
len32 = gamma_size - addr32;
gamma_tbl_a.addr= addr32;
local_irq_save(flags);
// spin_lock_irqsave(gamma_locks[sensor_port],flags);
x393_sens_gamma_tbl(gamma_tbl_a, sensor_port);
for (i = addr32; i < addr32 + len32; i++){
gamma_tbl_d.d32 = gamma[i];
x393_sens_gamma_tbl(gamma_tbl_d, sensor_port);
}
local_irq_restore(flags);
// spin_unlock_irqrestore(gamma_locks[sensor_port],flags);
}
spin_unlock_bh(gamma_locks[sensor_port]);
return 0;
}
///======================================
......@@ -743,8 +782,8 @@ int gammas_open(struct inode *inode, struct file *file) {
int res;
struct gammas_pd * privData;
privData= (struct gammas_pd *) kmalloc(sizeof(struct gammas_pd),GFP_KERNEL);
MDF10(printk("gammas[0].oldest_all=%d\n", gammas[0].oldest_all));
MDF10(printk("gammas[0].newest_all=%d\n", gammas[0].newest_all));
dev_dbg(g_dev_ptr,"gammas[0].oldest_all=%d\n", gammas[0].oldest_all);
dev_dbg(g_dev_ptr,"gammas[0].newest_all=%d\n", gammas[0].newest_all);
if (!privData) return -ENOMEM;
file->private_data = privData;
privData-> minor=MINOR(inode->i_rdev);
......@@ -810,7 +849,7 @@ loff_t gammas_lseek (struct file * file, loff_t offset, int orig) {
file->f_pos = offset;
break;
case SEEK_CUR:
// file->f_pos = getThisFrameNumber() + offset;
// file->f_pos = getThisFrameNumber() + offset;
break;
case SEEK_END:
if (offset < 0) {
......@@ -856,7 +895,7 @@ ssize_t gammas_write(struct file * file, ///< this file structure
const char * buf, ///< userland buffer
size_t count, ///< number of bytes to write
loff_t *off) ///< updated offset in the buffer
///< @return full length passed or 0 if failed
///< @return full length passed or 0 if failed
{
struct gammas_pd * privData = (struct gammas_pd *) file->private_data;
struct {
......@@ -868,9 +907,9 @@ ssize_t gammas_write(struct file * file, ///< this file structure
} data;
int head, result;
// ************* NOTE: Never use file->f_pos in write() and read() !!!
// ************* NOTE: Never use file->f_pos in write() and read() !!!
unsigned short * gamma= data.gamma;
MDF10(printk(" file->f_pos=0x%x, *off=0x%x\n", (int) file->f_pos, (int) *off));
dev_dbg(g_dev_ptr," file->f_pos=0x%x, *off=0x%x\n", (int) file->f_pos, (int) *off);
switch (privData->minor) {
case DEV393_MINOR(DEV393_GAMMA) :
if (count>sizeof (data)) count = sizeof (data);
......@@ -880,13 +919,13 @@ ssize_t gammas_write(struct file * file, ///< this file structure
if ((count-head) < (2 * 257)) gamma=NULL; // complete gamma table is not available
if (head>count) head=count;
memcpy (&(privData->scale),&(data.scale),head);
MDF10(printk("count=%d, head=%d, hash16=0x%x scale=0x%x mode=0x%x color=%x\n", count, head, (int) data.hash16, (int) data.scale, (int) data.mode, (int) data.color));
MDF10(printk("count=%d, head=%d, hash16=0x%x scale=0x%x mode=0x%x color=%x\n", count, head, (int) privData->hash16, (int) privData->scale, (int) privData->mode, (int) privData->color));
// result=set_gamma_table (privData->hash16, privData->scale, gamma, privData->mode, ( privData->color >> 3) & 3);
dev_dbg(g_dev_ptr,"count=%d, head=%d, hash16=0x%x scale=0x%x mode=0x%x color=%x\n", count, head, (int) data.hash16, (int) data.scale, (int) data.mode, (int) data.color);
dev_dbg(g_dev_ptr,"count=%d, head=%d, hash16=0x%x scale=0x%x mode=0x%x color=%x\n", count, head, (int) privData->hash16, (int) privData->scale, (int) privData->mode, (int) privData->color);
// result=set_gamma_table (privData->hash16, privData->scale, gamma, privData->mode, ( privData->color >> 3) & 3);
result=set_gamma_table (privData->hash16, privData->scale, gamma, privData->mode, ( privData->color >> 0) & 3, ( privData->color >> 4) & 3, ( privData->color >> 2) & 3);
*off= (result>0)?result:0;
} else *off=0;
MDF10(printk("file->f_pos=0x%x\n", (int) *off));
dev_dbg(g_dev_ptr,"file->f_pos=0x%x\n", (int) *off);
return (*off) ? count: 0;
default: return -EINVAL;
}
......@@ -901,7 +940,7 @@ ssize_t gammas_write(struct file * file, ///< this file structure
int gammas_mmap (struct file *file, struct vm_area_struct *vma) {
int result;
struct gammas_pd * privData = (struct gammas_pd *) file->private_data;
MDF10(printk("gammas_all_mmap, minor=0x%x\n",privData-> minor));
dev_dbg(g_dev_ptr,"gammas_all_mmap, minor=0x%x\n",privData-> minor);
switch (privData->minor) {
case DEV393_MINOR(DEV393_GAMMA) :
result=remap_pfn_range(vma,
......@@ -909,7 +948,7 @@ int gammas_mmap (struct file *file, struct vm_area_struct *vma) {
((unsigned long) virt_to_phys(gammas_p)) >> PAGE_SHIFT, // Should be page-aligned
vma->vm_end-vma->vm_start,
vma->vm_page_prot);
MDF10(printk("remap_pfn_range returned=%x\r\n",result));
dev_dbg(g_dev_ptr,"remap_pfn_range returned=%x\r\n",result);
if (result) return -EAGAIN;
return 0;
default: return -EINVAL;
......@@ -920,48 +959,54 @@ int gammas_mmap (struct file *file, struct vm_area_struct *vma) {
* @brief Gammas driver init
* @return 0
*/
static int __init gammas_init(void) {
static int gammas_init(struct platform_device *pdev) {
int res;
printk ("Starting "DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA));
struct device *dev = &pdev->dev;
const struct of_device_id *match; // not yet used
dev_info(dev,"Starting "DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA));
init_gammas();
MDF10(printk("set_gamma_table (0, GAMMA_SCLALE_1, NULL, 0, 0)\n"); udelay (ELPHEL_DEBUG_DELAY));
// MDF10(printk("set_gamma_table (0, GAMMA_SCLALE_1, NULL, 0, 0)\n"); udelay (ELPHEL_DEBUG_DELAY));
set_gamma_table (0, GAMMA_SCLALE_1, NULL, 0, 0, 0, 0); // maybe not needed to put linear to cache - it can be calculated as soon FPGA will be tried to be programmed with
// hash16==0
res = register_chrdev(DEV393_MAJOR(DEV393_GAMMA), DEV393_NAME(DEV393_GAMMA), &gammas_fops);
if(res < 0) {
printk(KERN_ERR "\ngammas_init: couldn't get a major number %d.\n",DEV393_MAJOR(DEV393_GAMMA));
dev_err(dev,"\ngammas_init: couldn't get a major number %d.\n",DEV393_MAJOR(DEV393_GAMMA));
return res;
}
// init_waitqueue_head(&gammas_wait_queue);
printk(DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA));
// init_waitqueue_head(&gammas_wait_queue);
dev_info(dev, DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA));
g_dev_ptr = dev; // to use for debug print
return 0;
}
int gammas_remove(struct platform_device *pdev)
{
unregister_chrdev(DEV393_MAJOR(DEV393_GAMMA), DEV393_NAME(DEV393_GAMMA));
return 0;
}
module_init(gammas_init);
MODULE_LICENSE("GPLv3.0");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(X3X3_GAMMAS_DRIVER_DESCRIPTION);
static const struct of_device_id elphel393_gamma_tables_of_match[] = {
{ .compatible = "elphel,elphel393-gamma_tables-1.00" },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, elphel393_gamma_tables_of_match);
static struct platform_driver elphel393_gamma_tables = {
.probe = gammas_init,
.remove = gammas_remove,
.driver = {
.name = DEV393_NAME(DEV393_GAMMA),
.of_match_table = elphel393_gamma_tables_of_match,
},
};
module_platform_driver(elphel393_gamma_tables);
//module_init(gammas_init);
MODULE_LICENSE("GPLv3.0");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(X3X3_GAMMAS_DRIVER_DESCRIPTION);
......@@ -12,7 +12,7 @@ int unlock_gamma_node (int color, int sensor_port, int sensor_subchn); /// NOTE:
/// return a pointer to the gamma table (single color) encoded in FPGA format (NULL if there is to table ready)
///
unsigned long * get_gamma_fpga(int color, int sensor_port, int sensor_subchn);
void fpga_gamma_write_nice (int color, int sensor_port, int sensor_subchn, u32 * gamma);
int fpga_gamma_write_nice (int color, int sensor_port, int sensor_subchn, unsigned long * gamma);
int gamma_new_node(void);
......
......@@ -78,7 +78,7 @@
*/
//copied from cxi2c.c - 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/module.h>
#include <linux/mm.h>
#include <linux/sched.h>
......@@ -88,6 +88,9 @@
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
//#include <linux/autoconf.h>
#include <linux/vmalloc.h>
......@@ -115,7 +118,8 @@
#include <elphel/elphel393-mem.h>
#include "x393.h"
#include "histograms.h"
#include "detect_sensors.h"
#include "x393_fpga_functions.h" // to check bitsteram
/**
* \def MDF21(x) optional debug output
*/
......@@ -140,6 +144,8 @@ dma_addr_t fpga_hist_phys; // physical address of the start of the received hi
/** for each port and possible sensor subchannel provides index in combine histogram data */
int histograms_map[SENSOR_PORTS][MAX_SENSORS];
static DEFINE_SPINLOCK(histograms_init_lock); ///< do not start multiple threads of histogram structures initialization
/** total number of sensors (on all ports) used */
static int numHistChn = 0;
......@@ -151,12 +157,44 @@ struct histogram_stuct_t (*histograms)[HISTOGRAM_CACHE_NUMBER];
dma_addr_t histograms_phys; ///< likely not needed, saved during allocation
struct histogram_stuct_t * histograms_p; ///< alias of histogram_stuct_t
/** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */
static struct device *g_dev_ptr;
wait_queue_head_t hist_y_wait_queue; ///< wait queue for the G1 histogram (used as Y)
wait_queue_head_t hist_c_wait_queue; ///< wait queue for all the other (R,G2,B) histograms (color)
void init_histograms(int chn_mask); ///< combined subchannels and ports Save mask to global P-variable
int histograms_init_hardware(void);
static volatile int histograms_initialized = 0; ///< 0 - not initialized, 1 - structures only, 2 structures and hardware NC393: initialize when first used?
/** Check if histograms structures are initialized, initialize if not */
int histograms_check_init(void)
{
int sensor_port, chn_mask=0;
if (histograms_initialized > 1)
return histograms_initialized;
spin_lock(&histograms_init_lock);
if (histograms_initialized > 1) {
spin_unlock(&histograms_init_lock);
return histograms_initialized;
}
if (!histograms_initialized){
dev_dbg(g_dev_ptr, "need to initialize histograms structures");
for (sensor_port = 0; sensor_port < SENSOR_PORTS; sensor_port++){
chn_mask |= get_subchannels(sensor_port) << (MAX_SENSORS * sensor_port);
dev_dbg(g_dev_ptr, "sensor_port=%d, chn_mask updated to 0x%x", sensor_port, chn_mask);
}
init_histograms(chn_mask);
histograms_initialized = 1; // structures initialized
}
if (is_fpga_programmed() >0 ){ // do not try to access FPGA if it is not programmed
dev_dbg(g_dev_ptr, "need to initialize histograms hardware");
if (!histograms_init_hardware())
histograms_initialized = 2; // fully initialized
}
dev_dbg(g_dev_ptr, "histograms_check_init() -> %d", histograms_initialized);
spin_unlock(&histograms_init_lock);
return histograms_initialized;
}
/** File operations private data */
struct histograms_pd {
......@@ -184,7 +222,6 @@ int histograms_open (struct inode *inode, struct file *file);
int histograms_release(struct inode *inode, struct file *file);
loff_t histograms_lseek (struct file * file, loff_t offset, int orig);
int histograms_mmap (struct file *file, struct vm_area_struct *vma);
static int __init histograms_init(void);
inline void histogram_calc_cumul ( unsigned long * hist, unsigned long * cumul_hist );
......@@ -224,9 +261,12 @@ void histograms_dma_ctrl(int mode) ///< 0 - reset, 1 - disable, 2 - enable
/** Initialize histograms data structures, should be called when active subchannels are known (maybe use DT)? */
//#define HISTOGRAMS_DISABLE_IRQ
void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask to global P-variable
{
#ifdef HISTOGRAMS_DISABLE_IRQ
unsigned long flags;
#endif
int p,s,i, sz,pages;
numHistChn = 0; //__builtin_popcount (chn_mask & 0xffff);
for (p=0; p< SENSOR_PORTS; p++) for (s=0;s <MAX_SENSORS;s++) {
......@@ -241,28 +281,44 @@ void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask
GLOBALPARS(p, G_SUBCHANNELS) &= ~(1 << s);
}
}
dev_dbg(g_dev_ptr, "Histograms structures, channel mask = 0x%x, numHistChn = 0x%x",chn_mask, numHistChn);
//G_SUBCHANNELS
sz = numHistChn * HISTOGRAM_CACHE_NUMBER * sizeof(struct histogram_stuct_t);
if (sz & (PAGE_SIZE-1)) pages++;
pages = sz >> PAGE_SHIFT;
pages = ((sz -1) >> PAGE_SHIFT)+1;
// if (sz & (PAGE_SIZE-1)) pages++;
// When device == NULL, dma_alloc_coherent just allocates notmal memory, page aligned, CMA if available
// histograms = (struct histogram_stuct_t* [HISTOGRAM_CACHE_NUMBER]) dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL);
// histograms = (struct histogram_stuct_t[HISTOGRAM_CACHE_NUMBER] * ) dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL);
// histograms = (struct histogram_stuct_t[HISTOGRAM_CACHE_NUMBER]) * dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL);
histograms = dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL); // OK
// histograms = (struct histogram_stuct_t * ) dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL); //<<<assignment from incompatible pointer type [-Wincompatible-pointer-types]>>>
// histograms = dma_alloc_coherent(NULL,(pages * PAGE_SIZE),&histograms_phys,GFP_KERNEL); // OK
// dev_warn(g_dev_ptr, "dma_alloc_coherent(NULL, 0x%x, 0x%x,GFP_KERNEL)",pages * PAGE_SIZE, (int) histograms_phys);
// This code is spin-locked above to prevent simultaneous allocation from several php instances, so GFP_KERNEL may not be used
// histograms = dma_alloc_coherent(NULL,(pages * PAGE_SIZE),&histograms_phys,GFP_NOWAIT); // OK
// dev_warn(g_dev_ptr, "dma_alloc_coherent(NULL, 0x%x, 0x%x,GFP_NOWAIT)",pages * PAGE_SIZE, (int) histograms_phys);
// histograms = dma_alloc_coherent(NULL,(pages * PAGE_SIZE),&histograms_phys,GFP_ATOMIC); // OK
dev_warn(g_dev_ptr, "dma_alloc_coherent should be done before (@probe), needed are 0x%x bytes)",pages * PAGE_SIZE);
BUG_ON(!histograms);
histograms_p= (struct histogram_stuct_t *) histograms;
MDF21(printk("\n"));
// MDF21(printk("\n"));
#ifdef HISTOGRAMS_DISABLE_IRQ
local_irq_save(flags);
#endif
dev_dbg(g_dev_ptr, "Histograms structures, channel mask = 0x%x",chn_mask);
for (s=0; s<numHistChn; s++) {
for (i=0; i < HISTOGRAM_CACHE_NUMBER; i++) {
histograms[s][i].frame=0xffffffff;
histograms[s][i].valid=0;
}
}
#ifdef HISTOGRAMS_DISABLE_IRQ
local_irq_restore(flags);
#endif
dev_dbg(g_dev_ptr, "Histograms structures initialized");
}
/** Get histogram index for sensor port/channel, skipping unused ones */
int get_hist_index (int sensor_port, ///< sensor port number (0..3)
......@@ -351,26 +407,26 @@ int get_histograms(int sensor_port, ///< sensor port number (0..3)
index=GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn);
raw_needed=(needed | (needed>>4) | needed>>8) & 0xf;
for (i=0;i<HISTOGRAM_CACHE_NUMBER;i++) {
MDF21(printk("index=%d, needed=0x%x\n",index,needed));
dev_dbg(g_dev_ptr, "index=%d, needed=0x%x\n",index,needed);
if ((histograms[hist_indx][index].frame <= frame) && ((histograms[hist_indx][index].valid & raw_needed)==raw_needed)) break;
index = (index-1) & (HISTOGRAM_CACHE_NUMBER-1);
}
if (i>=HISTOGRAM_CACHE_NUMBER) {
ELP_KERR(printk("no histograms exist for requested colors (0x%x), requested 0x%x\n",raw_needed,needed));
dev_err(g_dev_ptr, "no histograms exist for requested colors (0x%x), requested 0x%x\n",raw_needed,needed);
return -EFAULT; // if Y - never calculated, if C - maybe all the cache is used by Y
}
needed &= ~0x0f; // mask out FPGA read requests -= they are not handled here anymore (use set_histograms())
MDF22(printk("needed=0x%x\n",needed));
dev_dbg(g_dev_ptr, "needed=0x%x\n",needed);
needed |= ((needed >>4) & 0xf0); // cumulative histograms are needed for percentile calculations
needed &= ~histograms[hist_indx][index].valid;
MDF22(printk("needed=0x%x\n",needed));
dev_dbg(g_dev_ptr, "needed=0x%x\n",needed);
if (needed & 0xf0) { // Calculating cumulative histograms
for (i=0; i<4; i++) if (needed & ( 0x10 << i )) {
color_start= i<<8 ;
histogram_calc_cumul ( (unsigned long *) &histograms[hist_indx][index].hist[color_start], (unsigned long *) &histograms[hist_indx][index].cumul_hist[color_start] );
histograms[hist_indx][index].valid |= 0x10 << i;
}
MDF21(printk("needed=0x%x, valid=0x%lx\n",needed,histograms[hist_indx][index].valid));
dev_dbg(g_dev_ptr, "needed=0x%x, valid=0x%lx\n",needed,histograms[hist_indx][index].valid);
}
if (needed & 0xf00) { // Calculating percentiles
for (i=0; i<4; i++) if (needed & ( 0x100 << i )) {
......@@ -378,7 +434,7 @@ int get_histograms(int sensor_port, ///< sensor port number (0..3)
histogram_calc_percentiles ( (unsigned long *) &histograms[hist_indx][index].cumul_hist[color_start], (unsigned char *) &histograms[hist_indx][index].percentile[color_start] );
histograms[hist_indx][index].valid |= 0x100 << i;
}
MDF21(printk("needed=0x%x, valid=0x%lx\n",needed, histograms[hist_indx][index].valid));
dev_dbg(g_dev_ptr, "needed=0x%x, valid=0x%lx\n",needed, histograms[hist_indx][index].valid);
}
return index;
}
......@@ -461,7 +517,7 @@ int histograms_open(struct inode *inode, ///< inode
if (!privData) return -ENOMEM;
file->private_data = privData;
privData-> minor=MINOR(inode->i_rdev);
MDF21(printk("minor=0x%x\n",privData-> minor));
dev_dbg(g_dev_ptr, "histograms_open: minor=0x%x\n",privData-> minor);
switch (privData-> minor) {
case DEV393_MINOR(DEV393_HISTOGRAM) :
inode->i_size = HISTOGRAMS_FILE_SIZE;
......@@ -472,6 +528,8 @@ int histograms_open(struct inode *inode, ///< inode
privData->request_en=1; // enable requesting histogram for the specified frame (0 - rely on the available ones)
privData->port=0;
privData->subchannel=0;
if (histograms_check_init() < 2)
return -ENODEV; // Bitstream not loaded?
return 0;
default:
kfree(file->private_data); // already allocated
......@@ -488,7 +546,7 @@ int histograms_release (struct inode *inode, ///< inode
{
int res=0;
int p = MINOR(inode->i_rdev);
MDF21(printk("minor=0x%x\n",p));
dev_dbg(g_dev_ptr, "histograms_release minor=0x%x\n",p);
switch ( p ) {
case DEV393_MINOR(DEV393_HISTOGRAM) :
break;
......@@ -533,7 +591,7 @@ loff_t histograms_lseek (struct file * file,
struct histograms_pd * privData = (struct histograms_pd *) file->private_data;
unsigned long reqAddr,reqFrame;
MDF21(printk("offset=0x%x, orig=0x%x\n",(int) offset, (int) orig));
dev_dbg(g_dev_ptr, "histograms_lseek: offset=0x%x, orig=0x%x\n",(int) offset, (int) orig);
switch (privData->minor) {
case DEV393_MINOR(DEV393_HISTOGRAM) :
switch(orig) {
......@@ -615,11 +673,11 @@ loff_t histograms_lseek (struct file * file,
default:
switch (offset & ~0x1f) {
case LSEEK_DAEMON_HIST_Y: // wait for daemon enabled and histograms Y ready
MDF21(printk("wait_event_interruptible (hist_y_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))));
dev_dbg(g_dev_ptr, "wait_event_interruptible (hist_y_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f)));
wait_event_interruptible (hist_y_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f)));
break;
case LSEEK_DAEMON_HIST_C: // wait for daemon enabled and histograms Y ready
MDF21(printk("wait_event_interruptible (hist_c_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))));
dev_dbg(g_dev_ptr, "wait_event_interruptible (hist_c_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f)));
wait_event_interruptible (hist_c_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f)));
break;
default:
......@@ -653,7 +711,7 @@ loff_t histograms_lseek (struct file * file,
int histograms_mmap (struct file *file, struct vm_area_struct *vma) {
int result;
struct histograms_pd * privData = (struct histograms_pd *) file->private_data;
MDF21(printk("minor=0x%x\n",privData-> minor));
dev_dbg(g_dev_ptr, "histograms_mmap minor=0x%x\n",privData-> minor);
switch (privData->minor) {
case DEV393_MINOR(DEV393_HISTOGRAM) :
result=remap_pfn_range(vma,
......@@ -661,7 +719,7 @@ int histograms_mmap (struct file *file, struct vm_area_struct *vma) {
((unsigned long) virt_to_phys(histograms_p)) >> PAGE_SHIFT, // Should be page-aligned
vma->vm_end-vma->vm_start,
vma->vm_page_prot);
MDF21(printk("remap_pfn_range returned=%x\r\n",result));
dev_dbg(g_dev_ptr, "remap_pfn_range returned=%x\r\n",result);
if (result) return -EAGAIN;
return 0;
default: return -EINVAL;
......@@ -672,24 +730,62 @@ int histograms_mmap (struct file *file, struct vm_area_struct *vma) {
* @brief Histograms driver init
* @return 0
*/
static int __init histograms_init(void) {
int histograms_init(struct platform_device *pdev) {
int res;
int sz, pages;
struct device *dev = &pdev->dev;
const struct of_device_id *match; // not yet used
// init_histograms(); // Not now??? Need to have list of channels
// Do it later, from the user space
res = register_chrdev(DEV393_MAJOR(DEV393_HISTOGRAM), "gamma_tables_operations", &histograms_fops);
res = register_chrdev(DEV393_MAJOR(DEV393_HISTOGRAM), DEV393_NAME(DEV393_HISTOGRAM), &histograms_fops);
if(res < 0) {
printk(KERN_ERR "histograms_init: couldn't get a major number %d.\n",DEV393_MAJOR(DEV393_HISTOGRAM));
dev_err(dev, "histograms_init: couldn't get a major number %d.\n", DEV393_MAJOR(DEV393_HISTOGRAM));
return res;
}
// init_waitqueue_head(&histograms_wait_queue);
init_waitqueue_head(&hist_y_wait_queue); // wait queue for the G1 histogram (used as Y)
init_waitqueue_head(&hist_c_wait_queue); // wait queue for all the other (R,G2,B) histograms (color)
printk(DEV393_NAME(DEV393_HISTOGRAM)"\n");
dev_info(dev, DEV393_NAME(DEV393_HISTOGRAM)": registered MAJOR: %d\n", DEV393_MAJOR(DEV393_HISTOGRAM));
histograms_initialized = 0;
// NC393: Did not find a way to get memory when histograms a first needed:
// GFP_KERNEL can nolt work inside spinlock (needed to prevent simultaneous initializations
// from multiple php-cli instances, GFP_ATOMIC just fails.
// So here we
// allocate for all 16 (ports*subchannels) ~1.1MB and then use portion of it (usually 1/4)
sz = SENSOR_PORTS * MAX_SENSORS * HISTOGRAM_CACHE_NUMBER * sizeof(struct histogram_stuct_t);
pages = ((sz -1 ) >> PAGE_SHIFT) + 1;
histograms = dma_alloc_coherent(NULL,(pages * PAGE_SIZE),&histograms_phys,GFP_KERNEL);
dev_info(dev, "dma_alloc_coherent(NULL, 0x%x, 0x%x,GFP_KERNEL)",pages * PAGE_SIZE, (int) histograms_phys);
g_dev_ptr = dev; // to use for debug print
return 0;
}
int histograms_remove(struct platform_device *pdev)
{
unregister_chrdev(DEV393_MAJOR(DEV393_HISTOGRAM), DEV393_NAME(DEV393_HISTOGRAM));
return 0;
}
static const struct of_device_id elphel393_histograms_of_match[] = {
{ .compatible = "elphel,elphel393-histograms-1.00" },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, elphel393_histograms_of_match);
static struct platform_driver elphel393_histograms = {
.probe = histograms_init,
.remove = histograms_remove,
.driver = {
.name = DEV393_NAME(DEV393_HISTOGRAM),
.of_match_table = elphel393_histograms_of_match,
},
};
//module_init(histograms_init);
module_platform_driver(elphel393_histograms);
module_init(histograms_init);
MODULE_LICENSE("GPLv3.0");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(X3X3_HISTOGRAMS_DRIVER_DESCRIPTION);
......@@ -20,13 +20,11 @@
extern wait_queue_head_t hist_y_wait_queue; /// wait queue for the G1 histogram (used as Y)
extern wait_queue_head_t hist_c_wait_queue; /// wait queue for all the other (R,G2,B) histograms (color)
void init_histograms(int chn_mask);
int get_hist_index (int sensor_port, int sensor_chn);
// void init_histograms(int chn_mask);
int histograms_check_init(void);
int get_hist_index (int sensor_port, int sensor_chn); //no hardware involved
int set_histograms (int sensor_port, int sensor_chn, unsigned long frame, int needed, unsigned long * gammaHash, unsigned long * framep);
int get_histograms (int sensor_port, int sensor_chn, unsigned long frame, int needed);
int histograms_init_hardware(void);
//int histograms_init_hardware(void);
void histograms_dma_ctrl(int mode); // 0 - reset, 1 - disable, 2 - enable
......@@ -323,7 +323,7 @@
//
*/
#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
......@@ -337,6 +337,8 @@
#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>
......@@ -385,6 +387,12 @@
#define MD9(x)
#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)
{
g_dev_ptr = dev;
}
/** Capabilities of MT9M001 1.3 MPix */
struct sensor_t mt9m001={
......@@ -686,15 +694,15 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
u32 i2c_read_dataw;
// u8 * i2c_read_data = (u8*)& i2c_read_dataw; // each two bytes - one short word, big endian
// unsigned char chipver_reg=P_MT9X001_CHIPVER;
// u32 chipver_reg=P_MT9X001_CHIPVER;
int sensor_subtype=0;
int i;
struct sensor_t * psensor; // current sensor
x393_sensio_ctl_t sensio_ctl = {.d32=0};
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"**mt9x001_pgm_detectsensor**: {%d} frame16=%d, thispars->pars[P_SENSOR]= 0x%x\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()
MDF1(printk(" sensor 0x%x already detected, exiting\n",(int) thispars->pars[P_SENSOR]));
dev_dbg(g_dev_ptr,"{%d} sensor 0x%x already detected, exiting\n",sensor_port,(int) thispars->pars[P_SENSOR]);
return sensor->sensorType;
}
......@@ -714,7 +722,7 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
i2c_readData (0, (psensor->i2c_addr) | 1, i2c_read_data, 2, 0); ///restart, not start (cxi2c.c)
local_irq_restore(flags); // IRQ restore
if (((I2C_READ_DATA16(0) ^ MT9P001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9P001 2592x1944 sensor, chip ID=%x\n",(i2c_read_data[0]<<8)+i2c_read_data[1]);
dev_dbg(g_dev_ptr,"Found MT9P001 2592x1944 sensor, chip ID=%x\n",(i2c_read_data[0]<<8)+i2c_read_data[1]);
sensor_subtype=MT9P_TYP; //1;
}
#else
......@@ -735,13 +743,14 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
x393_sensio_ctrl(sensio_ctl,sensor_port);
udelay(50); // is it needed?
X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_MT9X001_CHIPVER, &i2c_read_dataw);
dev_dbg(g_dev_ptr,"Read i2c (port = %d, sa7=0x%x, reg=0x%x) chip ID=%x\n",sensor_port, psensor->i2c_addr, P_MT9X001_CHIPVER, i2c_read_dataw);
if (((i2c_read_dataw ^ MT9P001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9P001 2592x1944 sensor, chip ID=%x\n",i2c_read_dataw);
dev_dbg(g_dev_ptr,"Found MT9P001 2592x1944 sensor, chip ID=%x\n",i2c_read_dataw);
sensor_subtype=MT9P_TYP; //1;
}
#endif
// printk("sensor id= 0x%x\r\n",i2c_read_data[0]);
// MDD1(printk("sensor=0x%x\n", (int)sensor));
// dev_dbg(g_dev_ptr,"sensor id= 0x%x\n",i2c_read_data[0]);
// MDD1(dev_dbg(g_dev_ptr,"sensor=0x%x\n", (int)sensor));
if (sensor_subtype ==0) { // not a 5MPix chip
// CCAM_ARST_ON; // Why was it here
psensor= &mt9m001; //address the same for all others
......@@ -751,17 +760,17 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
i2c_writeData(0, (psensor->i2c_addr) & 0xfe, &chipver_reg, 1, 0); // no stop before read
i2c_readData (0, (psensor->i2c_addr) | 1, i2c_read_data, 2, 0); //restart, not strart
local_irq_restore(flags); // IRQ restore
// printk("-sensor id= 0x%x\r\n",i2c_read_data[0]);
// dev_dbg(g_dev_ptr,"-sensor id= 0x%x\n",i2c_read_data[0]);
if (((I2C_READ_DATA16(0)^MT9M001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9M001 1280x1024 sensor, chip ID=%x\r\n",I2C_READ_DATA16(0));
dev_dbg(g_dev_ptr,"Found MT9M001 1280x1024 sensor, chip ID=%x\n",I2C_READ_DATA16(0));
psensor= &mt9m001;
sensor_subtype=MT9M_TYP; //1;
} else if (((I2C_READ_DATA16(0)^MT9D001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9D001 1600x1200 sensor, chip ID=%x\r\n",I2C_READ_DATA16(0));
dev_dbg(g_dev_ptr,"Found MT9D001 1600x1200 sensor, chip ID=%x\n",I2C_READ_DATA16(0));
psensor= &mt9d001;
sensor_subtype=MT9D_TYP; //2;
} else if (((I2C_READ_DATA16(0)^MT9T001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9T001 2048x1536 sensor, chip ID=%x\r\n",I2C_READ_DATA16(0));
dev_dbg(g_dev_ptr,"Found MT9T001 2048x1536 sensor, chip ID=%x\n",I2C_READ_DATA16(0));
psensor= &mt9t001;
sensor_subtype=MT9T_TYP; //3;
// if(d[2] == 0x01) - MT9T001 chip rev 01 - color gains had a bug
......@@ -769,41 +778,43 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
#else
X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_MT9X001_CHIPVER, &i2c_read_dataw);
if (((i2c_read_dataw ^MT9M001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9M001 1280x1024 sensor, chip ID=%x\r\n",i2c_read_dataw);
dev_dbg(g_dev_ptr,"Found MT9M001 1280x1024 sensor, chip ID=%x\n",i2c_read_dataw);
psensor= &mt9m001;
sensor_subtype=MT9M_TYP; //1;
} else if (((i2c_read_dataw ^ MT9D001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9D001 1600x1200 sensor, chip ID=%x\r\n",i2c_read_dataw);
dev_dbg(g_dev_ptr,"Found MT9D001 1600x1200 sensor, chip ID=%x\n",i2c_read_dataw);
psensor= &mt9d001;
sensor_subtype=MT9D_TYP; //2;
} else if (((i2c_read_dataw ^ MT9T001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9T001 2048x1536 sensor, chip ID=%x\r\n",i2c_read_dataw);
dev_dbg(g_dev_ptr,"Found MT9T001 2048x1536 sensor, chip ID=%x\n",i2c_read_dataw);
psensor= &mt9t001;
sensor_subtype=MT9T_TYP; //3;
// if(d[2] == 0x01) - MT9T001 chip rev 01 - color gains had a bug
} else {
dev_dbg(g_dev_ptr,"Found Unknown sensor, chip ID=%x\n",i2c_read_dataw);
}
#endif
}
// MDD1(printk("sensor=0x%x, sensor_subtype=0x%x\n", (int)sensor, (int)sensor_subtype));
// MDD1(dev_dbg(g_dev_ptr,"sensor=0x%x, sensor_subtype=0x%x\n", (int)sensor, (int)sensor_subtype));
if (sensor_subtype ==0) return 0; // no sensor found
// Sensor recognized, go on
// memcpy(&sensor, psensor, sizeof(mt9p001)); // copy sensor definitions
memcpy(sensor, psensor, sizeof(mt9p001)); // copy sensor definitions
// MDD1(printk("sensor=0x%x\n", (int)sensor));
MDF1(printk("copied %d bytes of sensor static parameters\r\n",sizeof(mt9p001)));
add_sensor_proc(onchange_detectsensor,&mt9x001_pgm_detectsensor); // detect sensor type, sets sensor structure (capabilities), function pointers NOTE: will be called directly, not through pointers
add_sensor_proc(onchange_initsensor, &mt9x001_pgm_initsensor); // resets sensor, reads sensor registers, schedules "secret" manufacturer's corrections to the registers (stops/re-enables hardware i2c)
add_sensor_proc(onchange_exposure, &mt9x001_pgm_exposure); // program exposure
add_sensor_proc(onchange_window, &mt9x001_pgm_window); // program sensor WOI and mirroring (flipping)
add_sensor_proc(onchange_window_safe, &mt9x001_pgm_window_safe); // program sensor WOI and mirroring (flipping) - now - only flipping? with lower latency
add_sensor_proc(onchange_limitfps, &mt9x001_pgm_limitfps); // check compressor will keep up, limit sensor FPS if needed
add_sensor_proc(onchange_gains, &mt9x001_pgm_gains); // program analog gains
add_sensor_proc(onchange_triggermode, &mt9x001_pgm_triggermode); // program sensor trigger mode
add_sensor_proc(onchange_sensorregs, &mt9x001_pgm_sensorregs); // write sensor registers (only changed from outside the driver as they may have different latencies)?
// MDD1(printk("sensor->sensorType=0x%lx\n", sensor->sensorType));
// 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(mt9p001));
add_sensor_proc(sensor_port,onchange_detectsensor,&mt9x001_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, &mt9x001_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_exposure, &mt9x001_pgm_exposure); // program exposure
add_sensor_proc(sensor_port,onchange_window, &mt9x001_pgm_window); // program sensor WOI and mirroring (flipping)
add_sensor_proc(sensor_port,onchange_window_safe, &mt9x001_pgm_window_safe); // program sensor WOI and mirroring (flipping) - now - only flipping? with lower latency
add_sensor_proc(sensor_port,onchange_limitfps, &mt9x001_pgm_limitfps); // check compressor will keep up, limit sensor FPS if needed
add_sensor_proc(sensor_port,onchange_gains, &mt9x001_pgm_gains); // program analog gains
add_sensor_proc(sensor_port,onchange_triggermode, &mt9x001_pgm_triggermode); // program sensor trigger mode
add_sensor_proc(sensor_port,onchange_sensorregs, &mt9x001_pgm_sensorregs); // write sensor registers (only changed from outside the driver as they may have different latencies)?
// MDD1(dev_dbg(g_dev_ptr,"sensor->sensorType=0x%lx\n", sensor->sensorType));
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType); // was so
// setFramePar(thispars, P_SENSOR | FRAMEPAIR_FORCE_NEWPROC, sensor->sensorType); // force actions
// MDD1(printk("\n"));
// MDD1(dev_dbg(g_dev_ptr,"\n"));
///TODO: Fill G_MULTI_REGSM+i - which registers need individual values in multi-sensor applications
unsigned short * sensor_multi_regs;
int sensor_multi_regs_number;
......@@ -830,17 +841,17 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
}
for (i=0; i<sensor_multi_regs_number; i++ ) {
GLOBALPARS(sensor_port, G_MULTI_REGSM + ((sensor_multi_regs[i]>>5) & 7)) |= 1 << (sensor_multi_regs[i] & 0x1f);
// MDF(printk("i=%d, m=0x%x\n",i,(int)sensor_multi_regs[i]));
// MDF(printk("GLOBALPARS(0x%x)=0x%x\n",(int) G_MULTI_REGSM + ((sensor_multi_regs[i]>>5) & 7) ,(int)GLOBALPARS(G_MULTI_REGSM + ((sensor_multi_regs[i]>>5) & 7))));
// dev_dbg(g_dev_ptr,"{%d} i=%d, m=0x%x\n",sensor_port,i,(int)sensor_multi_regs[i]);
// dev_dbg(g_dev_ptr,"{%d} GLOBALPARS(0x%x)=0x%x\n",sensor_port,(int) G_MULTI_REGSM + ((sensor_multi_regs[i]>>5) & 7) ,(int)GLOBALPARS(G_MULTI_REGSM + ((sensor_multi_regs[i]>>5) & 7)));
}
}
//#define GLOBALPARS(x) globalPars[(x)-FRAMEPAR_GLOBALS] // should work in drivers and applications
for (i=0;i<8;i++) {
// MDF(printk("i=%d, m=0x%lx\n",i,GLOBALPARS(G_MULTI_REGSM+i)));
// dev_dbg(g_dev_ptr,"{%d} i=%d, m=0x%lx\n",sensor_port,i,GLOBALPARS(G_MULTI_REGSM+i));
}
// CCAM_ARO_ON ; //set Does it need to be set here? Not earlier (as it is now set for NC393
MDF4(printk(" set ARO (TRIGGER) line HIGH\n"));
dev_dbg(g_dev_ptr,"{%d} set ARO (TRIGGER) line HIGH\n",sensor_port);
sensio_ctl.d32=0;
sensio_ctl.aro = 1;
sensio_ctl.aro_set = 1;
......@@ -866,7 +877,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
unsigned short * sensor_register_overwrites;
x393_sensio_ctl_t sensio_ctl = {.d32=0};
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
if (frame16 >= 0) return -1; // should be ASAP
// int fpga_addr=(frame16 <0) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame16);
// unsigned char i2c_read_data[512]; // each two bytes - one short word, big endian
......@@ -874,14 +885,14 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
int nupdate=0;
int i,color;
int regval, regnum, mreg, j;
printk("Resetting MT9X001 sensor\r\n");
dev_dbg(g_dev_ptr,"Resetting MT9X001 sensor\n");
// reset sensor by applying MRST (low):
#ifdef NC353
CCAM_MRST_ON;
udelay (100);
CCAM_MRST_OFF;
udelay (100);
printk("Reading sensor registers to the shadows:\r\n");
dev_dbg(g_dev_ptr,"Reading sensor registers to the shadows:\n");
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));
......@@ -917,7 +928,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
sensio_ctl.d32=0;
// NC393: both sequencers started in pgm_detectsensor
udelay (100);
printk("Reading sensor registers to the shadows:\r\n");
dev_dbg(g_dev_ptr,"Reading sensor registers to the shadows:\n");
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));
......@@ -935,7 +946,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
}
#endif
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
printk("Initializing MT9X001 registers with default values:\r\n");
dev_dbg(g_dev_ptr,"Initializing MT9X001 registers with default values:\n");
int sensor_register_overwrites_number;
int sensor_subtype=sensor->sensorType - SENSOR_MT9X001;
switch (sensor_subtype) {
......@@ -958,7 +969,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
break;
}
// enable hardware i2c - NOTE: the only place where the i2c controller is enabled.
printk ("Starting hardware sequencers\n");
// dev_dbg(g_dev_ptr,"Starting hardware sequencers\n");
#ifdef NC353
local_irq_save(flags); // IRQ Off, so both sequencers to be started at the same time
i2c_run();
......@@ -974,7 +985,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
sensor->i2c_addr,
sensor_register_overwrites[2*i],\
sensor_register_overwrites[2*i+1]);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x,0x%x,0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) sensor_register_overwrites[2*i], (int) 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, 0x10000);
......@@ -986,7 +997,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
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) printk ("\n"); printk(" 0x%06lx",GLOBALPARS (sensor_port, G_SENSOR_CALIB+i));});
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));});
return 0;
}
......@@ -1004,7 +1015,7 @@ int mt9x001_pgm_window (int sensor_port, ///< sensor port numb
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
return mt9x001_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
......@@ -1018,7 +1029,7 @@ int mt9x001_pgm_window_safe (int sensor_port, ///< sensor port num
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
return mt9x001_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
......@@ -1034,7 +1045,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
int i,dv,dh,bv,bh,ww,wh,wl,wt,flip,flipX,flipY,d, v;
struct frameparspair_t pars_to_update[29];
int nupdate=0;
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int styp = sensor->sensorType & 7;
dh= thispars->pars[P_DCM_HOR];
......@@ -1054,7 +1065,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
// program sensor width
if ((ww-1) != thispars->pars[P_SENSOR_REGS+P_MT9X001_WIDTH]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_WIDTH, ww-1);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_WIDTH, (int) ww-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) P_MT9X001_WIDTH, (int) ww-1);
}
// height
d = (wh+1) & 0xfffe; // round up to even
......@@ -1066,7 +1077,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
// program sensor height
if ((wh-1) != thispars->pars[P_SENSOR_REGS+P_MT9X001_HEIGHT]) {
SET_SENSOR_MBPAR(sensor_port, frame16 ,sensor->i2c_addr, P_MT9X001_HEIGHT, wh-1);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_HEIGHT, (int) wh-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) P_MT9X001_HEIGHT, (int) wh-1);
}
// Margins
wl = thispars->pars[P_WOI_LEFT];
......@@ -1111,13 +1122,13 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
// Program sensor left margin
if (wl != thispars->pars[P_SENSOR_REGS+P_MT9X001_COLSTART]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_COLSTART, wl);
MDF4(printk(" XSET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_COLSTART, (int) wl));
dev_dbg(g_dev_ptr,"{%d} XSET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_COLSTART, (int) wl);
}
// Program sensor top margin
if (wt != thispars->pars[P_SENSOR_REGS+P_MT9X001_ROWSTART]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_ROWSTART, wt);
MDF4(printk(" SET_SENSOR_MBPAR(0x%0x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_ROWSTART,(int) wt));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%0x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_ROWSTART,(int) wt);
}
///TODO:Get rid of get_sensor_i2c_regs16 !!!
// the fields that should not chnage in non-stop will not change, so it is OK to write them always
......@@ -1125,19 +1136,19 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM] & 0xff88) | ((bv - 1) << 4) | (dv - 1) ;
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM]) {
SET_SENSOR_PAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RAM, v);
MDF4(printk(" SET_SENSOR_PAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RAM, (int) v));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_PAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RAM, (int) v);
}
v=(thispars->pars[P_SENSOR_REGS+P_MT9X001_CAM] & 0xff88) | ((bh - 1) << 4) | (dh - 1);
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_CAM]) {
SET_SENSOR_PAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_CAM, v);
MDF4(printk(" SET_SENSOR_PAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_CAM, (int) v));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_PAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_CAM, (int) v);
}
v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2] & 0x3fff) | // preserve other bits from shadows
(flipX ? (1 << 14) : 0) | // FLIPH - will control just alternative rows
(flipY ? (1 << 15) : 0) ; // FLIPV
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RMODE2, v);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE2, (int) v));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE2, (int) v);
}
} else { // 1.3 and 2 MPix sensors
......@@ -1148,7 +1159,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
((dv == 8) ? (1 << 5) : 0) ; // Row skip 8
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RMODE1, v);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE1, (int) v));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE1, (int) v);
}
v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2] & 0x3fe7) | // preserve other bits from shadows
((dh == 2) ? (1 << 3) : 0) | // Column skip 2
......@@ -1157,7 +1168,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
(flipY ? (1 << 15) : 0) ; // FLIPV
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RMODE2, v);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE2, (int) v));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE2, (int) v);
}
}
......@@ -1186,7 +1197,7 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
int dh= thispars->pars[P_DCM_HOR];
int ww= thispars->pars[P_SENSOR_PIXH] * dh;
int binning_cost = 0;
int width;
int width,i;
int row_time_in_pixels=0;
int hor_blank_min;
int hor_blank=0;
......@@ -1196,7 +1207,7 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
uint64_t ull_fp1000s;
#endif
int target_virt_width=(thispars->pars[P_VIRT_KEEP])?(thispars->pars[P_VIRT_WIDTH]):0;
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
switch(styp) {
case MT9P_TYP: //page 16
......@@ -1221,19 +1232,19 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
break;
}
hor_blank_min = 208 * thispars->pars[P_BIN_VERT] + 64 + (312 + 44 + binning_cost) / 2;
MDF4(printk("hor_blank_min =%d(0x%x)\n",hor_blank_min,hor_blank_min));
dev_dbg(g_dev_ptr,"{%d} hor_blank_min =%d(0x%x)\n",sensor_port,hor_blank_min,hor_blank_min);
hor_blank = hor_blank_min;
MDF4(printk("hor_blank =%d(0x%x)\n",hor_blank,hor_blank));
dev_dbg(g_dev_ptr,"{%d} hor_blank =%d(0x%x)\n",sensor_port,hor_blank,hor_blank);
row_time_in_pixels = width + hor_blank * 2;
MDF4(printk("row_time_in_pixels =%d(0x%x)\n",row_time_in_pixels,row_time_in_pixels));
int i = 2 * (41 + 208 * thispars->pars[P_BIN_VERT] + 99); ///strange 41 and 99, why not 140?
dev_dbg(g_dev_ptr,"{%d} row_time_in_pixels =%d(0x%x)\n",sensor_port,row_time_in_pixels,row_time_in_pixels);
i = 2 * (41 + 208 * thispars->pars[P_BIN_VERT] + 99); //strange 41 and 99, why not 140?
if(i > row_time_in_pixels) row_time_in_pixels = i;
MDF4(printk("row_time_in_pixels =%d(0x%x)\n",row_time_in_pixels,row_time_in_pixels));
dev_dbg(g_dev_ptr,"{%d} row_time_in_pixels =%d(0x%x)\n",sensor_port,row_time_in_pixels,row_time_in_pixels);
if(target_virt_width > row_time_in_pixels) { // extend line by adding horizontal blanking
hor_blank = (target_virt_width - width) / 2;
if(hor_blank > sensor->maxHorBlank) hor_blank = sensor->maxHorBlank;
row_time_in_pixels = width + 2 * hor_blank;
MDF4(printk("row_time_in_pixels =%d(0x%x)\n",row_time_in_pixels,row_time_in_pixels));
dev_dbg(g_dev_ptr,"{%d} row_time_in_pixels =%d(0x%x)\n",sensor_port,row_time_in_pixels,row_time_in_pixels);
}
break;
case MT9T_TYP:
......@@ -1288,15 +1299,15 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
break;
}
// schedule updating P_VIRT_WIDTH if it changed FIXME: Does not come here?
MDF4(printk("row_time_in_pixels =%d(0x%x), thispars->pars[P_VIRT_WIDTH ]=%d(0x%x)\n",row_time_in_pixels,row_time_in_pixels,(int)thispars->pars[P_VIRT_WIDTH ],(int)thispars->pars[P_VIRT_WIDTH ]));
dev_dbg(g_dev_ptr,"{%d} row_time_in_pixels =%d(0x%x), thispars->pars[P_VIRT_WIDTH ]=%d(0x%x)\n",sensor_port,row_time_in_pixels,row_time_in_pixels,(int)thispars->pars[P_VIRT_WIDTH ],(int)thispars->pars[P_VIRT_WIDTH ]);
if (thispars->pars[P_VIRT_WIDTH ] != row_time_in_pixels) {
SETFRAMEPARS_SET(P_VIRT_WIDTH, row_time_in_pixels);
}
// schedule updating P_MT9X001_HORBLANK senosr register and shadow FIXME: Seems hor_blank is too high. is the width itself subtracted?
if (hor_blank != thispars->pars[P_SENSOR_REGS+P_MT9X001_HORBLANK]) {
MDF4(printk("hor_blank =%d(0x%x), thispars->pars[P_SENSOR_REGS+P_MT9X001_HORBLANK]=%d(0x%x)\n",hor_blank,hor_blank,(int)thispars->pars[P_SENSOR_REGS+P_MT9X001_HORBLANK],(int)thispars->pars[P_SENSOR_REGS+P_MT9X001_HORBLANK]));
dev_dbg(g_dev_ptr,"{%d} hor_blank =%d(0x%x), thispars->pars[P_SENSOR_REGS+P_MT9X001_HORBLANK]=%d(0x%x)\n",sensor_port,hor_blank,hor_blank,(int)thispars->pars[P_SENSOR_REGS+P_MT9X001_HORBLANK],(int)thispars->pars[P_SENSOR_REGS+P_MT9X001_HORBLANK]);
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_HORBLANK, hor_blank);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_HORBLANK, (int)hor_blank));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_HORBLANK, (int)hor_blank);
}
// Now calculate P_PERIOD (extending it as needed)
// int vh, vb, wh, h, dv, sclk, row_time_in_pixels, ve, e, i;
......@@ -1317,13 +1328,13 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
}
}
MDF4(printk("height =%d(0x%x), virt_height=%d(0x%x)\n",height,height,virt_height,virt_height));
dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height);
// limit frame rate (using minimal period), but only in sync mode - async should be programmed to observe minimal period
if ((thispars->pars[P_TRIG] & 4) ==0) {
int virt_height1= thispars->pars[P_PERIOD_MIN]/row_time_in_pixels; // always non-zero, calculated by pgm_limitfps (common)
if ((row_time_in_pixels * virt_height1) < thispars->pars[P_PERIOD_MIN]) virt_height1++; //round up
if (virt_height < virt_height1) virt_height = virt_height1;
MDF4(printk("height =%d(0x%x), virt_height=%d(0x%x)\n",height,height,virt_height,virt_height));
dev_dbg(g_dev_ptr,"{%d} height =%d(0x%x), modified virt_height=%d(0x%x)\n",sensor_port,height,height,virt_height,virt_height);
}
int vert_blank= virt_height - height;
......@@ -1331,16 +1342,20 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
vert_blank = sensor->maxVertBlank;
virt_height = vert_blank + height;
}
MDF4(printk("vert_blank =%d(0x%x), virt_height=%d(0x%x)\n",vert_blank,vert_blank,virt_height,virt_height));
dev_dbg(g_dev_ptr,"{%d} vert_blank =%d(0x%x), virt_height=%d(0x%x)\n",sensor_port,vert_blank,vert_blank,virt_height,virt_height);
// schedule updating P_VIRT_HEIGHT if it changed
MDF4(printk("thispars->pars[P_VIRT_HEIGHT ] =%d(0x%x), virt_height=%d(0x%x)\n",(int)thispars->pars[P_VIRT_HEIGHT ],(int)thispars->pars[P_VIRT_HEIGHT ],virt_height,virt_height));
dev_dbg(g_dev_ptr,"{%d} thispars->pars[P_VIRT_HEIGHT ] =%d(0x%x), virt_height=%d(0x%x)\n",sensor_port,(int)thispars->pars[P_VIRT_HEIGHT ],(int)thispars->pars[P_VIRT_HEIGHT ],virt_height,virt_height);
if (thispars->pars[P_VIRT_HEIGHT ] != virt_height) {
SETFRAMEPARS_SET(P_VIRT_HEIGHT, virt_height);
}
// schedule updating P_PERIOD if it changed
pix_period=row_time_in_pixels*virt_height;
MDF4(printk("thispars->pars[P_PERIOD] =%d(0x%x), pix_period=%d(0x%x)\n",(int)thispars->pars[P_PERIOD],(int)thispars->pars[P_PERIOD],pix_period,pix_period));
if (!pix_period ){
dev_warn(g_dev_ptr,"** mt9x001_pgm_limitfps(%d) pix_period == 0!! (row_time_in_pixels =%d(0x%x), virt_height=%d(0x%x)\n",sensor_port,row_time_in_pixels,row_time_in_pixels,virt_height,virt_height);
pix_period = 1000; // just non-zero
}
dev_dbg(g_dev_ptr,"{%d} thispars->pars[P_PERIOD] =%d(0x%x), pix_period=%d(0x%x)\n",sensor_port,(int)thispars->pars[P_PERIOD],(int)thispars->pars[P_PERIOD],pix_period,pix_period);
if (thispars->pars[P_PERIOD] != pix_period) {
SETFRAMEPARS_SET(P_PERIOD, pix_period);
}
......@@ -1361,15 +1376,15 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
#else
fp1000s= 10*sclk/(pix_period/100);
#endif
MDF4(printk("thispars->pars[P_FP1000S] =%d(0x%x), fp1000s=%d(0x%x)\n",(int)thispars->pars[P_FP1000S],(int)thispars->pars[P_FP1000S],fp1000s,fp1000s));
dev_dbg(g_dev_ptr,"{%d} thispars->pars[P_FP1000S] =%d(0x%x), fp1000s=%d(0x%x)\n",sensor_port,(int)thispars->pars[P_FP1000S],(int)thispars->pars[P_FP1000S],fp1000s,fp1000s);
if (thispars->pars[P_FP1000S] != fp1000s) {
SETFRAMEPARS_SET(P_FP1000S, fp1000s);
}
// schedule updating P_MT9X001_VERTBLANK sensor register and shadow
MDF4(printk("thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK] =%d(0x%x), vert_blank=%d(0x%x)\n",(int)thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK],(int)thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK],vert_blank,vert_blank));
dev_dbg(g_dev_ptr,"{%d} thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK] =%d(0x%x), vert_blank=%d(0x%x)\n",sensor_port,(int)thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK],(int)thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK],vert_blank,vert_blank);
if (vert_blank != thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_VERTBLANK, vert_blank);
MDF4(printk(" SET_SENSOR_MPAR(0x%x, 0x%x,0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_VERTBLANK, (int) vert_blank));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MPAR(0x%x, 0x%x,0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_VERTBLANK, (int) vert_blank);
}
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to gains and sensor register shadows
return 0;
......@@ -1395,21 +1410,22 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int video_exposure = thispars->pars[P_VEXPOS];
int exposure;
MDF4(printk("sensor_port=%d, frame16=%d, frame=0x%lx (%s)exposure=0x%lx, (%s)video_exposure=0x%lx\n", sensor_port, frame16, thispars->pars[P_FRAME], FRAMEPAR_MODIFIED(P_EXPOS)?"*":" ",thispars->pars[P_EXPOS],FRAMEPAR_MODIFIED(P_VEXPOS)?"*":" ",thispars->pars[P_VEXPOS] ));
dev_dbg(g_dev_ptr,"{%d} sensor_port=%d, frame16=%d, frame=0x%lx (%s)exposure=0x%lx, (%s)video_exposure=0x%lx\n",sensor_port, sensor_port, frame16, thispars->pars[P_FRAME], FRAMEPAR_MODIFIED(P_EXPOS)?"*":" ",thispars->pars[P_EXPOS],FRAMEPAR_MODIFIED(P_VEXPOS)?"*":" ",thispars->pars[P_VEXPOS] );
int use_vexp=0;
int sclk=thispars->pars[P_CLK_SENSOR] ; // pixel clock, in Hz
// MDF1(printk(" sclk=0x%x\n",(int) sclk)); // 5b8d800 correct
int vert_blank;
// dev_dbg(g_dev_ptr,"{%d} sclk=0x%x\n",sensor_port,(int) sclk); // 5b8d800 correct
int styp = sensor->sensorType & 7;
// MDF1(printk(" styp=0x%x\n",styp)); // 0x4
// dev_dbg(g_dev_ptr,"{%d} styp=0x%x\n",sensor_port,styp); // 0x4
// NOTE: Is decimation taken care of here ??? FIXME: probably not (here and when deciding to use exposure, not number of lines)!!!
int row_time_in_pixels=thispars->pars[P_VIRT_WIDTH ];
MDF1(printk(" row_time_in_pixels=0x%x\n", row_time_in_pixels)); // 0
// int vert_blank= thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK ];
MDF1(printk(" vert_blank=0x%x\n",vert_blank)); // 0
dev_dbg(g_dev_ptr,"{%d} row_time_in_pixels=0x%x\n",sensor_port, row_time_in_pixels); // 0
vert_blank= thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK ];
dev_dbg(g_dev_ptr,"{%d} vert_blank=0x%x\n",sensor_port,vert_blank); // 0
// if video exposure is non-zero, P_VEXPOS is marked as modified or P_EXPOS is not modified - use video exposure (lines), else - absolute exposure (usec)
if ((video_exposure>0) && (FRAMEPAR_MODIFIED(P_VEXPOS) || ! (FRAMEPAR_MODIFIED(P_EXPOS) || FRAMEPAR_MODIFIED(P_VIRT_WIDTH)) )) { // use number of lines
MDF1(printk(" exposure=%d (0x%x), video_exposure=%d (0x%x)\n", (int) thispars->pars[P_VEXPOS], (int) thispars->pars[P_VEXPOS], (int) video_exposure, (int) video_exposure));
dev_dbg(g_dev_ptr,"{%d} exposure=%d (0x%x), video_exposure=%d (0x%x)\n",sensor_port, (int) thispars->pars[P_VEXPOS], (int) thispars->pars[P_VEXPOS], (int) video_exposure, (int) video_exposure);
#if USELONGLONG
ull_exposure= ((long long)(video_exposure * row_time_in_pixels)) * ((long long) 1000000);
#ifdef __div64_32
......@@ -1508,14 +1524,14 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
#else
fp1000s= 10*sclk/(pix_period/100);
#endif
D1(printk(" fp1000s=%d (0x%x)", (int) fp1000s, (int) fp1000s));
dev_dbg(g_dev_ptr," fp1000s=%d (0x%x)", (int) fp1000s, (int) fp1000s);
if (thispars->pars[P_FP1000S] != fp1000s) {
SETFRAMEPARS_SET(P_FP1000S, fp1000s);
}
}
}
// MDF1(printk(" exposure=0x%x, video_exposure\n", (int) exposure, (int) video_exposure,));
// dev_dbg(g_dev_ptr,"{%d} exposure=0x%x, video_exposure\n",sensor_port, (int) exposure, (int) video_exposure,);
// is video exposure P_VEXPOS modified?
if (thispars->pars[P_VEXPOS] != video_exposure) {
SETFRAMEPARS_SET(P_VEXPOS, video_exposure);
......@@ -1529,16 +1545,16 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
// high word of shutter width (>=3MPix)
if (((styp == MT9T_TYP) || (styp == MT9P_TYP)) && ((video_exposure >> 16) != thispars->pars[P_SENSOR_REGS+P_MT9X001_SHTRWDTHU])) {
SET_SENSOR_MBPAR(sensor_port, frame16,sensor->i2c_addr, P_MT9X001_SHTRWDTHU, video_exposure >> 16);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_SHTRWDTHU, (int) (video_exposure >> 16)));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_SHTRWDTHU, (int) (video_exposure >> 16));
}
// low word of shutter width (all sensors)
if ((video_exposure & 0xffff) != thispars->pars[P_SENSOR_REGS+P_MT9X001_SHTRWDTH]) {
SET_SENSOR_MBPAR(sensor_port, frame16,sensor->i2c_addr, P_MT9X001_SHTRWDTH, video_exposure & 0xffff);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_SHTRWDTH, (int) (video_exposure & 0xffff)));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_SHTRWDTH, (int) (video_exposure & 0xffff));
}
// MDF1(printk(" nupdate=0x%x\n", (int) nupdate));
// dev_dbg(g_dev_ptr,"{%d} nupdate=0x%x\n",sensor_port, (int) nupdate);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to gains and sensor register shadows
MDF1(printk(" exposure=%d (0x%x), video_exposure=%d (0x%x) OK!\n", (int) exposure, (int) exposure, (int) video_exposure, (int) video_exposure));
dev_dbg(g_dev_ptr,"{%d} exposure=%d (0x%x), video_exposure=%d (0x%x) OK!\n",sensor_port, (int) exposure, (int) exposure, (int) video_exposure, (int) video_exposure);
return 0;
}
......@@ -1557,7 +1573,7 @@ unsigned long gain_ajust_mt9x001(
unsigned long maxGain) ///< maximal allowed value of the analog gain (normally 0xfc000 ~ 15.75)
///< @return residual value of the digital gain (>=1.0 0x10000) except limited by the minGain
{
MDF4(printk(" gain=0x%lx, curRegGain=0x%lx, minGain=0x%lx, maxGain=0x%lx\n",gain,curRegGain,minGain,maxGain));
dev_dbg(g_dev_ptr,"gain=0x%lx, curRegGain=0x%lx, minGain=0x%lx, maxGain=0x%lx\n",gain,curRegGain,minGain,maxGain);
int g=gain;
int gainIndex; // index of the gain value in the table (each register value has index, each index has preferrable register value)
int curGainIndex; // current index in the gains table matching sensor register value
......@@ -1571,14 +1587,14 @@ unsigned long gain_ajust_mt9x001(
if (g>maxGain) g=maxGain;
// calculate theoretical gainIndex (0..80)
gainIndex=(g<=0x40000)?(g>>13):((g-0x40000)>>14);
MDF4(printk("gainIndex=0x%x\n",gainIndex));
dev_dbg(g_dev_ptr,"gainIndex=0x%x\n",gainIndex);
// adjust using gain table
while ((gainIndex>0) && (gainTab[gainIndex-1]>=g) && (gainTab[gainIndex-1]>=minGain)) gainIndex--; // adjust down
while ((gainIndex<80) && (gainTab[gainIndex+1]< g) && (gainTab[gainIndex+1]<=maxGain)) gainIndex++; // adjust up
MDF4(printk("gainIndex=0x%x\n",gainIndex));
dev_dbg(g_dev_ptr,"gainIndex=0x%x\n",gainIndex);
// Apply hysteresis
if ((gainIndex==(curGainIndex+1)) && (((gainTab[gainIndex]+gainTab[gainIndex+1])>>1)>g)) gainIndex--;
MDF4(printk("gainIndex=0x%x\n",gainIndex));
dev_dbg(g_dev_ptr,"gainIndex=0x%x\n",gainIndex);
// did the analog gain chnage?
*newRegGain=(gainIndex==curGainIndex)?curRegGain: // no - it is the same
((gainIndex<=32)?gainIndex:(gainIndex+48));
......@@ -1586,7 +1602,7 @@ unsigned long gain_ajust_mt9x001(
gainIndex=curGainIndex;
*newRegGain=curRegGain;
}
MDF4(printk("*newRegGain=0x%lx\n",*newRegGain));
dev_dbg(g_dev_ptr,"*newRegGain=0x%lx\n",*newRegGain);
// now divide gains
ull_gain =((long long) gain) << 16;
#ifdef __div64_32
......@@ -1595,7 +1611,7 @@ unsigned long gain_ajust_mt9x001(
do_div(ull_gain, gainTab[gainIndex]);
// ull_gain /= gainTab[gainIndex];
#endif
MDF4(printk("((unsigned long) ull_gain)=0x%lx\n",((unsigned long) ull_gain)));
dev_dbg(g_dev_ptr,"((unsigned long) ull_gain)=0x%lx\n",(unsigned long) ull_gain);
return ((unsigned long) ull_gain) >> SHIFT_DGAIN;
}
......@@ -1642,15 +1658,17 @@ inline unsigned long getScale16 (unsigned long nominator, ///< 32-bit nominato
uint64_t ull_result =((long long) nominator) << 16;
#if ELPHEL_DEBUG
unsigned long * l_result= (unsigned long *) &ull_result;
dev_dbg(g_dev_ptr,"{%d} l_result[1]=0x%lx, l_result[0]=0x%lx\n",sensor_port,l_result[1],l_result[0]);
#endif
MDF4(printk("l_result[1]=0x%lx, l_result[0]=0x%lx\n",l_result[1],l_result[0]));
#ifdef __div64_32
__div64_32(&ull_result, denominator);
#else
do_div(ull_result, denominator);
// ull_result /= denominator;
#endif
MDF4(printk("l_result[1]=0x%lx, l_result[0]=0x%lx\n",l_result[1],l_result[0]));
#if ELPHEL_DEBUG
dev_dbg("%s l_result[1]=0x%lx, l_result[0]=0x%lx\n",sensor_port,l_result[1],l_result[0]);
#endif
return (unsigned long) ull_result;
}
......@@ -1683,7 +1701,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
unsigned long maxGain;
int limitsModified=0;
int gaingModified=FRAMEPAR_MODIFIED(P_GAING);
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
///make sure limits are OK
if (FRAMEPAR_MODIFIED(P_GAIN_MIN)) {
......@@ -1726,7 +1744,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// scales will not be modified if they make gains out of limit, but gains will be. So automatic white balance should deal with gains, not with scales.
// Preserving application-set values for scales simplifies recovery when the green gain is adjusted so all colors fit in the limits
MDF4(printk("gainr=0x%lx, gaing=0x%lx, gaingb=0x%lx, gainb=0x%lx, rscale_all=0x%lx, gscale_all=0x%lx, bscale_all=0x%lx\n",gainr, gaing, gaingb, gainb, rscale_all, gscale_all, bscale_all));
dev_dbg(g_dev_ptr,"{%d}, gainr=0x%lx, gaing=0x%lx, gaingb=0x%lx, gainb=0x%lx, rscale_all=0x%lx, gscale_all=0x%lx, bscale_all=0x%lx\n",sensor_port, gainr, gaing, gaingb, gainb, rscale_all, gscale_all, bscale_all);
///Verify that green gain itself is within limits:
if (FRAMEPAR_MODIFIED(P_GAING) || limitsModified) {
if (gaing < minAnaGain) {
......@@ -1785,15 +1803,15 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// (not as a result of being limited by minimal/maximal gains)
if ((FRAMEPAR_MODIFIED(P_GAINR)) && (rscale_ctl!= CSCALES_CTL_DISABLE)) {
rscale=getScale16(gainr, gaing);
MDF4(printk("gainr=0x%lx, gaing=0x%lx, rscale=0x%lx\n",gainr, gaing, rscale));
dev_dbg(g_dev_ptr,"{%d} gainr=0x%lx, gaing=0x%lx, rscale=0x%lx\n",sensor_port,gainr, gaing, rscale);
}
if ((FRAMEPAR_MODIFIED(P_GAINGB)) && (gscale_ctl!= CSCALES_CTL_DISABLE)) {
gscale=getScale16(gaingb,gaing);
MDF4(printk("gaingb=0x%lx, gaing=0x%lx, gscale=0x%lx\n",gaingb, gaing, gscale));
dev_dbg(g_dev_ptr,"{%d} gaingb=0x%lx, gaing=0x%lx, gscale=0x%lx\n",sensor_port,gaingb, gaing, gscale);
}
if ((FRAMEPAR_MODIFIED(P_GAINB)) && (bscale_ctl!= CSCALES_CTL_DISABLE)) {
bscale=getScale16(gainb, gaing);
MDF4(printk("gainb=0x%lx, gaing=0x%lx, bscale=0x%lx\n",gainb, gaing, bscale));
dev_dbg(g_dev_ptr,"{%d} gainb=0x%lx, gaing=0x%lx, bscale=0x%lx\n",sensor_port,gainb, gaing, bscale);
}
// remove recalc flag
if (rscale_ctl == CSCALES_CTL_RECALC) rscale_ctl = CSCALES_CTL_NORMAL;
......@@ -1802,20 +1820,20 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// update P_*SCALE if either scale or scale control changed
if (((newval=((rscale_ctl<<CSCALES_CTL_BIT) | (rscale & ((1<<CSCALES_WIDTH)-1)))))!=rscale_all) {
SETFRAMEPARS_SET(P_RSCALE, newval);
MDF4(printk("newval=0x%lx\n",newval));
dev_dbg(g_dev_ptr,"{%d} newval=0x%lx\n",sensor_port,newval);
}
MDF4(printk("newval=0x%lx\n",newval));
dev_dbg(g_dev_ptr,"{%d} newval=0x%lx\n",sensor_port,newval);
if (((newval=((gscale_ctl<<CSCALES_CTL_BIT) | (gscale & ((1<<CSCALES_WIDTH)-1)))))!=gscale_all) {
SETFRAMEPARS_SET(P_GSCALE, newval);
MDF4(printk("newval=0x%lx\n",newval));
dev_dbg(g_dev_ptr,"{%d} newval=0x%lx\n",sensor_port,newval);
}
MDF4(printk("newval=0x%lx\n",newval));
dev_dbg(g_dev_ptr,"{%d} newval=0x%lx\n",sensor_port,newval);
if (((newval=((bscale_ctl<<CSCALES_CTL_BIT) | (bscale & ((1<<CSCALES_WIDTH)-1)))))!=bscale_all) {
SETFRAMEPARS_SET(P_BSCALE, newval);
MDF4(printk("newval=0x%lx\n",newval));
dev_dbg(g_dev_ptr,"{%d} newval=0x%lx\n",sensor_port,newval);
}
MDF4(printk("newval=0x%lx\n",newval));
MDF4(printk("gainr=0x%lx, gaing=0x%lx, gaingb=0x%lx, gainb=0x%lx, rscale_all=0x%lx, gscale_all=0x%lx, bscale_all=0x%lx\n",gainr, gaing, gaingb, gainb, rscale_all, gscale_all, bscale_all));
dev_dbg(g_dev_ptr,"{%d} newval=0x%lx\n",sensor_port,newval);
dev_dbg(g_dev_ptr,"{%d} gainr=0x%lx, gaing=0x%lx, gaingb=0x%lx, gainb=0x%lx, rscale_all=0x%lx, gscale_all=0x%lx, bscale_all=0x%lx\n",sensor_port,gainr, gaing, gaingb, gainb, rscale_all, gscale_all, bscale_all);
// Third part: Split overall gains into analog and digital components
......@@ -1831,7 +1849,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// apply sensor register gain red if it was changed
if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_RED]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RED, newRegGain);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RED, (int) newRegGain));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RED, (int) newRegGain);
}
// schedule application of (residual after analog gain adjustment) digital gain to the red channel
if (digitalGain != thispars->pars[P_DGAINR ]) {
......@@ -1849,7 +1867,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// apply sensor register gain green if it was changed
if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_GREEN1]) {
SET_SENSOR_MBPAR(sensor_port, frame16,sensor->i2c_addr, P_MT9X001_GREEN1, newRegGain);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_GREEN1, (int) newRegGain));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_GREEN1, (int) newRegGain);
}
// schedule application of (residual after analog gain adjustment) digital gain to the green channel
if (digitalGain != thispars->pars[P_DGAING ]) {
......@@ -1866,7 +1884,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// apply sensor register gain blue if it was changed
if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_BLUE]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_BLUE, newRegGain);
MDF4(printk(" SET_SENSOR_MBPAR(0x%0x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_BLUE, (int) newRegGain));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%0x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_BLUE, (int) newRegGain);
}
// schedule application of (residual after analog gain adjustment) digital gain to the blue channel
if (digitalGain != thispars->pars[P_DGAINB ]) {
......@@ -1884,7 +1902,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// apply sensor register gain second green if it was changed
if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_GREEN2]) {
SET_SENSOR_MBPAR(sensor_port, frame16,sensor->i2c_addr, P_MT9X001_GREEN2, newRegGain);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_GREEN2, (int) newRegGain));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_GREEN2, (int) newRegGain);
}
// schedule application of (residual after analog gain adjustment) digital gain to the second green channel
if (digitalGain != thispars->pars[P_DGAINGB ]) {
......@@ -1895,7 +1913,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
testmode= (testmode & 0x10000)? (((testmode & 0xf) << 3) | 1) : 0;
if (testmode != thispars->pars[P_SENSOR_REGS+P_MT9X001_TEST]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr , P_MT9X001_TEST, testmode) ;
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_TEST, (int) testmode));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_TEST, (int) testmode);
}
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to gains and sensor register shadows
......@@ -1936,14 +1954,14 @@ int mt9x001_pgm_triggermode (int sensor_port, ///< sensor p
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
struct frameparspair_t pars_to_update[4]; ///
int nupdate=0;
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
unsigned long newreg= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1] & 0xfeff) | ((thispars->pars[P_TRIG] & 4)?0x100:0);
if (newreg != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1]) {
SET_SENSOR_MBPAR(sensor_port, frame16,sensor->i2c_addr, P_MT9X001_RMODE1, newreg);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE1, (int) newreg));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBPAR(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",sensor_port, sensor_port, frame16, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE1, (int) newreg);
}
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to gains and sensor register shadows
return 0;
......@@ -1961,7 +1979,7 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
///< @return 0 - OK, negative - error
{
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// send all parameters marked as "needed to be processed" to the sensor, clear those flags
// mask out all non sensor pars
......@@ -1972,7 +1990,7 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
// unsigned long bmask32= ((thispars->mod32) >> (P_SENSOR_REGS>>5)) & (P_SENSOR_NUMREGS-1) ; // wromg!, only valid for P_SENSOR_NUMREGS==256 (that is the case, actually)
unsigned long bmask32= ((thispars->mod32) >> (P_SENSOR_REGS>>5)) & (( 1 << (P_SENSOR_NUMREGS >> 5))-1) ;
MDF4(printk(" bmask32=0x%lx, thispars->mod32=0x%lx, P_SENSOR_REGS=0x%x, P_SENSOR_NUMREGS=0x%x\n",bmask32,thispars->mod32,P_SENSOR_REGS,P_SENSOR_NUMREGS));
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);
unsigned long mask;
int index,index32;
struct frameparspair_t pars_to_update[2*P_MULTI_NUMREGS*MAX_SENSORS]; ///
......@@ -1981,14 +1999,14 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
if (GLOBALPARS(sensor_port, G_MULTI_NUM)==0) { // single sensor,don't bother with individual registers, do all old way.
if (bmask32) {
for (index32=(P_SENSOR_REGS>>5); bmask32; index32++, bmask32 >>= 1) {
MDF4(printk(" index32=0x%x, bmask32=0x%lx\n",index32,bmask32));
dev_dbg(g_dev_ptr,"{%d} index32=0x%x, bmask32=0x%lx\n",sensor_port,index32,bmask32);
if (bmask32 & 1) {
mask=thispars->mod[index32];
MDF4(printk(" mask=0x%lx\n",mask));
dev_dbg(g_dev_ptr,"{%d} mask=0x%lx\n",sensor_port,mask);
for (index=(index32<<5); mask; index++, mask >>= 1) {
if (mask & 1) {
X3X3_I2C_SEND2(sensor_port, frame16, sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]);
MDF4(printk("X3X3_I2C_SEND2(0x%x, 0x%x, 0x%lx,0x%x,0x%lx)\n",sensor_port, frame16,sensor->i2c_addr,(index-P_SENSOR_REGS),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,(index-P_SENSOR_REGS),thispars->pars[index]);
}
}
thispars->mod[index32]=0;
......@@ -2001,15 +2019,15 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
///pass 1 - process modified broadcast parameters
if (bmask32) {
for (index32=(P_SENSOR_REGS>>5); bmask32; index32++, bmask32 >>= 1) {
MDF4(printk(" index32=0x%x, bmask32=0x%lx\n",index32,bmask32));
dev_dbg(g_dev_ptr,"{%d} index32=0x%x, bmask32=0x%lx\n",sensor_port,index32,bmask32);
if (bmask32 & 1) {
mask=thispars->mod[index32];
MDF4(printk(" mask=0x%lx\n",mask));
dev_dbg(g_dev_ptr,"{%d} mask=0x%lx\n",sensor_port,mask);
for (index=(index32<<5); mask; index++, mask >>= 1) {
if (mask & 1) {
// apply broadcast register write and schedule change the individual ones (if they are not modified)
SET_SENSOR_MBOPAR(sensor_port, frame16, sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]);
MDF4(printk("SET_SENSOR_MBOPAR(0x%x, 0x%x, 0x%lx,0x%x,0x%lx)\n",sensor_port, frame16, sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]));
dev_dbg(g_dev_ptr,"{%d} SET_SENSOR_MBOPAR(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]);
}
}
thispars->mod[index32]=0;
......@@ -2021,10 +2039,10 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
bmask32= ((thispars->mod32) >> (P_MULTI_REGS >> 5)) & (( 1 << ((((MAX_SENSORS) * (P_MULTI_NUMREGS)) >> 5)+1))-1) ; // added one not to miss parameters with the last group of 32
if (bmask32) {
for (index32=(P_MULTI_REGS>>5); bmask32; index32++, bmask32 >>= 1) {
MDF4(printk(" index32=0x%x, bmask32=0x%lx\n",index32,bmask32));
dev_dbg(g_dev_ptr,"{%d} index32=0x%x, bmask32=0x%lx\n",sensor_port,index32,bmask32);
if (bmask32 & 1) {
mask=thispars->mod[index32];
MDF4(printk(" mask=0x%lx\n",mask));
dev_dbg(g_dev_ptr,"{%d} mask=0x%lx\n",sensor_port,mask);
for (index=(index32<<5); mask && (index < ((P_MULTI_REGS) + ((MAX_SENSORS) * (P_MULTI_NUMREGS)))); index++, mask >>= 1) {
if (mask & 1) {
if ((MULTIRVRSREG(sensor_port, index)) >0 ) {
......@@ -2033,12 +2051,12 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
sensor->i2c_addr + ((MULTIRVRSREG(sensor_port,index)>> 16) * I2C359_INC),
((MULTIRVRSREG(sensor_port,index) & 0xffff)-P_SENSOR_REGS),
thispars->pars[index]);
MDF4(printk(" X3X3_I2C_SEND2(0x%x, 0x%x, 0x%lx,0x%x,0x%lx)\n",
dev_dbg(g_dev_ptr," X3X3_I2C_SEND2(0x%x, 0x%x, 0x%lx,0x%x,0x%lx)\n",
sensor_port,
frame16,
sensor->i2c_addr+((MULTIRVRSREG(sensor_port,index)>> 16)*I2C359_INC),
(int) ((MULTIRVRSREG(sensor_port,index) & 0xffff)-P_SENSOR_REGS),
thispars->pars[index]));
thispars->pars[index]);
}
}
}
......
......@@ -194,6 +194,7 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
;
void mt9x001_set_device(struct device *dev);
#if 0
int adjustBinning_mt9x001(void);
int program_woi_mt9x001(int nonstop);
......
......@@ -92,6 +92,9 @@
#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 <linux/autoconf.h>
//#include <asm/system.h>
......@@ -210,29 +213,29 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
#ifdef NC353 // to hide old code
#define MULTISENSOR_WRITE_I2C(sa,ra,v,sz) \
{rslt |= multisensor_write_i2c((sa),(ra),(v),(sz)) ; \
MDF1(printk(" multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",(int)(sa),(int)(ra),(int)(v),(int)(sz),rslt));}
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",__func__,(int)(sa),(int)(ra),(int)(v),(int)(sz),rslt);}
#define MULTISENSOR_WRITE_I2C16(ra,v) \
{rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(ra),(v),2) ; \
MDF1(printk(" multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",(int)(I2C359_SLAVEADDR),(int)(ra),(int)(v),2,rslt));}
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",__func__,(int)(I2C359_SLAVEADDR),(int)(ra),(int)(v),2,rslt);}
#define MULTISENSOR_WRITE_I2C32(ra,v) \
{rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(I2C359_MSW),(v)>>16,2) ; \
MDF1(printk(" multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",(int)(I2C359_SLAVEADDR),I2C359_MSW,(int)(v)>>16,2,rslt)); \
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",__func__,(int)(I2C359_SLAVEADDR),I2C359_MSW,(int)(v)>>16,2,rslt); \
rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(ra),(v) & 0xffff,2) ; \
MDF1(printk(" multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",(int)(I2C359_SLAVEADDR),(int)(ra),(int)(v)&0xffff,2,rslt)); \
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",__func__,(int)(I2C359_SLAVEADDR),(int)(ra),(int)(v)&0xffff,2,rslt); \
}
#else
// using new access in immediate mode by class name
#define MULTISENSOR_WRITE_I2C(port,name,offs,ra,v) \
{rslt |= multisensor_write_i2c((port),(name),(offs),(ra),(v)) ; \
MDF1(printk(" multisensor_write_i2c(%d, %s, 0x%x, 0x%x, 0x%x) -> %d\n",(int)(port),name,int(offs),(int)(ra),(int)(v),rslt));}
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(%d, %s, 0x%x, 0x%x, 0x%x) -> %d\n",__func__,(int)(port),name,int(offs),(int)(ra),(int)(v),rslt);}
#define MULTISENSOR_WRITE_I2C16(port,ra,v) \
{rslt |= multisensor_write_i2c((port),(name_10359),0,(ra),(v)) ; \
MDF1(printk(" multisensor_write_i2c(%d, %s, 0x%x, 0x%x) -> %d\n",(int)(port),name_10359,(int)(ra),(int)(v),rslt));}
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(%d, %s, 0x%x, 0x%x) -> %d\n",__func__,(int)(port),name_10359,(int)(ra),(int)(v),rslt);}
#define MULTISENSOR_WRITE_I2C32(port,ra,v) \
{rslt |= multisensor_write_i2c((port),(name_10359),0,(I2C359_MSW),(v)>>16) ; \
MDF1(printk(" multisensor_write_i2c(%d, %s, 0x%x, 0x%x) -> %d\n",(int)(port),name_10359,I2C359_MSW,(int)(v)>>16,rslt)); \
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(%d, %s, 0x%x, 0x%x) -> %d\n",__func__,(int)(port),name_10359,I2C359_MSW,(int)(v)>>16,rslt); \
rslt |= multisensor_write_i2c((port),(name_10359),0,(ra), (v) & 0xffff) ; \
MDF1(printk(" multisensor_write_i2c(%d, %s, 0x%x, 0x%x) -> %d\n",(int)(port),name_10359,(int)(ra),(int)(v)&0xffff,2,rslt)); \
dev_dbg(g_dev_ptr,"%s multisensor_write_i2c(%d, %s, 0x%x, 0x%x) -> %d\n",__func__,(int)(port),name_10359,(int)(ra),(int)(v)&0xffff,2,rslt); \
}
#endif
//pars_to_update - local variable
......@@ -254,7 +257,7 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
{ pars_to_update[nupdate ].num= P_M10359_REGS+(r) ;\
pars_to_update[nupdate++].val=(v);\
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v)); \
MDF1(printk(" X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v)));\
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v));\
}
#define SET_10359_PAR32(p,f,r,v) \
......@@ -265,8 +268,8 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (I2C359_MSW), (v)>>16); \
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v) & 0xffff); \
local_irq_restore(flags); \
MDF1(printk(" X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(I2C359_MSW),(int)(v)>>16));\
MDF1(printk(" X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v) & 0xffff));\
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(I2C359_MSW),(int)(v)>>16);\
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v) & 0xffff);\
}
#define SET_10359_PAR(p, f,r,v) \
......@@ -282,7 +285,7 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
// same functions, but do not schedule updating parameter shadows, just send i2c
#define SET_10359_REG16(p, f,r,v) \
{ X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v)); \
MDF1(printk(" X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v)));\
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v));\
}
#define SET_10359_REG32(p, f,r,v) \
......@@ -291,8 +294,8 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (I2C359_MSW), (v)>>16); \
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v) & 0xffff); \
local_irq_restore(flags); \
MDF1(printk(" X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(I2C359_MSW),(int)(v)>>16));\
MDF1(printk(" X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v) & 0xffff));\
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(I2C359_MSW),(int)(v)>>16);\
dev_dbg(g_dev_ptr,"%s X3X3_I2C_SEND2(0x%x, 0x%x, 0x%x, 0x%x)\n",__func__,(int)(f),(int)(I2C359_SLAVEADDR),(int)(r),(int)(v) & 0xffff);\
}
#define SET_10359_REG(p,f,r,v) \
......@@ -304,6 +307,12 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
#define SENSOR_IN_SEQ(x,s) ((((s)>>((x)<<1)) & 3)-1) // returns hardware channel number (0..2) for frame 0..2 in sequence , -1 if disabled
#define SENSOR_IN_SEQ_EN(x,s,m) ((((s)>>((x)<<1)) & 3) && (((m)>> ((((s)>>((x)<<1)) & 3)-1)) & 1)) // returns hardware channel number (0..2) for frame 0..2 in sequence , -1 if disabled
static struct device *g_dev_ptr=NULL; ///< Global pointer to basic device structure. This pointer is used in debugfs output functions
void multi10359_set_device(struct device *dev)
{
g_dev_ptr = dev;
}
//int multisensor_read_i2c(unsigned char theSlave, unsigned char theRegister, unsigned long *theData, int size);
int multisensor_read_i2c (int sensor_port, const char * class_name, int sa7_offs, u32 reg_addr, u32 * reg_datap);
......@@ -345,7 +354,7 @@ int multisensor_pgm_window (int sensor_port, ///< sensor port
///< @return always 0
{
int rslt;
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
rslt = multisensor_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
return rslt;
......@@ -364,7 +373,7 @@ int multisensor_pgm_window_safe (int sensor_port, ///< sensor port
///< @return always 0
{
int rslt;
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
rslt = multisensor_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
return rslt;
}
......@@ -449,7 +458,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
{
struct frameparspair_t pars_to_update[50]; // 11 for 10359,sensor: 3 - broadcast (can be x4) and 4 individual (x3), 11+3*4+4*3+1+1 = 37
int nupdate=0;
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// int fpga_addr= (frame16 <0) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame16);
int fpga_addr= frame16 <0;
......@@ -490,7 +499,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
sFlipY[i]=flipY ^ (composite ?((thispars->pars[P_MULTI_FLIPV] & (1<<i))?1:0):0); // in single (non -composite) mode use just flipY
}
//sFlip* are now per-sensor absolute flips
MDF25(printk("selected=%x flipX=%x flipY=%x sFlipX[0]=%x sFlipY[0]=%x sFlipX[1]=%x sFlipY[1]=%x sFlipX[2]=%x sFlipY[2]=%x\n", selected, flipX,flipY,sFlipX[0],sFlipY[0],sFlipX[1],sFlipY[1],sFlipX[2],sFlipY[2]));
dev_dbg(g_dev_ptr,"%s selected=%x flipX=%x flipY=%x sFlipX[0]=%x sFlipY[0]=%x sFlipX[1]=%x sFlipY[1]=%x sFlipX[2]=%x sFlipY[2]=%x\n",__func__, selected, flipX,flipY,sFlipX[0],sFlipY[0],sFlipX[1],sFlipY[1],sFlipX[2],sFlipY[2]);
// calculations valid for individual and composite frames
int styp = sensor->sensorType & 7;
dh= thispars->pars[P_DCM_HOR];
......@@ -516,7 +525,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
wt = thispars->pars[P_WOI_TOP];
// flip margins for mirrored images (except oversized, not to rely on sensor->clearWidth/sensor->clearHeight
//-------------------------
MDF25(printk("dv=0x%x dh=0x%x ww=0x%x wh=0x%x wl=0x%x wt=0x%x \n",dv,dh,ww,wh,wl,wt));
dev_dbg(g_dev_ptr,"%s dv=0x%x dh=0x%x ww=0x%x wh=0x%x wl=0x%x wt=0x%x \n",__func__,dv,dh,ww,wh,wl,wt);
memcpy(wois, &(thispars->pars[P_MULTI_WOI]), sizeof(wois)); // copy WOI parameters for 3 sensors
if (composite && flipY) { // reverse sequence
......@@ -584,7 +593,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
}
}
for (i=0; (v=SENSOR_IN_SEQ(i,sequence))>=0;i++) active |= (1<<v);
MDF25(printk("height1=0x%x height2=0x%x height3=0x%x\n",height1, height2, height3));
dev_dbg(g_dev_ptr,"%s height1=0x%x height2=0x%x height3=0x%x\n",__func__,height1, height2, height3);
......@@ -601,19 +610,19 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
}
}
// multiFlip* are set in the sub-frame sequence (accounting for the global FLIP_V, bit 0 - top subframe,1 - middle, 2 - last
MDF25(printk("multiFlipX=0x%x multiFlipY=0x%x\n",multiFlipX, multiFlipY));
dev_dbg(g_dev_ptr,"%s multiFlipX=0x%x multiFlipY=0x%x\n",__func__,multiFlipX, multiFlipY);
// modify - multiFlipX,multiFlipY applies to sensors, not frames ???? No, they apply to sub-frames
relFlipX= (multiFlipX ^ (multiFlipX>>1))& 3;
relFlipY= (multiFlipY ^ (multiFlipY>>1))& 3;
MDF25(printk("relFlipX=0x%x relFlipY=0x%x\n",relFlipX, relFlipY));
dev_dbg(g_dev_ptr,"%s relFlipX=0x%x relFlipY=0x%x\n",__func__,relFlipX, relFlipY);
if (relFlipY & 1) vblank2+=dv;
if (relFlipY & 2) vblank3+=((vblank3>=dv) && (vblank2>vblank3))?-dv:dv; // Keep the total height constant, if possible. If not possible - increase
hactDelay=(relFlipX ^ (relFlipX << 1)) & 3;
MDF25(printk("hactDelay=0x%x vblank2=0x%x, vblank3=0x%x\n",hactDelay, vblank2, vblank3));
dev_dbg(g_dev_ptr,"%s hactDelay=0x%x vblank2=0x%x, vblank3=0x%x\n",__func__,hactDelay, vblank2, vblank3);
// Apply height1, height2, height3
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(0,sequence)]=height1; // always on,>= other frame heights
if ((SENSOR_IN_SEQ(1,sequence)>=0) && (SENSOR_IN_SEQ(1,sequence)!=SENSOR_IN_SEQ(0,sequence))) {
......@@ -637,10 +646,10 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+0]=ww; // all channels - same width, include margins (before decimation)
wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+1]=ww;
wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+2]=ww;
MDF25(printk("wois[LEFT1]=0x%lx, wois[LEFT2]=0x%lx, wois[LEFT3]=0x%lx\n", wois[(P_MULTI_LEFT1-P_MULTI_WOI)+0],wois[(P_MULTI_LEFT1-P_MULTI_WOI)+1],wois[(P_MULTI_LEFT1-P_MULTI_WOI)+2] ));
MDF25(printk("wois[WIDTH1]=0x%lx\n", wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+0] ));
MDF25(printk("wois[TOP1]=0x%lx, wois[TOP2]=0x%lx, wois[TOP3]=0x%lx\n", wois[(P_MULTI_TOP1-P_MULTI_WOI)+0],wois[(P_MULTI_TOP1-P_MULTI_WOI)+1],wois[(P_MULTI_TOP1-P_MULTI_WOI)+2] ));
MDF25(printk("wois[HEIGHT1]=0x%lx, wois[HEIGHT2]=0x%lx, wois[HEIGHT3]=0x%lx\n", wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0],wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1],wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2] ));
dev_dbg(g_dev_ptr,"%s wois[LEFT1]=0x%lx, wois[LEFT2]=0x%lx, wois[LEFT3]=0x%lx\n",__func__, wois[(P_MULTI_LEFT1-P_MULTI_WOI)+0],wois[(P_MULTI_LEFT1-P_MULTI_WOI)+1],wois[(P_MULTI_LEFT1-P_MULTI_WOI)+2] );
dev_dbg(g_dev_ptr,"%s wois[WIDTH1]=0x%lx\n",__func__, wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+0] );
dev_dbg(g_dev_ptr,"%s wois[TOP1]=0x%lx, wois[TOP2]=0x%lx, wois[TOP3]=0x%lx\n",__func__, wois[(P_MULTI_TOP1-P_MULTI_WOI)+0],wois[(P_MULTI_TOP1-P_MULTI_WOI)+1],wois[(P_MULTI_TOP1-P_MULTI_WOI)+2] );
dev_dbg(g_dev_ptr,"%s wois[HEIGHT1]=0x%lx, wois[HEIGHT2]=0x%lx, wois[HEIGHT3]=0x%lx\n",__func__, wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0],wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1],wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2] );
// TODO: Apply required height to the channels. If nothing but the direct channel is needed - apply it to sensor parameters
......@@ -648,14 +657,14 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
// Modify first sensor height even if it is increased to include part of the gap and minHeight
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(0,sequence)]= wh;
sequence &= 3; // turn off frames 2, 3
MDF25(printk("sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",sequence, height1, vblank2, height2, vblank3 ,height3 ));
dev_dbg(g_dev_ptr,"%s sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",__func__,sequence, height1, vblank2, height2, vblank3 ,height3 );
} else if ((wt+wh-height1-vblank2) < (height2+vblank3+(sensor->minHeight*dv))) { // Only first 2 sensors are needed - reduce second frame (10359, not the sensor)
height2=wh+wt-height1-vblank2; // only 10359, not the sensor
sequence &= 0xf; // turn off frame 3
MDF25(printk("sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",sequence, height1, vblank2, height2, vblank3 ,height3 ));
dev_dbg(g_dev_ptr,"%s sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",__func__,sequence, height1, vblank2, height2, vblank3 ,height3 );
} else { // all 3 sensors needed, adjust height3 to make sure 10359 sends out exactly wh/dv lines (vblank* could be adjusted to compensate for Bayer when flipping)
height3=wh+wt-height1-vblank2-height2-vblank3;
MDF25(printk("sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",sequence, height1, vblank2, height2, vblank3 ,height3 ));
dev_dbg(g_dev_ptr,"%s sequence=%x height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",__func__,sequence, height1, vblank2, height2, vblank3 ,height3 );
}
// zero out unused frames/blanks before them
......@@ -675,7 +684,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
vblank3/=dv;
height3/=dv;
}
MDF25(printk("height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",height1, vblank2, height2, vblank3 ,height3 ));
dev_dbg(g_dev_ptr,"%s height1=0x%x vblank2=0x%x height2=0x%x vblank3=0x%x height3=0x%x \n",__func__,height1, vblank2, height2, vblank3 ,height3 );
// un-apply dh from ww - number of pixels to be read in a line in frames2,3
if (dh>1) ww/=dh;
w359=ww;
......@@ -686,7 +695,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
((multiFlipY & 1)<<1) | ((multiFlipY & 2) << 2) | ((multiFlipY & 4) << 3) | 0x40; // 0x40 as a composite frame mark (test with &0xc0!=0 - future)
if (flipX) multi_mode_flips ^= 0x15;
if (flipY) multi_mode_flips ^= 0x2a;
MDF25(printk("sequence=0x%x flipX=%x flipY=%x multi_mode_flips=0x%x \n",sequence,flipX,flipY,multi_mode_flips ));
dev_dbg(g_dev_ptr,"%s sequence=0x%x flipX=%x flipY=%x multi_mode_flips=0x%x \n",__func__,sequence,flipX,flipY,multi_mode_flips );
SETFRAMEPARS_COND(P_MULTI_MODE_FLIPS, multi_mode_flips);
// subtract (2 * COLOR_MARGINS) from the first and last frame
......@@ -733,23 +742,23 @@ if (GLOBALPARS(sensor_port, G_MULTI_CFG) & (1 <<G_MULTI_CFG_BEFORE)) {
// comparisons are only valid if there are no individual parameters that were changed
// program sensors width (same for all sensors, use broadcast mode)
ww=wois[(P_MULTI_WIDTH1- P_MULTI_WOI)+(composite?SENSOR_IN_SEQ(0,sequence):(selected-1))];
MDF25(printk(" selected=%x, thispars->pars[P_MULTI_SELECTED]=%x composite=%x sequence=%x\n", selected, (int) thispars->pars[P_MULTI_SELECTED], composite, sequence));
dev_dbg(g_dev_ptr,"%s selected=%x, thispars->pars[P_MULTI_SELECTED]=%x composite=%x sequence=%x\n",__func__, selected, (int) thispars->pars[P_MULTI_SELECTED], composite, sequence);
if ((ww-1) != thispars->pars[P_SENSOR_REGS+P_MT9X001_WIDTH]) {
SET_SENSOR_MBPAR(sensor_port, fpga_addr, sensor->i2c_addr, P_MT9X001_WIDTH, ww-1);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x,0x%x, 0x%x, 0x%x)\n", fpga_addr, (int) sensor->i2c_addr, (int) P_MT9X001_WIDTH, (int) ww-1));
dev_dbg(g_dev_ptr,"%s SET_SENSOR_MBPAR(0x%x,0x%x, 0x%x, 0x%x)\n",__func__, fpga_addr, (int) sensor->i2c_addr, (int) P_MT9X001_WIDTH, (int) ww-1);
}
// Program binning/decimation (also common but some older sensors)
if((styp == MT9T_TYP) || (styp == MT9P_TYP)) { // 3MPix and 5MPix sensors
v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM] & 0xff88) | ((bv - 1) << 4) | (dv - 1) ;
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM]) {
SET_SENSOR_PAR(sensor_port, fpga_addr,sensor->i2c_addr, P_MT9X001_RAM, v);
MDF4(printk(" SET_SENSOR_PAR(0x%x,0x%x, 0x%x, 0x%x)\n", fpga_addr, (int) sensor->i2c_addr, (int) P_MT9X001_RAM, (int) v));
dev_dbg(g_dev_ptr,"%s SET_SENSOR_PAR(0x%x,0x%x, 0x%x, 0x%x)\n",__func__, fpga_addr, (int) sensor->i2c_addr, (int) P_MT9X001_RAM, (int) v);
}
v=(thispars->pars[P_SENSOR_REGS+P_MT9X001_CAM] & 0xff88) | ((bh - 1) << 4) | (dh - 1);
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_CAM]) {
SET_SENSOR_PAR(sensor_port, fpga_addr,sensor->i2c_addr, P_MT9X001_CAM, v);
MDF4(printk(" SET_SENSOR_PAR(0x%x,0x%x, 0x%x, 0x%x)\n", fpga_addr, (int) sensor->i2c_addr, (int) P_MT9X001_CAM, (int) v));
dev_dbg(g_dev_ptr,"%s SET_SENSOR_PAR(0x%x,0x%x, 0x%x, 0x%x)\n",__func__, fpga_addr, (int) sensor->i2c_addr, (int) P_MT9X001_CAM, (int) v);
}
} else { // 1.3 and 2 MPix sensors
v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1] & 0xffc3) | // preserve other bits from shadows (trigger mode moved to other function)
......@@ -759,7 +768,7 @@ if (GLOBALPARS(sensor_port, G_MULTI_CFG) & (1 <<G_MULTI_CFG_BEFORE)) {
((dv == 8) ? (1 << 5) : 0) ; // Row skip 8
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1]) {
SET_SENSOR_MBPAR(sensor_port,fpga_addr,sensor->i2c_addr, P_MT9X001_RMODE1, v);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x,0x%x, 0x%x, 0x%x)\n", fpga_addr, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE1, (int) v));
dev_dbg(g_dev_ptr,"%s SET_SENSOR_MBPAR(0x%x,0x%x, 0x%x, 0x%x)\n",__func__, fpga_addr, (int) sensor->i2c_addr, (int) P_MT9X001_RMODE1, (int) v);
}
}
// Other registers are programmed individually
......@@ -944,12 +953,12 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
// .hact_delay = -2500, // -2.5ns delay in ps
// .sensorDelay = 2460, // Delay from sensor clock at FPGA output to pixel data transition (FPGA input), short cable (ps)
multi_unitialized=0; // reset this static variable - it will prevent copying individual flips to multiple until composite mode is used
MDF3(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
GLOBALPARS(sensor_port,G_SENS_AVAIL)=0; // no 10359A board present
if (frame16 >= 0) return -1; // can only work in ASAP mode
if (thispars->pars[P_SENSOR]) return 0; // Sensor is already detected - do not bother (to re-detect it P_SENSOR should be set to 0)
MDF24(printk("Probing 10359 board, i2c bitdelays=0x%08x, hardware_i2c_running=%d\n",i2c_delays(0),i2s_running()));
#ifdef NC353
dev_dbg(g_dev_ptr,"%s Probing 10359 board, i2c bitdelays=0x%08x, hardware_i2c_running=%d\n",__func__,i2c_delays(0),i2s_running());
if (multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version, 4)<0) return -1;
#else
if (X3X3_I2C_RCV4(sensor_port, I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version)<0) return -1;
......@@ -957,8 +966,8 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
// Here we see that 10359A responds somehow. If next fails, no sense to try other sensor types.
multi_phases_initialized=0;
sensor->sensorType=SENSOR_NONE;
add_sensor_proc(onchange_multisens, &multisensor_pgm_multisens); // process 10359-specific parameters
add_sensor_proc(onchange_sensorphase, &multisensor_pgm_sensorphase); // set clock/phase for the 10359A
add_sensor_proc(sensor_port,onchange_multisens, &multisensor_pgm_multisens); // process 10359-specific parameters
add_sensor_proc(sensor_port,onchange_sensorphase, &multisensor_pgm_sensorphase); // set clock/phase for the 10359A
if ((((bitstream_version ^ I2C359_MINVERSION) & 0xffff0000)!=0) || ((bitstream_version & 0xffff) < (I2C359_MINVERSION & 0xffff))) {
printk ("invalid 10359 bitstream version, found 0x%08lx, required >= 0x%08x\n",bitstream_version, I2C359_MINVERSION );
......@@ -1023,8 +1032,8 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
GLOBALPARS(sensor_port,G_SENS_AVAIL) |= 1<< (GLOBALPARS(sensor_port,G_SENS_AVAIL)); // temporary to indicate sensor detection functions that they need to initialize multisensor registers
for (i=0;i<MAX_SENSORS;i++) {
MDF24(printk("Probing sensor port %d, i2c bitdelays=0x%08x\n",i,i2c_delays(0)));
#ifdef NC353
dev_dbg(g_dev_ptr,"%s Probing sensor port %d, i2c bitdelays=0x%08x\n",__func__,i,i2c_delays(0));
rslt= multisensor_read_i2c(sensor_port,
MT9P001_I2C_ADDR + ((i+1) * I2C359_INC),
P_MT9X001_CHIPVER,
......@@ -1036,7 +1045,7 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
P_MT9X001_CHIPVER,
&sensor_id[i]);
#endif
MDF24(printk("Probing sensor port %d, i2c bitdelays=0x%08x, rslt=0x%x\n",i,i2c_delays(0),rslt));
// dev_dbg(g_dev_ptr,"%s Probing sensor port %d, i2c bitdelays=0x%08x, rslt=0x%x\n",__func__,i,i2c_delays(0),rslt);
if (rslt==0) {
if (((sensor_id[i] ^ MT9P001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9P001 2592x1944 sensor on 10359A port %d, chip ID=%lx\n",(i+1), sensor_id[i]);
......@@ -1058,13 +1067,13 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
// At least one MT9P0X1 sensor found, initializing them in broadcast mode (will still need to modify phases - both 10353 and 10359
this_sensor_type=mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
// for (i=0;i<8;i++) {
// MDF(printk("i=%d, m=0x%lx\n",i,GLOBALPARS(G_MULTI_REGSM+i)));
// dev_dbg(g_dev_ptr,"%s i=%d, m=0x%lx\n",__func__,i,GLOBALPARS(G_MULTI_REGSM+i));
// }
initMultiPars(sensor_port); // this time the registors that need to have individual shadows are known, initialize the corresponding data structures
// memcpy(psensor, sensor, sizeof(struct sensor_t)); // copy physical sensor definitions to the save area (so some can be replaced by modified ones)
// MDF24(printk(" before: sensorproc_phys->sensor.sensorDelay=0x%x\n", sensorproc_phys->sensor.sensorDelay));
// dev_dbg(g_dev_ptr,"%s before: sensorproc_phys->sensor.sensorDelay=0x%x\n",__func__, sensorproc_phys->sensor.sensorDelay);
copy_sensorproc(sensor_port, sensorproc_phys); // save physical sensor functions
// MDF24(printk(" after: sensorproc_phys->sensor.sensorDelay=0x%x\n", sensorproc_phys->sensor.sensorDelay));
// dev_dbg(g_dev_ptr,"%s after: sensorproc_phys->sensor.sensorDelay=0x%x\n",__func__, sensorproc_phys->sensor.sensorDelay);
// Now calculate phases, swap ones from the sensor
long * multiOutDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_OUT);
......@@ -1072,15 +1081,15 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
sensor->hact_delay=0; // No hact delay on 10359 output
sensor->sensorDelay=multiOutDelay[0];
MDF24(printk("replaced: sensor->sensorDelay=0x%x\n", sensor->sensorDelay));
dev_dbg(g_dev_ptr,"%s replaced: sensor->sensorDelay=0x%x\n",__func__, sensor->sensorDelay);
//sensorproc_phys->sensor
/*
Now overwrite sensor functions with it's own (originals (physical sensor ones) are already copied to the local structure
*/
// add_sensor_proc(onchange_multisens, &multisensor_pgm_multisens); // process 10359-specific parameters
add_sensor_proc(onchange_sensorregs, &multisensor_pgm_sensorregs); // write sensor 10359 registers (only changed from outside the driver)
add_sensor_proc(onchange_window, &multisensor_pgm_window); // program sensor WOI and mirroring (flipping)
add_sensor_proc(onchange_window_safe, &multisensor_pgm_window_safe); // program sensor WOI and mirroring (flipping) - now - only flipping? with lower latency
// add_sensor_proc(sensor_port,onchange_multisens, &multisensor_pgm_multisens); // process 10359-specific parameters
add_sensor_proc(sensor_port,onchange_sensorregs, &multisensor_pgm_sensorregs); // write sensor 10359 registers (only changed from outside the driver)
add_sensor_proc(sensor_port,onchange_window, &multisensor_pgm_window); // program sensor WOI and mirroring (flipping)
add_sensor_proc(sensor_port,onchange_window_safe, &multisensor_pgm_window_safe); // program sensor WOI and mirroring (flipping) - now - only flipping? with lower latency
// Initialize other 10359A parameters (move it to init/afterinit?)
......@@ -1180,7 +1189,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
int i,j,sh;
unsigned long wois[12];
int dv= thispars->pars[P_DCM_VERT];
MDF3(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
// Handling sensor mask - which sensors (of the available) to use
int sensor_mask=(thispars->pars[P_MULTISENS_EN]) & GLOBALPARS(sensor_port, G_SENS_AVAIL);
if (!sensor_mask) sensor_mask=GLOBALPARS(sensor_port, G_SENS_AVAIL) ;// if none sensors were enabled - enable all what is available (same as with WOI size)
......@@ -1201,8 +1210,8 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
// TODO: recalculate sequence when MULTISENS_EN is chnaged (tried 5 - did not modify sequence, showed first frame only)
// Here - only recalculate SENSOR_HEIGHT, skipping disabled sensors. in multisensor_pgm_window() will need to skip disabled also
// No above is not really needed, sequence+enable can be handled by application software
MDF25(printk(" composite=0x%x\n",composite));
MDF25(printk(" sequence=0x%x\n", sequence));
dev_dbg(g_dev_ptr,"%s composite=0x%x\n",__func__,composite);
dev_dbg(g_dev_ptr,"%s sequence=0x%x\n",__func__, sequence);
// if sequence is zero, put "1-2-3"
if (sequence==0) {
j=1;
......@@ -1233,9 +1242,9 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
}
if ((selected==0) || !((1 << (selected-1)) & GLOBALPARS(sensor_port, G_SENS_AVAIL))) selected=sequence & 3; // if not set or invalid - set to first in sequence
MDF25(printk(" selected=0x%x, thispars->pars[P_MULTI_SELECTED]=0x%x\n", selected, (int) thispars->pars[P_MULTI_SELECTED]));
MDF25(printk(" sequence=0x%x\n", sequence));
MDF25(printk(" sensor_mask=0x%x\n", sensor_mask));
dev_dbg(g_dev_ptr,"%s selected=0x%x, thispars->pars[P_MULTI_SELECTED]=0x%x\n",__func__, selected, (int) thispars->pars[P_MULTI_SELECTED]);
dev_dbg(g_dev_ptr,"%s sequence=0x%x\n",__func__, sequence);
dev_dbg(g_dev_ptr,"%s sensor_mask=0x%x\n",__func__, sensor_mask);
SETFRAMEPARS_COND(P_MULTI_SELECTED, selected);
SETFRAMEPARS_COND(P_MULTI_SEQUENCE, sequence);
SETFRAMEPARS_COND(P_MULTISENS_EN, sensor_mask);
......@@ -1245,14 +1254,14 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
int old_sensor=prev_selected-1; // may be <0
int new_sensor=selected-1; // >=0
if (multi_unitialized && (!prev_composite) && (old_sensor>=0)) { // was single-sensor mode, copy P_WOI_* to individual sensor WOI and FLIPS
MDF25(printk(" multi_unitialized=%d old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", multi_unitialized, old_sensor, multi_fliph,multi_flipv));
dev_dbg(g_dev_ptr,"%s multi_unitialized=%d old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, multi_unitialized, old_sensor, multi_fliph,multi_flipv);
wois[(P_MULTI_WIDTH1- P_MULTI_WOI)+old_sensor]= prevpars->pars[P_WOI_WIDTH];
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+old_sensor]= prevpars->pars[P_WOI_HEIGHT];
wois[(P_MULTI_LEFT1- P_MULTI_WOI)+old_sensor]= prevpars->pars[P_WOI_LEFT];
wois[(P_MULTI_TOP1- P_MULTI_WOI)+old_sensor]= prevpars->pars[P_WOI_TOP];
multi_fliph= (multi_fliph & (~(1<<old_sensor))) | ((prevpars->pars[P_FLIPH] & 1) << old_sensor);
multi_flipv= (multi_flipv & (~(1<<old_sensor))) | ((prevpars->pars[P_FLIPV] & 1) << old_sensor);
MDF25(printk(" multi_unitialized=%d old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", multi_unitialized, old_sensor, multi_fliph,multi_flipv));
dev_dbg(g_dev_ptr,"%s multi_unitialized=%d old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, multi_unitialized, old_sensor, multi_fliph,multi_flipv);
}
if (multi_unitialized && (!composite) && (prev_composite || ((new_sensor>=0) && (old_sensor!=new_sensor)))) { // now single-sensor mode, set P_WOI* from saved parameters
if ((wois[(P_MULTI_WIDTH1- P_MULTI_WOI)+new_sensor]==0) || (wois[(P_MULTI_HEIGHT1- P_MULTI_WOI)+new_sensor]==0)) {
......@@ -1266,7 +1275,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
wois[(P_MULTI_LEFT1- P_MULTI_WOI)+new_sensor]= 0;
wois[(P_MULTI_TOP1- P_MULTI_WOI)+new_sensor]= 0;
multi_fliph= (multi_fliph & (~(1<<new_sensor))); // =0
MDF25(printk(" new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", new_sensor, old_sensor, multi_fliph,multi_flipv));
dev_dbg(g_dev_ptr,"%s new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, new_sensor, old_sensor, multi_fliph,multi_flipv);
multi_flipv= (multi_flipv & (~(1<<new_sensor))); // =0
} else { // was one single channel, now the different (not initialized window) one - copy window parameters
wois[(P_MULTI_WIDTH1- P_MULTI_WOI)+new_sensor]= prevpars->pars[P_WOI_WIDTH];
......@@ -1275,7 +1284,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
wois[(P_MULTI_TOP1- P_MULTI_WOI)+new_sensor]= prevpars->pars[P_WOI_TOP];
multi_fliph= (multi_fliph & (~(1<<new_sensor))) | ((prevpars->pars[P_FLIPH] & 1) << new_sensor);
multi_flipv= (multi_flipv & (~(1<<new_sensor))) | ((prevpars->pars[P_FLIPV] & 1) << new_sensor);
MDF25(printk(" new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", new_sensor, old_sensor, multi_fliph,multi_flipv));
dev_dbg(g_dev_ptr,"%s new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, new_sensor, old_sensor, multi_fliph,multi_flipv);
}
}
// saved sensor WOI are OK (or just fixed), use them
......@@ -1285,7 +1294,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
SETFRAMEPARS_COND(P_WOI_TOP, wois[(P_MULTI_TOP1- P_MULTI_WOI)+new_sensor] );
SETFRAMEPARS_COND(P_FLIPH, (multi_fliph>>new_sensor) & 1);
SETFRAMEPARS_COND(P_FLIPV, (multi_flipv>>new_sensor) & 1);
MDF25(printk(" new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n", new_sensor, old_sensor, multi_fliph,multi_flipv));
dev_dbg(g_dev_ptr,"%s new_sensor=%x old_sensor=%x, multi_fliph=%x multi_flipv=%x\n",__func__, new_sensor, old_sensor, multi_fliph,multi_flipv);
}
// Validate hights for all enabled channels (OK to skip disabled here)
int oversize=thispars->pars[P_OVERSIZE];
......@@ -1301,30 +1310,30 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
else if ((!oversize) && (height1 > sensor->imageHeight)) height1=sensor->imageHeight; // use clearHeight here?
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(0,sequence)]=height1;
total_height=height1;
MDF25(printk(" total_height=0x%x\n",total_height));
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
// is there frame 2 enabled?
int multi_frame=0;
if (composite && SENSOR_IN_SEQ_EN(1,sequence,sensor_mask)) { // specified in sequence is enabled
multi_frame=1;
total_height+=(vblank+(2 * COLOR_MARGINS))*dv;
MDF25(printk(" total_height=0x%x\n",total_height));
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
if (!height2) height2=sensor->imageHeight;
if (height2 < sensor->minHeight) height2=sensor->minHeight;
else if (height2 > sensor->arrayHeight) height2=sensor->arrayHeight;
else if ((!oversize) && (height2 > sensor->imageHeight)) height2=sensor->imageHeight; // use clearHeight here?
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(1,sequence)]=height2;
total_height+=height2;
MDF25(printk(" total_height=0x%x\n",total_height));
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
if (SENSOR_IN_SEQ_EN(2,sequence,sensor_mask)) {
total_height+=(vblank+(2 * COLOR_MARGINS))*dv;
MDF25(printk(" total_height=0x%x\n",total_height));
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
if (!height3) height3=sensor->imageHeight;
if (height3 < sensor->minHeight) height3=sensor->minHeight;
else if (height3 > sensor->arrayHeight) height3=sensor->arrayHeight;
else if ((!oversize) && (height2 > sensor->imageHeight)) height3=sensor->imageHeight; // use clearHeight here?
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(2,sequence)]=height3;
total_height+=height3;
MDF25(printk(" total_height=0x%x\n",total_height));
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
}
}
if (composite) {
......@@ -1364,7 +1373,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
}
SETFRAMEPARS_COND(P_MULTI_FLIPH, multi_fliph);
SETFRAMEPARS_COND(P_MULTI_FLIPV, multi_flipv);
MDF25(printk(" total_height=0x%x\n",total_height));
dev_dbg(g_dev_ptr,"%s total_height=0x%x\n",__func__,total_height);
SETFRAMEPARS_COND(P_SENSOR_HEIGHT, total_height);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes, schedule functions
......@@ -1409,7 +1418,7 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
long * cableDelay;
long * FPGADelay;
int clk_period;
MDF3(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
long sdram_chen=thispars->pars[P_M10359_REGS+I2C359_SDRAM_CHEN];
int adjustSDRAMNeed=0;
int thisPhaseSDRAM=thispars->pars[P_MULTI_PHASE_SDRAM];
......@@ -1433,17 +1442,17 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C1);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P1);
thisPhase1=calcThisPhase(clk_period, FPGADelay[0], cableDelay[0], sensorproc_phys->sensor.sensorDelay) | 0x80000;
MDF24(printk("cableDelay1=0x%lx FPGADelay1= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase1=0x%x\n",cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase1));
dev_dbg(g_dev_ptr,"%s cableDelay1=0x%lx FPGADelay1= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase1=0x%x\n",__func__,cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase1);
cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C2);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P2);
thisPhase2=calcThisPhase(clk_period, FPGADelay[0], cableDelay[0], sensorproc_phys->sensor.sensorDelay) | 0x80000;
MDF24(printk("cableDelay2=0x%lx FPGADelay2= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase3=0x%x\n",cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase2));
dev_dbg(g_dev_ptr,"%s cableDelay2=0x%lx FPGADelay2= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase3=0x%x\n",__func__,cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase2);
cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C3);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P3);
thisPhase3=calcThisPhase(clk_period, FPGADelay[0], cableDelay[0], sensorproc_phys->sensor.sensorDelay) | 0x80000;
MDF24(printk("cableDelay3=0x%lx FPGADelay3= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase3=0x%x\n",cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase3));
dev_dbg(g_dev_ptr,"%s cableDelay3=0x%lx FPGADelay3= 0x%lx sensorproc_phys->sensor.sensorDelay=0x%x, thisPhase3=0x%x\n",__func__,cableDelay[0] ,FPGADelay[0], sensorproc_phys->sensor.sensorDelay,thisPhase3);
// TODO: calculate SDRAM phase here too.
adjustSDRAMNeed=1;
......@@ -1473,7 +1482,7 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
rslt= multisensor_set_phase (sensor_port, I2C359_DCM_SDRAM, resetThisDCM, thisPhaseSDRAM, prevpars->pars[P_MULTI_PHASE_SDRAM]);
if ((rslt>=0) && (rslt != thisPhaseSDRAM)) SETFRAMEPARS_SET(P_MULTI_PHASE_SDRAM, rslt);
if (resetThisDCM) {
MDF16(printk("re-initializing SDRAM on 10359 after DCM reset\n"));
dev_dbg(g_dev_ptr,"%s re-initializing SDRAM on 10359 after DCM reset\n",__func__);
multisensor_initSDRAM(sensor_port, thispars); // init 10359 SDRAM
}
// Test memory phase here
......@@ -1644,7 +1653,7 @@ int multisensor_set_phase_recover(int sensor_port, ///< sensor port nu
else goodPhase = newPhase;
}
rslt=goodPhase;
MDF24(printk("Reduced NewPhase, goodPhase= 0x%lx oldPhase= 0x%lx\r\n", goodPhase, oldPhase ));
dev_dbg(g_dev_ptr,"%s Reduced NewPhase, goodPhase= 0x%lx oldPhase= 0x%lx\r\n",__func__, goodPhase, oldPhase );
}
return rslt;
}
......@@ -1675,7 +1684,7 @@ int multisensor_set_phase (int sensor_port, ///< sensor port number (0
oldPhase=0;
}
if (newPhase!=oldPhase) {
MDF16(printk("newPhase= 0x%lx oldPhase= 0x%lx\r\n", newPhase, oldPhase ));
dev_dbg(g_dev_ptr,"%s newPhase= 0x%lx oldPhase= 0x%lx\r\n",__func__, newPhase, oldPhase );
old_phase= oldPhase & 0xffff; if (old_phase>=0x8000) old_phase-=0x10000; // make it signed
old_phase90= (oldPhase >> 16) & 3;
if ((old_phase > 255) || (old_phase < -255)) {
......@@ -1691,9 +1700,9 @@ int multisensor_set_phase (int sensor_port, ///< sensor port number (0
diff_phase90=phase90-old_phase90;
if (diff_phase90>2) diff_phase90-=4;
else if (diff_phase90<-1)diff_phase90+=4;
MDF16(printk("old_phase= 0x%x old_phase90= 0x%x\r\n", old_phase, old_phase90 ));
MDF16(printk("phase= 0x%x phase90= 0x%x\r\n", phase, phase90 ));
MDF16(printk("diff_phase=0x%x diff_phase90=0x%x\r\n", diff_phase, diff_phase90 ));
dev_dbg(g_dev_ptr,"%s old_phase= 0x%x old_phase90= 0x%x\r\n",__func__, old_phase, old_phase90 );
dev_dbg(g_dev_ptr,"%s phase= 0x%x phase90= 0x%x\r\n",__func__, phase, phase90 );
dev_dbg(g_dev_ptr,"%s diff_phase=0x%x diff_phase90=0x%x\r\n",__func__, diff_phase, diff_phase90 );
if (diff_phase > 0) for (i=diff_phase; i > 0; i--) MULTISENSOR_WRITE_I2C16(sensor_port, reg_addr, I2C359_DCM_INC )
else if (diff_phase < 0) for (i=diff_phase; i < 0; i++) MULTISENSOR_WRITE_I2C16(sensor_port, reg_addr, I2C359_DCM_DEC )
if (diff_phase90 > 0) for (i=diff_phase90; i > 0; i--) MULTISENSOR_WRITE_I2C16(sensor_port, reg_addr, I2C359_DCM_INC90 )
......@@ -2030,28 +2039,28 @@ int multisensor_pgm_sensorregs (int sensor_port, ///< sensor port
///< @return always 0
{
MDF4(printk(" frame16=%d\n",frame16));
dev_dbg(g_dev_ptr,"%s frame16=%d\n",__func__,frame16);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// int fpga_addr=(frame16 <0) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame16);
int fpga_addr=frame16;
// do whatever is needed for 10359 registers, then call sesnor function (if available)
// rslt=sensorproc_phys->pgm_func[i+32] ( &(sensorproc->sensor), procpars, prevpars, seq_frame);
// add_sensor_proc(onchange_sensorregs, &mt9x001_pgm_sensorregs); // write sensor registers (only changed from outside the driver as they may have different latencies)?
// add_sensor_proc(sensor_port,onchange_sensorregs, &mt9x001_pgm_sensorregs); // write sensor registers (only changed from outside the driver as they may have different latencies)?
//#define SET_10359_REG(f,r,v)
// send all parameters marked as "needed to be processed" to the sensor, clear those flags
// mask out all non sensor pars
// It will be the first for the frame (before automatic sensor changes).
// Add testing for programmed sensor and move vbalues to later frames (not here but in the pgm_functions)
unsigned long bmask32= ((thispars->mod32) >> (P_M10359_REGS>>5)) & (( 1 << (P_M10359_NUMREGS >> 5))-1) ;
MDF4(printk(" bmask32=0x%lx, thispars->mod32=0x%lx, P_M10359_REGS=0x%x, P_M10359_NUMREGS=0x%x\n",bmask32,thispars->mod32,P_M10359_REGS,P_M10359_NUMREGS));
dev_dbg(g_dev_ptr,"%s bmask32=0x%lx, thispars->mod32=0x%lx, P_M10359_REGS=0x%x, P_M10359_NUMREGS=0x%x\n",__func__,bmask32,thispars->mod32,P_M10359_REGS,P_M10359_NUMREGS);
unsigned long mask;
int index,index32;
if (bmask32) {
for (index32=(P_M10359_REGS>>5); bmask32; index32++, bmask32 >>= 1) {
MDF4(printk(" index32=0x%x, bmask32=0x%lx\n",index32,bmask32));
dev_dbg(g_dev_ptr,"%s index32=0x%x, bmask32=0x%lx\n",__func__,index32,bmask32);
if (bmask32 & 1) {
mask=thispars->mod[index32];
MDF4(printk(" mask=0x%lx\n",mask));
dev_dbg(g_dev_ptr,"%s mask=0x%lx\n",__func__,mask);
for (index=(index32<<5); mask; index++, mask >>= 1) {
if (mask & 1) {
SET_10359_REG (sensor_port, fpga_addr, (index-P_M10359_REGS), thispars->pars[index]);
......
......@@ -129,7 +129,7 @@ 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);
/*
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -25,8 +25,9 @@
#define X393_MAXHEIGHT 65536 // 16384 // multiple of 16 - unsafe - not enough room for black level subtraction
#define X393_MAXHEIGHT_SAFE 65536 // 4096 // multiple of 16 OK for black level subtraction TODO: disable black level if unsafe
int init_pgm_proc(void);
int add_sensor_proc(int index, int (*sens_func)(int sensor_port, struct sensor_t * , struct framepars_t * , struct framepars_t *, int ));
void pgm_functions_set_device(struct device *dev);
int init_pgm_proc(int sensor_port);
int add_sensor_proc(int port, int index, int (*sens_func)(int sensor_port, struct sensor_t * , struct framepars_t * , struct framepars_t *, int ));
/// Commands through sequencer: switch between ASAP (frame <0) and absolute
/// @param port - sensor port (0..3)
......
......@@ -180,7 +180,7 @@ int get_cache_index(unsigned int chn)
void reset_qtables(unsigned int chn)
{
int ind = get_cache_index(chn);
qtables_set[ind].qtable_fpga_initialized = 0;
qtables_set[ind].qtable_cache_initialized = 0;
qtables_set[ind].qtable_fpga_initialized = 0;
}
......
......@@ -58,6 +58,9 @@
/** @brief The size in bytes of L2 cache invalidation area. This size must be aligned to cache line size. 16 kbytes seems to be good starting point.*/
#define L2_INVAL_SIZE (32 * 1024)
/** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */
static struct device *g_dev_ptr;
/** @brief Contains read and write pointers along with IRQ number for a single channel*/
struct jpeg_ptr_t {
volatile u32 frame; ///< Absolute frame number
......@@ -87,6 +90,8 @@ struct image_acq_pd_t {
int minor; ///< Driver minor number
struct jpeg_ptr_t jpeg_ptr[SENSOR_PORTS]; ///< Array of read/write pointers
};
/* debug code follows */
long long zero_counter[SENSOR_PORTS] = {0};
long long corrected_offset[SENSOR_PORTS] = {0};
......@@ -114,6 +119,12 @@ long long get_frame_pos(unsigned int chn, unsigned int pos)
static struct image_acq_pd_t image_acq_priv;
u32 get_compressor_frame(unsigned int chn) ///< Sensor port number (0..3)
///< @return absolute compressed frame number
{
return image_acq_priv.jpeg_ptr[chn & 3].frame;
}
//static volatile int JPEG_wp;
//static volatile int JPEG_rp;
//static int fpga_counter_prev=0; ///< Previous value of the FPGA transfer counter (to find out if it did change)
......@@ -253,7 +264,7 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
void *virt_addr;
// int prev_dword;
int xferred; // number of 32-byte chunks transferred since compressor was reset
x393_cmdseqmux_status_t cmdseqmux_status;
// x393_cmdseqmux_status_t cmdseqmux_status;
x393_afimux_status_t stat = x393_afimux0_status(jptr->chn_num);
int frame16;
u32 aframe = GLOBALPARS(jptr->chn_num,G_THIS_FRAME); // thisFrameNumber(jptr->chn_num); // current absolute frame number
......@@ -266,14 +277,17 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
jptr->fpga_cntr_prev = jptr->jpeg_wp;
jptr->jpeg_wp = (stat.offset256 << 3);
// Find absolute frame number just compressed
cmdseqmux_status = x393_cmdseqmux_status(); // CMDSEQMUX status data (frame numbers and interrupts
// Find absolute frame number just compressed WRONG, should use comressor frame number
// cmdseqmux_status = x393_cmdseqmux_status(); // CMDSEQMUX status data (frame numbers and interrupts
frame16 = getHardFrameNumber(jptr->chn_num, 1); // Use compressor
#if 0
switch (jptr->chn_num){
case 0: frame16 =cmdseqmux_status.frame_num0; break;
case 1: frame16 =cmdseqmux_status.frame_num1; break;
case 2: frame16 =cmdseqmux_status.frame_num2; break;
default: frame16 =cmdseqmux_status.frame_num3;
}
#endif
if (frame16 > (aframe & PARS_FRAMES_MASK))
aframe += 16;
jptr->frame = (aframe & ~PARS_FRAMES_MASK) | frame16; // This is absolute compressed frame number, may lag behind current one
......@@ -318,18 +332,18 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
// // prevent compiler from reordering operations.
// phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr;
// virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr;
// dev_dbg(NULL, "from updateIRQJPEG_wp: phys_addr = 0x%x, virt_addr = 0x%p\n", phys_addr, virt_addr);
// dev_dbg(g_dev_ptr, "from updateIRQJPEG_wp: phys_addr = 0x%x, virt_addr = 0x%p\n", phys_addr, virt_addr);
// outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1));
// __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE);
// phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr + CCAM_DMA_SIZE - CHUNK_SIZE;
// virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr + BYTE2DW(CCAM_DMA_SIZE - CHUNK_SIZE);
// outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1));
// __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE);
// dev_dbg(NULL, "from updateIRQJPEG_wp: phys_addr = 0x%x, virt_addr = 0x%p\n", phys_addr, virt_addr);
// dev_dbg(g_dev_ptr, "from updateIRQJPEG_wp: phys_addr = 0x%x, virt_addr = 0x%p\n", phys_addr, virt_addr);
// barrier();
// prev_dword = X393_BUFFSUB(DW2BYTE(jptr->jpeg_wp), 4);
// dev_dbg(NULL, "circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp] = 0x%x\n", circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp]);
// dev_dbg(NULL, "circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)] = 0x%x\n", circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)]);
// dev_dbg(g_dev_ptr, "circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp] = 0x%x\n", circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp]);
// dev_dbg(g_dev_ptr, "circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)] = 0x%x\n", circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)]);
//// if (circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp] == 0x00 &&
// if ((circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)] & MARKER_FF) == MARKER_FF) {
//// jptr->jpeg_wp += INTERFRAME_PARAMS_SZ;
......@@ -431,6 +445,31 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr)
return interframe;
}
#ifdef NC353
inline struct interframe_params_t* updateIRQ_interframe353(struct jpeg_ptr_t *jptr) {
int circbuf_size=get_globalParam (G_CIRCBUFSIZE)>>2;
int alen = jptr->jpeg_wp-9; if (alen<0) alen+=circbuf_size;
int jpeg_len=ccam_dma_buf_ptr[alen] & 0xffffff;
set_globalParam(G_FRAME_SIZE,jpeg_len);
int aframe_params=(alen & 0xfffffff8)-
(((jpeg_len + CCAM_MMAP_META + 3) & 0xffffffe0)>>2) /// multiple of 32-byte chunks to subtract
-8; /// size of the storage area to be filled before the frame
if(aframe_params < 0) aframe_params += circbuf_size;
struct interframe_params_t* interframe= (struct interframe_params_t*) &ccam_dma_buf_ptr[aframe_params];
/// should we use memcpy as before here?
interframe->frame_length=jpeg_len;
interframe->signffff=0xffff;
#if ELPHEL_DEBUG_THIS
set_globalParam (0x306,get_globalParam (0x306)+1);
#endif
return interframe;
}
#endif
/** Fill exif data with the current frame data, save pointer to Exif page in the interframe area
*
......@@ -567,12 +606,20 @@ inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, ///< pointer
static irqreturn_t frame_sync_irq_handler(int irq, void *dev_id)
{
struct jpeg_ptr_t *jptr = dev_id;
// update_frame_pars();
x393_cmdframeseq_mode_t cmdframeseq_mode = {.d32 = 0};
cmdframeseq_mode.interrupt_cmd = IRQ_CLEAR;
unsigned long flags;
int frame16;
local_irq_save(flags);
u32 aframe = GLOBALPARS(jptr->chn_num, G_THIS_FRAME); // thisFrameNumber(jptr->chn_num); // current absolute frame number
frame16 = getHardFrameNumber(jptr->chn_num, 0); // Use sensor frame number
updateFramePars (jptr->chn_num,
frame16);
wake_up_interruptible(&aframepars_wait_queue[jptr->chn_num]);
// tasklet_schedule(&tasklet_fpga);
tasklet_schedule(tasklets[jptr->chn_num]);
x393_cmdframeseq_ctrl(cmdframeseq_mode, jptr->chn_num);
local_irq_restore(flags);
return IRQ_HANDLED;
}
......@@ -589,23 +636,28 @@ static irqreturn_t compressor_irq_handler(int irq, void *dev_id)
struct jpeg_ptr_t *jptr = dev_id;
struct interframe_params_t *interframe = NULL;
x393_cmprs_interrupts_t irq_ctrl;
unsigned long flag;
int frame16;
unsigned long flags;
local_irq_save(flag);
local_irq_save(flags);
if (updateIRQJPEG_wp(jptr)) {
update_irq_circbuf(jptr);
updateIRQFocus(jptr);
interframe = updateIRQ_interframe(jptr);
updateIRQ_Exif(jptr, interframe);
frame16 = getHardFrameNumber(jptr->chn_num, 1); // Use compressor frame number
updateInterFrame(jptr->chn_num, // Sensor port number (0..3)
frame16, // number of frame just compressed (lower 4 bits, from FPGA), always >= sensor frame number,
// interrupt should be processed after frame sync interrupt
interframe); // pointer to the area in circbuf to save parameters
wake_up_interruptible(&circbuf_wait_queue);
}
//wake_up_interruptible(&framepars_wait_queue);
// tasklet_schedule(&tasklet_fpga);
tasklet_schedule(tasklets[jptr->chn_num]);
irq_ctrl.interrupt_cmd = IRQ_CLEAR;
x393_cmprs_interrupts(irq_ctrl, jptr->chn_num);
local_irq_restore(flag);
local_irq_restore(flags);
return IRQ_HANDLED;
}
......@@ -636,9 +688,9 @@ For displaying histograms - try use latest available - not waiting fro a particu
//#define HISTOGRAMS_WAKEUP_ALWAYS 0
void tasklet_fpga_function(unsigned long arg)
{
int is_compressor_irq = 1; // TODO: add interrupts from frame sync if compressor is off
// int is_compressor_irq = 1; // TODO: add interrupts from frame sync if compressor is off
int hist_en;
int sensor_port = image_acq_priv.jpeg_ptr[arg].chn_num;
int sensor_port = image_acq_priv.jpeg_ptr[arg].chn_num; // == arg & 3
int tasklet_disable=get_globalParam(sensor_port, G_TASKLET_CTL);
unsigned long thisFrameNumber=getThisFrameNumber(sensor_port);
unsigned long prevFrameNumber=thisFrameNumber-1;
......@@ -671,7 +723,10 @@ void tasklet_fpga_function(unsigned long arg)
}
// Time is out?
if ((getThisFrameNumber(sensor_port) ^ getHardFrameNumber(sensor_port,is_compressor_irq)) & PARS_FRAMES_MASK) return; // already next frame
if ((getThisFrameNumber(sensor_port) ^ getHardFrameNumber(sensor_port, 0)) & PARS_FRAMES_MASK) {
dev_dbg(g_dev_ptr, "%s : port= %d, === already next frame (1)\n", __func__, sensor_port);
return; // already next frame
}
// Histograms are available for the previous frame (that is already in circbuf if compressor was running)
// Is Y histogram needed?
PROFILE_NOW(2);
......@@ -697,6 +752,7 @@ void tasklet_fpga_function(unsigned long arg)
}
//#ifdef TEST_DISABLE_CODE
if (hist_en) {
histograms_check_init(); // check if histograms are initialized and initialize if not (structures and hardware)
// after updateFramePars gammaHash are from framepars[this-1]
for (subchn=0;subchn<MAX_SENSORS;subchn++) if (((hist_indx=get_hist_index(sensor_port,subchn)))>=0){
if (PER_CHANNEL393) {
......@@ -714,7 +770,12 @@ void tasklet_fpga_function(unsigned long arg)
PROFILE_NOW(3);
// Time is out?
// Old 353 if ((getThisFrameNumber(sensor_port) ^ X3X3_I2C_FRAME) & PARS_FRAMES_MASK) return; // already next frame
if ((getThisFrameNumber(sensor_port) ^ getHardFrameNumber(sensor_port,is_compressor_irq)) & PARS_FRAMES_MASK) return; // already next frame
if ((getThisFrameNumber(sensor_port) ^ getHardFrameNumber(sensor_port, 0)) & PARS_FRAMES_MASK) {
dev_dbg(g_dev_ptr, "%s : port= %d, === already next frame (1)\n", __func__, sensor_port);
return; // already next frame
}
#if HISTOGRAMS_WAKEUP_ALWAYS
}
wake_up_interruptible(&hist_y_wait_queue); // wait queue for the G1 histogram (used as Y)
......@@ -724,11 +785,14 @@ void tasklet_fpga_function(unsigned long arg)
#endif
// Process parameters
if ((tasklet_disable & (1 << TASKLET_CTL_PGM)) == 0) {
processPars (sensor_port, sensorproc, getThisFrameNumber(sensor_port), get_globalParam(sensor_port, G_MAXAHEAD)); // program parameters
PROFILE_NOW(4);
processPars (sensor_port, &asensorproc[sensor_port], getThisFrameNumber(sensor_port), get_globalParam(sensor_port, G_MAXAHEAD)); // program parameters
PROFILE_NOW(3); // was 5 in NC353
}
// Time is out?
if ((getThisFrameNumber(sensor_port) ^ getHardFrameNumber(sensor_port,is_compressor_irq)) & PARS_FRAMES_MASK) return; // already next frame
if ((getThisFrameNumber(sensor_port) ^ getHardFrameNumber(sensor_port, 0)) & PARS_FRAMES_MASK) {
dev_dbg(g_dev_ptr, "%s : port= %d, === already next frame (1)\n", __func__, sensor_port);
return; // already next frame
}
// Are C histograms needed?
switch ((tasklet_disable >> TASKLET_CTL_HISTC_BIT) & 7) {
case TASKLET_HIST_NEVER: // never calculate
......@@ -751,6 +815,7 @@ void tasklet_fpga_function(unsigned long arg)
hist_en=1;
}
if (hist_en) {
histograms_check_init(); // check if histograms are initialized and initialize if not (structures and hardware)
// after updateFramePars gammaHash are from framepars[this-1]
// after updateFramePars gammaHash are from framepars[this-1]
for (subchn=0;subchn<MAX_SENSORS;subchn++) if (((hist_indx=get_hist_index(sensor_port,subchn)))>=0){
......@@ -766,9 +831,12 @@ void tasklet_fpga_function(unsigned long arg)
}
GLOBALPARS(sensor_port, G_HIST_C_FRAME + subchn) = prevFrameNumber; // histogram corresponds to previous frame
}
PROFILE_NOW(5);
PROFILE_NOW(4); // was 5 in NC353
// Time is out?
if ((getThisFrameNumber(sensor_port) ^ getHardFrameNumber(sensor_port,is_compressor_irq)) & PARS_FRAMES_MASK) return; // already next frame
if ((getThisFrameNumber(sensor_port) ^ getHardFrameNumber(sensor_port, 0)) & PARS_FRAMES_MASK) {
dev_dbg(g_dev_ptr, "%s : port= %d, === already next frame (1)\n", __func__, sensor_port);
return; // already next frame
}
#if HISTOGRAMS_WAKEUP_ALWAYS
}
wake_up_interruptible(&hist_c_wait_queue); // wait queue for all the other (R,G2,B) histograms (color)
......@@ -806,11 +874,11 @@ void reset_compressor(unsigned int chn)
void compressor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt enable
int chn) ///< compressor channel (0..3)
{
int i;
// int i;
x393_cmprs_interrupts_t irq_ctrl = {.d32=0};
//MDF2(printk ("compressor_interrupts(%d)\n",on));
dev_dbg(NULL, "set camera interrupts status: %d\n", on);
dev_dbg(g_dev_ptr, "set camera interrupts status: %d\n", on);
#ifdef TEST_DISABLE_CODE
if (on) {
EN_INTERRUPT(SMART);
......@@ -835,11 +903,11 @@ void compressor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt e
void sensor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt enable
int chn) ///< compressor channel (0..3)
{
int i;
// int i;
x393_cmdframeseq_mode_t cmdframeseq_mode = {.d32=0};
//MDF2(printk ("compressor_interrupts(%d)\n",on));
dev_dbg(NULL, "set sensor interrupts status: %d\n", on);
dev_dbg(g_dev_ptr, "set sensor interrupts status: %d\n", on);
#ifdef TEST_DISABLE_CODE
if (on) {
EN_INTERRUPT(SMART);
......@@ -910,11 +978,13 @@ int image_acq_init(struct platform_device *pdev)
if (!match)
return -EINVAL;*/
asensorproc= &as_sensorproc[0];
// asensorproc= &as_sensorproc[0];
asensorproc= as_sensorproc;
//MDD1(printk("sensorproc=0x%x\n",(int) sensorproc));
dev_dbg(dev, "sensorproc address: 0x%x\n", (int)sensorproc);
// dev_dbg(dev, "sensorproc addresses: 0x%x\n", (int) sensorproc);
for (i = 0; i < SENSOR_PORTS; i++) {
dev_dbg(dev, "sensorproc addresses: 0x%x\n", (int) &asensorproc[i]);
irq = platform_get_irq_byname(pdev, frame_sync_irq_names[i]);
if (request_irq(irq,
frame_sync_irq_handler,
......@@ -925,6 +995,8 @@ int image_acq_init(struct platform_device *pdev)
return -EBUSY;
}
image_acq_priv.jpeg_ptr[i].irq_num_sens = irq;
dev_info(dev, "Elphel FPGA interrupts set: %s\n",frame_sync_irq_names[i]);
irq = platform_get_irq_byname(pdev, compressor_irq_names[i]);
if (request_irq(irq,
compressor_irq_handler,
......@@ -936,6 +1008,8 @@ int image_acq_init(struct platform_device *pdev)
}
image_acq_priv.jpeg_ptr[i].irq_num_comp = irq;
image_acq_priv.jpeg_ptr[i].chn_num = i;
dev_info(dev, "Elphel FPGA interrupts set: %s\n",compressor_irq_names[i]);
}
if (init_mmio_ptr() < 0) {
......@@ -961,16 +1035,18 @@ int image_acq_init(struct platform_device *pdev)
dev_dbg(dev, "reset all compressors\n");
for (i = 0; i < SENSOR_PORTS; i++) {
reset_compressor(i);
dev_info(dev, "init_pgm_proc (%d)\n",i);
init_pgm_proc (i); // setup pointers to functions (not sensor-specific)
}
//reset_compressor(); // reset compressor and buffer pointers
//MDD1(printk("x313_dma_init()\n"));
//x313_dma_init(); // initialize ETRAX FS DMA
//MDD1(printk("init_pgm_proc ()\n"));
//init_pgm_proc (); // setup pointers to functions (not sensor-specific)
//MDD1(printk("reset_qtables()\n"));
dev_info(dev, "reset_qtables(0) (policy = COMMON_CACHE)\n");
set_cache_policy(COMMON_CACHE);
reset_qtables(0); // force initialization at next access (with COMMON_CACHE chyannel is ignored, with PER_CHN_CACHE - do for each chennel)
// framepars_init(pdev);
pgm_functions_set_device(dev);
g_dev_ptr = dev;
return 0;
}
......@@ -991,7 +1067,7 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
BUG_ON(!class_10359);
class_sensor= xi2c_dev_get(name_sensor);
BUG_ON(!class_sensor);
memcpy(&dev_sensor, class_sensor, sizeof(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)) {
i2c_page_register(sensor_port, class_10359->slave7);
set_xi2c_wrc(class_10359, sensor_port, class_10359->slave7, 0);
......@@ -1001,12 +1077,20 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
set_xi2c_wrc(&dev_sensor, sensor_port, dev_sensor.slave7, 0);
}
// Now register one page for reading 10359 and the sensor using sensor speed data
memcpy(&dev_sensor, class_sensor, sizeof(dev_sensor));
memcpy(&dev_sensor, class_sensor, sizeof(x393_i2c_device_t)); // dev_sensor));
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE2);
dev_sensor.data_bytes=4; // for reading 10359 in 32-bit mode
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4);
}
return 0;
/*
/home/eyesis/git/elphel393/poky/build/tmp/work-shared/elphel393/kernel-source/drivers/elphel/sensor_common.c: In function 'legacy_i2c':
/home/eyesis/git/elphel393/poky/build/tmp/work-shared/elphel393/kernel-source/drivers/elphel/sensor_common.c:1060:45:
warning: argument to 'sizeof' in 'memcpy' call is the same pointer type 'x393_i2c_device_t * {aka struct <anonymous> *}'
as the destination; expected 'x393_i2c_device_t {aka struct <anonymous>}' or an explicit length [-Wsizeof-pointer-memaccess]
memcpy(&dev_sensor, class_sensor, sizeof(class_sensor));
invalid type argument of unary '*' (have 'x393_i2c_device_t {aka struct <anonymous>}')
*/
}
......
......@@ -6,7 +6,9 @@
#define _SENSOR_COMMON_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 * sensorproc;
extern struct sensorproc_t * asensorproc;
//extern struct sensorproc_t * sensorproc;
/// IRQ-safe "nice" FPGA table write and histogram read functions - they split the data in chunks of fixed size,
/// disable IRQ, transfer a chunk, then reenable interrupt before proceedg to the next chunk
#define FPGA_TABLE_CHUNK 64 // up to 64 words to send to the table/from histogram on a single IRQ-off transfer
......@@ -24,6 +26,8 @@ extern struct sensorproc_t * sensorproc;
//int camSeqGetJPEG_wp(void);
//int camSeqGetJPEG_rp(void);
//void camSeqSetJPEG_rp(int p);
u32 get_compressor_frame(unsigned int chn);
int getHardFrameNumber(int sensor_port, int use_compressor);
int camseq_get_jpeg_wp(unsigned int chn);
int camseq_get_jpeg_rp(unsigned int chn);
void camseq_set_jpeg_rp(unsigned int chn, int ptr);
......
......@@ -139,10 +139,10 @@ int i2c_page_alloc(int chn)
{
int g, b;
u32 * fb;
spin_lock(&lock);
spin_lock_bh(&lock);
g = __builtin_clz(free_i2c_groups[chn]);
if (unlikely(g > 7)) {
spin_unlock(&lock);
spin_unlock_bh(&lock);
return -ENOMEM; // no free i2c pages left
}
fb = free_i2c_pages + ((chn << 3) + g);
......@@ -151,7 +151,7 @@ int i2c_page_alloc(int chn)
if (unlikely(*fb == 0)){
free_i2c_groups[chn] &= ~(1 << (31 - g));
}
spin_unlock(&lock);
spin_unlock_bh(&lock);
return (g << 5) + b;
}
EXPORT_SYMBOL_GPL(i2c_page_alloc);
......@@ -165,16 +165,16 @@ int i2c_page_register(int chn, ///< Sensor port
int g = page >> 5;
int b = page & 0x1f;
u32 * fb = free_i2c_pages + ((chn << 3) + g);
spin_lock(&lock);
spin_lock_bh(&lock);
if (unlikely(!(*fb & (1 << (31-b))))) {
spin_unlock(&lock);
spin_unlock_bh(&lock);
return -ENOMEM; // page is already registered
}
*fb &= (1 << (31-b));
if (unlikely(*fb == 0)){
free_i2c_groups[chn] &= ~(1 << (31 - g));
}
spin_unlock(&lock);
spin_unlock_bh(&lock);
return 0;
}
EXPORT_SYMBOL_GPL(i2c_page_register);
......@@ -190,10 +190,10 @@ void i2c_page_free(int chn, int page)
int g = page >> 5;
int b = page & 0x1f;
u32 * fb = free_i2c_pages + ((chn << 3) + g);
spin_lock(&lock);
spin_lock_bh(&lock);
free_i2c_groups[chn] |= 1 << (31 - g);
*fb |= 1 << (31-b);
spin_unlock(&lock);
spin_unlock_bh(&lock);
}
EXPORT_SYMBOL_GPL(i2c_page_free);
......@@ -222,10 +222,10 @@ void set_xi2c_raw(int chn, ///< Sensor port number
tb_data.d32 = data;
tb_data.tbl_mode = 2; //
/* Table address and data should not interleave with others */
spin_lock(&lock);
spin_lock_bh(&lock);
x393_sensi2c_ctrl (tb_addr, chn);
x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock);
spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
}
EXPORT_SYMBOL_GPL(set_xi2c_raw);
......@@ -251,10 +251,10 @@ void set_xi2c_wrc( x393_i2c_device_t * dc, ///< device class
tb_data.dly = get_bit_delay(dc -> scl_khz);
tb_data.tbl_mode = 2;
/* Table address and data should not interleave with others */
spin_lock(&lock);
spin_lock_bh(&lock);
x393_sensi2c_ctrl (tb_addr, chn);
x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock);
spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
}
EXPORT_SYMBOL_GPL(set_xi2c_wrc);
......@@ -279,10 +279,10 @@ void set_xi2c_rdc(x393_i2c_device_t * dc, ///< device class
tb_data.tbl_mode = 2;
/* Table address and data should not interleave with others */
dev_dbg(sdev, "set_xi2c_rdc(*, %d, %d), tb_addr.d32=0x%08x, tb_data.d32 = 0x%08x\n",chn,page,tb_addr.d32,tb_data.d32);
spin_lock(&lock);
spin_lock_bh(&lock);
x393_sensi2c_ctrl (tb_addr, chn);
x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock);
spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] = tb_data.d32;
}
EXPORT_SYMBOL_GPL(set_xi2c_rdc);
......@@ -308,10 +308,10 @@ void set_xi2c_wr(int chn, ///< sensor port
tb_data.dly = bit_delay;
tb_data.tbl_mode = 2;
/* Table address and data should not interleave with others */
spin_lock(&lock);
spin_lock_bh(&lock);
x393_sensi2c_ctrl (tb_addr, chn);
x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock);
spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
}
EXPORT_SYMBOL_GPL(set_xi2c_wr);
......@@ -335,10 +335,10 @@ void set_xi2c_rd(int chn, ///< sensor port
tb_data.dly = bit_delay;
tb_data.tbl_mode = 2;
/* Table address and data should not interleave with others */
spin_lock(&lock);
spin_lock_bh(&lock);
x393_sensi2c_ctrl (tb_addr, chn);
x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock);
spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
}
EXPORT_SYMBOL_GPL(set_xi2c_rd);
......@@ -375,14 +375,14 @@ int write_xi2c_rel (int chn, ///< sensor port
if (tb_data.tbl_mode !=2) return -EBADR;
len = (tb_data.rnw )? 1:((tb_data.nbwr + 5) >> 2); // read mode - always 1 DWORD, write - 1..3
if (len > 1) {
spin_lock(&lock);
spin_lock_bh(&lock);
for (i = 0; i <len; i++){
x393_sensi2c_rel (data[i], chn, offs);
}
} else {
x393_sensi2c_rel (data[0], chn, offs);
}
spin_unlock(&lock);
spin_unlock_bh(&lock);
return 0;
}
EXPORT_SYMBOL_GPL(write_xi2c_rel);
......@@ -404,14 +404,14 @@ int write_xi2c_abs (int chn, ///< sensor port
if (tb_data.tbl_mode !=2) return -EBADR;
len = (tb_data.rnw )? 1:((tb_data.nbwr + 5) >> 2); // read mode - always 1 DWORD, write - 1..3
if (len > 1) {
spin_lock(&lock);
spin_lock_bh(&lock);
for (i = 0; i <len; i++){
x393_sensi2c_abs (data[i], chn, offs);
}
} else {
x393_sensi2c_abs (data[0], chn, offs);
}
spin_unlock(&lock);
spin_unlock_bh(&lock);
return 0;
}
EXPORT_SYMBOL_GPL(write_xi2c_abs);
......@@ -493,6 +493,30 @@ void read_xi2c_sa7 (int chn, ///< sensor port
}
EXPORT_SYMBOL_GPL(read_xi2c_sa7);
/** Read i2c sequencer frame number (4 bits). Make sure it is equal to the cmdseq one */
int read_xi2c_frame(int chn) ///< sensor port number
///< @return i2c sequencer frame number (4 bits)
{
int i;
x393_status_sens_i2c_t status;
x393_status_ctrl_t status_ctrl = get_x393_sensi2c_status_ctrl(chn); /* last written data to status_cntrl */
if (status_ctrl.mode != 3){
spin_lock_bh(&lock);
status = x393_sensi2c_status (chn);
status_ctrl.mode = 3;
status_ctrl.seq_num = status.seq_num ^ 0x20;
set_x393_sensi2c_status_ctrl(status_ctrl, chn);
for (i = 0; i < 10; i++) {
status = x393_sensi2c_status(chn);
if (likely(status.seq_num = status_ctrl.seq_num)) break;
}
spin_unlock_bh(&lock);
dev_dbg(sdev, "read_xi2c_frame(%d): mode set to 3, status updated to 0x%08x\n",chn, (int) status.d32);
}
status = x393_sensi2c_status (chn);
return (int) status.frame_num;
}
EXPORT_SYMBOL_GPL(read_xi2c_frame);
/** Read next byte from the channel i2c read FIFO.
* Sensor channel status will be set to auto update mode (3) if it was in different mode */
......@@ -504,6 +528,7 @@ int read_xi2c_fifo(int chn) ///< sensor port
x393_status_sens_i2c_t status;
x393_status_ctrl_t status_ctrl = get_x393_sensi2c_status_ctrl(chn); /* last written data to status_cntrl */
if (status_ctrl.mode != 3){
spin_lock_bh(&lock);
status = x393_sensi2c_status (chn);
status_ctrl.mode = 3;
status_ctrl.seq_num = status.seq_num ^ 0x20;
......@@ -512,6 +537,7 @@ int read_xi2c_fifo(int chn) ///< sensor port
status = x393_sensi2c_status(chn);
if (likely(status.seq_num = status_ctrl.seq_num)) break;
}
spin_unlock_bh(&lock);
dev_dbg(sdev, "read_xi2c_fifo(%d): mode set to 3, status updated to 0x%08x\n",chn, (int) status.d32);
}
status = x393_sensi2c_status (chn);
......@@ -1194,10 +1220,52 @@ static ssize_t get_i2c_help(struct device *dev, ///< Linux kernel b
"Read/write i2c register (for the pre-configured device classes), sa7_affset is added to class device slave address\n"
"[<data>] is used for register write, without - register read. Reading i2c* returns result of last i2c read operation\n"
"i2c*: read - last read data, write: <class_name> <sa7_offset> <reg_addr> [<data>]\n"
"i2c_frame*: read - i2c sequencer frame number (4 bit), write: 0 - stop, 1 - run, 2 - reset, 3 - reset+run\n"
);
}
/** Sysfs function - read i2c sequencer frame number (4 bits) */
static ssize_t i2c_frame_show(struct device *dev, ///< Linux kernel basic device structure
struct device_attribute *attr, ///< Linux kernel interface for exporting device attributes
char *buf) ///< 4K buffer to receive response
///< @return offset to the end of the output data in the *buf buffer
{
return sprintf(buf,"%d\n",read_xi2c_frame(get_channel_from_name(attr)));
}
/** Sysfs function - stop(0)/run(1)/reset(2)/reset+run(3) i2c sequencer */
static ssize_t i2c_frame_store(struct device *dev, ///< Linux kernel basic device structure
struct device_attribute *attr, ///< Linux kernel interface for exporting device attributes
const char *buf, ///< 4K buffer with what was written
size_t count) ///< offset to the end of buffer data
///< @return new offset to the end of buffer data
{
int cmd;
int chn = get_channel_from_name(attr) ;
if (sscanf(buf, "%i", &cmd)>0) {
switch (cmd){
case 0:
i2c_stop_run_reset (chn, I2C_CMD_STOP);
break;
case 1:
i2c_stop_run_reset (chn, I2C_CMD_RUN);
break;
case 2:
i2c_stop_run_reset (chn, I2C_CMD_RESET);
break;
case 3:
i2c_stop_run_reset (chn, I2C_CMD_RESET);
i2c_stop_run_reset (chn, I2C_CMD_RUN);
break;
default:
return - EINVAL;
}
}
return count;
}
// Sysfs top
/* alloc*: read - allocate and return page, write (any data) - free page */
static DEVICE_ATTR(i2c_all , SYSFS_PERMISSIONS , i2c_class_show , i2c_class_store);
......@@ -1226,6 +1294,10 @@ static DEVICE_ATTR(i2c0 , SYSFS_PERMISSIONS , i2c_sh
static DEVICE_ATTR(i2c1 , SYSFS_PERMISSIONS , i2c_show, i2c_store);
static DEVICE_ATTR(i2c2 , SYSFS_PERMISSIONS , i2c_show, i2c_store);
static DEVICE_ATTR(i2c3 , SYSFS_PERMISSIONS , i2c_show, i2c_store);
static DEVICE_ATTR(i2c_frame0 , SYSFS_PERMISSIONS , i2c_frame_show, i2c_frame_store);
static DEVICE_ATTR(i2c_frame1 , SYSFS_PERMISSIONS , i2c_frame_show, i2c_frame_store);
static DEVICE_ATTR(i2c_frame2 , SYSFS_PERMISSIONS , i2c_frame_show, i2c_frame_store);
static DEVICE_ATTR(i2c_frame3 , SYSFS_PERMISSIONS , i2c_frame_show, i2c_frame_store);
static DEVICE_ATTR(help, SYSFS_PERMISSIONS & SYSFS_READONLY, get_i2c_help, NULL);
/** Contains entries for the root node (directory) of the sysfs representation for sensor-port i2c devices */
......@@ -1255,6 +1327,10 @@ static struct attribute *root_dev_attrs[] = {
&dev_attr_i2c1.attr,
&dev_attr_i2c2.attr,
&dev_attr_i2c3.attr,
&dev_attr_i2c_frame0.attr,
&dev_attr_i2c_frame1.attr,
&dev_attr_i2c_frame2.attr,
&dev_attr_i2c_frame3.attr,
&dev_attr_help.attr,
NULL
};
......
......@@ -37,6 +37,7 @@ typedef struct{
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);
int i2c_page_alloc (int chn);
int i2c_page_register(int chn, int page);
......
......@@ -17,6 +17,9 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <uapi/elphel/c313a.h> // PARS_FRAMES_MASK
#include "x393.h"
......@@ -24,6 +27,7 @@
#define REPEAT_STATUS_READ 10 ///< Number of times status is re-read waiting for a new timestamp
static void __iomem* zynq_devcfg_ptr = NULL; // 0xF8007000..f8007fff /f800700c needed
static DEFINE_SPINLOCK(fpga_time_lock);
// Nothing to init? Started in pgm_detectsesnor through sensor_common:sequencer_stop_run_reset
......@@ -44,7 +48,7 @@ sec_usec_t * get_fpga_rtc(sec_usec_t * ts) ///< Pointer to a sec/usec structure
// x393_rtc_sec_t sec;
int i;
if (!ts) return NULL;
spin_lock(&fpga_time_lock);
spin_lock_bh(&fpga_time_lock);
stat = x393_rtc_status();
stat_ctrl.mode = 1;
stat_ctrl.seq_num = stat.seq_num + 1;
......@@ -57,7 +61,7 @@ sec_usec_t * get_fpga_rtc(sec_usec_t * ts) ///< Pointer to a sec/usec structure
break;
}
}
spin_unlock(&fpga_time_lock);
spin_unlock_bh(&fpga_time_lock);
return ts;
}
......@@ -68,8 +72,18 @@ void set_fpga_rtc (sec_usec_t ts) ///< timestamp providing seconds and microseco
x393_rtc_sec_t sec;
usec.usec = ts.usec;
sec.sec = ts.sec;
spin_lock(&fpga_time_lock);
spin_lock_bh(&fpga_time_lock);
set_x393_rtc_usec(usec);
set_x393_rtc_sec_set(sec); // And apply
spin_unlock(&fpga_time_lock);
spin_unlock_bh(&fpga_time_lock);
}
/** Check if bitstream is loaded */
int is_fpga_programmed(void) ///< @return 0 - bitstream is NOT loaded, 1 - bitsteam IS loaded, -ENOMEM - error in ioremap
{
if (!zynq_devcfg_ptr){
zynq_devcfg_ptr = ioremap(0xf8007000, 0x00010000);
if (!zynq_devcfg_ptr)
return -ENOMEM;
}
return (readl(zynq_devcfg_ptr + 0x000c) & 4)? 1: 0;
}
......@@ -19,4 +19,5 @@
//void fpga_table_write_nice (int addr, int len, unsigned long * data);
sec_usec_t * get_fpga_rtc(sec_usec_t * ts);
void set_fpga_rtc (sec_usec_t ts);
int is_fpga_programmed(void);
......@@ -423,26 +423,22 @@ static ssize_t show_frames_in_buffer(struct device *dev, struct device_attribute
}
static ssize_t store_frame_start(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
size_t len;
sscanf(buf, "%i", &buffer_settings.frame_start[get_channel_from_name(attr)], &len);
sscanf(buf, "%i", &buffer_settings.frame_start[get_channel_from_name(attr)]);
return count;
}
static ssize_t store_full_width(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
size_t len;
sscanf(buf, "%i", &buffer_settings.frame_full_width[get_channel_from_name(attr)], &len);
sscanf(buf, "%i", &buffer_settings.frame_full_width[get_channel_from_name(attr)]);
return count;
}
static ssize_t store_frame_height(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
size_t len;
sscanf(buf, "%i", &buffer_settings.frame_height[get_channel_from_name(attr)], &len);
sscanf(buf, "%i", &buffer_settings.frame_height[get_channel_from_name(attr)]);
return count;
}
static ssize_t store_frames_in_buffer(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
size_t len;
sscanf(buf, "%i", &buffer_settings.frames_in_buffer[get_channel_from_name(attr)], &len);
sscanf(buf, "%i", &buffer_settings.frames_in_buffer[get_channel_from_name(attr)]);
return count;
}
......
......@@ -509,11 +509,13 @@
#define P_EXPOS 141 ///< P_RW_EXPOS 1 exposure time - now in microseconds?
#define P_VEXPOS 142 ///< video exposure (if 0 - use P_RW_EXPOS in ms)
#define P_FOCUS_VALUE 143 ///< (readonly) - sum of all blocks focus values inside focus WOI
#define P_COMPMOD_BYRSH 144 ///< Bayer shift in compressor
#define P_PORTRAIT 145 ///< Quantization coefficients optimized for vertical scan lines
/// 143 - last to copy ============
// 145 (was 143 in NC353) - last to copy ============
#define P_COMPMOD_BYRSH 160 ///< Bayer shift in compressor
#define P_PORTRAIT 161 ///< Quantization coefficients optimized for vertical scan lines
//#define P_COMPMOD_BYRSH 160 ///< Bayer shift in compressor
//#define P_PORTRAIT 161 ///< Quantization coefficients optimized for vertical scan lines
//TODO: rearrange, combine with other AUTOEXP
......@@ -666,9 +668,9 @@
#define P_MAX_GPAR (NUM_GPAR - 1) ///< maximal # of global parameter - TODO: change name to NUM_GPAR and make it 2048
#define PARS_SAVE_FROM 128 ///< PARS_SAVE_NUM parameters starting from PARS_SAVE_FROM from "this" frame will be saved in circular buffer, PASTPARS_SAVE_ENTRIES entries
#define PARS_SAVE_COPY 16 ///< number of parameters copied from future (framepars) to the past (pastpars)
#define PARS_SAVE_COPY 18 ///< number of parameters copied from future (framepars) to the past (pastpars)
#define PARS_SAVE_NUM 32 ///< total size of previous parameter save page
#define PP_PROFILE_START 16 ///< index of the first profile timestamp in pastpars
#define PP_PROFILE_START PARS_SAVE_COPY ///< index of the first profile timestamp in pastpars
#define P_PROFILE (PARS_SAVE_FROM + PP_PROFILE_START) ///< index to access profiles as pastpars (i.e. from PHP ELPHEL_PROFILE1,PHP ELPHEL_PROFILE2)
#define FRAMEPAR_GLOBALS 0x01000 ///< start of global (not frame-related) parameters
......@@ -758,6 +760,10 @@
//#define G_HIST_Y_FRAME (FRAMEPAR_GLOBALS + 57) // /< last frame for which Y histogram was calculated
//#define G_HIST_C_FRAME (FRAMEPAR_GLOBALS + 58) // /< last frame for which C histograms were calculated
#define G_SUBCHANNELS (FRAMEPAR_GLOBALS + 56) ///< subchannels used on this sensor port (bitmask)
#define G_COMPRESSOR_FRAME (FRAMEPAR_GLOBALS + 57) ///< last compressed frame number
//Gap 2 DWORDS
#define G_SKIP_DIFF_FRAME (FRAMEPAR_GLOBALS + 59) ///< number of frames with different size to tolerate before producing POLLHUP in poll(circbuf)
#define G_FTP_NEXT_TIME (FRAMEPAR_GLOBALS + 60) ///< time of the next FTP upload (seconds from epoch)
......@@ -925,40 +931,40 @@ struct framepars_t {
* TODO: Try to make room for some new ones.
*/
enum onchange_functions_t {
onchange_recalcseq=0, ///< recalculate sequences/latencies, according to P_SKIP, P_TRIG
onchange_detectsensor, ///< detect sensor type, sets sensor structure (capabilities), function pointers
onchange_sensorphase, ///< program sensor clock/phase (needs to know maximal clock frequency)
onchange_i2c, ///< program i2c
onchange_sensorregs, ///< write sensor registers (only changed from outside the driver as they may have different latencies)?
onchange_initsensor, ///< resets sensor, reads sensor registers, schedules "secret" manufacturer's corrections to the registers (stops/re-enables hardware i2c)
onchange_afterinit, ///< restore image size, decimation,... after sensor reset or set them according to sensor capabilities if none were specified
onchange_multisens, ///< chnages related to multiplexed sensors
onchange_window, ///< program sensor WOI and mirroring (flipping)
onchange_window_safe, ///< program sensor WOI and mirroring (flipping) - lower latency, no bad frames
onchange_recalcseq=0, ///< 0 recalculate sequences/latencies, according to P_SKIP, P_TRIG
onchange_detectsensor, ///< 1 detect sensor type, sets sensor structure (capabilities), function pointers
onchange_sensorphase, ///< 2 program sensor clock/phase (needs to know maximal clock frequency)
onchange_i2c, ///< 3 program i2c
onchange_sensorregs, ///< 4 write sensor registers (only changed from outside the driver as they may have different latencies)?
onchange_initsensor, ///< 5 resets sensor, reads sensor registers, schedules "secret" manufacturer's corrections to the registers (stops/re-enables hardware i2c)
onchange_afterinit, ///< 6 restore image size, decimation,... after sensor reset or set them according to sensor capabilities if none were specified
onchange_multisens, ///< 7 chnages related to multiplexed sensors
onchange_window, ///< 8 program sensor WOI and mirroring (flipping)
onchange_window_safe, ///< 9 program sensor WOI and mirroring (flipping) - lower latency, no bad frames
// onchange_exposure, ///< program exposure
onchange_gains, ///< program analog gains
onchange_triggermode, ///< program sensor trigger mode
onchange_sensorin, ///< program sensor input in FPGA (Bayer, 8/16 bits, ??)
onchange_sensorstop, ///< Stop acquisition from the sensor to the FPGA (start has latency of 2)
onchange_sensorrun, ///< Start/single acquisition from the sensor to the FPGA (stop has latency of 1)
onchange_gamma, ///< program gamma table
onchange_hist, ///< program histogram window
onchange_aexp, ///< program autoexposure mode
onchange_quality, ///< program quantization table(s)
onchange_memsensor, ///< program memory channels 0 (sensor->memory) and 1 (memory->FPN)
onchange_memcompressor, ///< program memory channel 2 (memory->compressor)
onchange_limitfps, ///< check compressor will keep up, limit sensor FPS if needed
onchange_exposure, ///< program exposure - NOTE: was just after onchange_window
onchange_compmode, ///< program compressor modes (excluding start/stop/single)
onchange_focusmode, ///< program focus modes
onchange_trigseq, ///< program sequencer (int/ext)
onchange_irq, ///< program smart IRQ mode (needs to be on)
onchange_comprestart, ///< restart after changing geometry (recognizes ASAP and programs memory channel 2 then)
onchange_compstop, ///< stop compressor when changing geometry
onchange_compctl, ///< only start/stop/single (after explicitly changed, not when geometry was changed)
onchange_gammaload, ///< write gamma tables (should be prepared). Maybe - just last byte, to activate?
onchange_prescal ///< change scales for per-color digital gains, apply vignetting correction
onchange_gains, ///< 10 program analog gains
onchange_triggermode, ///< 11 program sensor trigger mode
onchange_sensorin, ///< 12 program sensor input in FPGA (Bayer, 8/16 bits, ??)
onchange_sensorstop, ///< 13 Stop acquisition from the sensor to the FPGA (start has latency of 2)
onchange_sensorrun, ///< 14 Start/single acquisition from the sensor to the FPGA (stop has latency of 1)
onchange_gamma, ///< 15 program gamma table
onchange_hist, ///< 16 program histogram window
onchange_aexp, ///< 17 program autoexposure mode
onchange_quality, ///< 18 program quantization table(s)
onchange_memsensor, ///< 19 program memory channels 0 (sensor->memory) and 1 (memory->FPN)
onchange_memcompressor, ///< 20 program memory channel 2 (memory->compressor)
onchange_limitfps, ///< 21 check compressor will keep up, limit sensor FPS if needed
onchange_exposure, ///< 22 program exposure - NOTE: was just after onchange_window
onchange_compmode, ///< 23 program compressor modes (excluding start/stop/single)
onchange_focusmode, ///< 24 program focus modes
onchange_trigseq, ///< 25 program sequencer (int/ext)
onchange_irq, ///< 26 program smart IRQ mode (needs to be on)
onchange_comprestart, ///< 27 restart after changing geometry (recognizes ASAP and programs memory channel 2 then)
onchange_compstop, ///< 28 stop compressor when changing geometry
onchange_compctl, ///< 29 only start/stop/single (after explicitly changed, not when geometry was changed)
onchange_gammaload, ///< 30 write gamma tables (should be prepared). Maybe - just last byte, to activate?
onchange_prescal ///< 31 change scales for per-color digital gains, apply vignetting correction
// onchange_sensorregs /// write sensor registers (only changed from outside the driver as they may have different latencies)?
// add others - none left, all 32 bits used
};
......@@ -1325,6 +1331,7 @@ struct p_names_t {
G_NAME_ENTRY(HIST_Y_FRAME), \
G_NAME_ENTRY(HIST_C_FRAME), \
G_NAME_ENTRY(SUBCHANNELS), \
G_NAME_ENTRY(COMPRESSOR_FRAME), \
G_NAME_ENTRY(SKIP_DIFF_FRAME), \
G_NAME_ENTRY(FTP_NEXT_TIME), \
G_NAME_ENTRY(DAEMON_ERR), \
......
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