Commit 5414b1d7 authored by Andrey Filippov's avatar Andrey Filippov

more debugging

parent 406266d1
This diff is collapsed.
......@@ -30,7 +30,7 @@ unsigned long get_globalParam (int sensor_port, int n);
void set_globalParam (int sensor_port, int n, unsigned long d);
void set_imageParamsR_all(int sensor_port, int n, unsigned long d);
//Next 2 called from ISR
void updateInterFrame(int sensor_port, int frame16, struct interframe_params_t * interframe_pars);
void updateInterFrame(int sensor_port, u32 compressed_frame, struct interframe_params_t * interframe_pars);
void updateFramePars (int sensor_port, int frame16);
int setFrameParsStatic (int sensor_port, int numPars, struct frameparspair_t * pars);
......@@ -40,28 +40,32 @@ unsigned long getThisFrameNumber (int sensor_port); /// just return current thi
/// Return - 0 if OK, -ERR_FRAMEPARS_TOOEARLY or -ERR_FRAMEPARS_TOOLATE if it is too early or too late to set parameters (numPars may be 0 to just test)
///
/// NOTE: When writing parameter to P_SENSOR_RUN or P_COMPRESSOR_RUN "*_RUN_SINGLE", first write "*SENSOR_RUN_STOP" (it will propagate to all next frames) and then
/// write "*_RUN_SINGLE", to (P_*_RUN | FRAMEPAIR_JUST_THIS) - then this *_RUN_SINGLE will not propagate to the next frames (they will stay stopped)
// write "*_RUN_SINGLE", to (P_*_RUN | FRAMEPAIR_JUST_THIS) - then this *_RUN_SINGLE will not propagate to the next frames (they will stay stopped)
/// TODO: Make (an "unlimited") future commands que based on lists and a tree frame index
// TODO: Make (an "unlimited") future commands que based on lists and a tree frame index
int setFrameParsAtomic (int sensor_port, unsigned long frameno, int maxLatency, int numPars, struct frameparspair_t * pars);
/// set output/calculated parameter and propagate changes - will not trigger any actions
// set output/calculated parameter and propagate changes - will not trigger any actions
int setFramePar (int sensor_port, struct framepars_t * this_framepars, unsigned long mindex, unsigned long val);
// Same, but adds lock to call from user thread
int setFrameParLocked (int sensor_port, struct framepars_t * this_framepars, unsigned long mindex, unsigned long val);
///same for several pars at once
int setFramePars (int sensor_port, struct framepars_t * this_framepars, int numPars, struct frameparspair_t * pars);
/// schedule pgm_func to be executed for selected frame
void schedule_pgm_func (int sensor_port, int frame8, int func_num);
/// schedule pgm_func to be executed for the current frame
// schedule pgm_func to be executed for the current frame
void schedule_this_pgm_func (int sensor_port, struct framepars_t * this_framepars, int func_num);
/// program acquisition, according to the parameters changed.
/// maxahead - how many frames ahead of time (start with most urgent, then 1 ahead, ...)
/// make maxahead - P_* parameter?
/* 393: See if sesnor port is needed here */
inline void processParsASAP (int sensor_port, struct sensorproc_t * sensorproc, int frame8);
inline void processParsSeq (int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead);
// program acquisition, according to the parameters changed.
// maxahead - how many frames ahead of time (start with most urgent, then 1 ahead, ...)
// make maxahead - P_* parameter?
/* 393: See if sensor port is needed here */
/* NC393: Removed, should not be called from outside the lock-ed processPars() */
//inline void _processParsASAP (int sensor_port, struct sensorproc_t * sensorproc, int frame8);
//inline void _processParsSeq (int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead);
void processPars (int sensor_port, struct sensorproc_t * sensorproc, int frame8, int maxahead);
///*** TODO: Add option (flag?) to write "single" (like single compress, single sensor) so it will not make all the next frames "single"
......
......@@ -173,10 +173,7 @@ 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};
static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE)));
struct gamma_stuct_t * gammas_p; // to use with mmap
......
......@@ -622,11 +622,11 @@ loff_t histograms_lseek (struct file * file,
}
// request histogram(s)
// setFramePar(&framepars[reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(privData->port, &aframepars[privData->port][reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
setFrameParLocked(privData->port, &aframepars[privData->port][reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
// make sure (harmful) interrupt did not happen since getThisFrameNumber()
if (reqFrame < getThisFrameNumber(privData->port)) {
// setFramePar(&framepars[getThisFrameNumber() & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(privData->port, &aframepars[privData->port][getThisFrameNumber(privData->port) & PARS_FRAMES_MASK], reqAddr, 1);
setFrameParLocked(privData->port, &aframepars[privData->port][getThisFrameNumber(privData->port) & PARS_FRAMES_MASK], reqAddr, 1);
}
}
......
......@@ -344,6 +344,9 @@
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <uapi/elphel/c313a.h>
#include <uapi/elphel/x393_devices.h> // For sysfs
#include <linux/platform_device.h> // For sysfs
//#include "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr
//#include "x3x3.h" // detect sensor
//#include "cci2c.h"
......@@ -388,9 +391,9 @@
#endif
static struct device *g_dev_ptr=NULL; ///< Global pointer to basic device structure. This pointer is used in debugfs output functions
void mt9x001_set_device(struct device *dev)
void mt9x001_set_device(struct device *dev) // do nothing, now it has it's own device
{
g_dev_ptr = dev;
//g_dev_ptr = dev;
}
......@@ -548,6 +551,14 @@ struct sensor_t mt9p001={
.needReset= SENSOR_NEED_RESET_CLK | SENSOR_NEED_RESET_PHASE ///< bit 0 - need reset after clock frequency change, bit 1 - need reset after phase change
};
// Sysfs Interface for debugging the driver
static int first_sensor_sa7 [SENSOR_PORTS] = {0,0,0,0};
static unsigned int debug_delays = 0x0; // 0x6464; // udelay() values for mrst (low 8 - mrst on), [15:8] - after mrst
static unsigned int debug_modes = 3;
static unsigned short sensor_reg_copy[SENSOR_PORTS][256]; ///< Read all 256 sensor registers here - during initialization and on demand
///< Later may increase to include multiple subchannels on 10359
// a place to add some general purpose register writes to sensors during init
/** Register initial writes for MT9M001 */
......@@ -885,7 +896,6 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
int nupdate=0;
int i,color;
int regval, regnum, mreg, j;
dev_dbg(g_dev_ptr,"Resetting MT9X001 sensor\n");
// reset sensor by applying MRST (low):
#ifdef NC353
CCAM_MRST_ON;
......@@ -918,24 +928,31 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
}
#else
// CCAM_MRST_ON;
if (debug_delays & 0xff) {
dev_dbg(g_dev_ptr,"Resetting MT9X001 sensor, port=%d\n",sensor_port);
sensio_ctl.mrst = 0;
sensio_ctl.mrst_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
udelay (100);
// CCAM_MRST_OFF;
udelay (debug_delays & 0xff) ; // 100);
// CCAM_MRST_OFF;
sensio_ctl.mrst = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
sensio_ctl.d32=0;
}
// NC393: both sequencers started in pgm_detectsensor
udelay (100);
dev_dbg(g_dev_ptr,"Reading sensor registers to the shadows:\n");
if (debug_delays & 0xff00) {
udelay ((debug_delays >> 8) & 0xff); // 100);
}
first_sensor_i2c=sensor->i2c_addr;
if (GLOBALPARS(sensor_port, G_SENS_AVAIL)) {
first_sensor_i2c+= I2C359_INC * ((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 1)?1:((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 2)?2:3));
}
dev_dbg(g_dev_ptr,"Reading sensor (port=%d) registers to the shadows, sa7=0x%x:\n",sensor_port,first_sensor_i2c);
first_sensor_sa7[sensor_port] = first_sensor_i2c;
for (i=0; i<256; i++) { // read all registers, one at a time (slower than in 353)
X3X3_I2C_RCV2(sensor_port, first_sensor_i2c, i, &(i2c_read_data_dw[i]));
}
dev_dbg(g_dev_ptr,"Read 256 registers (port=%d) ID=0x%x:\n",sensor_port,i2c_read_data_dw[0]);
for (i=0; i<256; i++) { // possible to modify register range to save (that is why nupdate is separate from i)
regval=i2c_read_data_dw[i];
regnum=P_SENSOR_REGS+i;
......@@ -944,6 +961,10 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
SETFRAMEPARS_SET(mreg+j,regval);
}
}
for (i=0;i<256;i++) {
sensor_reg_copy[sensor_port][i] = i2c_read_data_dw[i];
}
#endif
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
dev_dbg(g_dev_ptr,"Initializing MT9X001 registers with default values:\n");
......@@ -2070,10 +2091,147 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
return 0;
}
//#define MAX_SENSORS 3 // maximal number of sensor attached (modify some hard-wired constants below if this to be changed)
//#define G_MULTI_NUM (FRAMEPAR_GLOBALS + 34) // Actual number of parameters that are individual for different channels (limited by P_MULTI_NUMREGS)
//#define P_MULTI_NUMREGS 32 // up to 32 sensor register may have individual values
//#define P_MULTI_REGS (P_SENSOR_REGS + P_SENSOR_NUMREGS) // 32-words aligned
//I2C359_INC
//#define FRAMEPAR_MODIFIED(x) (thispars->mod[(x) >> 5] & (1<<((x) & 0x1f)))
// #define MULTIRVRSREG(x) (multiSensRvrsIndex[x])
//static short sensor_reg_copy[SENSOR_PORTS][256]; // Read all 256 sensor registers here - during initialization and on demand
// // Later may increase to include multiple subchannels on 10359
// SysFS interface to mt9x001
#define SYSFS_PERMISSIONS 0644 /* default permissions for sysfs files */
#define SYSFS_READONLY 0444
#define SYSFS_WRITEONLY 0222
/** Sysfs helper function - get channel number from the last character of the attribute name*/
static int get_channel_from_name(struct device_attribute *attr) ///< Linux kernel interface for exporting device attributes
///< @return channel number
{
int reg = 0;
sscanf(attr->attr.name + (strlen(attr->attr.name)-1), "%du", &reg);
return reg;
}
// Dump 256 16-bit sensor registers */
static ssize_t show_sensor_regs(struct device *dev, struct device_attribute *attr, char *buf)
{
int chn = get_channel_from_name(attr);
char * cp = buf;
int i,j, ij=0;
for (i=0; i < 16; i++){
cp += sprintf(cp,"%02x:",i*16);
for (j=0;j<16;j++) cp += sprintf(cp," %04x", sensor_reg_copy[chn][ij++]);
cp += sprintf(cp,"\n");
}
return cp - buf;
}
/** Ignore data, re-read 256 sensor registers */
static ssize_t store_sensor_regs(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int chn = get_channel_from_name(attr);
u32 datai2c;
int i;
if (first_sensor_sa7[chn]) for (i = 0; i< 256;i++) {
X3X3_I2C_RCV2(chn, first_sensor_sa7[chn], i, &datai2c);
sensor_reg_copy[chn][i] = datai2c;
}
return count;
}
static ssize_t show_debug_delays(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"0x%08x\n", debug_delays);
}
static ssize_t store_debug_delays(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
if (!sscanf(buf, "%x", &debug_delays)) {
return - EINVAL;
}
return count;
}
static ssize_t show_debug_modes(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"0x%08x\n", debug_modes);
}
static ssize_t store_debug_modes(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
if (!sscanf(buf, "%x", &debug_modes)) {
return - EINVAL;
}
return count;
}
static DEVICE_ATTR(sensor_regs0, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs);
static DEVICE_ATTR(sensor_regs1, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs);
static DEVICE_ATTR(sensor_regs2, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs);
static DEVICE_ATTR(sensor_regs3, SYSFS_PERMISSIONS, show_sensor_regs, store_sensor_regs);
static DEVICE_ATTR(debug_delays, SYSFS_PERMISSIONS, show_debug_delays, store_debug_delays);
static DEVICE_ATTR(debug_modes, SYSFS_PERMISSIONS, show_debug_modes, store_debug_modes);
static struct attribute *root_dev_attrs[] = {
&dev_attr_sensor_regs0.attr,
&dev_attr_sensor_regs1.attr,
&dev_attr_sensor_regs2.attr,
&dev_attr_sensor_regs3.attr,
&dev_attr_debug_delays.attr,
&dev_attr_debug_modes.attr,
NULL
};
static const struct attribute_group dev_attr_root_group = {
.attrs = root_dev_attrs,
.name = NULL,
};
static int elphel393_mt9x001_sysfs_register(struct platform_device *pdev)
{
int retval=0;
struct device *dev = &pdev->dev;
if (&dev->kobj) {
if (((retval = sysfs_create_group(&dev->kobj, &dev_attr_root_group)))<0) return retval;
}
return retval;
}
int mt9x001_init(struct platform_device *pdev)
{
int res;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
int sensor_port;
for (sensor_port = 0; sensor_port < SENSOR_PORTS; sensor_port++) {
first_sensor_sa7[sensor_port] = 0;
}
elphel393_mt9x001_sysfs_register(pdev);
dev_info(dev, DEV393_NAME(DEV393_MT9X001)": registered sysfs\n");
g_dev_ptr = dev;
return 0;
}
int mt9x001_remove(struct platform_device *pdev)
{
unregister_chrdev(DEV393_MAJOR(DEV393_MT9X001), DEV393_NAME(DEV393_MT9X001));
return 0;
}
static const struct of_device_id elphel393_mt9x001_of_match[] = {
{ .compatible = "elphel,elphel393-mt9x001-1.00" },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, elphel393_mt9x001_of_match);
static struct platform_driver elphel393_mt9x001 = {
.probe = mt9x001_init,
.remove = mt9x001_remove,
.driver = {
.name = DEV393_NAME(DEV393_MT9X001),
.of_match_table = elphel393_mt9x001_of_match,
},
};
module_platform_driver(elphel393_mt9x001);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION("Driver for parallel interface image sensors Micron/Aptina/On Semi MT9M*, MT9D*, MT9T* and MT9P* in Elphel cameras");
......@@ -131,11 +131,3 @@ each dibit:
//#define I2C359_CLK_NUMBER 4 // system clock number for the 10359A on-board clock generator
void multi10359_set_device(struct device *dev);
int multisensor_pgm_detectsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
//int legacy_i2c (int ports);
/*
struct frameparspair_t pars_to_update[8];
int nupdate=0;
...
if (nupdate) setFramePars(thispars, nupdate, pars_to_update); /// save changes to sensor register shadows
*/
......@@ -391,7 +391,7 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
dev_dbg(g_dev_ptr,"Setting i2c drive mode for port %d\n",sensor_port);
i2c_drive_mode (sensor_port, SDA_DRIVE_HIGH, SDA_RELEASE);
i2c_stop_run_reset (sensor_port, I2C_CMD_RUN); // also programs status update
legacy_i2c(1<<sensor_port);// Setup i2c pages for legacy i2c commands. TODO NC393: update for compatibility with 14MPix
camsync_mode.trig = 0;
camsync_mode.trig_set = 1;
camsync_mode.ext = 1; // use external timestamp (default)
......
This diff is collapsed.
This diff is collapsed.
......@@ -34,7 +34,7 @@ typedef struct{
u8 data_bytes; ///< Number of data bytes (1..10), for writes it includes register address bytes
int scl_khz; ///< maximal SCL frequency in KHz (currently limited by 200KHz slowest)
} x393_i2c_device_t;
void i2c_page_alloc_init( int chn); // reset page allocation for selscted channel
int i2c_stop_run_reset(int chn, int cmd);
int i2c_drive_mode (int chn, int sda_drive_high, int sda_release);
int read_xi2c_frame (int chn);
......
......@@ -79,6 +79,9 @@ int setup_sensor_memory (int num_sensor, ///< sensor port number (0..3)
window_width_height.height = window_height;
window_left_top.left = window_left;
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);
switch (x393cmd){
case ASAP:
......@@ -210,6 +213,10 @@ int setup_compressor_memory (int num_sensor, ///< sensor port number (0..3
window_tile_whs.vert_step = tile_vstep;
window_tile_whs.tile_height = tile_height;
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 whs=0x%08x\n",
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, window_tile_whs.d32);
switch (x393cmd){
case ASAP:
frame16 = 0;
......
......@@ -90,6 +90,7 @@
#define DEV393_DETECT_SENSORS ("detect_sensors", "detect_sensors",143, 1, "0666", "c") ///< Probably not needed, only sysfs is used
#define DEV393_I2C_SENSORS ("", "elphel393-sensor-i2c",-1, -1, "0666", "c") ///< Used only in sysfs, no character device (yet?)
#define DEV393_MT9X001 ("", "elphel393-mt9x001", -1, -1, "0666", "c") ///< Used only in sysfs, no character device (yet?)
#define _DEV393_PATH(n, ...) "/dev/"n
......
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