Commit 1769750d authored by Andrey Filippov's avatar Andrey Filippov

debugging initialization

parent b2b0813b
This diff is collapsed.
......@@ -28,8 +28,11 @@
struct circbuf_priv_t {
int minor; ///< device file minor number
unsigned long *buf_ptr; ///< pointer to circular buffer memory region
unsigned long buf_size; ///< circular region size in bytes
unsigned long buf_size32; ///< circular region size in dwords
dma_addr_t phys_addr; ///< physical address of memory region reported by memory driver
};
struct circbuf_priv_t *get_circbuf(int chn); // alternative to use of extern struct circbuf_priv_ptr;
extern struct circbuf_priv_t *circbuf_priv_ptr;
extern wait_queue_head_t circbuf_wait_queue;
......
This diff is collapsed.
......@@ -154,6 +154,9 @@
*/
#define FRAMEPARS_DRIVER_DESCRIPTION "Elphel (R) Model 393 Frame Parameters device driver"
static int hardware_initialized = 0;
/* 393: sFrameParsAll is an array of 4per-port structures */
static struct framepars_all_t sFrameParsAll[SENSOR_PORTS] __attribute__ ((aligned(PAGE_SIZE))); ///< Sensor Parameters, currently 16 pages all and 2048 pages some, static struct
unsigned int frameParsInitialized[SENSOR_PORTS]; // set to 0 at startup, 1 after initialization that is triggered by setParsAtomic()
......@@ -253,12 +256,23 @@ int framepars_mmap(struct file *file, struct vm_area_struct *vma);
/**
* @brief Reset hardware sequencers (i2c, command) and initialize framepars structure
*/
void initSequencers(int sensor_port)
int initSequencers(int sensor_port)
{
FLAGS_IBH
if (!is_fpga_programmed){
dev_err(g_devfp_ptr,"*** Attempted to access hardware without bitsteram ***\n");
return - ENODEV;
}
if (!hardware_initialized) {
dev_dbg(g_devfp_ptr,"Configuring compressor DMA channels\n");
dev_info(g_devfp_ptr,"Configuring compressor DMA channels\n");
init_compressor_dma(0xf, // all channels (TODO: NC393 - select channels in DT or use existing for sesnors?
0); // not to interfere with python setting the same
// 1); // reset all channels (do only once, resetting running DMA may confuse AXI)
hardware_initialized = 1;
dev_dbg(g_devfp_ptr,"%s \n",__func__);
dev_dbg(g_devfp_ptr,"%s : port= %d,initSequencers:resetting both sequencers (not really?)\n",__func__, sensor_port);
}
dev_dbg(g_devfp_ptr,"port= %d,initSequencers:resetting both sequencers (not really?)\n", sensor_port);
#ifdef TEST_DISABLE_CODE
local_irq_save(flags);
X3X3_SEQ_RESET;
......@@ -266,6 +280,7 @@ void initSequencers(int sensor_port)
local_irq_restore(flags);
#endif
initFramePars(sensor_port);
return 0;
}
/** Reset absolute frame number \b thisFrameNumber to \b frame16, optionally reset/restart sequencer */
......@@ -909,7 +924,7 @@ void processPars(int sensor_port, struct sensorproc_t * sensorproc, int frame16,
#endif
}
#else
void processPars(int sensor_port, struct sensorproc_t * sensorproc, int frame16, int maxahead)
int processPars(int sensor_port, struct sensorproc_t * sensorproc, int frame16, int maxahead)
{
FLAGS_IBH
frame16 &= PARS_FRAMES_MASK;
......@@ -922,7 +937,7 @@ void processPars(int sensor_port, struct sensorproc_t * sensorproc, int frame16,
dev_dbg(g_devfp_ptr,"port= %d, frame16=%d, maxahead=%d\n", sensor_port, frame16, maxahead);
if (!sensorproc){
dev_err(g_devfp_ptr,"%s port=%d frame16=%d sensorproc==NULL !!!! \n", __func__, sensor_port, frame16);
return;
return -ENODEV;
}
LOCK_IBH(framepars_locks[sensor_port]);
_processPars(sensor_port, sensorproc, frame16, maxahead);
......@@ -1013,7 +1028,7 @@ int setFrameParsAtomic(int sensor_port, ///< sensor port number (0
///< @return 0 - OK, -ERR_FRAMEPARS_TOOEARLY, -ERR_FRAMEPARS_TOOLATE
{
FLAGS_IBH
int npar, nframe;
int npar, nframe, res;
unsigned long val, bmask, bmask32;
int index, bindex;
struct framepars_t *framepars = aframepars[sensor_port];
......@@ -1029,7 +1044,8 @@ int setFrameParsAtomic(int sensor_port, ///< sensor port number (0
//int klog393_ts(const char * str);
if (!frameParsInitialized[sensor_port]) {
initSequencers(sensor_port); // Will call initFramePars(); and initialize functions
res = initSequencers(sensor_port); // Will call initFramePars(); and initialize functions
if (res <0) return res;
}
LOCK_IBH(framepars_locks[sensor_port]);
PROFILE_NOW(5); // Was 6, but no 7 in NC393
......@@ -1465,6 +1481,7 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig)
struct framepars_pd * privData = (struct framepars_pd*) file -> private_data;
int sensor_port = privData -> minor - DEV393_MINOR(DEV393_FRAMEPARS0);
sec_usec_t sec_usec;
int res;
// struct framepars_t *framepars = aframepars[sensor_port];
dev_dbg(g_devfp_ptr, "(framepars_lseek) offset=0x%x, orig=0x%x, sensor_port = %d\n", (int)offset, (int)orig, sensor_port);
MDP(DBGB_FFOP, sensor_port, "(framepars_lseek) offset=0x%x, orig=0x%x\n", (int)offset, (int)orig)
......@@ -1498,7 +1515,8 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig)
switch (offset) {
case LSEEK_GET_FPGA_TIME:
//X313_GET_FPGA_TIME( GLOBALPARS(G_SECONDS), GLOBALPARS(G_MICROSECONDS) );
get_fpga_rtc(&sec_usec);
if (!get_fpga_rtc(&sec_usec))
return - ENODEV;
GLOBALPARS(sensor_port,G_SECONDS) = sec_usec.sec;
GLOBALPARS(sensor_port,G_MICROSECONDS) = sec_usec.usec;
dev_dbg(g_devfp_ptr, "LSEEK_GET_FPGA_TIME: sec=%ld, usec=%ld\n", sec_usec.sec, sec_usec.usec);
......@@ -1507,13 +1525,17 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig)
//X313_SET_FPGA_TIME( GLOBALPARS(G_SECONDS) , GLOBALPARS(G_MICROSECONDS) );
sec_usec.sec = GLOBALPARS(sensor_port,G_SECONDS);
sec_usec.usec = GLOBALPARS(sensor_port,G_MICROSECONDS);
set_fpga_rtc(sec_usec);
res = set_fpga_rtc(sec_usec);
if (res <0){
return - ENODEV;
}
dev_dbg(g_devfp_ptr, "LSEEK_SET_FPGA_TIME: sec=%ld, usec=%ld\n", sec_usec.sec, sec_usec.usec);
break;
case LSEEK_FRAMEPARS_INIT: // reset hardware sequencers, init framepars structure
dev_dbg(g_devfp_ptr, "LSEEK_FRAMEPARS_INIT\n");
initGlobalPars(sensor_port); // reset all global parameters but the first 32
initSequencers(sensor_port);
res = initSequencers(sensor_port);
if (res <0) return res;
break;
case LSEEK_FRAME_RESET: // reset absolute frame number to avoid integer frame number overflow
dev_dbg(g_devfp_ptr, "LSEEK_FRAME_RESET\n");
......@@ -1522,7 +1544,8 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig)
case LSEEK_SENSORPROC: // process modified parameters in frame 0 (to start sensor detection)
dev_dbg(g_devfp_ptr, "LSEEK_SENSORPROC: aframepars[%d][0].functions=0x%08lx\n",
sensor_port, aframepars[sensor_port][0].functions);
processPars(sensor_port, &asensorproc[sensor_port], 0, PARS_FRAMES); //frame0, all 8 frames (maxAhead==8)
res = processPars(sensor_port, &asensorproc[sensor_port], 0, PARS_FRAMES); //frame0, all 8 frames (maxAhead==8)
if (res <0) return res;
break;
case LSEEK_DMA_INIT: // initialize ETRAX DMA (normally done in sensor_common.c at driver init
dev_dbg(g_devfp_ptr, "LSEEK_DMA_INIT\n");
......@@ -1620,11 +1643,14 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff
//X313_SET_FPGA_TIME( GLOBALPARS(G_SECONDS) , GLOBALPARS(G_MICROSECONDS) );
sec_usec.sec = GLOBALPARS(sensor_port,G_SECONDS);
sec_usec.usec = GLOBALPARS(sensor_port,G_MICROSECONDS);
set_fpga_rtc(sec_usec);
result = set_fpga_rtc(sec_usec);
if (result <0)
return result;
break;
case FRAMEPARS_GETFPGATIME: //ignore value, set frame 0 G_SECONDS, G_MICROSECONDS to FPGA registers
//X313_GET_FPGA_TIME( GLOBALPARS(G_SECONDS) , GLOBALPARS(G_MICROSECONDS) );
get_fpga_rtc(&sec_usec);
if (!get_fpga_rtc(&sec_usec))
return - ENODEV;
GLOBALPARS(sensor_port,G_SECONDS) = sec_usec.sec;
GLOBALPARS(sensor_port,G_MICROSECONDS) = sec_usec.usec;
break;
......@@ -1722,7 +1748,8 @@ static ssize_t store_this_frame(struct device *dev, struct device_attribute *att
static ssize_t show_fpga_time(struct device *dev, struct device_attribute *attr, char *buf)
{
sec_usec_t sec_usec;
get_fpga_rtc(&sec_usec);
if (!get_fpga_rtc(&sec_usec))
return - ENODEV;
return sprintf(buf,"%lu.%lu\n", sec_usec.sec, sec_usec.usec);
}
......@@ -1736,7 +1763,8 @@ static ssize_t store_fpga_time(struct device *dev, struct device_attribute *attr
sscanf(cp,"%lu",&sec_usec.usec);
for (i=strlen(cp); i<6;i++)
sec_usec.usec *=10;
set_fpga_rtc(sec_usec);
i = set_fpga_rtc(sec_usec);
if (i<0) return i;
} else {
return - EINVAL;
}
......@@ -1848,6 +1876,8 @@ int framepars_init(struct platform_device *pdev)
elphel393_framepars_sysfs_register(pdev);
dev_info(dev, DEV393_NAME(DEV393_FRAMEPARS0)": registered sysfs\n");
g_devfp_ptr = dev;
hardware_initialized = 0;
return 0;
}
......
......@@ -13,7 +13,7 @@ extern wait_queue_head_t aframepars_wait_queue[SENSOR_PORTS];
///TODO: init framepars (zero parameters) before initscripts (not when detecting the sensors) - then initscript will be able to overwrite some
void init_framepars_ptr(int sensor_port);
void initSequencers (int sensor_port); ///Move to sensorcommon? currently it is used through frameparsall file (lseek)
int initSequencers (int sensor_port); ///Move to sensorcommon? currently it is used through frameparsall file (lseek)
void initGlobalPars (int sensor_port); /// resets all global parameters but debug mask (if ELPHEL_DEBUG)
int initMultiPars (int sensor_port); /// initialize structures for individual per-sensor parameters. Now only works for sensor registers using G_MULTI_REGSM. Should be called aftre/during sensor detection
void initFramePars (int sensor_port); ///initialize all parameters, set thisFrameNumber to frame8 (read from hardware, usually 0 after resetting i2c and cmd_seq)
......@@ -67,7 +67,7 @@ void schedule_this_pgm_func (int sensor_port, struct framepars_t * this_fr
//inline void _processParsASAP (int sensor_port, struct sensorproc_t * sensorproc, int frame8);
//inline void _processParsSeq (int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead);
void processPars (int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead);
int processPars (int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead);
///*** TODO: Add option (flag?) to write "single" (like single compress, single sensor) so it will not make all the next frames "single"
int framepars_init (struct platform_device *pdev);
......
......@@ -1055,8 +1055,8 @@ void logger_irq_cmd(int cmd) ///< interrupt command: 0 - nop, 1 - reset, 2 - dis
#ifdef NC353
///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
//#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)));
......@@ -1222,7 +1222,7 @@ int x313_setDMA1Buffer(void) {
i++;
}
// TODO: make new global parameter?
// set_globalParam (G_CIRCBUFSIZE,CCAM_DMA_SIZE<<2); /// make it adjustable? TODO: initialize with others?
// 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++) logger_buffer[dai] = dai;
......
......@@ -581,7 +581,8 @@ static unsigned short mt9t001_inits[]=
/** Register initial writes for MT9P006 */
static unsigned short mt9p001_inits[]=
{
P_MT9X001_OUTCTRL, 0x2, // set slowest output signals (clock and non-clock) to reduce EMI (for FCC part 15)
// P_MT9X001_OUTCTRL, 0x2, // set slowest output signals (clock and non-clock) to reduce EMI (for FCC part 15)
P_MT9X001_OUTCTRL, 0x1f82, // NC393: Restoring default, will adjust later
P_MT9X001_7F , 0x0 // Should be written 0 to prevent blue "blooming" columns
};
/** Specifying sensor registers to be controlled individually in multi-sensor applications, MT9M001 */
......
This diff is collapsed.
......@@ -52,6 +52,7 @@
#include <asm/delay.h> // just for usleep1000()
#include "x393_fpga_functions.h"
// NC393 debug macros
#include "debug393.h"
......@@ -135,7 +136,7 @@ u32 get_compressor_frame(unsigned int chn) ///< Sensor port number (0..3)
/** @brief Works like a cache to time save on looking for tags in the directory (forced to recalculate if does not match)
* will have offset of the Exif_Image_DateTime data in meta page (Exif_Photo_SubSecTime should go immediately after in meta page)
*/
static struct meta_offsets_t {
static struct meta_offsets_t { // Never used even in NC353?
int Image_DateTime; ///< EXIF Date/Time offset
int Photo_DateTimeOriginal; ///< EXIF Date/Time Original offset
int Photo_ExposureTime; ///< EXIF exposure offset
......@@ -158,6 +159,7 @@ void camSeqSetJPEG_rp(int p) {
}
#endif /* TEST_DISABLE_CODE */
/** Write pointer in circbuf, in bytes */
int camseq_get_jpeg_wp(unsigned int chn)
{
return (chn < SENSOR_PORTS) ? image_acq_priv.jpeg_ptr[chn].jpeg_wp : 0;
......@@ -172,8 +174,51 @@ void camseq_set_jpeg_rp(unsigned int chn, int ptr)
{
if (chn < SENSOR_PORTS) {
image_acq_priv.jpeg_ptr[chn].jpeg_rp = ptr;
set_globalParam(chn, G_CIRCBUFRP, ptr);
set_globalParam(chn, G_FREECIRCBUF,
(((get_globalParam(chn, G_CIRCBUFRP) <= get_globalParam(chn, G_CIRCBUFWP))?
get_globalParam(chn, G_CIRCBUFSIZE):0)+ get_globalParam(chn, G_CIRCBUFRP))
- get_globalParam(chn, G_CIRCBUFWP));
}
}
/** Write pointer in circbuf, in DWORDs */
int camSeqGetJPEG_wp(unsigned int chn)
{
return (chn < SENSOR_PORTS) ? image_acq_priv.jpeg_ptr[chn].jpeg_wp : 0;
}
int camSeqGetJPEG_rp(unsigned int chn)
{
return (chn < SENSOR_PORTS) ? image_acq_priv.jpeg_ptr[chn].jpeg_rp : 0;
}
void camSeqSetJPEG_rp(unsigned int chn, ///< channel (0..3)
int ptr) /// DWORD index in the buffer
{
if (chn < SENSOR_PORTS) {
image_acq_priv.jpeg_ptr[chn].jpeg_rp = ptr << 2;
set_globalParam(chn, G_CIRCBUFRP, ptr);
set_globalParam(chn, G_FREECIRCBUF,
(((get_globalParam(chn, G_CIRCBUFRP) <= get_globalParam(chn, G_CIRCBUFWP))?
get_globalParam(chn, G_CIRCBUFSIZE):0)+ get_globalParam(chn, G_CIRCBUFRP))
- get_globalParam(chn, G_CIRCBUFWP));
}
}
#ifdef NC353
void camSeqSetJPEG_rp(int p) {
JPEG_rp=p;
set_globalParam(G_CIRCBUFRP, p<< 2);
set_globalParam(G_FREECIRCBUF,
(((get_globalParam(G_CIRCBUFRP) <= get_globalParam(G_CIRCBUFWP))?
get_globalParam(G_CIRCBUFSIZE):0)+ get_globalParam(G_CIRCBUFRP))
- get_globalParam(G_CIRCBUFWP));
}
#endif
/** Return current frame number, if it was from the compressor interrupt
* get the compressed frame number (updated when compression is over,
* can happen even later than start of the next frame.
......@@ -218,7 +263,7 @@ void tasklet_compressor_function(unsigned long arg);
/**
* @brief Copy #sensorproc structure, needed for multisensor board to be able
* to replace some of the functions
* @param[in] sensor_port sesnolr port number
* @param[in] sensor_port sensor port number
* @param[in] copy pointer to a copy structure
* @return pointer to a \b copy structure
*/
......@@ -345,13 +390,13 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
// dev_dbg(g_dev_ptr, "from updateIRQJPEG_wp: phys_addr = 0x%x, virt_addr = 0x%p\n", phys_addr, virt_addr);
// outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1));
// __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE);
// phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr + CCAM_DMA_SIZE - CHUNK_SIZE;
// virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr + BYTE2DW(CCAM_DMA_SIZE - CHUNK_SIZE);
// phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr + CCAM__DMA_SIZE - CHUNK_SIZE;
// virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr + BYTE2DW(CCAM__DMA_SIZE - CHUNK_SIZE);
// outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1));
// __cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE);
// dev_dbg(g_dev_ptr, "from updateIRQJPEG_wp: phys_addr = 0x%x, virt_addr = 0x%p\n", phys_addr, virt_addr);
// barrier();
// prev_dword = X393_BUFFSUB(DW2BYTE(jptr->jpeg_wp), 4);
// prev_dword = X393__BUFFSUB(DW2BYTE(jptr->jpeg_wp), 4);
// dev_dbg(g_dev_ptr, "circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp] = 0x%x\n", circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp]);
// dev_dbg(g_dev_ptr, "circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)] = 0x%x\n", circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)]);
//// if (circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp] == 0x00 &&
......@@ -418,21 +463,22 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr)
{
dma_addr_t phys_addr;
void *virt_addr;
int chn = jptr->chn_num;
struct interframe_params_t *interframe = NULL;
int len_offset = X393_BUFFSUB(DW2BYTE(jptr->jpeg_wp), CHUNK_SIZE + 4);
int len_offset = X393_BUFFSUB_CHN(DW2BYTE(jptr->jpeg_wp), CHUNK_SIZE + 4, chn);
int jpeg_len = circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(len_offset)] & FRAME_LENGTH_MASK;
int jpeg_start = X393_BUFFSUB(DW2BYTE(jptr->jpeg_wp) - CHUNK_SIZE - INSERTED_BYTES(jpeg_len) - CCAM_MMAP_META, jpeg_len);
int jpeg_start = X393_BUFFSUB_CHN(DW2BYTE(jptr->jpeg_wp) - CHUNK_SIZE - INSERTED_BYTES(jpeg_len) - CCAM_MMAP_META, jpeg_len,chn);
// frame_params_offset points to interframe_params_t area before current frame (this parameters belong to the frame below in memory, not the previous)
int frame_params_offset = BYTE2DW(X393_BUFFSUB(jpeg_start, CHUNK_SIZE));
int prev_len32_off = X393_BUFFSUB(jpeg_start, CHUNK_SIZE + 4);
int frame_params_offset = BYTE2DW(X393_BUFFSUB_CHN(jpeg_start, CHUNK_SIZE, chn));
int prev_len32_off = X393_BUFFSUB_CHN(jpeg_start, CHUNK_SIZE + 4,chn);
int prev_len32 = circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_len32_off)];
if ((prev_len32 & MARKER_FF) != MARKER_FF) {
// try to correct offset
prev_len32_off = X393_BUFFSUB(prev_len32_off, 0x20);
prev_len32_off = X393_BUFFSUB_CHN(prev_len32_off, 0x20,chn);
prev_len32 = circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_len32_off)];
if ((prev_len32 & MARKER_FF) == MARKER_FF) {
frame_params_offset = BYTE2DW(X393_BUFFADD(prev_len32_off, 4));
frame_params_offset = BYTE2DW(X393_BUFFADD_CHN(prev_len32_off, 4, jptr->chn_num));
}
}
......@@ -441,7 +487,7 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr)
interframe->signffff = 0xffff;
/* debug code follows */
set_default_interframe(interframe); // TODO: Production NC393: should be removed?
//set_default_interframe(interframe); // TODO: Production NC393: should be removed?
/* end of debug code */
set_globalParam(jptr->chn_num, G_FRAME_SIZE, jpeg_len);
......@@ -690,24 +736,25 @@ void tasklet_compressor_function(unsigned long arg)
int sensor_port = image_acq_priv.jpeg_ptr[arg].chn_num; // == arg & 3
const struct jpeg_ptr_t *jptr = &image_acq_priv.jpeg_ptr[arg];
unsigned int sz;
u32 ccam_dma_size = circbuf_priv_ptr[jptr->chn_num].buf_size;
/* invalidate L2 cache lines in the beginning of current frame */
phys_addr_start = circbuf_priv_ptr[jptr->chn_num].phys_addr + DW2BYTE(jptr->fpga_cntr_prev);
virt_addr_start = circbuf_priv_ptr[jptr->chn_num].buf_ptr + jptr->fpga_cntr_prev;
sz = DW2BYTE(jptr->fpga_cntr_prev) + L2_INVAL_SIZE;
if (sz < CCAM_DMA_SIZE) {
if (sz < ccam_dma_size) {
phys_addr_end = phys_addr_start + L2_INVAL_SIZE - 1;
outer_inv_range(phys_addr_start, phys_addr_end);
__cpuc_flush_dcache_area(virt_addr_start, L2_INVAL_SIZE);
} else {
phys_addr_end = phys_addr_start + (CCAM_DMA_SIZE - DW2BYTE(jptr->fpga_cntr_prev) - 1);
phys_addr_end = phys_addr_start + (ccam_dma_size - DW2BYTE(jptr->fpga_cntr_prev) - 1);
outer_inv_range(phys_addr_start, phys_addr_end);
__cpuc_flush_dcache_area(virt_addr_start, CCAM_DMA_SIZE - DW2BYTE(jptr->fpga_cntr_prev));
__cpuc_flush_dcache_area(virt_addr_start, ccam_dma_size - DW2BYTE(jptr->fpga_cntr_prev));
phys_addr_start = circbuf_priv_ptr[jptr->chn_num].phys_addr;
phys_addr_end = phys_addr_start + (sz - CCAM_DMA_SIZE - 1);
phys_addr_end = phys_addr_start + (sz - ccam_dma_size - 1);
virt_addr_start = circbuf_priv_ptr[jptr->chn_num].buf_ptr;
outer_inv_range(phys_addr_start, phys_addr_end);
__cpuc_flush_dcache_area(virt_addr_start, sz - CCAM_DMA_SIZE);
__cpuc_flush_dcache_area(virt_addr_start, sz - ccam_dma_size);
}
wake_up_interruptible(&circbuf_wait_queue); // should be done in here (after cache invalidation), not in ISR
}
......@@ -873,6 +920,33 @@ void tasklet_cmdseq_function(unsigned long arg)
//#endif /* TEST_DISABLE_CODE */
int init_compressor_dma(int chn_mask, int reset)
{ int res;
int status_mode = 3;
int report_mode = 0;
int port_afi = 0;
dma_addr_t cmprs_sa[4];
u32 cmprs_len[4];
int chn;
struct circbuf_priv_t * cirbuf_data;
for (chn = 0; chn <4; chn++) if (chn_mask & (1 << chn)){
cirbuf_data = get_circbuf(chn);
cmprs_sa[chn] = cirbuf_data->phys_addr;
cmprs_len[chn] = cirbuf_data->buf_size;
}
res = compressor_dma_setup (port_afi,
chn_mask,
reset,
status_mode,
report_mode,
cmprs_sa[0], cmprs_len[0],
cmprs_sa[1], cmprs_len[1],
cmprs_sa[2], cmprs_len[2],
cmprs_sa[3], cmprs_len[3]);
return res;
}
/**
* @brief resets compressor and buffer pointers
*/
......
......@@ -28,22 +28,32 @@ extern struct sensorproc_t * asensorproc;
//void camSeqSetJPEG_rp(int p);
u32 get_compressor_frame(unsigned int chn);
int getHardFrameNumber(int sensor_port, int use_compressor);
// Byte I/O
int camseq_get_jpeg_wp(unsigned int chn);
int camseq_get_jpeg_rp(unsigned int chn);
void camseq_set_jpeg_rp(unsigned int chn, int ptr);
// DWORD I/O, same as in NC353
int camSeqGetJPEG_wp (unsigned int chn);
int camSeqGetJPEG_rp (unsigned int chn);
void camSeqSetJPEG_rp(unsigned int chn, int ptr);
///CIRCBUF macros
extern unsigned long * ccam_dma_buf_ptr[SENSOR_PORTS];
/* move these lines to x313_macro.h
#define X313_LENGTH_MASK 0xff000000
#define X313_PADDED_FRAME(x)((((x)+67+CCAM_MMAP_META ) >>2) & 0xfffffff8)
#define X313_BUFFSUB(x,y) (((x)>=(y))? ((x)-(y)) : ((x)+ (CCAM_DMA_SIZE-(y))))
#define X313_BUFFADD(x,y) ((((x) + (y))<=CCAM_DMA_SIZE)? ((x) + (y)) : ((x) - (CCAM_DMA_SIZE-(y))))
#define X313_BUFFSUB(x,y) (((x)>=(y))? ((x)-(y)) : ((x)+ (CCAM__DMA_SIZE-(y))))
#define X313_BUFFADD(x,y) ((((x) + (y))<=CCAM__DMA_SIZE)? ((x) + (y)) : ((x) - (CCAM__DMA_SIZE-(y))))
*/
//int init_FPGA(void); /// can be initialized only after FPGA is configured, not at module init (NOTE was static??)
///can be verified with if (!X313_IS_SDRAM_ON)
int init_compressor_dma(int chn_mask, int reset);
void reset_compressor(unsigned int chn);
void compressor_interrupts (int on, int chn);
void sensor_interrupts (int on, int chn);
......
......@@ -1424,7 +1424,6 @@ static ssize_t get_i2c_help(struct device *dev, ///< Linux kernel b
);
}
/** Sysfs function - read i2c sequencer frame number (4 bits) */
static ssize_t i2c_frame_show(struct device *dev, ///< Linux kernel basic device structure
struct device_attribute *attr, ///< Linux kernel interface for exporting device attributes
......
......@@ -19,6 +19,7 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <uapi/elphel/c313a.h> // PARS_FRAMES_MASK
......@@ -38,50 +39,102 @@ int init_command_sequencer(int sensor_port)
}
#endif
int compressor_dma_setup (int port_afi, ///< number of AFI port (0 - afi 1, 1 - afi2) (currently only 0 is routed)
int chn_mask, ///< compressor channels to use, bitmask
int status_mode, ///< status update mode status mode (3 for auto)
int report_mode, ///< readback mode:
///< * 0 - show EOF pointer, internal
///< * 1 - show EOF pointer, confirmed written to the system memory
///< * 2 - show show current pointer, internal (debug mode)
///< * 3 - show current pointer, confirmed written to the system memory (debug mode)
u32 cmprs0_sa, ///< input channel 0 start address, 32-bytes aligned
u32 cmprs0_len, ///< input channel 0 buffer length, 32-byte aligned
u32 cmprs1_sa, ///< input channel 1 start address, 32-bytes aligned
u32 cmprs1_len, ///< input channel 1 buffer length, 32-byte aligned
u32 cmprs2_sa, ///< input channel 2 start address, 32-bytes aligned
u32 cmprs2_len, ///< input channel 2 buffer length, 32-byte aligned
u32 cmprs3_sa, ///< input channel 3 start address, 32-bytes aligned
u32 cmprs3_len) ///< input channel 3 buffer length, 32-byte aligned
int compressor_dma_setup (int port_afi, ///< number of AFI port (0 - afi 1, 1 - afi2) (currently only 0 is routed)
int chn_mask, ///< compressor channels to use, bitmask
int reset, ///< 1 - reset all channels
int status_mode, ///< status update mode status mode (3 for auto)
int report_mode, ///< readback mode:
///< * 0 - show EOF pointer, internal
///< * 1 - show EOF pointer, confirmed written to the system memory
///< * 2 - show show current pointer, internal (debug mode)
///< * 3 - show current pointer, confirmed written to the system memory (debug mode)
dma_addr_t cmprs0_sa, ///< input channel 0 start address, 32-bytes aligned
u32 cmprs0_len, ///< input channel 0 buffer length, 32-byte aligned
dma_addr_t cmprs1_sa, ///< input channel 1 start address, 32-bytes aligned
u32 cmprs1_len, ///< input channel 1 buffer length, 32-byte aligned
dma_addr_t cmprs2_sa, ///< input channel 2 start address, 32-bytes aligned
u32 cmprs2_len, ///< input channel 2 buffer length, 32-byte aligned
dma_addr_t cmprs3_sa, ///< input channel 3 start address, 32-bytes aligned
u32 cmprs3_len) ///< input channel 3 buffer length, 32-byte aligned
{
x393_status_ctrl_t status_ctrl = {.d32=0};
x393_afimux_report_t afimux_report= {.d32=0};
x393_afimux_sa_t afimux_sa[4]={{.d32=0},{.d32=0},{.d32=0},{.d32=0}};
x393_afimux_len_t afimux_len[4]={{.d32=0},{.d32=0},{.d32=0},{.d32=0}};
x393_afimux_rst_t afimux_rst={.d32=0};
x393_afimux_en_t afimux_en = {.d32=0};
int chn;
if ((cmprs0_sa | cmprs0_len | cmprs1_sa | cmprs1_len | cmprs2_sa | cmprs2_len | cmprs3_sa | cmprs3_len) & 0x1f){
return -EINVAL;
}
status_ctrl.mode = status_mode;
afimux_report.mode0 = report_mode;
afimux_report.mode0_set = 1 & (chn_mask >> 0);
afimux_report.mode1 = report_mode;
afimux_report.mode1_set = 1 & (chn_mask >> 1);
afimux_report.mode2 = report_mode;
afimux_report.mode2_set = 1 & (chn_mask >> 2);
afimux_report.mode3 = report_mode;
afimux_report.mode3_set = 1 & (chn_mask >> 3);
afimux_sa[0].sa256 = (u32) cmprs0_sa >> 5;
afimux_sa[1].sa256 = (u32) cmprs1_sa >> 5;
afimux_sa[2].sa256 = (u32) cmprs2_sa >> 5;
afimux_sa[3].sa256 = (u32) cmprs3_sa >> 5;
afimux_len[0].len256 = cmprs0_len >> 5;
afimux_len[1].len256 = cmprs1_len >> 5;
afimux_len[2].len256 = cmprs2_len >> 5;
afimux_len[3].len256 = cmprs3_len >> 5;
afimux_en.en = 1; // global enable
afimux_en.en_set = 1; // set global enable
afimux_en.en0 = 1;
afimux_en.en0_set = 1 & (chn_mask >> 0);
afimux_en.en1 = 1;
afimux_en.en1_set = 1 & (chn_mask >> 1);
afimux_en.en2 = 1;
afimux_en.en2_set = 1 & (chn_mask >> 2);
afimux_en.en3 = 1;
afimux_en.en3_set = 1 & (chn_mask >> 3);
for (chn = 0; chn < 4; chn++) if (chn_mask & (1 << chn)){
if (!port_afi) set_x393_afimux0_status_control (status_ctrl, chn); // AFI MUX 0 status report mode
else set_x393_afimux1_status_control (status_ctrl, chn); // AFI MUX 1 status report mode
}
if (!port_afi) x393_afimux0_report_mode (afimux_report); // AFI MUX 0 readout pointer report mode
else x393_afimux1_report_mode (afimux_report); // AFI MUX 1 readout pointer report mode
if (reset) {
afimux_rst.rst0 = 1 & (chn_mask >> 0);
afimux_rst.rst1 = 1 & (chn_mask >> 1);
afimux_rst.rst2 = 1 & (chn_mask >> 2);
afimux_rst.rst0 = 1 & (chn_mask >> 3);
if (!port_afi) set_x393_afimux0_rst(afimux_rst);
else set_x393_afimux1_rst(afimux_rst);
udelay(1);
afimux_rst.rst0 = 0;
afimux_rst.rst1 = 0;
afimux_rst.rst2 = 0;
afimux_rst.rst0 = 0;
if (!port_afi) set_x393_afimux0_rst(afimux_rst);
else set_x393_afimux1_rst(afimux_rst);
udelay(1);
}
for (chn = 0; chn < 4; chn++) if (chn_mask & (1 << chn)){
if (!port_afi) {
set_x393_afimux0_sa (afimux_sa[chn], chn); // AFI MUX 0 DMA buffer start address in 32-byte blocks
set_x393_afimux0_len (afimux_len[chn], chn); // AFI MUX 0 DMA buffer length in 32-byte blocks
} else {
set_x393_afimux1_sa (afimux_sa[chn], chn); // AFI MUX 1 DMA buffer start address in 32-byte blocks
set_x393_afimux1_len (afimux_len[chn], chn); // AFI MUX 0 DMA buffer length in 32-byte blocks
}
}
if (!port_afi) x393_afimux0_en (afimux_en); // AFI MUX 0 global/port run/pause control
else x393_afimux1_en (afimux_en); // AFI MUX 1 global/port run/pause control
return 0;
}
/*
Set mode of selected input channel of the selected AFI multiplexer
@param port_afi - number of AFI port (0 - afi 1, 1 - afi2)
@param chn - number of afi input channel to program
@param status_mode - status mode (3 for auto)
@param report_mode - readback mode:
mode == 0 - show EOF pointer, internal
mode == 1 - show EOF pointer, confirmed written to the system memory
mode == 2 - show current pointer, internal
mode == 3 - show current pointer, confirmed written to the system memory
@param afi_cmprs0_sa - input channel 0 start address in 32-byte chunks
@param afi_cmprs0_len - input channel 0 buffer length in 32-byte chunks
@param afi_cmprs1_sa - input channel 0 start address in 32-byte chunks
@param afi_cmprs1_len - input channel 0 buffer length in 32-byte chunks
@param afi_cmprs2_sa - input channel 0 start address in 32-byte chunks
@param afi_cmprs2_len - input channel 0 buffer length in 32-byte chunks
@param afi_cmprs3_sa - input channel 0 start address in 32-byte chunks
@param afi_cmprs3_len - input channel 0 buffer length in 32-byte chunks
@param verbose - verbose level
*/
/** Read time (seconds and microseconds) from the FPGA RTC */
sec_usec_t * get_fpga_rtc(sec_usec_t * ts) ///< Pointer to a sec/usec structure to fill in
///< @return structure link to a passed structure
......@@ -116,18 +169,19 @@ sec_usec_t * get_fpga_rtc(sec_usec_t * ts) ///< Pointer to a sec/usec structure
}
/** Set FPGA RTC to specified time */
void set_fpga_rtc (sec_usec_t ts) ///< timestamp providing seconds and microseconds
int set_fpga_rtc (sec_usec_t ts) ///< timestamp providing seconds and microseconds
{
x393_rtc_usec_t usec;
x393_rtc_sec_t sec;
usec.usec = ts.usec;
sec.sec = ts.sec;
if (!is_fpga_programmed())
return;
return -ENODEV;
spin_lock_bh(&fpga_time_lock);
set_x393_rtc_usec(usec);
set_x393_rtc_sec_set(sec); // And apply
spin_unlock_bh(&fpga_time_lock);
return 0;
}
/** Check if bitstream is loaded */
......
......@@ -16,8 +16,13 @@
*******************************************************************************/
//typedef enum {DIRECT,ABSOLUTE,RELATIVE} x393cmd_t;
#include "x393.h"
int compressor_dma_setup (int port_afi, int chn_mask, int reset, int status_mode, int report_mode,
dma_addr_t cmprs0_sa, u32 cmprs0_len, dma_addr_t cmprs1_sa, u32 cmprs1_len,
dma_addr_t cmprs2_sa, u32 cmprs2_len, dma_addr_t cmprs3_sa, u32 cmprs3_len);
//void fpga_table_write_nice (int addr, int len, unsigned long * data);
sec_usec_t * get_fpga_rtc(sec_usec_t * ts);
void set_fpga_rtc (sec_usec_t ts);
int set_fpga_rtc (sec_usec_t ts);
int is_fpga_programmed(void);
......@@ -20,6 +20,7 @@
#define _X393_MACRO
#include <uapi/elphel/x393_devices.h>
#include "circbuf.h" // for circbuf_priv (or disable X393_BUFSUB_CHN, X393_BUFADD_CHN if _CIRCBUF_H is not defined?
/** @brief Resolution of current/OEF pointer in bits */
......@@ -55,9 +56,15 @@
#define X313_LENGTH_MASK 0xff000000
/** @brief Subtract two offsets considering that the resulting offset can roll over the start of circular buffer */
#define X393_BUFFSUB(x, y) (((x) >= (y)) ? ((x)-(y)) : ((x) + (CCAM_DMA_SIZE -(y))))
/** @brief Add two offsets considering that the resulting offset car roll over the end of circular buffer */
#define X393_BUFFADD(x, y) ((((x) + (y)) <= CCAM_DMA_SIZE) ? ((x) + (y)) : ((x) - (CCAM_DMA_SIZE -(y))))
//#define X393__BUFFSUB(x, y) (((x) >= (y)) ? ((x)-(y)) : ((x) + (CCAM__DMA_SIZE -(y))))
#define X393_BUFFSUB_CHN(x, y, chn) (((x) >= (y)) ? ((x)-(y)) : ((x) + (circbuf_priv_ptr[chn].buf_size -(y))))
#define X393_BUFFSUB32(x, y, chn) (((x) >= (y)) ? ((x)-(y)) : ((x) + (circbuf_priv_ptr[chn].buf_size32 -(y))))
/** @brief Add two offsets considering that the resulting offset can roll over the end of circular buffer */
//#define X393__BUFFADD(x, y) ((((x) + (y)) <= CCAM__DMA_SIZE) ? ((x) + (y)) : ((x) - (CCAM__DMA_SIZE -(y))))
#define X393_BUFFADD_CHN(x, y, chn) ((((x) + (y)) <= circbuf_priv_ptr[chn].buf_size) ? ((x) + (y)) : ((x) - (circbuf_priv_ptr[chn].buf_size -(y))))
#define X393_BUFFADD32(x, y, chn) ((((x) + (y)) <= circbuf_priv_ptr[chn].buf_size32) ? ((x) + (y)) : ((x) - (circbuf_priv_ptr[chn].buf_size32 -(y))))
#define TABLE_TYPE_QUANT 0
#define TABLE_TYPE_CORING 1
......
......@@ -681,7 +681,7 @@
#define G_DEBUG (FRAMEPAR_GLOBALS + 2) ///< Each bit turns on/off some debug outputs
#define G_TEST_CTL_BITS (FRAMEPAR_GLOBALS + 3) ///< turn some features on/off in the drivers for debugging purposes
#define G_TEST_CTL_BITS_RESET_DMA_COMPRESSOR 0 ///< reset compressor and DMA when detecting sensor, bit number in G_TEST_CTL_BITS
#define G_TEST_CTL_BITS_RESET_DMA_COMPRESSOR 0 ///< reset compressor and DMA when detecting sensor, bit number in G_TEST_CTL_BITS
#define G_CABLE_TIM (FRAMEPAR_GLOBALS + 7) ///< Extra cable delay, signed ps)
#define G_FPGA_TIM0 (FRAMEPAR_GLOBALS + 8) ///< FPGA timing parameter 0 - difference between DCLK pad and DCM input, signed (ps)
......@@ -1448,7 +1448,7 @@ struct p_names_t {
#define LSEEK_CIRC_USED 13
#define LSEEK_CIRC_STOP_COMPRESSOR 14
#define LSEEK_CIRC_UTIME 15
#define LSEEK_CIRC_GETFRAME 16
#define LSEEK_HUFFMAN_DC0 1
#define LSEEK_HUFFMAN_AC0 2
#define LSEEK_HUFFMAN_DC1 3
......@@ -1541,6 +1541,7 @@ struct p_names_t {
LSEEK_NAME_ENTRY(CIRC_WAIT), \