Commit 0f25f13b authored by Mikhail Karpenko's avatar Mikhail Karpenko
Browse files

Merge 'framepars'

parent ba32b44b
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -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);
+2 −2
Original line number Original line Diff line number Diff line
@@ -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 */


+25 −23
Original line number Original line Diff line number Diff line
@@ -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 
@@ -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
@@ -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)
@@ -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))
@@ -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;
}
}


+140 −136
Original line number Original line Diff line number Diff line
@@ -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
@@ -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?
@@ -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?)
@@ -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);
    }
    }
@@ -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) {
@@ -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;
@@ -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;
@@ -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
@@ -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:
+3 −3
Original line number Original line Diff line number Diff line
@@ -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