Commit 3c106d1d authored by Andrey Filippov's avatar Andrey Filippov

Making driver files compile

parent 581d1d2f
......@@ -23,3 +23,9 @@ obj-$(CONFIG_ELPHEL393) += quantization_tables.o
obj-$(CONFIG_ELPHEL393) += circbuf.o
obj-$(CONFIG_ELPHEL393) += jpeghead.o
obj-$(CONFIG_ELPHEL393) += gamma_tables.o
obj-$(CONFIG_ELPHEL393) += histograms.o
obj-$(CONFIG_ELPHEL393) += pgm_functions.o
obj-$(CONFIG_ELPHEL393) += mt9x001.o
obj-$(CONFIG_ELPHEL393) += multi10359.o
......@@ -187,94 +187,95 @@ int x393_getClockFreq(int sensor_port, int nclock) {
EXPORT_SYMBOL_GPL(x393_getClockFreq);
int x393_setClockFreq(int sensor_port, int nclock, int freq) { // freq now in Hz
int err=0;
sensor_port &= 3;
nclock &= 3;
t_pll_params pll_params;
int i,bp,bq,bdiv,pllc,fact;
bp=0; bq=0; bdiv=0; pllc= 0; // just to make gcc happy
fact=0;
dev_dbg(sdev, "setClockFreq(%d,%d,%d)\r\n",sensor_port,nclock,freq);
if ((freq!=0) && (nclock!=3) ){
if ( (i=calc_pll_params (freq, &pll_params)) !=0) {
dev_err(sdev, "bad frequency for clock %d - %d Hz, err=%d\n",nclock,freq,i);
return -EINVAL;
}
fact=CY22393_SCALE*(CY22393_XTAL*(pll_params.p+6)/(pll_params.q+2)/pll_params.dv);
bp= pll_params.p; // (freqtab[freq]>>20)&0x7ff;
bq= pll_params.q; // (freqtab[freq]>>12)&0xff;
bdiv=pll_params.dv; // (freqtab[freq]>> 4)&0xff;
pllc=pll_params.corr; // freqtab[freq] &0x0f;
}
switch (nclock) {
case 0:
if (freq==0) {
err |= setCYField (sensor_port,0x16, 0x40, 0x00); // turn off pll3
err |= setCYField (sensor_port,0x09, 0x7f, 0x00); // turn off divider- A
err |= setCYField (sensor_port,0x08, 0x7f, 0x00); // turn off divider- A
} else {
err |= setCYField (sensor_port,0x16, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
err |= setCYField (sensor_port,0x15, 0xff, ((bp & 0x1fe)>>1) );
err |= setCYField (sensor_port,0x14, 0xff, bq );
err |= setCYField (sensor_port,0x09, 0x7f, bdiv); // set divider- A
err |= setCYField (sensor_port,0x08, 0x7f, bdiv); // set divider- A
err |= setCYField (sensor_port,0x0e, 0x03, 0x03); // set PLL3 as source for ClkA
}
// fpga_state |= FPGA_STATE_CLOCKS;
break;
case 1:
if (freq==0) {
err |= setCYField (sensor_port,0x0b, 0x7f, 0x00); // turn off divider- B
err |= setCYField (sensor_port,0x0a, 0x7f, 0x00); // turn off divider- B
for (i=0;i<24;i+=3) err |= setCYField (sensor_port,0x42+i, 0x40, 0x00); // turn off pll1
} else {
// progam all variants
for (i=0;i<24;i+=3) {
err |= setCYField (sensor_port,0x42+i, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
err |= setCYField (sensor_port,0x41+i, 0xff, ((bp & 0x1fe)>>1) );
err |= setCYField (sensor_port,0x40+i, 0xff, bq );
}
err |= setCYField (sensor_port,0x0b, 0x7f, bdiv); // set divider- B
err |= setCYField (sensor_port,0x0a, 0x7f, bdiv); // set divider- B
err |= setCYField (sensor_port,0x0e, 0x0c, 0x04); // set PLL1 as source for ClkB
}
break;
case 2:
if (freq==0) {
err |= setCYField (sensor_port,0x13, 0x40, 0x00); // turn off pll2
err |= setCYField (sensor_port,0x0d, 0x7f, 0x00); // turn off divider- D
} else {
err |= setCYField (sensor_port,0x13, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
err |= setCYField (sensor_port,0x12, 0xff, ((bp & 0x1fe)>>1) );
err |= setCYField (sensor_port,0x11, 0xff, bq );
err |= setCYField (sensor_port,0x0d, 0x7f, bdiv); // set divider- D
err |= setCYField (sensor_port,0x0e, 0xc0, 0x80); // set PLL2 as source for ClkD
}
break;
case 3:
if ((freq!=0) && (freq!=CY22393_SCALE*CY22393_XTAL)) {
dev_err(sdev, "Only frequency 0 (off) and %d Hz (xtal) are allowed for channel 3\r\n",CY22393_SCALE*CY22393_XTAL);
return -EINVAL;
} else {
// int setCYField (sensor_port,int devfd, int addr, int mask, int value) O_RDWR
if (freq==0) {
err |= setCYField (sensor_port,0x0f, 0x04, 0x00);
} else {
err |= setCYField (sensor_port,0x0f, 0x04, 0x04);
fact= CY22393_SCALE*CY22393_XTAL;
}
}
break;
default: return -1; // wrong clock number
}
dev_dbg(sdev, "nclock=%d fact=%d\n",nclock,fact);
if (err != 0) {
dev_err(sdev, "Error programming clock %d fact=%d, err=0x%x\n",nclock,fact, err);
return err;
}
clock_frequency[(sensor_port << 2) + nclock] = fact;
return fact;
int x393_setClockFreq(int sensor_port, int nclock, int freq)
{ // freq now in Hz
int err=0;
sensor_port &= 3;
nclock &= 3;
t_pll_params pll_params;
int i,bp,bq,bdiv,pllc,fact;
bp=0; bq=0; bdiv=0; pllc= 0; // just to make gcc happy
fact=0;
dev_dbg(sdev, "setClockFreq(%d,%d,%d)\r\n",sensor_port,nclock,freq);
if ((freq!=0) && (nclock!=3) ){
if ( (i=calc_pll_params (freq, &pll_params)) !=0) {
dev_err(sdev, "bad frequency for clock %d - %d Hz, err=%d\n",nclock,freq,i);
return -EINVAL;
}
fact=CY22393_SCALE*(CY22393_XTAL*(pll_params.p+6)/(pll_params.q+2)/pll_params.dv);
bp= pll_params.p; // (freqtab[freq]>>20)&0x7ff;
bq= pll_params.q; // (freqtab[freq]>>12)&0xff;
bdiv=pll_params.dv; // (freqtab[freq]>> 4)&0xff;
pllc=pll_params.corr; // freqtab[freq] &0x0f;
}
switch (nclock) {
case 0:
if (freq==0) {
err |= setCYField (sensor_port,0x16, 0x40, 0x00); // turn off pll3
err |= setCYField (sensor_port,0x09, 0x7f, 0x00); // turn off divider- A
err |= setCYField (sensor_port,0x08, 0x7f, 0x00); // turn off divider- A
} else {
err |= setCYField (sensor_port,0x16, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
err |= setCYField (sensor_port,0x15, 0xff, ((bp & 0x1fe)>>1) );
err |= setCYField (sensor_port,0x14, 0xff, bq );
err |= setCYField (sensor_port,0x09, 0x7f, bdiv); // set divider- A
err |= setCYField (sensor_port,0x08, 0x7f, bdiv); // set divider- A
err |= setCYField (sensor_port,0x0e, 0x03, 0x03); // set PLL3 as source for ClkA
}
// fpga_state |= FPGA_STATE_CLOCKS;
break;
case 1:
if (freq==0) {
err |= setCYField (sensor_port,0x0b, 0x7f, 0x00); // turn off divider- B
err |= setCYField (sensor_port,0x0a, 0x7f, 0x00); // turn off divider- B
for (i=0;i<24;i+=3) err |= setCYField (sensor_port,0x42+i, 0x40, 0x00); // turn off pll1
} else {
// progam all variants
for (i=0;i<24;i+=3) {
err |= setCYField (sensor_port,0x42+i, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
err |= setCYField (sensor_port,0x41+i, 0xff, ((bp & 0x1fe)>>1) );
err |= setCYField (sensor_port,0x40+i, 0xff, bq );
}
err |= setCYField (sensor_port,0x0b, 0x7f, bdiv); // set divider- B
err |= setCYField (sensor_port,0x0a, 0x7f, bdiv); // set divider- B
err |= setCYField (sensor_port,0x0e, 0x0c, 0x04); // set PLL1 as source for ClkB
}
break;
case 2:
if (freq==0) {
err |= setCYField (sensor_port,0x13, 0x40, 0x00); // turn off pll2
err |= setCYField (sensor_port,0x0d, 0x7f, 0x00); // turn off divider- D
} else {
err |= setCYField (sensor_port,0x13, 0x7f, 0x40+(pllc<<3)+((bp & 1)<<2)+((bp & 0x600)>>9) );
err |= setCYField (sensor_port,0x12, 0xff, ((bp & 0x1fe)>>1) );
err |= setCYField (sensor_port,0x11, 0xff, bq );
err |= setCYField (sensor_port,0x0d, 0x7f, bdiv); // set divider- D
err |= setCYField (sensor_port,0x0e, 0xc0, 0x80); // set PLL2 as source for ClkD
}
break;
case 3:
if ((freq!=0) && (freq!=CY22393_SCALE*CY22393_XTAL)) {
dev_err(sdev, "Only frequency 0 (off) and %d Hz (xtal) are allowed for channel 3\r\n",CY22393_SCALE*CY22393_XTAL);
return -EINVAL;
} else {
// int setCYField (sensor_port,int devfd, int addr, int mask, int value) O_RDWR
if (freq==0) {
err |= setCYField (sensor_port,0x0f, 0x04, 0x00);
} else {
err |= setCYField (sensor_port,0x0f, 0x04, 0x04);
fact= CY22393_SCALE*CY22393_XTAL;
}
}
break;
default: return -1; // wrong clock number
}
dev_dbg(sdev, "nclock=%d fact=%d\n",nclock,fact);
if (err != 0) {
dev_err(sdev, "Error programming clock %d fact=%d, err=0x%x\n",nclock,fact, err);
return err;
}
clock_frequency[(sensor_port << 2) + nclock] = fact;
return fact;
}
EXPORT_SYMBOL_GPL(x393_setClockFreq);
......
......@@ -550,10 +550,10 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
framepars[4].functions, framepars[5].functions, framepars[6].functions, framepars[7].functions));
if (sensorproc->pgm_func[i]) {
rslt = sensorproc->pgm_func[i] ( &(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
if ((rslt >= 0) && (sensorproc->pgm_func[i + 32])) { // sensor - specific functions, called after the main ones
rslt = sensorproc->pgm_func[i + 32] ( &(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) printk("%s:%d:%s - error=%d", __FILE__, __LINE__, __FUNCTION__, rslt);
......@@ -627,10 +627,10 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
if (sensorproc->pgm_func[i]) {
// NOTE: Was (frame8+job_ahead +1) & PARS_FRAMES_MASK
rslt = sensorproc->pgm_func[i] ( &(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
if ((rslt >= 0) && (sensorproc->pgm_func[i + 32])) { // sensor - specific functions, called after the main ones
rslt = sensorproc->pgm_func[i + 32] ( &(sensorproc->sensor), procpars, prevpars, seq_frame);
rslt = sensorproc->pgm_func[i + 32] (sensor_port, &(sensorproc->sensor), procpars, prevpars, seq_frame);
}
if (rslt >= 0) {
procpars->functions &= ~mask; // mark it done
......@@ -1113,7 +1113,7 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig)
unsigned long target_frame;
struct framepars_pd * privData = (struct framepars_pd*) file -> private_data;
int sensor_port = privData -> minor - CMOSCAM_MINOR_FRAMEPARS_CHN_0;
struct framepars_t *framepars = aframepars[sensor_port];
// struct framepars_t *framepars = aframepars[sensor_port];
MDF1(printk(" offset=0x%x, orig=0x%x, sensor_port = %d\n", (int)offset, (int)orig, sensor_port));
switch (orig) {
case SEEK_SET:
......
......@@ -7,11 +7,11 @@ int is_gamma_current (unsigned short hash16, unsigned short scale, int index);
int is_gamma_valid (unsigned short hash16, unsigned short scale, int index);
// int prev_locked_color[4];
int unlock_gamma_node (int color); /// NOTE: Not needed anymore
int unlock_gamma_node (int color, int sensor_port, int sensor_subchn); /// NOTE: Not needed anymore
///
/// 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);
unsigned long * get_gamma_fpga(int color, int sensor_port, int sensor_subchn);
int gamma_new_node(void);
void gamma_encode_fpga(unsigned short * gamma_in, unsigned long * gamma_out);///Hardware-dependent encoding of the FPGA "gamma" table. Converts unsigned short array of 257 16-bit values (only 10 msb-s are used) to 256 unsigned long words to be written to FPGA
......@@ -27,5 +27,6 @@ void gamma_calc_reverse(unsigned short * gamma_in, unsigned char * gamma_out);/
// #define GAMMA_MODE_HARDWARE 4 // the table is needed to program FPGA: fpga-encoded table will be calculated (if not yet), node will be locked for specified
// color/frame pair
int set_gamma_table (unsigned short hash16, unsigned short scale, unsigned short * gamma_proto, unsigned char mode, int color, int sensor_port, int sensor_subchn);
unsigned long get_locked_hash32(int color);
unsigned long get_locked_hash32(int color, int sensor_port,int sensor_subchn);
#endif
......@@ -102,7 +102,9 @@
#include <asm/outercache.h>
#include <asm/cacheflush.h>
#include <linux/dma-mapping.h>
#include <linux/dma-direction.h>
// ##include <asm/dma-mapping.h>
#include <elphel/driver_numbers.h>
#include <elphel/c313a.h>
......@@ -130,7 +132,9 @@
#define MDF22(x)
#endif
u32 (*fpga_hist_data)[SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]; ///< Array of histogram data, mapped to the memory wheer FPGA sends data
//u32 (*fpga_hist_data)[SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]; ///< Array of histogram data, mapped to the memory wheer FPGA sends data
//u32 *fpga_hist_data[SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]; ///< Array of histogram data, mapped to the memory wheer FPGA sends data
u32 (*fpga_hist_data)[SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]; ///< Array of histogram data, mapped to the memory wheer FPGA sends data
dma_addr_t fpga_hist_phys; // physical address of the start of the received histogram data
#define X3X3_HISTOGRAMS_DRIVER_NAME "Elphel (R) Model 353 Histograms device driver"
......@@ -144,6 +148,7 @@ static int numHistChn = 0;
/** Variable-length array (length is the total number of active sensors <=16), each being the same as in 353:
* consisting of SENSOR_PORTS histogram_stuct_t structures */
struct histogram_stuct_t (*histograms)[HISTOGRAM_CACHE_NUMBER];
//struct histogram_stuct_t *histograms;
dma_addr_t histograms_phys; ///< likely not needed, saved during allocation
......@@ -193,7 +198,8 @@ int histograms_init_hardware(void)
{
int port, chn;
x393_hist_saxi_addr_t saxi_addr;
fpga_hist_data = (u32 [SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]) pElphel_buf->d2h_vaddr; // must be page-aligned!
// fpga_hist_data = (u32 [SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]) pElphel_buf->d2h_vaddr; // must be page-aligned!
fpga_hist_data = (u32 *) pElphel_buf->d2h_vaddr; // must be page-aligned!
fpga_hist_phys = pElphel_buf->d2h_paddr;
for (port=0; port<SENSOR_PORTS; port++) for (chn=0; chn < MAX_SENSORS; chn++) {
saxi_addr.page=(fpga_hist_phys >> PAGE_SHIFT)+ PARS_FRAMES * (chn + MAX_SENSORS *port);// table for 4 colors is exactly 1 page;
......@@ -225,24 +231,29 @@ void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask
unsigned long flags;
int p,s,i, sz,pages;
numHistChn = 0; //__builtin_popcount (chn_mask & 0xffff);
if (sz & (PAGE_SIZE-1)) pages++;
for (p=0; p< SENSOR_PORTS; p++) for (s=0;s <MAX_SENSORS;s++) {
i = p * SENSOR_PORTS + s;
if (chn_mask & (1 << i)){
histograms_map = numHistChn++;
histograms_map[p][s] = numHistChn++;
GLOBALPARS(p, G_HIST_LAST_INDEX + s) =0; // mark as valid
GLOBALPARS(p, G_SUBCHANNELS) |= 1 << s;
} else {
histograms_map = -1;
histograms_map[p][s] = -1;
GLOBALPARS(p, G_HIST_LAST_INDEX + s) =0xffffffff; // mark as invalid
GLOBALPARS(p, G_SUBCHANNELS) &= ~(1 << s);
}
}
//G_SUBCHANNELS
sz = numHistChn * HISTOGRAM_CACHE_NUMBER * sizeof(struct histogram_stuct_t);
if (sz & (PAGE_SIZE-1)) pages++;
pages = sz >> PAGE_SHIFT;
// 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 = 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]>>>
BUG_ON(!histograms);
histograms_p= (struct histogram_stuct_t *) histograms;
MDF21(printk("\n"));
......@@ -284,12 +295,12 @@ int set_histograms (int sensor_port, ///< sensor port number (0..3)
int i, color_start, hist_indx, hist_frame;
hist_indx=get_hist_index(sensor_port,sensor_chn);
if (hist_indx <0 ) return -EINVAL;
if (histograms[GLOBALPARS(sensor_port,G_HIST_LAST_INDEX+sensor_chn)].frame!=frame) {
if (histograms[hist_indx][GLOBALPARS(sensor_port,G_HIST_LAST_INDEX+sensor_chn)].frame!=frame) {
GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn)=(GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn)+1) & (HISTOGRAM_CACHE_NUMBER-1);
histograms[hist_indx][GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn)].valid=0; // overwrite all
histograms[hist_indx][GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn)].frame=frame; // add to existent
if (framep) memcpy (&(histograms[GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].frame), framep, 32); // copy provided frame, gains,expos,vexpos, focus
if (gammaHash) memcpy (&(histograms[GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].gtab_r), gammaHash, 16); // copy provided 4 hash32 values
if (framep) memcpy (&(histograms[hist_indx][GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].frame), framep, 32); // copy provided frame, gains,expos,vexpos, focus
if (gammaHash) memcpy (&(histograms[hist_indx][GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].gtab_r), gammaHash, 16); // copy provided 4 hash32 values
} else {
needed &= ~histograms[hist_indx][GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].valid; // remove those that are already available from the request
}
......@@ -337,9 +348,10 @@ int get_histograms(int sensor_port, ///< sensor port number (0..3)
{
int i, color_start, index;
int hist_indx=get_hist_index(sensor_port,sensor_chn);
int raw_needed;
if (hist_indx <0 ) return -EINVAL;
index=GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn);
int raw_needed=(needed | (needed>>4) | needed>>8) & 0xf;
raw_needed=(needed | (needed>>4) | needed>>8) & 0xf;
for (i=0;i<HISTOGRAM_CACHE_NUMBER;i++) {
MDF21(printk("index=%d, needed=0x%x\n",index,needed));
if ((histograms[hist_indx][index].frame <= frame) && ((histograms[hist_indx][index].valid & raw_needed)==raw_needed)) break;
......@@ -403,12 +415,12 @@ inline void histogram_calc_percentiles (unsigned long * cumul_hist, ///< [IN]
unsigned long v256=0; // running value to be compared against cumulative histogram (it is 256 larger than cumul_hist)
unsigned long inc_v256=cumul_hist[255]; // step of v256 increment
int shiftl=8;
int p=0; // current value of percentile
int x=0; // current percentile index
while (inc_v256>0xffffff) { // to protect from unlikely overflow at 16MPix - in the future)
inc_v256 >>= 1;
shiftl--;
}
int p=0; // current value of percentile
int x=0; // current percentile index
while ((p<256) && (x<256)) {
percentile[x]=p;
if ((p<255) && ( (cumul_hist[p] << shiftl) <= v256)) {
......@@ -547,24 +559,24 @@ loff_t histograms_lseek (struct file * file,
else reqFrame=offset;
}
if ((offset < reqFrame) && // if the requested frame is in the past - try to get it first before requesting a new
(((privData->frame_index = get_histograms (offset, privData->needed))) >=0)) {
(((privData->frame_index = get_histograms (privData->port, privData->subchannel, offset, privData->needed))) >=0)) {
// file->f_pos=privData->frame_index;
file->f_pos=privData->frame_index + HISTOGRAM_CACHE_NUMBER * get_hist_index(privData->port, privData->subchannel);
return file->f_pos;
}
// request histogram(s)
// setFramePar(&framepars[reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(&aframepars[privData->port][reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(privData->port, &aframepars[privData->port][reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
// make sure (harmful) interrupt did not happen since getThisFrameNumber()
if (reqFrame < getThisFrameNumber(privData->port)) {
// setFramePar(&framepars[getThisFrameNumber() & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(&aframepars[privData->port][getThisFrameNumber(privData->port) & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(privData->port, &aframepars[privData->port][getThisFrameNumber(privData->port) & PARS_FRAMES_MASK], reqAddr, 1);
}
}
if (privData-> wait_mode) wait_event_interruptible (hist_c_wait_queue,GLOBALPARS(privData->port,G_HIST_C_FRAME + privData->subchannel)>=offset);
else wait_event_interruptible (hist_y_wait_queue,GLOBALPARS(privData->port,G_HIST_Y_FRAME + privData->subchannel)>=offset);
privData->frame_index = get_histograms (offset, privData->needed);
privData->frame_index = get_histograms (privData->port, privData->subchannel, offset, privData->needed);
if (privData->frame_index <0) {
return -EFAULT;
} else {
......@@ -605,12 +617,12 @@ loff_t histograms_lseek (struct file * file,
default:
switch (offset & ~0x1f) {
case LSEEK_DAEMON_HIST_Y: // wait for daemon enabled and histograms Y ready
MDF21(printk("wait_event_interruptible (hist_y_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(P_DAEMON_EN), (int) (1<<(offset & 0x1f))));
wait_event_interruptible (hist_y_wait_queue, get_imageParamsThis(P_DAEMON_EN) & (1<<(offset & 0x1f)));
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))));
wait_event_interruptible (hist_y_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f)));
break;
case LSEEK_DAEMON_HIST_C: // wait for daemon enabled and histograms Y ready
MDF21(printk("wait_event_interruptible (hist_c_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(P_DAEMON_EN), (int) (1<<(offset & 0x1f))));
wait_event_interruptible (hist_c_wait_queue, get_imageParamsThis(P_DAEMON_EN) & (1<<(offset & 0x1f)));
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))));
wait_event_interruptible (hist_c_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f)));
break;
default:
return -EINVAL;
......
......@@ -26,7 +26,7 @@ int get_hist_index (int sensor_port, int sensor_chn);
int set_histograms (int sensor_port, int sensor_chn, unsigned long frame, int needed, unsigned long * gammaHash, unsigned long * framep);
int get_histograms (unsigned long frame, int needed);
int get_histograms (int sensor_port, int sensor_chn, unsigned long frame, int needed);
int histograms_init_hardware(void);
void histograms_dma_ctrl(int mode); // 0 - reset, 1 - disable, 2 - enable
/*!***************************************************************************
*! FILE NAME : imu_log353.c
*! DESCRIPTION: reading IMU log fifo
*! Copyright (C) 2011 Elphel, Inc.
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: imu_log353.c,v $
*! Revision 1.5 2012/04/14 03:53:48 elphel
*! bug fix in the driver (was producing errors in 3-4 hours)
*!
*! Revision 1.3 2011/08/13 00:54:08 elphel
*! added /dev/imu_ctl where it is possible to read current logger settings
*!
*! Revision 1.2 2011/07/30 23:22:54 elphel
*! Modified to enable simultaneous access to IMU logger,
*! fixed bug noticed by Lemay
*!
*! Revision 1.1 2011/05/20 03:33:48 elphel
*! IMU/GPS logger driver, initial commit
*!
*/
/****************** INCLUDE FILES SECTION ***********************************/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/autoconf.h>
#include <asm/system.h>
#include <asm/arch/memmap.h>
//#include <asm/svinto.h>
#include <asm/io.h>
#include <asm/arch/dma.h>
#include <asm/arch/hwregs/dma_defs.h>
#include <asm/arch/hwregs/dma.h>
#include <asm/arch/hwregs/reg_map.h>
#include <asm/arch/hwregs/bif_dma_defs.h>
#include <asm/irq.h>
#include <asm/fasttimer.h>
#include <asm/atomic.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <asm/arch/cache.h>
#include <asm/elphel/driver_numbers.h>
#include <asm/elphel/c313a.h>
#include <asm/elphel/fpgaconfa.h>
#include "fpgactrl.h"
//#include "fpga_sdram.h"
#include "imu_log353.h"
#include "x3x3.h"
#include "cci2c.h" // i2c to enable CS for the IMU
#if 0
#define D(x) x
#define D0(x) x
#define MD7(x) printk("%s:%d:",__FILE__,__LINE__);x
#define MD8(x) printk("%s:%d:",__FILE__,__LINE__);x
#define MD12(x) printk("%s:%d:",__FILE__,__LINE__);x
#else
#define D(x)
#define D0(x)
#define MD7(x)
#define MD8(x)
#define MD12(x)
#endif
#define D1(x) x
#define IS_103695_REV_A 1
#define EXT_DMA_1_START \
do { reg_bif_dma_rw_ch1_start c = {.run=1};\
REG_WR(bif_dma, regi_bif_dma, rw_ch1_start, (reg_bif_dma_rw_ch1_start) c); } while( 0 )
#define EXT_DMA_1_STOP \
do { reg_bif_dma_rw_ch1_start c = {.run=0};\
REG_WR(bif_dma, regi_bif_dma, rw_ch1_start, (reg_bif_dma_rw_ch1_start) c); } while( 0 )
#define bytePtrMask ((CCAM_DMA1_SIZE << 2)-1) // and byte pointer in the dma buffer to get index in the array
#define XCLK_RATE 80000000
#define RS232_RATE 19200
#define IMU_MODULE_DESCRIPTION "IMU logger for 10365 ext. board"
#define IMU_DRIVER_NAME "imu_logger"
#define IMU_MAXMINOR 10
#define X313_WA_IOPINS 0x70 // bits [31:24] - enable channels (channel 0 -software, enabled at FPGA init)
#define X313_WA_IOPINS_EN_IMU 0xc0000000
#define X313_WA_IOPINS_DIS_IMU 0x80000000
#define X313_WA_IMU_DATA 0x7e
#define X313_WA_IMU_CTRL 0x7f
// #define X313_RA_IMU_DATA 0x7e // use csp4
// #define X313_RA_IMU_STATUS 0x7f // use csp4
#define IMU_COUNT_OVERFLOW 0x1000000 // number of records written is modulo IMU_COUNT_OVERFLOW
#define X313_RA_IMU_COUNT 0x7e // number of 64-byte samples recorded (24 bit counter)
#define X313_IMU_PERIOD_ADDR 0x0 // request period for IMU (in SPI bit periods)
#define X313_IMU_DIVISOR_ADDR 0x1 // xclk (80MHz) clock divisor for half SPI bit period
#define X313_IMU_RS232DIV_ADDR 0x2 // serial gps bit duration in xclk (80MHz) periods - 16 bits
#define X313_IMU_CONFIGURE_ADDR 0x3 // IMU logger configuration
#define IMU_CONF(x,y) (((((y) & ((1 << IMUCR__##x##__WIDTH)-1))) | (1 << IMUCR__##x##__WIDTH) ) << IMUCR__##x##__BITNM)
#define IMUCR__IMU_SLOT__BITNM 0 // slot, where 103695 (imu) bnoard is connected: 0 - none, 1 - J9, 2 - J10, 3 - J11)
#define IMUCR__IMU_SLOT__WIDTH 2
#define IMUCR__GPS_CONF__BITNM 3 // slot, where 103695 (imu) bnoard is connected: 0 - none, 1 - J9, 2 - J10, 3 - J11)
#define IMUCR__GPS_CONF__WIDTH 4 // bits 0,1 - slot #, same as for IMU_SLOT, bits 2,3:
// 0 - ext pulse, leading edge,
// 1 - ext pulse, trailing edge
// 2 - start of the first rs232 character after pause
// 3 - start of the last "$" character (start of each NMEA sentence)
#define IMUCR__MSG_CONF__BITNM 8 // source of external pulses to log:
#define IMUCR__MSG_CONF__WIDTH 5 // bits 0-3 - number of fpga GPIO input 0..11 (i.e. 0x0a - external optoisolated sync input (J15)
// 0x0f - disable MSG module
// bit 4 - invert polarity: 0 - timestamp leading edge, log at trailing edge, 1 - opposite
// software may set (up to 56 bytes) log message before trailing end of the pulse
#define IMUCR__SYN_CONF__BITNM 14 // logging frame time stamps (may be synchronized by another camera and have timestamp of that camera)
#define IMUCR__SYN_CONF__WIDTH 1 // 0 - disable, 1 - enable
#define IMUCR__RST_CONF__BITNM 16 // reset module
#define IMUCR__RST_CONF__WIDTH 1 // 0 - enable, 1 -reset (needs resettimng DMA address in ETRAX also)
#define IMUCR__DBG_CONF__BITNM 18 // several axtra IMU configuration bits
#define IMUCR__DBG_CONF__WIDTH 4 // 0 - config_long_sda_en, 1 -config_late_clk, 2 - config_single_wire, should be set for 103695 rev "A"
#define X313_IMU_REGISTERS_ADDR 0x4
#define X313_IMU_NMEA_FORMAT_ADDR 0x20
#define X313_IMU_MESSAGE_ADDR 0x40 // 40..4f, only first 0xe visible
// offsets in the file (during write)
#define X313_IMU_PERIOD_OFFS 0x0
#define X313_IMU_DIVISOR_OFFS 0x4
#define X313_IMU_RS232DIV_OFFS 0x8
#define X313_IMU_CONFIGURE_OFFS 0xc
#define X313_IMU_SLEEP_OFFS 0x10
#define X313_IMU_REGISTERS_OFFS 0x14 // .. 0x2f
#define X313_IMU_NMEA_FORMAT_OFFS 0x30
#define X313_IMU_MESSAGE_OFFS 0xB0 // 0xB0..0xE7
#define PCA9500_PP_ADDR 0x40 // PCA9500 i2c slave addr for the parallel port (read will be 0x41)
#define DFLT_SLAVE_ADDR 3 // i2c slave addr modifier (0..7) for the IMU (103695) board
#define DFLT_SCLK_FREQ 5000000 // SCLK frequency
#define DFLT_DIVISOR ( XCLK_RATE / DFLT_SCLK_FREQ /2 )
#define DFLT_STALL_USEC 2 // stall time in usec
#define DFLT_STALL (( DFLT_STALL_USEC * ( XCLK_RATE / DFLT_DIVISOR )) / 1000000 ) // stall time in usec
#define DFLT_SLEEP 30000 // usec, sleep if not ready
//#define DFLT_FEQ 300
//#define DFLT_PERIOD ( XCLK_RATE / DFLT_DIVISOR / DFLT_FEQ ) // fixed scan period
#define DFLT_PERIOD 0xFFFFFFFF // read IMU when it is ready
#define DFLT_RS232DIV ( XCLK_RATE / 2 / RS232_RATE )
#if IS_103695_REV_A
#define EXTRA_CONF 0x4
#else
#define EXTRA_CONF 0x0
#endif
#define SLOW_SPI 0 // set to 1 for slower SPI (not ADIS-16375), it will increase SCLK period that does not end CS active
#define DFLT_CONFIG ( IMU_CONF(IMU_SLOT,1) | \
IMU_CONF(GPS_CONF, ( 2 | 8) ) | \
IMU_CONF(MSG_CONF,10) | \
IMU_CONF(SYN_CONF, 1) | \
IMU_CONF(DBG_CONF, EXTRA_CONF) | \
((SLOW_SPI & 1)<<23) | \
(DFLT_SLAVE_ADDR << 24))
#define WHICH_INIT 1
#define WHICH_RESET 2
#define WHICH_RESET_SPI 4
#define WHICH_DIVISOR 8
#define WHICH_RS232DIV 16
#define WHICH_NMEA 32
#define WHICH_CONFIG 64
#define WHICH_REGISTERS 128
#define WHICH_MESSAGE 256
#define WHICH_PERIOD 512
#define WHICH_EN_DMA 1024
#define WHICH_EN_LOGGER 2048
#define LSEEK_IMU_NEW 1 // start from the new data, discard buffer
#define LSEEK_IMU_STOP 2 // stop DMA1 and IMU
#define LSEEK_IMU_START 3 // start IMU and DMA1 (do not modify parameters)
static unsigned char dflt_wbuf[]=
{ DFLT_PERIOD & 0xff, ( DFLT_PERIOD >> 8 ) & 0xff, ( DFLT_PERIOD >> 16) & 0xff, ( DFLT_PERIOD >> 24 ) & 0xff,
// {0,0,0,0, // period - off
DFLT_DIVISOR, DFLT_STALL, 0,0, // clock divisor
DFLT_RS232DIV & 0xff, ( DFLT_RS232DIV >> 8 ) & 0xff, ( DFLT_RS232DIV >> 16) & 0xff, ( DFLT_RS232DIV >> 24 ) & 0xff,
DFLT_CONFIG & 0xff, ( DFLT_CONFIG >> 8 ) & 0xff, ( DFLT_CONFIG >> 16) & 0xff, ( DFLT_CONFIG >> 24 ) & 0xff,
DFLT_SLEEP & 0xff, ( DFLT_SLEEP >> 8 ) & 0xff, ( DFLT_SLEEP >> 16) & 0xff, ( DFLT_SLEEP >> 24 ) & 0xff,
0x10, // x gyro low
0x12, // x gyro high
0x14, // y gyro low
0x16, // y gyro high
0x18, // z gyro low
0x1a, // z gyro high
0x1c, // x accel low
0x1e, // x accel high
0x20, // y accel low
0x22, // y accel high
0x24, // z accel low
0x26, // z accel high
0x40, // x delta angle low
0x42, // x delta angle high
0x44, // y delta angle low
0x46, // y delta angle high
0x48, // z delta angle low
0x4a, // z delta angle high
0x4c, // x delta velocity low
0x4e, // x delta velocity high
0x50, // y delta velocity low
0x52, // y delta velocity high
0x54, // z delta velocity low
0x56, // z delta velocity high
0x0e, // temperature
0x70, // time m/s
0x72, // time d/h
0x74,// time y/m
/// NMEA sentences
/// first three letters - sentence to log (letters after "$GP"). next "n"/"b" (up to 24 total) - "n" number (will be encoded 4 digits/byte, follwed by "0xF"
/// "b" - byte - all but last will have MSB 0 (& 0x7f), the last one - with MSB set (| 0x80). If there are no characters in the field 0xff will be output
'R','M','C','n','b','n','b','n','b','n','n','n','n','b', 0, 0, 0, 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
'G','G','A','n','n','b','n','b','n','n','n','n','b','n','b','b','b', 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
'G','S','A','b','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n', 0,0,0,0, 0,0,0,0, 0,0,0,0,
'V','T','G','n','b','n','b','n','b','n','b', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
// Message - up to 56 bytes
'O', 'd', 'o', 'm', 'e', 't', 'e', 'r', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e',
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
};
static unsigned char wbuf[sizeof(dflt_wbuf)];
//static unsigned char brbuf[8192]; /// twice the FPGA FIFO size
//static unsigned long * rbuf= (unsigned long *) brbuf;
/*
#define IMU_MAJOR 141
#define IMU_MINOR 1
*/
static const char fpga_name[] = "imu_control";
static int imu_open (struct inode *inode, struct file *filp);
static int imu_release(struct inode *inode, struct file *filp);
//static int imu_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
static ssize_t imu_write (struct file * file, const char * buf, size_t count, loff_t *off);
static loff_t imu_lseek (struct file * file, loff_t offset, int orig);
static ssize_t imu_read (struct file * file, char * buf, size_t count, loff_t *off);
//static loff_t fpga_lseek(struct file * file, loff_t offset, int orig);
//static ssize_t fpga_read(struct file * file, char * buf, size_t count, loff_t *off);
//static int __init fpga_init(void);
#define IMU_MAXMINOR 10
//static int minors[IMU_MAXMINOR+1]; // each minor can be opened only once
//static int num_reads; // number of fifo reads (does not advance file position)
//static int numRecordsRead=0; // number of 64-byte log records read (24 bit, same format as FPGA write counter)
static loff_t numBytesRead=0; // totalnumber of bytes read from the imu - global pointer (modified when open in write mode)
static loff_t numBytesWritten=0; // totalnumber of bytes writtent to the IMU buffer since it was started/restarted
static int lastFPGABytes=0; // last read FPGA counter (24 bits) << 6
static unsigned long ccam_dma1_buf[CCAM_DMA1_SIZE + (PAGE_SIZE>>2)] __attribute__ ((aligned (PAGE_SIZE)));
//!Without "static" system hangs after "Uncompressing Linux...
unsigned long * ccam_dma1_buf_ptr = NULL;
//unsigned long * ccam_dma1 = NULL; //! still used in autoexposure or something - why is in needed there?
void init_ccam_dma1_buf_ptr(void) {
ccam_dma1_buf_ptr = ccam_dma1_buf;
// ccam_dma1 = ccam_dma1_buf; //&ccam_dma_buf[0]; Use in autoexposure
}
void updateNumBytesWritten(void){
int thisFPGABytes=(int) port_csp0_addr[X313_RA_IMU_COUNT]<<6;
int delta=(thisFPGABytes-lastFPGABytes);
lastFPGABytes=thisFPGABytes;
if (delta<0) delta+=(IMU_COUNT_OVERFLOW<<6);
numBytesWritten+=delta; // long long
}
static struct file_operations imu_fops = {
owner: THIS_MODULE,
open: imu_open,
release: imu_release,
// ioctl: umu_ioctl,
llseek: imu_lseek,
read: imu_read,
write: imu_write
};
static void set_logger_params(int which){ // 1 - program IOPINS, 2 - reset first, 4 - set divisor, 8 set regs, 16 - set period
// IMU should be enable through i2c before opening
D(int i2c_err=0;)
int i,j,b,f,n;
int nmea_sel[16];
int nmea_fpga_frmt[16];
unsigned long d;
unsigned long * period= (unsigned long *) &wbuf[X313_IMU_PERIOD_OFFS];
unsigned long * divisor= (unsigned long *) &wbuf[X313_IMU_DIVISOR_OFFS];
unsigned long * rs232_div= (unsigned long *) &wbuf[X313_IMU_RS232DIV_OFFS];
unsigned long * config= (unsigned long *) &wbuf[X313_IMU_CONFIGURE_OFFS];
unsigned long * message= (unsigned long *) &wbuf[X313_IMU_MESSAGE_OFFS];
char * nmea_format= (char *) &wbuf[X313_IMU_NMEA_FORMAT_OFFS];
D(for (i=0; i< sizeof (wbuf); i++ ) { if ((i & 0x1f)==0) printk("\n %03x",i); printk(" %02x",(int) wbuf[i]); });
/*
if (which & WHICH_INIT) {
D(printk("Enabling I/O pins for IMU, written 0x%x to 0x%x\n", (int) X313_WA_IOPINS_EN_IMU, (int) X313_WA_IOPINS));
port_csp0_addr[X313_WA_IOPINS] = X313_WA_IOPINS_EN_IMU;
///TODO: add enabling via i2c (bus=1&raw=0x2300&data=0xfe)
}
*/
if (which & WHICH_RESET) {
if (x313_is_dma1_on()!=0) {
D(printk("Stopping DMA\n"));
x313_dma1_stop();
}
D(printk("Resetting logger\n"));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_CONFIGURE_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = IMU_CONF(RST_CONF,1);
}
if (which & WHICH_INIT) {
D(printk("Enabling I/O pins for IMU, written 0x%x to 0x%x\n", (int) X313_WA_IOPINS_EN_IMU, (int) X313_WA_IOPINS));
port_csp0_addr[X313_WA_IOPINS] = X313_WA_IOPINS_EN_IMU;
///TODO: add enabling via i2c (bus=1&raw=0x2300&data=0xfe)
//PCA9500_PP_ADDR
unsigned char i2c_sa= PCA9500_PP_ADDR+((config[0]>>23) & 0xe);
unsigned char enable_IMU=0xfe; // maybe we need to reset it here? bit [1]
#if IS_103695_REV_A
enable_IMU=(((config[0]>>23) & 1)?0xfd:0xff); // bit[0] - reset IMU
#else
enable_IMU=0xfe; // maybe we need to reset it here? bit [1]
#endif
i2c_writeData(1, // int n - bus (0 - to the sensor)
i2c_sa, // unsigned char theSlave,
&enable_IMU, //unsigned char *theData,
1, // int size,
1); // int stop (send stop in the end)
D(printk("Sent i2c command in raw mode - address=0x%x, data=0x%x, result=0x%x\n",(int)i2c_sa, (int) enable_IMU, i2c_err));
}
if (which & WHICH_RESET_SPI) {
D(printk("stopped IMU logger (set period=0)\n"));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_PERIOD_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = 0; // reset IMU
}
if (which & WHICH_DIVISOR) {
D(printk("IMU clock divisor= %ld\n", divisor[0]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_DIVISOR_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = divisor[0]-1;
}
if (which & WHICH_RS232DIV) {
D(printk("RS232 clock divisor= %ld\n", rs232_div[0]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_RS232DIV_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = rs232_div[0]-1;
}
if (which & WHICH_NMEA) {
for (i=0;i<16;i++) {
nmea_sel[i]=0;
nmea_fpga_frmt[i]=0;
}
for (n=0;n<4;n++) {
nmea_format[32*n+27]=0; // just in case
D(printk("Setting NMEA sentence format for $GP%s\n", &nmea_format[32*n]));
D(printk("(0x%x, 0x%x, 0x%x\n",(int) nmea_format[32*n],(int) nmea_format[32*n+1],(int) nmea_format[32*n+2]));
f=0;
for (i=2;i>=0;i--) {
b=nmea_format[32*n+i]; /// first 3 letters in each sentence
D(printk("n=%d, i=%d, b=0x%x\n", n,i,b));
for (j=4; j>=0; j--) {
f<<=1;
if ((b & (1<<j))!=0) f++;
}
}
D(printk("n=%d, f=0x%x\n", n,f));
for (i=0;i<15;i++) if ((f & (1<<i))!=0) nmea_sel[i] |= (1<<n);
f=0;
nmea_fpga_frmt[n*4]=0;
for (i=0; (i<24) && (nmea_format[32*n+3+i]!=0);i++ ) {
b=nmea_format[32*n+3+i];
if ((b=='b') || (b=='B')) f|=(1<<i);
nmea_fpga_frmt[n*4]++;
}
nmea_fpga_frmt[n*4+1]=f & 0xff;
nmea_fpga_frmt[n*4+2]=(f>> 8)&0xff;
nmea_fpga_frmt[n*4+3]=(f>>16)&0xff;
}
D(printk("Selection data is %x%x%x%x%x%x%x%x%x%x%x%x%x%x%x\n", nmea_sel[0],nmea_sel[1],nmea_sel[2],
nmea_sel[3],nmea_sel[4],nmea_sel[5],nmea_sel[6],nmea_sel[7],nmea_sel[8],nmea_sel[9],
nmea_sel[10],nmea_sel[11],nmea_sel[12],nmea_sel[13],nmea_sel[14]));
D(printk("Format data for sentence 1 is %02x %02x %02x %02x\n", nmea_fpga_frmt[ 0],nmea_fpga_frmt[ 1],nmea_fpga_frmt[ 2],nmea_fpga_frmt[ 3]));
D(printk("Format data for sentence 2 is %02x %02x %02x %02x\n", nmea_fpga_frmt[ 4],nmea_fpga_frmt[ 5],nmea_fpga_frmt[ 6],nmea_fpga_frmt[ 7]));
D(printk("Format data for sentence 3 is %02x %02x %02x %02x\n", nmea_fpga_frmt[ 8],nmea_fpga_frmt[ 9],nmea_fpga_frmt[10],nmea_fpga_frmt[11]));
D(printk("Format data for sentence 4 is %02x %02x %02x %02x\n", nmea_fpga_frmt[12],nmea_fpga_frmt[13],nmea_fpga_frmt[14],nmea_fpga_frmt[15]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_NMEA_FORMAT_ADDR;
for (i=0;i<16;i++) {
port_csp0_addr[X313_WA_IMU_DATA] = nmea_sel[i];
D(printk("Loading imu fpga register 0x%x with 0x%x\n", X313_IMU_NMEA_FORMAT_ADDR+i, nmea_sel[i] ));
}
for (i=0;i<16;i++) {
port_csp0_addr[X313_WA_IMU_DATA] = nmea_fpga_frmt[i];
D(printk("Loading imu fpga register 0x%x with 0x%x\n", X313_IMU_NMEA_FORMAT_ADDR+i+16, nmea_fpga_frmt[i] ));
}
}
if (which & WHICH_CONFIG) {
D(printk("Setting configuration= 0x%lx\n", config[0]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_CONFIGURE_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] =(config[0] & 0xffffff); // MSB used for the i2c slave addr of the 10365
}
if (which & WHICH_REGISTERS) {
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_REGISTERS_ADDR;
for (i=X313_IMU_REGISTERS_OFFS; i< X313_IMU_NMEA_FORMAT_OFFS ;i++) {
d=wbuf[i];
D(printk("%d: logging IMU register with 0x%lx\n", (i-X313_IMU_REGISTERS_OFFS+1),d));
port_csp0_addr[X313_WA_IMU_DATA] = d;
}
}
if (which & WHICH_MESSAGE) {
D(printk("Setting odometer message %56s\n", (char *) message));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_MESSAGE_ADDR;
for (i=0; i<(((sizeof(wbuf)-X313_IMU_MESSAGE_OFFS))>>2);i++) {
D(printk("%d: message 4 bytes= 0x%x\n", i+1,(int) message[i]));
port_csp0_addr[X313_WA_IMU_DATA] = message[i];
}
}
// setting IMU SPI period, turning it on
if (which & WHICH_PERIOD) {
D(printk("IMU cycle period= %ld\n", period[0]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_PERIOD_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = period[0];
}
if (which & WHICH_EN_DMA) {
D(printk("Enabling DMA\n"));
/*!
TODO: (re)start DMA1 here !
*/
/// for now - init everything again?
if (x313_is_dma1_on()!=0) {
D(printk("Stopping DMA\n"));
x313_dma1_stop();
}
x313_dma1_init();
x313_dma1_start();
}
if (which & WHICH_EN_LOGGER) {
D(printk("Enabling logger\n"));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_CONFIGURE_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = IMU_CONF(RST_CONF,0);
}
}
//filp->f_mode & FMODE_WRITE
static int imu_open(struct inode *inode, struct file *filp) {
int p= MINOR(inode->i_rdev);
// int res;
int i;
// loff_t numBytesWritten;
D(printk("imu_open: minor=%x\r\n",p) );
D(printk("filp=%lx\r\n",(unsigned long)filp) );
switch ( p ) {
case IMU_CTL_MINOR:
D1(printk(KERN_NOTICE "IMU_ctl_open\n"));
inode->i_size=sizeof(wbuf);
// nothing more here, after writeing parameters should start imu (and dma), otherwise will use defaults on next open of /dev/imu
break;
case IMU_MINOR :
{
D1(printk(KERN_NOTICE "IMU_open\n"));
inode->i_size=sizeof(wbuf); // only in write mode
/// See if initialization is needed
if (x313_is_dma1_on()==0) {
/// copy defaults
D1(printk(KERN_NOTICE "Initializing IMU\n"));
for (i=0;i<sizeof(wbuf);i++) wbuf[i]=dflt_wbuf[i];
set_logger_params(WHICH_INIT |
WHICH_RESET |
WHICH_RESET_SPI |
WHICH_DIVISOR |
WHICH_RS232DIV |
WHICH_NMEA |
WHICH_CONFIG |
WHICH_REGISTERS |
WHICH_MESSAGE |
WHICH_PERIOD |
WHICH_EN_DMA |
WHICH_EN_LOGGER );
numBytesRead=0;
} else {
D1(printk(KERN_NOTICE "Skipping IMU initialization\n"));
updateNumBytesWritten();
// numBytesWritten= (int) port_csp0_addr[X313_RA_IMU_COUNT]<<6;
if (filp->f_mode & FMODE_WRITE) { // write mode, use global read pointer
// if ((numBytesWritten < numBytesRead) || (numBytesWritten - numBytesRead)>=(CCAM_DMA1_SIZE<<2)) {
if ((numBytesWritten - numBytesRead)>=(CCAM_DMA1_SIZE<<2)) { // there is still a chance to read as much as possible using lseek
// alternatively - open at lower pointer?
D1(printk(KERN_ERR "DMA1 buffer overrun (numBytesWritten=0x%llx, numBytesRead=0x%llx, resetting numBytesRead\n", numBytesWritten, numBytesRead));
numBytesRead=numBytesWritten;
}
//printk("imu opened in R/W mode, (numBytesWritten=0x%x, numBytesRead=0x%x\n", numBytesWritten, numBytesRead);
} else { // read mode, use file pointer as read pointer, start from the latest data
filp->f_pos=numBytesWritten; // there is still a chance to lseek to an earlier position - reopening at the position of the total number of bytes written to the buffer
//printk("imu opened in RDONLY mode, (numBytesWritten=0x%x, numBytesRead=0x%x\n", numBytesWritten, numBytesRead);
}
}
break;
}
default: return -EINVAL;
}
// minors[p]=p;
// filp->private_data = &minors[p];
filp->private_data = (int *) p; // store just minor there
return 0;
}
static int imu_release(struct inode *inode, struct file *filp) {
// int res=0;
int p = MINOR(inode->i_rdev);
switch ( p ) {
case IMU_MINOR :
case IMU_CTL_MINOR:
printk(KERN_NOTICE "Closing IMU device, numBytesWritten=0x%llx, numBytesRead=0x%llx (only global pointer, does not include files opened in read mode)\n", numBytesWritten, numBytesRead);
/*
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_PERIOD_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = 0; // reset IMU
port_csp0_addr[X313_WA_IOPINS] = X313_WA_IOPINS_DIS_IMU;
*/
// minors[p]=0;
break;
default: return -EINVAL;
}
D(printk("imu_release: done\r\n"));
return 0;
}
/*
static int imu_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { // switch by minor
// int res=0;
D(printk("fpga_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
switch (((int *)filp->private_data)[0]) {
case FPGACONF_MINOR_IORW : {// read write FPGA registers
D(printk("fpga_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
if(_IOC_TYPE(cmd) == FPGACONF_GETSTATE) {
return fpga_state;
}
return fpga_io_ioctl (inode, filp, cmd, arg);
}
default:return -EINVAL;
}
}
*/
static ssize_t imu_write(struct file * file, const char * buf, size_t count, loff_t *off) {
unsigned long p=*off;
unsigned long left;
int which=0;
// D(printk("imu_write: ((int *)file->private_data)[0]= %x\r\n",((int *)file->private_data)[0]));
D(printk("imu_write: (int)file->private_data)= %x\r\n",((int)file->private_data)));
// switch (((int *)file->private_data)[0]) {
switch ((int) file->private_data) {
case IMU_MINOR :
case IMU_CTL_MINOR:
if (!file->f_mode & FMODE_WRITE) {
return -EINVAL; // readonly
}
if (p >= sizeof(wbuf)) return -EINVAL; // bigger than all
if( (p + count) > sizeof(wbuf)) { // truncate count
count = sizeof(wbuf) - p;
}
left=count;
if (left==0) return 0;
if (copy_from_user(&wbuf[p], buf, count)) return -EFAULT;
if (p<(X313_IMU_PERIOD_OFFS+4)) which |= WHICH_PERIOD;
if ((p<(X313_IMU_DIVISOR_OFFS+4)) && ((p+count)>X313_IMU_DIVISOR_OFFS)) which |= WHICH_DIVISOR;
if ((p<(X313_IMU_RS232DIV_OFFS+4)) && ((p+count)>X313_IMU_RS232DIV_OFFS)) which |= WHICH_RS232DIV;
// if ((p<(X313_IMU_CONFIGURE_OFFS+4)) && ((p+count)>X313_IMU_CONFIGURE_OFFS)) which |= WHICH_CONFIG;
if ((p<(X313_IMU_CONFIGURE_OFFS+4)) && ((p+count)>X313_IMU_CONFIGURE_OFFS)) which |= WHICH_CONFIG | WHICH_INIT;
if ((p<(X313_IMU_NMEA_FORMAT_OFFS)) && ((p+count)>X313_IMU_REGISTERS_OFFS)) which |= WHICH_REGISTERS;
if ((p<(X313_IMU_MESSAGE_OFFS)) && ((p+count)>X313_IMU_NMEA_FORMAT_OFFS)) which |= WHICH_NMEA;
if ((p+count)>X313_IMU_MESSAGE_OFFS) which |= WHICH_MESSAGE;
// will not add automatic restarts here
set_logger_params(which);
// if (which & WHICH_PERIOD) num_reads=0;
*off+=count;
return count;
default: return -EINVAL;
}
}
static loff_t imu_lseek(struct file * file, loff_t offset, int orig) {
D(printk (" file=%x, offset=%llx (%d), orig=%x\r\n", (int) file, offset,(int) offset, (int) orig));
int p=(int)file->private_data;
switch (p) {
case IMU_MINOR:
case IMU_CTL_MINOR:
switch (orig) {
case SEEK_SET:
file->f_pos = offset;
break;
case SEEK_CUR:
file->f_pos += offset;
break;
case SEEK_END:
//!overload later?
if (offset<=0) {
file->f_pos = sizeof(wbuf) + offset;
} else {
switch (offset) {
case LSEEK_IMU_NEW: // sets file pointer to the last written data TODO: add lseeking to the earliest data?
updateNumBytesWritten();
// numBytesRead=(int) port_csp0_addr[X313_RA_IMU_COUNT]<<6; //numBytesWritten
return file->f_pos;
case LSEEK_IMU_STOP:
D(printk("got LSEEK_IMU_STOP\n"));
set_logger_params(WHICH_RESET |
WHICH_RESET_SPI);
numBytesRead=0;
return file->f_pos;
case LSEEK_IMU_START:
D(printk("got LSEEK_IMU_START\n"));
set_logger_params(WHICH_RESET |
WHICH_RESET_SPI |
WHICH_PERIOD |
WHICH_EN_DMA |
WHICH_EN_LOGGER );
return file->f_pos;
}
/// Add stuff later?
}
break;
default:
printk(KERN_ERR "lseek: invalid orig=%d\n", orig);
return -EINVAL;
}
break;
default:
printk(KERN_ERR "lseek: invalid minor=%d\n", p);
return -EINVAL;
/*
#define LSEEK_IMU_STOP 1 // stop DMA1 and IMU
#define LSEEK_IMU_START 2 // start IMU and DMA1 (do not modify parameters)
*/
}
/** truncate position */
if (file->f_pos < 0) {
printk(KERN_ERR "negative position: minor=%d, file->f_pos=0x%llx\n", p, file->f_pos);
file->f_pos = 0;
return (-EOVERFLOW);
}
/** enable seeking beyond buffer - it now is absolute position in the data stream*/
if ((p==IMU_CTL_MINOR) && (file->f_pos > sizeof(wbuf))) {
printk(KERN_ERR "beyond end: minor=%d, file->f_pos=0x%llx\n", p, file->f_pos);
file->f_pos = sizeof(wbuf);
return (-EOVERFLOW);
}
return (file->f_pos);
}
static ssize_t imu_read(struct file * file, char * buf, size_t count, loff_t *off) {
int err;
unsigned long * sleep;
char *charDMABuf;
int idbg;
// loff_t numBytesWritten; - it is global now, made absolute from the IMU start
loff_t thisNumBytesRead;
reg_dma_rw_stat stat;
reg_bif_dma_r_ch1_stat ch1_stat;
// REG_WR(bif_dma, regi_bif_dma, rw_ch1_addr, exdma_addr);
// switch (((int *)file->private_data)[0]) {
switch ((int)file->private_data) {
case IMU_CTL_MINOR:
// if (*off >= sizeof(wbuf)) return -EINVAL; // bigger than all
if (*off >= sizeof(wbuf)) return 0; // bigger than all
if( (*off + count) > sizeof(wbuf)) { // truncate count
count = sizeof(wbuf) - *off;
}
if (count==0) return 0;
err=copy_to_user(buf, &wbuf[*off], count);
if (err) {
printk(KERN_ERR "0. tried to copy 0x%x bytes to offset 0x%llx, result=0x%x\n", count, *off,err);
return -EFAULT;
}
*off+=count;
return count;
break;
case IMU_MINOR :
updateNumBytesWritten();
thisNumBytesRead=(file->f_mode & FMODE_WRITE)?numBytesRead:*off; // is that needed ("write mode") ?
charDMABuf = (char *) ccam_dma1_buf_ptr;
sleep= (unsigned long *) &wbuf[X313_IMU_SLEEP_OFFS];
// numBytesWritten= (int) port_csp0_addr[X313_RA_IMU_COUNT]<<6;
// if ( thisNumBytesRead > numBytesWritten) thisNumBytesRead-= (IMU_COUNT_OVERFLOW<<6); // may become negative here
/// should we wait for data?
idbg=0;
while ((sleep[0]!=0) && ((numBytesWritten-thisNumBytesRead)<= 64)) { /// last 32 bytes can get stuck in ETRAX dma channel
schedule_usleep(*sleep);
updateNumBytesWritten();
// numBytesWritten= (int) port_csp0_addr[X313_RA_IMU_COUNT]<<6;
// if ( thisNumBytesRead > numBytesWritten) thisNumBytesRead-= (IMU_COUNT_OVERFLOW<<6); // may become negative here
idbg++;
}
if (idbg>0) {
D(printk ("slept %d times (%d usec)\n", idbg, (int) (*sleep * idbg)));
}
//! now read what is available (and required), roll over the buffer (if needed), copy data and advance numReadBytes
int byteIndexRead=thisNumBytesRead & bytePtrMask;
int byteIndexValid=(numBytesWritten-64) & bytePtrMask; // one record less to mitigate data hidden in ETRAX dma buffer
if (byteIndexValid<byteIndexRead) byteIndexValid += (CCAM_DMA1_SIZE<<2);
if (count>(byteIndexValid-byteIndexRead)) count = (byteIndexValid-byteIndexRead);
int leftToRead=count;
int pe=byteIndexRead+leftToRead;
if (pe>(CCAM_DMA1_SIZE<<2)) pe=(CCAM_DMA1_SIZE<<2);
/// copy all (or first part)
err=copy_to_user(buf, &charDMABuf[byteIndexRead], (pe-byteIndexRead));
if (err) {
printk(KERN_ERR "1. tried to copy 0x%x bytes to offset 0x%llx, result=0x%x\n", count, *off,err);
return -EFAULT;
}
// advance pointers
leftToRead -= (pe-byteIndexRead);
thisNumBytesRead+= (pe-byteIndexRead);
///Do we need to copy from the beginning of the buffer?
if (leftToRead>0) {
// err=copy_to_user(buf, &charDMABuf[0], leftToRead);
err=copy_to_user(&buf[pe-byteIndexRead], &charDMABuf[0], leftToRead);
byteIndexRead=0;
}
if (err) {
printk(KERN_ERR "2. tried to copy 0x%x bytes to offset 0x%llx, result=0x%x\n", count, *off,err);
return -EFAULT;
}
thisNumBytesRead+=leftToRead;
stat = REG_RD(dma, regi_dma7, rw_stat);
ch1_stat= REG_RD(bif_dma, regi_bif_dma, r_ch1_stat);
// reg_bif_dma_r_ch1_stat ch1_stat;
// REG_WR(bif_dma, regi_bif_dma, rw_ch1_addr, exdma_addr);
D(printk ("count=0x%x, thisNumBytesRead=0x%llx, numBytesWritten=0x%llx, stat.buf=0x%x, stat.mode=%x, ch1.run=%x ch1.cnt=0x%x\n", (int) count, thisNumBytesRead, numBytesWritten, (int) stat.buf,(int) stat.mode, (int) ch1_stat.run, (int) ch1_stat.cnt ));
//printk(" file->f_mode & FMODE_WRITE=0x%d\n",file->f_mode & FMODE_WRITE);
if (file->f_mode & FMODE_WRITE) numBytesRead=thisNumBytesRead;
// else *off=thisNumBytesRead;
*off=thisNumBytesRead; // always update
if (count<0) {
printk(KERN_ERR "Count is negative ( 0x%x)\n", count);
}
return count;
default:
//printk(" Wrong minor=0x%x\n",((int *)file->private_data)[0]);
printk(KERN_ERR " Wrong minor=0x%x\n",(int)file->private_data);
return -EINVAL;
}
}
static int __init
imu_init(void)
{
// int i;
int res;
res = register_chrdev(IMU_MAJOR, IMU_DRIVER_NAME, &imu_fops);
if(res < 0) {
printk(KERN_ERR "\nimu_init: couldn't get a major number %d.\n ",IMU_MAJOR);
return res;
}
printk(IMU_DRIVER_NAME"- %d\n",IMU_MAJOR);
// for (i=0;i<=IMU_MAXMINOR;i++) minors[i]=0;
init_ccam_dma1_buf_ptr();
return 0;
}
///TODO: it seems we could use a single data descriptor (in LX data segment was limited to 16KB), but let's have minimal changes
//#define DMA_CHUNK 0x4000 // 32-bit words - may increase??
//#define CCAM_DESCR_DATA_NUM (( CCAM_DMA_SIZE / DMA_CHUNK) +1 ) // number of data descriptors
#define CCAM_DESCR1_DATA_NUM (( CCAM_DMA1_SIZE / DMA_CHUNK) +1 ) // number of data descriptors
static dma_descr_data ccam_dma1_descr_data [CCAM_DESCR1_DATA_NUM] __attribute__ ((__aligned__(16)));
static dma_descr_context ccam_dma1_descr_context __attribute__ ((__aligned__(32)));
static int dma1_on=0;
int x313_setDMA1Buffer(void);
unsigned long x313_DMA1_size (void);
/**
* @brief tests if ETRAX DMA1 is running
* @return 1 - DMA is on, 0 - DMA is off
*/
int x313_is_dma1_on(void) {
return dma1_on;
}
/**
* @brief Stop ETRAX DMA1
* @return 0
*/
int x313_dma1_stop(void) {
dma1_on=0;
MD12(printk("==========x313_dma1_stop\n"));
port_csp0_addr[X313_WA_DMACR] = 0x20; // disable DMA1, dot't modify DMA0
EXT_DMA_1_STOP ; /// for testing - no reset DMA after acquisition
udelay(10) ; //?
DMA_RESET( regi_dma7 );
// put here restoring of the .after pointer ?
return 0;
}
/**
* @brief Start ETRAX DMA for the IMU
*/
void x313_dma1_start(void) {
unsigned long dai;
int i = 0;
MD12(printk("----------x313_dma1_start\n"));
DMA_RESET(regi_dma7);
/// need to restore pointers after previous stop DMA - maybe later move there?
for(dai = 0; dai < CCAM_DMA1_SIZE; dai += DMA_CHUNK) { /// DMA_CHUNK==0x4000
if(dai + DMA_CHUNK >= CCAM_DMA1_SIZE) /// last descriptor
ccam_dma1_descr_data[i].after = (char *)virt_to_phys(&ccam_dma1_buf_ptr[CCAM_DMA1_SIZE]);
else /// not the last one
ccam_dma1_descr_data[i].after = (char *)virt_to_phys(&ccam_dma1_buf_ptr[dai + DMA_CHUNK]);
//!TODO: does flush here IS IT STILL NEEDED HERE?
flush_dma_descr( & ccam_dma1_descr_data[i], 0);
i++;
}
DMA_ENABLE(regi_dma7);
port_csp0_addr[X313_WA_DMACR] = 0x20; // disable DMA1, don't modify DMA0
/// NOTE: needs to be here (not in x313_dma1_init) - word width is reset by channel reset !!!
DMA_WR_CMD(regi_dma7, regk_dma_set_w_size4); ///32-bit transfers
/// point to the beginning of the buffer?
ccam_dma1_descr_context.saved_data = (dma_descr_data*)virt_to_phys(&ccam_dma1_descr_data[0]);
ccam_dma1_descr_context.saved_data_buf = ccam_dma1_descr_data[0].buf;
//! need this also?
flush_dma_descr((dma_descr_data*) & ccam_dma1_descr_context, 0);
DMA_START_CONTEXT(regi_dma7, virt_to_phys(&ccam_dma1_descr_context));
EXT_DMA_1_START ;
port_csp0_addr[X313_WA_DMACR] = 0x28; // enable DMA1, don't modify DMA0
dma1_on=1;
}
/*
#define DMA_CHUNK 0x4000 // 32-bit words - may increase??
#define CCAM_DESCR_DATA_NUM (( CCAM_DMA_SIZE / DMA_CHUNK) +1 ) // number of data descriptors
#define CCAM_BYTES_PER_CHUNK (1<<16) // dma buffer bytes per descriptor
#define CCAM_DESCR_PER_CHUNK 1
#define CCAM_CHUNK_PER_DMABUF 302 // no. of 64Kbyte chunks per buffer
#define CCAM_WORDS_PER_DMABUF (CCAM_CHUNK_PER_DMABUF<<14) //32bit words
#define CCAM_BYTES_PER_DMABUF (CCAM_CHUNK_PER_DMABUF<<16)
#define CCAM_DMA_SIZE CCAM_WORDS_PER_DMABUF
#define CCAM_CHUNK_PER_DMA1BUF 16 // no. of 64Kbyte chunks per buffer
#define CCAM_WORDS_PER_DMA1BUF (CCAM_CHUNK_PER_DMA1BUF<<14) //32bit words
#define CCAM_BYTES_PER_DMA1BUF (CCAM_CHUNK_PER_DMA1BUF<<16)
#define CCAM_DMA1_SIZE CCAM_WORDS_PER_DMA1BUF
*/
///dma0 is using external dma 3 (input) with dma channel 9
///dma1 (this) is using external dma 1 (input) with dma channel 7 (shared with async. serial 0, so do not use DMA there!)
unsigned long x313_dma1_init(void) {
dma1_on=0;
int rslt;
reg_dma_rw_cfg cfg = {.en = regk_dma_yes}; // if disabled - will be busy and hang on attemt of DMA_WR_CMD
reg_bif_dma_rw_ch1_ctrl exdma_ctrl = {
.bw = regk_bif_dma_bw32,
.burst_len = regk_bif_dma_burst8, // changed - updated FPGA to use 8-word bursts
.cont = 1, // continuous transfer mode (probably - don't care)
.end_discard = 0, // discard end of burst date (don't care)
.cnt = 0, // transfer counter ignored
.dreq_pin = 2, // use hsh2
.dreq_mode = regk_bif_dma_norm, // normal - active high DREQ from pin (see above)
.tc_in_pin = 0, // don't care - tc pin number
.tc_in_mode = 0, // no tc pin
.bus_mode = regk_bif_dma_master, // bus mode - master
.rate_en = 0 // no rate limiting
};
reg_bif_dma_rw_ch1_addr exdma_addr = {.addr = ( MEM_CSR0_START + 4 ) | MEM_NON_CACHEABLE}; // fpga register 1
reg_bif_dma_rw_pin2_cfg exdma_pin2 = {
.master_ch = 0, // don't care
.master_mode = regk_bif_dma_off, // off
.slave_ch = 0, // don't care
.slave_mode = regk_bif_dma_off // off
};
reg_bif_dma_rw_pin3_cfg exdma_pin3 = {
.master_ch = 1, // ext DMA channel #
.master_mode = regk_bif_dma_dack, // use DACK, active high
.slave_ch = 1, // don't care
.slave_mode = regk_bif_dma_off // off
};
// just in case - free DMA channel (we are only using it here)
crisv32_free_dma(EXTDMA1_RX_DMA_NBR);
printk("Initializing DMA registers for EXTDMA1\n");
MD7(printk("x313_dma1_init(void)"));
D0(printk ("before crisv32_request_dma\n"); udelay (500000));
rslt = crisv32_request_dma(EXTDMA1_RX_DMA_NBR,
"imu data in from fpga",
DMA_VERBOSE_ON_ERROR,
0,
dma_ext1);
D0(printk ("after crisv32_request_dma - result=%d\n",rslt); udelay(500000));
if(rslt) {
printk("failed\n");
crisv32_free_dma(EXTDMA1_RX_DMA_NBR);
printk(KERN_CRIT "Can't allocate external dma port for compressed data in from fpga");
} else { /// dma channel 7 allocated for ext dma 1
/// setup source of hsh2, hsh3
REG_WR(bif_dma, regi_bif_dma, rw_pin2_cfg, exdma_pin2); /// just in case - turn hsh2 off
REG_WR(bif_dma, regi_bif_dma, rw_pin3_cfg, exdma_pin3); /// make hsh3 DACK
/// Configure ext DMA 3
REG_WR(bif_dma, regi_bif_dma, rw_ch1_ctrl, exdma_ctrl);
REG_WR(bif_dma, regi_bif_dma, rw_ch1_addr, exdma_addr);
REG_WR(dma, regi_dma7, rw_cfg, cfg); /// DMA configuration (bit 0 - enable, bit 1 - stop) - stopped
}
/// DMABufferLength = 0;
x313_setDMA1Buffer();
return ((unsigned long)virt_to_phys(ccam_dma1_buf_ptr)) | 0x80000000;
}
int x313_setDMA1Buffer(void) {
unsigned long dai;
int i = 0;
EXT_DMA_1_STOP; /// Stop DMA1 (just in case)
for(dai = 0; dai < CCAM_DMA1_SIZE; dai += DMA_CHUNK) { /// DMA_CHUNK==0x4000
ccam_dma1_descr_data[i].buf = (char *)virt_to_phys(&ccam_dma1_buf_ptr[dai]);
ccam_dma1_descr_data[i].intr = 0;
ccam_dma1_descr_data[i].wait = 0;
ccam_dma1_descr_data[i].eol = 0; /// we probably do not need to use eol as the descriptors are linked in a loop anyway
if(dai + DMA_CHUNK >= CCAM_DMA1_SIZE) { ///last descriptor
ccam_dma1_descr_data[i].after = (char *)virt_to_phys(&ccam_dma1_buf_ptr[CCAM_DMA1_SIZE]);
ccam_dma1_descr_data[i].next = (dma_descr_data*)virt_to_phys(&ccam_dma1_descr_data[0]);
} else { /// not the last one
ccam_dma1_descr_data[i].after = (char *)virt_to_phys(&ccam_dma1_buf_ptr[dai + DMA_CHUNK]);
ccam_dma1_descr_data[i].next = (dma_descr_data*)virt_to_phys(&ccam_dma1_descr_data[i + 1]);
}
flush_dma_descr( & ccam_dma1_descr_data[i], 0);
i++;
}
// TODO: make new global parameter?
// set_globalParam (G_CIRCBUFSIZE,CCAM_DMA_SIZE<<2); /// make it adjustable? TODO: initialize with others?
//*********************** TEMPORARY ********************************
MD8(printk ("filling DMA1 buffer with natural numbers - just test \n"));
for(dai = 0; dai < CCAM_DMA1_SIZE; dai++) ccam_dma1_buf_ptr[dai] = dai;
return 0;
}
module_init(imu_init);
MODULE_LICENSE("GPLv3");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(IMU_MODULE_DESCRIPTION);
void x313_dma1_start(void);
int x313_dma1_stop(void);
int x313_is_dma1_on(void);
unsigned long x313_dma1_init(void);
......@@ -72,12 +72,12 @@
#define CONFIG_ETRAX_ELPHEL_MT9X001 1
void x313_dma_stop() {}
void x313_dma_init() {}
void reset_compressor() {}
void i2c_run(void) {}
void i2c_stop_wait(void){}
//pgm_functions:pgm_detect_sensor
// void x313_dma_stop() {}
// void x313_dma_init() {}
// void reset_compressor() {} // available in sensor_common (make sure it does it all
void i2c_run(void);
void i2c_stop_wait(void);
// if ((gtable= get_gamma_fpga(color))) fpga_table_write_nice (CX313_FPGA_TABLES_GAMMA + (color * 256), 256, gtable);
......
......@@ -682,12 +682,12 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
///< @return 0 - OK, negative - error
{
unsigned long flags; // this function uses software i2c operations - they need to have interrupts (and hardware i2c off)
// unsigned long flags; // this function uses software i2c operations - they need to have interrupts (and hardware i2c off)
// unsigned char i2c_read_data[2]; // each two bytes - one short word, big endian
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;
u32 chipver_reg=P_MT9X001_CHIPVER;
// u32 chipver_reg=P_MT9X001_CHIPVER;
int sensor_subtype=0;
int i;
struct sensor_t * psensor; // current sensor
......@@ -753,15 +753,15 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
#else
X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_MT9X001_CHIPVER, &i2c_read_dataw);
if (((i2c_read_dataw ^MT9M001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9M001 1280x1024 sensor, chip ID=%x\r\n",I2C_READ_DATA16(0));
printk("Found MT9M001 1280x1024 sensor, chip ID=%x\r\n",i2c_read_dataw);
psensor= &mt9m001;
sensor_subtype=MT9M_TYP; //1;
} else if (((i2c_read_dataw ^ MT9D001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9D001 1600x1200 sensor, chip ID=%x\r\n",I2C_READ_DATA16(0));
printk("Found MT9D001 1600x1200 sensor, chip ID=%x\r\n",i2c_read_dataw);
psensor= &mt9d001;
sensor_subtype=MT9D_TYP; //2;
} else if (((i2c_read_dataw ^ MT9T001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9T001 2048x1536 sensor, chip ID=%x\r\n",I2C_READ_DATA16(0));
printk("Found MT9T001 2048x1536 sensor, chip ID=%x\r\n",i2c_read_dataw);
psensor= &mt9t001;
sensor_subtype=MT9T_TYP; //3;
// if(d[2] == 0x01) - MT9T001 chip rev 01 - color gains had a bug
......@@ -785,7 +785,7 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
add_sensor_proc(onchange_triggermode, &mt9x001_pgm_triggermode); // program sensor trigger mode
add_sensor_proc(onchange_sensorregs, &mt9x001_pgm_sensorregs); // write sensor registers (only changed from outside the driver as they may have different latencies)?
// MDD1(printk("sensor->sensorType=0x%lx\n", sensor->sensorType));
setFramePar(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
// MDD1(printk("\n"));
///TODO: Fill G_MULTI_REGSM+i - which registers need individual values in multi-sensor applications
......@@ -840,11 +840,13 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
// unsigned long flags; // this function uses software i2c operations - they need to have interrupts (and hardware i2c off)
struct frameparspair_t pars_to_update[258+(MAX_SENSORS * P_MULTI_NUMREGS )]; // for all the sensor registers. Other P_* values will reuse the same ones
int first_sensor_i2c;
unsigned short * sensor_register_overwrites;
MDF4(printk(" frame8=%d\n",frame8));
if (frame16 >= 0) return -1; // should be ASAP
// int fpga_addr=(frame8 <0) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame8);
unsigned long flags; // this function uses software i2c operations - they need to have interrupts (and hardware i2c off)
struct frameparspair_t pars_to_update[258+(MAX_SENSORS * P_MULTI_NUMREGS )]; // for all the sensor registers. Other P_* values will reuse the same ones
// unsigned char i2c_read_data[512]; // each two bytes - one short word, big endian
u32 i2c_read_data_dw[256];
int nupdate=0;
......@@ -857,7 +859,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
CCAM_MRST_OFF;
udelay (100);
printk("Reading sensor registers to the shadows:\r\n");
int first_sensor_i2c=sensor->i2c_addr;
first_sensor_i2c=sensor->i2c_addr;
if (GLOBALPARS(sensor_port, G_SENS_AVAIL)) {
first_sensor_i2c+= I2C359_INC * ((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 1)?1:((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 2)?2:3));
}
......@@ -895,9 +897,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
}
#endif
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
printk("Initializing MT9X001 registers with default values:\r\n");
unsigned short * sensor_register_overwrites;
int sensor_register_overwrites_number;
int sensor_subtype=sensor->sensorType - SENSOR_MT9X001;
switch (sensor_subtype) {
......@@ -933,7 +933,11 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
nupdate=0; // Second pass over the registers to set
//#define SET_SENSOR_MBPAR(p,f,s,r,v)
for (i=0; i<sensor_register_overwrites_number;i++ ) { // unconditionally set those registers NOTE: Should be < 63 of them!
SET_SENSOR_MBPAR(sensor_port,frame16,sensor->i2c_addr, sensor_register_overwrites[2*i], sensor_register_overwrites[2*i+1]);
SET_SENSOR_MBPAR(sensor_port,
frame16,
sensor->i2c_addr,
sensor_register_overwrites[2*i],\
sensor_register_overwrites[2*i+1]);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x,0x%x,0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) sensor_register_overwrites[2*i], (int) sensor_register_overwrites[2*i+1]));
}
......@@ -979,7 +983,7 @@ int mt9x001_pgm_window_safe (int sensor_port, ///< sensor port num
///< @return 0 - OK, negative - error
{
MDF4(printk(" frame16=%d\n",frame16));
return mt9x001_pgm_window_common (sensor, thispars, prevpars, frame16);
return mt9x001_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
/** PCommon part of programming sensor WOI */
......@@ -991,11 +995,11 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
int i,dv,dh,bv,bh,ww,wh,wl,wt,flip,flipX,flipY,d, v;
struct frameparspair_t pars_to_update[29];
int nupdate=0;
MDF4(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int i,dv,dh,bv,bh,ww,wh,wl,wt,flip,flipX,flipY,d, v;
int styp = sensor->sensorType & 7;
dh= thispars->pars[P_DCM_HOR];
dv= thispars->pars[P_DCM_VERT];
......@@ -1143,8 +1147,6 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
{
struct frameparspair_t pars_to_update[16]; // maximum 7 registers updated (need to recount)
int nupdate=0;
MDF4(printk(" frame8=%d\n",frame8));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int dh= thispars->pars[P_DCM_HOR];
int ww= thispars->pars[P_SENSOR_PIXH] * dh;
int binning_cost = 0;
......@@ -1158,6 +1160,8 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
uint64_t ull_fp1000s;
#endif
int target_virt_width=(thispars->pars[P_VIRT_KEEP])?(thispars->pars[P_VIRT_WIDTH]):0;
MDF4(printk(" frame8=%d\n",frame8));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
switch(styp) {
case MT9P_TYP: //page 16
width = 2 * ww / (2 * dh);
......@@ -1310,7 +1314,12 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
sclk=thispars->pars[P_CLK_SENSOR] ; ///pixel clock, in Hz
#if USELONGLONG
ull_fp1000s=((long long) 1000)* ((long long) sclk);
#ifdef __div64_32
__div64_32(&ull_fp1000s,pix_period);
#else
do_div(ull_fp1000s,pix_period);
// ull_fp1000s /= pix_period;
#endif
fp1000s= ull_fp1000s;
// fp1000s= ((long long) 1000)* ((long long)sclk) /pix_period;
#else
......@@ -1367,7 +1376,12 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
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));
#if USELONGLONG
ull_exposure= ((long long)(video_exposure * row_time_in_pixels)) * ((long long) 1000000);
#ifdef __div64_32
__div64_32(&ull_exposure, sclk);
#else
do_div(ull_exposure, sclk);
// ull_exposure /= sclk;
#endif
exposure= ull_exposure;
#else
exposure = (100*video_exposure * row_time_in_pixels) / (sclk/10000); // in microseconds
......@@ -1377,8 +1391,15 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
exposure = thispars->pars[P_EXPOS];
#if USELONGLONG
ull_video_exposure= (long long) exposure * (long long) sclk;
#ifdef __div64_32
__div64_32(&ull_video_exposure, row_time_in_pixels);
__div64_32(&ull_video_exposure, 1000000);
#else
do_div(ull_video_exposure, row_time_in_pixels);
do_div(ull_video_exposure, 1000000);
// ull_video_exposure /= row_time_in_pixels;
// ull_video_exposure /= 1000000;
#endif
video_exposure= ull_video_exposure;
#else
///TODO - use shifts, not division where possible?
......@@ -1401,7 +1422,12 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
video_exposure=sensor->maxShutter;
#if USELONGLONG
ull_exposure= ((long long)(video_exposure * row_time_in_pixels)) *((long long) 1000000);
#ifdef __div64_32
__div64_32(&ull_exposure, sclk);
#else
do_div(ull_exposure, sclk);
// ull_exposure /= sclk;
#endif
exposure= ull_exposure;
#else
exposure = (100*video_exposure * row_time_in_pixels) / (sclk/10000); // in microseconds
......@@ -1415,7 +1441,12 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
video_exposure=thispars->pars[P_PERIOD_MAX]/row_time_in_pixels;
#if USELONGLONG
ull_exposure= (((long long) thispars->pars[P_PERIOD_MAX]) *((long long) 1000000));
#ifdef __div64_32
__div64_32(&ull_exposure, sclk);
#else
do_div(ull_exposure, sclk);
// ull_exposure /= sclk;
#endif
exposure= ull_exposure;
#else
exposure = (thispars->pars[P_PERIOD_MAX] * 100) / (sclk/10000); // in microseconds
......@@ -1431,7 +1462,12 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
// schedule updating P_FP1000S if it changed
#if USELONGLONG
ull_fp1000s=((long long) 1000)* ((long long) sclk);
#ifdef __div64_32
__div64_32(&ull_fp1000s,pix_period);
#else
do_div(ull_fp1000s,pix_period);
// ull_fp1000s /= pix_period;
#endif
fp1000s= ull_fp1000s;
#else
fp1000s= 10*sclk/(pix_period/100);
......@@ -1517,14 +1553,19 @@ unsigned long gain_ajust_mt9x001(
MDF4(printk("*newRegGain=0x%lx\n",*newRegGain));
// now divide gains
ull_gain =((long long) gain) << 16;
#ifdef __div64_32
__div64_32(&ull_gain, gainTab[gainIndex]);
#else
do_div(ull_gain, gainTab[gainIndex]);
// ull_gain /= gainTab[gainIndex];
#endif
MDF4(printk("((unsigned long) ull_gain)=0x%lx\n",((unsigned long) ull_gain)));
return ((unsigned long) ull_gain) >> SHIFT_DGAIN;
}
/** Calculates hardware specific analog gains.
* Changed to rounding (was truncaiting)*/
* Changed to rounding (was truncating)*/
inline int gain_mt9x001(int g, ///< gain value (integer, 256 for unity gain)
int maxGain256) ///< maximal supported gain (integer, 256 for unity gain)
///< @return hardware gain value
......@@ -1567,7 +1608,12 @@ inline unsigned long getScale16 (unsigned long nominator, ///< 32-bit nominato
unsigned long * l_result= (unsigned long *) &ull_result;
#endif
MDF4(printk("l_result[1]=0x%lx, l_result[0]=0x%lx\n",l_result[1],l_result[0]));
#ifdef __div64_32
__div64_32(&ull_result, denominator);
#else
do_div(ull_result, denominator);
// ull_result /= denominator;
#endif
MDF4(printk("l_result[1]=0x%lx, l_result[0]=0x%lx\n",l_result[1],l_result[0]));
return (unsigned long) ull_result;
}
......@@ -1594,8 +1640,6 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
{
struct frameparspair_t pars_to_update[38]; // 22+12 needed
int nupdate=0;
MDF4(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
unsigned long newRegGain,digitalGain, testmode;
unsigned long anaGainEn= (thispars->pars[P_GAIN_CTRL]>> GAIN_BIT_ENABLE) & 1;
unsigned long minAnaGain=thispars->pars[P_GAIN_MIN];
......@@ -1603,6 +1647,8 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
unsigned long maxGain;
int limitsModified=0;
int gaingModified=FRAMEPAR_MODIFIED(P_GAING);
MDF4(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
///make sure limits are OK
if (FRAMEPAR_MODIFIED(P_GAIN_MIN)) {
limitsModified=1;
......
......@@ -99,7 +99,8 @@
#include <asm/irq.h>
#include <asm/delay.h>
//#include <asm/delay.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <elphel/c313a.h>
......@@ -116,6 +117,7 @@
//#include "x3x3.h" // hardware definitions
#include "legacy_defines.h" // temporarily
#include "sensor_i2c.h"
#include "clock10359.h"
/**
* \def D(x) optional debug output
......@@ -226,12 +228,12 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
{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));}
#define MULTISENSOR_WRITE_I2C16(port,ra,v) \
{rslt |= multisensor_write_i2c((port),(name_10359),(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));}
#define MULTISENSOR_WRITE_I2C32(port,ra,v) \
{rslt |= multisensor_write_i2c((port),(name_10359),(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)); \
rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(ra),(v) & 0xffff,2) ; \
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)); \
}
#endif
......@@ -306,9 +308,9 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
//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);
//int multisensor_write_i2c(unsigned char theSlave, unsigned char theRegister, unsigned long theData, int size);
int multisensor_write_i2c(int sensor_port, const char * class_name,int sa7_offs, u32 reg_addr, u32 reg_data);
int multisensor_write_i2c (int sensor_port, const char * class_name,int sa7_offs, u32 reg_addr, u32 reg_data);
int multisensor_pgm_multisens (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int multisensor_pgm_sensorphase (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int multisensor_set_freq (int sensor_port, int first, struct framepars_t * thispars);
......@@ -960,37 +962,43 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
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 );
setFramePar(thispars, P_SENSOR, sensor->sensorType);
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType);
return -1;
}
printk("10359 bitstream version =0x%08lx\n",bitstream_version);
// now set sensor clock in both system board and 10359A to 96MHz - currently we support only 5MPix in thias mode
setFramePar(thispars, P_CLK_FPGA, getClockFreq(0)); // just in case - read the actual fpga clock frequency and store it (no actions)
setFramePar(thispars, P_CLK_SENSOR, 96000000);
setClockFreq(1, thispars->pars[P_CLK_SENSOR]);
#ifdef NC353
setFramePar(sensor_port, thispars, P_CLK_FPGA, getClockFreq(0)); // just in case - read the actual fpga clock frequency and store it (no actions)
setFramePar(sensor_port, thispars, P_CLK_SENSOR, 96000000);
setClockFreq(sensor_port, 1, thispars->pars[P_CLK_SENSOR]);
#endif
printk("10353 sensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]);
udelay (100);// 0.0001 sec to stabilize clocks
X3X3_RSTSENSDCM; // FPGA DCM can fail after clock change, needs to be reset
X3X3_SENSDCM_CLK2X_RESET; // reset pclk2x DCM also
// reset system and SDRAM DCMs on 10359
MULTISENSOR_WRITE_I2C16(sensor_port,I2C359_DCM_SYSTEM, I2C359_DCM_RESET | I2C359_DCM_RESET90);
MULTISENSOR_WRITE_I2C16(sensor_port,I2C359_DCM_SDRAM, I2C359_DCM_RESET | I2C359_DCM_RESET90);
multisensor_initSDRAM(thispars); // init 10359 SDRAM
multisensor_initSDRAM(sensor_port, thispars); // init 10359 SDRAM
rslt=0;
// TODO: read other?
// MULTISENSOR_WRITE_I2C16_SHADOW(I2C359_I2CMUX, I2C359_I2CMUX_2MEM);
//TODO: Is it needed for NC393?
#ifdef NC353
if (rslt!=0) { // select memory/clock i2c bus
printk ("10359A did not respond after changing 10353 sensor clock frequency to 96MHz\n");
setFramePar(thispars, P_CLK_SENSOR, 20000000);
setFramePar(sensor_port, thispars, P_CLK_SENSOR, 20000000);
setClockFreq(1, thispars->pars[P_CLK_SENSOR]);
printk("10353 sensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]);
udelay (50000);// 0.05 sec to stabilize clocks
setFramePar(thispars, P_SENSOR, sensor->sensorType);
mdelay (50);// 0.05 sec to stabilize clocks
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
return -1;
}
rslt=multisensor_set_freq (1, thispars); // first time (1)
#endif
rslt=multisensor_set_freq (sensor_port, 1, thispars); // first time (1)
if (rslt>0) printk("10359A sensor clock set to %d\n", rslt);
else if (rslt==0) printk("10359A sensors are using 10353 system clock, as set in configuration\n");
else printk("10359 sensor clock failure, will use system clock from 10353 board\n");
......@@ -1031,21 +1039,21 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
GLOBALPARS(sensor_port,G_SENS_AVAIL) &= (1<< (GLOBALPARS(sensor_port,G_SENS_AVAIL)))-1; // remove flag used to indicate sensor detection functions that they need to initialize multisesnor registers
if (GLOBALPARS(sensor_port,G_SENS_AVAIL)==0) {
printk ("No supported sensors connected to 10359A board\n");
setFramePar(thispars, P_SENSOR, sensor->sensorType);
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
return 0;
}
printk ("Setting internal HACT generation\n");
MULTISENSOR_WRITE_I2C16_SHADOW(sensor_port, I2C359_HACT_MODE, 7);
// 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, 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++) {
// MDF(printk("i=%d, m=0x%lx\n",i,GLOBALPARS(G_MULTI_REGSM+i)));
// }
initMultiPars(); // 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)
// MDF24(printk(" before: sensorproc_phys->sensor.sensorDelay=0x%x\n", sensorproc_phys->sensor.sensorDelay));
copy_sensorproc(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));
// Now calculate phases, swap ones from the sensor
......@@ -1397,16 +1405,19 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
int thisPhase1= thispars->pars[P_MULTI_PHASE1];
int thisPhase2= thispars->pars[P_MULTI_PHASE2];
int thisPhase3= thispars->pars[P_MULTI_PHASE3];
uint64_t ull_result = 1000000000000LL;
if (frame16 >= 0) return -1; // can only work in ASAP mode
//changed (just set) clock frequency initiates calculation of phase settings
if (!multi_phases_initialized || (thispars->pars[P_CLK_SENSOR] != prevpars->pars[P_CLK_SENSOR])) { // system clock is already set to the new frequency
if (thispars->pars[P_CLK_SENSOR] == prevpars->pars[P_CLK_SENSOR]) {
printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__); printk ("WARNING: ((thispars->pars[P_CLK_SENSOR] == prevpars->pars[P_CLK_SENSOR])) but multi_phases_initialized is not yet set (re-init?)\n");
}
multisensor_set_freq (0, thispars); // not the first time. Assuming no clock chip if clock4 is not set
multisensor_set_freq (sensor_port, 0, thispars); // not the first time. Assuming no clock chip if clock4 is not set
reset=1;
// TODO: put here calculation of the sensor phases in 10359 from bitstream data and clock rate
clk_period= 1000000000000.0/thispars->pars[P_CLK_SENSOR]; // period in ps
// clk_period= 1000000000000.0f/thispars->pars[P_CLK_SENSOR]; // period in ps
do_div(ull_result,thispars->pars[P_CLK_SENSOR]);
clk_period= ull_result;
// Now for each of 3 sensor ports of the 10359
cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C1);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P1);
......@@ -1431,7 +1442,7 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
if (reset) {
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_DCM_SYSTEM, I2C359_DCM_RESET | I2C359_DCM_RESET90);
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_DCM_SDRAM, I2C359_DCM_RESET | I2C359_DCM_RESET90);
multisensor_initSDRAM(thispars); // init 10359 SDRAM
multisensor_initSDRAM(sensor_port, thispars); // init 10359 SDRAM
}
if ((thisPhaseSDRAM != prevpars->pars[P_MULTI_PHASE_SDRAM]) || adjustSDRAMNeed) {
if (adjustSDRAMNeed || (thisPhaseSDRAM & 0x200000)) { // at boot, after frequency change or manually requested (0x200000)
......@@ -1508,15 +1519,15 @@ int multisensor_set_freq (int sensor_port, ///< sensor port numb
int was_sensor_freq=0;
if (!(GLOBALPARS(sensor_port, G_MULTI_CFG) && (1<<G_MULTI_CFG_SYSCLK))) { // skip local clock if disabled in configuration
// was_sensor_freq=getClockFreq(I2C359_CLK_NUMBER);
was_sensor_freq=x393_getClockFreq(I2C359_CLK_NUMBER & 3); // clock 0
was_sensor_freq=x393_getClockFreq(sensor_port, I2C359_CLK_NUMBER & 3); // clock 0
if (first || (was_sensor_freq !=0)) { // Otherwise it is likely rev 0 - no clock
// was_sensor_freq=getClockFreq(1);
was_sensor_freq=90000000; // TODO: Find out how to read actual clock frequency for sensor ports
// i=setClockFreq(I2C359_CLK_NUMBER, was_sensor_freq);
i=x393_setClockFreq(I2C359_CLK_NUMBER & 3, was_sensor_freq);
i=x393_setClockFreq(sensor_port, I2C359_CLK_NUMBER & 3, was_sensor_freq);
if (i>0) {
MULTISENSOR_WRITE_I2C16_SHADOW(sensor_port, I2C359_CLKSRC, I2C359_CLKSRC_LOCAL);
udelay (50000); // 0.05 sec to stabilize clocks - will miss multiple frames
mdelay (50); // 0.05 sec to stabilize clocks - will miss multiple frames
} else {
was_sensor_freq=-1; // error
}
......@@ -1713,7 +1724,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
int results90 [4];
int i;
int oldPhase=0;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, 0, oldPhase); // reset SDRAM phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, 0, oldPhase); // reset SDRAM phase
if (oldPhase<0) return oldPhase; // failed to reset
int needReset=0;
int ok90=0;
......@@ -1722,7 +1733,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
int high90=-1;
int low_l, low_h, high_l,high_h;
for (i=0; i<4; i++) {
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, i<<16, oldPhase); // do not reset SDRAM phase - no fine tuning
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, i<<16, oldPhase); // do not reset SDRAM phase - no fine tuning
if (oldPhase<0) return oldPhase; // any error is fatal here
results90 [i]=multisensor_memphase (sensor_port,&centroids90[i]);
if (results90 [i]==0) {
......@@ -1777,12 +1788,12 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
#define I2C359_DCM_ERR_OVFL 3
#define I2C359_DCM_ERR_NODONE 4
#define I2C359_DCM_ERR_NOLOCKED 5*/
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, (low90<<16), oldPhase); // reset dcm, set 90-degree phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, (low90<<16), oldPhase); // reset dcm, set 90-degree phase
if (oldPhase<0) return oldPhase; // any error is fatal here - fine phase is 0
needReset=0;
while ((low_h-low_l)>1) {
i=(low_l+low_h)/2;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
needReset=1;
......@@ -1802,12 +1813,12 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
high_l= 0;
high_h= maxAdjust;
}
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, (high90<<16), oldPhase); // reset dcm, set 90-degree phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, (high90<<16), oldPhase); // reset dcm, set 90-degree phase
if (oldPhase<0) return oldPhase; // any error is fatal here - fine phase is 0
needReset=0;
while ((high_h-high_l)>1) {
i=(high_h+high_l)/2;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
needReset=1;
......@@ -1823,7 +1834,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
if (high90==low90) { // 0,1 OK phases
if (high_l>low_h) { // 0,1 OK phases
i= (high90<<16) | (((high_l+low_h)>>1) & 0xffff);
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
if (oldPhase<0) return oldPhase;
// Verify that final phase is OK
if (multisensor_memphase (sensor_port,NULL)==0) return i;
......@@ -1844,12 +1855,12 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
low90=high90;
low_l= -maxAdjust;
low_h= 0;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, (low90<<16), oldPhase); // reset dcm, set 90-degree phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, (low90<<16), oldPhase); // reset dcm, set 90-degree phase
if (oldPhase<0) return oldPhase; // any error is fatal here - fine phase is 0
needReset=0;
while ((low_h-low_l)>1) {
i=(low_l+low_h)/2;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
needReset=1;
......@@ -1865,12 +1876,12 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
high90=low90;
high_l= 0;
high_h= maxAdjust;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, (high90<<16), oldPhase); // reset dcm, set 90-degree phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, (high90<<16), oldPhase); // reset dcm, set 90-degree phase
if (oldPhase<0) return oldPhase; // any error is fatal here - fine phase is 0
needReset=0;
while ((high_h-high_l)>1) {
i=(high_h+high_l)/2;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
needReset=1;
......@@ -1886,7 +1897,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
MDF24 (printk("Re-measured to the same 90-degree phase low90=%d, low=%d, high90=%d, high=%d\n",low90,low_h,high90,high_l));
if (high_l>low_h) { // 0,1 OK phases
i= (high90<<16) | (((high_l+low_h)>>1) & 0xffff);
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
return oldPhase; // (both >=0 or error (<0)
} else { // something strange - should not get here
printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);
......@@ -2041,7 +2052,7 @@ int multisensor_pgm_sensorregs (int sensor_port, ///< sensor port
thispars->mod32=0;
}
// Now proceed with physical sensor(s) i2c registers - both broadcast and individual
if (sensorproc_phys->pgm_func[onchange_sensorregs+32]) return sensorproc_phys->pgm_func[onchange_sensorregs+32] (sensor, thispars, prevpars, frame16);
if (sensorproc_phys->pgm_func[onchange_sensorregs+32]) return sensorproc_phys->pgm_func[onchange_sensorregs+32] (sensor_port, sensor, thispars, prevpars, frame16);
return 0; // physical sensor function does not exist
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -40,16 +40,18 @@
#include "framepars.h"
#include "sensor_common.h"
//#include "pgm_functions.h"
#include "pgm_functions.h"
#include "circbuf.h"
#include "exif393.h"
//#include "histograms.h"
//#include "gamma_tables.h"
#include "histograms.h"
#include "gamma_tables.h"
#include "quantization_tables.h"
#include "x393_macro.h"
//#include "x393.h"
#include "x393.h"
#include "x393_helpers.h"
#include <asm/delay.h> // just for usleep1000()
/** @brief Driver name to display in log messages.*/
#define IMAGEACQ_DRIVER_NAME "Elphel (R) Model 393 Image Acquisition device driver"
......@@ -67,6 +69,18 @@ struct jpeg_ptr_t {
volatile unsigned int flags;
};
// just temporarily
void i2c_run(void) {}
void i2c_stop_wait(void){}
void udelay1000(int ms)
{
int i;
for (i=0;i<ms;i++) udelay(1000);
}
/** @brief Contains private data for the image acquisition driver */
struct image_acq_pd_t {
int minor; ///< Driver minor number
......@@ -410,26 +424,31 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr)
inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, struct interframe_params_t* interframe) {
unsigned char short_buff[2];
unsigned int sensor_port = jptr->chn_num;
int index_time = jptr->jpeg_wp - 11; if (index_time<0) index_time+=get_globalParam (sensor_port, G_CIRCBUFSIZE)>>2;
int index_time = jptr->jpeg_wp - 11;
char time_buff[27];
char * exif_meta_time_string;
int global_flips, extra_flips;
unsigned char orientations[]="1638274545273816";
unsigned char orientation_short[2];
int maker_offset;
if (index_time<0) index_time+=get_globalParam (sensor_port, G_CIRCBUFSIZE)>>2;
// struct exif_datetime_t
// calculates datetime([20] and subsec[7], returns pointer to char[27]
char time_buff[27];
char * exif_meta_time_string=encode_time(time_buff, ccam_dma_buf_ptr[sensor_port][index_time], ccam_dma_buf_ptr[sensor_port][index_time+1]);
exif_meta_time_string=encode_time(time_buff, ccam_dma_buf_ptr[sensor_port][index_time], ccam_dma_buf_ptr[sensor_port][index_time+1]);
// may be split in datetime/subsec - now it will not notice missing subseq field in template
write_meta_irq(sensor_port, exif_meta_time_string, &meta_offsets.Photo_DateTimeOriginal, Exif_Photo_DateTimeOriginal, 27);
write_meta_irq(sensor_port, exif_meta_time_string, &meta_offsets.Image_DateTime, Exif_Image_DateTime, 20); // may use 27 if room is provided
putlong_meta_irq(sensor_port, get_imageParamsThis(sensor_port, P_EXPOS), &meta_offsets.Photo_ExposureTime, Exif_Photo_ExposureTime);
putlong_meta_irq(sensor_port, get_imageParamsThis(sensor_port, P_FRAME), &meta_offsets.Image_ImageNumber, Exif_Image_ImageNumber);
//Exif_Photo_MakerNote
int global_flips=(get_imageParamsThis(sensor_port, P_FLIPH) & 1) | ((get_imageParamsThis(sensor_port, P_FLIPV)<<1) & 2);
int extra_flips=0;
global_flips=(get_imageParamsThis(sensor_port, P_FLIPH) & 1) | ((get_imageParamsThis(sensor_port, P_FLIPV)<<1) & 2);
extra_flips=0;
if (get_imageParamsThis(sensor_port, P_MULTI_MODE)!=0) {
extra_flips=get_imageParamsThis(sensor_port, P_MULTI_MODE_FLIPS);
global_flips=extra_flips & 3;
}
unsigned char orientations[]="1638274545273816";
unsigned char orientation_short[2];
orientation_short[0]=0;
orientation_short[1]=0xf & orientations[(get_imageParamsThis(sensor_port, P_PORTRAIT)&3) | (global_flips<<2)];
write_meta_irq(sensor_port, orientation_short, &meta_offsets.Image_Orientation, Exif_Image_Orientation, 2);
......@@ -441,7 +460,6 @@ inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, struct interframe_params_t*
write_meta_irq(sensor_port, short_buff, &meta_offsets.PageNumber, Exif_Image_PageNumber, 2);
//TODO - use memcpy
int maker_offset;
maker_offset=putlong_meta_irq(sensor_port, get_imageParamsThis(sensor_port, P_GAINR), &meta_offsets.Photo_MakerNote, Exif_Photo_MakerNote);
if (maker_offset>0) {
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_GAING), maker_offset+4);
......@@ -660,8 +678,8 @@ void tasklet_fpga_function(unsigned long arg) {
subchn,
prevFrameNumber,
(1 << COLOR_Y_NUMBER),
hash32p+hist_indx*16*(sizeof u32),
framep+hist_indx*32*(sizeof u32)); // 0x2 Green1
hash32p+hist_indx*16*sizeof (u32),
framep+hist_indx*32*sizeof (u32)); // 0x2 Green1
} else {
set_histograms (sensor_port, subchn, prevFrameNumber, (1 << COLOR_Y_NUMBER), hash32p, framep); // 0x2 Green1
}
......@@ -723,8 +741,8 @@ if (hist_en) {
subchn,
prevFrameNumber,
0xf, // all colors
hash32p+hist_indx*16*(sizeof u32),
framep+hist_indx*32*(sizeof u32)); // 0x2 Green1
hash32p+hist_indx*16*sizeof (u32),
framep+hist_indx*32*sizeof (u32)); // 0x2 Green1
} else {
set_histograms (sensor_port, subchn, prevFrameNumber, 0xf, hash32p, framep); // 0x2 Green1
}
......@@ -809,10 +827,10 @@ void camera_interrupts (int on) {
int image_acq_init(struct platform_device *pdev)
{
int i;
int res;
// int res;
unsigned int irq;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
// const struct of_device_id *match;
const char *frame_sync_irq_names[4] = {"frame_sync_irq_0", "frame_sync_irq_1",
"frame_sync_irq_2", "frame_sync_irq_3"};
const char *compressor_irq_names[4] = {"compr_irq_0", "compr_irq_1",
......@@ -915,10 +933,10 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
set_xi2c_wrc(&dev_sensor, sensor_port, dev_sensor.slave7, 0);
}
// Now register one page for reading 10359 and the sensor using sensor speed data
memcpy(&dev_sensor, class_sensor, sizeof(class_sensor));
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE2, 0);
dev_sensor->data_bytes=4; // for reading 10359 in 32-bit mode
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4, 0);
memcpy(&dev_sensor, class_sensor, sizeof(dev_sensor));
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE2);
dev_sensor.data_bytes=4; // for reading 10359 in 32-bit mode
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4);
}
return 0;
}
......
......@@ -121,6 +121,6 @@ long long get_frame_pos(unsigned int chn, unsigned int pos);
#define X3X3_I2C_RCV4(port,sa7,reg,datap) legacy_read_i2c_reg((port),(LEGACY_READ_PAGE4),(sa7),(reg),4,(datap))
int legacy_i2c (int ports);
void udelay1000(int ms);
#endif
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