Loading src/drivers/elphel/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -33,3 +33,4 @@ obj-$(CONFIG_ELPHEL393) += imu_log393.o obj-$(CONFIG_ELPHEL393) += cxi2c.o obj-$(CONFIG_ELPHEL393) += x393_videomem.o obj-$(CONFIG_ELPHEL393) += detect_sensors.o obj-$(CONFIG_ELPHEL393) += x393_fpga_functions.o No newline at end of file src/drivers/elphel/framepars.c +80 −59 Original line number Diff line number Diff line Loading @@ -55,7 +55,7 @@ //#include "cc3x3.h" //#include "x3x3.h" // hardware definitions #include "x393_fpga_functions.h" #include "sensor_common.h" #include "framepars.h" #include "param_depend.h" // specifies what functions should be called for different parameters changed Loading Loading @@ -169,6 +169,9 @@ struct sensorproc_t * sensorproc = NULL; #endif /** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */ static struct device *g_devfp_ptr; //wait_queue_head_t framepars_wait_queue; // used to wait for the frame to be acquired /** Loading Loading @@ -879,7 +882,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l struct framepars_t *framepars = aframepars[sensor_port]; unsigned long *funcs2call =afuncs2call[sensor_port]; MDF8(printk(": thisFrameNumber=0x%lx frame8=%d index= %d (0x%lx), val=0x%lx\n", thisFrameNumber(sensor_port), frame8, index, mindex, val)); dev_dbg(g_devfp_ptr, ": thisFrameNumber=0x%lx frame8=%d index= %d (0x%lx), val=0x%lx\n", thisFrameNumber(sensor_port), frame8, index, mindex, val); D1I(local_irq_save(flags)); // if (index > P_MAX_PAR) { if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) { Loading Loading @@ -911,7 +914,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l if (mindex & FRAMEPAIR_FORCE_PROC) { framepars[frame8].functions |= funcs2call[index]; //Mark which functions will be needed to process the parameters } MDF8(printk(" bindex=0x%lx, bmask=0x%08lx, bmask32=0x%08lx, functions=0x%08lx\n", bindex, bmask, bmask32, framepars[frame8].functions)); dev_dbg(g_devfp_ptr, " bindex=0x%lx, bmask=0x%08lx, bmask32=0x%08lx, functions=0x%08lx\n", bindex, bmask, bmask32, framepars[frame8].functions); // Write parameter to the next frames up to the one that have the same parameter already modified if ((mindex & FRAMEPAIR_JUST_THIS) == 0) { MDF8(printk(": --- setting next frames")); Loading @@ -936,7 +939,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l } } else { // error - trying to write "just this" to the "future" - that would stick if allowed D1I(local_irq_restore(flags)); ELP_KERR(printk("Tried to write JUST_THIS parameter (0x%lx) too far in the future", mindex)); dev_err(g_devfp_ptr, "Tried to write JUST_THIS parameter (0x%lx) too far in the future", mindex); return -ERR_FRAMEPARS_TOOEARLY; } D1I(local_irq_restore(flags)); Loading Loading @@ -964,17 +967,17 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa struct framepars_t *framepars = aframepars[sensor_port]; unsigned long *funcs2call =afuncs2call[sensor_port]; MDF8(printk(": this_framepars=0x%x numPars=%d\n", (int)this_framepars, numPars)); dev_dbg(g_devfp_ptr, ": this_framepars=0x%x numPars=%d\n", (int)this_framepars, numPars); D1I(local_irq_save(flags)); for (npar = 0; npar < numPars; npar++) { frame8 = (this_framepars->pars[P_FRAME]) & PARS_FRAMES_MASK; val = pars[npar].val; index = pars[npar].num & 0xffff; MDF8(printk(": --- frame8=%d index=%d (0x%x) val=0x%x\n", frame8, index, (int)pars[npar].num, (int)val)); dev_dbg(g_devfp_ptr, ": --- frame8=%d index=%d (0x%x) val=0x%x\n", frame8, index, (int)pars[npar].num, (int)val); // remark: code below looks similar to setFramePar function, call it instead if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) { D1I(local_irq_restore(flags)); ELP_KERR(printk(" bad index=%d > %d\n", index, P_MAX_PAR)); dev_err(g_devfp_ptr, " bad index=%d > %d\n", index, P_MAX_PAR); return -ERR_FRAMEPARS_BADINDEX; } if (index >= FRAMEPAR_GLOBALS) { // ignore frame logic, set "static" parameters to frame 0 Loading Loading @@ -1021,7 +1024,7 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa } } else { // error - trying to write "just this" to the "future" - that would stick if allowed D1I(local_irq_restore(flags)); ELP_KERR(printk("Tried to write JUST_THIS parameter (0x%lx) too far in the future", pars[npar].num)); dev_err(g_devfp_ptr, "Tried to write JUST_THIS parameter (0x%lx) too far in the future", pars[npar].num); return -ERR_FRAMEPARS_TOOEARLY; } } Loading Loading @@ -1124,8 +1127,10 @@ 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 - DEV393_MINOR(DEV393_FRAMEPARS0); sec_usec_t sec_usec; // 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)); dev_dbg(g_devfp_ptr, "(framepars_lseek) offset=0x%x, orig=0x%x, sensor_port = %d\n", (int)offset, (int)orig, sensor_port); switch (orig) { case SEEK_SET: file->f_pos = offset; Loading Loading @@ -1155,48 +1160,55 @@ 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) ); MDF2(printk("X313_GET_FPGA_TIME\n")); get_fpga_rtc(&sec_usec); 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); break; case LSEEK_SET_FPGA_TIME: // better to use write, not lseek to set FPGA time //X313_SET_FPGA_TIME( GLOBALPARS(G_SECONDS) , GLOBALPARS(G_MICROSECONDS) ); MDF2(printk("X313_SET_FPGA_TIME\n")); sec_usec.sec = GLOBALPARS(sensor_port,G_SECONDS); sec_usec.usec = GLOBALPARS(sensor_port,G_MICROSECONDS); set_fpga_rtc(sec_usec); 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 MDF2(printk("LSEEK_FRAMEPARS_INIT\n")); dev_dbg(g_devfp_ptr, "LSEEK_FRAMEPARS_INIT\n"); initGlobalPars(sensor_port); // reset all global parameters but the first 32 initSequencers(sensor_port); break; case LSEEK_FRAME_RESET: // reset absolute frame number to avoid integer frame number overflow MDF2(printk("LSEEK_FRAME_RESET\n")); dev_dbg(g_devfp_ptr, "LSEEK_FRAME_RESET\n"); resetFrameNumber(sensor_port); break; case LSEEK_SENSORPROC: // process modified parameters in frame 0 (to start sensor detection) MDF2(printk("LSEEK_SENSORPROC: framepars[0].functions=0x%08lx\n", framepars[0].functions)); dev_dbg(g_devfp_ptr, "LSEEK_SENSORPROC: aframepars[%d][0].functions=0x%08lx\n", sensor_port, aframepars[sensor_port][0].functions); processPars(sensor_port, sensorproc, 0, 8); //frame0, all 8 frames (maxAhead==8) break; case LSEEK_DMA_INIT: // initialize ETRAX DMA (normally done in sensor_common.c at driver init MDF2(printk("LSEEK_DMA_INIT\n")); dev_dbg(g_devfp_ptr, "LSEEK_DMA_INIT\n"); //x313_dma_init(); break; case LSEEK_DMA_STOP: // stop DMA MDF2(printk("LSEEK_DMA_STOP\n")); dev_dbg(g_devfp_ptr, "LSEEK_DMA_STOP\n"); //x313_dma_stop(); // break; case LSEEK_DMA_START: // start DMA MDF2(printk("LSEEK_DMA_START\n")); dev_dbg(g_devfp_ptr, "LSEEK_DMA_START\n"); //x313_dma_start(); // break; case LSEEK_COMPRESSOR_RESET: // reset compressor and buffer pointers MDF2(printk("LSEEK_COMPRESSOR_RESET\n")); dev_dbg(g_devfp_ptr, "LSEEK_COMPRESSOR_RESET\n"); //reset_compressor(); break; case LSEEK_INTERRUPT_OFF: // disable camera interrupts MDF2(printk("LSEEK_INTERRUPT_OFF\n")); dev_dbg(g_devfp_ptr, "LSEEK_INTERRUPT_OFF\n"); // compressor_interrupts(0,sensor_port); sensor_interrupts(0,sensor_port); break; case LSEEK_INTERRUPT_ON: // enable camera interrupts // MDF2(printk("LSEEK_INTERRUPT_ON\n")); dev_dbg(g_devfp_ptr, "LSEEK_INTERRUPT_ON\n"); sensor_interrupts(1,sensor_port); break; } Loading Loading @@ -1231,8 +1243,9 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff int first = 0; int last; int result; MDF1(printk(": file->f_pos=0x%x, *off=0x%x, count=0x%x\n", (int)file->f_pos, (int)*off, (int)count)); sec_usec_t sec_usec; // MDF1(printk(": file->f_pos=0x%x, *off=0x%x, count=0x%x\n", (int)file->f_pos, (int)*off, (int)count)); dev_dbg(g_devfp_ptr, ": file->f_pos=0x%x, *off=0x%x, count=0x%x\n", (int)file->f_pos, (int)*off, (int)count); count &= ~7; // sizeof (struct frameparspair_t)==8 switch (privData->minor) { case DEV393_MINOR(DEV393_FRAMEPARS0): Loading Loading @@ -1262,9 +1275,15 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff break; case FRAMEPARS_SETFPGATIME: //ignore value (should be already set in G_SECONDS, G_MICROSECONDS frame0) //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); 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); GLOBALPARS(sensor_port,G_SECONDS) = sec_usec.sec; GLOBALPARS(sensor_port,G_MICROSECONDS) = sec_usec.usec; break; default: printk("framepars_write: invalid special instruction: 0x%x\n", (int)pars[first].num); Loading @@ -1274,7 +1293,7 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff last = first + 1; while ((last < count) && ((pars[last].num & 0xff00) != 0xff00)) last++; // skip to the end or next special instructions result = setFrameParsAtomic(sensor_port,frame, latency, last - first, &pars[first]); MDF1(printk("setFrameParsAtomic(%ld, %d, %d)\n", frame, latency, last - first)); dev_dbg(g_devfp_ptr, "setFrameParsAtomic(%ld, %d, %d)\n", frame, latency, last - first); if (result < 0) { if (count > sizeof(pars_static)) kfree(pars); return -EFAULT; Loading Loading @@ -1313,7 +1332,7 @@ int framepars_mmap(struct file *file, struct vm_area_struct *vma) ((unsigned long)virt_to_phys(&aframeparsall[sensor_port])) >> PAGE_SHIFT, // Should be page-aligned vma->vm_end - vma->vm_start, vma->vm_page_prot); MDF1(printk("remap_pfn_range returned=%x\r\n", result)); dev_dbg(g_devfp_ptr, "remap_pfn_range returned=%x\n", result); if (result) return -EAGAIN; return 0; default: return -EINVAL; Loading @@ -1340,13 +1359,15 @@ int framepars_init(struct platform_device *pdev) frameParsInitialized = 0; res = register_chrdev(DEV393_MAJOR(DEV393_FRAMEPARS0), DEV393_NAME(DEV393_FRAMEPARS0), &framepars_fops); if (res < 0) { printk(KERN_ERR "\nframepars_init: couldn't get a major number %d.\n", DEV393_MAJOR(DEV393_FRAMEPARS0)); dev_err(dev, "framepars_init: couldn't get a major number %d (DEV393_MAJOR(DEV393_FRAMEPARS0)).\n", DEV393_MAJOR(DEV393_FRAMEPARS0)); return res; } for (sensor_port = 0; sensor_port < SENSOR_PORTS; sensor_port++) { init_waitqueue_head(&aframepars_wait_queue[sensor_port]); } dev_info(dev, "registered MAJOR: %d\n", DEV393_MAJOR(DEV393_FRAMEPARS0)); dev_info(dev, DEV393_NAME(DEV393_FRAMEPARS0)": registered MAJOR: %d\n", DEV393_MAJOR(DEV393_FRAMEPARS0)); g_devfp_ptr = dev; return 0; } Loading @@ -1358,24 +1379,24 @@ int framepars_remove(struct platform_device *pdev) return 0; } //static const struct of_device_id elphel393_framepars_of_match[] = { // { .compatible = "elphel,elphel393-framepars-1.00" }, // { /* end of list */ } //}; //MODULE_DEVICE_TABLE(of, elphel393_framepars_of_match); // //static struct platform_driver elphel393_framepars = { // .probe = framepars_init, // .remove = framepars_remove, // .driver = { // .name = DEV393_NAME(DEV393_FRAMEPARS0), // .of_match_table = elphel393_framepars_of_match, // }, //}; // //module_platform_driver(elphel393_framepars); // //MODULE_LICENSE("GPL"); //MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>."); //MODULE_DESCRIPTION(FRAMEPARS_DRIVER_DESCRIPTION); // static const struct of_device_id elphel393_framepars_of_match[] = { { .compatible = "elphel,elphel393-framepars-1.00" }, { /* end of list */ } }; MODULE_DEVICE_TABLE(of, elphel393_framepars_of_match); static struct platform_driver elphel393_framepars = { .probe = framepars_init, .remove = framepars_remove, .driver = { .name = DEV393_NAME(DEV393_FRAMEPARS0), .of_match_table = elphel393_framepars_of_match, }, }; module_platform_driver(elphel393_framepars); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>."); MODULE_DESCRIPTION(FRAMEPARS_DRIVER_DESCRIPTION); src/drivers/elphel/sensor_common.c +2 −2 Original line number Diff line number Diff line Loading @@ -957,7 +957,7 @@ int image_acq_init(struct platform_device *pdev) #endif dev_dbg(dev, "Elphel FPGA interrupts initialized\n"); dev_info(dev, "Elphel FPGA interrupts initialized\n"); dev_dbg(dev, "reset all compressors\n"); for (i = 0; i < SENSOR_PORTS; i++) { reset_compressor(i); Loading @@ -969,7 +969,7 @@ int image_acq_init(struct platform_device *pdev) //init_pgm_proc (); // setup pointers to functions (not sensor-specific) //MDD1(printk("reset_qtables()\n")); framepars_init(pdev); // framepars_init(pdev); return 0; } Loading src/drivers/elphel/x393_fpga_functions.c +51 −0 Original line number Diff line number Diff line Loading @@ -14,11 +14,62 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ #include <linux/spinlock.h> #include <uapi/elphel/c313a.h> // PARS_FRAMES_MASK #include "x393.h" #include "x393_fpga_functions.h" #define REPEAT_STATUS_READ 10 ///< Number of times status is re-read waiting for a new timestamp static DEFINE_SPINLOCK(fpga_time_lock); // Nothing to init? Started in pgm_detectsesnor through sensor_common:sequencer_stop_run_reset #if 0 int init_command_sequencer(int sensor_port) { return 0; } #endif /** 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 { // sec_usec_t ts = {.sec=0, .usec=0}; x393_rtc_status_t stat; x393_status_ctrl_t stat_ctrl={.d32=0}; // x393_rtc_usec_t usec; // x393_rtc_sec_t sec; int i; if (!ts) return NULL; spin_lock(&fpga_time_lock); stat = x393_rtc_status(); stat_ctrl.mode = 1; stat_ctrl.seq_num = stat.seq_num + 1; set_x393_rtc_set_status(stat_ctrl); // Requests single status, latches current time for (i = 0; i < REPEAT_STATUS_READ; i++) { stat = x393_rtc_status(); if (stat.seq_num == stat_ctrl.seq_num) { ts->sec = x393_rtc_status_sec().sec; ts->usec = x393_rtc_status_usec().usec; break; } } spin_unlock(&fpga_time_lock); return ts; } /** Set FPGA RTC to specified time */ void 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; spin_lock(&fpga_time_lock); set_x393_rtc_usec(usec); set_x393_rtc_sec_set(sec); // And apply spin_unlock(&fpga_time_lock); } src/drivers/elphel/x393_fpga_functions.h +4 −1 Original line number Diff line number Diff line Loading @@ -16,4 +16,7 @@ *******************************************************************************/ //typedef enum {DIRECT,ABSOLUTE,RELATIVE} x393cmd_t; #include "x393.h" void fpga_table_write_nice (int addr, int len, unsigned long * data); //void fpga_table_write_nice (int addr, int len, unsigned long * data); sec_usec_t * get_fpga_rtc(sec_usec_t * ts); void set_fpga_rtc (sec_usec_t ts); Loading
src/drivers/elphel/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -33,3 +33,4 @@ obj-$(CONFIG_ELPHEL393) += imu_log393.o obj-$(CONFIG_ELPHEL393) += cxi2c.o obj-$(CONFIG_ELPHEL393) += x393_videomem.o obj-$(CONFIG_ELPHEL393) += detect_sensors.o obj-$(CONFIG_ELPHEL393) += x393_fpga_functions.o No newline at end of file
src/drivers/elphel/framepars.c +80 −59 Original line number Diff line number Diff line Loading @@ -55,7 +55,7 @@ //#include "cc3x3.h" //#include "x3x3.h" // hardware definitions #include "x393_fpga_functions.h" #include "sensor_common.h" #include "framepars.h" #include "param_depend.h" // specifies what functions should be called for different parameters changed Loading Loading @@ -169,6 +169,9 @@ struct sensorproc_t * sensorproc = NULL; #endif /** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */ static struct device *g_devfp_ptr; //wait_queue_head_t framepars_wait_queue; // used to wait for the frame to be acquired /** Loading Loading @@ -879,7 +882,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l struct framepars_t *framepars = aframepars[sensor_port]; unsigned long *funcs2call =afuncs2call[sensor_port]; MDF8(printk(": thisFrameNumber=0x%lx frame8=%d index= %d (0x%lx), val=0x%lx\n", thisFrameNumber(sensor_port), frame8, index, mindex, val)); dev_dbg(g_devfp_ptr, ": thisFrameNumber=0x%lx frame8=%d index= %d (0x%lx), val=0x%lx\n", thisFrameNumber(sensor_port), frame8, index, mindex, val); D1I(local_irq_save(flags)); // if (index > P_MAX_PAR) { if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) { Loading Loading @@ -911,7 +914,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l if (mindex & FRAMEPAIR_FORCE_PROC) { framepars[frame8].functions |= funcs2call[index]; //Mark which functions will be needed to process the parameters } MDF8(printk(" bindex=0x%lx, bmask=0x%08lx, bmask32=0x%08lx, functions=0x%08lx\n", bindex, bmask, bmask32, framepars[frame8].functions)); dev_dbg(g_devfp_ptr, " bindex=0x%lx, bmask=0x%08lx, bmask32=0x%08lx, functions=0x%08lx\n", bindex, bmask, bmask32, framepars[frame8].functions); // Write parameter to the next frames up to the one that have the same parameter already modified if ((mindex & FRAMEPAIR_JUST_THIS) == 0) { MDF8(printk(": --- setting next frames")); Loading @@ -936,7 +939,7 @@ int setFramePar(int sensor_port, struct framepars_t * this_framepars, unsigned l } } else { // error - trying to write "just this" to the "future" - that would stick if allowed D1I(local_irq_restore(flags)); ELP_KERR(printk("Tried to write JUST_THIS parameter (0x%lx) too far in the future", mindex)); dev_err(g_devfp_ptr, "Tried to write JUST_THIS parameter (0x%lx) too far in the future", mindex); return -ERR_FRAMEPARS_TOOEARLY; } D1I(local_irq_restore(flags)); Loading Loading @@ -964,17 +967,17 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa struct framepars_t *framepars = aframepars[sensor_port]; unsigned long *funcs2call =afuncs2call[sensor_port]; MDF8(printk(": this_framepars=0x%x numPars=%d\n", (int)this_framepars, numPars)); dev_dbg(g_devfp_ptr, ": this_framepars=0x%x numPars=%d\n", (int)this_framepars, numPars); D1I(local_irq_save(flags)); for (npar = 0; npar < numPars; npar++) { frame8 = (this_framepars->pars[P_FRAME]) & PARS_FRAMES_MASK; val = pars[npar].val; index = pars[npar].num & 0xffff; MDF8(printk(": --- frame8=%d index=%d (0x%x) val=0x%x\n", frame8, index, (int)pars[npar].num, (int)val)); dev_dbg(g_devfp_ptr, ": --- frame8=%d index=%d (0x%x) val=0x%x\n", frame8, index, (int)pars[npar].num, (int)val); // remark: code below looks similar to setFramePar function, call it instead if (index > ((index >= FRAMEPAR_GLOBALS) ? (P_MAX_GPAR + FRAMEPAR_GLOBALS) : P_MAX_PAR)) { D1I(local_irq_restore(flags)); ELP_KERR(printk(" bad index=%d > %d\n", index, P_MAX_PAR)); dev_err(g_devfp_ptr, " bad index=%d > %d\n", index, P_MAX_PAR); return -ERR_FRAMEPARS_BADINDEX; } if (index >= FRAMEPAR_GLOBALS) { // ignore frame logic, set "static" parameters to frame 0 Loading Loading @@ -1021,7 +1024,7 @@ int setFramePars(int sensor_port, struct framepars_t * this_framepars, int numPa } } else { // error - trying to write "just this" to the "future" - that would stick if allowed D1I(local_irq_restore(flags)); ELP_KERR(printk("Tried to write JUST_THIS parameter (0x%lx) too far in the future", pars[npar].num)); dev_err(g_devfp_ptr, "Tried to write JUST_THIS parameter (0x%lx) too far in the future", pars[npar].num); return -ERR_FRAMEPARS_TOOEARLY; } } Loading Loading @@ -1124,8 +1127,10 @@ 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 - DEV393_MINOR(DEV393_FRAMEPARS0); sec_usec_t sec_usec; // 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)); dev_dbg(g_devfp_ptr, "(framepars_lseek) offset=0x%x, orig=0x%x, sensor_port = %d\n", (int)offset, (int)orig, sensor_port); switch (orig) { case SEEK_SET: file->f_pos = offset; Loading Loading @@ -1155,48 +1160,55 @@ 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) ); MDF2(printk("X313_GET_FPGA_TIME\n")); get_fpga_rtc(&sec_usec); 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); break; case LSEEK_SET_FPGA_TIME: // better to use write, not lseek to set FPGA time //X313_SET_FPGA_TIME( GLOBALPARS(G_SECONDS) , GLOBALPARS(G_MICROSECONDS) ); MDF2(printk("X313_SET_FPGA_TIME\n")); sec_usec.sec = GLOBALPARS(sensor_port,G_SECONDS); sec_usec.usec = GLOBALPARS(sensor_port,G_MICROSECONDS); set_fpga_rtc(sec_usec); 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 MDF2(printk("LSEEK_FRAMEPARS_INIT\n")); dev_dbg(g_devfp_ptr, "LSEEK_FRAMEPARS_INIT\n"); initGlobalPars(sensor_port); // reset all global parameters but the first 32 initSequencers(sensor_port); break; case LSEEK_FRAME_RESET: // reset absolute frame number to avoid integer frame number overflow MDF2(printk("LSEEK_FRAME_RESET\n")); dev_dbg(g_devfp_ptr, "LSEEK_FRAME_RESET\n"); resetFrameNumber(sensor_port); break; case LSEEK_SENSORPROC: // process modified parameters in frame 0 (to start sensor detection) MDF2(printk("LSEEK_SENSORPROC: framepars[0].functions=0x%08lx\n", framepars[0].functions)); dev_dbg(g_devfp_ptr, "LSEEK_SENSORPROC: aframepars[%d][0].functions=0x%08lx\n", sensor_port, aframepars[sensor_port][0].functions); processPars(sensor_port, sensorproc, 0, 8); //frame0, all 8 frames (maxAhead==8) break; case LSEEK_DMA_INIT: // initialize ETRAX DMA (normally done in sensor_common.c at driver init MDF2(printk("LSEEK_DMA_INIT\n")); dev_dbg(g_devfp_ptr, "LSEEK_DMA_INIT\n"); //x313_dma_init(); break; case LSEEK_DMA_STOP: // stop DMA MDF2(printk("LSEEK_DMA_STOP\n")); dev_dbg(g_devfp_ptr, "LSEEK_DMA_STOP\n"); //x313_dma_stop(); // break; case LSEEK_DMA_START: // start DMA MDF2(printk("LSEEK_DMA_START\n")); dev_dbg(g_devfp_ptr, "LSEEK_DMA_START\n"); //x313_dma_start(); // break; case LSEEK_COMPRESSOR_RESET: // reset compressor and buffer pointers MDF2(printk("LSEEK_COMPRESSOR_RESET\n")); dev_dbg(g_devfp_ptr, "LSEEK_COMPRESSOR_RESET\n"); //reset_compressor(); break; case LSEEK_INTERRUPT_OFF: // disable camera interrupts MDF2(printk("LSEEK_INTERRUPT_OFF\n")); dev_dbg(g_devfp_ptr, "LSEEK_INTERRUPT_OFF\n"); // compressor_interrupts(0,sensor_port); sensor_interrupts(0,sensor_port); break; case LSEEK_INTERRUPT_ON: // enable camera interrupts // MDF2(printk("LSEEK_INTERRUPT_ON\n")); dev_dbg(g_devfp_ptr, "LSEEK_INTERRUPT_ON\n"); sensor_interrupts(1,sensor_port); break; } Loading Loading @@ -1231,8 +1243,9 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff int first = 0; int last; int result; MDF1(printk(": file->f_pos=0x%x, *off=0x%x, count=0x%x\n", (int)file->f_pos, (int)*off, (int)count)); sec_usec_t sec_usec; // MDF1(printk(": file->f_pos=0x%x, *off=0x%x, count=0x%x\n", (int)file->f_pos, (int)*off, (int)count)); dev_dbg(g_devfp_ptr, ": file->f_pos=0x%x, *off=0x%x, count=0x%x\n", (int)file->f_pos, (int)*off, (int)count); count &= ~7; // sizeof (struct frameparspair_t)==8 switch (privData->minor) { case DEV393_MINOR(DEV393_FRAMEPARS0): Loading Loading @@ -1262,9 +1275,15 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff break; case FRAMEPARS_SETFPGATIME: //ignore value (should be already set in G_SECONDS, G_MICROSECONDS frame0) //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); 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); GLOBALPARS(sensor_port,G_SECONDS) = sec_usec.sec; GLOBALPARS(sensor_port,G_MICROSECONDS) = sec_usec.usec; break; default: printk("framepars_write: invalid special instruction: 0x%x\n", (int)pars[first].num); Loading @@ -1274,7 +1293,7 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff last = first + 1; while ((last < count) && ((pars[last].num & 0xff00) != 0xff00)) last++; // skip to the end or next special instructions result = setFrameParsAtomic(sensor_port,frame, latency, last - first, &pars[first]); MDF1(printk("setFrameParsAtomic(%ld, %d, %d)\n", frame, latency, last - first)); dev_dbg(g_devfp_ptr, "setFrameParsAtomic(%ld, %d, %d)\n", frame, latency, last - first); if (result < 0) { if (count > sizeof(pars_static)) kfree(pars); return -EFAULT; Loading Loading @@ -1313,7 +1332,7 @@ int framepars_mmap(struct file *file, struct vm_area_struct *vma) ((unsigned long)virt_to_phys(&aframeparsall[sensor_port])) >> PAGE_SHIFT, // Should be page-aligned vma->vm_end - vma->vm_start, vma->vm_page_prot); MDF1(printk("remap_pfn_range returned=%x\r\n", result)); dev_dbg(g_devfp_ptr, "remap_pfn_range returned=%x\n", result); if (result) return -EAGAIN; return 0; default: return -EINVAL; Loading @@ -1340,13 +1359,15 @@ int framepars_init(struct platform_device *pdev) frameParsInitialized = 0; res = register_chrdev(DEV393_MAJOR(DEV393_FRAMEPARS0), DEV393_NAME(DEV393_FRAMEPARS0), &framepars_fops); if (res < 0) { printk(KERN_ERR "\nframepars_init: couldn't get a major number %d.\n", DEV393_MAJOR(DEV393_FRAMEPARS0)); dev_err(dev, "framepars_init: couldn't get a major number %d (DEV393_MAJOR(DEV393_FRAMEPARS0)).\n", DEV393_MAJOR(DEV393_FRAMEPARS0)); return res; } for (sensor_port = 0; sensor_port < SENSOR_PORTS; sensor_port++) { init_waitqueue_head(&aframepars_wait_queue[sensor_port]); } dev_info(dev, "registered MAJOR: %d\n", DEV393_MAJOR(DEV393_FRAMEPARS0)); dev_info(dev, DEV393_NAME(DEV393_FRAMEPARS0)": registered MAJOR: %d\n", DEV393_MAJOR(DEV393_FRAMEPARS0)); g_devfp_ptr = dev; return 0; } Loading @@ -1358,24 +1379,24 @@ int framepars_remove(struct platform_device *pdev) return 0; } //static const struct of_device_id elphel393_framepars_of_match[] = { // { .compatible = "elphel,elphel393-framepars-1.00" }, // { /* end of list */ } //}; //MODULE_DEVICE_TABLE(of, elphel393_framepars_of_match); // //static struct platform_driver elphel393_framepars = { // .probe = framepars_init, // .remove = framepars_remove, // .driver = { // .name = DEV393_NAME(DEV393_FRAMEPARS0), // .of_match_table = elphel393_framepars_of_match, // }, //}; // //module_platform_driver(elphel393_framepars); // //MODULE_LICENSE("GPL"); //MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>."); //MODULE_DESCRIPTION(FRAMEPARS_DRIVER_DESCRIPTION); // static const struct of_device_id elphel393_framepars_of_match[] = { { .compatible = "elphel,elphel393-framepars-1.00" }, { /* end of list */ } }; MODULE_DEVICE_TABLE(of, elphel393_framepars_of_match); static struct platform_driver elphel393_framepars = { .probe = framepars_init, .remove = framepars_remove, .driver = { .name = DEV393_NAME(DEV393_FRAMEPARS0), .of_match_table = elphel393_framepars_of_match, }, }; module_platform_driver(elphel393_framepars); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>."); MODULE_DESCRIPTION(FRAMEPARS_DRIVER_DESCRIPTION);
src/drivers/elphel/sensor_common.c +2 −2 Original line number Diff line number Diff line Loading @@ -957,7 +957,7 @@ int image_acq_init(struct platform_device *pdev) #endif dev_dbg(dev, "Elphel FPGA interrupts initialized\n"); dev_info(dev, "Elphel FPGA interrupts initialized\n"); dev_dbg(dev, "reset all compressors\n"); for (i = 0; i < SENSOR_PORTS; i++) { reset_compressor(i); Loading @@ -969,7 +969,7 @@ int image_acq_init(struct platform_device *pdev) //init_pgm_proc (); // setup pointers to functions (not sensor-specific) //MDD1(printk("reset_qtables()\n")); framepars_init(pdev); // framepars_init(pdev); return 0; } Loading
src/drivers/elphel/x393_fpga_functions.c +51 −0 Original line number Diff line number Diff line Loading @@ -14,11 +14,62 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ #include <linux/spinlock.h> #include <uapi/elphel/c313a.h> // PARS_FRAMES_MASK #include "x393.h" #include "x393_fpga_functions.h" #define REPEAT_STATUS_READ 10 ///< Number of times status is re-read waiting for a new timestamp static DEFINE_SPINLOCK(fpga_time_lock); // Nothing to init? Started in pgm_detectsesnor through sensor_common:sequencer_stop_run_reset #if 0 int init_command_sequencer(int sensor_port) { return 0; } #endif /** 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 { // sec_usec_t ts = {.sec=0, .usec=0}; x393_rtc_status_t stat; x393_status_ctrl_t stat_ctrl={.d32=0}; // x393_rtc_usec_t usec; // x393_rtc_sec_t sec; int i; if (!ts) return NULL; spin_lock(&fpga_time_lock); stat = x393_rtc_status(); stat_ctrl.mode = 1; stat_ctrl.seq_num = stat.seq_num + 1; set_x393_rtc_set_status(stat_ctrl); // Requests single status, latches current time for (i = 0; i < REPEAT_STATUS_READ; i++) { stat = x393_rtc_status(); if (stat.seq_num == stat_ctrl.seq_num) { ts->sec = x393_rtc_status_sec().sec; ts->usec = x393_rtc_status_usec().usec; break; } } spin_unlock(&fpga_time_lock); return ts; } /** Set FPGA RTC to specified time */ void 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; spin_lock(&fpga_time_lock); set_x393_rtc_usec(usec); set_x393_rtc_sec_set(sec); // And apply spin_unlock(&fpga_time_lock); }
src/drivers/elphel/x393_fpga_functions.h +4 −1 Original line number Diff line number Diff line Loading @@ -16,4 +16,7 @@ *******************************************************************************/ //typedef enum {DIRECT,ABSOLUTE,RELATIVE} x393cmd_t; #include "x393.h" void fpga_table_write_nice (int addr, int len, unsigned long * data); //void fpga_table_write_nice (int addr, int len, unsigned long * data); sec_usec_t * get_fpga_rtc(sec_usec_t * ts); void set_fpga_rtc (sec_usec_t ts);