Commit cffce9dc authored by Andrey Filippov's avatar Andrey Filippov

optimizing fpga tables write

parent 9a0d39a7
......@@ -279,7 +279,7 @@ int initSequencers(int sensor_port)
}
dev_dbg(g_devfp_ptr,"port= %d,initSequencers:resetting both sequencers (not really?)\n", sensor_port);
#ifdef TEST_DISABLE_CODE
local_irq_save(flags);
local_ irq_save(flags);
X3X3_SEQ_RESET;
i2c_reset_wait();
local_irq_restore(flags);
......@@ -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_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?)
* Should never be called from outside processPars() where there is a per-port lock */
......
......@@ -132,14 +132,6 @@
#include "x393.h"
#include "detect_sensors.h"
#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
......@@ -176,12 +168,23 @@
static struct device *g_dev_ptr;
static DEFINE_SPINLOCK(gamma_lock); ///< Non port-specific lock
static DEFINE_SPINLOCK(gamma_lock_0); ///<
static DEFINE_SPINLOCK(gamma_lock_1); ///<
static DEFINE_SPINLOCK(gamma_lock_2); ///<
static DEFINE_SPINLOCK(gamma_lock_3); ///<
//static DEFINE_SPINLOCK(gamma_lock_0); ///<
//static DEFINE_SPINLOCK(gamma_lock_1); ///<
//static DEFINE_SPINLOCK(gamma_lock_2); ///<
//static DEFINE_SPINLOCK(gamma_lock_3); ///<
/** 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)));
struct gamma_stuct_t * gammas_p; // to use with mmap
......@@ -377,7 +380,7 @@ int unlock_gamma_node (int color, ///< color channel 0..3
int index;
int cps = PORT_CHN_COLOR(color,sensor_port,sensor_subchn);
dev_dbg(g_dev_ptr,"color=0x%x, cps = 0x%x\n",color,cps);
// local_irq_save(flags);
// local_ irq_save(flags);
GAMMA_LOCK_BH(&gamma_lock);
index =gammas[0].locked_chn_color[cps];
if (index) {
......@@ -542,7 +545,7 @@ int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scale
dev_dbg(g_dev_ptr, "Using non-linear table\n"); ///NOTE: here
}
///disable interrupts here
// D1I(local_irq_save(flags));
// D1I(local_ irq_save(flags));
GAMMA_LOCK_BH(&gamma_lock);
// look for the matching hash
tmp_p=gammas[0].newest_non_scaled;
......@@ -592,7 +595,7 @@ int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scale
// let interrupts to take place, and disable again - not needed with a tasklet
// D1I(local_irq_restore(flags));
// MDF10(printk("Interrupts reenabled, tmp_p=0x%x\n", tmp_p));
// D1I(local_irq_save(flags));
// D1I(local_ irq_save(flags));
// check if it is still there (likely so, but allow it to fail).
if (unlikely(!is_gamma_current (hash16, 0, tmp_p))) {
// D1I(local_irq_restore(flags));
......@@ -649,7 +652,7 @@ int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scale
if ((mode & GAMMA_MODE_NOT_NICE)==0) {
// let interrupts to take place, and disable again - not needed with tasklets
// D1I(local_irq_restore(flags));
// D1I(local_irq_save(flags));
// D1I(local_ irq_save(flags));
// check if it is still there (likely so, but allow it to fail).
if (unlikely(!is_gamma_current (hash16, scale, tmp_p1))) {
// D1I(local_irq_restore(flags));
......@@ -715,8 +718,8 @@ int set_gamma_table (unsigned short hash16, ///< 16-bit unique (non-scale
if ((gammas[tmp_p1].valid & GAMMA_VALID_REVERSE)==0) {
if ((mode & GAMMA_MODE_NOT_NICE)==0) {
// let interrupts to take place, and disable again // not needed with tasklets
// D1I(local_irq_restore(flags));
// D1I(local_irq_save(flags));
// D1I(local_ irq_restore(flags));
// D1I(local_ irq_save(flags));
// check if it is still there (likely so, but allow it to fail).
if (unlikely(!is_gamma_current (hash16, 0, tmp_p))) {
// D1I(local_irq_restore(flags));
......@@ -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
*
* This code may be called from the IRQ context, and from the different CPU */
* This function is only called from tasklet context, no extra locking is required */
int fpga_gamma_write_nice(int color, ///< Color (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.color = color;
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){
len32 = FPGA_TABLE_CHUNK;
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);
}
}
GAMMA_UNLOCK_BH(gamma_locks[sensor_port]);
// GAMMA_UNLOCK_BH(gamma_locks[sensor_port]);
return 0;
}
......
......@@ -312,7 +312,7 @@ void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask
histograms_p= (struct histogram_stuct_t *) histograms;
// MDF21(printk("\n"));
#ifdef HISTOGRAMS_DISABLE_IRQ
local_irq_save(flags);
local_ irq_save(flags);
#endif
dev_dbg(g_dev_ptr, "Histograms structures, channel mask = 0x%x",chn_mask);
for (s=0; s<numHistChn; s++) {
......@@ -322,7 +322,7 @@ void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask
}
}
#ifdef HISTOGRAMS_DISABLE_IRQ
local_irq_restore(flags);
local_ irq_restore(flags);
#endif
dev_dbg(g_dev_ptr, "Histograms structures initialized");
......
......@@ -63,14 +63,13 @@
//#include "circbuf.h"
//#include "sensor_common.h"
//#include "exif.h"
#include "x393_macro.h"
#include "x393_fpga_functions.h"
#include "x393_macro.h" // X313_LENGTH_MASK
#include "x393.h"
static struct device *g_dev_ptr = NULL;
/**
* @brief All Huffman tables data to be read/written from the application
*/
/** All Huffman tables data to be read/written from the user space */
struct huff_tables_t {
struct huffman_encoded_t header_huffman_tables[4];
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 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);
int rslt = get_qtable(params->quality2, &buf[0], &buf[64], chn); /// will copy both quantization tables
if (rslt < 0) return rslt; /// bad quality table
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,
struct interframe_params_t *fp)
{
int rp;
// int rp;
unsigned int minor = MINOR(file->f_inode->i_rdev);
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 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;
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 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;
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 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;
if (p >= sizeof(struct huff_tables_t))
......@@ -676,17 +675,26 @@ void jpeg_htable_fpga_pgm(unsigned int chn)
{
int i;
unsigned long flags;
x393_cmprs_table_addr_t table_addr;
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.type = 3;
local_irq_save(flags);
local_ irq_save(flags);
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);
}
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;
}
......
///@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
......@@ -216,6 +216,7 @@
#include "sensor_i2c.h"
#include "x393_videomem.h"
#include "detect_sensors.h"
#include "x393_fpga_functions.h"
// NC393 debug macros
#include "debug393.h"
......@@ -2401,7 +2402,7 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
{
unsigned long flags;
int i;
x393_cmprs_table_addr_t table_addr;
// x393_cmprs_table_addr_t table_addr;
struct {
short left;
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
#ifndef NC353
#if 0
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,
// And FPGA accepts 32-bit data (16-bit ones merged in pairs). So address is 32*15
......@@ -2460,12 +2462,19 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
//focus_setup_data32
local_irq_save(flags);
local_ irq_save(flags);
x393_cmprs_tables_address(table_addr, sensor_port);
for (i = 0; i < 4; i++) {
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));
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,
......
......@@ -68,8 +68,9 @@
//#include "fpga_io.h"//fpga_table_write_nice
#include "quantization_tables.h"
#include "x393_macro.h"
//#include "x393_macro.h"
#include "x393.h"
#include "x393_fpga_functions.h"
/** @brief Number of elements in quantization table */
#define QTABLE_SIZE 64
......@@ -127,15 +128,14 @@ static unsigned int std_quant_tbls[4 * QTABLE_SIZE] = { /// make it possible to
/// with a number of programmed tables equal to PARS_FRAMES, and that "this" table is not needed it will always be possible to find an unused table slot
/// LRU cache for JPEG headers
struct qtables_set_t {
unsigned char qtable_cache [QTABLE_SIZE * 2 * QTABLE_HEAD_CACHE]; ///quantization tables cache
int qtable_cache_values [QTABLE_HEAD_CACHE]; /// quality values for the tables in cache
int qtable_cache_next[QTABLE_HEAD_CACHE] ; /// index of the next (not used longer than this) slot
int qtable_cache_mre; ///index of most recently used slot
int qtable_fpga_values [FPGA_NQTAB]; /// quality values for the tables in FPGA
int qtable_fpga_next[FPGA_NQTAB] ; /// index of the next (not used longer than this) slot in FPGA quantization tables
int qtable_fpga_mre; ///index of most recently used slot
unsigned char qtable_cache [QTABLE_SIZE * 2 * QTABLE_HEAD_CACHE]; ///< quantization tables cache
int qtable_cache_values [QTABLE_HEAD_CACHE]; ///< quality values for the tables in cache
int qtable_cache_next[QTABLE_HEAD_CACHE] ; ///< index of the next (not used longer than this) slot
int qtable_cache_mre; ///< index of most recently used slot
int qtable_fpga_values [FPGA_NQTAB]; ///< quality values for the tables in FPGA
int qtable_fpga_next[FPGA_NQTAB] ; ///< index of the next (not used longer than this) slot in FPGA quantization tables
int qtable_fpga_mre; ///< index of most recently used slot
int qtable_cache_initialized;
int qtable_fpga_initialized;
};
......@@ -352,21 +352,20 @@ void init_qtable_fpga(unsigned int chn)
local_irq_restore(flags);
}
/**
* @brief Finds an already programmed FPGA page or calculates (and programs FPGA with) a new one
* @param[in] quality2 single byte (standard) or a pair of bytes (see file header description)
* @param[in] chn compressor channel number
* @return table page number used (0..7) or -1 - invalid q
*/
/** Finds an already programmed FPGA page or calculates (and programs FPGA with) a new one
* It is only called from pgm_functions (tasklet context, already spin-locked for a channel), so no locking is needed */
//TODO 393: Change to spinlock_irq_save!
int set_qtable_fpga(int quality2, unsigned int chn)
int set_qtable_fpga(int quality2, ///< single byte (standard) or a pair of bytes (see file header description)
unsigned int chn) ///< compressor channel number
///< @return table page number (hardware) used (0..7) or -1 - invalid q
{
unsigned long flags;
int i,transpose,fpga_index,fpga_index_prev,q_type,quality,temp,tstart;
unsigned short qtable_fpga[QTABLE_SIZE * 2];
unsigned short *tab;
unsigned long *qtable_fpga_dw = (unsigned long *)qtable_fpga;
#if 0
x393_cmprs_table_addr_t table_addr;
#endif
int ind = get_cache_index(chn);
int *qtable_fpga_values = qtables_set[ind].qtable_fpga_values;
int *qtable_fpga_next = qtables_set[ind].qtable_fpga_next;
......@@ -381,7 +380,7 @@ int set_qtable_fpga(int quality2, unsigned int chn)
dev_dbg(g_dev_ptr, "transformed quality2 = 0x%x\n", quality2);
local_irq_save(flags);
// local_ irq_save(flags);
/// look if such q value is already in cache
fpga_index = qtables_set[ind].qtable_fpga_mre;
fpga_index_prev = -1;
......@@ -460,22 +459,28 @@ int set_qtable_fpga(int quality2, unsigned int chn)
}
}
#if 0
table_addr.type = TABLE_TYPE_QUANT;
//NC393 TODO: Find why address should be x4
// **** NC393 TODO: Find why address should be x4 - answer: it is in bytes in FPGA ****
// table_addr.addr32 = qtables_set[ind].qtable_fpga_mre * QTABLE_SIZE;
table_addr.addr32 = qtables_set[ind].qtable_fpga_mre * QTABLE_SIZE*4;
dev_dbg(g_dev_ptr, "table_addr=0x%08x\n", table_addr);
dev_dbg(g_dev_ptr, "table_addr=0x%08x\n", table_addr.d32);
x393_cmprs_tables_address(table_addr, chn);
for (i = 0; i < QTABLE_SIZE; i++) {
x393_cmprs_tables_data(qtable_fpga_dw[i], chn);
}
print_hex_dump_bytes("", DUMP_PREFIX_NONE, qtable_fpga, QTABLE_SIZE * 2);
print_hex_dump_bytes("", DUMP_PREFIX_NONE, std_quant_tbls, QTABLE_SIZE * 2);
#endif
write_compressor_table(chn,
TABLE_TYPE_QUANT,
qtables_set[ind].qtable_fpga_mre,
QTABLE_SIZE,
qtable_fpga_dw );
} /// now table pair is calculated and stored in cache
/// copy tables to the FPGA
local_irq_restore(flags);
// local_ irq_restore(flags);
dev_dbg(g_dev_ptr, "qtable_fpga_mre = %d\n", qtables_set[ind].qtable_fpga_mre);
......@@ -995,8 +1000,7 @@ static unsigned long coring_tables[] = {
0xcccccccc, 0xddddddcc, 0xdddddddd, 0xeeeeeeed, 0xeeeeeeee, 0xfffffffe, 0xffffffff, 0xffffffff
};
/**
* @brief Directly set one of the coring LUTs (currently 100: 0.0 to 9.9 with 0.1 step)
/** Directly set one of the coring LUTs (currently 100: 0.0 to 9.9 with 0.1 step)
* to one of 16 FPGA tables (even - for Y, odd - for C)
* Table is rather small, so turn off IRQ for the whole duration */
void set_coring_fpga(unsigned int coring_number, ///< [in] 0..99 - function number
......@@ -1004,23 +1008,30 @@ void set_coring_fpga(unsigned int coring_number, ///< [in] 0..99 - function nu
unsigned int chn) ///< [in] compressor channel number
{
int i;
unsigned long flags;
x393_cmprs_table_addr_t table_addr;
// unsigned long flags;
// x393_cmprs_table_addr_t table_addr;
if (coring_number >= sizeof(coring_tables) / (4 * CORING_SIZE))
coring_number = sizeof(coring_tables) / (4 * CORING_SIZE);
#if 0
dev_dbg(g_dev_ptr, "coring_number = 0x%x, fpga_number = 0x%x\n", coring_number, fpga_tbl_num);
table_addr.type = TABLE_TYPE_CORING;
table_addr.addr32 = fpga_tbl_num * CORING_SIZE;
local_irq_save(flags);
local_ irq_save(flags);
x393_cmprs_tables_address(table_addr, chn);
for (i = 0; i < CORING_SIZE; i++) {
x393_cmprs_tables_data(coring_tables[coring_number * CORING_SIZE + i], chn);
}
local_irq_restore(flags);
local_ irq_restore(flags);
print_hex_dump_bytes("", DUMP_PREFIX_NONE, &coring_tables[coring_number * CORING_SIZE], CORING_SIZE * 4);
#endif
write_compressor_table(chn,
TABLE_TYPE_CORING,
coring_number,
CORING_SIZE,
&coring_tables[coring_number * CORING_SIZE]);
}
void qt_init(struct platform_device *pdev)
......
......@@ -46,13 +46,6 @@ void camSeqSetJPEG_rp(unsigned int chn, int ptr);
///CIRCBUF macros
extern unsigned long * ccam_dma_buf_ptr[SENSOR_PORTS];
/* move these lines to x313_macro.h
#define X313_LENGTH_MASK 0xff000000
#define X313_PADDED_FRAME(x)((((x)+67+CCAM_MMAP_META ) >>2) & 0xfffffff8)
#define X313_BUFFSUB(x,y) (((x)>=(y))? ((x)-(y)) : ((x)+ (CCAM__DMA_SIZE-(y))))
#define X313_BUFFADD(x,y) ((((x) + (y))<=CCAM__DMA_SIZE)? ((x) + (y)) : ((x) - (CCAM__DMA_SIZE-(y))))
*/
//int init_FPGA(void); /// can be initialized only after FPGA is configured, not at module init (NOTE was static??)
///can be verified with if (!X313_IS_SDRAM_ON)
int init_compressor_dma(int chn_mask, int reset);
......
......@@ -20,12 +20,25 @@
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <uapi/elphel/c313a.h> // PARS_FRAMES_MASK
#include "x393.h"
#include "x393_macro.h"
#include "x393_fpga_functions.h"
// Define individual locks for compressor (quantization, coring, focus and Huffman) tables
// sensor gamma tables arde handled in gamma_tables.c (no locking as they are called from tasklet and already per-channel locked)
static DEFINE_SPINLOCK(compressor_table_lock_0); ///<
static DEFINE_SPINLOCK(compressor_table_lock_1); ///<
static DEFINE_SPINLOCK(compressor_table_lock_2); ///<
static DEFINE_SPINLOCK(compressor_table_lock_3); ///<
/** Define array of pointers to locks - hardware allows concurrent writes to different ports tables */
spinlock_t * compressor_table_locks[4] = {&compressor_table_lock_0, &compressor_table_lock_1, &compressor_table_lock_2, &compressor_table_lock_3};
#define REPEAT_STATUS_READ 10 ///< Number of times status is re-read waiting for a new timestamp
static void __iomem* zynq_devcfg_ptr = NULL; // 0xF8007000..f8007fff /f800700c needed
......@@ -194,3 +207,39 @@ int is_fpga_programmed(void) ///< @return 0 - bitstream is NOT loaded, 1 - bitst
}
return (readl(zynq_devcfg_ptr + 0x000c) & 4)? 1: 0;
}
//typedef enum {TABLE_TYPE_QUANT,TABLE_TYPE_CORING,TABLE_TYPE_FOCUS,TABLE_TYPE_HUFFMAN} x393cmprs_tables_t; ///< compressor table type
int write_compressor_table(int chn, // compressor channel (0..3)
x393cmprs_tables_t type, // table type (
int index,
int num_items,
u32 * data )
{
x393_cmprs_table_addr_t table_addr;
int i;
table_addr.type = (int) type;
table_addr.addr32 = index * type*4;
// dev_dbg(g_dev_ptr, "table_addr=0x%08x\n", table_addr.d32);
x393_cmprs_tables_address(table_addr, chn);
for (i = 0; i < num_items; i++) {
x393_cmprs_tables_data(data[i], chn);
}
return 0;
}
#if 0
#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
switch (x393cmd){
case ASAP:
#endif
......@@ -17,6 +17,7 @@
//typedef enum {DIRECT,ABSOLUTE,RELATIVE} x393cmd_t;
#include "x393.h"
int compressor_dma_setup (int port_afi, int chn_mask, int reset, int status_mode, int report_mode,
dma_addr_t cmprs0_sa, u32 cmprs0_len, dma_addr_t cmprs1_sa, u32 cmprs1_len,
dma_addr_t cmprs2_sa, u32 cmprs2_len, dma_addr_t cmprs3_sa, u32 cmprs3_len);
......@@ -25,4 +26,4 @@ int compressor_dma_setup (int port_afi, int chn_mask, int reset, int status_mode
sec_usec_t * get_fpga_rtc(sec_usec_t * ts);
int set_fpga_rtc (sec_usec_t ts);
int is_fpga_programmed(void);
int write_compressor_table(int chn, x393cmprs_tables_t type, int index, int num_items, u32 * data );
......@@ -66,10 +66,12 @@
#define X393_BUFFADD_CHN(x, y, chn) ((((x) + (y)) <= circbuf_priv_ptr[chn].buf_size) ? ((x) + (y)) : ((x) - (circbuf_priv_ptr[chn].buf_size -(y))))
#define X393_BUFFADD32(x, y, chn) ((((x) + (y)) <= circbuf_priv_ptr[chn].buf_size32) ? ((x) + (y)) : ((x) - (circbuf_priv_ptr[chn].buf_size32 -(y))))
#if 0
#define TABLE_TYPE_QUANT 0
#define TABLE_TYPE_CORING 1
#define TABLE_TYPE_FOCUS 2
#define TABLE_TYPE_HUFFMAN 3
#endif
/**
* @brief Converts file minor number to image compressor channel.
......
......@@ -83,10 +83,10 @@ int setup_sensor_memory (int num_sensor, ///< sensor port number (0..3)
window_left_top.top = window_top;
dev_dbg(g_dev_ptr,"{%d} frame16=%d, command=%d\n",num_sensor,frame16, (int) x393cmd);
dev_dbg(g_dev_ptr,"sa=0x%08x sa_inc=0x%08x lfn=0x%08x fw=0x%08x wh=0x%08x lt=0x%08x\n",
window_frame_sa.d32,window_frame_sa_inc.d32, window_last_frame_num, window_full_width.d32,window_width_height.d32,window_left_top.d32);
window_frame_sa.d32,window_frame_sa_inc.d32, window_last_frame_num.d32, window_full_width.d32,window_width_height.d32,window_left_top.d32);
MDP(DBGB_VM,num_sensor,"frame16=%d, command=%d\n", frame16, (int) x393cmd)
MDP(DBGB_VM,num_sensor,"sa=0x%08x sa_inc=0x%08x lfn=0x%08x fw=0x%08x wh=0x%08x lt=0x%08x\n",
window_frame_sa.d32,window_frame_sa_inc.d32, window_last_frame_num, window_full_width.d32,window_width_height.d32,window_left_top.d32)
window_frame_sa.d32,window_frame_sa_inc.d32, window_last_frame_num.d32, window_full_width.d32,window_width_height.d32,window_left_top.d32)
switch (x393cmd){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment