Commit cffce9dc authored by Andrey Filippov's avatar Andrey Filippov
Browse files

optimizing fpga tables write

parent 9a0d39a7
Loading
Loading
Loading
Loading
+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;
}
}


+22 −14
Original line number Original line Diff line number Diff line
@@ -63,14 +63,13 @@
//#include "circbuf.h"
//#include "circbuf.h"
//#include "sensor_common.h"
//#include "sensor_common.h"
//#include "exif.h"
//#include "exif.h"
#include "x393_macro.h"
#include "x393_fpga_functions.h"
#include "x393_macro.h" // X313_LENGTH_MASK
#include "x393.h"
#include "x393.h"


static struct device *g_dev_ptr = NULL;
static struct device *g_dev_ptr = NULL;


/**
/** All Huffman tables data to be read/written from the user space */
 * @brief All Huffman tables data to be read/written from the application
 */
struct huff_tables_t {
struct huff_tables_t {
	struct huffman_encoded_t header_huffman_tables[4];
	struct huffman_encoded_t header_huffman_tables[4];
	unsigned long            fpga_huffman_table[512];
	unsigned long            fpga_huffman_table[512];
@@ -109,8 +108,8 @@ static struct jpeghead_priv_t {
 */
 */
int qtables_create(struct interframe_params_t *params, unsigned char *buf, unsigned int chn)
int qtables_create(struct interframe_params_t *params, unsigned char *buf, unsigned int chn)
{
{
	dev_dbg(g_dev_ptr, "params->quality2 = 0x%x\n", params->quality2);
    int rslt = get_qtable(params->quality2, &buf[0], &buf[64], chn); /// will copy both quantization tables
    int rslt = get_qtable(params->quality2, &buf[0], &buf[64], chn); /// will copy both quantization tables
	dev_dbg(g_dev_ptr, "params->quality2 = 0x%x\n", params->quality2);
	if (rslt < 0) return rslt; /// bad quality table
	if (rslt < 0) return rslt; /// bad quality table
	return 128;
	return 128;
}
}
@@ -343,7 +342,7 @@ int jpeghead_open(struct inode *inode, struct file *filp)
loff_t jpeghead_lseek(struct file *file, loff_t offset, int orig,
loff_t jpeghead_lseek(struct file *file, loff_t offset, int orig,
		struct interframe_params_t *fp)
		struct interframe_params_t *fp)
{
{
	int rp;
//	int rp;
	unsigned int minor = MINOR(file->f_inode->i_rdev);
	unsigned int minor = MINOR(file->f_inode->i_rdev);
	unsigned int chn = minor_to_chn(minor, NULL);
	unsigned int chn = minor_to_chn(minor, NULL);


@@ -396,7 +395,7 @@ ssize_t jpeghead_read(struct file *file, char *buf, size_t count, loff_t *off)
	unsigned int minor = MINOR(file->f_inode->i_rdev);
	unsigned int minor = MINOR(file->f_inode->i_rdev);
	unsigned int chn = minor_to_chn(minor, NULL);
	unsigned int chn = minor_to_chn(minor, NULL);


	dev_dbg(g_dev_ptr, "reading from jpeghead, minor = 0x%x, off = 0x%lld\n", minor, off);
	dev_dbg(g_dev_ptr, "reading from jpeghead, minor = 0x%x, off = 0x%lld\n", minor, *off);


	p = *off;
	p = *off;
	if (p >= jpeghead_priv[chn].jpeg_h_sz)
	if (p >= jpeghead_priv[chn].jpeg_h_sz)
@@ -495,7 +494,7 @@ ssize_t huffman_read(struct file *file, char *buf, size_t count, loff_t *off)
	unsigned int chn = minor_to_chn(minor, NULL);
	unsigned int chn = minor_to_chn(minor, NULL);
	unsigned char *uc_huff_tables = (unsigned char *) &jpeghead_priv[chn].huff_tables;
	unsigned char *uc_huff_tables = (unsigned char *) &jpeghead_priv[chn].huff_tables;


	dev_dbg(g_dev_ptr, "reading from huffman, minor = 0x%x, off = 0x%llx\n", minor, off);
	dev_dbg(g_dev_ptr, "reading from huffman, minor = 0x%x, off = 0x%llx\n", minor, *off);


	p = *off;
	p = *off;
	if (p >= sizeof(struct huff_tables_t))
	if (p >= sizeof(struct huff_tables_t))
@@ -516,7 +515,7 @@ ssize_t huffman_write(struct file *file, const char *buf, size_t count, loff_t *
	unsigned int chn = minor_to_chn(minor, NULL);
	unsigned int chn = minor_to_chn(minor, NULL);
	unsigned char * uc_huff_tables= (unsigned char *) &jpeghead_priv[chn].huff_tables;
	unsigned char * uc_huff_tables= (unsigned char *) &jpeghead_priv[chn].huff_tables;


	dev_dbg(g_dev_ptr, "writing to huffman, minor = 0x%x, off = 0x%llx\n", minor, off);
	dev_dbg(g_dev_ptr, "writing to huffman, minor = 0x%x, off = 0x%llx\n", minor, *off);


	p = *off;
	p = *off;
	if (p >= sizeof(struct huff_tables_t))
	if (p >= sizeof(struct huff_tables_t))
@@ -676,17 +675,26 @@ void jpeg_htable_fpga_pgm(unsigned int chn)
{
{
	int i;
	int i;
	unsigned long flags;
	unsigned long flags;
	x393_cmprs_table_addr_t table_addr;
	struct huff_tables_t *huff_tables = &jpeghead_priv[chn].huff_tables;
	struct huff_tables_t *huff_tables = &jpeghead_priv[chn].huff_tables;

    int len = sizeof(huff_tables->fpga_huffman_table) / sizeof(huff_tables->fpga_huffman_table[0]);
#if 0
    x393_cmprs_table_addr_t table_addr;
	table_addr.addr32 = 0;
	table_addr.addr32 = 0;
	table_addr.type = 3;
	table_addr.type = 3;
	local_ irq_save(flags);
	local_ irq_save(flags);
	x393_cmprs_tables_address(table_addr, chn);
	x393_cmprs_tables_address(table_addr, chn);
	for (i = 0; i < sizeof(huff_tables->fpga_huffman_table) / sizeof(huff_tables->fpga_huffman_table[0]); i++) {
	for (i = 0; i < len; i++) {
		x393_cmprs_tables_data((u32)huff_tables->fpga_huffman_table[i], chn);
		x393_cmprs_tables_data((u32)huff_tables->fpga_huffman_table[i], chn);
	}
	}
	local_ irq_restore(flags);
	local_ irq_restore(flags);
#endif
    write_compressor_table(chn,
                           TABLE_TYPE_HUFFMAN,
                           0,
                           len,
                           (u32*) huff_tables->fpga_huffman_table );


	jpeghead_priv[chn].fpga_programmed = 1;
	jpeghead_priv[chn].fpga_programmed = 1;
}
}


+0 −138
Original line number Original line Diff line number Diff line
///@file legacy_defines.h
#define X313_MAXWIDTH       65536 // 4096 // multiple of 128
#define X313_MAXHEIGHT      65536 // 16384 // multiple of 16 - unsafe - not enough room for black level subtraction
#define X313_MAXHEIGHT_SAFE 65536 // 4096 // multiple of 16  OK for black level subtraction TODO: disable black level if unsafe
#define X313_MAP_FRAME ((X313_MAP_FPN) + (X313_MAXWIDTH) * (X313_MAXHEIGHT_SAFE))
#define X313_MARGINS 4
#define X313_TILEHOR 16
#define X313_TILEVERT 16
#define   X313_TIMESTAMPLEN 28 // pixels used for timestamp (in linescan mode added after the line)

#define   X3X3_RSTSENSDCM          // FPGA DCM can fail after clock change, needs to be reset
#define   X3X3_SENSDCM_CLK2X_RESET // reset pclk2x DCM also
#define I2C359_CLK_NUMBER 4


#define     CCAM_NEGRST   //set negative MRST polarity
#define     CCAM_TRIG_INT
#define     CCAM_MRST_OFF
#define     CCAM_ARST_OFF
#define     CCAM_ARST_ON
#define     CCAM_RESET_MCONTR_ON  // Set mode that resets memory controller pointers after each frame sync. TODO: Later - make it work without?
#define     CCAM_ENDFRAMES_EN     // Enable ending frame being compressed if no more data will be available (frame ended before specified number of blocks compressed)
#define     CCAM_ARO_ON //set


#define     CCAM_DCLK_ON
#define     CCAM_CNVEN_OFF
#define     CCAM_MRST_ON
#define     CCAM_EXTERNALTS_EN // Maybe use default as enabled - yes, it will not be active if not available
#define     CCAM_CNVEN_ON
#define     CCAM_POSRST

#define     X3X3_SENSDCM_HACT_ZERO
#define     X3X3_SENSDCM_HACT_LATE90
#define     X3X3_SENSDCM_HACT_EARLY90

#define     X3X3_SENSDCM_INC
#define     X3X3_SENSDCM_DEC
#define     X3X3_SENSDCM_INC90
#define     X3X3_SENSDCM_DEC90

#define     X3X3_SEQ_RUN

 #define COMPCMD_DEMOS(x) ((1<<13) | (((x) & 0x0f) << 9))
 //  6 blocks output per macroblock:
 #define DEMOS_MONO6     0 // original monochrome YCbCr 4:2:0 with zeroed color components
 #define DEMOS_COLOR18   1 // original color YCbCr 4:2:0, 3x3 demosaic (18x18 tiles)
 #define DEMOS_JP46      2 // original jp4, (4:2:0, zero color), decoded by regular JPEG decoder
 #define DEMOS_JP46DC    3 // dc-improved: same as DEMOS_JP46, but DC difference separate for each component
 #define DEMOS_COLOR20   4 // color YCbCr 4:2:0, 5x5 demosaic (20x20 tiles) - not yet implemented
//  4 blocks output per macroblock:
 #define DEMOS_JP4       5 // similar to DEMOS_JP46 ,   but zero color components are not output
 #define DEMOS_JP4DC     6 // similar to DEMOS_JP46DC , but zero color components are not output
 #define DEMOS_JP4DIFF   7 // differential red := (R-G1), blue:=(B-G1), green=G1, green2 (G2-G1). G1 is defined by Bayer shift, any pixel can be used
 #define DEMOS_JP4HDR    8 // similar to DEMOS_JP4DIFF, but second green (opposite from the reference one) is encoded without subtracting:
                           // red := (R-G1), blue:=(B-G1), green=G1, green2 (high gain)=G2) (G1 and G2 - diagonally opposite)
 #define DEMOS_JP4DIFF2  9 // similar to DEMOS_JP4DIFF, but all differences are divided by 2 to fit into 8 bit range:
                           // red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (G2-G1)/2
 #define DEMOS_JP4HDR2  10 // red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (high gain)=G2),
 #define DEMOS_MONO4    14 // monochrome, but the block scan order is still the same as in YCbCr 4:2:0 (macroblocks in scan order, block in 2x2 macroblock in scan order)

// [8:7] == 0,1 - NOP, 2 - disable, 3 - enable subtracting of average value (DC component), bypassing DCT

 #define COMPCMD_DCSUB(x) ((1<<8) | (((x) & 1) << 7))

// [6] == 1 - enable quantization bank select, 0 - disregard bits [5:3]
// [5:3] = quantization page number (0..7)

 #define COMPCMD_QTAB(x) ((1<<6) | (((x) & 7) << 3))




#define CONFIG_ETRAX_ELPHEL_MT9X001 1
//pgm_functions:pgm_detect_sensor
// void x313_dma_stop()    {}
// void x313_dma_init()    {}
// void reset_compressor() {} // available in sensor_common (make sure it does it all
 void i2c_run(void);
 void i2c_stop_wait(void);

// if ((gtable= get_gamma_fpga(color))) fpga_table_write_nice (CX313_FPGA_TABLES_GAMMA + (color * 256), 256, gtable);



// X3X3_SEQ_SEND1(frame16,  X313_WA_DCR0, X353_DCR0(SENSTRIGEN,async));

#ifdef NC353
 void i2c_reset_wait(void) {X3X3_I2C_RESET_WAIT;i2c_hardware_on=0;}
 void i2c_stop_wait(void) {X3X3_I2C_STOP_WAIT;  i2c_hardware_on=0;}
 void i2c_run(void)       {X3X3_I2C_RUN;        i2c_hardware_on=1;}
 int  i2s_running(void)   {return i2c_hardware_on;}



 /// IRQ-safe "nice" FPGA table write and histogram read functions - they split the data in chunks of fixed size,
 /// disable IRQ, transfer a chunk, then reenable interrupt before proceedg to the next chunk
 #define FPGA_TABLE_CHUNK 64 // up to 64 words to send to the table/from histogram on a single IRQ-off transfer
 void fpga_table_write_nice (int addr, int len, unsigned long * data) {
   unsigned long flags;
   int l,i;
   MDF12(printk("addr=0x%x, len=0x%x, data=0x%08lx 0x%08lx 0x%08lx 0x%08lx...\n", addr, len, data[0], data[1], data[2], data[3]));
   while (len>0) {
     l=(len < FPGA_TABLE_CHUNK)?len:FPGA_TABLE_CHUNK;
     local_irq_save(flags);
     port_csp0_addr[X313_WA_COMP_TA]=addr; // open fpga for writing table(s)
     for (i=0; i<l; i++) port_csp0_addr[X313_WA_COMP_TD]=data[i]; /// will autoincrement FPGA table address
     local_irq_restore(flags);
     len  -=l;
     addr +=l;
     data +=l;
   }
 }

 ///
 /// reading histograms really does not need disabling IRQs - they only could interfere with other process, reading histograms
 ///
 void fpga_hist_read_nice (int addr, int len, unsigned long * data) {
   unsigned long flags;
   int l,i;
   MDF13(printk("addr=0x%x, len=0x%x, ",addr, len));
   while (len>0) {
     l=(len < FPGA_TABLE_CHUNK)?len:FPGA_TABLE_CHUNK;
     local_irq_save(flags);
 //  #define   X313_WA_HIST_ADDR   0x44
 //  #define   X313_RA_HIST_DATA   0x45  /// use CSP4 with wait cycles to have a pulse
     port_csp0_addr[X313_WA_HIST_ADDR]=addr; /// Write start address, read first word from the memory to the output buffer (will be read out during next read)
     X3X3_AFTERWRITE ; //! needed before reading from FPGA after writing to it (for the writes that influence reads only)
     for (i=0; i<l; i++) data[i]=port_csp4_addr[X313_RA_HIST_DATA]; /// will autoincrement FPGA table address)
     local_irq_restore(flags);
     len  -=l;
     addr +=l;
     data +=l;
   }
   D13(printk("data=0x%08lx 0x%08lx 0x%08lx 0x%08lx...\n", data[0], data[1], data[2], data[3]));
 }

#endif
+12 −3
Original line number Original line Diff line number Diff line
@@ -216,6 +216,7 @@
#include "sensor_i2c.h"
#include "sensor_i2c.h"
#include "x393_videomem.h"
#include "x393_videomem.h"
#include "detect_sensors.h"
#include "detect_sensors.h"
#include "x393_fpga_functions.h"


// NC393 debug macros
// NC393 debug macros
#include "debug393.h"
#include "debug393.h"
@@ -2401,7 +2402,7 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
{
{
    unsigned long flags;
    unsigned long flags;
    int i;
    int i;
    x393_cmprs_table_addr_t table_addr;
//    x393_cmprs_table_addr_t table_addr;
    struct {
    struct {
        short left;
        short left;
        short right;
        short right;
@@ -2453,6 +2454,7 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
        // from that file are replaced, but we still need table write with disabling IRQ
        // from that file are replaced, but we still need table write with disabling IRQ


#ifndef NC353
#ifndef NC353
    #if 0
        table_addr.type =   X393_TABLE_FOCUS_TYPE;
        table_addr.type =   X393_TABLE_FOCUS_TYPE;
        // Each focus page has 64 of 16-bit entries, total 16 pages (2KB). Configuration uses first 8 of 16-bit words in last page,
        // Each focus page has 64 of 16-bit entries, total 16 pages (2KB). Configuration uses first 8 of 16-bit words in last page,
        // And FPGA accepts 32-bit data (16-bit ones merged in pairs). So address is 32*15
        // And FPGA accepts 32-bit data (16-bit ones merged in pairs). So address is 32*15
@@ -2466,6 +2468,13 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
            x393_cmprs_tables_data(focus_setup_data32[i], sensor_port);
            x393_cmprs_tables_data(focus_setup_data32[i], sensor_port);
        }
        }
        local_ irq_restore(flags);
        local_ irq_restore(flags);
    #endif
        write_compressor_table(sensor_port,
                               TABLE_TYPE_FOCUS,
                               8*15, // to adress short (4-dwords) instead of full(32-dwords) page #15, multiply by 8
                               4,    // dwords to write
                               focus_setup_data32);

//        print_hex_dump_bytes("", DUMP_PREFIX_NONE, &focus_setup_data32[0], sizeof (focus_setup_data));
//        print_hex_dump_bytes("", DUMP_PREFIX_NONE, &focus_setup_data32[0], sizeof (focus_setup_data));
        MDP(DBGB_PADD, sensor_port,"focus_setup_data left=%d, right=%d, top=%d, bottom=%d, total width=%d, filter_no=%d, show1=%d\n",
        MDP(DBGB_PADD, sensor_port,"focus_setup_data left=%d, right=%d, top=%d, bottom=%d, total width=%d, filter_no=%d, show1=%d\n",
                focus_setup_data.left,focus_setup_data.right,focus_setup_data.top,focus_setup_data.bottom,
                focus_setup_data.left,focus_setup_data.right,focus_setup_data.top,focus_setup_data.bottom,
Loading