Loading src/drivers/elphel/circbuf.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -824,7 +824,8 @@ unsigned int circbuf_poll (struct file *file, poll_table *wait) int rslt; int rslt; dev_dbg(g_dev_ptr, "minor = 0x%x\n", minor); dev_dbg(g_dev_ptr, "minor = 0x%x\n", minor); rslt = circbufValidPointer(&file->f_pos, &fp, chn); // rslt = circbufValidPointer(&file->f_pos, &fp, chn); rslt = circbufValidPointer(file->f_pos, &fp, chn); if (rslt < 0) { if (rslt < 0) { // not a valid read pointer, probable buffer overrun // not a valid read pointer, probable buffer overrun dev_dbg(g_dev_ptr, "invalid pointer file->f_pos = 0x%llx\n", file->f_pos); dev_dbg(g_dev_ptr, "invalid pointer file->f_pos = 0x%llx\n", file->f_pos); Loading src/drivers/elphel/framepars.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -826,7 +826,7 @@ inline void _processParsASAP(int sensor_port, ///< sensor port //#define G_CALLNEXT3 122 // bitmask of actions to be three or more frames ahead of the programmed one (OR-ed with G_CALLNEXT4) //#define G_CALLNEXT3 122 // bitmask of actions to be three or more frames ahead of the programmed one (OR-ed with G_CALLNEXT4) //#define G_CALLNEXT4 123 // bitmask of actions to be four or more frames ahead of the programmed one //#define G_CALLNEXT4 123 // bitmask of actions to be four or more frames ahead of the programmed one /** Process parameters that are overdue or due in ASAP mode (not through the sequencer) /** Process parameters in "normal way" - not ASAP or overdue * Called twice from processPars - at the beginning and at the end to finish off any derivatives (needed?) * Called twice from processPars - at the beginning and at the end to finish off any derivatives (needed?) * Should never be called from outside processPars() where there is a per-port lock */ * Should never be called from outside processPars() where there is a per-port lock */ Loading src/drivers/elphel/gamma_tables.c +25 −23 Original line number Original line Diff line number Diff line Loading @@ -132,14 +132,6 @@ #include "x393.h" #include "x393.h" #include "detect_sensors.h" #include "detect_sensors.h" #include "x393_fpga_functions.h" // to check bitsteram #include "x393_fpga_functions.h" // to check bitsteram #ifdef USE_GAMMA_LOCK #define GAMMA_LOCK_BH(x) spin_lock_bh(x) #define GAMMA_UNLOCK_BH(x) spin_unlock_bh(x) #else #define GAMMA_LOCK_BH(x) {} #define GAMMA_UNLOCK_BH(x) {} #endif /** /** * @brief optional debug output * @brief optional debug output Loading Loading @@ -176,12 +168,23 @@ static struct device *g_dev_ptr; static struct device *g_dev_ptr; static DEFINE_SPINLOCK(gamma_lock); ///< Non port-specific lock static DEFINE_SPINLOCK(gamma_lock); ///< Non port-specific lock static DEFINE_SPINLOCK(gamma_lock_0); ///< //static DEFINE_SPINLOCK(gamma_lock_0); ///< static DEFINE_SPINLOCK(gamma_lock_1); ///< //static DEFINE_SPINLOCK(gamma_lock_1); ///< static DEFINE_SPINLOCK(gamma_lock_2); ///< //static DEFINE_SPINLOCK(gamma_lock_2); ///< static DEFINE_SPINLOCK(gamma_lock_3); ///< //static DEFINE_SPINLOCK(gamma_lock_3); ///< /** Define array of pointers to locks - hardware allows concurrent writes to different ports tables */ /** Define array of pointers to locks - hardware allows concurrent writes to different ports tables */ spinlock_t * gamma_locks[4] = {&gamma_lock_0, &gamma_lock_1, &gamma_lock_2, &gamma_lock_3}; //spinlock_t * gamma_locks[4] = {&gamma_lock_0, &gamma_lock_1, &gamma_lock_2, &gamma_lock_3}; #ifdef USE_GAMMA_LOCK #define GAMMA_LOCK_BH(x) spin_lock_bh(x) #define GAMMA_UNLOCK_BH(x) spin_unlock_bh(x) #else #define GAMMA_LOCK_BH(x) {} #define GAMMA_UNLOCK_BH(x) {} #endif static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE))); static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE))); struct gamma_stuct_t * gammas_p; // to use with mmap struct gamma_stuct_t * gammas_p; // to use with mmap Loading Loading @@ -736,8 +739,7 @@ int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scale } } /** Writing gamma table to FPGA (1 color, 1 sub-channel) enabling IRQ after transferring each FPGA_TABLE_CHUNK DWORDs /** Writing gamma table to FPGA (1 color, 1 sub-channel) enabling IRQ after transferring each FPGA_TABLE_CHUNK DWORDs * * This function is only called from tasklet context, no extra locking is required */ * This code may be called from the IRQ context, and from the different CPU */ int fpga_gamma_write_nice(int color, ///< Color (0..3) int fpga_gamma_write_nice(int color, ///< Color (0..3) int sensor_port, ///< sensor port (0..3) int sensor_port, ///< sensor port (0..3) Loading @@ -756,7 +758,7 @@ int fpga_gamma_write_nice(int color, ///< Color (0..3) gamma_tbl_a.a_n_d = 1; gamma_tbl_a.a_n_d = 1; gamma_tbl_a.color = color; gamma_tbl_a.color = color; gamma_tbl_a.sub_chn = sensor_subchn; gamma_tbl_a.sub_chn = sensor_subchn; GAMMA_LOCK_BH(gamma_locks[sensor_port]); // GAMMA_LOCK_BH(gamma_locks[sensor_port]); for (addr32 = 0; addr32 < gamma_size; addr32 += FPGA_TABLE_CHUNK){ for (addr32 = 0; addr32 < gamma_size; addr32 += FPGA_TABLE_CHUNK){ len32 = FPGA_TABLE_CHUNK; len32 = FPGA_TABLE_CHUNK; if (unlikely(addr32 + len32 > gamma_size)) if (unlikely(addr32 + len32 > gamma_size)) Loading @@ -768,7 +770,7 @@ int fpga_gamma_write_nice(int color, ///< Color (0..3) x393_sens_gamma_tbl(gamma_tbl_d, sensor_port); x393_sens_gamma_tbl(gamma_tbl_d, sensor_port); } } } } GAMMA_UNLOCK_BH(gamma_locks[sensor_port]); // GAMMA_UNLOCK_BH(gamma_locks[sensor_port]); return 0; return 0; } } Loading src/drivers/elphel/histograms.c +140 −136 Original line number Original line Diff line number Diff line Loading @@ -110,7 +110,7 @@ // ##include <asm/dma-mapping.h> // ##include <asm/dma-mapping.h> #include <uapi/elphel/x393_devices.h> #include <uapi/elphel/x393_devices.h> #include <uapi/elphel/c313a.h> //#include <uapi/elphel/c313a.h> #include <uapi/elphel/exifa.h> #include <uapi/elphel/exifa.h> //#include "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr //#include "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr //#include "fpga_io.h"//fpga_table_write_nice //#include "fpga_io.h"//fpga_table_write_nice Loading Loading @@ -166,8 +166,8 @@ struct histogram_stuct_t * histograms_p; ///< alias of histogram_stuct_t /** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */ /** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */ static struct device *g_dev_ptr; static struct device *g_dev_ptr; wait_queue_head_t hist_y_wait_queue; ///< wait queue for the G1 histogram (used as Y) wait_queue_head_t ahist_y_wait_queue[SENSOR_PORTS]; ///< wait queue for the G1 histogram (used as Y) wait_queue_head_t hist_c_wait_queue; ///< wait queue for all the other (R,G2,B) histograms (color) wait_queue_head_t ahist_c_wait_queue[SENSOR_PORTS]; ///< wait queue for all the other (R,G2,B) histograms (color) void init_histograms(int chn_mask); ///< combined subchannels and ports Save mask to global P-variable void init_histograms(int chn_mask); ///< combined subchannels and ports Save mask to global P-variable int histograms_init_hardware(void); int histograms_init_hardware(void); static volatile int histograms_initialized = 0; ///< 0 - not initialized, 1 - structures only, 2 structures and hardware NC393: initialize when first used? static volatile int histograms_initialized = 0; ///< 0 - not initialized, 1 - structures only, 2 structures and hardware NC393: initialize when first used? Loading Loading @@ -206,7 +206,7 @@ int histograms_check_init(void) struct histograms_pd { struct histograms_pd { int minor; int minor; unsigned long frame; ///< absolute frame number requested unsigned long frame; ///< absolute frame number requested int frame_index; ///< histogram fame index (in cache and when accessing through mmap), -1 if invalid, int frame_index; ///< histogram frame index (in cache and when accessing through mmap), -1 if invalid, int needed; ///< bits specify what histograms (color, type) are requested int needed; ///< bits specify what histograms (color, type) are requested ///< each group of 4 bits covers 4 colors of the same type: ///< each group of 4 bits covers 4 colors of the same type: ///< - bits 0..3 - read raw histograms from the FPGA - normally called from IRQ/tasklet (use just 1 color for autoexposure to speed up?) ///< - bits 0..3 - read raw histograms from the FPGA - normally called from IRQ/tasklet (use just 1 color for autoexposure to speed up?) Loading Loading @@ -469,7 +469,7 @@ int get_histograms(int sensor_port, ///< sensor port number (0..3) } } index=GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn); // set_histograms may increment G_HIST_LAST_INDEX+sensor_chn index=GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn); // set_histograms may increment G_HIST_LAST_INDEX+sensor_chn for (i=0;i<HISTOGRAM_CACHE_NUMBER;i++) { for (i=0;i<HISTOGRAM_CACHE_NUMBER;i++) { dev_dbg(g_dev_ptr, "index=%d, needed=0x%x\n",index,needed); dev_dbg(g_dev_ptr, "hist_indx= %d, index=%d, needed=0x%x\n",hist_indx, index,needed); if ((histograms[hist_indx][index].frame <= frame) && ((histograms[hist_indx][index].valid & raw_needed)==raw_needed)) break; if ((histograms[hist_indx][index].frame <= frame) && ((histograms[hist_indx][index].valid & raw_needed)==raw_needed)) break; index = (index-1) & (HISTOGRAM_CACHE_NUMBER-1); index = (index-1) & (HISTOGRAM_CACHE_NUMBER-1); } } Loading Loading @@ -725,14 +725,14 @@ loff_t histograms_lseek (struct file * file, dev_dbg(g_dev_ptr, "privData->request_en=0\n"); dev_dbg(g_dev_ptr, "privData->request_en=0\n"); } } #if 0 #if 0 if (privData-> wait_mode) wait_event_interruptible (hist_c_wait_queue,GLOBALPARS(privData->port,G_HIST_C_FRAME + privData->subchannel)>=offset); if (privData-> wait_mode) wait_event_interruptible (ahist_c_wait_queue[privData->port],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); else wait_event_interruptible (ahist_y_wait_queue[privData->port],GLOBALPARS(privData->port,G_HIST_Y_FRAME + privData->subchannel)>=offset); #endif #endif dev_dbg(g_dev_ptr, "Before waiting: frame = 0x%x, offset=0x%x privData-> wait_mode=%d\n", dev_dbg(g_dev_ptr, "Before waiting: frame = 0x%x, offset=0x%x privData-> wait_mode=%d\n", (int) getThisFrameNumber(privData->port), (int) offset, privData-> wait_mode); (int) getThisFrameNumber(privData->port), (int) offset, privData-> wait_mode); // neded next frame after requested (modify php too?) // neded next frame after requested (modify php too?) if (privData-> wait_mode) wait_event_interruptible (hist_c_wait_queue,getThisFrameNumber(privData->port)>offset); if (privData-> wait_mode) wait_event_interruptible (ahist_c_wait_queue[privData->port],getThisFrameNumber(privData->port)>offset); else wait_event_interruptible (hist_y_wait_queue,getThisFrameNumber(privData->port)>offset); else wait_event_interruptible (ahist_y_wait_queue[privData->port],getThisFrameNumber(privData->port)>offset); dev_dbg(g_dev_ptr, "After waiting: frame = 0x%x\n", (int) getThisFrameNumber(privData->port)); dev_dbg(g_dev_ptr, "After waiting: frame = 0x%x\n", (int) getThisFrameNumber(privData->port)); privData->frame_index = get_histograms (privData->port, privData->subchannel, offset, privData->needed); privData->frame_index = get_histograms (privData->port, privData->subchannel, offset, privData->needed); if (privData->frame_index <0) { if (privData->frame_index <0) { Loading Loading @@ -776,12 +776,12 @@ loff_t histograms_lseek (struct file * file, default: default: switch (offset & ~0x1f) { switch (offset & ~0x1f) { case LSEEK_DAEMON_HIST_Y: // wait for daemon enabled and histograms Y ready case LSEEK_DAEMON_HIST_Y: // wait for daemon enabled and histograms Y ready dev_dbg(g_dev_ptr, "wait_event_interruptible (hist_y_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))); dev_dbg(g_dev_ptr, "wait_event_interruptible (ahist_y_wait_queue[%d],0x%x & 0x%x)\n",privData->port, (int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))); wait_event_interruptible (hist_y_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f))); wait_event_interruptible (ahist_y_wait_queue[privData->port], get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f))); break; break; case LSEEK_DAEMON_HIST_C: // wait for daemon enabled and histograms Y ready case LSEEK_DAEMON_HIST_C: // wait for daemon enabled and histograms Y ready dev_dbg(g_dev_ptr, "wait_event_interruptible (hist_c_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))); dev_dbg(g_dev_ptr, "wait_event_interruptible (ahist_c_wait_queue[%d],0x%x & 0x%x)\n",privData->port, (int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))); wait_event_interruptible (hist_c_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f))); wait_event_interruptible (ahist_c_wait_queue[privData->port], get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f))); break; break; default: default: return -EINVAL; return -EINVAL; Loading @@ -793,12 +793,14 @@ loff_t histograms_lseek (struct file * file, return -EINVAL; return -EINVAL; } } file->f_pos= HISTOGRAMS_FILE_SIZE; file->f_pos= HISTOGRAMS_FILE_SIZE; dev_dbg(g_dev_ptr, "file->f_pos = HISTOGRAMS_FILE_SIZE = 0x%x\n", (int) file->f_pos); return file->f_pos; return file->f_pos; } } break; break; default: // not SEEK_SET/SEEK_CUR/SEEK_END default: // not SEEK_SET/SEEK_CUR/SEEK_END return -EINVAL; return -EINVAL; } // switch (orig) } // switch (orig) dev_dbg(g_dev_ptr, "file->f_pos = 0x%x\n", (int) file->f_pos); return file->f_pos ; return file->f_pos ; default: // other minors default: // other minors return -EINVAL; return -EINVAL; Loading Loading @@ -834,7 +836,7 @@ int histograms_mmap (struct file *file, struct vm_area_struct *vma) { * @return 0 * @return 0 */ */ int histograms_init(struct platform_device *pdev) { int histograms_init(struct platform_device *pdev) { int res; int res,i; int sz, pages; int sz, pages; struct device *dev = &pdev->dev; struct device *dev = &pdev->dev; // const struct of_device_id *match; // not yet used // const struct of_device_id *match; // not yet used Loading @@ -846,8 +848,10 @@ int histograms_init(struct platform_device *pdev) { return res; return res; } } // init_waitqueue_head(&histograms_wait_queue); // init_waitqueue_head(&histograms_wait_queue); init_waitqueue_head(&hist_y_wait_queue); // wait queue for the G1 histogram (used as Y) for (i = 0; i < SENSOR_PORTS; i++) { init_waitqueue_head(&hist_c_wait_queue); // wait queue for all the other (R,G2,B) histograms (color) init_waitqueue_head(&ahist_y_wait_queue[i]); // wait queue for the G1 histogram (used as Y) init_waitqueue_head(&ahist_c_wait_queue[i]); // wait queue for all the other (R,G2,B) histograms (color) } dev_info(dev, DEV393_NAME(DEV393_HISTOGRAM)": registered MAJOR: %d\n", DEV393_MAJOR(DEV393_HISTOGRAM)); dev_info(dev, DEV393_NAME(DEV393_HISTOGRAM)": registered MAJOR: %d\n", DEV393_MAJOR(DEV393_HISTOGRAM)); histograms_initialized = 0; histograms_initialized = 0; // NC393: Did not find a way to get memory when histograms a first needed: // NC393: Did not find a way to get memory when histograms a first needed: Loading src/drivers/elphel/histograms.h +3 −3 Original line number Original line Diff line number Diff line Loading @@ -17,12 +17,12 @@ #ifndef HISTOGRAMS_H #ifndef HISTOGRAMS_H #define HISTOGRAMS_H #define HISTOGRAMS_H #undef ISR_HISTOGRAMS // to histograms-related disable code in ISR - not needed in NC393 #undef ISR_HISTOGRAMS // to histograms-related disable code in ISR - not needed in NC393 #include <uapi/elphel/c313a.h> // These wait queues will be advanced each frame after the histogram data is transferred to the FPGA. // These wait queues will be advanced each frame after the histogram data is transferred to the FPGA. // It will happen even if the corresponding task is disabled, with the only exception: // It will happen even if the corresponding task is disabled, with the only exception: // hist_c_wait_queue will not be awaken in the current frame if it is too late (frame counter incremented while serving tasklet) // hist_c_wait_queue will not be awaken in the current frame if it is too late (frame counter incremented while serving tasklet) extern wait_queue_head_t hist_y_wait_queue; /// wait queue for the G1 histogram (used as Y) extern wait_queue_head_t ahist_y_wait_queue[SENSOR_PORTS]; /// wait queue for the G1 histogram (used as Y) extern wait_queue_head_t hist_c_wait_queue; /// wait queue for all the other (R,G2,B) histograms (color) extern wait_queue_head_t ahist_c_wait_queue[SENSOR_PORTS]; /// wait queue for all the other (R,G2,B) histograms (color) // void init_histograms(int chn_mask); // void init_histograms(int chn_mask); int histograms_check_init(void); int histograms_check_init(void); Loading Loading
src/drivers/elphel/circbuf.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -824,7 +824,8 @@ unsigned int circbuf_poll (struct file *file, poll_table *wait) int rslt; int rslt; dev_dbg(g_dev_ptr, "minor = 0x%x\n", minor); dev_dbg(g_dev_ptr, "minor = 0x%x\n", minor); rslt = circbufValidPointer(&file->f_pos, &fp, chn); // rslt = circbufValidPointer(&file->f_pos, &fp, chn); rslt = circbufValidPointer(file->f_pos, &fp, chn); if (rslt < 0) { if (rslt < 0) { // not a valid read pointer, probable buffer overrun // not a valid read pointer, probable buffer overrun dev_dbg(g_dev_ptr, "invalid pointer file->f_pos = 0x%llx\n", file->f_pos); dev_dbg(g_dev_ptr, "invalid pointer file->f_pos = 0x%llx\n", file->f_pos); Loading
src/drivers/elphel/framepars.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -826,7 +826,7 @@ inline void _processParsASAP(int sensor_port, ///< sensor port //#define G_CALLNEXT3 122 // bitmask of actions to be three or more frames ahead of the programmed one (OR-ed with G_CALLNEXT4) //#define G_CALLNEXT3 122 // bitmask of actions to be three or more frames ahead of the programmed one (OR-ed with G_CALLNEXT4) //#define G_CALLNEXT4 123 // bitmask of actions to be four or more frames ahead of the programmed one //#define G_CALLNEXT4 123 // bitmask of actions to be four or more frames ahead of the programmed one /** Process parameters that are overdue or due in ASAP mode (not through the sequencer) /** Process parameters in "normal way" - not ASAP or overdue * Called twice from processPars - at the beginning and at the end to finish off any derivatives (needed?) * Called twice from processPars - at the beginning and at the end to finish off any derivatives (needed?) * Should never be called from outside processPars() where there is a per-port lock */ * Should never be called from outside processPars() where there is a per-port lock */ Loading
src/drivers/elphel/gamma_tables.c +25 −23 Original line number Original line Diff line number Diff line Loading @@ -132,14 +132,6 @@ #include "x393.h" #include "x393.h" #include "detect_sensors.h" #include "detect_sensors.h" #include "x393_fpga_functions.h" // to check bitsteram #include "x393_fpga_functions.h" // to check bitsteram #ifdef USE_GAMMA_LOCK #define GAMMA_LOCK_BH(x) spin_lock_bh(x) #define GAMMA_UNLOCK_BH(x) spin_unlock_bh(x) #else #define GAMMA_LOCK_BH(x) {} #define GAMMA_UNLOCK_BH(x) {} #endif /** /** * @brief optional debug output * @brief optional debug output Loading Loading @@ -176,12 +168,23 @@ static struct device *g_dev_ptr; static struct device *g_dev_ptr; static DEFINE_SPINLOCK(gamma_lock); ///< Non port-specific lock static DEFINE_SPINLOCK(gamma_lock); ///< Non port-specific lock static DEFINE_SPINLOCK(gamma_lock_0); ///< //static DEFINE_SPINLOCK(gamma_lock_0); ///< static DEFINE_SPINLOCK(gamma_lock_1); ///< //static DEFINE_SPINLOCK(gamma_lock_1); ///< static DEFINE_SPINLOCK(gamma_lock_2); ///< //static DEFINE_SPINLOCK(gamma_lock_2); ///< static DEFINE_SPINLOCK(gamma_lock_3); ///< //static DEFINE_SPINLOCK(gamma_lock_3); ///< /** Define array of pointers to locks - hardware allows concurrent writes to different ports tables */ /** Define array of pointers to locks - hardware allows concurrent writes to different ports tables */ spinlock_t * gamma_locks[4] = {&gamma_lock_0, &gamma_lock_1, &gamma_lock_2, &gamma_lock_3}; //spinlock_t * gamma_locks[4] = {&gamma_lock_0, &gamma_lock_1, &gamma_lock_2, &gamma_lock_3}; #ifdef USE_GAMMA_LOCK #define GAMMA_LOCK_BH(x) spin_lock_bh(x) #define GAMMA_UNLOCK_BH(x) spin_unlock_bh(x) #else #define GAMMA_LOCK_BH(x) {} #define GAMMA_UNLOCK_BH(x) {} #endif static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE))); static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE))); struct gamma_stuct_t * gammas_p; // to use with mmap struct gamma_stuct_t * gammas_p; // to use with mmap Loading Loading @@ -736,8 +739,7 @@ int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scale } } /** Writing gamma table to FPGA (1 color, 1 sub-channel) enabling IRQ after transferring each FPGA_TABLE_CHUNK DWORDs /** Writing gamma table to FPGA (1 color, 1 sub-channel) enabling IRQ after transferring each FPGA_TABLE_CHUNK DWORDs * * This function is only called from tasklet context, no extra locking is required */ * This code may be called from the IRQ context, and from the different CPU */ int fpga_gamma_write_nice(int color, ///< Color (0..3) int fpga_gamma_write_nice(int color, ///< Color (0..3) int sensor_port, ///< sensor port (0..3) int sensor_port, ///< sensor port (0..3) Loading @@ -756,7 +758,7 @@ int fpga_gamma_write_nice(int color, ///< Color (0..3) gamma_tbl_a.a_n_d = 1; gamma_tbl_a.a_n_d = 1; gamma_tbl_a.color = color; gamma_tbl_a.color = color; gamma_tbl_a.sub_chn = sensor_subchn; gamma_tbl_a.sub_chn = sensor_subchn; GAMMA_LOCK_BH(gamma_locks[sensor_port]); // GAMMA_LOCK_BH(gamma_locks[sensor_port]); for (addr32 = 0; addr32 < gamma_size; addr32 += FPGA_TABLE_CHUNK){ for (addr32 = 0; addr32 < gamma_size; addr32 += FPGA_TABLE_CHUNK){ len32 = FPGA_TABLE_CHUNK; len32 = FPGA_TABLE_CHUNK; if (unlikely(addr32 + len32 > gamma_size)) if (unlikely(addr32 + len32 > gamma_size)) Loading @@ -768,7 +770,7 @@ int fpga_gamma_write_nice(int color, ///< Color (0..3) x393_sens_gamma_tbl(gamma_tbl_d, sensor_port); x393_sens_gamma_tbl(gamma_tbl_d, sensor_port); } } } } GAMMA_UNLOCK_BH(gamma_locks[sensor_port]); // GAMMA_UNLOCK_BH(gamma_locks[sensor_port]); return 0; return 0; } } Loading
src/drivers/elphel/histograms.c +140 −136 Original line number Original line Diff line number Diff line Loading @@ -110,7 +110,7 @@ // ##include <asm/dma-mapping.h> // ##include <asm/dma-mapping.h> #include <uapi/elphel/x393_devices.h> #include <uapi/elphel/x393_devices.h> #include <uapi/elphel/c313a.h> //#include <uapi/elphel/c313a.h> #include <uapi/elphel/exifa.h> #include <uapi/elphel/exifa.h> //#include "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr //#include "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr //#include "fpga_io.h"//fpga_table_write_nice //#include "fpga_io.h"//fpga_table_write_nice Loading Loading @@ -166,8 +166,8 @@ struct histogram_stuct_t * histograms_p; ///< alias of histogram_stuct_t /** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */ /** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */ static struct device *g_dev_ptr; static struct device *g_dev_ptr; wait_queue_head_t hist_y_wait_queue; ///< wait queue for the G1 histogram (used as Y) wait_queue_head_t ahist_y_wait_queue[SENSOR_PORTS]; ///< wait queue for the G1 histogram (used as Y) wait_queue_head_t hist_c_wait_queue; ///< wait queue for all the other (R,G2,B) histograms (color) wait_queue_head_t ahist_c_wait_queue[SENSOR_PORTS]; ///< wait queue for all the other (R,G2,B) histograms (color) void init_histograms(int chn_mask); ///< combined subchannels and ports Save mask to global P-variable void init_histograms(int chn_mask); ///< combined subchannels and ports Save mask to global P-variable int histograms_init_hardware(void); int histograms_init_hardware(void); static volatile int histograms_initialized = 0; ///< 0 - not initialized, 1 - structures only, 2 structures and hardware NC393: initialize when first used? static volatile int histograms_initialized = 0; ///< 0 - not initialized, 1 - structures only, 2 structures and hardware NC393: initialize when first used? Loading Loading @@ -206,7 +206,7 @@ int histograms_check_init(void) struct histograms_pd { struct histograms_pd { int minor; int minor; unsigned long frame; ///< absolute frame number requested unsigned long frame; ///< absolute frame number requested int frame_index; ///< histogram fame index (in cache and when accessing through mmap), -1 if invalid, int frame_index; ///< histogram frame index (in cache and when accessing through mmap), -1 if invalid, int needed; ///< bits specify what histograms (color, type) are requested int needed; ///< bits specify what histograms (color, type) are requested ///< each group of 4 bits covers 4 colors of the same type: ///< each group of 4 bits covers 4 colors of the same type: ///< - bits 0..3 - read raw histograms from the FPGA - normally called from IRQ/tasklet (use just 1 color for autoexposure to speed up?) ///< - bits 0..3 - read raw histograms from the FPGA - normally called from IRQ/tasklet (use just 1 color for autoexposure to speed up?) Loading Loading @@ -469,7 +469,7 @@ int get_histograms(int sensor_port, ///< sensor port number (0..3) } } index=GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn); // set_histograms may increment G_HIST_LAST_INDEX+sensor_chn index=GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn); // set_histograms may increment G_HIST_LAST_INDEX+sensor_chn for (i=0;i<HISTOGRAM_CACHE_NUMBER;i++) { for (i=0;i<HISTOGRAM_CACHE_NUMBER;i++) { dev_dbg(g_dev_ptr, "index=%d, needed=0x%x\n",index,needed); dev_dbg(g_dev_ptr, "hist_indx= %d, index=%d, needed=0x%x\n",hist_indx, index,needed); if ((histograms[hist_indx][index].frame <= frame) && ((histograms[hist_indx][index].valid & raw_needed)==raw_needed)) break; if ((histograms[hist_indx][index].frame <= frame) && ((histograms[hist_indx][index].valid & raw_needed)==raw_needed)) break; index = (index-1) & (HISTOGRAM_CACHE_NUMBER-1); index = (index-1) & (HISTOGRAM_CACHE_NUMBER-1); } } Loading Loading @@ -725,14 +725,14 @@ loff_t histograms_lseek (struct file * file, dev_dbg(g_dev_ptr, "privData->request_en=0\n"); dev_dbg(g_dev_ptr, "privData->request_en=0\n"); } } #if 0 #if 0 if (privData-> wait_mode) wait_event_interruptible (hist_c_wait_queue,GLOBALPARS(privData->port,G_HIST_C_FRAME + privData->subchannel)>=offset); if (privData-> wait_mode) wait_event_interruptible (ahist_c_wait_queue[privData->port],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); else wait_event_interruptible (ahist_y_wait_queue[privData->port],GLOBALPARS(privData->port,G_HIST_Y_FRAME + privData->subchannel)>=offset); #endif #endif dev_dbg(g_dev_ptr, "Before waiting: frame = 0x%x, offset=0x%x privData-> wait_mode=%d\n", dev_dbg(g_dev_ptr, "Before waiting: frame = 0x%x, offset=0x%x privData-> wait_mode=%d\n", (int) getThisFrameNumber(privData->port), (int) offset, privData-> wait_mode); (int) getThisFrameNumber(privData->port), (int) offset, privData-> wait_mode); // neded next frame after requested (modify php too?) // neded next frame after requested (modify php too?) if (privData-> wait_mode) wait_event_interruptible (hist_c_wait_queue,getThisFrameNumber(privData->port)>offset); if (privData-> wait_mode) wait_event_interruptible (ahist_c_wait_queue[privData->port],getThisFrameNumber(privData->port)>offset); else wait_event_interruptible (hist_y_wait_queue,getThisFrameNumber(privData->port)>offset); else wait_event_interruptible (ahist_y_wait_queue[privData->port],getThisFrameNumber(privData->port)>offset); dev_dbg(g_dev_ptr, "After waiting: frame = 0x%x\n", (int) getThisFrameNumber(privData->port)); dev_dbg(g_dev_ptr, "After waiting: frame = 0x%x\n", (int) getThisFrameNumber(privData->port)); privData->frame_index = get_histograms (privData->port, privData->subchannel, offset, privData->needed); privData->frame_index = get_histograms (privData->port, privData->subchannel, offset, privData->needed); if (privData->frame_index <0) { if (privData->frame_index <0) { Loading Loading @@ -776,12 +776,12 @@ loff_t histograms_lseek (struct file * file, default: default: switch (offset & ~0x1f) { switch (offset & ~0x1f) { case LSEEK_DAEMON_HIST_Y: // wait for daemon enabled and histograms Y ready case LSEEK_DAEMON_HIST_Y: // wait for daemon enabled and histograms Y ready dev_dbg(g_dev_ptr, "wait_event_interruptible (hist_y_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))); dev_dbg(g_dev_ptr, "wait_event_interruptible (ahist_y_wait_queue[%d],0x%x & 0x%x)\n",privData->port, (int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))); wait_event_interruptible (hist_y_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f))); wait_event_interruptible (ahist_y_wait_queue[privData->port], get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f))); break; break; case LSEEK_DAEMON_HIST_C: // wait for daemon enabled and histograms Y ready case LSEEK_DAEMON_HIST_C: // wait for daemon enabled and histograms Y ready dev_dbg(g_dev_ptr, "wait_event_interruptible (hist_c_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))); dev_dbg(g_dev_ptr, "wait_event_interruptible (ahist_c_wait_queue[%d],0x%x & 0x%x)\n",privData->port, (int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))); wait_event_interruptible (hist_c_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f))); wait_event_interruptible (ahist_c_wait_queue[privData->port], get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f))); break; break; default: default: return -EINVAL; return -EINVAL; Loading @@ -793,12 +793,14 @@ loff_t histograms_lseek (struct file * file, return -EINVAL; return -EINVAL; } } file->f_pos= HISTOGRAMS_FILE_SIZE; file->f_pos= HISTOGRAMS_FILE_SIZE; dev_dbg(g_dev_ptr, "file->f_pos = HISTOGRAMS_FILE_SIZE = 0x%x\n", (int) file->f_pos); return file->f_pos; return file->f_pos; } } break; break; default: // not SEEK_SET/SEEK_CUR/SEEK_END default: // not SEEK_SET/SEEK_CUR/SEEK_END return -EINVAL; return -EINVAL; } // switch (orig) } // switch (orig) dev_dbg(g_dev_ptr, "file->f_pos = 0x%x\n", (int) file->f_pos); return file->f_pos ; return file->f_pos ; default: // other minors default: // other minors return -EINVAL; return -EINVAL; Loading Loading @@ -834,7 +836,7 @@ int histograms_mmap (struct file *file, struct vm_area_struct *vma) { * @return 0 * @return 0 */ */ int histograms_init(struct platform_device *pdev) { int histograms_init(struct platform_device *pdev) { int res; int res,i; int sz, pages; int sz, pages; struct device *dev = &pdev->dev; struct device *dev = &pdev->dev; // const struct of_device_id *match; // not yet used // const struct of_device_id *match; // not yet used Loading @@ -846,8 +848,10 @@ int histograms_init(struct platform_device *pdev) { return res; return res; } } // init_waitqueue_head(&histograms_wait_queue); // init_waitqueue_head(&histograms_wait_queue); init_waitqueue_head(&hist_y_wait_queue); // wait queue for the G1 histogram (used as Y) for (i = 0; i < SENSOR_PORTS; i++) { init_waitqueue_head(&hist_c_wait_queue); // wait queue for all the other (R,G2,B) histograms (color) init_waitqueue_head(&ahist_y_wait_queue[i]); // wait queue for the G1 histogram (used as Y) init_waitqueue_head(&ahist_c_wait_queue[i]); // wait queue for all the other (R,G2,B) histograms (color) } dev_info(dev, DEV393_NAME(DEV393_HISTOGRAM)": registered MAJOR: %d\n", DEV393_MAJOR(DEV393_HISTOGRAM)); dev_info(dev, DEV393_NAME(DEV393_HISTOGRAM)": registered MAJOR: %d\n", DEV393_MAJOR(DEV393_HISTOGRAM)); histograms_initialized = 0; histograms_initialized = 0; // NC393: Did not find a way to get memory when histograms a first needed: // NC393: Did not find a way to get memory when histograms a first needed: Loading
src/drivers/elphel/histograms.h +3 −3 Original line number Original line Diff line number Diff line Loading @@ -17,12 +17,12 @@ #ifndef HISTOGRAMS_H #ifndef HISTOGRAMS_H #define HISTOGRAMS_H #define HISTOGRAMS_H #undef ISR_HISTOGRAMS // to histograms-related disable code in ISR - not needed in NC393 #undef ISR_HISTOGRAMS // to histograms-related disable code in ISR - not needed in NC393 #include <uapi/elphel/c313a.h> // These wait queues will be advanced each frame after the histogram data is transferred to the FPGA. // These wait queues will be advanced each frame after the histogram data is transferred to the FPGA. // It will happen even if the corresponding task is disabled, with the only exception: // It will happen even if the corresponding task is disabled, with the only exception: // hist_c_wait_queue will not be awaken in the current frame if it is too late (frame counter incremented while serving tasklet) // hist_c_wait_queue will not be awaken in the current frame if it is too late (frame counter incremented while serving tasklet) extern wait_queue_head_t hist_y_wait_queue; /// wait queue for the G1 histogram (used as Y) extern wait_queue_head_t ahist_y_wait_queue[SENSOR_PORTS]; /// wait queue for the G1 histogram (used as Y) extern wait_queue_head_t hist_c_wait_queue; /// wait queue for all the other (R,G2,B) histograms (color) extern wait_queue_head_t ahist_c_wait_queue[SENSOR_PORTS]; /// wait queue for all the other (R,G2,B) histograms (color) // void init_histograms(int chn_mask); // void init_histograms(int chn_mask); int histograms_check_init(void); int histograms_check_init(void); Loading