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) ...@@ -706,7 +706,18 @@ loff_t circbuf_lseek(struct file *file, loff_t offset, int orig)
case LSEEK_CIRC_UTIME: case LSEEK_CIRC_UTIME:
return get_rtc_usec(); return get_rtc_usec();
break; 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) { if ((offset & ~0x1f)==LSEEK_DAEMON_CIRCBUF) {
wait_event_interruptible(circbuf_wait_queue, get_imageParamsThis(chn, P_DAEMON_EN) & (1<<(offset & 0x1f))); 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) ...@@ -153,7 +153,7 @@ int get_detected_sensor_code(int port, ///< Sensor port number (0..3)
return SENSOR_NONE; return SENSOR_NONE;
} }
/** Gert configured sensorport subchannels */ /** Get configured sensor port subchannels */
int get_subchannels(int port) ///< Sensor port int get_subchannels(int port) ///< Sensor port
///< @return bitmask of available channels ///< @return bitmask of available channels
{ {
......
...@@ -21,11 +21,10 @@ ...@@ -21,11 +21,10 @@
//copied from cxi2c.c - TODO:remove unneeded //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 <linux/types.h> // div for 64
#include <asm/div64.h> // div for 64 #include <asm/div64.h> // div for 64
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -38,6 +37,7 @@ ...@@ -38,6 +37,7 @@
//#include <linux/autoconf.h> //#include <linux/autoconf.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/delay.h>
//#include <asm/system.h> //#include <asm/system.h>
//#include <asm/byteorder.h> // endians //#include <asm/byteorder.h> // endians
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
//#include "cci2c.h" // to use void i2c_reset_wait(void), reset shadow static 'i2c_hardware_on' //#include "cci2c.h" // to use void i2c_reset_wait(void), reset shadow static 'i2c_hardware_on'
#include "x393_macro.h" #include "x393_macro.h"
#include "x393.h" #include "x393.h"
#include "sensor_i2c.h" // read_xi2c_frame()
/** /**
* \def MDF1(x) optional debug output * \def MDF1(x) optional debug output
*/ */
...@@ -122,8 +122,9 @@ ...@@ -122,8 +122,9 @@
/* 393: sFrameParsAll is an array of 4per-port structures */ /* 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 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 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 #ifdef NC353
struct framepars_all_t *frameparsall = NULL; // - will be mmap-ed struct framepars_all_t *frameparsall = NULL; // - will be mmap-ed
...@@ -146,7 +147,7 @@ unsigned long *amultiSensRvrsIndex[SENSOR_PORTS]; // reverse index (t ...@@ -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 wait_queue_head_t aframepars_wait_queue[SENSOR_PORTS];// used to wait for the frame to be acquired
/* Remove after compilation OK */ /* Remove after compilation OK */
struct sensorproc_t * sensorproc = NULL; //struct sensorproc_t * sensorproc = NULL;
//void compressor_interrupts (int on) {} //void compressor_interrupts (int on) {}
#if 0 #if 0
#define wait_event_interruptible(wq, condition) \ #define wait_event_interruptible(wq, condition) \
...@@ -214,27 +215,38 @@ void initSequencers(int sensor_port) ...@@ -214,27 +215,38 @@ void initSequencers(int sensor_port)
{ {
unsigned long flags; unsigned long flags;
MDF2(printk("\n")); dev_dbg(g_devfp_ptr,"%s \n",__func__);
printk("initSequencers:resetting both sequencers\n"); dev_dbg(g_devfp_ptr,"%s : port= %d,initSequencers:resetting both sequencers (not really?)\n",__func__, sensor_port);
#ifdef TEST_DISABLE_CODE #ifdef TEST_DISABLE_CODE
local_irq_save(flags); local_irq_save(flags);
X3X3_SEQ_RESET; X3X3_SEQ_RESET;
i2c_reset_wait(); i2c_reset_wait();
local_irq_restore(flags); local_irq_restore(flags);
initFramePars();
#endif #endif
initFramePars(sensor_port);
} }
/** /** Reset absolute frame number \b thisFrameNumber to \b frame16, optionally reset/restart sequencer */
* @brief reset absolute frame number \b thisFrameNumber to \b frame8 void resetFrameNumber(int sensor_port, ///< sensor_port sensor port number (0..3)
* @param 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
void resetFrameNumber(int sensor_port)
{ {
int i; int i;
// Setup update mode for // Setup update mode for
x393_cmdseqmux_status_t stat; x393_cmdseqmux_status_t stat;
x393_status_ctrl_t stat_ctrl; 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 */ /* Check if the status update mode for command sequencer is not 3 (auto), set/wait if needed */
stat_ctrl = get_x393_cmdseqmux_status_ctrl(); stat_ctrl = get_x393_cmdseqmux_status_ctrl();
if (stat_ctrl.mode !=3) { if (stat_ctrl.mode !=3) {
...@@ -251,17 +263,21 @@ void resetFrameNumber(int sensor_port) ...@@ -251,17 +263,21 @@ void resetFrameNumber(int sensor_port)
stat = x393_cmdseqmux_status(); stat = x393_cmdseqmux_status();
} }
switch (sensor_port) { switch (sensor_port) {
case 0: thisFrameNumber(sensor_port) = stat.frame_num0; break; // case 0: thisFrameNumber(sensor_port) = stat.frame_num0; break;
case 1: thisFrameNumber(sensor_port) = stat.frame_num1; break; case 0: frame16 = stat.frame_num0; break;
case 2: thisFrameNumber(sensor_port) = stat.frame_num2; break; case 1: frame16 = stat.frame_num1; break;
case 3: thisFrameNumber(sensor_port) = stat.frame_num3; break; case 2: frame16 = stat.frame_num2; break;
default:
frame16 = stat.frame_num3; break;
} }
thisFrameNumber(sensor_port) = (aframe & PARS_FRAMES_MASK) | frame16;
#ifdef NC353 #ifdef NC353
thisFrameNumber(sensor_port) = X3X3_I2C_FRAME; thisFrameNumber(sensor_port) = X3X3_I2C_FRAME;
#endif #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 // 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) ...@@ -271,20 +287,20 @@ void resetFrameNumber(int sensor_port)
void initFramePars(int sensor_port) void initFramePars(int sensor_port)
{ {
int i; int i;
memset(aframepars[sensor_port], 0, sizeof(struct framepars_t) * PARS_FRAMES); memset(aframepars[sensor_port], 0, sizeof(struct framepars_t) * PARS_FRAMES);
resetFrameNumber(sensor_port); resetFrameNumber(sensor_port, 0, 1);
// initialize frameParsDeps.pars masks: // initialize frameParsDeps.pars masks:
for (i = 0; i < (sizeof(param_depend_tab) / 8); i++) { 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 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 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 // 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 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 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) ...@@ -295,7 +311,7 @@ void initGlobalPars(int sensor_port)
{ {
memset(&aglobalPars[sensor_port][GLOBALS_PRESERVE], 0, (NUM_GPAR - GLOBALS_PRESERVE) * sizeof(unsigned long)); 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(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) ...@@ -316,11 +332,11 @@ int initMultiPars(int sensor_port)
GLOBALPARS(sensor_port,G_MULTI_NUM) = 0; GLOBALPARS(sensor_port,G_MULTI_NUM) = 0;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
m = GLOBALPARS(sensor_port, G_MULTI_REGSM + i); // 1 bit per register that need individual shadows 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) { for (j = P_SENSOR_REGS + (i << 5); m && (GLOBALPARS(sensor_port,G_MULTI_NUM) < P_MULTI_NUMREGS); j++, m >>= 1) {
if (m & 1) { if (m & 1) {
amultiSensIndex[j] = ireg; amultiSensIndex[sensor_port][j] = ireg;
// MDF(printk("j=0x%x ireg=0x%x\n",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++) { 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 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); amultiSensRvrsIndex[sensor_port][ireg++] = j | ((n + 1) << 16);
...@@ -331,7 +347,7 @@ int initMultiPars(int sensor_port) ...@@ -331,7 +347,7 @@ int initMultiPars(int sensor_port)
} }
// remark: the line below is called from initFramePars, consider removing it // 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 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); return GLOBALPARS(sensor_port, G_MULTI_NUM);
} }
...@@ -414,10 +430,40 @@ inline void set_imageParamsR_all(int sensor_port, int n, unsigned long ...@@ -414,10 +430,40 @@ inline void set_imageParamsR_all(int sensor_port, int n, unsigned long
int i; int i;
for (i = 0; i < PARS_FRAMES; i++) aframepars[sensor_port][i].pars[n] = d; 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;
}
//++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++
/*! /** Called from ISR (sensor frame interrupt)- advance thisFrameNumber to match hardware frame16, copy parameters as needed.
* @brief called from ISR - advance thisFrameNumber to match hardware frame8, copy parameters as needed.
* before: (thisFrameNumber mod8 pointed to current (for the software) parameters frame (now behind by at least 1, maybe 2) * 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?) * (thisFrameNumber-1) mod 8 - oldest with parameters preserved, also containes histograms results (+image timestamp, size?)
* subset of that frame data is copied to pastpars * 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 ...@@ -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 * @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?) * 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 findex_this, findex_prev, findex_future, findex_next;
int index, index32; int index, index32;
unsigned long bmask, bmask32; unsigned long bmask, bmask32;
int pastParsIndex; int pastParsIndex;
struct framepars_t *framepars = aframepars[sensor_port]; 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 // 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)) { #ifdef NC353
findex_this = frame8 & PARS_FRAMES_MASK; 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 */ /* 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: // before update:
// framepars[findex_prev] holds previous frame data (oldest availble) // framepars[findex_prev] holds previous frame data (oldest availble)
// framepars[findex_future] holds farthest in the future one // 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 ...@@ -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 (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)); 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) // 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 if (interframe_pars) { // frame was compressed, not just vsync
//TODO: get rid of *_prev, use it for the future. //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] 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 ...@@ -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->byrshift = framepars[findex_this].pars[P_COMPMOD_BYRSH];
interframe_pars->quality2 |= (framepars[findex_this].pars[P_PORTRAIT] & 1) << 7; 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 // 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)) { 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) { for (index32 = 0; bmask32; index32++, bmask32 >>= 1) {
if (bmask32 & 1) { if (bmask32 & 1) {
for (index = (index32 << 5), bmask = framepars[findex_prev].modsince[index32]; bmask; index++, bmask >>= 1) for (index = (index32 << 5), bmask = framepars[findex_prev].modsince[index32]; bmask; index++, bmask >>= 1)
if (bmask & 1) { if (bmask & 1) {
framepars[findex_prev].pars[index] = framepars[findex_future].pars[index]; 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) 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 ...@@ -503,9 +557,9 @@ void updateFramePars(int sensor_port, int frame8, struct interframe_params_t * i
framepars[findex_next].mod32 |= framepars[findex_this].mod32; 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 { } 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)++; thisFrameNumber(sensor_port)++;
...@@ -517,12 +571,12 @@ void updateFramePars(int sensor_port, int frame8, struct interframe_params_t * i ...@@ -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?) * 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 sensor_port sensor port number (0..3)
* @param sensorproc * @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; 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 int frame_proc; // current frame for which parameters are considered
struct framepars_t * procpars; struct framepars_t * procpars;
struct framepars_t * prevpars; // maybe - drop calculation for each function, move it to pgm_* where needed? 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 ...@@ -533,14 +587,20 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
#if ELPHEL_DEBUG #if ELPHEL_DEBUG
unsigned long allfunctions = framepars[0].functions | framepars[1].functions | framepars[2].functions | framepars[3].functions | 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; 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[1].functions, framepars[2].functions, framepars[3].functions, framepars[4].functions, framepars[5].functions,
framepars[6].functions, framepars[7].functions)); framepars[6].functions, framepars[7].functions));
#endif #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!) // 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 // Now try overdue functions with latencies >=1 and try them in ASAP mode
for (pars_ahead = 0; pars_ahead <= 4; pars_ahead++ ) { 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]; procpars = &framepars[frame_proc];
prevpars = &framepars[(frame_proc - 1) & PARS_FRAMES_MASK]; prevpars = &framepars[(frame_proc - 1) & PARS_FRAMES_MASK];
i = 0; i = 0;
...@@ -556,28 +616,31 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i ...@@ -556,28 +616,31 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
remain <<= 1; remain <<= 1;
} }
// now (todo & mask) !=0 // 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", 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",
todo, procpars->functions, frame8, pars_ahead, frame_proc, i, mask)); 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",
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,"port= %d, %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
sensor_port,
framepars[0].functions, framepars[1].functions, framepars[2].functions, framepars[3].functions,
framepars[4].functions, framepars[5].functions, framepars[6].functions, framepars[7].functions);
if (sensorproc->pgm_func[i]) { 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); 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 } 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 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); rslt = sensorproc->pgm_func[i + 32] (sensor_port, &(sensorproc->sensor), procpars, prevpars, -1);
} }
// Nothing to do with errors here - just report? 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?
if (rslt < 0) printk("%s:%d:%s - error=%d", __FILE__, __LINE__, __FUNCTION__, rslt);
procpars->functions &= ~mask; 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++; i++;
mask <<= 1; mask <<= 1;
remain <<= 1; remain <<= 1;
} }
} }
dev_dbg(g_devfp_ptr,"%s port=%d DONE\n", __func__, sensor_port);
} }
// Next 5 should go in that sequence // 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 //#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 ...@@ -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 //#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; unsigned long todo, mask, remain;
int job_ahead; // doing job "job_ahead" ahead of needed 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 int frame_proc; // current frame for which parameters are considered
struct framepars_t * procpars; struct framepars_t * procpars;
struct framepars_t * prevpars; // maybe - drop calculation for each function, move it to pgm_* where needed? 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 ...@@ -602,6 +665,7 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
int rslt; int rslt;
int max_par_ahead; int max_par_ahead;
int this_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 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 // 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 ...@@ -611,14 +675,14 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
for (job_ahead = 0; job_ahead <= maxahead; job_ahead++ ) { for (job_ahead = 0; job_ahead <= maxahead; job_ahead++ ) {
max_par_ahead = min(5, (PARS_FRAMES - 3) - job_ahead); max_par_ahead = min(5, (PARS_FRAMES - 3) - job_ahead);
for (pars_ahead = 0; pars_ahead < max_par_ahead; pars_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]; procpars = &framepars[frame_proc];
// Check if at least one function is needed for frame_proc // Check if at least one function is needed for frame_proc
if (procpars->functions & if (procpars->functions &
p_nasap[pars_ahead] & //all, *1, *2,*3,*4 - for all will have G_CALLNASAP twice p_nasap[pars_ahead] & //all, *1, *2,*3,*4 - for all will have G_CALLNASAP twice
p_nasap[0]) { p_nasap[0]) {
prevpars = &framepars[(frame_proc - 1) & PARS_FRAMES_MASK]; 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; i = 0;
mask = 1; mask = 1;
remain = 0xffffffff; remain = 0xffffffff;
...@@ -633,23 +697,27 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in ...@@ -633,23 +697,27 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
// now (todo & mask) !=0 // now (todo & mask) !=0
// find the right latency // find the right latency
for (this_ahead = 1; (p_nasap[this_ahead] & todo & mask) && (this_ahead <= 4); this_ahead++) ; // this_ahead==1..5 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; 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)); 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",
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)); __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]) { 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); 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 } 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 if ((rslt >= 0) && (sensorproc->pgm_func[i + 32])) { // sensor - specific functions, called after the main ones
rslt = sensorproc->pgm_func[i + 32] (sensor_port, &(sensorproc->sensor), procpars, prevpars, seq_frame); 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) { if (rslt >= 0) {
procpars->functions &= ~mask; // mark it done procpars->functions &= ~mask; // mark it done
} else { } 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++; i++;
mask <<= 1; mask <<= 1;
...@@ -665,38 +733,47 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in ...@@ -665,38 +733,47 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
* Called from ISR? * Called from ISR?
* @param sensor_port sensor port number (0..3) * @param sensor_port sensor port number (0..3)
* @param sensorproc pointer to sensor static parameters and functions * @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 ?) * @param maxahead maximal number of frames to program ahead of the current (make it P_* parameter ?)
* @return always 0 ? * @return always 0 ?
*/ */
//TODO: "Do it later" should be the only reason not to erase todo bit //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 //#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!) // first - do all ASAP tasks (they should not be done ahead of the corresponding interrupt!)
// MDF6(printk("before first processParsASAP\n")); // dev_dbg(g_devfp_ptr,"%s before first processParsASAP\n",__func__);
processParsASAP(sensor_port, sensorproc, frame8); 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 // 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 // for jobahead =0 it is still possible to have some functions in ASAP mode with non-zero latency
// MDF6(printk("before processParsSeq\n")); // dev_dbg(g_devfp_ptr,"%s before processParsSeq\n",__func__);
processParsSeq(sensor_port, sensorproc, frame8, maxahead); 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 // re-test ASAP tasks - they might appear as a result of other commands executed
// MDF6(printk("before second processParsASAP\n")); // dev_dbg(g_devfp_ptr,"%s before second processParsASAP\n",__func__);
processParsASAP(sensor_port, sensorproc, frame8); 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 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 * @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)); dev_dbg(g_devfp_ptr,"%s port= %d, frame16=%d, func_num=%d\n",__func__, sensor_port, frame16, func_num);
aframepars[sensor_port][frame8 & PARS_FRAMES_MASK].functions |= 1 << 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) ...@@ -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) 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)); dev_dbg(g_devfp_ptr,"%s port= %d, frame16=%d, func_num=%d\n",__func__, sensor_port, frame16, func_num);
aframepars[sensor_port][frame8].functions |= 1 << 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 ...@@ -765,17 +842,17 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
int index, bindex; int index, bindex;
struct framepars_t *framepars = aframepars[sensor_port]; struct framepars_t *framepars = aframepars[sensor_port];
unsigned long *funcs2call =afuncs2call[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 initSequencers(sensor_port); // Will call initFramePars(); and initialize functions
} }
int findex_this = thisFrameNumber(sensor_port) & PARS_FRAMES_MASK; findex_this = thisFrameNumber(sensor_port) & PARS_FRAMES_MASK;
int findex_prev = (findex_this - 1) & PARS_FRAMES_MASK; findex_prev = (findex_this - 1) & PARS_FRAMES_MASK;
int findex_future = (findex_this - 2) & PARS_FRAMES_MASK; // actually - fartherst in the future?? 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));
D1I(local_irq_save(flags)); D1I(local_irq_save(flags));
PROFILE_NOW(6); PROFILE_NOW(5); // Was 6, but no 7 in NC393
if (maxLatency >= 0) { if (maxLatency >= 0) {
if (frameno <= (thisFrameNumber(sensor_port) + maxLatency)) { if (frameno <= (thisFrameNumber(sensor_port) + maxLatency)) {
D1I(local_irq_restore(flags)); D1I(local_irq_restore(flags));
...@@ -788,8 +865,8 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i ...@@ -788,8 +865,8 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
// not too late, not too early, go ahead // not too late, not too early, go ahead
for (npar = 0; npar < numPars; npar++) { 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)); 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); // frame16= (pars[npar].num & FRAMEPAR_GLOBALS)? -1: (frameno & PARS_FRAMES_MASK);
frame8 = frameno & PARS_FRAMES_MASK; frame16 = frameno & PARS_FRAMES_MASK;
val = pars[npar].val; val = pars[npar].val;
index = pars[npar].num & 0xffff; index = pars[npar].num & 0xffff;
if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) { 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 ...@@ -807,35 +884,35 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i
funcs2call[index] = val; funcs2call[index] = val;
D5(printk(" set funcs2call[0x%x]=0x%lx\n", 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 ((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 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 //TODO: optimize to use mask several parameters together
D5(printk(" frame8=0x%x\n", frame8)); D5(printk(" frame16=0x%x\n", frame16));
if ((framepars[frame8].pars[index] != val) || (pars[npar].num & FRAMEPAIR_FORCE_NEW)) { if ((framepars[frame16].pars[index] != val) || (pars[npar].num & FRAMEPAIR_FORCE_NEW)) {
bmask = 1 << (index & 31); bmask = 1 << (index & 31);
bindex = index >> 5; bindex = index >> 5;
bmask32 = 1 << bindex; bmask32 = 1 << bindex;
// Set this parameter for specified frame // Set this parameter for specified frame
framepars[frame8].pars[index] = val; framepars[frame16].pars[index] = val;
framepars[frame8].mod[bindex] |= bmask; framepars[frame16].mod[bindex] |= bmask;
framepars[frame8].mod32 |= bmask32; framepars[frame16].mod32 |= bmask32;
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
D5(printk(" bindex=0x%x, bmask=0x%08lx, bmask32=0x%08lx, functions=0x%08lx\n", bindex, bmask, bmask32, framepars[frame8].functions)); 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) // 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) { if ((pars[npar].num & FRAMEPAIR_JUST_THIS) == 0) {
MDF5(printk(": --- setting next frames")); 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; framepars[nframe].pars[index] = val;
D5(printk(" %d", nframe)); 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")); D5(printk("\n"));
} }
// Mark this parameter in all previous frames as "modified since" // Mark this parameter in all previous frames as "modified since"
// TODO: consider alternative way - first iterate through all parameters, build masks, then apply them // 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].modsince[bindex] |= bmask;
framepars[nframe].modsince32 |= bmask32; framepars[nframe].modsince32 |= bmask32;
} }
...@@ -851,10 +928,10 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i ...@@ -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) // 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))) { 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 // processParsSeq (sensorproc, thisFrameNumber & PARS_FRAMES_MASK, 0); //maxahead=0, the rest will be processed after frame sync, from the tasklet
MDF5(printk("\n")); 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, sensorproc, thisFrameNumber(sensor_port) & PARS_FRAMES_MASK, 0); //maxahead=0, the rest will be processed after frame sync, from the tasklet 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)); D1I(local_irq_restore(flags));
return 0; return 0;
} }
...@@ -871,7 +948,7 @@ int setFrameParsAtomic(int sensor_port, unsigned long frameno, int maxLatency, i ...@@ -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 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; unsigned long flags;
int nframe; int nframe;
unsigned long bmask, bmask32, bindex; unsigned long bmask, bmask32, bindex;
...@@ -882,7 +959,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l ...@@ -882,7 +959,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l
struct framepars_t *framepars = aframepars[sensor_port]; struct framepars_t *framepars = aframepars[sensor_port];
unsigned long *funcs2call =afuncs2call[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)); D1I(local_irq_save(flags));
// if (index > P_MAX_PAR) { // if (index > P_MAX_PAR) {
if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : 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 ...@@ -899,38 +976,38 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l
funcs2call[index] = val; funcs2call[index] = val;
// } else { // } 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 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); bmask = 1 << (index & 31);
bindex = index >> 5; bindex = index >> 5;
bmask32 = 1 << bindex; 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! // 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[frame16].pars[index] = val;
framepars[frame8].mod[bindex] |= bmask; framepars[frame16].mod[bindex] |= bmask;
framepars[frame8].mod32 |= bmask32; framepars[frame16].mod32 |= bmask32;
if (mindex & FRAMEPAIR_FORCE_PROC) { 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 // Write parameter to the next frames up to the one that have the same parameter already modified
if ((mindex & FRAMEPAIR_JUST_THIS) == 0) { if ((mindex & FRAMEPAIR_JUST_THIS) == 0) {
MDF8(printk(": --- setting next frames")); 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=(frame16+1) & PARS_FRAMES_MASK; (nframe != findex_prev) && (!(framepars[frame16].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[nframe].mod[bindex] & bmask)); nframe = (nframe + 1) & PARS_FRAMES_MASK) {
framepars[nframe].pars[index] = val; framepars[nframe].pars[index] = val;
D8(printk(" %d", nframe)); 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" // Mark this parameter in all previous frames as "modified since"
// TODO: consider alternative way - first iterate through all parameters, build masks, then apply them // TODO: consider alternative way - first iterate through all parameters, build masks, then apply them
MDF8(printk(": >>> setting modsince")); MDF8(printk(": >>> setting modsince"));
// for (nframe=(frame8-1) & PARS_FRAMES_MASK; nframe != findex_future; nframe=(nframe-1) & PARS_FRAMES_MASK) { // for (nframe=(frame16-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; nframe != findex_future; nframe = (nframe - 1) & PARS_FRAMES_MASK) { //NOTE: frame16 is modified here
framepars[nframe].modsince[bindex] |= bmask; framepars[nframe].modsince[bindex] |= bmask;
framepars[nframe].modsince32 |= bmask32; framepars[nframe].modsince32 |= bmask32;
D8(printk(" %d", nframe)); D8(printk(" %d", nframe));
...@@ -956,7 +1033,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l ...@@ -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 setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPars, struct frameparspair_t * pars)
{ {
int frame8; int frame16;
unsigned long flags; unsigned long flags;
int npar, nframe; int npar, nframe;
unsigned long val, bmask, bmask32; unsigned long val, bmask, bmask32;
...@@ -967,13 +1044,13 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa ...@@ -967,13 +1044,13 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa
struct framepars_t *framepars = aframepars[sensor_port]; struct framepars_t *framepars = aframepars[sensor_port];
unsigned long *funcs2call =afuncs2call[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)); D1I(local_irq_save(flags));
for (npar = 0; npar < numPars; npar++) { 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; val = pars[npar].val;
index = pars[npar].num & 0xffff; 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 // remark: code below looks similar to setFramePar function, call it instead
if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) { if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) {
D1I(local_irq_restore(flags)); D1I(local_irq_restore(flags));
...@@ -988,36 +1065,36 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa ...@@ -988,36 +1065,36 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa
} else if (pars[npar].num & FRAMEPAIR_FRAME_FUNC) { } else if (pars[npar].num & FRAMEPAIR_FRAME_FUNC) {
funcs2call[index] = val; funcs2call[index] = val;
// } else { // } 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 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 //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); bmask = 1 << (index & 31);
bindex = index >> 5; bindex = index >> 5;
bmask32 = 1 << bindex; 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! // 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[frame16].pars[index] = val;
framepars[frame8].mod[bindex] |= bmask; framepars[frame16].mod[bindex] |= bmask;
framepars[frame8].mod32 |= bmask32; framepars[frame16].mod32 |= bmask32;
if (pars[npar].num & FRAMEPAIR_FORCE_PROC) { 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) // 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) { if ((pars[npar].num & FRAMEPAIR_JUST_THIS) == 0) {
MDF8(printk(": --- setting next frames")); 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)); D8(printk(" %d", nframe));
framepars[nframe].pars[index] = val; 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")); D8(printk("\n"));
} }
// Mark this parameter in all previous frames as "modified since" // Mark this parameter in all previous frames as "modified since"
// TODO: consider alternative way - first iterate through all parameters, build masks, then apply them // 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=(frame16-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; nframe != findex_future; nframe = (nframe - 1) & PARS_FRAMES_MASK) { //NOTE: frame16 is modified here
framepars[nframe].modsince[bindex] |= bmask; framepars[nframe].modsince[bindex] |= bmask;
framepars[nframe].modsince32 |= bmask32; framepars[nframe].modsince32 |= bmask32;
} }
...@@ -1069,7 +1146,7 @@ int framepars_open(struct inode *inode, struct file *filp) ...@@ -1069,7 +1146,7 @@ int framepars_open(struct inode *inode, struct file *filp)
if (!privData) return -ENOMEM; if (!privData) return -ENOMEM;
filp->private_data = privData; filp->private_data = privData;
privData->minor = MINOR(inode->i_rdev); 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) { switch (privData->minor) {
case DEV393_MINOR(DEV393_FRAMEPARS0): case DEV393_MINOR(DEV393_FRAMEPARS0):
case DEV393_MINOR(DEV393_FRAMEPARS1): case DEV393_MINOR(DEV393_FRAMEPARS1):
...@@ -1095,7 +1172,7 @@ int framepars_release(struct inode *inode, struct file *filp) ...@@ -1095,7 +1172,7 @@ int framepars_release(struct inode *inode, struct file *filp)
int res = 0; int res = 0;
int p = MINOR(inode->i_rdev); 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 ) { switch ( p ) {
case DEV393_MINOR(DEV393_FRAMEPARS0): case DEV393_MINOR(DEV393_FRAMEPARS0):
case DEV393_MINOR(DEV393_FRAMEPARS1): case DEV393_MINOR(DEV393_FRAMEPARS1):
...@@ -1179,12 +1256,12 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig) ...@@ -1179,12 +1256,12 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig)
break; break;
case LSEEK_FRAME_RESET: // reset absolute frame number to avoid integer frame number overflow case LSEEK_FRAME_RESET: // reset absolute frame number to avoid integer frame number overflow
dev_dbg(g_devfp_ptr, "LSEEK_FRAME_RESET\n"); 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; break;
case LSEEK_SENSORPROC: // process modified parameters in frame 0 (to start sensor detection) 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", dev_dbg(g_devfp_ptr, "LSEEK_SENSORPROC: aframepars[%d][0].functions=0x%08lx\n",
sensor_port, aframepars[sensor_port][0].functions); 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; break;
case LSEEK_DMA_INIT: // initialize ETRAX DMA (normally done in sensor_common.c at driver init 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"); 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 ...@@ -1244,8 +1321,9 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff
int last; int last;
int result; int result;
sec_usec_t sec_usec; 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,"%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, ": 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, minor=0x%x\n",
__func__, (int)file->f_pos, (int)*off, (int)count, (int) privData->minor);
count &= ~7; // sizeof (struct frameparspair_t)==8 count &= ~7; // sizeof (struct frameparspair_t)==8
switch (privData->minor) { switch (privData->minor) {
case DEV393_MINOR(DEV393_FRAMEPARS0): case DEV393_MINOR(DEV393_FRAMEPARS0):
...@@ -1286,14 +1364,16 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff ...@@ -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; GLOBALPARS(sensor_port,G_MICROSECONDS) = sec_usec.usec;
break; break;
default: 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++; first++;
} }
last = first + 1; last = first + 1;
while ((last < count) && ((pars[last].num & 0xff00) != 0xff00)) last++; // skip to the end or next special instructions 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]); 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 (result < 0) {
if (count > sizeof(pars_static)) kfree(pars); if (count > sizeof(pars_static)) kfree(pars);
return -EFAULT; return -EFAULT;
...@@ -1321,7 +1401,7 @@ int framepars_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -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; struct framepars_pd * privData = (struct framepars_pd*)file->private_data;
int sensor_port = privData -> minor - DEV393_MINOR(DEV393_FRAMEPARS0); 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) { switch (privData->minor) {
case DEV393_MINOR(DEV393_FRAMEPARS0): case DEV393_MINOR(DEV393_FRAMEPARS0):
case DEV393_MINOR(DEV393_FRAMEPARS1): case DEV393_MINOR(DEV393_FRAMEPARS1):
...@@ -1338,6 +1418,135 @@ int framepars_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1338,6 +1418,135 @@ int framepars_mmap(struct file *file, struct vm_area_struct *vma)
default: return -EINVAL; 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 * @brief framepars driver probing function
...@@ -1355,8 +1564,8 @@ int framepars_init(struct platform_device *pdev) ...@@ -1355,8 +1564,8 @@ int framepars_init(struct platform_device *pdev)
init_framepars_ptr(sensor_port); init_framepars_ptr(sensor_port);
initGlobalPars(sensor_port); // sets default debug if enabled - not anymore. Add here? 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 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); res = register_chrdev(DEV393_MAJOR(DEV393_FRAMEPARS0), DEV393_NAME(DEV393_FRAMEPARS0), &framepars_fops);
if (res < 0) { if (res < 0) {
dev_err(dev, "framepars_init: couldn't get a major number %d (DEV393_MAJOR(DEV393_FRAMEPARS0)).\n", 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) ...@@ -1367,15 +1576,15 @@ int framepars_init(struct platform_device *pdev)
init_waitqueue_head(&aframepars_wait_queue[sensor_port]); init_waitqueue_head(&aframepars_wait_queue[sensor_port]);
} }
dev_info(dev, DEV393_NAME(DEV393_FRAMEPARS0)": registered MAJOR: %d\n", DEV393_MAJOR(DEV393_FRAMEPARS0)); 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; g_devfp_ptr = dev;
return 0; return 0;
} }
int framepars_remove(struct platform_device *pdev) int framepars_remove(struct platform_device *pdev)
{ {
unregister_chrdev(DEV393_MAJOR(DEV393_FRAMEPARS0), DEV393_NAME(DEV393_FRAMEPARS0)); unregister_chrdev(DEV393_MAJOR(DEV393_FRAMEPARS0), DEV393_NAME(DEV393_FRAMEPARS0));
return 0; return 0;
} }
......
...@@ -17,7 +17,7 @@ void initSequencers (int sensor_port); ///Move to sensorcommon? currently it ...@@ -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) 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 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 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_imageParamsThis (int sensor_port, int n);
unsigned long get_imageParamsPrev (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); ...@@ -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_globalParam (int sensor_port, int n, unsigned long d);
void set_imageParamsR_all(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. //Next 2 called from ISR
/// frame8 usually is just next after thisFrameNumber void updateInterFrame(int sensor_port, int frame16, struct interframe_params_t * interframe_pars);
/// frame_pars - pointer to structure (between frames in the frame buffer) to save a pointer to past parameters void updateFramePars (int sensor_port, int frame16);
int setFrameParsStatic (int sensor_port, int numPars, struct frameparspair_t * pars); int setFrameParsStatic (int sensor_port, int numPars, struct frameparspair_t * pars);
unsigned long getThisFrameNumber (int sensor_port); /// just return current thisFrameNumber unsigned long getThisFrameNumber (int sensor_port); /// just return current thisFrameNumber
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
*/ */
//copied from cxi2c.c - TODO:remove unneeded //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/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -103,6 +103,8 @@ ...@@ -103,6 +103,8 @@
#include <linux/init.h> #include <linux/init.h>
//#include <linux/autoconf.h> //#include <linux/autoconf.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
//#include <asm/system.h> //#include <asm/system.h>
#include <asm/byteorder.h> // endians #include <asm/byteorder.h> // endians
...@@ -128,25 +130,28 @@ ...@@ -128,25 +130,28 @@
//#include "quantization_tables.h" //#include "quantization_tables.h"
#include "gamma_tables.h" #include "gamma_tables.h"
#include "x393.h" #include "x393.h"
#include "detect_sensors.h"
#include "x393_fpga_functions.h" // to check bitsteram
/** /**
* @brief optional debug output * @brief optional debug output
*/ */
#if ELPHEL_DEBUG #if ELPHEL_DEBUG
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} #define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
#define D10(x) { if (GLOBALPARS(G_DEBUG) & (1 <<10)) { 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 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 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 MDF11(x) { if (GLOBALPARS(G_DEBUG) & (1 <<11)) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} }
// #define MDD1(x) // #define MDD1(x)
#define D1I(x) x #define D1I(x) x
#else #else
#define MDF(x) #define MDF(x)
#define D10(x) #define D10(x)
#define D1I(x) x #define D1I(x) x
#define MDF10(x) #define MDF10(x)
#define MDF11(x) #define MDF11(x)
#endif #endif
...@@ -159,9 +164,22 @@ ...@@ -159,9 +164,22 @@
* \n TODO: use P_*? * \n TODO: use P_*?
*/ */
#define GAMMA_THRESH (GAMMA_CACHE_NUMBER/16) #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))); 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 { struct gammas_pd {
int minor; int minor;
...@@ -169,7 +187,7 @@ struct gammas_pd { ...@@ -169,7 +187,7 @@ struct gammas_pd {
unsigned short hash16; unsigned short hash16;
unsigned char mode; unsigned char mode;
unsigned char color; // Does it need port/sub-channel? 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); int gammas_open (struct inode *inode, struct file *file);
...@@ -177,7 +195,8 @@ int gammas_release(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); 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); 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); int gammas_mmap (struct file *file, struct vm_area_struct *vma);
static int __init gammas_init(void);
//static int __init gammas_init(void);
/** /**
...@@ -196,8 +215,8 @@ inline void remove_from_nonscaled(int index) { ...@@ -196,8 +215,8 @@ inline void remove_from_nonscaled(int index) {
*/ */
inline void remove_from_scaled (int index) { inline void remove_from_scaled (int index) {
if (likely(gammas[index].newer_scaled)) { // will skip first, untill the cache is all used if (likely(gammas[index].newer_scaled)) { // will skip first, untill the cache is all used
gammas[gammas[index].newer_scaled].older_scaled=gammas[index].older_scaled; gammas[gammas[index].newer_scaled].older_scaled=gammas[index].older_scaled;
gammas[gammas[index].older_scaled].newer_scaled=gammas[index].newer_scaled; gammas[gammas[index].older_scaled].newer_scaled=gammas[index].newer_scaled;
} }
} }
...@@ -215,7 +234,7 @@ inline void remove_from_all (int index) { // always - in that chain - after ...@@ -215,7 +234,7 @@ inline void remove_from_all (int index) { // always - in that chain - after
* @param index item index to remove * @param index item index to remove
*/ */
inline void insert_first_nonscaled(int index) { 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[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[index].older_non_scaled= gammas[0].newest_non_scaled; // 4
gammas[0].newest_non_scaled=index; // 5 gammas[0].newest_non_scaled=index; // 5
...@@ -233,14 +252,14 @@ inline void insert_first_nonscaled(int index) { ...@@ -233,14 +252,14 @@ inline void insert_first_nonscaled(int index) {
* @param index item index to remove * @param index item index to remove
*/ */
inline void insert_first_scaled (int non_scaled, int index) { 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[index].older_scaled= gammas[non_scaled].newest_scaled; //4
gammas[gammas[non_scaled].newest_scaled].newer_scaled= index; //1 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[index].newer_scaled= non_scaled; //6
gammas[non_scaled].newest_scaled= index; //5 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; gammas[index].this_non_scaled=non_scaled;
} }
...@@ -259,33 +278,31 @@ inline void insert_first_all (int index) { ...@@ -259,33 +278,31 @@ inline void insert_first_all (int index) {
* @brief Initialize gamma tables data structures * @brief Initialize gamma tables data structures
*/ */
void init_gammas(void) { void init_gammas(void) {
unsigned long flags; int i;
int i; gammas_p=gammas;
gammas_p=gammas; // empty 2-d chain
// empty 2-d chain dev_dbg(g_dev_ptr,"init_gammas()\n");
local_irq_save(flags); spin_lock_bh(&gamma_lock);
gammas[0].oldest_non_scaled=0; gammas[0].oldest_non_scaled=0;
gammas[0].newest_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].oldest_all=GAMMA_CACHE_NUMBER-1;
gammas[0].newest_all=1; gammas[0].newest_all=1;
MDF10(printk("\n")); for (i=1; i < GAMMA_CACHE_NUMBER;i++) {
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
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].newer_all=i-1; gammas[i].older_all= (i==(GAMMA_CACHE_NUMBER-1))? 0: (i+1);
gammas[i].older_all= (i==(GAMMA_CACHE_NUMBER-1))? 0: (i+1); gammas[i].locked=0;
gammas[i].locked=0; gammas[i].valid=0;
gammas[i].valid=0; }
} gammas[0].non_scaled_length=0;
gammas[0].non_scaled_length=0; for (i=1; i < sizeof(gammas[0].locked_chn_color)/sizeof(gammas[0].locked_chn_color[0]);i++) {
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;
gammas[0].locked_chn_color[i]=0; }
} spin_unlock_bh(&gamma_lock);
local_irq_restore(flags);
} }
/** /**
* @brief verifies that index is current (points to specified hash and scale) * @brief verifies that index is current (points to specified hash and scale)
* @param hash16 - 16-bit unique hash for gamma table * @param hash16 - 16-bit unique hash for gamma table
...@@ -294,7 +311,7 @@ void init_gammas(void) { ...@@ -294,7 +311,7 @@ void init_gammas(void) {
* @return 1 - table pointed by index is current, 0 - table is not current * @return 1 - table pointed by index is current, 0 - table is not current
*/ */
int is_gamma_current (unsigned short hash16, unsigned short scale, int index) { int is_gamma_current (unsigned short hash16, unsigned short scale, int index) {
return ((gammas[index].hash16 == hash16) && (gammas[index].scale == scale))?1:0; return ((gammas[index].hash16 == hash16) && (gammas[index].scale == scale))?1:0;
} }
/** /**
...@@ -305,7 +322,7 @@ int is_gamma_current (unsigned short hash16, unsigned short scale, int index) { ...@@ -305,7 +322,7 @@ int is_gamma_current (unsigned short hash16, unsigned short scale, int index) {
* @return 1 - table pointed by index is current and valid, 0 - table is not current or not valid * @return 1 - table pointed by index is current and valid, 0 - table is not current or not valid
*/ */
int is_gamma_valid (unsigned short hash16, unsigned short scale, int index) { int is_gamma_valid (unsigned short hash16, unsigned short scale, int index) {
return ((gammas[index].hash16 == hash16) && (gammas[index].scale == scale) && (gammas[index].valid != 0))?1:0; return ((gammas[index].hash16 == hash16) && (gammas[index].scale == scale) && (gammas[index].valid != 0))?1:0;
} }
...@@ -314,66 +331,68 @@ int is_gamma_valid (unsigned short hash16, unsigned short scale, int index) { ...@@ -314,66 +331,68 @@ int is_gamma_valid (unsigned short hash16, unsigned short scale, int index) {
* @return hash32 (combined gamma/black/scale) locked for a specified color. If none - return 0 * @return hash32 (combined gamma/black/scale) locked for a specified color. If none - return 0
*/ */
unsigned long get_locked_hash32(int color, ///< color channel 0..3 unsigned long get_locked_hash32(int color, ///< color channel 0..3
int sensor_port, ///< sensor port number (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) 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, ///< @return hash32 (combined gamma/black/scale) locked for a specified color,
///< port, sub-channel ///< port, sub-channel
{ {
int index=gammas[0].locked_chn_color[PORT_CHN_COLOR(color,sensor_port,sensor_subchn)]; int index=gammas[0].locked_chn_color[PORT_CHN_COLOR(color,sensor_port,sensor_subchn)];
return index?gammas[index].hash32:0; return index?gammas[index].hash32:0;
} }
/** /**
* @brief Lock gamma table for the specified color/port/subchannel, save previous locks (if any) so new locks can be applied/canceled * @brief Lock gamma table for the specified color/port/subchannel, save previous locks (if any) so new locks can be applied/canceled
* NOTE: interrupts should be disabled! */ * NOTE: interrupts should be disabled! */
inline void lock_gamma_node (int index, ///< gamma table index inline void lock_gamma_node (int index, ///< gamma table index
int color, ///< color channel 0..3 int color, ///< color channel 0..3
int sensor_port, ///< sensor port number (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) int sensor_subchn) ///< sensor sub-channel (connected to the same port through 10359 mux) (0..3)
{ {
int tmp_p; int tmp_p;
int cps = PORT_CHN_COLOR(color,sensor_port,sensor_subchn); int cps = PORT_CHN_COLOR(color,sensor_port,sensor_subchn);
if (((tmp_p=gammas[0].locked_chn_color[cps]))!=0) { ///new gamma to the same color if (((tmp_p=gammas[0].locked_chn_color[cps]))!=0) { ///new gamma to the same color
gammas[tmp_p].locked &= ~(1ULL << cps); // remove any previous lock on the same color (if any) gammas[tmp_p].locked &= ~(1ULL << cps); // remove any previous lock on the same color (if any)
} }
gammas[0].locked_chn_color[cps]= index; gammas[0].locked_chn_color[cps]= index;
gammas[index].locked |= (1ULL << cps); gammas[index].locked |= (1ULL << cps);
} }
/** Unlock gamma table for the specified color/port/subchannel /** Unlock gamma table for the specified color/port/subchannel
* NOTE: Not needed anymore */ * NOTE: Not needed anymore */
int unlock_gamma_node (int color, ///< color channel 0..3 int unlock_gamma_node (int color, ///< color channel 0..3
int sensor_port, ///< sensor port number (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) 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 index;
int cps = PORT_CHN_COLOR(color,sensor_port,sensor_subchn); int cps = PORT_CHN_COLOR(color,sensor_port,sensor_subchn);
MDF11(printk("color=0x%x\n",color)); dev_dbg(g_dev_ptr,"color=0x%x\n",color);
local_irq_save(flags); // local_irq_save(flags);
index =gammas[0].locked_chn_color[cps]; spin_lock_bh(&gamma_lock);
if (index) { index =gammas[0].locked_chn_color[cps];
gammas[index].locked &= ~(1ULL << color); // clear appropriate "locked" bit for this table if (index) {
gammas[0].locked_chn_color[color]=0; gammas[index].locked &= ~(1ULL << color); // clear appropriate "locked" bit for this table
} gammas[0].locked_chn_color[color]=0;
local_irq_restore(flags); }
return index; 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) */ /** 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 unsigned long * get_gamma_fpga (int color, ///< color channel 0..3
int sensor_port, ///< sensor port number (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) 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? { // NOTE: Not needed anymore?
int index; int index;
int cps = PORT_CHN_COLOR(color,sensor_port,sensor_subchn); 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]; 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; if (index) return gammas[index].fpga;
else return NULL; else return NULL;
} }
...@@ -385,23 +404,23 @@ unsigned long * get_gamma_fpga (int color, ///< color channel 0..3 ...@@ -385,23 +404,23 @@ unsigned long * get_gamma_fpga (int color, ///< color channel 0..3
* @return Node index or 0 if none (unlocked) nodes are found * @return Node index or 0 if none (unlocked) nodes are found
*/ */
int gamma_new_node(void) { int gamma_new_node(void) {
int tmp_p; 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 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; tmp_p=gammas[0].oldest_non_scaled;
remove_from_nonscaled(tmp_p); remove_from_nonscaled(tmp_p);
} else { // use oldest scaled } else { // use oldest scaled
tmp_p=gammas[0].oldest_all; 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; 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 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_all (tmp_p);
// remove from "scaled chain" // remove from "scaled chain"
remove_from_scaled (tmp_p); remove_from_scaled (tmp_p);
} }
gammas[tmp_p].valid=0; gammas[tmp_p].valid=0;
return tmp_p; return tmp_p;
} }
/** /**
...@@ -410,19 +429,19 @@ int gamma_new_node(void) { ...@@ -410,19 +429,19 @@ int gamma_new_node(void) {
* @param gamma_out pointer to an array of 256 unsigned long words to be written to FPGA * @param gamma_out pointer to an array of 256 unsigned long words to be written to FPGA
*/ */
void gamma_encode_fpga(unsigned short * gamma_in, unsigned long * gamma_out) { void gamma_encode_fpga(unsigned short * gamma_in, unsigned long * gamma_out) {
int i,base,diff; int i,base,diff;
MDF11(printk("\n")); dev_dbg(g_dev_ptr,"gamma_encode_fpga()\n");
for (i=0;i<256;i++) { for (i=0;i<256;i++) {
base=(gamma_in[i] >> 6); base=(gamma_in[i] >> 6);
diff=(gamma_in[i+1] >> 6); diff=(gamma_in[i+1] >> 6);
diff-=base; diff-=base;
if ((diff>63) || (diff < -64)) { if ((diff>63) || (diff < -64)) {
diff=(diff+8)>>4; diff=(diff+8)>>4;
gamma_out[i]=(base & 0x3ff) | ((diff & 0x7f) << 10) | (1 << 17); gamma_out[i]=(base & 0x3ff) | ((diff & 0x7f) << 10) | (1 << 17);
} else { } else {
gamma_out[i]=(base & 0x3ff) | ((diff & 0x7f) << 10); gamma_out[i]=(base & 0x3ff) | ((diff & 0x7f) << 10);
}
} }
}
} }
/** /**
...@@ -432,15 +451,15 @@ void gamma_encode_fpga(unsigned short * gamma_in, unsigned long * gamma_out) { ...@@ -432,15 +451,15 @@ void gamma_encode_fpga(unsigned short * gamma_in, unsigned long * gamma_out) {
* @param gamma_out output (scaled) gamma table (16 bit) * @param gamma_out output (scaled) gamma table (16 bit)
*/ */
void gamma_calc_scaled (unsigned short scale,unsigned short * gamma_in, unsigned short * gamma_out) { void gamma_calc_scaled (unsigned short scale,unsigned short * gamma_in, unsigned short * gamma_out) {
int i; int i;
unsigned long d; unsigned long d;
unsigned long max_scaled=0xffff << GAMMA_SCALE_SHIFT; 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++) { for (i=0; i<257; i++) {
d= ((unsigned long) scale ) * ((unsigned long) gamma_in[i] ) + (1 <<(GAMMA_SCALE_SHIFT-1)); ///rounding, not truncating d= ((unsigned long) scale ) * ((unsigned long) gamma_in[i] ) + (1 <<(GAMMA_SCALE_SHIFT-1)); ///rounding, not truncating
if (d>max_scaled) d=max_scaled; if (d>max_scaled) d=max_scaled;
gamma_out[i]=d >> GAMMA_SCALE_SHIFT; gamma_out[i]=d >> GAMMA_SCALE_SHIFT;
} }
} }
/** /**
...@@ -452,250 +471,270 @@ void gamma_calc_scaled (unsigned short scale,unsigned short * gamma_in, unsigne ...@@ -452,250 +471,270 @@ void gamma_calc_scaled (unsigned short scale,unsigned short * gamma_in, unsigne
* @param gamma_out reversed gamma table (8 bit) * @param gamma_out reversed gamma table (8 bit)
*/ */
void gamma_calc_reverse(unsigned short * gamma_in, unsigned char * gamma_out) { void gamma_calc_reverse(unsigned short * gamma_in, unsigned char * gamma_out) {
unsigned long gcurr=0; // running value to be compared against direct gamma unsigned long gcurr=0; // running value to be compared against direct gamma
int r=0; // current value of reverse gamma table int r=0; // current value of reverse gamma table
int x=0; // current indedx 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)) { while ((r<256) && (x<256)) {
gamma_out[x]=r; 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)) { if ((r<255) && ( gamma_in[r] <= gcurr)) {
r++; r++;
} else { } else {
x++; x++;
gcurr+=256; gcurr+=256;
}
} }
}
} }
/** Calculate gamma table (and requested derivatives), insert new node if needed. */ /** Calculate gamma table (and requested derivatives), insert new node if needed. */
int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scaled) gamma table identifier. Can be 1-byte gamma and 1-byte black level shift int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scaled) gamma table identifier. Can be 1-byte gamma and 1-byte black level shift
///< TODO: make black level fine-grained? ///< TODO: make black level fine-grained?
unsigned short scale, ///< gamma table scale (currently 0x400 ~ 1.0) GAMMA_SCLALE_1 = 0x400 unsigned short scale, ///< gamma table scale (currently 0x400 ~ 1.0) GAMMA_SCLALE_1 = 0x400
unsigned short * gamma_proto, ///< 16-bit gamma table prototype (or NULL) unsigned short * gamma_proto, ///< 16-bit gamma table prototype (or NULL)
unsigned char mode, ///< bits specify calculation mode: unsigned char mode, ///< bits specify calculation mode:
///< - 1 - if set, no interrupts will be enabled between steps, whole operation will be atomic ///< - 1 - if set, no interrupts will be enabled between steps, whole operation will be atomic
///<- 2 - calculate reverse gamma table ///<- 2 - calculate reverse gamma table
///<- 4 - calculate FPGA-format gamma table ///<- 4 - calculate FPGA-format gamma table
///< - 8 - Lock (FPGA) table for specified color/port/subchannel ///< - 8 - Lock (FPGA) table for specified color/port/subchannel
int color, ///< index (0..63) combined with the next two parameters to lock int color, ///< index (0..63) combined with the next two parameters to lock
///< table for (if mode bit 4 is set), otherwise color, sensor_port, sensor_subchn are ignored ///< 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_port, ///< sensor port number (0..3)
int sensor_subchn) ///< sensor sub-channel (connected to the same port through 10359 mux) (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 tmp_p, tmp_p1; //,tmp_p0;
int cps=PORT_CHN_COLOR(color,sensor_port,sensor_subchn); int cps=PORT_CHN_COLOR(color,sensor_port,sensor_subchn);
unsigned short gamma_linear[257]= unsigned short gamma_linear[257]=
{0x0000,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700,0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00, {0x0000,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700,0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00,
0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x0600,0x1700,0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00, 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x0600,0x1700,0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00,
0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x0600,0x2700,0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00,0x2f00, 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x0600,0x2700,0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00,0x2f00,
0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,0x0600,0x3700,0x3800,0x3900,0x3a00,0x3b00,0x3c00,0x3d00,0x3e00,0x3f00, 0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,0x0600,0x3700,0x3800,0x3900,0x3a00,0x3b00,0x3c00,0x3d00,0x3e00,0x3f00,
0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x0600,0x4700,0x4800,0x4900,0x4a00,0x4b00,0x4c00,0x4d00,0x4e00,0x4f00, 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x0600,0x4700,0x4800,0x4900,0x4a00,0x4b00,0x4c00,0x4d00,0x4e00,0x4f00,
0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x0600,0x5700,0x5800,0x5900,0x5a00,0x5b00,0x5c00,0x5d00,0x5e00,0x5f00, 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x0600,0x5700,0x5800,0x5900,0x5a00,0x5b00,0x5c00,0x5d00,0x5e00,0x5f00,
0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,0x0600,0x6700,0x6800,0x6900,0x6a00,0x6b00,0x6c00,0x6d00,0x6e00,0x6f00, 0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,0x0600,0x6700,0x6800,0x6900,0x6a00,0x6b00,0x6c00,0x6d00,0x6e00,0x6f00,
0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,0x0600,0x7700,0x7800,0x7900,0x7a00,0x7b00,0x7c00,0x7d00,0x7e00,0x7f00, 0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,0x0600,0x7700,0x7800,0x7900,0x7a00,0x7b00,0x7c00,0x7d00,0x7e00,0x7f00,
0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,0x0600,0x8700,0x8800,0x8900,0x8a00,0x8b00,0x8c00,0x8d00,0x8e00,0x8f00, 0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,0x0600,0x8700,0x8800,0x8900,0x8a00,0x8b00,0x8c00,0x8d00,0x8e00,0x8f00,
0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,0x0600,0x9700,0x9800,0x9900,0x9a00,0x9b00,0x9c00,0x9d00,0x9e00,0x9f00, 0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,0x0600,0x9700,0x9800,0x9900,0x9a00,0x9b00,0x9c00,0x9d00,0x9e00,0x9f00,
0xa000,0xa100,0xa200,0xa300,0xa400,0xa500,0x0600,0xa700,0xa800,0xa900,0xaa00,0xab00,0xac00,0xad00,0xae00,0xaf00, 0xa000,0xa100,0xa200,0xa300,0xa400,0xa500,0x0600,0xa700,0xa800,0xa900,0xaa00,0xab00,0xac00,0xad00,0xae00,0xaf00,
0xb000,0xb100,0xb200,0xb300,0xb400,0xb500,0x0600,0xb700,0xb800,0xb900,0xba00,0xbb00,0xbc00,0xbd00,0xbe00,0xbf00, 0xb000,0xb100,0xb200,0xb300,0xb400,0xb500,0x0600,0xb700,0xb800,0xb900,0xba00,0xbb00,0xbc00,0xbd00,0xbe00,0xbf00,
0xc000,0xc100,0xc200,0xc300,0xc400,0xc500,0x0600,0xc700,0xc800,0xc900,0xca00,0xcb00,0xcc00,0xcd00,0xce00,0xcf00, 0xc000,0xc100,0xc200,0xc300,0xc400,0xc500,0x0600,0xc700,0xc800,0xc900,0xca00,0xcb00,0xcc00,0xcd00,0xce00,0xcf00,
0xf000,0xd100,0xd200,0xd300,0xd400,0xd500,0x0600,0xd700,0xd800,0xd900,0xda00,0xdb00,0xdc00,0xdd00,0xde00,0xdf00, 0xf000,0xd100,0xd200,0xd300,0xd400,0xd500,0x0600,0xd700,0xd800,0xd900,0xda00,0xdb00,0xdc00,0xdd00,0xde00,0xdf00,
0xe000,0xe100,0xe200,0xe300,0xe400,0xe500,0x0600,0xe700,0xe800,0xe900,0xea00,0xeb00,0xec00,0xed00,0xee00,0xef00, 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, 0xf000,0xf100,0xf200,0xf300,0xf400,0xf500,0x0600,0xf700,0xf800,0xf900,0xfa00,0xfb00,0xfc00,0xfd00,0xfe00,0xff00,
0xffff}; 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)) { if (!gamma_proto & (hash16==0)) {
gamma_proto=gamma_linear; gamma_proto=gamma_linear;
MDF10(printk("Using linear table\n")); dev_dbg(g_dev_ptr, "Using linear table\n");
} else { } 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 ///disable interrupts here
D1I(local_irq_save(flags)); // D1I(local_irq_save(flags));
// look for the matching hash spin_lock_bh(&gamma_lock);
tmp_p=gammas[0].newest_non_scaled; // look for the matching hash
// gammas[0].oldest_all=GAMMA_CACHE_NUMBER-1; tmp_p=gammas[0].newest_non_scaled;
// 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);
while ((tmp_p!=0) && (gammas[tmp_p].hash16 != hash16)) { 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 );
D10(printk(" --tmp_p=0x%x\n", tmp_p)); ///NOTE: never while ((tmp_p!=0) && (gammas[tmp_p].hash16 != hash16)) {
tmp_p=gammas[tmp_p].older_non_scaled; 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?
if (tmp_p == 0) { // no luck
MDF10(printk("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
return 0; // matching hash not found, new table is not provided - return 0;
} }
// Create new proto table dev_dbg(g_dev_ptr,"tmp_p=0x%x\n", tmp_p); ///NOTE: 0xff
tmp_p=gamma_new_node(); // Got right hash?
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])); if (tmp_p == 0) { // no luck
if (unlikely(!tmp_p)) { // could not allocate node dev_dbg(g_dev_ptr,"Need new table\n"); ///NOTE: never
D1I(local_irq_restore(flags)); if (!gamma_proto) { //
return 0; // failure: could not allocate node - return 0; 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
tmp_p=gamma_new_node();
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));
spin_unlock_bh(&gamma_lock);
return 0; // failure: could not allocate node - return 0;
}
// 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 - 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));
spin_unlock_bh(&gamma_lock);
return 0; // failure: other code used this node - return 0; (try not_nice next time?)
}
}
// 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
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)
} else if (gammas[tmp_p].newer_non_scaled !=0) { // if 0 - it is already the newest
dev_dbg(g_dev_ptr,"remove_from_nonscaled (0x%x)\n", tmp_p); ///NOTE: 0xff
remove_from_nonscaled (tmp_p);
dev_dbg(g_dev_ptr,"insert_first_nonscaled (0x%x)\n", tmp_p);///NOTE: 0xff
insert_first_nonscaled(tmp_p);
} }
// fill it: dev_dbg(g_dev_ptr,"tmp_p= 0x%x\n", tmp_p); ///NOTE: 0xff
gammas[tmp_p].hash16=hash16;
gammas[tmp_p].scale=0;
gammas[tmp_p].oldest_scaled=tmp_p; // points to itself - no scaled versions yet // now looking for the correct scale.
gammas[tmp_p].newest_scaled=tmp_p; // points to itself - no scaled versions yet if (scale==0) {
if ((mode & GAMMA_MODE_NOT_NICE)==0) { // D1I(local_irq_restore(flags));
// let interrupts to take place, and disable again spin_unlock_bh(&gamma_lock);
D1I(local_irq_restore(flags)); return tmp_p; // wanted non-scaled, got it ///NOTE: returns here
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));
return 0; // failure: other code used this node - return 0; (try not_nice next time?)
}
} }
// memcpy ((void *)... tmp_p1=gammas[tmp_p].newest_scaled;
memcpy (gammas[tmp_p].direct, gamma_proto, 257*2) ; ///copy the provided table (full 16 bits) dev_dbg(g_dev_ptr,"tmp_p1=0x%x\n", tmp_p1); ///FIXME: 0xff
gammas[tmp_p].valid |= GAMMA_VALID_MASK; while ((tmp_p1!=tmp_p) && (gammas[tmp_p1].scale != scale)){ ///FIXME: got stuck here
// add it to the chain dev_dbg(g_dev_ptr," >>tmp_p1=0x%x)\n", tmp_p1);
MDF10(printk("insert_first_nonscaled(0x%x)\n", tmp_p)); tmp_p1=gammas[tmp_p1].older_scaled;
insert_first_nonscaled(tmp_p);
// 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
remove_from_nonscaled (tmp_p);
MDF10(printk("insert_first_nonscaled (0x%x)\n", tmp_p));///NOTE: 0xff
insert_first_nonscaled(tmp_p);
}
MDF10(printk("0x%x\n", tmp_p)); ///NOTE: 0xff
// now looking for the correct scale.
if (scale==0) {
D1I(local_irq_restore(flags));
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
while ((tmp_p1!=tmp_p) && (gammas[tmp_p1].scale != scale)){ ///FIXME: got stuck here
D10(printk(" >>tmp_p1=0x%x)\n", tmp_p1));
tmp_p1=gammas[tmp_p1].older_scaled;
}
// 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
tmp_p1=gamma_new_node();
if (unlikely(!tmp_p1)) { // could not allocate node
D1I(local_irq_restore(flags));
return 0; // failure: could not allocate node - return 0;
} }
// fill it // Got right scale?
gammas[tmp_p1].hash16=hash16; // if (tmp_p1 == 0) { // no luck
gammas[tmp_p1].scale= scale; if (tmp_p1 == tmp_p) { // no luck
// insert into 2-d dev_dbg(g_dev_ptr,"create new scaled table\n");
insert_first_scaled (tmp_p, tmp_p1); // create new scale
// insert into 1-d (all) tmp_p1=gamma_new_node();
insert_first_all (tmp_p1); if (unlikely(!tmp_p1)) { // could not allocate node
if ((mode & GAMMA_MODE_NOT_NICE)==0) { // D1I(local_irq_restore(flags));
// let interrupts to take place, and disable again spin_unlock_bh(&gamma_lock);
D1I(local_irq_restore(flags)); return 0; // failure: could not allocate node - return 0;
D1I(local_irq_save(flags)); }
// check if it is still there (likely so, but allow it to fail). // fill it
if (unlikely(!is_gamma_current (hash16, scale, tmp_p1))) { gammas[tmp_p1].hash16=hash16;
D1I(local_irq_restore(flags)); gammas[tmp_p1].scale= scale;
return 0; // failure: other code used this node - return 0; (try not_nice next time?) // insert into 2-d
} insert_first_scaled (tmp_p, tmp_p1);
// 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 - 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));
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:
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
if (gammas[tmp_p1].newer_all != 0) { // not already the newest from all scaled
remove_from_all (tmp_p1);
insert_first_all (tmp_p1);
}
} }
} else { // scaled table already exists, make it first in 2 chains: // is the scaled version already calculated?
MDF10(printk("reuse scaled table\n")); if ((gammas[tmp_p1].valid & GAMMA_VALID_MASK) == 0) {
// found right scale, make it newest in two chain (2d - hash/scale and 1-d - all scaled together, regardless of the hash // calculate scaled version
///2-d chain gamma_calc_scaled (scale, gammas[tmp_p].direct, gammas[tmp_p1].direct);
if (gammas[tmp_p1].newer_scaled != tmp_p) { // not already the newest of scales for the same hash gammas[tmp_p1].valid |= GAMMA_VALID_MASK;
remove_from_scaled (tmp_p1);
insert_first_scaled (tmp_p, tmp_p1);
} }
///1-d chain if (mode & GAMMA_MODE_HARDWARE) {
if (gammas[tmp_p1].newer_all != 0) { // not already the newest from all scaled // is hardware-encoded array already calculated (do it if not)?
remove_from_all (tmp_p1); if ((gammas[tmp_p1].valid & GAMMA_FPGA_MASK)==0) {
insert_first_all (tmp_p1); gamma_encode_fpga(gammas[tmp_p1].direct, gammas[tmp_p1].fpga);
gammas[tmp_p1].valid |= GAMMA_FPGA_MASK;
}
} }
} if (mode & GAMMA_MODE_LOCK) {
// is the scaled version already calculated? // lock the node for the color/port/channel
if ((gammas[tmp_p1].valid & GAMMA_VALID_MASK) == 0) { lock_gamma_node (tmp_p1, color, sensor_port,sensor_subchn);
// 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)?
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_NEED_REVERSE) {
if (mode & GAMMA_MODE_LOCK) { if ((gammas[tmp_p1].valid & GAMMA_VALID_REVERSE)==0) {
// lock the node for the color/port/channel if ((mode & GAMMA_MODE_NOT_NICE)==0) {
lock_gamma_node (tmp_p1, color, sensor_port,sensor_subchn); // let interrupts to take place, and disable again // not needed with tasklets
} // D1I(local_irq_restore(flags));
if (mode & GAMMA_MODE_NEED_REVERSE) { // D1I(local_irq_save(flags));
if ((gammas[tmp_p1].valid & GAMMA_VALID_REVERSE)==0) { // check if it is still there (likely so, but allow it to fail).
if ((mode & GAMMA_MODE_NOT_NICE)==0) { if (unlikely(!is_gamma_current (hash16, 0, tmp_p))) {
// let interrupts to take place, and disable again // D1I(local_irq_restore(flags));
D1I(local_irq_restore(flags)); spin_unlock_bh(&gamma_lock);
D1I(local_irq_save(flags)); return 0; // failure: other code used this node - return 0; (try not_nice next time?)
// 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)); gamma_calc_reverse(gammas[tmp_p1].direct, gammas[tmp_p1].reverse);
return 0; // failure: other code used this node - return 0; (try not_nice next time?) gammas[tmp_p1].valid |= GAMMA_VALID_REVERSE;
} }
}
gamma_calc_reverse(gammas[tmp_p1].direct, gammas[tmp_p1].reverse);
gammas[tmp_p1].valid |= GAMMA_VALID_REVERSE;
} }
} // D1I(local_irq_restore(flags));
D1I(local_irq_restore(flags)); spin_unlock_bh(&gamma_lock);
MDF10(printk("- return %d\n",tmp_p1));
return tmp_p1; 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 */ /** 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) *
int sensor_port, ///< sensor port (0..3) * This code may be called from the IRQ context, and from the different CPU */
int sensor_subchn, ///< sensor sub-channel (when several are connected through a multiplexer)
u32 * gamma) ///< Gamma table (256 DWORDs) in encoded FPGA format 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)
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_a = {.d32=0};
x393_gamma_tbl_t gamma_tbl_d = {.d32=0}; x393_gamma_tbl_t gamma_tbl_d = {.d32=0};
const int gamma_size=256; // 18-bit entries const int gamma_size=256; // 18-bit entries
unsigned long flags; // unsigned long flags;
int addr32, len32, i; int addr32, len32, i;
if (is_fpga_programmed()<=0){
return -ENODEV;
}
gamma_tbl_a.a_n_d = 1; gamma_tbl_a.a_n_d = 1;
gamma_tbl_a.color = color; gamma_tbl_a.color = color;
gamma_tbl_a.sub_chn = sensor_subchn; gamma_tbl_a.sub_chn = sensor_subchn;
spin_lock_bh(gamma_locks[sensor_port]);
for (addr32 = 0; addr32 < gamma_size; addr32 += FPGA_TABLE_CHUNK){ for (addr32 = 0; addr32 < gamma_size; addr32 += FPGA_TABLE_CHUNK){
len32 = FPGA_TABLE_CHUNK; len32 = FPGA_TABLE_CHUNK;
if (unlikely(addr32 + len32 > gamma_size)) if (unlikely(addr32 + len32 > gamma_size))
len32 = gamma_size - addr32; len32 = gamma_size - addr32;
gamma_tbl_a.addr= 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); x393_sens_gamma_tbl(gamma_tbl_a, sensor_port);
for (i = addr32; i < addr32 + len32; i++){ for (i = addr32; i < addr32 + len32; i++){
gamma_tbl_d.d32 = gamma[i]; gamma_tbl_d.d32 = gamma[i];
x393_sens_gamma_tbl(gamma_tbl_d, sensor_port); 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;
} }
///====================================== ///======================================
...@@ -726,12 +765,12 @@ void fpga_gamma_write_nice(int color, ///< Color (0..3) ...@@ -726,12 +765,12 @@ void fpga_gamma_write_nice(int color, ///< Color (0..3)
*/ */
#define GAMMA_FILE_SIZE GAMMA_CACHE_NUMBER #define GAMMA_FILE_SIZE GAMMA_CACHE_NUMBER
static struct file_operations gammas_fops = { static struct file_operations gammas_fops = {
owner: THIS_MODULE, owner: THIS_MODULE,
llseek: gammas_lseek, llseek: gammas_lseek,
write: gammas_write, write: gammas_write,
open: gammas_open, open: gammas_open,
mmap: gammas_mmap, mmap: gammas_mmap,
release: gammas_release release: gammas_release
}; };
/** /**
* @brief Gammas driver OPEN method * @brief Gammas driver OPEN method
...@@ -740,28 +779,28 @@ static struct file_operations gammas_fops = { ...@@ -740,28 +779,28 @@ static struct file_operations gammas_fops = {
* @return OK - 0, -EINVAL for wrong minor * @return OK - 0, -EINVAL for wrong minor
*/ */
int gammas_open(struct inode *inode, struct file *file) { int gammas_open(struct inode *inode, struct file *file) {
int res; int res;
struct gammas_pd * privData; struct gammas_pd * privData;
privData= (struct gammas_pd *) kmalloc(sizeof(struct gammas_pd),GFP_KERNEL); privData= (struct gammas_pd *) kmalloc(sizeof(struct gammas_pd),GFP_KERNEL);
MDF10(printk("gammas[0].oldest_all=%d\n", gammas[0].oldest_all)); dev_dbg(g_dev_ptr,"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].newest_all=%d\n", gammas[0].newest_all);
if (!privData) return -ENOMEM; if (!privData) return -ENOMEM;
file->private_data = privData; file->private_data = privData;
privData-> minor=MINOR(inode->i_rdev); privData-> minor=MINOR(inode->i_rdev);
MDF10(printk("gammas_open, minor=0x%x\n",privData-> minor)); MDF10(printk("gammas_open, minor=0x%x\n",privData-> minor));
switch (privData-> minor) { switch (privData-> minor) {
case DEV393_MINOR(DEV393_GAMMA) : case DEV393_MINOR(DEV393_GAMMA) :
inode->i_size = GAMMA_FILE_SIZE; inode->i_size = GAMMA_FILE_SIZE;
privData-> scale= 0; privData-> scale= 0;
privData-> hash16=0; privData-> hash16=0;
privData-> mode= 0; privData-> mode= 0;
return 0; return 0;
default: default:
kfree(file->private_data); // already allocated kfree(file->private_data); // already allocated
return -EINVAL; return -EINVAL;
} }
file->f_pos = 0; file->f_pos = 0;
return res; return res;
} }
/** /**
...@@ -771,17 +810,17 @@ int gammas_open(struct inode *inode, struct file *file) { ...@@ -771,17 +810,17 @@ int gammas_open(struct inode *inode, struct file *file) {
* @return OK - 0, -EINVAL for wrong minor * @return OK - 0, -EINVAL for wrong minor
*/ */
int gammas_release(struct inode *inode, struct file *file) { int gammas_release(struct inode *inode, struct file *file) {
int res=0; int res=0;
int p = MINOR(inode->i_rdev); int p = MINOR(inode->i_rdev);
MDF10(printk("gammas_release, minor=0x%x\n",p)); MDF10(printk("gammas_release, minor=0x%x\n",p));
switch ( p ) { switch ( p ) {
case DEV393_MINOR(DEV393_GAMMA) : case DEV393_MINOR(DEV393_GAMMA) :
break; break;
default: default:
return -EINVAL; //! do not need to free anything - "wrong number" return -EINVAL; //! do not need to free anything - "wrong number"
} }
kfree(file->private_data); kfree(file->private_data);
return res; return res;
} }
...@@ -801,46 +840,46 @@ int gammas_release(struct inode *inode, struct file *file) { ...@@ -801,46 +840,46 @@ int gammas_release(struct inode *inode, struct file *file) {
* @return file position gamma cache index (0 - invalid) * @return file position gamma cache index (0 - invalid)
*/ */
loff_t gammas_lseek (struct file * file, loff_t offset, int orig) { loff_t gammas_lseek (struct file * file, loff_t offset, int orig) {
struct gammas_pd * privData = (struct gammas_pd *) file->private_data; struct gammas_pd * privData = (struct gammas_pd *) file->private_data;
MDF10(printk("offset=0x%x, orig=0x%x, file->f_pos=0x%x\n",(int) offset, (int) orig, (int) file->f_pos)); MDF10(printk("offset=0x%x, orig=0x%x, file->f_pos=0x%x\n",(int) offset, (int) orig, (int) file->f_pos));
switch (privData->minor) { switch (privData->minor) {
case DEV393_MINOR(DEV393_GAMMA) : case DEV393_MINOR(DEV393_GAMMA) :
switch(orig) { switch(orig) {
case SEEK_SET: case SEEK_SET:
file->f_pos = offset; file->f_pos = offset;
break; break;
case SEEK_CUR: case SEEK_CUR:
// file->f_pos = getThisFrameNumber() + offset; // file->f_pos = getThisFrameNumber() + offset;
break; break;
case SEEK_END: case SEEK_END:
if (offset < 0) { if (offset < 0) {
break; break;
} else if (offset == 0) { } else if (offset == 0) {
file->f_pos=GAMMA_CACHE_NUMBER; file->f_pos=GAMMA_CACHE_NUMBER;
break; break;
} else {//!Execute commands } else {//!Execute commands
switch (offset) { switch (offset) {
case LSEEK_GAMMA_INIT: case LSEEK_GAMMA_INIT:
init_gammas(); init_gammas();
file->f_pos=0; file->f_pos=0;
break; break;
case LSEEK_GAMMA_ISCURRENT: case LSEEK_GAMMA_ISCURRENT:
if (file->f_pos==0) break; // wrong index if (file->f_pos==0) break; // wrong index
if (!is_gamma_current (privData->hash16, privData->scale, (int) file->f_pos)) file->f_pos=0; if (!is_gamma_current (privData->hash16, privData->scale, (int) file->f_pos)) file->f_pos=0;
break; break;
default: ///other commands default: ///other commands
return -EINVAL; return -EINVAL;
} }
break; break;
} }
default: // not SEEK_SET/SEEK_CUR/SEEK_END default: // not SEEK_SET/SEEK_CUR/SEEK_END
return -EINVAL; return -EINVAL;
} // switch (orig) } // switch (orig)
MDF10(printk("file->f_pos=0x%x\n",(int) file->f_pos)); MDF10(printk("file->f_pos=0x%x\n",(int) file->f_pos));
return file->f_pos ; return file->f_pos ;
default: // other minors default: // other minors
return -EINVAL; return -EINVAL;
} }
} }
/** Gammas driver WRITE method /** Gammas driver WRITE method
...@@ -853,43 +892,43 @@ loff_t gammas_lseek (struct file * file, loff_t offset, int orig) { ...@@ -853,43 +892,43 @@ loff_t gammas_lseek (struct file * file, loff_t offset, int orig) {
* - next 514 bytes [6..519] - 16-bit gamma table (if less than 514 bytes NULL will be passed to \b set_gamma_table() * - next 514 bytes [6..519] - 16-bit gamma table (if less than 514 bytes NULL will be passed to \b set_gamma_table()
* sets file pointer to gamma cache index (0 - no table exist) */ * sets file pointer to gamma cache index (0 - no table exist) */
ssize_t gammas_write(struct file * file, ///< this file structure ssize_t gammas_write(struct file * file, ///< this file structure
const char * buf, ///< userland buffer const char * buf, ///< userland buffer
size_t count, ///< number of bytes to write size_t count, ///< number of bytes to write
loff_t *off) ///< updated offset in the buffer 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 gammas_pd * privData = (struct gammas_pd *) file->private_data;
struct { struct {
unsigned short scale; unsigned short scale;
unsigned short hash16; unsigned short hash16;
unsigned char mode; unsigned char mode;
unsigned char color; // 393: it is now combination of color, port and channel. Could not find what are the 3 LSBs ((privData->color >> 3) &3) below unsigned char color; // 393: it is now combination of color, port and channel. Could not find what are the 3 LSBs ((privData->color >> 3) &3) below
unsigned short gamma[257]; unsigned short gamma[257];
} data; } data;
int head, result; 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; 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) { switch (privData->minor) {
case DEV393_MINOR(DEV393_GAMMA) : case DEV393_MINOR(DEV393_GAMMA) :
if (count>sizeof (data)) count = sizeof (data); if (count>sizeof (data)) count = sizeof (data);
if(count) { if(count) {
if(copy_from_user((char *) &data, buf, count)) return -EFAULT; if(copy_from_user((char *) &data, buf, count)) return -EFAULT;
head=6; head=6;
if ((count-head) < (2 * 257)) gamma=NULL; // complete gamma table is not available if ((count-head) < (2 * 257)) gamma=NULL; // complete gamma table is not available
if (head>count) head=count; if (head>count) head=count;
memcpy (&(privData->scale),&(data.scale),head); 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)); 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);
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)); 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 >> 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); 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; *off= (result>0)?result:0;
} else *off=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; return (*off) ? count: 0;
default: return -EINVAL; default: return -EINVAL;
} }
} }
/** /**
...@@ -899,69 +938,75 @@ ssize_t gammas_write(struct file * file, ///< this file structure ...@@ -899,69 +938,75 @@ ssize_t gammas_write(struct file * file, ///< this file structure
* @return OK - 0, negative - errors * @return OK - 0, negative - errors
*/ */
int gammas_mmap (struct file *file, struct vm_area_struct *vma) { int gammas_mmap (struct file *file, struct vm_area_struct *vma) {
int result; int result;
struct gammas_pd * privData = (struct gammas_pd *) file->private_data; 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) { switch (privData->minor) {
case DEV393_MINOR(DEV393_GAMMA) : case DEV393_MINOR(DEV393_GAMMA) :
result=remap_pfn_range(vma, result=remap_pfn_range(vma,
vma->vm_start, vma->vm_start,
((unsigned long) virt_to_phys(gammas_p)) >> PAGE_SHIFT, // Should be page-aligned ((unsigned long) virt_to_phys(gammas_p)) >> PAGE_SHIFT, // Should be page-aligned
vma->vm_end-vma->vm_start, vma->vm_end-vma->vm_start,
vma->vm_page_prot); 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; if (result) return -EAGAIN;
return 0; return 0;
default: return -EINVAL; default: return -EINVAL;
} }
} }
/** /**
* @brief Gammas driver init * @brief Gammas driver init
* @return 0 * @return 0
*/ */
static int __init gammas_init(void) { static int gammas_init(struct platform_device *pdev) {
int res; int res;
printk ("Starting "DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA)); struct device *dev = &pdev->dev;
init_gammas(); const struct of_device_id *match; // not yet used
MDF10(printk("set_gamma_table (0, GAMMA_SCLALE_1, NULL, 0, 0)\n"); udelay (ELPHEL_DEBUG_DELAY)); dev_info(dev,"Starting "DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA));
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 init_gammas();
// hash16==0 // 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
res = register_chrdev(DEV393_MAJOR(DEV393_GAMMA), DEV393_NAME(DEV393_GAMMA), &gammas_fops); // hash16==0
if(res < 0) {
printk(KERN_ERR "\ngammas_init: couldn't get a major number %d.\n",DEV393_MAJOR(DEV393_GAMMA)); res = register_chrdev(DEV393_MAJOR(DEV393_GAMMA), DEV393_NAME(DEV393_GAMMA), &gammas_fops);
return res; if(res < 0) {
} dev_err(dev,"\ngammas_init: couldn't get a major number %d.\n",DEV393_MAJOR(DEV393_GAMMA));
// init_waitqueue_head(&gammas_wait_queue); return res;
printk(DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA)); }
return 0; // 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); static const struct of_device_id elphel393_gamma_tables_of_match[] = {
MODULE_LICENSE("GPLv3.0"); { .compatible = "elphel,elphel393-gamma_tables-1.00" },
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>."); { /* end of list */ }
MODULE_DESCRIPTION(X3X3_GAMMAS_DRIVER_DESCRIPTION); };
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: ...@@ -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) /// 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); 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); int gamma_new_node(void);
......
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
*/ */
//copied from cxi2c.c - TODO:remove unneeded //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/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -88,6 +88,9 @@ ...@@ -88,6 +88,9 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
//#include <linux/autoconf.h> //#include <linux/autoconf.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
...@@ -115,7 +118,8 @@ ...@@ -115,7 +118,8 @@
#include <elphel/elphel393-mem.h> #include <elphel/elphel393-mem.h>
#include "x393.h" #include "x393.h"
#include "histograms.h" #include "histograms.h"
#include "detect_sensors.h"
#include "x393_fpga_functions.h" // to check bitsteram
/** /**
* \def MDF21(x) optional debug output * \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 ...@@ -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 */ /** for each port and possible sensor subchannel provides index in combine histogram data */
int histograms_map[SENSOR_PORTS][MAX_SENSORS]; 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 */ /** total number of sensors (on all ports) used */
static int numHistChn = 0; static int numHistChn = 0;
...@@ -151,12 +157,44 @@ struct histogram_stuct_t (*histograms)[HISTOGRAM_CACHE_NUMBER]; ...@@ -151,12 +157,44 @@ struct histogram_stuct_t (*histograms)[HISTOGRAM_CACHE_NUMBER];
dma_addr_t histograms_phys; ///< likely not needed, saved during allocation dma_addr_t histograms_phys; ///< likely not needed, saved during allocation
struct histogram_stuct_t * histograms_p; ///< alias of histogram_stuct_t 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_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) 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 */ /** File operations private data */
struct histograms_pd { struct histograms_pd {
...@@ -184,7 +222,6 @@ int histograms_open (struct inode *inode, struct file *file); ...@@ -184,7 +222,6 @@ int histograms_open (struct inode *inode, struct file *file);
int histograms_release(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); loff_t histograms_lseek (struct file * file, loff_t offset, int orig);
int histograms_mmap (struct file *file, struct vm_area_struct *vma); 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 ); 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 ...@@ -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)? */ /** 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 void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask to global P-variable
{ {
#ifdef HISTOGRAMS_DISABLE_IRQ
unsigned long flags; unsigned long flags;
#endif
int p,s,i, sz,pages; int p,s,i, sz,pages;
numHistChn = 0; //__builtin_popcount (chn_mask & 0xffff); numHistChn = 0; //__builtin_popcount (chn_mask & 0xffff);
for (p=0; p< SENSOR_PORTS; p++) for (s=0;s <MAX_SENSORS;s++) { 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 ...@@ -241,28 +281,44 @@ void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask
GLOBALPARS(p, G_SUBCHANNELS) &= ~(1 << s); 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 //G_SUBCHANNELS
sz = numHistChn * HISTOGRAM_CACHE_NUMBER * sizeof(struct histogram_stuct_t); sz = numHistChn * HISTOGRAM_CACHE_NUMBER * sizeof(struct histogram_stuct_t);
if (sz & (PAGE_SIZE-1)) pages++; pages = ((sz -1) >> PAGE_SHIFT)+1;
pages = sz >> PAGE_SHIFT; // if (sz & (PAGE_SIZE-1)) pages++;
// When device == NULL, dma_alloc_coherent just allocates notmal memory, page aligned, CMA if available // 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 = (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); BUG_ON(!histograms);
histograms_p= (struct histogram_stuct_t *) histograms; histograms_p= (struct histogram_stuct_t *) histograms;
MDF21(printk("\n")); // MDF21(printk("\n"));
#ifdef HISTOGRAMS_DISABLE_IRQ
local_irq_save(flags); 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 (s=0; s<numHistChn; s++) {
for (i=0; i < HISTOGRAM_CACHE_NUMBER; i++) { for (i=0; i < HISTOGRAM_CACHE_NUMBER; i++) {
histograms[s][i].frame=0xffffffff; histograms[s][i].frame=0xffffffff;
histograms[s][i].valid=0; histograms[s][i].valid=0;
} }
} }
#ifdef HISTOGRAMS_DISABLE_IRQ
local_irq_restore(flags); local_irq_restore(flags);
#endif
dev_dbg(g_dev_ptr, "Histograms structures initialized");
} }
/** Get histogram index for sensor port/channel, skipping unused ones */ /** Get histogram index for sensor port/channel, skipping unused ones */
int get_hist_index (int sensor_port, ///< sensor port number (0..3) 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) ...@@ -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); index=GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn);
raw_needed=(needed | (needed>>4) | needed>>8) & 0xf; raw_needed=(needed | (needed>>4) | needed>>8) & 0xf;
for (i=0;i<HISTOGRAM_CACHE_NUMBER;i++) { 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; if ((histograms[hist_indx][index].frame <= frame) && ((histograms[hist_indx][index].valid & raw_needed)==raw_needed)) break;
index = (index-1) & (HISTOGRAM_CACHE_NUMBER-1); index = (index-1) & (HISTOGRAM_CACHE_NUMBER-1);
} }
if (i>=HISTOGRAM_CACHE_NUMBER) { 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 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()) 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 |= ((needed >>4) & 0xf0); // cumulative histograms are needed for percentile calculations
needed &= ~histograms[hist_indx][index].valid; 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 if (needed & 0xf0) { // Calculating cumulative histograms
for (i=0; i<4; i++) if (needed & ( 0x10 << i )) { for (i=0; i<4; i++) if (needed & ( 0x10 << i )) {
color_start= i<<8 ; 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] ); 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; 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 if (needed & 0xf00) { // Calculating percentiles
for (i=0; i<4; i++) if (needed & ( 0x100 << i )) { 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) ...@@ -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] ); 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; 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; return index;
} }
...@@ -461,7 +517,7 @@ int histograms_open(struct inode *inode, ///< inode ...@@ -461,7 +517,7 @@ int histograms_open(struct inode *inode, ///< inode
if (!privData) return -ENOMEM; if (!privData) return -ENOMEM;
file->private_data = privData; file->private_data = privData;
privData-> minor=MINOR(inode->i_rdev); 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) { switch (privData-> minor) {
case DEV393_MINOR(DEV393_HISTOGRAM) : case DEV393_MINOR(DEV393_HISTOGRAM) :
inode->i_size = HISTOGRAMS_FILE_SIZE; inode->i_size = HISTOGRAMS_FILE_SIZE;
...@@ -472,6 +528,8 @@ int histograms_open(struct inode *inode, ///< inode ...@@ -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->request_en=1; // enable requesting histogram for the specified frame (0 - rely on the available ones)
privData->port=0; privData->port=0;
privData->subchannel=0; privData->subchannel=0;
if (histograms_check_init() < 2)
return -ENODEV; // Bitstream not loaded?
return 0; return 0;
default: default:
kfree(file->private_data); // already allocated kfree(file->private_data); // already allocated
...@@ -488,7 +546,7 @@ int histograms_release (struct inode *inode, ///< inode ...@@ -488,7 +546,7 @@ int histograms_release (struct inode *inode, ///< inode
{ {
int res=0; int res=0;
int p = MINOR(inode->i_rdev); 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 ) { switch ( p ) {
case DEV393_MINOR(DEV393_HISTOGRAM) : case DEV393_MINOR(DEV393_HISTOGRAM) :
break; break;
...@@ -533,7 +591,7 @@ loff_t histograms_lseek (struct file * file, ...@@ -533,7 +591,7 @@ loff_t histograms_lseek (struct file * file,
struct histograms_pd * privData = (struct histograms_pd *) file->private_data; struct histograms_pd * privData = (struct histograms_pd *) file->private_data;
unsigned long reqAddr,reqFrame; 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) { switch (privData->minor) {
case DEV393_MINOR(DEV393_HISTOGRAM) : case DEV393_MINOR(DEV393_HISTOGRAM) :
switch(orig) { switch(orig) {
...@@ -615,11 +673,11 @@ loff_t histograms_lseek (struct file * file, ...@@ -615,11 +673,11 @@ loff_t histograms_lseek (struct file * file,
default: default:
switch (offset & ~0x1f) { switch (offset & ~0x1f) {
case LSEEK_DAEMON_HIST_Y: // wait for daemon enabled and histograms Y ready 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))); wait_event_interruptible (hist_y_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f)));
break; break;
case LSEEK_DAEMON_HIST_C: // wait for daemon enabled and histograms Y ready 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))); wait_event_interruptible (hist_c_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f)));
break; break;
default: default:
...@@ -653,17 +711,17 @@ loff_t histograms_lseek (struct file * file, ...@@ -653,17 +711,17 @@ loff_t histograms_lseek (struct file * file,
int histograms_mmap (struct file *file, struct vm_area_struct *vma) { int histograms_mmap (struct file *file, struct vm_area_struct *vma) {
int result; int result;
struct histograms_pd * privData = (struct histograms_pd *) file->private_data; 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) { switch (privData->minor) {
case DEV393_MINOR(DEV393_HISTOGRAM) : case DEV393_MINOR(DEV393_HISTOGRAM) :
result=remap_pfn_range(vma, result=remap_pfn_range(vma,
vma->vm_start, vma->vm_start,
((unsigned long) virt_to_phys(histograms_p)) >> PAGE_SHIFT, // Should be page-aligned ((unsigned long) virt_to_phys(histograms_p)) >> PAGE_SHIFT, // Should be page-aligned
vma->vm_end-vma->vm_start, vma->vm_end-vma->vm_start,
vma->vm_page_prot); 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; if (result) return -EAGAIN;
return 0; return 0;
default: return -EINVAL; default: return -EINVAL;
} }
} }
...@@ -672,24 +730,62 @@ int histograms_mmap (struct file *file, struct vm_area_struct *vma) { ...@@ -672,24 +730,62 @@ int histograms_mmap (struct file *file, struct vm_area_struct *vma) {
* @brief Histograms driver init * @brief Histograms driver init
* @return 0 * @return 0
*/ */
static int __init histograms_init(void) { int histograms_init(struct platform_device *pdev) {
int res; 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 // init_histograms(); // Not now??? Need to have list of channels
// Do it later, from the user space // 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) { 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; return res;
} }
// init_waitqueue_head(&histograms_wait_queue); // 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_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) 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; 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_LICENSE("GPLv3.0");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>."); MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(X3X3_HISTOGRAMS_DRIVER_DESCRIPTION); MODULE_DESCRIPTION(X3X3_HISTOGRAMS_DRIVER_DESCRIPTION);
...@@ -20,13 +20,11 @@ ...@@ -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_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) 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); // void init_histograms(int chn_mask);
int histograms_check_init(void);
int get_hist_index (int sensor_port, int sensor_chn); 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 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 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 void histograms_dma_ctrl(int mode); // 0 - reset, 1 - disable, 2 - enable
...@@ -323,7 +323,7 @@ ...@@ -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 FILES SECTION ***********************************/
#include <linux/types.h> // for div 64 #include <linux/types.h> // for div 64
#include <asm/div64.h> // for div 64 #include <asm/div64.h> // for div 64
...@@ -337,6 +337,8 @@ ...@@ -337,6 +337,8 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/init.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/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/delay.h> #include <asm/delay.h>
...@@ -385,6 +387,12 @@ ...@@ -385,6 +387,12 @@
#define MD9(x) #define MD9(x)
#endif #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 */ /** Capabilities of MT9M001 1.3 MPix */
struct sensor_t mt9m001={ struct sensor_t mt9m001={
...@@ -686,15 +694,15 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -686,15 +694,15 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
u32 i2c_read_dataw; u32 i2c_read_dataw;
// u8 * i2c_read_data = (u8*)& i2c_read_dataw; // each two bytes - one short word, big endian // u8 * i2c_read_data = (u8*)& i2c_read_dataw; // each two bytes - one short word, big endian
// unsigned char chipver_reg=P_MT9X001_CHIPVER; // unsigned char chipver_reg=P_MT9X001_CHIPVER;
// u32 chipver_reg=P_MT9X001_CHIPVER;
int sensor_subtype=0; int sensor_subtype=0;
int i; int i;
struct sensor_t * psensor; // current sensor struct sensor_t * psensor; // current sensor
x393_sensio_ctl_t sensio_ctl = {.d32=0}; 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)); // 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() 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; return sensor->sensorType;
} }
...@@ -714,7 +722,7 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -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) i2c_readData (0, (psensor->i2c_addr) | 1, i2c_read_data, 2, 0); ///restart, not start (cxi2c.c)
local_irq_restore(flags); // IRQ restore local_irq_restore(flags); // IRQ restore
if (((I2C_READ_DATA16(0) ^ MT9P001_PARTID) & MT9X001_PARTIDMASK)==0) { 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; sensor_subtype=MT9P_TYP; //1;
} }
#else #else
...@@ -735,13 +743,14 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -735,13 +743,14 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
x393_sensio_ctrl(sensio_ctl,sensor_port); x393_sensio_ctrl(sensio_ctl,sensor_port);
udelay(50); // is it needed? udelay(50); // is it needed?
X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_MT9X001_CHIPVER, &i2c_read_dataw); 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) { 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; sensor_subtype=MT9P_TYP; //1;
} }
#endif #endif
// 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]);
// MDD1(printk("sensor=0x%x\n", (int)sensor)); // MDD1(dev_dbg(g_dev_ptr,"sensor=0x%x\n", (int)sensor));
if (sensor_subtype ==0) { // not a 5MPix chip if (sensor_subtype ==0) { // not a 5MPix chip
// CCAM_ARST_ON; // Why was it here // CCAM_ARST_ON; // Why was it here
psensor= &mt9m001; //address the same for all others psensor= &mt9m001; //address the same for all others
...@@ -751,17 +760,17 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -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_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 i2c_readData (0, (psensor->i2c_addr) | 1, i2c_read_data, 2, 0); //restart, not strart
local_irq_restore(flags); // IRQ restore 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) { 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; psensor= &mt9m001;
sensor_subtype=MT9M_TYP; //1; sensor_subtype=MT9M_TYP; //1;
} else if (((I2C_READ_DATA16(0)^MT9D001_PARTID) & MT9X001_PARTIDMASK)==0) { } 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; psensor= &mt9d001;
sensor_subtype=MT9D_TYP; //2; sensor_subtype=MT9D_TYP; //2;
} else if (((I2C_READ_DATA16(0)^MT9T001_PARTID) & MT9X001_PARTIDMASK)==0) { } 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; psensor= &mt9t001;
sensor_subtype=MT9T_TYP; //3; sensor_subtype=MT9T_TYP; //3;
// if(d[2] == 0x01) - MT9T001 chip rev 01 - color gains had a bug // 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 ...@@ -769,41 +778,43 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
#else #else
X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_MT9X001_CHIPVER, &i2c_read_dataw); X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_MT9X001_CHIPVER, &i2c_read_dataw);
if (((i2c_read_dataw ^MT9M001_PARTID) & MT9X001_PARTIDMASK)==0) { 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; psensor= &mt9m001;
sensor_subtype=MT9M_TYP; //1; sensor_subtype=MT9M_TYP; //1;
} else if (((i2c_read_dataw ^ MT9D001_PARTID) & MT9X001_PARTIDMASK)==0) { } 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; psensor= &mt9d001;
sensor_subtype=MT9D_TYP; //2; sensor_subtype=MT9D_TYP; //2;
} else if (((i2c_read_dataw ^ MT9T001_PARTID) & MT9X001_PARTIDMASK)==0) { } 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; psensor= &mt9t001;
sensor_subtype=MT9T_TYP; //3; sensor_subtype=MT9T_TYP; //3;
// if(d[2] == 0x01) - MT9T001 chip rev 01 - color gains had a bug // 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 #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 if (sensor_subtype ==0) return 0; // no sensor found
// Sensor recognized, go on // Sensor recognized, go on
// memcpy(&sensor, psensor, sizeof(mt9p001)); // copy sensor definitions // memcpy(&sensor, psensor, sizeof(mt9p001)); // copy sensor definitions
memcpy(sensor, psensor, sizeof(mt9p001)); // copy sensor definitions memcpy(sensor, psensor, sizeof(mt9p001)); // copy sensor definitions
// MDD1(printk("sensor=0x%x\n", (int)sensor)); // MDD1(dev_dbg(g_dev_ptr,"sensor=0x%x\n", (int)sensor));
MDF1(printk("copied %d bytes of sensor static parameters\r\n",sizeof(mt9p001))); dev_dbg(g_dev_ptr,"{%d} copied %d bytes of sensor static parameters\n",sensor_port,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(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(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_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(sensor_port,onchange_exposure, &mt9x001_pgm_exposure); // program exposure
add_sensor_proc(onchange_window, &mt9x001_pgm_window); // program sensor WOI and mirroring (flipping) add_sensor_proc(sensor_port,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(sensor_port,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(sensor_port,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(sensor_port,onchange_gains, &mt9x001_pgm_gains); // program analog gains
add_sensor_proc(onchange_triggermode, &mt9x001_pgm_triggermode); // program sensor trigger mode add_sensor_proc(sensor_port,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)? 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(printk("sensor->sensorType=0x%lx\n", sensor->sensorType)); // MDD1(dev_dbg(g_dev_ptr,"sensor->sensorType=0x%lx\n", sensor->sensorType));
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType); // was so setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType); // was so
// setFramePar(thispars, P_SENSOR | FRAMEPAIR_FORCE_NEWPROC, sensor->sensorType); // force actions // 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 ///TODO: Fill G_MULTI_REGSM+i - which registers need individual values in multi-sensor applications
unsigned short * sensor_multi_regs; unsigned short * sensor_multi_regs;
int sensor_multi_regs_number; int sensor_multi_regs_number;
...@@ -830,17 +841,17 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port ...@@ -830,17 +841,17 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
} }
for (i=0; i<sensor_multi_regs_number; i++ ) { 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); 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])); // dev_dbg(g_dev_ptr,"{%d} i=%d, m=0x%x\n",sensor_port,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} 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 //#define GLOBALPARS(x) globalPars[(x)-FRAMEPAR_GLOBALS] // should work in drivers and applications
for (i=0;i<8;i++) { 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 // 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.d32=0;
sensio_ctl.aro = 1; sensio_ctl.aro = 1;
sensio_ctl.aro_set = 1; sensio_ctl.aro_set = 1;
...@@ -866,7 +877,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -866,7 +877,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
unsigned short * sensor_register_overwrites; unsigned short * sensor_register_overwrites;
x393_sensio_ctl_t sensio_ctl = {.d32=0}; 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 if (frame16 >= 0) return -1; // should be ASAP
// int fpga_addr=(frame16 <0) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame16); // 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 // 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 ...@@ -874,14 +885,14 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
int nupdate=0; int nupdate=0;
int i,color; int i,color;
int regval, regnum, mreg, j; 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): // reset sensor by applying MRST (low):
#ifdef NC353 #ifdef NC353
CCAM_MRST_ON; CCAM_MRST_ON;
udelay (100); udelay (100);
CCAM_MRST_OFF; CCAM_MRST_OFF;
udelay (100); 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; first_sensor_i2c=sensor->i2c_addr;
if (GLOBALPARS(sensor_port, G_SENS_AVAIL)) { 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)); 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 ...@@ -917,7 +928,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
sensio_ctl.d32=0; sensio_ctl.d32=0;
// NC393: both sequencers started in pgm_detectsensor // NC393: both sequencers started in pgm_detectsensor
udelay (100); 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; first_sensor_i2c=sensor->i2c_addr;
if (GLOBALPARS(sensor_port, G_SENS_AVAIL)) { 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)); 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 ...@@ -935,7 +946,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
} }
#endif #endif
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows 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_register_overwrites_number;
int sensor_subtype=sensor->sensorType - SENSOR_MT9X001; int sensor_subtype=sensor->sensorType - SENSOR_MT9X001;
switch (sensor_subtype) { switch (sensor_subtype) {
...@@ -958,7 +969,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -958,7 +969,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
break; break;
} }
// enable hardware i2c - NOTE: the only place where the i2c controller is enabled. // 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 #ifdef NC353
local_irq_save(flags); // IRQ Off, so both sequencers to be started at the same time local_irq_save(flags); // IRQ Off, so both sequencers to be started at the same time
i2c_run(); i2c_run();
...@@ -974,7 +985,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -974,7 +985,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
sensor->i2c_addr, sensor->i2c_addr,
sensor_register_overwrites[2*i],\ sensor_register_overwrites[2*i],\
sensor_register_overwrites[2*i+1]); 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); SETFRAMEPARS_SET(P_GAIN_MIN, 0x10000);
...@@ -986,7 +997,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port ...@@ -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 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; return 0;
} }
...@@ -1004,7 +1015,7 @@ int mt9x001_pgm_window (int sensor_port, ///< sensor port numb ...@@ -1004,7 +1015,7 @@ int mt9x001_pgm_window (int sensor_port, ///< sensor port numb
///< be applied to, negative - ASAP ///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error ///< @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); 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 ...@@ -1018,7 +1029,7 @@ int mt9x001_pgm_window_safe (int sensor_port, ///< sensor port num
///< be applied to, negative - ASAP ///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error ///< @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); 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 ...@@ -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; int i,dv,dh,bv,bh,ww,wh,wl,wt,flip,flipX,flipY,d, v;
struct frameparspair_t pars_to_update[29]; struct frameparspair_t pars_to_update[29];
int nupdate=0; 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 if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int styp = sensor->sensorType & 7; int styp = sensor->sensorType & 7;
dh= thispars->pars[P_DCM_HOR]; dh= thispars->pars[P_DCM_HOR];
...@@ -1054,7 +1065,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port ...@@ -1054,7 +1065,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
// program sensor width // program sensor width
if ((ww-1) != thispars->pars[P_SENSOR_REGS+P_MT9X001_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); 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 // height
d = (wh+1) & 0xfffe; // round up to even d = (wh+1) & 0xfffe; // round up to even
...@@ -1066,7 +1077,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port ...@@ -1066,7 +1077,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
// program sensor height // program sensor height
if ((wh-1) != thispars->pars[P_SENSOR_REGS+P_MT9X001_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); 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 // Margins
wl = thispars->pars[P_WOI_LEFT]; wl = thispars->pars[P_WOI_LEFT];
...@@ -1111,13 +1122,13 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port ...@@ -1111,13 +1122,13 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
// Program sensor left margin // Program sensor left margin
if (wl != thispars->pars[P_SENSOR_REGS+P_MT9X001_COLSTART]) { if (wl != thispars->pars[P_SENSOR_REGS+P_MT9X001_COLSTART]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_COLSTART, wl); 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 // Program sensor top margin
if (wt != thispars->pars[P_SENSOR_REGS+P_MT9X001_ROWSTART]) { if (wt != thispars->pars[P_SENSOR_REGS+P_MT9X001_ROWSTART]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_ROWSTART, wt); 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 !!! ///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 // 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 ...@@ -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) ; 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]) { if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM]) {
SET_SENSOR_PAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RAM, v); 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); 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]) { if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_CAM]) {
SET_SENSOR_PAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_CAM, v); 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 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 (flipX ? (1 << 14) : 0) | // FLIPH - will control just alternative rows
(flipY ? (1 << 15) : 0) ; // FLIPV (flipY ? (1 << 15) : 0) ; // FLIPV
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2]) { if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RMODE2, v); 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 } else { // 1.3 and 2 MPix sensors
...@@ -1148,7 +1159,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port ...@@ -1148,7 +1159,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
((dv == 8) ? (1 << 5) : 0) ; // Row skip 8 ((dv == 8) ? (1 << 5) : 0) ; // Row skip 8
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1]) { if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RMODE1, v); 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 v= (thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2] & 0x3fe7) | // preserve other bits from shadows
((dh == 2) ? (1 << 3) : 0) | // Column skip 2 ((dh == 2) ? (1 << 3) : 0) | // Column skip 2
...@@ -1157,7 +1168,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port ...@@ -1157,7 +1168,7 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
(flipY ? (1 << 15) : 0) ; // FLIPV (flipY ? (1 << 15) : 0) ; // FLIPV
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2]) { if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE2]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RMODE2, v); 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 ...@@ -1186,7 +1197,7 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
int dh= thispars->pars[P_DCM_HOR]; int dh= thispars->pars[P_DCM_HOR];
int ww= thispars->pars[P_SENSOR_PIXH] * dh; int ww= thispars->pars[P_SENSOR_PIXH] * dh;
int binning_cost = 0; int binning_cost = 0;
int width; int width,i;
int row_time_in_pixels=0; int row_time_in_pixels=0;
int hor_blank_min; int hor_blank_min;
int hor_blank=0; int hor_blank=0;
...@@ -1196,7 +1207,7 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1196,7 +1207,7 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
uint64_t ull_fp1000s; uint64_t ull_fp1000s;
#endif #endif
int target_virt_width=(thispars->pars[P_VIRT_KEEP])?(thispars->pars[P_VIRT_WIDTH]):0; 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 if (frame16 >= PARS_FRAMES) return -1; // wrong frame
switch(styp) { switch(styp) {
case MT9P_TYP: //page 16 case MT9P_TYP: //page 16
...@@ -1221,19 +1232,19 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1221,19 +1232,19 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
break; break;
} }
hor_blank_min = 208 * thispars->pars[P_BIN_VERT] + 64 + (312 + 44 + binning_cost) / 2; 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; 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; 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)); dev_dbg(g_dev_ptr,"{%d} row_time_in_pixels =%d(0x%x)\n",sensor_port,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? 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; 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 if(target_virt_width > row_time_in_pixels) { // extend line by adding horizontal blanking
hor_blank = (target_virt_width - width) / 2; hor_blank = (target_virt_width - width) / 2;
if(hor_blank > sensor->maxHorBlank) hor_blank = sensor->maxHorBlank; if(hor_blank > sensor->maxHorBlank) hor_blank = sensor->maxHorBlank;
row_time_in_pixels = width + 2 * hor_blank; 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; break;
case MT9T_TYP: case MT9T_TYP:
...@@ -1288,15 +1299,15 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1288,15 +1299,15 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
break; break;
} }
// schedule updating P_VIRT_WIDTH if it changed FIXME: Does not come here? // 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) { if (thispars->pars[P_VIRT_WIDTH ] != row_time_in_pixels) {
SETFRAMEPARS_SET(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? // 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]) { 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); 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) // Now calculate P_PERIOD (extending it as needed)
// int vh, vb, wh, h, dv, sclk, row_time_in_pixels, ve, e, i; // 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 ...@@ -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 // 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) { 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) 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 ((row_time_in_pixels * virt_height1) < thispars->pars[P_PERIOD_MIN]) virt_height1++; //round up
if (virt_height < virt_height1) virt_height = virt_height1; 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; int vert_blank= virt_height - height;
...@@ -1331,16 +1342,20 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1331,16 +1342,20 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
vert_blank = sensor->maxVertBlank; vert_blank = sensor->maxVertBlank;
virt_height = vert_blank + height; 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 // 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) { if (thispars->pars[P_VIRT_HEIGHT ] != virt_height) {
SETFRAMEPARS_SET(P_VIRT_HEIGHT, virt_height); SETFRAMEPARS_SET(P_VIRT_HEIGHT, virt_height);
} }
// schedule updating P_PERIOD if it changed // schedule updating P_PERIOD if it changed
pix_period=row_time_in_pixels*virt_height; 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) { if (thispars->pars[P_PERIOD] != pix_period) {
SETFRAMEPARS_SET(P_PERIOD, pix_period); SETFRAMEPARS_SET(P_PERIOD, pix_period);
} }
...@@ -1361,15 +1376,15 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb ...@@ -1361,15 +1376,15 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
#else #else
fp1000s= 10*sclk/(pix_period/100); fp1000s= 10*sclk/(pix_period/100);
#endif #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) { if (thispars->pars[P_FP1000S] != fp1000s) {
SETFRAMEPARS_SET(P_FP1000S, fp1000s); SETFRAMEPARS_SET(P_FP1000S, fp1000s);
} }
// schedule updating P_MT9X001_VERTBLANK sensor register and shadow // 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]) { 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); 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 if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to gains and sensor register shadows
return 0; return 0;
...@@ -1395,21 +1410,22 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port ...@@ -1395,21 +1410,22 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
if (frame16 >= PARS_FRAMES) return -1; // wrong frame if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int video_exposure = thispars->pars[P_VEXPOS]; int video_exposure = thispars->pars[P_VEXPOS];
int exposure; 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 use_vexp=0;
int sclk=thispars->pars[P_CLK_SENSOR] ; // pixel clock, in Hz 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; 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)!!! // 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 ]; int row_time_in_pixels=thispars->pars[P_VIRT_WIDTH ];
MDF1(printk(" row_time_in_pixels=0x%x\n", row_time_in_pixels)); // 0 dev_dbg(g_dev_ptr,"{%d} row_time_in_pixels=0x%x\n",sensor_port, row_time_in_pixels); // 0
// int vert_blank= thispars->pars[P_SENSOR_REGS+P_MT9X001_VERTBLANK ]; 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} 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 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 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 #if USELONGLONG
ull_exposure= ((long long)(video_exposure * row_time_in_pixels)) * ((long long) 1000000); ull_exposure= ((long long)(video_exposure * row_time_in_pixels)) * ((long long) 1000000);
#ifdef __div64_32 #ifdef __div64_32
...@@ -1508,14 +1524,14 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port ...@@ -1508,14 +1524,14 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
#else #else
fp1000s= 10*sclk/(pix_period/100); fp1000s= 10*sclk/(pix_period/100);
#endif #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) { if (thispars->pars[P_FP1000S] != fp1000s) {
SETFRAMEPARS_SET(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? // is video exposure P_VEXPOS modified?
if (thispars->pars[P_VEXPOS] != video_exposure) { if (thispars->pars[P_VEXPOS] != video_exposure) {
SETFRAMEPARS_SET(P_VEXPOS, video_exposure); SETFRAMEPARS_SET(P_VEXPOS, video_exposure);
...@@ -1529,16 +1545,16 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port ...@@ -1529,16 +1545,16 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
// high word of shutter width (>=3MPix) // high word of shutter width (>=3MPix)
if (((styp == MT9T_TYP) || (styp == MT9P_TYP)) && ((video_exposure >> 16) != thispars->pars[P_SENSOR_REGS+P_MT9X001_SHTRWDTHU])) { 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); 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) // low word of shutter width (all sensors)
if ((video_exposure & 0xffff) != thispars->pars[P_SENSOR_REGS+P_MT9X001_SHTRWDTH]) { 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); 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 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; return 0;
} }
...@@ -1557,7 +1573,7 @@ unsigned long gain_ajust_mt9x001( ...@@ -1557,7 +1573,7 @@ unsigned long gain_ajust_mt9x001(
unsigned long maxGain) ///< maximal allowed value of the analog gain (normally 0xfc000 ~ 15.75) 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 ///< @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 g=gain;
int gainIndex; // index of the gain value in the table (each register value has index, each index has preferrable register value) 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 int curGainIndex; // current index in the gains table matching sensor register value
...@@ -1571,14 +1587,14 @@ unsigned long gain_ajust_mt9x001( ...@@ -1571,14 +1587,14 @@ unsigned long gain_ajust_mt9x001(
if (g>maxGain) g=maxGain; if (g>maxGain) g=maxGain;
// calculate theoretical gainIndex (0..80) // calculate theoretical gainIndex (0..80)
gainIndex=(g<=0x40000)?(g>>13):((g-0x40000)>>14); 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 // adjust using gain table
while ((gainIndex>0) && (gainTab[gainIndex-1]>=g) && (gainTab[gainIndex-1]>=minGain)) gainIndex--; // adjust down 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 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 // Apply hysteresis
if ((gainIndex==(curGainIndex+1)) && (((gainTab[gainIndex]+gainTab[gainIndex+1])>>1)>g)) gainIndex--; 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? // did the analog gain chnage?
*newRegGain=(gainIndex==curGainIndex)?curRegGain: // no - it is the same *newRegGain=(gainIndex==curGainIndex)?curRegGain: // no - it is the same
((gainIndex<=32)?gainIndex:(gainIndex+48)); ((gainIndex<=32)?gainIndex:(gainIndex+48));
...@@ -1586,7 +1602,7 @@ unsigned long gain_ajust_mt9x001( ...@@ -1586,7 +1602,7 @@ unsigned long gain_ajust_mt9x001(
gainIndex=curGainIndex; gainIndex=curGainIndex;
*newRegGain=curRegGain; *newRegGain=curRegGain;
} }
MDF4(printk("*newRegGain=0x%lx\n",*newRegGain)); dev_dbg(g_dev_ptr,"*newRegGain=0x%lx\n",*newRegGain);
// now divide gains // now divide gains
ull_gain =((long long) gain) << 16; ull_gain =((long long) gain) << 16;
#ifdef __div64_32 #ifdef __div64_32
...@@ -1595,7 +1611,7 @@ unsigned long gain_ajust_mt9x001( ...@@ -1595,7 +1611,7 @@ unsigned long gain_ajust_mt9x001(
do_div(ull_gain, gainTab[gainIndex]); do_div(ull_gain, gainTab[gainIndex]);
// ull_gain /= gainTab[gainIndex]; // ull_gain /= gainTab[gainIndex];
#endif #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; return ((unsigned long) ull_gain) >> SHIFT_DGAIN;
} }
...@@ -1642,15 +1658,17 @@ inline unsigned long getScale16 (unsigned long nominator, ///< 32-bit nominato ...@@ -1642,15 +1658,17 @@ inline unsigned long getScale16 (unsigned long nominator, ///< 32-bit nominato
uint64_t ull_result =((long long) nominator) << 16; uint64_t ull_result =((long long) nominator) << 16;
#if ELPHEL_DEBUG #if ELPHEL_DEBUG
unsigned long * l_result= (unsigned long *) &ull_result; 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 #endif
MDF4(printk("l_result[1]=0x%lx, l_result[0]=0x%lx\n",l_result[1],l_result[0]));
#ifdef __div64_32 #ifdef __div64_32
__div64_32(&ull_result, denominator); __div64_32(&ull_result, denominator);
#else #else
do_div(ull_result, denominator); do_div(ull_result, denominator);
// ull_result /= denominator; // ull_result /= denominator;
#endif #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; return (unsigned long) ull_result;
} }
...@@ -1683,7 +1701,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb ...@@ -1683,7 +1701,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
unsigned long maxGain; unsigned long maxGain;
int limitsModified=0; int limitsModified=0;
int gaingModified=FRAMEPAR_MODIFIED(P_GAING); 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 if (frame16 >= PARS_FRAMES) return -1; // wrong frame
///make sure limits are OK ///make sure limits are OK
if (FRAMEPAR_MODIFIED(P_GAIN_MIN)) { if (FRAMEPAR_MODIFIED(P_GAIN_MIN)) {
...@@ -1726,7 +1744,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb ...@@ -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. // 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 // 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: ///Verify that green gain itself is within limits:
if (FRAMEPAR_MODIFIED(P_GAING) || limitsModified) { if (FRAMEPAR_MODIFIED(P_GAING) || limitsModified) {
if (gaing < minAnaGain) { if (gaing < minAnaGain) {
...@@ -1785,15 +1803,15 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb ...@@ -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) // (not as a result of being limited by minimal/maximal gains)
if ((FRAMEPAR_MODIFIED(P_GAINR)) && (rscale_ctl!= CSCALES_CTL_DISABLE)) { if ((FRAMEPAR_MODIFIED(P_GAINR)) && (rscale_ctl!= CSCALES_CTL_DISABLE)) {
rscale=getScale16(gainr, gaing); 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)) { if ((FRAMEPAR_MODIFIED(P_GAINGB)) && (gscale_ctl!= CSCALES_CTL_DISABLE)) {
gscale=getScale16(gaingb,gaing); 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)) { if ((FRAMEPAR_MODIFIED(P_GAINB)) && (bscale_ctl!= CSCALES_CTL_DISABLE)) {
bscale=getScale16(gainb, gaing); 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 // remove recalc flag
if (rscale_ctl == CSCALES_CTL_RECALC) rscale_ctl = CSCALES_CTL_NORMAL; 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 ...@@ -1802,20 +1820,20 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// update P_*SCALE if either scale or scale control changed // update P_*SCALE if either scale or scale control changed
if (((newval=((rscale_ctl<<CSCALES_CTL_BIT) | (rscale & ((1<<CSCALES_WIDTH)-1)))))!=rscale_all) { if (((newval=((rscale_ctl<<CSCALES_CTL_BIT) | (rscale & ((1<<CSCALES_WIDTH)-1)))))!=rscale_all) {
SETFRAMEPARS_SET(P_RSCALE, newval); 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) { if (((newval=((gscale_ctl<<CSCALES_CTL_BIT) | (gscale & ((1<<CSCALES_WIDTH)-1)))))!=gscale_all) {
SETFRAMEPARS_SET(P_GSCALE, newval); 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) { if (((newval=((bscale_ctl<<CSCALES_CTL_BIT) | (bscale & ((1<<CSCALES_WIDTH)-1)))))!=bscale_all) {
SETFRAMEPARS_SET(P_BSCALE, newval); 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)); dev_dbg(g_dev_ptr,"{%d} newval=0x%lx\n",sensor_port,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} 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 // Third part: Split overall gains into analog and digital components
...@@ -1831,7 +1849,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb ...@@ -1831,7 +1849,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// apply sensor register gain red if it was changed // apply sensor register gain red if it was changed
if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_RED]) { if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_RED]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_RED, newRegGain); 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 // schedule application of (residual after analog gain adjustment) digital gain to the red channel
if (digitalGain != thispars->pars[P_DGAINR ]) { if (digitalGain != thispars->pars[P_DGAINR ]) {
...@@ -1849,7 +1867,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb ...@@ -1849,7 +1867,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// apply sensor register gain green if it was changed // apply sensor register gain green if it was changed
if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_GREEN1]) { if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_GREEN1]) {
SET_SENSOR_MBPAR(sensor_port, frame16,sensor->i2c_addr, P_MT9X001_GREEN1, newRegGain); 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 // schedule application of (residual after analog gain adjustment) digital gain to the green channel
if (digitalGain != thispars->pars[P_DGAING ]) { if (digitalGain != thispars->pars[P_DGAING ]) {
...@@ -1866,7 +1884,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb ...@@ -1866,7 +1884,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// apply sensor register gain blue if it was changed // apply sensor register gain blue if it was changed
if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_BLUE]) { if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_BLUE]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr, P_MT9X001_BLUE, newRegGain); 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 // schedule application of (residual after analog gain adjustment) digital gain to the blue channel
if (digitalGain != thispars->pars[P_DGAINB ]) { if (digitalGain != thispars->pars[P_DGAINB ]) {
...@@ -1884,7 +1902,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb ...@@ -1884,7 +1902,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
// apply sensor register gain second green if it was changed // apply sensor register gain second green if it was changed
if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_GREEN2]) { if (newRegGain != thispars->pars[P_SENSOR_REGS+P_MT9X001_GREEN2]) {
SET_SENSOR_MBPAR(sensor_port, frame16,sensor->i2c_addr, P_MT9X001_GREEN2, newRegGain); 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 // schedule application of (residual after analog gain adjustment) digital gain to the second green channel
if (digitalGain != thispars->pars[P_DGAINGB ]) { if (digitalGain != thispars->pars[P_DGAINGB ]) {
...@@ -1895,7 +1913,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb ...@@ -1895,7 +1913,7 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
testmode= (testmode & 0x10000)? (((testmode & 0xf) << 3) | 1) : 0; testmode= (testmode & 0x10000)? (((testmode & 0xf) << 3) | 1) : 0;
if (testmode != thispars->pars[P_SENSOR_REGS+P_MT9X001_TEST]) { if (testmode != thispars->pars[P_SENSOR_REGS+P_MT9X001_TEST]) {
SET_SENSOR_MBPAR(sensor_port, frame16, sensor->i2c_addr , P_MT9X001_TEST, testmode) ; 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 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 ...@@ -1936,14 +1954,14 @@ int mt9x001_pgm_triggermode (int sensor_port, ///< sensor p
///< be applied to, negative - ASAP ///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error ///< @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]; /// struct frameparspair_t pars_to_update[4]; ///
int nupdate=0; int nupdate=0;
if (frame16 >= PARS_FRAMES) return -1; // wrong frame 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); 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]) { if (newreg != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1]) {
SET_SENSOR_MBPAR(sensor_port, frame16,sensor->i2c_addr, P_MT9X001_RMODE1, newreg); 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 if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to gains and sensor register shadows
return 0; return 0;
...@@ -1961,7 +1979,7 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port ...@@ -1961,7 +1979,7 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
///< @return 0 - OK, negative - error ///< @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 if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// send all parameters marked as "needed to be processed" to the sensor, clear those flags // send all parameters marked as "needed to be processed" to the sensor, clear those flags
// mask out all non sensor pars // mask out all non sensor pars
...@@ -1972,7 +1990,7 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port ...@@ -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)) & (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) ; 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; unsigned long mask;
int index,index32; int index,index32;
struct frameparspair_t pars_to_update[2*P_MULTI_NUMREGS*MAX_SENSORS]; /// 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 ...@@ -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 (GLOBALPARS(sensor_port, G_MULTI_NUM)==0) { // single sensor,don't bother with individual registers, do all old way.
if (bmask32) { if (bmask32) {
for (index32=(P_SENSOR_REGS>>5); bmask32; index32++, bmask32 >>= 1) { 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) { if (bmask32 & 1) {
mask=thispars->mod[index32]; 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) { for (index=(index32<<5); mask; index++, mask >>= 1) {
if (mask & 1) { if (mask & 1) {
X3X3_I2C_SEND2(sensor_port, frame16, sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]); 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; thispars->mod[index32]=0;
...@@ -2001,15 +2019,15 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port ...@@ -2001,15 +2019,15 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
///pass 1 - process modified broadcast parameters ///pass 1 - process modified broadcast parameters
if (bmask32) { if (bmask32) {
for (index32=(P_SENSOR_REGS>>5); bmask32; index32++, bmask32 >>= 1) { 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) { if (bmask32 & 1) {
mask=thispars->mod[index32]; 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) { for (index=(index32<<5); mask; index++, mask >>= 1) {
if (mask & 1) { if (mask & 1) {
// apply broadcast register write and schedule change the individual ones (if they are not modified) // 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]); 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; thispars->mod[index32]=0;
...@@ -2021,10 +2039,10 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port ...@@ -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 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) { if (bmask32) {
for (index32=(P_MULTI_REGS>>5); bmask32; index32++, bmask32 >>= 1) { 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) { if (bmask32 & 1) {
mask=thispars->mod[index32]; 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) { for (index=(index32<<5); mask && (index < ((P_MULTI_REGS) + ((MAX_SENSORS) * (P_MULTI_NUMREGS)))); index++, mask >>= 1) {
if (mask & 1) { if (mask & 1) {
if ((MULTIRVRSREG(sensor_port, index)) >0 ) { if ((MULTIRVRSREG(sensor_port, index)) >0 ) {
...@@ -2033,12 +2051,12 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port ...@@ -2033,12 +2051,12 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
sensor->i2c_addr + ((MULTIRVRSREG(sensor_port,index)>> 16) * I2C359_INC), sensor->i2c_addr + ((MULTIRVRSREG(sensor_port,index)>> 16) * I2C359_INC),
((MULTIRVRSREG(sensor_port,index) & 0xffff)-P_SENSOR_REGS), ((MULTIRVRSREG(sensor_port,index) & 0xffff)-P_SENSOR_REGS),
thispars->pars[index]); 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, sensor_port,
frame16, frame16,
sensor->i2c_addr+((MULTIRVRSREG(sensor_port,index)>> 16)*I2C359_INC), sensor->i2c_addr+((MULTIRVRSREG(sensor_port,index)>> 16)*I2C359_INC),
(int) ((MULTIRVRSREG(sensor_port,index) & 0xffff)-P_SENSOR_REGS), (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 ...@@ -194,6 +194,7 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
///< be applied to, negative - ASAP ///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error ///< @return 0 - OK, negative - error
; ;
void mt9x001_set_device(struct device *dev);
#if 0 #if 0
int adjustBinning_mt9x001(void); int adjustBinning_mt9x001(void);
int program_woi_mt9x001(int nonstop); int program_woi_mt9x001(int nonstop);
......
...@@ -92,6 +92,9 @@ ...@@ -92,6 +92,9 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/init.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 <linux/autoconf.h>
//#include <asm/system.h> //#include <asm/system.h>
...@@ -210,29 +213,29 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use ...@@ -210,29 +213,29 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
#ifdef NC353 // to hide old code #ifdef NC353 // to hide old code
#define MULTISENSOR_WRITE_I2C(sa,ra,v,sz) \ #define MULTISENSOR_WRITE_I2C(sa,ra,v,sz) \
{rslt |= 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) \ #define MULTISENSOR_WRITE_I2C16(ra,v) \
{rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(ra),(v),2) ; \ {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) \ #define MULTISENSOR_WRITE_I2C32(ra,v) \
{rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(I2C359_MSW),(v)>>16,2) ; \ {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) ; \ 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 #else
// using new access in immediate mode by class name // using new access in immediate mode by class name
#define MULTISENSOR_WRITE_I2C(port,name,offs,ra,v) \ #define MULTISENSOR_WRITE_I2C(port,name,offs,ra,v) \
{rslt |= 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) \ #define MULTISENSOR_WRITE_I2C16(port,ra,v) \
{rslt |= multisensor_write_i2c((port),(name_10359),0,(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) \ #define MULTISENSOR_WRITE_I2C32(port,ra,v) \
{rslt |= multisensor_write_i2c((port),(name_10359),0,(I2C359_MSW),(v)>>16) ; \ {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) ; \ 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 #endif
//pars_to_update - local variable //pars_to_update - local variable
...@@ -254,7 +257,7 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use ...@@ -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 ].num= P_M10359_REGS+(r) ;\
pars_to_update[nupdate++].val=(v);\ pars_to_update[nupdate++].val=(v);\
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (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_PAR32(p,f,r,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 ...@@ -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), (I2C359_MSW), (v)>>16); \
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v) & 0xffff); \ X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v) & 0xffff); \
local_irq_restore(flags); \ 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));\ 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);\
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)(r),(int)(v) & 0xffff);\
} }
#define SET_10359_PAR(p, f,r,v) \ #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 ...@@ -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 // same functions, but do not schedule updating parameter shadows, just send i2c
#define SET_10359_REG16(p, f,r,v) \ #define SET_10359_REG16(p, f,r,v) \
{ X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (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) \ #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 ...@@ -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), (I2C359_MSW), (v)>>16); \
X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v) & 0xffff); \ X3X3_I2C_SEND2((p), (f), (I2C359_SLAVEADDR), (r), (v) & 0xffff); \
local_irq_restore(flags); \ 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));\ 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);\
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)(r),(int)(v) & 0xffff);\
} }
#define SET_10359_REG(p,f,r,v) \ #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 ...@@ -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(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 #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(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); 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 ...@@ -345,7 +354,7 @@ int multisensor_pgm_window (int sensor_port, ///< sensor port
///< @return always 0 ///< @return always 0
{ {
int rslt; 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); rslt = multisensor_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
return rslt; return rslt;
...@@ -364,7 +373,7 @@ int multisensor_pgm_window_safe (int sensor_port, ///< sensor port ...@@ -364,7 +373,7 @@ int multisensor_pgm_window_safe (int sensor_port, ///< sensor port
///< @return always 0 ///< @return always 0
{ {
int rslt; 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); rslt = multisensor_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
return rslt; return rslt;
} }
...@@ -449,7 +458,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p ...@@ -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 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; 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 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) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame16);
int fpga_addr= frame16 <0; int fpga_addr= frame16 <0;
...@@ -490,7 +499,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p ...@@ -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 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 //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 // calculations valid for individual and composite frames
int styp = sensor->sensorType & 7; int styp = sensor->sensorType & 7;
dh= thispars->pars[P_DCM_HOR]; dh= thispars->pars[P_DCM_HOR];
...@@ -516,7 +525,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p ...@@ -516,7 +525,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
wt = thispars->pars[P_WOI_TOP]; wt = thispars->pars[P_WOI_TOP];
// flip margins for mirrored images (except oversized, not to rely on sensor->clearWidth/sensor->clearHeight // 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 memcpy(wois, &(thispars->pars[P_MULTI_WOI]), sizeof(wois)); // copy WOI parameters for 3 sensors
if (composite && flipY) { // reverse sequence if (composite && flipY) { // reverse sequence
...@@ -584,7 +593,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p ...@@ -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); 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 ...@@ -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 // 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 // modify - multiFlipX,multiFlipY applies to sensors, not frames ???? No, they apply to sub-frames
relFlipX= (multiFlipX ^ (multiFlipX>>1))& 3; relFlipX= (multiFlipX ^ (multiFlipX>>1))& 3;
relFlipY= (multiFlipY ^ (multiFlipY>>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 & 1) vblank2+=dv;
if (relFlipY & 2) vblank3+=((vblank3>=dv) && (vblank2>vblank3))?-dv:dv; // Keep the total height constant, if possible. If not possible - increase 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; 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 // Apply height1, height2, height3
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(0,sequence)]=height1; // always on,>= other frame heights 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))) { 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 ...@@ -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)+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)+1]=ww;
wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+2]=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] )); 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] );
MDF25(printk("wois[WIDTH1]=0x%lx\n", wois[(P_MULTI_WIDTH1-P_MULTI_WOI)+0] )); dev_dbg(g_dev_ptr,"%s wois[WIDTH1]=0x%lx\n",__func__, 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] )); 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] );
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[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 // 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 ...@@ -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 // 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; wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(0,sequence)]= wh;
sequence &= 3; // turn off frames 2, 3 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) } 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 height2=wh+wt-height1-vblank2; // only 10359, not the sensor
sequence &= 0xf; // turn off frame 3 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) } 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; 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 // zero out unused frames/blanks before them
...@@ -675,7 +684,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p ...@@ -675,7 +684,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
vblank3/=dv; vblank3/=dv;
height3/=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 // un-apply dh from ww - number of pixels to be read in a line in frames2,3
if (dh>1) ww/=dh; if (dh>1) ww/=dh;
w359=ww; w359=ww;
...@@ -686,7 +695,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p ...@@ -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) ((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 (flipX) multi_mode_flips ^= 0x15;
if (flipY) multi_mode_flips ^= 0x2a; 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); SETFRAMEPARS_COND(P_MULTI_MODE_FLIPS, multi_mode_flips);
// subtract (2 * COLOR_MARGINS) from the first and last frame // 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)) { ...@@ -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 // comparisons are only valid if there are no individual parameters that were changed
// program sensors width (same for all sensors, use broadcast mode) // 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))]; 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]) { 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); 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) // Program binning/decimation (also common but some older sensors)
if((styp == MT9T_TYP) || (styp == MT9P_TYP)) { // 3MPix and 5MPix 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) ; 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]) { if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RAM]) {
SET_SENSOR_PAR(sensor_port, fpga_addr,sensor->i2c_addr, P_MT9X001_RAM, v); 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); 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]) { if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_CAM]) {
SET_SENSOR_PAR(sensor_port, fpga_addr,sensor->i2c_addr, P_MT9X001_CAM, v); 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 } 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) 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)) { ...@@ -759,7 +768,7 @@ if (GLOBALPARS(sensor_port, G_MULTI_CFG) & (1 <<G_MULTI_CFG_BEFORE)) {
((dv == 8) ? (1 << 5) : 0) ; // Row skip 8 ((dv == 8) ? (1 << 5) : 0) ; // Row skip 8
if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1]) { if (v != thispars->pars[P_SENSOR_REGS+P_MT9X001_RMODE1]) {
SET_SENSOR_MBPAR(sensor_port,fpga_addr,sensor->i2c_addr, P_MT9X001_RMODE1, v); 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 // Other registers are programmed individually
...@@ -944,12 +953,12 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p ...@@ -944,12 +953,12 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
// .hact_delay = -2500, // -2.5ns delay in ps // .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) // .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 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 GLOBALPARS(sensor_port,G_SENS_AVAIL)=0; // no 10359A board present
if (frame16 >= 0) return -1; // can only work in ASAP mode 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) 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 #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; if (multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version, 4)<0) return -1;
#else #else
if (X3X3_I2C_RCV4(sensor_port, I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version)<0) return -1; 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 ...@@ -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. // Here we see that 10359A responds somehow. If next fails, no sense to try other sensor types.
multi_phases_initialized=0; multi_phases_initialized=0;
sensor->sensorType=SENSOR_NONE; sensor->sensorType=SENSOR_NONE;
add_sensor_proc(onchange_multisens, &multisensor_pgm_multisens); // process 10359-specific parameters add_sensor_proc(sensor_port,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_sensorphase, &multisensor_pgm_sensorphase); // set clock/phase for the 10359A
if ((((bitstream_version ^ I2C359_MINVERSION) & 0xffff0000)!=0) || ((bitstream_version & 0xffff) < (I2C359_MINVERSION & 0xffff))) { 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 ); 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 ...@@ -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 GLOBALPARS(sensor_port,G_SENS_AVAIL) |= 1<< (GLOBALPARS(sensor_port,G_SENS_AVAIL)); // temporary to indicate sensor detection functions that they need to initialize multisensor registers
for (i=0;i<MAX_SENSORS;i++) { for (i=0;i<MAX_SENSORS;i++) {
MDF24(printk("Probing sensor port %d, i2c bitdelays=0x%08x\n",i,i2c_delays(0)));
#ifdef NC353 #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, rslt= multisensor_read_i2c(sensor_port,
MT9P001_I2C_ADDR + ((i+1) * I2C359_INC), MT9P001_I2C_ADDR + ((i+1) * I2C359_INC),
P_MT9X001_CHIPVER, P_MT9X001_CHIPVER,
...@@ -1036,7 +1045,7 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p ...@@ -1036,7 +1045,7 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
P_MT9X001_CHIPVER, P_MT9X001_CHIPVER,
&sensor_id[i]); &sensor_id[i]);
#endif #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 (rslt==0) {
if (((sensor_id[i] ^ MT9P001_PARTID) & MT9X001_PARTIDMASK)==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]); 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 ...@@ -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 // 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 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++) { // 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 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) // 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 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 // Now calculate phases, swap ones from the sensor
long * multiOutDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_OUT); long * multiOutDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_OUT);
...@@ -1072,15 +1081,15 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p ...@@ -1072,15 +1081,15 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
sensor->hact_delay=0; // No hact delay on 10359 output sensor->hact_delay=0; // No hact delay on 10359 output
sensor->sensorDelay=multiOutDelay[0]; 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 //sensorproc_phys->sensor
/* /*
Now overwrite sensor functions with it's own (originals (physical sensor ones) are already copied to the local structure 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(sensor_port,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(sensor_port,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(sensor_port,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_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?) // Initialize other 10359A parameters (move it to init/afterinit?)
...@@ -1180,7 +1189,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n ...@@ -1180,7 +1189,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
int i,j,sh; int i,j,sh;
unsigned long wois[12]; unsigned long wois[12];
int dv= thispars->pars[P_DCM_VERT]; 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 // Handling sensor mask - which sensors (of the available) to use
int sensor_mask=(thispars->pars[P_MULTISENS_EN]) & GLOBALPARS(sensor_port, G_SENS_AVAIL); 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) 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 ...@@ -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) // 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 // 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 // No above is not really needed, sequence+enable can be handled by application software
MDF25(printk(" composite=0x%x\n",composite)); dev_dbg(g_dev_ptr,"%s composite=0x%x\n",__func__,composite);
MDF25(printk(" sequence=0x%x\n", sequence)); dev_dbg(g_dev_ptr,"%s sequence=0x%x\n",__func__, sequence);
// if sequence is zero, put "1-2-3" // if sequence is zero, put "1-2-3"
if (sequence==0) { if (sequence==0) {
j=1; j=1;
...@@ -1233,9 +1242,9 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n ...@@ -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 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])); 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]);
MDF25(printk(" sequence=0x%x\n", sequence)); dev_dbg(g_dev_ptr,"%s sequence=0x%x\n",__func__, sequence);
MDF25(printk(" sensor_mask=0x%x\n", sensor_mask)); dev_dbg(g_dev_ptr,"%s sensor_mask=0x%x\n",__func__, sensor_mask);
SETFRAMEPARS_COND(P_MULTI_SELECTED, selected); SETFRAMEPARS_COND(P_MULTI_SELECTED, selected);
SETFRAMEPARS_COND(P_MULTI_SEQUENCE, sequence); SETFRAMEPARS_COND(P_MULTI_SEQUENCE, sequence);
SETFRAMEPARS_COND(P_MULTISENS_EN, sensor_mask); SETFRAMEPARS_COND(P_MULTISENS_EN, sensor_mask);
...@@ -1245,14 +1254,14 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n ...@@ -1245,14 +1254,14 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
int old_sensor=prev_selected-1; // may be <0 int old_sensor=prev_selected-1; // may be <0
int new_sensor=selected-1; // >=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 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_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_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_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]; 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_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); 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 (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)) { 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 ...@@ -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_LEFT1- P_MULTI_WOI)+new_sensor]= 0;
wois[(P_MULTI_TOP1- P_MULTI_WOI)+new_sensor]= 0; wois[(P_MULTI_TOP1- P_MULTI_WOI)+new_sensor]= 0;
multi_fliph= (multi_fliph & (~(1<<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 multi_flipv= (multi_flipv & (~(1<<new_sensor))); // =0
} else { // was one single channel, now the different (not initialized window) one - copy window parameters } 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]; 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 ...@@ -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]; 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_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); 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 // saved sensor WOI are OK (or just fixed), use them
...@@ -1285,7 +1294,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n ...@@ -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_WOI_TOP, wois[(P_MULTI_TOP1- P_MULTI_WOI)+new_sensor] );
SETFRAMEPARS_COND(P_FLIPH, (multi_fliph>>new_sensor) & 1); SETFRAMEPARS_COND(P_FLIPH, (multi_fliph>>new_sensor) & 1);
SETFRAMEPARS_COND(P_FLIPV, (multi_flipv>>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) // Validate hights for all enabled channels (OK to skip disabled here)
int oversize=thispars->pars[P_OVERSIZE]; int oversize=thispars->pars[P_OVERSIZE];
...@@ -1301,30 +1310,30 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n ...@@ -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? 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; wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(0,sequence)]=height1;
total_height=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? // is there frame 2 enabled?
int multi_frame=0; int multi_frame=0;
if (composite && SENSOR_IN_SEQ_EN(1,sequence,sensor_mask)) { // specified in sequence is enabled if (composite && SENSOR_IN_SEQ_EN(1,sequence,sensor_mask)) { // specified in sequence is enabled
multi_frame=1; multi_frame=1;
total_height+=(vblank+(2 * COLOR_MARGINS))*dv; 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) height2=sensor->imageHeight;
if (height2 < sensor->minHeight) height2=sensor->minHeight; if (height2 < sensor->minHeight) height2=sensor->minHeight;
else if (height2 > sensor->arrayHeight) height2=sensor->arrayHeight; else if (height2 > sensor->arrayHeight) height2=sensor->arrayHeight;
else if ((!oversize) && (height2 > sensor->imageHeight)) height2=sensor->imageHeight; // use clearHeight here? 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; wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(1,sequence)]=height2;
total_height+=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)) { if (SENSOR_IN_SEQ_EN(2,sequence,sensor_mask)) {
total_height+=(vblank+(2 * COLOR_MARGINS))*dv; 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) height3=sensor->imageHeight;
if (height3 < sensor->minHeight) height3=sensor->minHeight; if (height3 < sensor->minHeight) height3=sensor->minHeight;
else if (height3 > sensor->arrayHeight) height3=sensor->arrayHeight; else if (height3 > sensor->arrayHeight) height3=sensor->arrayHeight;
else if ((!oversize) && (height2 > sensor->imageHeight)) height3=sensor->imageHeight; // use clearHeight here? 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; wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+SENSOR_IN_SEQ(2,sequence)]=height3;
total_height+=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) { if (composite) {
...@@ -1364,7 +1373,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n ...@@ -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_FLIPH, multi_fliph);
SETFRAMEPARS_COND(P_MULTI_FLIPV, multi_flipv); 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); SETFRAMEPARS_COND(P_SENSOR_HEIGHT, total_height);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes, schedule functions 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 ...@@ -1409,7 +1418,7 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
long * cableDelay; long * cableDelay;
long * FPGADelay; long * FPGADelay;
int clk_period; 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]; long sdram_chen=thispars->pars[P_M10359_REGS+I2C359_SDRAM_CHEN];
int adjustSDRAMNeed=0; int adjustSDRAMNeed=0;
int thisPhaseSDRAM=thispars->pars[P_MULTI_PHASE_SDRAM]; int thisPhaseSDRAM=thispars->pars[P_MULTI_PHASE_SDRAM];
...@@ -1433,17 +1442,17 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port ...@@ -1433,17 +1442,17 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C1); cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C1);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P1); FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P1);
thisPhase1=calcThisPhase(clk_period, FPGADelay[0], cableDelay[0], sensorproc_phys->sensor.sensorDelay) | 0x80000; 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); cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C2);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P2); FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P2);
thisPhase2=calcThisPhase(clk_period, FPGADelay[0], cableDelay[0], sensorproc_phys->sensor.sensorDelay) | 0x80000; 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); cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C3);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P3); FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P3);
thisPhase3=calcThisPhase(clk_period, FPGADelay[0], cableDelay[0], sensorproc_phys->sensor.sensorDelay) | 0x80000; 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. // TODO: calculate SDRAM phase here too.
adjustSDRAMNeed=1; adjustSDRAMNeed=1;
...@@ -1473,7 +1482,7 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port ...@@ -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]); 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 ((rslt>=0) && (rslt != thisPhaseSDRAM)) SETFRAMEPARS_SET(P_MULTI_PHASE_SDRAM, rslt);
if (resetThisDCM) { 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 multisensor_initSDRAM(sensor_port, thispars); // init 10359 SDRAM
} }
// Test memory phase here // Test memory phase here
...@@ -1644,7 +1653,7 @@ int multisensor_set_phase_recover(int sensor_port, ///< sensor port nu ...@@ -1644,7 +1653,7 @@ int multisensor_set_phase_recover(int sensor_port, ///< sensor port nu
else goodPhase = newPhase; else goodPhase = newPhase;
} }
rslt=goodPhase; 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; return rslt;
} }
...@@ -1675,7 +1684,7 @@ int multisensor_set_phase (int sensor_port, ///< sensor port number (0 ...@@ -1675,7 +1684,7 @@ int multisensor_set_phase (int sensor_port, ///< sensor port number (0
oldPhase=0; oldPhase=0;
} }
if (newPhase!=oldPhase) { 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_phase= oldPhase & 0xffff; if (old_phase>=0x8000) old_phase-=0x10000; // make it signed
old_phase90= (oldPhase >> 16) & 3; old_phase90= (oldPhase >> 16) & 3;
if ((old_phase > 255) || (old_phase < -255)) { if ((old_phase > 255) || (old_phase < -255)) {
...@@ -1691,9 +1700,9 @@ int multisensor_set_phase (int sensor_port, ///< sensor port number (0 ...@@ -1691,9 +1700,9 @@ int multisensor_set_phase (int sensor_port, ///< sensor port number (0
diff_phase90=phase90-old_phase90; diff_phase90=phase90-old_phase90;
if (diff_phase90>2) diff_phase90-=4; if (diff_phase90>2) diff_phase90-=4;
else if (diff_phase90<-1)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 )); dev_dbg(g_dev_ptr,"%s old_phase= 0x%x old_phase90= 0x%x\r\n",__func__, old_phase, old_phase90 );
MDF16(printk("phase= 0x%x phase90= 0x%x\r\n", phase, phase90 )); dev_dbg(g_dev_ptr,"%s phase= 0x%x phase90= 0x%x\r\n",__func__, phase, phase90 );
MDF16(printk("diff_phase=0x%x diff_phase90=0x%x\r\n", diff_phase, diff_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 ) 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 ) 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 ) 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 ...@@ -2030,28 +2039,28 @@ int multisensor_pgm_sensorregs (int sensor_port, ///< sensor port
///< @return always 0 ///< @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 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) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame16);
int fpga_addr=frame16; int fpga_addr=frame16;
// do whatever is needed for 10359 registers, then call sesnor function (if available) // 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); // 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) //#define SET_10359_REG(f,r,v)
// send all parameters marked as "needed to be processed" to the sensor, clear those flags // send all parameters marked as "needed to be processed" to the sensor, clear those flags
// mask out all non sensor pars // mask out all non sensor pars
// It will be the first for the frame (before automatic sensor changes). // 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) // 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) ; 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; unsigned long mask;
int index,index32; int index,index32;
if (bmask32) { if (bmask32) {
for (index32=(P_M10359_REGS>>5); bmask32; index32++, bmask32 >>= 1) { 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) { if (bmask32 & 1) {
mask=thispars->mod[index32]; 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) { for (index=(index32<<5); mask; index++, mask >>= 1) {
if (mask & 1) { if (mask & 1) {
SET_10359_REG (sensor_port, fpga_addr, (index-P_M10359_REGS), thispars->pars[index]); SET_10359_REG (sensor_port, fpga_addr, (index-P_M10359_REGS), thispars->pars[index]);
......
...@@ -129,7 +129,7 @@ each dibit: ...@@ -129,7 +129,7 @@ each dibit:
//#define I2C359_CLK_NUMBER 4 // system clock number for the 10359A on-board clock generator //#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 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); //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 @@ ...@@ -25,8 +25,9 @@
#define X393_MAXHEIGHT 65536 // 16384 // multiple of 16 - unsafe - not enough room for black level subtraction #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 #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); void pgm_functions_set_device(struct device *dev);
int add_sensor_proc(int index, int (*sens_func)(int sensor_port, struct sensor_t * , struct framepars_t * , struct framepars_t *, int )); 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 /// Commands through sequencer: switch between ASAP (frame <0) and absolute
/// @param port - sensor port (0..3) /// @param port - sensor port (0..3)
......
...@@ -180,7 +180,7 @@ int get_cache_index(unsigned int chn) ...@@ -180,7 +180,7 @@ int get_cache_index(unsigned int chn)
void reset_qtables(unsigned int chn) void reset_qtables(unsigned int chn)
{ {
int ind = get_cache_index(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; qtables_set[ind].qtable_fpga_initialized = 0;
} }
......
...@@ -58,6 +58,9 @@ ...@@ -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.*/ /** @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) #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*/ /** @brief Contains read and write pointers along with IRQ number for a single channel*/
struct jpeg_ptr_t { struct jpeg_ptr_t {
volatile u32 frame; ///< Absolute frame number volatile u32 frame; ///< Absolute frame number
...@@ -87,6 +90,8 @@ struct image_acq_pd_t { ...@@ -87,6 +90,8 @@ struct image_acq_pd_t {
int minor; ///< Driver minor number int minor; ///< Driver minor number
struct jpeg_ptr_t jpeg_ptr[SENSOR_PORTS]; ///< Array of read/write pointers struct jpeg_ptr_t jpeg_ptr[SENSOR_PORTS]; ///< Array of read/write pointers
}; };
/* debug code follows */ /* debug code follows */
long long zero_counter[SENSOR_PORTS] = {0}; long long zero_counter[SENSOR_PORTS] = {0};
long long corrected_offset[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) ...@@ -114,6 +119,12 @@ long long get_frame_pos(unsigned int chn, unsigned int pos)
static struct image_acq_pd_t image_acq_priv; 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_wp;
//static volatile int JPEG_rp; //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) //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) ...@@ -253,7 +264,7 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
void *virt_addr; void *virt_addr;
// int prev_dword; // int prev_dword;
int xferred; // number of 32-byte chunks transferred since compressor was reset 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); x393_afimux_status_t stat = x393_afimux0_status(jptr->chn_num);
int frame16; int frame16;
u32 aframe = GLOBALPARS(jptr->chn_num,G_THIS_FRAME); // thisFrameNumber(jptr->chn_num); // current absolute frame number 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) ...@@ -266,14 +277,17 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
jptr->fpga_cntr_prev = jptr->jpeg_wp; jptr->fpga_cntr_prev = jptr->jpeg_wp;
jptr->jpeg_wp = (stat.offset256 << 3); jptr->jpeg_wp = (stat.offset256 << 3);
// Find absolute frame number just compressed // Find absolute frame number just compressed WRONG, should use comressor frame number
cmdseqmux_status = x393_cmdseqmux_status(); // CMDSEQMUX status data (frame numbers and interrupts // 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){ switch (jptr->chn_num){
case 0: frame16 =cmdseqmux_status.frame_num0; break; case 0: frame16 =cmdseqmux_status.frame_num0; break;
case 1: frame16 =cmdseqmux_status.frame_num1; break; case 1: frame16 =cmdseqmux_status.frame_num1; break;
case 2: frame16 =cmdseqmux_status.frame_num2; break; case 2: frame16 =cmdseqmux_status.frame_num2; break;
default: frame16 =cmdseqmux_status.frame_num3; default: frame16 =cmdseqmux_status.frame_num3;
} }
#endif
if (frame16 > (aframe & PARS_FRAMES_MASK)) if (frame16 > (aframe & PARS_FRAMES_MASK))
aframe += 16; aframe += 16;
jptr->frame = (aframe & ~PARS_FRAMES_MASK) | frame16; // This is absolute compressed frame number, may lag behind current one 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) ...@@ -318,18 +332,18 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
// // prevent compiler from reordering operations. // // prevent compiler from reordering operations.
// phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr; // phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr;
// virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr; // 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)); // outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1));
// __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE); // __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE);
// phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr + CCAM_DMA_SIZE - 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); // 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)); // outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1));
// __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE); // __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(); // barrier();
// prev_dword = X393_BUFFSUB(DW2BYTE(jptr->jpeg_wp), 4); // 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(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(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[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[jptr->jpeg_wp] == 0x00 &&
// if ((circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)] & MARKER_FF) == MARKER_FF) { // if ((circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)] & MARKER_FF) == MARKER_FF) {
//// jptr->jpeg_wp += INTERFRAME_PARAMS_SZ; //// jptr->jpeg_wp += INTERFRAME_PARAMS_SZ;
...@@ -431,6 +445,31 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr) ...@@ -431,6 +445,31 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr)
return interframe; 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 /** 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 ...@@ -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) static irqreturn_t frame_sync_irq_handler(int irq, void *dev_id)
{ {
struct jpeg_ptr_t *jptr = dev_id; struct jpeg_ptr_t *jptr = dev_id;
x393_cmdframeseq_mode_t cmdframeseq_mode = {.d32 = 0};
// update_frame_pars(); 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]); wake_up_interruptible(&aframepars_wait_queue[jptr->chn_num]);
// tasklet_schedule(&tasklet_fpga); // tasklet_schedule(&tasklet_fpga);
tasklet_schedule(tasklets[jptr->chn_num]); tasklet_schedule(tasklets[jptr->chn_num]);
x393_cmdframeseq_ctrl(cmdframeseq_mode, jptr->chn_num);
local_irq_restore(flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -589,23 +636,28 @@ static irqreturn_t compressor_irq_handler(int irq, void *dev_id) ...@@ -589,23 +636,28 @@ static irqreturn_t compressor_irq_handler(int irq, void *dev_id)
struct jpeg_ptr_t *jptr = dev_id; struct jpeg_ptr_t *jptr = dev_id;
struct interframe_params_t *interframe = NULL; struct interframe_params_t *interframe = NULL;
x393_cmprs_interrupts_t irq_ctrl; 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)) { if (updateIRQJPEG_wp(jptr)) {
update_irq_circbuf(jptr); update_irq_circbuf(jptr);
updateIRQFocus(jptr); updateIRQFocus(jptr);
interframe = updateIRQ_interframe(jptr); interframe = updateIRQ_interframe(jptr);
updateIRQ_Exif(jptr, interframe); 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(&circbuf_wait_queue);
} }
//wake_up_interruptible(&framepars_wait_queue); //wake_up_interruptible(&framepars_wait_queue);
// tasklet_schedule(&tasklet_fpga); // tasklet_schedule(&tasklet_fpga);
tasklet_schedule(tasklets[jptr->chn_num]); tasklet_schedule(tasklets[jptr->chn_num]);
irq_ctrl.interrupt_cmd = IRQ_CLEAR; irq_ctrl.interrupt_cmd = IRQ_CLEAR;
x393_cmprs_interrupts(irq_ctrl, jptr->chn_num); x393_cmprs_interrupts(irq_ctrl, jptr->chn_num);
local_irq_restore(flag); local_irq_restore(flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -636,9 +688,9 @@ For displaying histograms - try use latest available - not waiting fro a particu ...@@ -636,9 +688,9 @@ For displaying histograms - try use latest available - not waiting fro a particu
//#define HISTOGRAMS_WAKEUP_ALWAYS 0 //#define HISTOGRAMS_WAKEUP_ALWAYS 0
void tasklet_fpga_function(unsigned long arg) 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 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); int tasklet_disable=get_globalParam(sensor_port, G_TASKLET_CTL);
unsigned long thisFrameNumber=getThisFrameNumber(sensor_port); unsigned long thisFrameNumber=getThisFrameNumber(sensor_port);
unsigned long prevFrameNumber=thisFrameNumber-1; unsigned long prevFrameNumber=thisFrameNumber-1;
...@@ -671,7 +723,10 @@ void tasklet_fpga_function(unsigned long arg) ...@@ -671,7 +723,10 @@ void tasklet_fpga_function(unsigned long arg)
} }
// Time is out? // 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) // Histograms are available for the previous frame (that is already in circbuf if compressor was running)
// Is Y histogram needed? // Is Y histogram needed?
PROFILE_NOW(2); PROFILE_NOW(2);
...@@ -697,6 +752,7 @@ void tasklet_fpga_function(unsigned long arg) ...@@ -697,6 +752,7 @@ void tasklet_fpga_function(unsigned long arg)
} }
//#ifdef TEST_DISABLE_CODE //#ifdef TEST_DISABLE_CODE
if (hist_en) { 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){ for (subchn=0;subchn<MAX_SENSORS;subchn++) if (((hist_indx=get_hist_index(sensor_port,subchn)))>=0){
if (PER_CHANNEL393) { if (PER_CHANNEL393) {
...@@ -714,7 +770,12 @@ void tasklet_fpga_function(unsigned long arg) ...@@ -714,7 +770,12 @@ void tasklet_fpga_function(unsigned long arg)
PROFILE_NOW(3); PROFILE_NOW(3);
// Time is out? // Time is out?
// Old 353 if ((getThisFrameNumber(sensor_port) ^ X3X3_I2C_FRAME) & PARS_FRAMES_MASK) return; // already next frame // 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 #if HISTOGRAMS_WAKEUP_ALWAYS
} }
wake_up_interruptible(&hist_y_wait_queue); // wait queue for the G1 histogram (used as Y) 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) ...@@ -724,11 +785,14 @@ void tasklet_fpga_function(unsigned long arg)
#endif #endif
// Process parameters // Process parameters
if ((tasklet_disable & (1 << TASKLET_CTL_PGM)) == 0) { if ((tasklet_disable & (1 << TASKLET_CTL_PGM)) == 0) {
processPars (sensor_port, sensorproc, getThisFrameNumber(sensor_port), get_globalParam(sensor_port, G_MAXAHEAD)); // program parameters processPars (sensor_port, &asensorproc[sensor_port], getThisFrameNumber(sensor_port), get_globalParam(sensor_port, G_MAXAHEAD)); // program parameters
PROFILE_NOW(4); PROFILE_NOW(3); // was 5 in NC353
} }
// Time is out? // 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? // Are C histograms needed?
switch ((tasklet_disable >> TASKLET_CTL_HISTC_BIT) & 7) { switch ((tasklet_disable >> TASKLET_CTL_HISTC_BIT) & 7) {
case TASKLET_HIST_NEVER: // never calculate case TASKLET_HIST_NEVER: // never calculate
...@@ -751,6 +815,7 @@ void tasklet_fpga_function(unsigned long arg) ...@@ -751,6 +815,7 @@ void tasklet_fpga_function(unsigned long arg)
hist_en=1; hist_en=1;
} }
if (hist_en) { 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]
// 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){ 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) ...@@ -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 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? // 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 #if HISTOGRAMS_WAKEUP_ALWAYS
} }
wake_up_interruptible(&hist_c_wait_queue); // wait queue for all the other (R,G2,B) histograms (color) 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) ...@@ -806,11 +874,11 @@ void reset_compressor(unsigned int chn)
void compressor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt enable void compressor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt enable
int chn) ///< compressor channel (0..3) int chn) ///< compressor channel (0..3)
{ {
int i; // int i;
x393_cmprs_interrupts_t irq_ctrl = {.d32=0}; x393_cmprs_interrupts_t irq_ctrl = {.d32=0};
//MDF2(printk ("compressor_interrupts(%d)\n",on)); //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 #ifdef TEST_DISABLE_CODE
if (on) { if (on) {
EN_INTERRUPT(SMART); EN_INTERRUPT(SMART);
...@@ -835,11 +903,11 @@ void compressor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt e ...@@ -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 void sensor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt enable
int chn) ///< compressor channel (0..3) int chn) ///< compressor channel (0..3)
{ {
int i; // int i;
x393_cmdframeseq_mode_t cmdframeseq_mode = {.d32=0}; x393_cmdframeseq_mode_t cmdframeseq_mode = {.d32=0};
//MDF2(printk ("compressor_interrupts(%d)\n",on)); //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 #ifdef TEST_DISABLE_CODE
if (on) { if (on) {
EN_INTERRUPT(SMART); EN_INTERRUPT(SMART);
...@@ -910,11 +978,13 @@ int image_acq_init(struct platform_device *pdev) ...@@ -910,11 +978,13 @@ int image_acq_init(struct platform_device *pdev)
if (!match) if (!match)
return -EINVAL;*/ return -EINVAL;*/
asensorproc= &as_sensorproc[0]; // asensorproc= &as_sensorproc[0];
asensorproc= as_sensorproc;
//MDD1(printk("sensorproc=0x%x\n",(int) 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++) { 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]); irq = platform_get_irq_byname(pdev, frame_sync_irq_names[i]);
if (request_irq(irq, if (request_irq(irq,
frame_sync_irq_handler, frame_sync_irq_handler,
...@@ -925,7 +995,9 @@ int image_acq_init(struct platform_device *pdev) ...@@ -925,7 +995,9 @@ int image_acq_init(struct platform_device *pdev)
return -EBUSY; return -EBUSY;
} }
image_acq_priv.jpeg_ptr[i].irq_num_sens = irq; image_acq_priv.jpeg_ptr[i].irq_num_sens = irq;
irq = platform_get_irq_byname(pdev, compressor_irq_names[i]); 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, if (request_irq(irq,
compressor_irq_handler, compressor_irq_handler,
0, // no flags 0, // no flags
...@@ -936,6 +1008,8 @@ int image_acq_init(struct platform_device *pdev) ...@@ -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].irq_num_comp = irq;
image_acq_priv.jpeg_ptr[i].chn_num = i; 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) { if (init_mmio_ptr() < 0) {
...@@ -961,16 +1035,18 @@ int image_acq_init(struct platform_device *pdev) ...@@ -961,16 +1035,18 @@ int image_acq_init(struct platform_device *pdev)
dev_dbg(dev, "reset all compressors\n"); dev_dbg(dev, "reset all compressors\n");
for (i = 0; i < SENSOR_PORTS; i++) { for (i = 0; i < SENSOR_PORTS; i++) {
reset_compressor(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 //reset_compressor(); // reset compressor and buffer pointers
//MDD1(printk("x313_dma_init()\n")); //MDD1(printk("x313_dma_init()\n"));
//x313_dma_init(); // initialize ETRAX FS DMA //x313_dma_init(); // initialize ETRAX FS DMA
//MDD1(printk("init_pgm_proc ()\n")); dev_info(dev, "reset_qtables(0) (policy = COMMON_CACHE)\n");
//init_pgm_proc (); // setup pointers to functions (not sensor-specific) set_cache_policy(COMMON_CACHE);
//MDD1(printk("reset_qtables()\n")); 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); // framepars_init(pdev);
pgm_functions_set_device(dev);
g_dev_ptr = dev;
return 0; return 0;
} }
...@@ -991,7 +1067,7 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use ...@@ -991,7 +1067,7 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
BUG_ON(!class_10359); BUG_ON(!class_10359);
class_sensor= xi2c_dev_get(name_sensor); class_sensor= xi2c_dev_get(name_sensor);
BUG_ON(!class_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)) { for (sensor_port=1; sensor_port< SENSOR_PORTS; sensor_port++) if (ports & (1 << sensor_port)) {
i2c_page_register(sensor_port, class_10359->slave7); i2c_page_register(sensor_port, class_10359->slave7);
set_xi2c_wrc(class_10359, sensor_port, class_10359->slave7, 0); 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 ...@@ -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); 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 // 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); set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE2);
dev_sensor.data_bytes=4; // for reading 10359 in 32-bit mode dev_sensor.data_bytes=4; // for reading 10359 in 32-bit mode
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4); set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4);
} }
return 0; 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 @@ ...@@ -6,7 +6,9 @@
#define _SENSOR_COMMON_H #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 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, /// 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 /// 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 #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; ...@@ -24,6 +26,8 @@ extern struct sensorproc_t * sensorproc;
//int camSeqGetJPEG_wp(void); //int camSeqGetJPEG_wp(void);
//int camSeqGetJPEG_rp(void); //int camSeqGetJPEG_rp(void);
//void camSeqSetJPEG_rp(int p); //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_wp(unsigned int chn);
int camseq_get_jpeg_rp(unsigned int chn); int camseq_get_jpeg_rp(unsigned int chn);
void camseq_set_jpeg_rp(unsigned int chn, int ptr); void camseq_set_jpeg_rp(unsigned int chn, int ptr);
......
...@@ -139,10 +139,10 @@ int i2c_page_alloc(int chn) ...@@ -139,10 +139,10 @@ int i2c_page_alloc(int chn)
{ {
int g, b; int g, b;
u32 * fb; u32 * fb;
spin_lock(&lock); spin_lock_bh(&lock);
g = __builtin_clz(free_i2c_groups[chn]); g = __builtin_clz(free_i2c_groups[chn]);
if (unlikely(g > 7)) { if (unlikely(g > 7)) {
spin_unlock(&lock); spin_unlock_bh(&lock);
return -ENOMEM; // no free i2c pages left return -ENOMEM; // no free i2c pages left
} }
fb = free_i2c_pages + ((chn << 3) + g); fb = free_i2c_pages + ((chn << 3) + g);
...@@ -151,7 +151,7 @@ int i2c_page_alloc(int chn) ...@@ -151,7 +151,7 @@ int i2c_page_alloc(int chn)
if (unlikely(*fb == 0)){ if (unlikely(*fb == 0)){
free_i2c_groups[chn] &= ~(1 << (31 - g)); free_i2c_groups[chn] &= ~(1 << (31 - g));
} }
spin_unlock(&lock); spin_unlock_bh(&lock);
return (g << 5) + b; return (g << 5) + b;
} }
EXPORT_SYMBOL_GPL(i2c_page_alloc); EXPORT_SYMBOL_GPL(i2c_page_alloc);
...@@ -165,16 +165,16 @@ int i2c_page_register(int chn, ///< Sensor port ...@@ -165,16 +165,16 @@ int i2c_page_register(int chn, ///< Sensor port
int g = page >> 5; int g = page >> 5;
int b = page & 0x1f; int b = page & 0x1f;
u32 * fb = free_i2c_pages + ((chn << 3) + g); u32 * fb = free_i2c_pages + ((chn << 3) + g);
spin_lock(&lock); spin_lock_bh(&lock);
if (unlikely(!(*fb & (1 << (31-b))))) { if (unlikely(!(*fb & (1 << (31-b))))) {
spin_unlock(&lock); spin_unlock_bh(&lock);
return -ENOMEM; // page is already registered return -ENOMEM; // page is already registered
} }
*fb &= (1 << (31-b)); *fb &= (1 << (31-b));
if (unlikely(*fb == 0)){ if (unlikely(*fb == 0)){
free_i2c_groups[chn] &= ~(1 << (31 - g)); free_i2c_groups[chn] &= ~(1 << (31 - g));
} }
spin_unlock(&lock); spin_unlock_bh(&lock);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(i2c_page_register); EXPORT_SYMBOL_GPL(i2c_page_register);
...@@ -190,10 +190,10 @@ void i2c_page_free(int chn, int page) ...@@ -190,10 +190,10 @@ void i2c_page_free(int chn, int page)
int g = page >> 5; int g = page >> 5;
int b = page & 0x1f; int b = page & 0x1f;
u32 * fb = free_i2c_pages + ((chn << 3) + g); u32 * fb = free_i2c_pages + ((chn << 3) + g);
spin_lock(&lock); spin_lock_bh(&lock);
free_i2c_groups[chn] |= 1 << (31 - g); free_i2c_groups[chn] |= 1 << (31 - g);
*fb |= 1 << (31-b); *fb |= 1 << (31-b);
spin_unlock(&lock); spin_unlock_bh(&lock);
} }
EXPORT_SYMBOL_GPL(i2c_page_free); EXPORT_SYMBOL_GPL(i2c_page_free);
...@@ -222,10 +222,10 @@ void set_xi2c_raw(int chn, ///< Sensor port number ...@@ -222,10 +222,10 @@ void set_xi2c_raw(int chn, ///< Sensor port number
tb_data.d32 = data; tb_data.d32 = data;
tb_data.tbl_mode = 2; // tb_data.tbl_mode = 2; //
/* Table address and data should not interleave with others */ /* 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_addr, chn);
x393_sensi2c_ctrl (tb_data, chn); x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock); spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] =tb_data.d32; i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
} }
EXPORT_SYMBOL_GPL(set_xi2c_raw); EXPORT_SYMBOL_GPL(set_xi2c_raw);
...@@ -251,10 +251,10 @@ void set_xi2c_wrc( x393_i2c_device_t * dc, ///< device class ...@@ -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.dly = get_bit_delay(dc -> scl_khz);
tb_data.tbl_mode = 2; tb_data.tbl_mode = 2;
/* Table address and data should not interleave with others */ /* 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_addr, chn);
x393_sensi2c_ctrl (tb_data, chn); x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock); spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] =tb_data.d32; i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
} }
EXPORT_SYMBOL_GPL(set_xi2c_wrc); EXPORT_SYMBOL_GPL(set_xi2c_wrc);
...@@ -279,10 +279,10 @@ void set_xi2c_rdc(x393_i2c_device_t * dc, ///< device class ...@@ -279,10 +279,10 @@ void set_xi2c_rdc(x393_i2c_device_t * dc, ///< device class
tb_data.tbl_mode = 2; tb_data.tbl_mode = 2;
/* Table address and data should not interleave with others */ /* 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); 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_addr, chn);
x393_sensi2c_ctrl (tb_data, chn); x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock); spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] = tb_data.d32; i2c_pages_shadow[(chn << 8) + page] = tb_data.d32;
} }
EXPORT_SYMBOL_GPL(set_xi2c_rdc); EXPORT_SYMBOL_GPL(set_xi2c_rdc);
...@@ -308,10 +308,10 @@ void set_xi2c_wr(int chn, ///< sensor port ...@@ -308,10 +308,10 @@ void set_xi2c_wr(int chn, ///< sensor port
tb_data.dly = bit_delay; tb_data.dly = bit_delay;
tb_data.tbl_mode = 2; tb_data.tbl_mode = 2;
/* Table address and data should not interleave with others */ /* 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_addr, chn);
x393_sensi2c_ctrl (tb_data, chn); x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock); spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] =tb_data.d32; i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
} }
EXPORT_SYMBOL_GPL(set_xi2c_wr); EXPORT_SYMBOL_GPL(set_xi2c_wr);
...@@ -335,10 +335,10 @@ void set_xi2c_rd(int chn, ///< sensor port ...@@ -335,10 +335,10 @@ void set_xi2c_rd(int chn, ///< sensor port
tb_data.dly = bit_delay; tb_data.dly = bit_delay;
tb_data.tbl_mode = 2; tb_data.tbl_mode = 2;
/* Table address and data should not interleave with others */ /* 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_addr, chn);
x393_sensi2c_ctrl (tb_data, chn); x393_sensi2c_ctrl (tb_data, chn);
spin_unlock(&lock); spin_unlock_bh(&lock);
i2c_pages_shadow[(chn << 8) + page] =tb_data.d32; i2c_pages_shadow[(chn << 8) + page] =tb_data.d32;
} }
EXPORT_SYMBOL_GPL(set_xi2c_rd); EXPORT_SYMBOL_GPL(set_xi2c_rd);
...@@ -375,14 +375,14 @@ int write_xi2c_rel (int chn, ///< sensor port ...@@ -375,14 +375,14 @@ int write_xi2c_rel (int chn, ///< sensor port
if (tb_data.tbl_mode !=2) return -EBADR; 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 len = (tb_data.rnw )? 1:((tb_data.nbwr + 5) >> 2); // read mode - always 1 DWORD, write - 1..3
if (len > 1) { if (len > 1) {
spin_lock(&lock); spin_lock_bh(&lock);
for (i = 0; i <len; i++){ for (i = 0; i <len; i++){
x393_sensi2c_rel (data[i], chn, offs); x393_sensi2c_rel (data[i], chn, offs);
} }
} else { } else {
x393_sensi2c_rel (data[0], chn, offs); x393_sensi2c_rel (data[0], chn, offs);
} }
spin_unlock(&lock); spin_unlock_bh(&lock);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(write_xi2c_rel); EXPORT_SYMBOL_GPL(write_xi2c_rel);
...@@ -404,14 +404,14 @@ int write_xi2c_abs (int chn, ///< sensor port ...@@ -404,14 +404,14 @@ int write_xi2c_abs (int chn, ///< sensor port
if (tb_data.tbl_mode !=2) return -EBADR; 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 len = (tb_data.rnw )? 1:((tb_data.nbwr + 5) >> 2); // read mode - always 1 DWORD, write - 1..3
if (len > 1) { if (len > 1) {
spin_lock(&lock); spin_lock_bh(&lock);
for (i = 0; i <len; i++){ for (i = 0; i <len; i++){
x393_sensi2c_abs (data[i], chn, offs); x393_sensi2c_abs (data[i], chn, offs);
} }
} else { } else {
x393_sensi2c_abs (data[0], chn, offs); x393_sensi2c_abs (data[0], chn, offs);
} }
spin_unlock(&lock); spin_unlock_bh(&lock);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(write_xi2c_abs); EXPORT_SYMBOL_GPL(write_xi2c_abs);
...@@ -493,6 +493,30 @@ void read_xi2c_sa7 (int chn, ///< sensor port ...@@ -493,6 +493,30 @@ void read_xi2c_sa7 (int chn, ///< sensor port
} }
EXPORT_SYMBOL_GPL(read_xi2c_sa7); 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. /** 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 */ * 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 ...@@ -504,6 +528,7 @@ int read_xi2c_fifo(int chn) ///< sensor port
x393_status_sens_i2c_t status; x393_status_sens_i2c_t status;
x393_status_ctrl_t status_ctrl = get_x393_sensi2c_status_ctrl(chn); /* last written data to status_cntrl */ x393_status_ctrl_t status_ctrl = get_x393_sensi2c_status_ctrl(chn); /* last written data to status_cntrl */
if (status_ctrl.mode != 3){ if (status_ctrl.mode != 3){
spin_lock_bh(&lock);
status = x393_sensi2c_status (chn); status = x393_sensi2c_status (chn);
status_ctrl.mode = 3; status_ctrl.mode = 3;
status_ctrl.seq_num = status.seq_num ^ 0x20; status_ctrl.seq_num = status.seq_num ^ 0x20;
...@@ -512,6 +537,7 @@ int read_xi2c_fifo(int chn) ///< sensor port ...@@ -512,6 +537,7 @@ int read_xi2c_fifo(int chn) ///< sensor port
status = x393_sensi2c_status(chn); status = x393_sensi2c_status(chn);
if (likely(status.seq_num = status_ctrl.seq_num)) break; 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); 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); status = x393_sensi2c_status (chn);
...@@ -1194,10 +1220,52 @@ static ssize_t get_i2c_help(struct device *dev, ///< Linux kernel b ...@@ -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" "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" "[<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*: 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 // Sysfs top
/* alloc*: read - allocate and return page, write (any data) - free page */ /* alloc*: read - allocate and return page, write (any data) - free page */
static DEVICE_ATTR(i2c_all , SYSFS_PERMISSIONS , i2c_class_show , i2c_class_store); 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 ...@@ -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(i2c1 , SYSFS_PERMISSIONS , i2c_show, i2c_store);
static DEVICE_ATTR(i2c2 , 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(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); 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 */ /** 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[] = { ...@@ -1255,6 +1327,10 @@ static struct attribute *root_dev_attrs[] = {
&dev_attr_i2c1.attr, &dev_attr_i2c1.attr,
&dev_attr_i2c2.attr, &dev_attr_i2c2.attr,
&dev_attr_i2c3.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, &dev_attr_help.attr,
NULL NULL
}; };
......
...@@ -37,6 +37,7 @@ typedef struct{ ...@@ -37,6 +37,7 @@ typedef struct{
int i2c_stop_run_reset(int chn, int cmd); int i2c_stop_run_reset(int chn, int cmd);
int i2c_drive_mode (int chn, int sda_drive_high, int sda_release); 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_alloc (int chn);
int i2c_page_register(int chn, int page); int i2c_page_register(int chn, int page);
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <uapi/elphel/c313a.h> // PARS_FRAMES_MASK #include <uapi/elphel/c313a.h> // PARS_FRAMES_MASK
#include "x393.h" #include "x393.h"
...@@ -24,6 +27,7 @@ ...@@ -24,6 +27,7 @@
#define REPEAT_STATUS_READ 10 ///< Number of times status is re-read waiting for a new timestamp #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); static DEFINE_SPINLOCK(fpga_time_lock);
// Nothing to init? Started in pgm_detectsesnor through sensor_common:sequencer_stop_run_reset // 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 ...@@ -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; // x393_rtc_sec_t sec;
int i; int i;
if (!ts) return NULL; if (!ts) return NULL;
spin_lock(&fpga_time_lock); spin_lock_bh(&fpga_time_lock);
stat = x393_rtc_status(); stat = x393_rtc_status();
stat_ctrl.mode = 1; stat_ctrl.mode = 1;
stat_ctrl.seq_num = stat.seq_num + 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 ...@@ -57,7 +61,7 @@ sec_usec_t * get_fpga_rtc(sec_usec_t * ts) ///< Pointer to a sec/usec structure
break; break;
} }
} }
spin_unlock(&fpga_time_lock); spin_unlock_bh(&fpga_time_lock);
return ts; return ts;
} }
...@@ -68,8 +72,18 @@ void set_fpga_rtc (sec_usec_t ts) ///< timestamp providing seconds and microseco ...@@ -68,8 +72,18 @@ void set_fpga_rtc (sec_usec_t ts) ///< timestamp providing seconds and microseco
x393_rtc_sec_t sec; x393_rtc_sec_t sec;
usec.usec = ts.usec; usec.usec = ts.usec;
sec.sec = ts.sec; sec.sec = ts.sec;
spin_lock(&fpga_time_lock); spin_lock_bh(&fpga_time_lock);
set_x393_rtc_usec(usec); set_x393_rtc_usec(usec);
set_x393_rtc_sec_set(sec); // And apply 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 @@ ...@@ -19,4 +19,5 @@
//void fpga_table_write_nice (int addr, int len, unsigned long * data); //void fpga_table_write_nice (int addr, int len, unsigned long * data);
sec_usec_t * get_fpga_rtc(sec_usec_t * ts); sec_usec_t * get_fpga_rtc(sec_usec_t * ts);
void set_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 ...@@ -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) 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)]);
sscanf(buf, "%i", &buffer_settings.frame_start[get_channel_from_name(attr)], &len);
return count; return count;
} }
static ssize_t store_full_width(struct device *dev, struct device_attribute *attr, const char *buf, size_t 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)]);
sscanf(buf, "%i", &buffer_settings.frame_full_width[get_channel_from_name(attr)], &len);
return count; return count;
} }
static ssize_t store_frame_height(struct device *dev, struct device_attribute *attr, const char *buf, size_t 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)]);
sscanf(buf, "%i", &buffer_settings.frame_height[get_channel_from_name(attr)], &len);
return count; return count;
} }
static ssize_t store_frames_in_buffer(struct device *dev, struct device_attribute *attr, const char *buf, size_t 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)]);
sscanf(buf, "%i", &buffer_settings.frames_in_buffer[get_channel_from_name(attr)], &len);
return count; return count;
} }
......
...@@ -509,11 +509,13 @@ ...@@ -509,11 +509,13 @@
#define P_EXPOS 141 ///< P_RW_EXPOS 1 exposure time - now in microseconds? #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_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_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_COMPMOD_BYRSH 160 ///< Bayer shift in compressor
#define P_PORTRAIT 161 ///< Quantization coefficients optimized for vertical scan lines //#define P_PORTRAIT 161 ///< Quantization coefficients optimized for vertical scan lines
//TODO: rearrange, combine with other AUTOEXP //TODO: rearrange, combine with other AUTOEXP
...@@ -666,9 +668,9 @@ ...@@ -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 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_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 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 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 #define FRAMEPAR_GLOBALS 0x01000 ///< start of global (not frame-related) parameters
...@@ -758,6 +760,10 @@ ...@@ -758,6 +760,10 @@
//#define G_HIST_Y_FRAME (FRAMEPAR_GLOBALS + 57) // /< last frame for which Y histogram was calculated //#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_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_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_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) #define G_FTP_NEXT_TIME (FRAMEPAR_GLOBALS + 60) ///< time of the next FTP upload (seconds from epoch)
...@@ -925,40 +931,40 @@ struct framepars_t { ...@@ -925,40 +931,40 @@ struct framepars_t {
* TODO: Try to make room for some new ones. * TODO: Try to make room for some new ones.
*/ */
enum onchange_functions_t { enum onchange_functions_t {
onchange_recalcseq=0, ///< recalculate sequences/latencies, according to P_SKIP, P_TRIG onchange_recalcseq=0, ///< 0 recalculate sequences/latencies, according to P_SKIP, P_TRIG
onchange_detectsensor, ///< detect sensor type, sets sensor structure (capabilities), function pointers onchange_detectsensor, ///< 1 detect sensor type, sets sensor structure (capabilities), function pointers
onchange_sensorphase, ///< program sensor clock/phase (needs to know maximal clock frequency) onchange_sensorphase, ///< 2 program sensor clock/phase (needs to know maximal clock frequency)
onchange_i2c, ///< program i2c onchange_i2c, ///< 3 program i2c
onchange_sensorregs, ///< write sensor registers (only changed from outside the driver as they may have different latencies)? onchange_sensorregs, ///< 4 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_initsensor, ///< 5 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_afterinit, ///< 6 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_multisens, ///< 7 chnages related to multiplexed sensors
onchange_window, ///< program sensor WOI and mirroring (flipping) onchange_window, ///< 8 program sensor WOI and mirroring (flipping)
onchange_window_safe, ///< program sensor WOI and mirroring (flipping) - lower latency, no bad frames onchange_window_safe, ///< 9 program sensor WOI and mirroring (flipping) - lower latency, no bad frames
// onchange_exposure, ///< program exposure // onchange_exposure, ///< program exposure
onchange_gains, ///< program analog gains onchange_gains, ///< 10 program analog gains
onchange_triggermode, ///< program sensor trigger mode onchange_triggermode, ///< 11 program sensor trigger mode
onchange_sensorin, ///< program sensor input in FPGA (Bayer, 8/16 bits, ??) onchange_sensorin, ///< 12 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_sensorstop, ///< 13 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_sensorrun, ///< 14 Start/single acquisition from the sensor to the FPGA (stop has latency of 1)
onchange_gamma, ///< program gamma table onchange_gamma, ///< 15 program gamma table
onchange_hist, ///< program histogram window onchange_hist, ///< 16 program histogram window
onchange_aexp, ///< program autoexposure mode onchange_aexp, ///< 17 program autoexposure mode
onchange_quality, ///< program quantization table(s) onchange_quality, ///< 18 program quantization table(s)
onchange_memsensor, ///< program memory channels 0 (sensor->memory) and 1 (memory->FPN) onchange_memsensor, ///< 19 program memory channels 0 (sensor->memory) and 1 (memory->FPN)
onchange_memcompressor, ///< program memory channel 2 (memory->compressor) onchange_memcompressor, ///< 20 program memory channel 2 (memory->compressor)
onchange_limitfps, ///< check compressor will keep up, limit sensor FPS if needed onchange_limitfps, ///< 21 check compressor will keep up, limit sensor FPS if needed
onchange_exposure, ///< program exposure - NOTE: was just after onchange_window onchange_exposure, ///< 22 program exposure - NOTE: was just after onchange_window
onchange_compmode, ///< program compressor modes (excluding start/stop/single) onchange_compmode, ///< 23 program compressor modes (excluding start/stop/single)
onchange_focusmode, ///< program focus modes onchange_focusmode, ///< 24 program focus modes
onchange_trigseq, ///< program sequencer (int/ext) onchange_trigseq, ///< 25 program sequencer (int/ext)
onchange_irq, ///< program smart IRQ mode (needs to be on) onchange_irq, ///< 26 program smart IRQ mode (needs to be on)
onchange_comprestart, ///< restart after changing geometry (recognizes ASAP and programs memory channel 2 then) onchange_comprestart, ///< 27 restart after changing geometry (recognizes ASAP and programs memory channel 2 then)
onchange_compstop, ///< stop compressor when changing geometry onchange_compstop, ///< 28 stop compressor when changing geometry
onchange_compctl, ///< only start/stop/single (after explicitly changed, not when geometry was changed) onchange_compctl, ///< 29 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_gammaload, ///< 30 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_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)? // 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 // add others - none left, all 32 bits used
}; };
...@@ -1325,6 +1331,7 @@ struct p_names_t { ...@@ -1325,6 +1331,7 @@ struct p_names_t {
G_NAME_ENTRY(HIST_Y_FRAME), \ G_NAME_ENTRY(HIST_Y_FRAME), \
G_NAME_ENTRY(HIST_C_FRAME), \ G_NAME_ENTRY(HIST_C_FRAME), \
G_NAME_ENTRY(SUBCHANNELS), \ G_NAME_ENTRY(SUBCHANNELS), \
G_NAME_ENTRY(COMPRESSOR_FRAME), \
G_NAME_ENTRY(SKIP_DIFF_FRAME), \ G_NAME_ENTRY(SKIP_DIFF_FRAME), \
G_NAME_ENTRY(FTP_NEXT_TIME), \ G_NAME_ENTRY(FTP_NEXT_TIME), \
G_NAME_ENTRY(DAEMON_ERR), \ 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