Commit 2c9168ed authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

Merge branch 'master' of https://github.com/Elphel/linux-elphel

parents bee02963 fa5d6aea
...@@ -111,6 +111,36 @@ static int elphel_check_load(struct device *dev) ...@@ -111,6 +111,36 @@ static int elphel_check_load(struct device *dev)
return ret; return ret;
} }
/** Calculate the difference between two time stamps and return it in microseconds */
static unsigned long time_diff_usec(sec_usec_t *start_time, sec_usec_t *end_time)
{
unsigned long time_us;
const unsigned long scale = 1000000;
if (start_time->sec <= end_time->sec) {
time_us = (end_time->sec - start_time->sec) * scale;
} else {
// time counter has rolled over
time_us = (ULONG_MAX - start_time->sec + end_time->sec) * scale;
}
if (start_time->usec <= end_time->usec)
time_us += end_time->usec - start_time->usec;
else
time_us += scale - start_time->usec + end_time->usec;
return time_us;
}
/** Add new recording speed sample to the list of samples */
static void add_sample(unsigned int sample, struct rec_stat *stat)
{
stat->samples[stat->samples_ptr] = sample;
stat->samples_ptr++;
if (stat->samples_ptr >= SPEED_SAMPLES_NUM) {
stat->samples_ptr = 0;
}
}
static irqreturn_t elphel_irq_handler(int irq, void * dev_instance) static irqreturn_t elphel_irq_handler(int irq, void * dev_instance)
{ {
unsigned long irq_flags; unsigned long irq_flags;
...@@ -154,9 +184,22 @@ static irqreturn_t elphel_irq_handler(int irq, void * dev_instance) ...@@ -154,9 +184,22 @@ static irqreturn_t elphel_irq_handler(int irq, void * dev_instance)
/** Command queue processing tasklet */ /** Command queue processing tasklet */
void process_queue(unsigned long data) void process_queue(unsigned long data)
{ {
int i;
size_t total_sz = 0;
unsigned long irq_flags; unsigned long irq_flags;
unsigned long time_usec;
sec_usec_t end_time = {0};
struct elphel_ahci_priv *dpriv = (struct elphel_ahci_priv *)data; struct elphel_ahci_priv *dpriv = (struct elphel_ahci_priv *)data;
// calculate the speed this frame has been written with
get_fpga_rtc(&end_time);
time_usec = time_diff_usec(&dpriv->stat.start_time, &end_time);
if (time_usec != 0) {
for (i = 0; i < dpriv->sg_elems; i++)
total_sz += dpriv->sgl[i].iov_len;
add_sample(total_sz / time_usec, &dpriv->stat);
}
if (process_cmd(dpriv) == 0) { if (process_cmd(dpriv) == 0) {
finish_cmd(dpriv); finish_cmd(dpriv);
if (move_head(dpriv) != -1) { if (move_head(dpriv) != -1) {
...@@ -919,6 +962,8 @@ static int process_cmd(struct elphel_ahci_priv *dpriv) ...@@ -919,6 +962,8 @@ static int process_cmd(struct elphel_ahci_priv *dpriv)
size_t max_sz = (MAX_LBA_COUNT + 1) * PHY_BLOCK_SIZE; size_t max_sz = (MAX_LBA_COUNT + 1) * PHY_BLOCK_SIZE;
size_t rem_sz = get_size_from(dpriv->data_chunks[dpriv->head_ptr], dpriv->curr_data_chunk, dpriv->curr_data_offset, EXCLUDE_REM); size_t rem_sz = get_size_from(dpriv->data_chunks[dpriv->head_ptr], dpriv->curr_data_chunk, dpriv->curr_data_offset, EXCLUDE_REM);
get_fpga_rtc(&dpriv->stat.start_time);
if (dpriv->flags & PROC_CMD) if (dpriv->flags & PROC_CMD)
dpriv->lba_ptr.lba_write += dpriv->lba_ptr.wr_count; dpriv->lba_ptr.lba_write += dpriv->lba_ptr.wr_count;
dpriv->flags |= PROC_CMD; dpriv->flags |= PROC_CMD;
...@@ -1389,17 +1434,45 @@ static ssize_t lba_current_write(struct device *dev, struct device_attribute *at ...@@ -1389,17 +1434,45 @@ static ssize_t lba_current_write(struct device *dev, struct device_attribute *at
return buff_sz; return buff_sz;
} }
/** Return the current disk write speed in MB/s */
static ssize_t wr_speed_read(struct device *dev, struct device_attribute *attr, char *buff)
{
int i;
unsigned int val, median;
unsigned int *l, *r;
unsigned int samples[SPEED_SAMPLES_NUM];
struct elphel_ahci_priv *dpriv = dev_get_dpriv(dev);
// sort recording speed samples and get median
memcpy(samples, dpriv->stat.samples, SPEED_SAMPLES_NUM * sizeof(dpriv->stat.samples[0]));
l = samples;
for (i = 1; i < SPEED_SAMPLES_NUM; i++) {
val = samples[i];
r = &samples[i- 1];
while (r >= l && *r > val) {
*(r + 1) = *r;
r--;
}
*(r + 1) = val;
}
median = samples[SPEED_SAMPLES_NUM / 2];
return snprintf(buff, 32, "Write speed: %u MB/s\n", median);
}
static DEVICE_ATTR(load_module, S_IWUSR | S_IWGRP, NULL, set_load_flag); static DEVICE_ATTR(load_module, S_IWUSR | S_IWGRP, NULL, set_load_flag);
static DEVICE_ATTR(SYSFS_AHCI_FNAME_WRITE, S_IWUSR | S_IWGRP, NULL, rawdev_write); static DEVICE_ATTR(SYSFS_AHCI_FNAME_WRITE, S_IWUSR | S_IWGRP, NULL, rawdev_write);
static DEVICE_ATTR(SYSFS_AHCI_FNAME_START, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, lba_start_read, lba_start_write); static DEVICE_ATTR(SYSFS_AHCI_FNAME_START, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP, lba_start_read, lba_start_write);
static DEVICE_ATTR(SYSFS_AHCI_FNAME_END, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, lba_end_read, lba_end_write); static DEVICE_ATTR(SYSFS_AHCI_FNAME_END, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP, lba_end_read, lba_end_write);
static DEVICE_ATTR(SYSFS_AHCI_FNAME_CURR, S_IRUSR | S_IRGRP | S_IWUSR | S_IRGRP, lba_current_read, lba_current_write); static DEVICE_ATTR(SYSFS_AHCI_FNAME_CURR, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP, lba_current_read, lba_current_write);
static DEVICE_ATTR(SYSFS_AHCI_FNAME_WRSPEED, S_IRUSR | S_IRGRP | S_IROTH, wr_speed_read, NULL);
static struct attribute *root_dev_attrs[] = { static struct attribute *root_dev_attrs[] = {
&dev_attr_load_module.attr, &dev_attr_load_module.attr,
&dev_attr_SYSFS_AHCI_FNAME_WRITE.attr, &dev_attr_SYSFS_AHCI_FNAME_WRITE.attr,
&dev_attr_SYSFS_AHCI_FNAME_START.attr, &dev_attr_SYSFS_AHCI_FNAME_START.attr,
&dev_attr_SYSFS_AHCI_FNAME_END.attr, &dev_attr_SYSFS_AHCI_FNAME_END.attr,
&dev_attr_SYSFS_AHCI_FNAME_CURR.attr, &dev_attr_SYSFS_AHCI_FNAME_CURR.attr,
&dev_attr_SYSFS_AHCI_FNAME_WRSPEED.attr,
NULL NULL
}; };
static const struct attribute_group dev_attr_root_group = { static const struct attribute_group dev_attr_root_group = {
......
...@@ -20,7 +20,9 @@ ...@@ -20,7 +20,9 @@
*/ */
#include <uapi/elphel/ahci_cmd.h> #include <uapi/elphel/ahci_cmd.h>
#include <uapi/elphel/c313a.h>
#include "../elphel/circbuf.h" #include "../elphel/circbuf.h"
#include "../elphel/x393_fpga_functions.h"
#ifndef _AHCI_ELPHEL_EXT #ifndef _AHCI_ELPHEL_EXT
#define _AHCI_ELPHEL_EXT #define _AHCI_ELPHEL_EXT
...@@ -55,6 +57,15 @@ ...@@ -55,6 +57,15 @@
#define JPEG_SIZE_LEN 2 ///< The size in bytes of JPEG marker length field #define JPEG_SIZE_LEN 2 ///< The size in bytes of JPEG marker length field
#define INCLUDE_REM 1 ///< Include REM buffer to total size calculation #define INCLUDE_REM 1 ///< Include REM buffer to total size calculation
#define EXCLUDE_REM 0 ///< Exclude REM buffer from total size calculation #define EXCLUDE_REM 0 ///< Exclude REM buffer from total size calculation
#define SPEED_SAMPLES_NUM 5 ///< Maximum number of samples for disk recording speed measurement
/** This structure is for collecting some recording statistics */
struct rec_stat {
unsigned int samples_ptr; ///< pointer to next sample in rec_stat::samples
unsigned int samples[SPEED_SAMPLES_NUM]; ///< calculated recording speed samples, the value of recording speed
///< presented via sysfs is a median of this array
sec_usec_t start_time; ///< time when current command has been issued
};
/** This structure holds raw device buffer pointers */ /** This structure holds raw device buffer pointers */
struct drv_pointers { struct drv_pointers {
...@@ -111,6 +122,7 @@ struct elphel_ahci_priv { ...@@ -111,6 +122,7 @@ struct elphel_ahci_priv {
///< because this flag is accessed from interrupt context ///< because this flag is accessed from interrupt context
struct tasklet_struct bh; ///< command processing tasklet struct tasklet_struct bh; ///< command processing tasklet
struct device *dev; ///< pointer to parent device structure struct device *dev; ///< pointer to parent device structure
struct rec_stat stat; ///< recording statistics
}; };
#endif /* _AHCI_ELPHEL_EXT */ #endif /* _AHCI_ELPHEL_EXT */
...@@ -1462,7 +1462,7 @@ void trigSlaveUpdate(int sensor_port) ///< sensor port number (0..3) ...@@ -1462,7 +1462,7 @@ void trigSlaveUpdate(int sensor_port) ///< sensor port number (0..3)
while (common_pars->updated[sensor_port]) { while (common_pars->updated[sensor_port]) {
dev_dbg(g_devfp_ptr,"port= %d, thisFrameNumber[%d] = %d\n", sensor_port, sensor_port, (int) thisFrameNumber(sensor_port)); dev_dbg(g_devfp_ptr,"port= %d, thisFrameNumber[%d] = %d\n", sensor_port, sensor_port, (int) thisFrameNumber(sensor_port));
common_pars->updated[sensor_port] = 0; common_pars->updated[sensor_port] = 0;
if (pars_to_update[nupdate ].num != P_TRIG_PERIOD){ //??? if (pars_to_update[nupdate ].num != P_TRIG_PERIOD){ // updated any other parameter - treat as period is updated (make sure it will not trigger)
updated_period = FRAMEPAIR_FORCE_PROC; updated_period = FRAMEPAIR_FORCE_PROC;
} }
pars_to_update[nupdate ].num= P_TRIG_MASTER ; pars_to_update[nupdate++].val = common_pars->master_chn; pars_to_update[nupdate ].num= P_TRIG_MASTER ; pars_to_update[nupdate++].val = common_pars->master_chn;
......
...@@ -1095,7 +1095,18 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p ...@@ -1095,7 +1095,18 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
x393_sensio_ctrl(sensio_ctl,sensor_port); x393_sensio_ctrl(sensio_ctl,sensor_port);
camsync_mode.trig = 0; camsync_mode.trig = 0;
camsync_mode.trig_set = 1; camsync_mode.trig_set = 1;
// Maybe it should be set to triggered mode first
x393_camsync_mode (camsync_mode); x393_camsync_mode (camsync_mode);
// Trying with the sequencer
// X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_mode, camsync_mode);
// dev_dbg(g_dev_ptr,"{%d} X3X3_SEQ_SEND1(0x%x, 0x%x, x393_camsync_mode, 0x%x)\n",
// sensor_port, sensor_port, frame16, (int) camsync_mode.d32);
udelay (100); udelay (100);
GLOBALPARS(sensor_port,G_SENS_AVAIL) |= 1<< (GLOBALPARS(sensor_port,G_SENS_AVAIL)); // temporary to indicate sensor detection functions that they need to initialize multisensor registers GLOBALPARS(sensor_port,G_SENS_AVAIL) |= 1<< (GLOBALPARS(sensor_port,G_SENS_AVAIL)); // temporary to indicate sensor detection functions that they need to initialize multisensor registers
......
...@@ -169,6 +169,8 @@ const unsigned long param_depend_tab[]= ...@@ -169,6 +169,8 @@ const unsigned long param_depend_tab[]=
P_SENSOR_PHASE, ONCHANGE_SENSORPHASE | ONCHANGE_EXPOSURE | ONCHANGE_LIMITFPS | \ P_SENSOR_PHASE, ONCHANGE_SENSORPHASE | ONCHANGE_EXPOSURE | ONCHANGE_LIMITFPS | \
ONCHANGE_MEMSENSOR | ONCHANGE_MEMCOMPRESSOR | ONCHANGE_COMPMODE | ONCHANGE_COMPSTOP | ONCHANGE_COMPRESTART , ONCHANGE_MEMSENSOR | ONCHANGE_MEMCOMPRESSOR | ONCHANGE_COMPMODE | ONCHANGE_COMPSTOP | ONCHANGE_COMPRESTART ,
P_FPGA_XTRA, ONCHANGE_LIMITFPS , P_FPGA_XTRA, ONCHANGE_LIMITFPS ,
//TODO NC393: Check - maybe no-need to stop/restart the compressor when changing trigger modes?
P_TRIG, ONCHANGE_RECALCSEQ | ONCHANGE_TRIGGERMODE | ONCHANGE_TRIGSEQ | ONCHANGE_LIMITFPS | /// Next to call with afterinit P_TRIG, ONCHANGE_RECALCSEQ | ONCHANGE_TRIGGERMODE | ONCHANGE_TRIGSEQ | ONCHANGE_LIMITFPS | /// Next to call with afterinit
ONCHANGE_MULTISENS | ONCHANGE_MULTISENS |
ONCHANGE_WINDOW | ONCHANGE_EXPOSURE | ONCHANGE_HIST | ONCHANGE_AEXP | ONCHANGE_FOCUSMODE | ONCHANGE_LIMITFPS | ONCHANGE_HIST | \ ONCHANGE_WINDOW | ONCHANGE_EXPOSURE | ONCHANGE_HIST | ONCHANGE_AEXP | ONCHANGE_FOCUSMODE | ONCHANGE_LIMITFPS | ONCHANGE_HIST | \
......
...@@ -365,8 +365,8 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number ( ...@@ -365,8 +365,8 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
///< @return OK - 0, <0 - error ///< @return OK - 0, <0 - error
{ {
x393_camsync_mode_t camsync_mode = {.d32=0}; x393_camsync_mode_t camsync_mode = {.d32=0};
x393_camsync_io_t camsync_src = {.d32=0x55555}; // all disabled (use internal) x393_camsync_io_t camsync_src = {.d32=0x00000}; // all disabled (use internal)
x393_camsync_io_t camsync_dst = {.d32=0x55555}; // all disable - nothing to output x393_camsync_io_t camsync_dst = {.d32=0x00000}; // all disable - nothing to output
// Setting trigger input, output and preriod to off // Setting trigger input, output and preriod to off
...@@ -418,15 +418,14 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number ( ...@@ -418,15 +418,14 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
// This causes mismatch with parameters, let it be there // This causes mismatch with parameters, let it be there
// camsync_mode.ext = 1; // use external timestamp (default) // camsync_mode.ext = 1; // use external timestamp (default)
// camsync_mode.ext_set = 1; // camsync_mode.ext_set = 1;
x393_camsync_mode (camsync_mode); x393_camsync_mode (camsync_mode); // here in immediate mode, no sequencer
// Set inactive state to all I/O) and period: // Set inactive state to all I/O) and period:
x393_camsync_trig_src(camsync_src); x393_camsync_trig_src(camsync_src); // here in immediate mode, no sequencer
x393_camsync_trig_dst(camsync_dst); x393_camsync_trig_dst(camsync_dst); // here in immediate mode, no sequencer
set_x393_camsync_trig_period(0); set_x393_camsync_trig_period(0); // here in immediate mode, no sequencer
dev_dbg(g_dev_ptr,"{%d} set_x393_camsync_trig_period(0)\n",sensor_port);
// dev_dbg(g_dev_ptr,"trying MT9P001\n"); // dev_dbg(g_dev_ptr,"trying MT9P001\n");
// mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type // mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
if (mux != SENSOR_NONE) { if (mux != SENSOR_NONE) {
dev_dbg(g_dev_ptr,"Mux mode for port %d is %d, tryng 10359\n",sensor_port, mux); dev_dbg(g_dev_ptr,"Mux mode for port %d is %d, tryng 10359\n",sensor_port, mux);
MDP(DBGB_PADD, sensor_port,"Mux mode for port %d is %d, tryng 10359\n",sensor_port, mux) MDP(DBGB_PADD, sensor_port,"Mux mode for port %d is %d, tryng 10359\n",sensor_port, mux)
...@@ -615,16 +614,18 @@ typedef union { ...@@ -615,16 +614,18 @@ typedef union {
camsync_mode.trig = 0; camsync_mode.trig = 0;
camsync_mode.trig_set = 1; camsync_mode.trig_set = 1;
x393_camsync_mode (camsync_mode); // immediate mode, bypass sequencer CAMSYNC mode // x393_camsync_mode (camsync_mode); // immediate mode, bypass sequencer CAMSYNC mode TODO NC393: Make it possible to synchronize writes (through sequencer)
// (TODO NC393: Make it possible to synchronize writes (through sequencer) X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_mode, camsync_mode); // trying through the sequencer
set_x393_camsync_trig_period (0); // reset circuitry (immediate mode)
// dev_dbg(g_dev_ptr,"{%d} set_x393_camsync_trig_period(0)\n",sensor_port);
// set_x393_camsync_trig_period (0); // reset circuitry (immediate mode)
X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_trig_period, 0); // trying through the sequencer
if (frame16 >= 0) return -1; // should be ASAP if (frame16 >= 0) return -1; // should be ASAP
//TODO: seems nothing to do here - all in the sensor-specific function: //TODO: seems nothing to do here - all in the sensor-specific function:
//Adding setup compressor report status mode - maybe move elsethere? Needed for comprfessor frame reporting, has to be done just once //Adding setup compressor report status mode - maybe move elsethere? Needed for comprfessor frame reporting, has to be done just once
return 0; return 0;
} }
/** Restore image size, decimation,... after sensor reset or set them according to sensor capabilities if none were specified /** Restore image size, decimation,... after sensor reset or set them according to sensor capabilities if none were specified
TODO: NC393 add default P_SENSOR_IFACE_TIM0..3 for parallel/serial? */ TODO: NC393 add default P_SENSOR_IFACE_TIM0..3 for parallel/serial? */
int pgm_afterinit (int sensor_port, ///< sensor port number (0..3) int pgm_afterinit (int sensor_port, ///< sensor port number (0..3)
...@@ -1312,24 +1313,36 @@ int pgm_triggermode(int sensor_port, ///< sensor port number (0..3 ...@@ -1312,24 +1313,36 @@ int pgm_triggermode(int sensor_port, ///< sensor port number (0..3
///< @return OK - 0, <0 - error ///< @return OK - 0, <0 - error
{ {
x393_camsync_mode_t camsync_mode = {.d32=0}; x393_camsync_mode_t camsync_mode = {.d32=0};
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16); int is_master = (thispars->pars[P_TRIG_MASTER] == sensor_port)? 1 : 0;
dev_dbg(g_dev_ptr,"{%d} frame16=%d, is_master=%d\n",sensor_port,frame16, is_master);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16) MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame if (frame16 >= PARS_FRAMES) return -1; // wrong frame
camsync_mode.trig = (thispars->pars[P_TRIG] & 4)?1:0; camsync_mode.trig = (thispars->pars[P_TRIG] & 4)?1:0;
if (camsync_mode.trig) { // if trigger mode, enable camsync module, if off - do nothing if (camsync_mode.trig) { // if trigger mode, enable camsync module, if off - do nothing
camsync_mode.en = 1; camsync_mode.en = 1;
camsync_mode.en_set = 1; camsync_mode.en_set = 1; // OK to do for non-master ports too
//When does it need to be disabled? //When does it need to be disabled?
// camsync_mode.ts_chns = (thispars->pars[P_EXTERN_TIMESTAMP]?1:0) << sensor_port; // camsync_mode.ts_chns = (thispars->pars[P_EXTERN_TIMESTAMP]?1:0) << sensor_port;
camsync_mode.ts_chns = 1 << sensor_port; camsync_mode.ts_chns = 1 << sensor_port;
camsync_mode.ts_chns_set = 1 << sensor_port; camsync_mode.ts_chns_set = 1 << sensor_port;
} }
camsync_mode.trig_set = 1; if (is_master) {
camsync_mode.trig_set = 1;
} else {
dev_dbg(g_dev_ptr,"{%d} frame16=%d, Only master port can change camsync trigger mode, master port is %d\n",sensor_port,frame16, (int) thispars->pars[P_TRIG_MASTER]);
}
// set directly, bypassing sequencer as it may fail with wrong trigger // set directly, bypassing sequencer as it may fail with wrong trigger
x393_camsync_mode (camsync_mode); // x393_camsync_mode (camsync_mode);
MDP(DBGB_PADD, sensor_port,"x393_camsync_mode(0x%x)\n",camsync_mode.d32) // dev_dbg(g_dev_ptr,"{%d} frame16=%d, x393_camsync_mode(0x%x)\n",sensor_port,frame16, (int)camsync_mode.d32);
// MDP(DBGB_PADD, sensor_port,"x393_camsync_mode(0x%x)\n",camsync_mode.d32)
// Trying with the sequencer
X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_mode, camsync_mode);
dev_dbg(g_dev_ptr,"{%d} X3X3_SEQ_SEND1(0x%x, 0x%x, x393_camsync_mode, 0x%x)\n",
sensor_port, sensor_port, frame16, (int) camsync_mode.d32);
// now update common trigger parameters and mark dependent channels to update, if anything changed; // now update common trigger parameters and mark dependent channels to update, if anything changed;
if (thispars->pars[P_TRIG] != common_pars->trig_mode){ if (is_master && (thispars->pars[P_TRIG] != common_pars->trig_mode)){
int i; int i;
dev_dbg(g_dev_ptr,"{%d} Updating common trigger mode, old=0x%lx, new=0x%lx\n",sensor_port,common_pars->trig_mode,thispars->pars[P_TRIG]); dev_dbg(g_dev_ptr,"{%d} Updating common trigger mode, old=0x%lx, new=0x%lx\n",sensor_port,common_pars->trig_mode,thispars->pars[P_TRIG]);
common_pars->trig_mode = thispars->pars[P_TRIG]; common_pars->trig_mode = thispars->pars[P_TRIG];
...@@ -2431,17 +2444,17 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3 ...@@ -2431,17 +2444,17 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
* TODO: 393 reimplement * TODO: 393 reimplement
* Was for 353: can not use sequencer as data is more than 24 bit wide * Was for 353: can not use sequencer as data is more than 24 bit wide
* In NC393 P_TRIG_DELAY and P_XMIT_TIMESTAMP are per-channel, other parameters are common (Last modified takes control). * In NC393 P_TRIG_DELAY and P_XMIT_TIMESTAMP are per-channel, other parameters are common (Last modified takes control).
* Master channel is set to the current channels when any of the common parameters is set *
* P_TRIG_OUT (outputs): * P_TRIG_OUT (outputs):
* off: 0x55555 * off: 0x00000
* external: 0x56555 * external: 0x02000
* internal: 0x65555 * internal: 0x00000
* both: 0x66555 * both: 0x22000
* P_TRIG_IN (inputs): * P_TRIG_IN (inputs):
* off: 0x55555 * off: 0x00000
* external: 0x95555 * external: 0x80000
* internal: 0x59555 * internal: 0x08000
* both: 0x99555 * both: 0x88000
*/ */
int pgm_trigseq (int sensor_port, ///< sensor port number (0..3) int pgm_trigseq (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities) struct sensor_t * sensor, ///< sensor static parameters (capabilities)
...@@ -2461,10 +2474,7 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3 ...@@ -2461,10 +2474,7 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
x393_camsync_mode_t camsync_mode = {.d32=0}; x393_camsync_mode_t camsync_mode = {.d32=0};
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16); dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16) MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
// MDP(DBGB_PADD, sensor_port,"X393_SEQ_SEND1(0x%x, 0x%x, x393_cmprs_control_reg, 0x%x)\n",sensor_port, frame16, cmprs_mode.d32);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame if (frame16 >= PARS_FRAMES) return -1; // wrong frame
//+++++ if (frame16 >= 0) return -1; // ASAP only mode Was on
// See if master channel is set to this channel directly // See if master channel is set to this channel directly
is_master = (thispars->pars[P_TRIG_MASTER] == sensor_port)? 1 : 0; is_master = (thispars->pars[P_TRIG_MASTER] == sensor_port)? 1 : 0;
if (is_master && FRAMEPAR_MODIFIED(P_TRIG_MASTER)) { if (is_master && FRAMEPAR_MODIFIED(P_TRIG_MASTER)) {
...@@ -2475,9 +2485,12 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3 ...@@ -2475,9 +2485,12 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
// Process per-channel (not common) parameters regardless of the master status (just trigger delay) // Process per-channel (not common) parameters regardless of the master status (just trigger delay)
// Trigger delay changed? // Trigger delay changed?
if (FRAMEPAR_MODIFIED(P_TRIG_DELAY)) { // individual per-channel parameters if (FRAMEPAR_MODIFIED(P_TRIG_DELAY)) { // individual per-channel parameters
set_x393_camsync_trig_delay (thispars->pars[P_TRIG_DELAY], sensor_port); // CAMSYNC trigger delay /// set_x393_camsync_trig_delay (thispars->pars[P_TRIG_DELAY], sensor_port); // CAMSYNC trigger delay
dev_dbg(g_dev_ptr,"{%d} set_x393_camsync_trig_delay(0x%x, %d)\n",sensor_port, camsync_src.d32, sensor_port); /// dev_dbg(g_dev_ptr,"{%d} set_x393_camsync_trig_delay(0x%x, %d)\n",sensor_port, camsync_src.d32, sensor_port);
MDP(DBGB_PADD, sensor_port,"set_x393_camsync_trig_delay(0x%x, %d)\n", camsync_src.d32, sensor_port) /// MDP(DBGB_PADD, sensor_port,"set_x393_camsync_trig_delay(0x%x, %d)\n", camsync_src.d32, sensor_port)
X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_trig_delay, thispars->pars[P_TRIG_DELAY]);
dev_dbg(g_dev_ptr,"{%d} X3X3_SEQ_SEND1(0x%x, 0x%x, x393_camsync_trig_delay, 0x%x)\n",
sensor_port, sensor_port, frame16, (int) thispars->pars[P_TRIG_DELAY]);
} }
if (!is_master){ if (!is_master){
...@@ -2487,28 +2500,33 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3 ...@@ -2487,28 +2500,33 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
// Trigger condition changed? (0 - internal sequencer) // Trigger condition changed? (0 - internal sequencer)
if (FRAMEPAR_MODIFIED(P_TRIG_CONDITION)) { if (FRAMEPAR_MODIFIED(P_TRIG_CONDITION)) {
camsync_src.d32 = thispars->pars[P_TRIG_CONDITION]; camsync_src.d32 = thispars->pars[P_TRIG_CONDITION];
x393_camsync_trig_src(camsync_src); /// x393_camsync_trig_src(camsync_src);
// update_master_channel=1; /// dev_dbg(g_dev_ptr,"{%d} x393_camsync_trig_src(0x%x)\n",sensor_port, camsync_src.d32);
dev_dbg(g_dev_ptr,"{%d} x393_camsync_trig_src(0x%x)\n",sensor_port, camsync_src.d32); /// MDP(DBGB_PADD, sensor_port,"x393_camsync_trig_src(0x%x)\n", camsync_src.d32)
MDP(DBGB_PADD, sensor_port,"x393_camsync_trig_src(0x%x)\n", camsync_src.d32) X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_trig_src, camsync_src);
dev_dbg(g_dev_ptr,"{%d} X3X3_SEQ_SEND1(0x%x, 0x%x, x393_camsync_trig_src, 0x%x)\n",
sensor_port, sensor_port, frame16, camsync_src.d32);
} }
// Sequencer output word changed? (to which outputs it is sent and what polarity) // Sequencer output word changed? (to which outputs it is sent and what polarity)
if (FRAMEPAR_MODIFIED(P_TRIG_OUT)) { if (FRAMEPAR_MODIFIED(P_TRIG_OUT)) {
camsync_dst.d32 = thispars->pars[P_TRIG_OUT]; camsync_dst.d32 = thispars->pars[P_TRIG_OUT];
x393_camsync_trig_dst(camsync_dst); /// x393_camsync_trig_dst(camsync_dst);
// update_master_channel=1; /// dev_dbg(g_dev_ptr,"{%d} x393_camsync_trig_dst(0x%x)\n",sensor_port, camsync_dst.d32);
dev_dbg(g_dev_ptr,"{%d} x393_camsync_trig_dst(0x%x)\n",sensor_port, camsync_dst.d32); /// MDP(DBGB_PADD, sensor_port,"x393_camsync_trig_dst(0x%x)\n", camsync_dst.d32)
MDP(DBGB_PADD, sensor_port,"x393_camsync_trig_dst(0x%x)\n", camsync_dst.d32) X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_trig_dst, camsync_dst);
dev_dbg(g_dev_ptr,"{%d} X3X3_SEQ_SEND1(0x%x, 0x%x, x393_camsync_trig_dst, 0x%x)\n",
sensor_port, sensor_port, frame16, camsync_dst.d32);
if (thispars->pars[P_TRIG_OUT]!=0) { if (thispars->pars[P_TRIG_OUT]!=0) {
gpio_set_pins.chn_a = 3; // Set dibit enable gpio_set_pins.chn_a = 3; // Set dibit enable
x393_gpio_set_pins(gpio_set_pins); /// x393_gpio_set_pins(gpio_set_pins);
dev_dbg(g_dev_ptr,"{%d} x393_gpio_set_pins(0x%x)\n",sensor_port, gpio_set_pins.d32); /// dev_dbg(g_dev_ptr,"{%d} x393_gpio_set_pins(0x%x)\n",sensor_port, gpio_set_pins.d32);
MDP(DBGB_PADD, sensor_port,"x393_gpio_set_pins(0x%x)\n",gpio_set_pins.d32) /// MDP(DBGB_PADD, sensor_port,"x393_gpio_set_pins(0x%x)\n",gpio_set_pins.d32)
X393_SEQ_SEND1 (sensor_port, frame16, x393_gpio_set_pins, gpio_set_pins);
dev_dbg(g_dev_ptr,"{%d} X3X3_SEQ_SEND1(0x%x, 0x%x, x393_gpio_set_pins, 0x%x)\n",
sensor_port, sensor_port, frame16, gpio_set_pins.d32);
} else { } else {
// Not needed, I think // Not needed, I think
// port_csp0_addr[X313_WA_IOPINS] = X313_WA_IOPINS_DIS_TRIG_OUT;
// dev_dbg(g_dev_ptr,"{%d} port_csp0_addr[0x%x]=0x%x\n",sensor_port, (int) X313_WA_IOPINS, (int) X313_WA_IOPINS_DIS_TRIG_OUT);
} }
} }
// Bit length changed or not yet initialized? // Bit length changed or not yet initialized?
...@@ -2520,40 +2538,45 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3 ...@@ -2520,40 +2538,45 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
d=P_TRIG_BITLENGTH_DEFAULT; d=P_TRIG_BITLENGTH_DEFAULT;
SETFRAMEPARS_SET(P_TRIG_BITLENGTH,d); SETFRAMEPARS_SET(P_TRIG_BITLENGTH,d);
} }
set_x393_camsync_trig_period(d); /// set_x393_camsync_trig_period(d);
update_master_channel=1; // update_master_channel=1;
dev_dbg(g_dev_ptr,"{%d} set_x393_camsync_trig_period(0x%x) (bit length)\n",sensor_port, d); /// dev_dbg(g_dev_ptr,"{%d} set_x393_camsync_trig_period(0x%x) (bit length)\n",sensor_port, d);
MDP(DBGB_PADD, sensor_port,"set_x393_camsync_trig_period(0x%x) (bit length)\n",d) /// MDP(DBGB_PADD, sensor_port,"set_x393_camsync_trig_period(0x%x) (bit length)\n",d)
X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_trig_period, d);
dev_dbg(g_dev_ptr,"{%d} X3X3_SEQ_SEND1(0x%x, 0x%x, set_x393_camsync_trig_period, 0x%x)\n",
sensor_port, sensor_port, frame16, d);
} }
// Sequencer period changed? (0 - stopped, 1 - single trigger, >=256 - start repetitive) // Sequencer period changed? (0 - stopped, 1 - single trigger, >=256 - start repetitive)
if (FRAMEPAR_MODIFIED(P_TRIG_PERIOD)) { if (FRAMEPAR_MODIFIED(P_TRIG_PERIOD)) {
if (unlikely((thispars->pars[P_TRIG_PERIOD] > 1) && (thispars->pars[P_TRIG_PERIOD] < 256))) { // Wrong value, restore old one if (unlikely((thispars->pars[P_TRIG_PERIOD] > 1) && (thispars->pars[P_TRIG_PERIOD] < 256))) { // Wrong value, restore old one
SETFRAMEPARS_SET(P_TRIG_PERIOD,prevpars->pars[P_TRIG_PERIOD]); //+1 SETFRAMEPARS_SET(P_TRIG_PERIOD,prevpars->pars[P_TRIG_PERIOD]); //+1
} else { } else {
set_x393_camsync_trig_period(thispars->pars[P_TRIG_PERIOD]); /// set_x393_camsync_trig_period(thispars->pars[P_TRIG_PERIOD]);
// update_master_channel=1; /// dev_dbg(g_dev_ptr,"{%d} set_x393_camsync_trig_period(0x%lx)\n",sensor_port, thispars->pars[P_TRIG_PERIOD]);
dev_dbg(g_dev_ptr,"{%d} set_x393_camsync_trig_period(0x%lx)\n",sensor_port, thispars->pars[P_TRIG_PERIOD]); /// MDP(DBGB_PADD, sensor_port,"set_x393_camsync_trig_period(0x%lx)\n", thispars->pars[P_TRIG_PERIOD])
MDP(DBGB_PADD, sensor_port,"set_x393_camsync_trig_period(0x%lx)\n", thispars->pars[P_TRIG_PERIOD]) X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_trig_period, thispars->pars[P_TRIG_PERIOD]);
dev_dbg(g_dev_ptr,"{%d} X3X3_SEQ_SEND1(0x%x, 0x%x, x393_camsync_trig_period, 0x%x)\n",
sensor_port, sensor_port, frame16, (int) thispars->pars[P_TRIG_PERIOD]);
} }
} }
// P_EXTERN_TIMESTAMP changed? (0 - internal sequencer) // P_EXTERN_TIMESTAMP changed? (0 - internal sequencer)
if (FRAMEPAR_MODIFIED(P_EXTERN_TIMESTAMP)) { if (FRAMEPAR_MODIFIED(P_EXTERN_TIMESTAMP)) {
camsync_mode.ext = thispars->pars[P_EXTERN_TIMESTAMP]?1:0; camsync_mode.ext = thispars->pars[P_EXTERN_TIMESTAMP]?1:0;
camsync_mode.ext_set = 1; camsync_mode.ext_set = 1;
// update_master_channel=1;
} }
// P_XMIT_TIMESTAMP changed? (0 - internal sequencer) // P_XMIT_TIMESTAMP changed? (0 - internal sequencer)
if (FRAMEPAR_MODIFIED(P_XMIT_TIMESTAMP)) { if (FRAMEPAR_MODIFIED(P_XMIT_TIMESTAMP)) {
camsync_mode.en_snd = (thispars->pars[P_XMIT_TIMESTAMP]?1:0); camsync_mode.en_snd = (thispars->pars[P_XMIT_TIMESTAMP]?1:0);
camsync_mode.en_snd_set = 1; camsync_mode.en_snd_set = 1;
// camsync_mode.ts_chns = (thispars->pars[P_EXTERN_TIMESTAMP]?1:0) << sensor_port;
// camsync_mode.ts_chns_set = 1 << sensor_port;
} }
if (camsync_mode.d32){ // anything set? if (camsync_mode.d32){ // anything set?
x393_camsync_mode (camsync_mode); /// x393_camsync_mode (camsync_mode);
dev_dbg(g_dev_ptr,"{%d} x393_camsync_mode(0x%x)\n",sensor_port, camsync_mode.d32); /// dev_dbg(g_dev_ptr,"{%d} x393_camsync_mode(0x%x)\n",sensor_port, camsync_mode.d32);
MDP(DBGB_PADD, sensor_port,"x393_camsync_mode(0x%x)\n", camsync_mode.d32) /// MDP(DBGB_PADD, sensor_port,"x393_camsync_mode(0x%x)\n", camsync_mode.d32)
X393_SEQ_SEND1 (sensor_port, frame16, x393_camsync_mode, camsync_mode);
dev_dbg(g_dev_ptr,"{%d} X3X3_SEQ_SEND1(0x%x, 0x%x, x393_camsync_mode, 0x%x)\n",
sensor_port, sensor_port, frame16, camsync_mode.d32);
} }
// Does not seem to have any parameters to update? // Does not seem to have any parameters to update?
if (nupdate) setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions if (nupdate) setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions
......
...@@ -41,7 +41,7 @@ unsigned long sensor_to_camsync(unsigned long pixel_time, unsigned long sensor_c ...@@ -41,7 +41,7 @@ unsigned long sensor_to_camsync(unsigned long pixel_time, unsigned long sensor_c
#define X393_SEQ_SEND1S(port,frame,func,data,subchn) {if ((frame) < 0) seqr_##func (0, (data), (port), (subchn)); \ #define X393_SEQ_SEND1S(port,frame,func,data,subchn) {if ((frame) < 0) seqr_##func (0, (data), (port), (subchn)); \
else seqa_##func ((frame), (data), (port), (subchn)); } else seqa_##func ((frame), (data), (port), (subchn)); }
/** Tells if parameter is modifies /** Tells if parameter is modified
* @param x parameter index to test * @param x parameter index to test
* @return nonzero if modified */ * @return nonzero if modified */
#define FRAMEPAR_MODIFIED(x) (thispars->mod[(x) >> 5] & (1<<((x) & 0x1f))) #define FRAMEPAR_MODIFIED(x) (thispars->mod[(x) >> 5] & (1<<((x) & 0x1f)))
......
...@@ -180,6 +180,7 @@ sec_usec_t * get_fpga_rtc(sec_usec_t * ts) ///< Pointer to a sec/usec structure ...@@ -180,6 +180,7 @@ sec_usec_t * get_fpga_rtc(sec_usec_t * ts) ///< Pointer to a sec/usec structure
spin_unlock_bh(&fpga_time_lock); spin_unlock_bh(&fpga_time_lock);
return ts; return ts;
} }
EXPORT_SYMBOL_GPL(get_fpga_rtc);
/** Set FPGA RTC to specified time */ /** Set FPGA RTC to specified time */
int set_fpga_rtc (sec_usec_t ts) ///< timestamp providing seconds and microseconds int set_fpga_rtc (sec_usec_t ts) ///< timestamp providing seconds and microseconds
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#define SYSFS_AHCI_FNAME_END lba_end #define SYSFS_AHCI_FNAME_END lba_end
/** sysfs entry name, no double quotes. This macro is used to populate <em>struct attribute</em> in #ahci_elphel.c */ /** sysfs entry name, no double quotes. This macro is used to populate <em>struct attribute</em> in #ahci_elphel.c */
#define SYSFS_AHCI_FNAME_CURR lba_current #define SYSFS_AHCI_FNAME_CURR lba_current
/** sysfs entry name, no double quotes. This macro is used to populate <em>struct attribute</em> in #ahci_elphel.c */
#define SYSFS_AHCI_FNAME_WRSPEED wr_speed
/** This file is used to send commands to AHCI driver from user space applications (camogm as for now). */ /** This file is used to send commands to AHCI driver from user space applications (camogm as for now). */
#define SYSFS_AHCI_WRITE SYSFS_AHCI_ENTRY NAME_TO_STR(SYSFS_AHCI_FNAME_WRITE) #define SYSFS_AHCI_WRITE SYSFS_AHCI_ENTRY NAME_TO_STR(SYSFS_AHCI_FNAME_WRITE)
/** This file is used to control starting LBA of a disk buffer (R/W). */ /** This file is used to control starting LBA of a disk buffer (R/W). */
...@@ -47,6 +49,8 @@ ...@@ -47,6 +49,8 @@
/** This file is used to control current LBA of a disk buffer (R/W). Use this file to set a pointer inside /** This file is used to control current LBA of a disk buffer (R/W). Use this file to set a pointer inside
* [lba_start..lba_end] area where next write operation will begin. */ * [lba_start..lba_end] area where next write operation will begin. */
#define SYSFS_AHCI_LBA_CURRENT SYSFS_AHCI_ENTRY NAME_TO_STR(SYSFS_AHCI_FNAME_CURR) #define SYSFS_AHCI_LBA_CURRENT SYSFS_AHCI_ENTRY NAME_TO_STR(SYSFS_AHCI_FNAME_CURR)
/** This file shows avarage write speed */
#define SYSFS_AHCI_WR_SPEED SYSFS_AHCI_ENTRY_NAME_TO_STR(SYSFS_AHCI_FNAME_WRSPEED)
struct frame_data { struct frame_data {
unsigned int sensor_port; unsigned int sensor_port;
......
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