Commit 581d1d2f authored by Andrey Filippov's avatar Andrey Filippov

converting sensor-related code

parent af248eb3
/*!********************************************************************************
*! FILE NAME : histograms.c
*! DESCRIPTION: Handles histograms storage, access and percentile calculation
*! Copyright (C) 2008 Elphel, Inc.
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
/***************************************************************************//**
* @file histograms.c
* @brief Handles histograms storage, access and percentile calculation
* @copyright Copyright 2008-2016 (C) Elphel, Inc.
* @par <b>License</b>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
/* -----------------------------------------------------------------------------**
*! $Log: histograms.c,v $
*! Revision 1.3 2009/02/18 06:25:59 elphel
*! typo in format
......@@ -77,8 +75,6 @@
*!
*! Revision 1.1 2008/06/08 23:46:45 elphel
*! added drivers files for handling quantization tables, gamma tables and the histograms
*!
*!
*/
//copied from cxi2c.c - TODO:remove unneeded
......@@ -133,42 +129,44 @@
#define MDF21(x)
#define MDF22(x)
#endif
//[SENSOR_PORTS]
u32 (*fpga_hist_data)[SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256];
u32 (*fpga_hist_data)[SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]; ///< Array of histogram data, mapped to the memory wheer FPGA sends data
dma_addr_t fpga_hist_phys; // physical address of the start of the received histogram data
//dma_buf_ptr = pElphel_buf->vaddr;
//dma_handle = pElphel_buf->paddr;
#define X3X3_HISTOGRAMS_DRIVER_NAME "Elphel (R) Model 353 Histograms device driver"
///* for each port and possible sensor subchannel provides index in combine histogram data
/** for each port and possible sensor subchannel provides index in combine histogram data */
int histograms_map[SENSOR_PORTS][MAX_SENSORS];
/** total number of sensors (on all ports) used */
static int numHistChn = 0;
/** Variable-length array (length is the total number of active sensors <=16), each being the same as in 353:
* consisting of SENSOR_PORTS histogram_stuct_t structures */
struct histogram_stuct_t (*histograms)[HISTOGRAM_CACHE_NUMBER];
dma_addr_t histograms_phys; ///< likely not needed
struct histogram_stuct_t * histograms_p; // to use with mmap
dma_addr_t histograms_phys; ///< likely not needed, saved during allocation
/*
static struct histogram_stuct_t histograms[HISTOGRAM_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE)));
struct histogram_stuct_t * histograms_p; ///< alias of histogram_stuct_t
struct histogram_stuct_t * histograms_p; // to use with mmap
*/
wait_queue_head_t hist_y_wait_queue; // wait queue for the G1 histogram (used as Y)
wait_queue_head_t hist_c_wait_queue; // wait queue for all the other (R,G2,B) histograms (color)
wait_queue_head_t hist_y_wait_queue; ///< wait queue for the G1 histogram (used as Y)
wait_queue_head_t hist_c_wait_queue; ///< wait queue for all the other (R,G2,B) histograms (color)
/** File operations private data */
struct histograms_pd {
int minor;
unsigned long frame;
int frame_index; ///< -1 if invalid
int needed;
unsigned long frame; ///< absolute frame number requested
int frame_index; ///< histogram fame index (in cache and when accessing through mmap), -1 if invalid,
int needed; ///< bits specify what histograms (color, type) are requested
///< each group of 4 bits covers 4 colors of the same type:
///< - bits 0..3 - read raw histograms from the FPGA - normally called from IRQ/tasklet (use just 1 color for autoexposure to speed up?)
///< - bits 4..7 - calculate cumulative histograms (sum of raw ones) - normally called from applications
///< - bits 8..11 - calculate percentiles (reverse cumulative histograms) - normally called from applications
///< "needed" for raw histograms should be specified explicitly (can not be read from FPGA later),
///< "needed" for cumul_hist will be added automatically if percentiles are requested
int wait_mode; ///< 0 - wait just for G1 histogram, 1 - wait for all histograms
int request_en; ///< enable requesting histogram for the specified frame (0 - rely on the available ones)
int port; ///< selected sensor port (0..3)
......@@ -178,6 +176,7 @@ struct histograms_pd {
// something else to be added here?
};
int histograms_open (struct inode *inode, struct file *file);
int histograms_release(struct inode *inode, struct file *file);
loff_t histograms_lseek (struct file * file, loff_t offset, int orig);
......@@ -220,8 +219,7 @@ void histograms_dma_ctrl(int mode) ///< 0 - reset, 1 - disable, 2 - enable
}
/** Initialize histograms data structures, should be called when active subchannels are known (maybe use DT)?
*/
/** Initialize histograms data structures, should be called when active subchannels are known (maybe use DT)? */
void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask to global P-variable
{
unsigned long flags;
......@@ -246,7 +244,7 @@ void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask
// When device == NULL, dma_alloc_coherent just allocates notmal memory, page aligned, CMA if available
histograms = (struct histogram_stuct_t*[HISTOGRAM_CACHE_NUMBER]) dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL);
BUG_ON(!histograms);
histograms_p=histograms;
histograms_p= (struct histogram_stuct_t *) histograms;
MDF21(printk("\n"));
local_irq_save(flags);
for (s=0; s<numHistChn; s++) {
......@@ -259,7 +257,7 @@ void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask
}
/** Get histogram index for sensor port/channel, skipping unused ones */
int get_hist_index (int sensor_port, ///< sensor port number (0..3)
int sensor_chn) ///< sensor subchannel (0 w/o multiplexer)
int sensor_chn) ///< sensor subchannel (0..3, 0 w/o multiplexer)
///< @return index of used (active) histogram set (just skipping unused ports/subchannels
{
return histograms_map[sensor_port][sensor_chn];
......@@ -423,7 +421,7 @@ inline void histogram_calc_percentiles (unsigned long * cumul_hist, ///< [IN]
}
///======================================
//======================================
// use G_SUBCHANNELS in userspace to re-calculate full histogram index
// File operations:
// open, release - nop
......@@ -491,30 +489,30 @@ int histograms_release (struct inode *inode, ///< inode
return res;
}
/**
* @brief Histograms driver LSEEK method (and execute commands)
* lseek (SEEK_SET, value) wait for histogram of the absolute frame 'value' (G1 or all depending on wait_mode
/** Histograms driver LSEEK method (and execute commands)<ul>
* <li>lseek <b>(SEEK_SET, value)</b> wait for histogram of the absolute frame 'value' (G1 or all depending on wait_mode
* locate frame number value and set frame_index (and file pointer) to the result.
* Return error if frame can not be found, otherwise - histogram index (to use with mmap)
* Calculate missing tables according to "needed" variable
* lseek (SEEK_CUR, value) wait for histogram of the frame 'value' from the current one (G1 or all depending on wait_mode
* <li>lseek <b>(SEEK_CUR, value)</b> wait for histogram of the frame 'value' from the current one (G1 or all depending on wait_mode
* locate frame number value and set frame_index (and file pointer) to the result.
* Return error if frame can not be found, otherwise - histogram index (to use with mmap)
* Calculate missing tables according to "needed" variable
* lseek (SEEK_CUR, 0) will wait for the histogram(s) for current frame
* lseek (SEEK_CUR, value) - ignore value, return frame_index (may be negative if error)
* lseek (SEEK_END, value < 0) - do nothing?, do not modify file pointer, return error
* lseek (SEEK_END, value = 0) - return HISTOGRAMS_FILE_SIZE
* lseek (SEEK_END, LSEEK_HIST_WAIT_Y) - set histogram waiting for the Y (actually G1) histogram (default after open)
* lseek (SEEK_END, LSEEK_HIST_WAIT_C) - set histogram waiting for the C (actually R, G2, B) histograms to become available - implies G1 too
* ENXIO
* lseek (SEEK_END, LSEEK_HIST_NEEDED) // LSEEK_HIST_NEEDED | (0..0xffff) set histogram "needed" bits
* lseek (SEEK_END, LSEEK_HIST_REQ_EN) - (default)enable histogram request when reading histogram (safer, but may be not desirable in HDR mode) - default after opening
* lseek (SEEK_END, LSEEK_HIST_REQ_DIS) - disable histogram request when reading histogram - will read latest available relying it is available
* <li> lseek <b>(SEEK_CUR, value)</b> - ignore value, return frame_index (may be negative if error)
* <li> lseek <b>(SEEK_END, value < 0)</b> - do nothing?, do not modify file pointer, return error
* <li> lseek <b>(SEEK_END, value = 0)</b> - return HISTOGRAMS_FILE_SIZE
* <li> lseek <b>(SEEK_END, LSEEK_HIST_WAIT_Y)</b> - set histogram waiting for the Y (actually G1) histogram (default after open)
* <li> lseek <b>(SEEK_END, LSEEK_HIST_WAIT_C)</b> - set histogram waiting for the C (actually R, G2, B) histograms to become available - implies G1 too
* <li> lseek <b>(SEEK_END, LSEEK_HIST_SET_CHN +4*port+ subchannel)</b> - select sensor port and subchannel. Returns -ENXIO if port/subchannel does not
* match any active sensor.
* <li> lseek <b>(SEEK_END, LSEEK_HIST_NEEDED)</b> set histogram "needed" bits
* <li> lseek <b>(SEEK_END, LSEEK_HIST_REQ_EN)</b> - (default)enable histogram request when reading histogram (safer, but may be not desirable in HDR mode) - default after opening
* <li> lseek <b>(SEEK_END, LSEEK_HIST_REQ_DIS</b>) - disable histogram request when reading histogram - will read latest available relying it is available </ul>
* @param file
* @param offset
* @param orig SEEK_SET, SEEK_CUR or SEEK_SET END
* @return file position (absolute frame number)
* @return file position (histogram frame index (combined frame index and channel))
*/
// TODO: add flag that will allow driver to wakeup processes before the specified frame comes ?
loff_t histograms_lseek (struct file * file,
......
//histograms.h
/// These wait queues will be advanced each frame after the histogram data is transferred to the FPGA.
/// It will happen even if the corresponding task is disabled, with the only exception:
/// hist_c_wait_queue will not be awaken in the current frame if it is too late (frame counter incremented while serving tasklet)
/***************************************************************************//**
* @file histograms.h
* @brief Handles histograms storage, access and percentile calculation
* @copyright Copyright 2008-2016 (C) Elphel, Inc.
* @par <b>License</b>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
// These wait queues will be advanced each frame after the histogram data is transferred to the FPGA.
// It will happen even if the corresponding task is disabled, with the only exception:
// hist_c_wait_queue will not be awaken in the current frame if it is too late (frame counter incremented while serving tasklet)
extern wait_queue_head_t hist_y_wait_queue; /// wait queue for the G1 histogram (used as Y)
extern wait_queue_head_t hist_c_wait_queue; /// wait queue for all the other (R,G2,B) histograms (color)
......@@ -12,22 +26,6 @@ int get_hist_index (int sensor_port, int sensor_chn);
int set_histograms (int sensor_port, int sensor_chn, unsigned long frame, int needed, unsigned long * gammaHash, unsigned long * framep);
/**
* @brief Get histograms from the FPGA (called as tasklet?) and/or calculate derivatives (if needed)
* @param frame absolute frame number (Caller should match it to the hardware frame) frame==0xffffffff - find the latest available frame, don't wait
* TODO: should it be one frame behind current?
* @param needed bits specify what histograms (color, type) are requested
* TODO: Add P_* parameter - what to read from tasklet, turn colors it off for high FPS/small window
* each group of 4 bits covers 4 colors of the same type:
* - bits 0..3 - read raw histograms from the FPGA - normally called from IRQ/tasklet (use just 1 color for autoexposure to speed up?)
* - bits 4..7 - calculate cumulative histograms (sum of raw ones) - normally called from applications
* - bits 8..11 - calculate percentiles (reverse cumulative histograms) - normally called from applications
* "needed" for raw histograms should be specified explicitly (can not be read from FPGA later),
* "needed" for cumul_hist will be added automatically if percentiles are requested
* @return index of the histogram (>=0) if OK, otherwise:
* - -1 not reading FPGA and frame number stored is different from the requested (too late - histogram buffer overrun?)
* - -2 - not reading from FPGA, but some needed raw histograms are missing (should be requested/loaded earlier)
*/
int get_histograms (unsigned long frame, int needed);
int histograms_init_hardware(void);
......
......@@ -17,8 +17,10 @@
#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
......@@ -37,6 +39,7 @@
#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:
......@@ -70,9 +73,11 @@
#define CONFIG_ETRAX_ELPHEL_MT9X001 1
void x313_dma_stop(){}
void x313_dma_init(){}
void reset_compressor(){}
void x313_dma_stop() {}
void x313_dma_init() {}
void reset_compressor() {}
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);
......@@ -81,6 +86,13 @@
// 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
......
This source diff could not be displayed because it is too large. You can view the blob instead.
//mt9x001.h
#define MT9M001_PARTID 0x8411
#define MT9D001_PARTID 0x8511
#define MT9T001_PARTID 0x1601
#define MT9P001_PARTID 0x1801
#define MT9X001_PARTIDMASK 0xff00
#define MT9X001_I2C_ADDR 0xba
#define MT9P001_I2C_ADDR 0x90 //change later to the same 0xba as others
#define MT9M_TYP 1
#define MT9D_TYP 2
#define MT9T_TYP 3
#define MT9P_TYP 4
/***************************************************************************//**
* @file mt9x001.h
* @brief Handles Micron/Aptina/On Semiconductor MT9M*, MT9D*,MT9T*, andMT9P*
* image sensors
* @copyright Copyright 2004-2016 (C) Elphel, Inc.
* @par <b>License</b>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
#define MT9M001_PARTID 0x8411 ///< MT9M00* PartID register value
#define MT9D001_PARTID 0x8511 ///< MT9D00* PartID register value
#define MT9T001_PARTID 0x1601 ///< MT9T00* PartID register value
#define MT9P001_PARTID 0x1801 ///< MT9P00* PartID register value
#define MT9X001_PARTIDMASK 0xff00 ///< Part ID mask
#define MT9X001_I2C_ADDR 0x5d ///< MT9M, MT9D, MT9T I2C slave address (7 bit)
#define MT9P001_I2C_ADDR 0x48 ///< MT9P I2C slave address (7 bit)
#define MT9M_TYP 1 ///< MT9M00* type for the driver
#define MT9D_TYP 2 ///< MT9D00* type for the driver
#define MT9T_TYP 3 ///< MT9T00* type for the driver
#define MT9P_TYP 4 ///< MT9P00* type for the driver
/* i2c Micron MI-1300 registers will be defined here */
#define P_MT9X001_CHIPVER 0x00 /* Chip version, dflt= 0x8411 - will change??? /0x1801 */
#define P_MT9X001_ROWSTART 0x01 /* First row to read out, dflt=0x0c/0x0c/0x14/0x36 [0..2004],even*/
#define P_MT9X001_COLSTART 0x02 /* First column to read out, must be even! Dflt=0x14/18/20/0x10 [0..2750],even */
#define P_MT9X001_HEIGHT 0x03 /* Number of rows-1 (min value=2), dflt=0x03ff/4af/5ff/0x797 1..2005], odd */
#define P_MT9X001_WIDTH 0x04 /* Number of columns-1 (odd, >=3),dflt =0x4ff/63f/7ff/a1f [1..2751] odd */
#define P_MT9X001_HORBLANK 0x05 /* Horizontal blanking, dflt=0x09/35/8e/0 pixels [0..4095]*/
#define P_MT9X001_VERTBLANK 0x06 /* Vertical blanking, dflt=0x19/19/19/19 rows [8..2047]*/
///NOTE: There seems to be a bug in P_MT9X001_VERTBLANK register in MT9P031 sesnor
/// when increasing the value. I.e. changing it from default in the camera after startup 0x284 to 0x285
/// the sensor "sleeps" for ~35 seconds with to Frame Sync output . That may depend on something else, of course,
#define P_MT9X001_OUTCTRL 0x07 /* Output format bits (dflt=2/2/2/1f82) :
bit 0 - 0 - normal, 1 - do not update integration, gains, blanking, flip, decimation''
bit 1 - 0 - stop sensor, 1 - normal (0->1 restarts from start of the frame)
bits 2,3 should be 0 (in mt9p bit 2 selects fifo output data)
bit 6 - 0 - normal, 1 - test (mt9p - reserved)
mt9p001:
9:7 pixclk slew rate (0..7, higher - faster) dflt - 7
12:10 output (but pixclk) slew rate (0..7, higher - faster) dflt -7
#define P_MT9X001_CHIPVER 0x00 ///< Chip version, dflt= 0x8411 - will change??? /0x1801
#define P_MT9X001_ROWSTART 0x01 ///< First row to read out, dflt=0x0c/0x0c/0x14/0x36 [0..2004],even
#define P_MT9X001_COLSTART 0x02 ///< First column to read out, must be even! Dflt=0x14/18/20/0x10 [0..2750],even
#define P_MT9X001_HEIGHT 0x03 ///< Number of rows-1 (min value=2), dflt=0x03ff/4af/5ff/0x797 1..2005], odd
#define P_MT9X001_WIDTH 0x04 ///< Number of columns-1 (odd, >=3),dflt =0x4ff/63f/7ff/a1f [1..2751] odd
#define P_MT9X001_HORBLANK 0x05 ///< Horizontal blanking, dflt=0x09/35/8e/0 pixels [0..4095]
#define P_MT9X001_VERTBLANK 0x06 ///< Vertical blanking, dflt=0x19/19/19/19 rows [8..2047]
///< NOTE: There seems to be a bug in P_MT9X001_VERTBLANK register in MT9P031 sensor
///< when increasing the value. I.e. changing it from default in the camera after startup 0x284 to 0x285
///< the sensor "sleeps" for ~35 seconds with to Frame Sync output . That may depend on something else, of course,
#define P_MT9X001_OUTCTRL 0x07 ///< Output format bits (dflt=2/2/2/1f82) :<ul>
///<<li> bit 0 - 0 - normal, 1 - do not update integration, gains, blanking, flip, decimation''
///<<li> bit 1 - 0 - stop sensor, 1 - normal (0->1 restarts from start of the frame)
///<<li> bits 2,3 should be 0 (in mt9p bit 2 selects fifo output data)
///<<li> bit 6 - 0 - normal, 1 - test (mt9p - reserved)</ul>
///< mt9p001:<ul>
///<<li> 9:7 pixclk slew rate (0..7, higher - faster) dflt - 7
///<<li> 12:10 output (but pixclk) slew rate (0..7, higher - faster) dflt -7 </ul>
#define P_MT9X001_SHTRWDTHU 0x08 ///< Shutter width upper - number of rows to integrate (dflt=0x?/?/0/0)
#define P_MT9X001_SHTRWDTH 0x09 ///< Shutter width - number of rows to integrate (dflt=0x419/4c9/619/797)
#define P_MT9X001_PXLCTL 0x0a ///< MT9P: Pixel clock control (dflt=0)
///< - bits 6:0 - divide pixel clock {0,1,2,4,8,16,32,64}
///< - bits 10:8 - shift pixel clock [-2,2]
///< - bit 15 - invert pixel clock
#define P_MT9X001_RESTART 0x0b ///< Sensor restart (autozeroed) writing 1 restarts frame /0
///< - bit 0 - 1 - restart (autoclearing bit)
///< - bit 1 - pause restart
///< - bit 2 - trigger (like trigger input)
#define P_MT9X001_SHTRDLY 0x0c ///< Shutter delay - number of pixels before row reset (dflt=0/0/0) - not mt9p
#define P_MT9X001_RESET 0x0d ///< 0 - normal, 1 - reset /0
#define P_MT9X001_PLL1 0x10 ///< MT9P: PLL CTL 1 (dflt=0x50)
///< - bit 0 - power PLL
///< - bit 1 - use PLL
///< - other bits - set to dflt (0x50)
#define P_MT9X001_PLL2 0x11 ///< MT9P: PLL CTL 2 (dflt=0x6404)
///< - 5:0 - PLL n divider [0,63] - dflt 4
///< - 15:8 PLL m factor [16,255] - dflt 0x64
*/
#define P_MT9X001_SHTRWDTHU 0x08 /* Shutter width upper - number of rows to integrate (dflt=0x?/?/0/0) */
#define P_MT9X001_SHTRWDTH 0x09 /* Shutter width - number of rows to integrate (dflt=0x419/4c9/619/797) */
#define P_MT9X001_PXLCTL 0x0a /* MT9P: Pixel clock control (dflt=0)
bits 6:0 - divide pixel clock {0,1,2,4,8,16,32,64}
bits 10:8 - shift pixel clock [-2,2]
bit 15 - invert pixel clock
*/
#define P_MT9X001_RESTART 0x0b /* Sensor restart (autozeroed) writing 1 restarts frame /0
bit 0 - 1 - restart (autoclearing bit)
bit 1 - pause restart
bit 2 - trigger (like trigger input)
*/
#define P_MT9X001_PLL3 0x12 ///< MT9P: PLL CTL 3 (dflt=0x0)
///< 4:0 PLL p1 divider [0,127]
#define P_MT9X001_SHTRDLY 0x0c /* Shutter delay - number of pixels before row reset (dflt=0/0/0) - not mt9p*/
#define P_MT9X001_RMODE1 0x1e ///< Read options 1 (+/- indicate per-device support), (dflt=0x8000/8040/8040/4006):<ul>
///< <li> ---+bits 0,1 - reserved, sould be 0 | strobe end
///< <li> ++--bit 2 - column skip 4 (1- skip, 0 - no) reg 0x20 bit 3 should be 0 to enable this bit
///< <li> ++--bit 3 - row skip 4 (1- skip, 0 - no) reg 0x20 bit 4 should be 0 to enable this bit
///< <li> ---+bits 3:2 - Strobe start
///< <li> ++-+bit 4 - column skip 8 (1- skip, 0 - no) bit 2 and reg 0x20 bit 3 should be 0 to enable this bit
///< <li> ---+bit 4 - Strobe enable
///< <li> ++--bit 5 - row skip 8 (1- skip, 0 - no) bit 3 and reg 0x20 bit 4 should be 0 to enable this bit
///< <li> ---+bit 5 - invert strobe
///< <li> -+--bit 6 - Noise suppression (1 - enabled, default=1)
///< <li> ---+bit 6 - bulb exposure
///< <li> ---+bit 7 - Global shutter reset (0 - ers)
///< <li> ++++bit 8 - snapshot mode (0 - continuous, 1 - wait trigger)
///< <li> +++-bit 9 - strobe enable (1 - enable, 0 - disable)
///< <li> ---+bit 9 - inver trigger
///< <li> +++-bit 10 - strobe width (0 - minimal, 1 - extended)
///< <li> ---+bit 10 - continuous line valid (during vert blank)
///< <li> +++-bit 11 - strobe override (strobe enable should be 0) - set strobe active if 1, 0 - normal
///< <li> ---+bit 11 - XOR line valid
///< <li> ---bits 12,13,14 - reserved, should be 0
///< <li> +++bit 15 - reserved, should be 1</ul>
#define P_MT9X001_RESET 0x0d /* 0 - normal, 1 - reset /0 */
#define P_MT9X001_RMODE2 0x20 ///< Read options 2 (+/- indicate per-device support), (dflt=0x1104/1104/0/40):<ul>
///< <li> +++-bit 0 - allow "bad frames". 0 (default) - output only good frames, 1 - allow bad also
///< <li> ----bits 1 - reserved, sould be 0
///< <li> ++--bit 2 - reserved, sould be 1/1/0
///< <li> ++--bit 3 - column skip (1 - read 2, skip 2; 0 - read all) If this bit is 1, both column skip 4 and column skip 8 (0x1e) are ignored
///< <li> ++--bit 4 - row skip (1 - read 2, skip 2; 0 - read all) Similar to the above
///< <li> ---+bit 5 -column sum in binning (0 - average)
///< <li> ++--bit 6 - reserved, should be 0
///< <li> ---+bit 6 - row BLC (dflt=`1) (use per-row black level, 0 - global)
///< <li> +??-bit 7 - flip odd/even rows (0 - normal)
///< <li> ++--bit 8 - reserved, should be 1
///< <li> +++-bit 9 - enable "line valid" during vertical blanking, 0 - normal (no lane valid during blanking)
///< <li> +++-bit 10 - XOR "line valid" with vertical blanking, 0 just mask "l.v." with bit 9
///< <li> +---bit 11 - reserved, sould be 0
///< <li> ---+bit 11 - show dark rows
///< <li> +---bit 12 - reserved, sould be 1
///< <li> ---+bit 12 - show dark columns
///< <li> +---bits 13 - reserved, sould be 0
///< <li> --++bit 14 - flip horizontal (0 - normal) *UNDOCUMENTED* documented in MT9P001 !!
///< <li> --++bit 15 - flip vertical (0 - normal)</ul>
#define P_MT9X001_RMODE3 0x21 ///< Read options 3 (+/- indicate per-device support) (MT9T only), (dflt=0x0):<ul>
///< <li> --+-bit 0 - Global Reset. If set, uses global reset in snapshot mode (dflt=0x0)
///< <li> --+-bit 1 - Use GSHT_CTL (if set uses GSHT_CTL pad signal only, if 0 - together with TRIGGER</ul>
#define P_MT9X001_RAM 0x22 ///< Row address mode (+/- indicate per-device support) (MT9T,P only), (dflt=0x0):<ul>
///< <li> --++bits 2:0 Row skip - number of rows to skip (0 - each row). Row period will be this value+1 (even in binning mode)
///< <li> --++bits 5:4 Row Bin - number of rows to bin to the first one. For full binning &lt;Row skip&gt;==&lt;row bin&gt;</ul>
#define P_MT9X001_CAM 0x23 ///< Column address mode (+/- indicate per-device support) (MT9T,P only), (dflt=0x0):<ul>
///< <li> --++bits 2:0 Column skip - number of column-pairs to skip (0 - each column-pair). Column-pair period will be this value+1 (even in binning mode)
///< <li> --++bits 5:4 Column Bin - number of columns to bin to the first one. Not clear is binning also in pairs? needs testing</ul>
///< Column start address should be multiple of &lt;column bin&gt;+1
#define P_MT9X001_GREEN1 0x2b ///< Green Gain 1, dflt= 0x08 (1x), for MT9T bits 14:8 - "digital gain"
#define P_MT9X001_BLUE 0x2c ///< Green Gain 1, dflt= 0x08 (1x), for MT9T bits 14:8 - "digital gain"
#define P_MT9X001_RED 0x2d ///< Green Gain 1, dflt= 0x08 (1x), for MT9T bits 14:8 - "digital gain"
#define P_MT9X001_GREEN2 0x2e ///< Green Gain 1, dflt= 0x08 (1x), for MT9T bits 14:8 - "digital gain"
#define P_MT9X001_ALLGAINS 0x35 ///< write to all 4 gains (0x2b,0x2c,0x2d,0x2e), read from red (0x2b)
#define P_MT9X001_DESIRBLACK 0x49 ///< bits 11:2 - desired black level (MT9T,P only dflt=0xa8)
#define P_MT9X001_ROWRBLACKOFFS 0x4b ///< bits 11:0 - desired black level (MT9P only - dflt=0x28)
#define P_MT9X001_COARSETHRSH 0x5d ///< Black level calibration coarse thersholds (+/- indicate per-device support) (MT9T only), dflt=0x2d13 <ul>
///< <li> --+bits 6:0 low coarse thershold (should be less than low thershold - see 0x5f) ,dflt=0x13
///< <li> --+bits 14:8 high coarse thershold (should be noless than high thershold - see 0x5f) ,dflt=0x2d</ul>
#define P_MT9X001_CALTHRESH 0x5f ///< Black level calibration control fields (+/- indicate per-device support) (dflt=0x904/a39f/231d):<ul>
///< <li> +--bits 5:0 - Low threshold for black in ADC LSBs (default - 4)
///< <li> -+-bits 5:0 - Low threshold for black in ADC LSBs (default - 29)
///< <li> --+bits 6:0 - Low threshold for black in ADC LSBs (default - 0x13)
///< <li> ++-bit 7 - Override automatic bits 5:0 and 14:8, 0 - automatic. dflt= 0/1/x
///< <li> +--bits 14:8 - Maximal allowed black level in ADC LSBs (default - low theresh+5=0x09)
///< <li> -+-bits 14:8 - Maximal allowed black level in ADC LSBs (default - low theresh+5=0x23)
///< <li> --+bits 14:8 - Maximal allowed black level in ADC LSBs (default - low theresh+5=0x23)
///< <li> ++-bit 15 - no gain dependence, 0 - both thresholds set automatically, dflt=0/1/x</ul>
#define P_MT9X001_PLL1 0x10 /* MT9P: PLL CTL 1 (dflt=0x50)
bit 0 - power PLL
bit 1 - use PLL
other bits - set to dflt (0x50)
*/
#define P_MT9X001_CALGREEN1 0x60 ///< analog offset for GREEN1 For MT9M, MT9D: bits 7:0 - magnitude, bit 8 - sign, MT9T - two's complement
#define P_MT9X001_CALGREEN2 0x61 ///< analog offset for GREEN2. For MT9M, MT9D: bits 7:0 - magnitude, bit 8 - sign, MT9T - two's complement
#define P_MT9X001_CALCTRL 0x62 ///< Black levels calibration control fields (+/- indicate per-device support) (dflt 0x498/8498/0):<ul>
///< <li> +++bit 0 - manual override, correct with programmed values. 0 (default) - automatically adjust offset values
///< <li> ++-bits 2,1 - force/disable black level calibration. 00 - apply calibration during ADC operation only (default),
///< 10 - apply calibration continuously, X1 - disable black level correction (set calibration voltages to 0)
///< <li> --+bit 2 0 - enable offset calibration (dflt), 1 - disable offset calibration voltage
///< <li> ++-bits 4:3 - reserved, sould be 1
///< <li> ++-bits 6:5 - reserved, sould be 0
///< <li> ++-bit 7 - reserved, sould be 1
///< <li> ++-bits 9:8 - reserved, sould be 0
///< <li> ++-bit 10 - reserved, sould be 1
///< <li> ++-bit 11 - 1 - do not reset the upper threshold after a black level recalculation sweep, 0 - reset after sweep (default)
///< <li> +++bit 12 - (autoreset bit) - start a new running average and perform a fast black level calibration (0 - normal)
///< <li> ++-bits 14:13 - reserved, sould be 0
///< <li> --+bit 13 - if set, lock red and blue channels calibration (red and blue gains should be equal)
///< <li> --+bit 14 - if set, lock green1 and green2 channels calibration (red and blue gains should be equal)
///< <li> ++-bit 15 - 1 - do not perform fast sweep after gains change, 0 - normal operation</ul>
#define P_MT9X001_CALRED 0x63 ///< analog offset for RED. For MT9M, MT9D: bits 7:0 - magnitude, bit 8 - sign MT9T - two's complement
#define P_MT9X001_CALBLUE 0x64 ///< analog offset for BLUE. For MT9M, MT9D: bits 7:0 - magnitude, bit 8 - sign MT9T - two's complement
#define P_MT9X001_7F 0x7f ///< Should be written 0 to prevent blue "bluming" columns
#define P_MT9X001_TEST 0xa0 ///< test patterns. Probably only in MT9P001?<ul>
///< <li> bits 6:3: <ul>
///< <li> 0: color field
///< <li> 1: horizontal gradient
///< <li> 2: vertical gradient
///< <li> 3: diagonal
///< <li> 4: classic
///< <li> 5: marching 1's
///< <li> 6: monochrome horizontal bars
///< <li> 7: monochrome vertical bars
///< <li> 8: vertical color bars</ul>
///< Legal values: [0, 15].</li>
///< <li> bit 2 Reserved</li>
///< <li> bit 1 Reserved
///< <li> bit 0 Enable_Test_Pattern. Enables the test pattern. When set, data from the ADC will be replaced with a digitally
///< generated test pattern specified by Test_Pattern_Mode.</li></ul>
#define P_MT9X001_PLL2 0x11 /* MT9P: PLL CTL 2 (dflt=0x6404)
5:0 - PLL n divider [0,63] - dflt 4
15:8 PLL m factor [16,255] - dflt 0x64
*/
#define P_MT9X001_PLL3 0x12 /* MT9P: PLL CTL 3 (dflt=0x0)
4:0 PLL p1 divider [0,127]
*/
#define P_MT9X001_RMODE1 0x1e /* Read options 1, (dflt=0x8000/8040/8040/4006):
---+bits 0,1 - reserved, sould be 0 | strobe end
++--bit 2 - column skip 4 (1- skip, 0 - no) reg 0x20 bit 3 should be 0 to enable this bit
++--bit 3 - row skip 4 (1- skip, 0 - no) reg 0x20 bit 4 should be 0 to enable this bit
---+bits 3:2 - Strobe start
++-+bit 4 - column skip 8 (1- skip, 0 - no) bit 2 and reg 0x20 bit 3 should be 0 to enable this bit
---+bit 4 - Strobe enable
++--bit 5 - row skip 8 (1- skip, 0 - no) bit 3 and reg 0x20 bit 4 should be 0 to enable this bit
---+bit 5 - invert strobe
-+--bit 6 - Noise suppression (1 - enabled, default=1)
---+bit 6 - bulb exposure
---+bit 7 - Global shutter reset (0 - ers)
++++bit 8 - snapshot mode (0 - continuous, 1 - wait trigger)
+++-bit 9 - strobe enable (1 - enable, 0 - disable)
---+bit 9 - inver trigger
+++-bit 10 - strobe width (0 - minimal, 1 - extended)
---+bit 10 - continuous line valid (during vert blank)
+++-bit 11 - strobe override (strobe enable should be 0) - set strobe active if 1, 0 - normal
---+bit 11 - XOR line valid
---bits 12,13,14 - reserved, should be 0
+++bit 15 - reserved, should be 1
*/
#define P_MT9X001_RMODE2 0x20 /* Read options 2, (dflt=0x1104/1104/0/40):
+++-bit 0 - allow "bad frames". 0 (default) - output only good frames, 1 - allow bad also
----bits 1 - reserved, sould be 0
++--bit 2 - reserved, sould be 1/1/0
++--bit 3 - column skip (1 - read 2, skip 2; 0 - read all) If this bit is 1, both column skip 4 and column skip 8 (0x1e) are ignored
++--bit 4 - row skip (1 - read 2, skip 2; 0 - read all) Similar to the above
---+bit 5 -column sum in binning (0 - average)
++--bit 6 - reserved, should be 0
---+bit 6 - row BLC (dflt=`1) (use per-row black level, 0 - global)
+??-bit 7 - flip odd/even rows (0 - normal)
++--bit 8 - reserved, should be 1
+++-bit 9 - enable "line valid" during vertical blanking, 0 - normal (no lane valid during blanking)
+++-bit 10 - XOR "line valid" with vertical blanking, 0 just mask "l.v." with bit 9
+---bit 11 - reserved, sould be 0
---+bit 11 - show dark rows
+---bit 12 - reserved, sould be 1
---+bit 12 - show dark columns
+---bits 13 - reserved, sould be 0
--++bit 14 - flip horizontal (0 - normal) *UNDOCUMENTED* documented in MT9P001 !!
--++bit 15 - flip vertical (0 - normal)
*/
#define P_MT9X001_RMODE3 0x21 /* Read options 3 (MT9T only), (dflt=0x0):
--+-bit 0 - Global Reset. If set, uses global reset in snapshot mode (dflt=0x0)
--+-bit 1 - Use GSHT_CTL (if set uses GSHT_CTL pad signal only, if 0 - together with TRIGGER
*/
#define P_MT9X001_RAM 0x22 /* Row address mode (MT9T,P only), (dflt=0x0):
--++bits 2:0 Row skip - number of rows to skip (0 - each row). Row period will be this value+1 (even in binning mode)
--++bits 5:4 Row Bin - number of rows to bin to the first one. For full binning <Row skip>==<row bin>
*/
#define P_MT9X001_CAM 0x23 /* Column address mode (MT9T,P only), (dflt=0x0):
--++bits 2:0 Column skip - number of column-pairs to skip (0 - each column-pair). Column-pair period will be this value+1 (even in binning mode)
--++bits 5:4 Column Bin - number of columns to bin to the first one. Not clear is binning also in pairs? needs testing
Column start address should be multiple of <column bin>+1
*/
#define P_MT9X001_GREEN1 0x2b /* Green Gain 1, dflt= 0x08 (1x)
for MT9T bits 14:8 - "digital gain" */
#define P_MT9X001_BLUE 0x2c /* Green Gain 1, dflt= 0x08 (1x)
for MT9T bits 14:8 - "digital gain" */
#define P_MT9X001_RED 0x2d /* Green Gain 1, dflt= 0x08 (1x)
for MT9T bits 14:8 - "digital gain" */
#define P_MT9X001_GREEN2 0x2e /* Green Gain 1, dflt= 0x08 (1x)
for MT9T bits 14:8 - "digital gain" */
#define P_MT9X001_ALLGAINS 0x35 /* write to all 4 gains (0x2b,0x2c,0x2d,0x2e), read from red (0x2b) */
#define P_MT9X001_DESIRBLACK 0x49 /* bits 11:2 - desired black level (MT9T,P only dflt=0xa8) */
#define P_MT9X001_ROWRBLACKOFFS 0x4b /* bits 11:0 - desired black level (MT9P only - dflt=0x28) */
#define P_MT9X001_COARSETHRSH 0x5d /* Black level calibration coarse thersholds (MT9T only), dflt=0x2d13
--+bits 6:0 low coarse thershold (should be less than low thershold - see 0x5f) ,dflt=0x13
--+bits 14:8 high coarse thershold (should be noless than high thershold - see 0x5f) ,dflt=0x2d
*/
#define P_MT9X001_CALTHRESH 0x5f /* Black level calibration control fields b(dflt=0x904/a39f/231d):
+--bits 5:0 - Low threshold for black in ADC LSBs (default - 4)
-+-bits 5:0 - Low threshold for black in ADC LSBs (default - 29)
--+bits 6:0 - Low threshold for black in ADC LSBs (default - 0x13)
++-bit 7 - Override automatic bits 5:0 and 14:8, 0 - automatic. dflt= 0/1/x
+--bits 14:8 - Maximal allowed black level in ADC LSBs (default - low theresh+5=0x09)
-+-bits 14:8 - Maximal allowed black level in ADC LSBs (default - low theresh+5=0x23)
--+bits 14:8 - Maximal allowed black level in ADC LSBs (default - low theresh+5=0x23)
++-bit 15 - no gain dependence, 0 - both thresholds set automatically, dflt=0/1/x
*/
#define P_MT9X001_CALGREEN1 0x60 /* analog offset for GREEN1. For MT9M, MT9D: bits 7:0 - magnitude, bit 8 - sign,
MT9T - two's complement
*/
#define P_MT9X001_CALGREEN2 0x61 /* analog offset for GREEN21. For MT9M, MT9D: bits 7:0 - magnitude, bit 8 - sign,
MT9T - two's complement
*/
#define P_MT9X001_CALCTRL 0x62 /* Black levels calibration control fields (dflt 0x498/8498/0)
+++bit 0 - manual override, correct with programmed values. 0 (default) - automatically adjust offset values
++-bits 2,1 - force/disable black level calibration. 00 - apply calibration during ADC operation only (default),
10 - apply calibration continuously, X1 - disable black level correction (set calibration voltages to 0)
--+bit 2 0 - enable offset calibration (dflt), 1 - disable offset calibration voltage
++-bits 4:3 - reserved, sould be 1
++-bits 6:5 - reserved, sould be 0
++-bit 7 - reserved, sould be 1
++-bits 9:8 - reserved, sould be 0
++-bit 10 - reserved, sould be 1
++-bit 11 - 1 - do not reset the upper threshold after a black level recalculation sweep, 0 - reset after sweep (default)
+++bit 12 - (autoreset bit) - start a new running average and perform a fast black level calibration (0 - normal)
++-bits 14:13 - reserved, sould be 0
--+bit 13 - if set, lock red and blue channels calibration (red and blue gains should be equal)
--+bit 14 - if set, lock green1 and green2 channels calibration (red and blue gains should be equal)
++-bit 15 - 1 - do not perform fast sweep after gains change, 0 - normal operation
*/
#define P_MT9X001_CALRED 0x63 /* analog offset for RED. For MT9M, MT9D: bits 7:0 - magnitude, bit 8 - sign
MT9T - two's complement
*/
#define P_MT9X001_CALBLUE 0x64 /* analog offset for BLUE. For MT9M, MT9D: bits 7:0 - magnitude, bit 8 - sign
MT9T - two's complement */
#define P_MT9X001_7F 0x7f /* Should be written 0 to prevent blue "bluming" columns*/
#define P_MT9X001_TEST 0xa0 ///test patterns. Probably only in MT9P001?
/*! bits 6:3:
0: color field
1: horizontal gradient
2: vertical gradient
3: diagonal
4: classic
5: marching 1's
6: monochrome horizontal bars
7: monochrome vertical bars
8: vertical color bars
Legal values: [0, 15].
bit 2 Reserved
bit 1 Reserved
bit 0 Enable_Test_Pattern. Enables the test pattern. When set, data from the ADC will be replaced with a digitally
generated test pattern specified by Test_Pattern_Mode.
*/
#define P_MT9X001_CHIPEN 0xF1 /* Chip enable and i2c sync (mirrors bits in feg 0x07 (default=0x01):
++-bit 0 - 1 - normal operation, 0 - stop readout (same as reg 0x07, bit 1)
++-bit 1 - 0 - normal, appropriate changes are made at frame boudary. 1 - do not update (same as reg 7 bit 0)
*/
#define P_MT9X001_CHIPEN1 0xF8 /* Chip enable and i2c sync (mirrors bits in feg 0x07 (default=0x01):
--+bit 0 - 1 - normal operation, 0 - stop readout (same as reg 0x07, bit 1)
--+bit 1 - 0 - normal, appropriate changes are made at frame boudary. 1 - do not update (same as reg 7 bit 0)
*/
int mt9x001_pgm_detectsensor (struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
#define P_MT9X001_CHIPEN 0xF1 ///< Chip enable and i2c sync (mirrors bits in reg 0x07 (+/- indicate per-device support) (default=0x01):<ul>
///< <li> ++-bit 0 - 1 - normal operation, 0 - stop readout (same as reg 0x07, bit 1)
///< <li> ++-bit 1 - 0 - normal, appropriate changes are made at frame boudary. 1 - do not update (same as reg 7 bit 0) </ul>
#define P_MT9X001_CHIPEN1 0xF8 ///< Chip enable and i2c sync (mirrors bits in feg 0x07 (+/- indicate per-device support)(default=0x01):<ul>
///< <li> --+bit 0 - 1 - normal operation, 0 - stop readout (same as reg 0x07, bit 1)
///< <li> --+bit 1 - 0 - normal, appropriate changes are made at frame boudary. 1 - do not update (same as reg 7 bit 0)</ul>
/** Detect one of Micron/Aptina/On Semiconductor sensors MT9M*, MT9D*,MT9T*, andMT9P* with parallel interface */
int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities)
struct framepars_t * thispars, ///< sensor current parameters
struct framepars_t * prevpars, ///< sensor previous parameters (not used here)
int frame16) ///< 4-bit (hardware) frame number parameters should
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
;
#if 0
int adjustBinning_mt9x001(void);
int program_woi_mt9x001(int nonstop);
......
......@@ -151,34 +151,9 @@
// porting 10353, 10359 r/w does not use sequencer, so pages allocation is handled by sensor_i2c module
const char * name_10359 = "el10359"; // Get name from DT (together with port mask)
const char * name_sensor = "mt9p006"; // Get name from DT (together with port mask)
//const char * name_10359 = "el10359"; // Get name from DT (together with port mask)
//const char * name_sensor = "mt9p006"; // Get name from DT (together with port mask)
//const char * name_clock = "cy22393"; // Get name from DT (together with port mask)
//#define I2C359_INC 2 ///< slave address increment between sensors in 10359A board (broadcast, 1,2,3)
/** Register i2c pages equal to slave address */
int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
///< @return 0 (may add errors)
{
int sensor_port, subchn;
x393_i2c_device_t *class_10359, *class_sensor, dev_sensor;
class_10359 = xi2c_dev_get(name_10359);
BUG_ON(!class_10359);
class_sensor= xi2c_dev_get(name_sensor);
BUG_ON(!class_sensor);
memcpy(&dev_sensor, class_sensor, sizeof(class_sensor));
for (sensor_port=1; sensor_port< SENSOR_PORTS; sensor_port++) if (ports & (1 << sensor_port)) {
i2c_page_register(sensor_port, class_10359->slave7);
set_xi2c_wrc(class_10359, sensor_port, class_10359->slave7, 0);
for (subchn = 0; subchn <4; subchn++){ // subchn == 0 - broadcast
dev_sensor.slave7 = class_sensor->slave7 + I2C359_INC * subchn;
i2c_page_register(sensor_port, dev_sensor.slave7);
set_xi2c_wrc(&dev_sensor, sensor_port, dev_sensor.slave7, 0);
}
// Now register one page for reading 10359 and the sensor using sensor speed data
set_xi2c_rdc(class_sensor, sensor_port, LEGACY_READ_PAGE, 0);
}
return 0;
}
......@@ -246,6 +221,7 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
MDF1(printk(" multisensor_write_i2c(0x%x, 0x%x, 0x%x, %d) -> %d\n",(int)(I2C359_SLAVEADDR),(int)(ra),(int)(v)&0xffff,2,rslt)); \
}
#else
// using new access in immediate mode by class name
#define MULTISENSOR_WRITE_I2C(port,name,offs,ra,v) \
{rslt |= multisensor_write_i2c((port),(name),(offs),(ra),(v)) ; \
MDF1(printk(" multisensor_write_i2c(%d, %s, 0x%x, 0x%x, 0x%x) -> %d\n",(int)(port),name,int(offs),(int)(ra),(int)(v),rslt));}
......@@ -971,7 +947,11 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
if (frame16 >= 0) return -1; // can only work in ASAP mode
if (thispars->pars[P_SENSOR]) return 0; // Sensor is already detected - do not bother (to re-detect it P_SENSOR should be set to 0)
MDF24(printk("Probing 10359 board, i2c bitdelays=0x%08x, hardware_i2c_running=%d\n",i2c_delays(0),i2s_running()));
#ifdef NC353
if (multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version, 4)<0) return -1;
#else
if (X3X3_I2C_RCV4(sensor_port, I2C359_SLAVEADDR, I2C359_VERSION, &bitstream_version)<0) return -1;
#endif
// Here we see that 10359A responds somehow. If next fails, no sense to try other sensor types.
multi_phases_initialized=0;
sensor->sensorType=SENSOR_NONE;
......@@ -1026,7 +1006,18 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
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
for (i=0;i<MAX_SENSORS;i++) {
MDF24(printk("Probing sensor port %d, i2c bitdelays=0x%08x\n",i,i2c_delays(0)));
rslt= multisensor_read_i2c(MT9P001_I2C_ADDR + ((i+1) * I2C359_INC), P_MT9X001_CHIPVER, &sensor_id[i], 2);
#ifdef NC353
rslt= multisensor_read_i2c(sensor_port,
MT9P001_I2C_ADDR + ((i+1) * I2C359_INC),
P_MT9X001_CHIPVER,
&sensor_id[i],
2);
#else
rslt= X3X3_I2C_RCV2 (sensor_port,
MT9P001_I2C_ADDR + ((i+1) * I2C359_INC),
P_MT9X001_CHIPVER,
&sensor_id[i]);
#endif
MDF24(printk("Probing sensor port %d, i2c bitdelays=0x%08x, rslt=0x%x\n",i,i2c_delays(0),rslt));
if (rslt==0) {
if (((sensor_id[i] ^ MT9P001_PARTID) & MT9X001_PARTIDMASK)==0) {
......@@ -1551,22 +1542,26 @@ int multisensor_set_phase_verify (int sensor_port, ///< sensor port nu
///< - -4 - not DONE (why?)
///< - -5 - not LOCKED
{
int rslt=multisensor_set_phase (sensor_port, reg_addr, resetDCM, newPhase, oldPhase);
unsigned long status=0;
int channel=-1;
if (rslt <0) return rslt;
switch (reg_addr) {
case I2C359_DCM_SDRAM: channel=0;break;
case I2C359_DCM_SENSOR1:channel=1;break;
case I2C359_DCM_SENSOR2:channel=2;break;
case I2C359_DCM_SENSOR3:channel=3;break;
}
if (channel<0) rslt= -I2C359_DCM_ERR_UNKNOWN; // unknown DCM
multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_DCM_STATUS, &status, 2);
if ( I2C359_DCM_OFL(0,status)) rslt= -I2C359_DCM_ERR_OVFL; // overflow
if (!I2C359_DCM_DONE(0,status)) rslt= -I2C359_DCM_ERR_NODONE; // not DONE - seems to bee too far - reset and put maximum (by abs value)
if (!I2C359_DCM_LOCKED(0,status)) rslt= -I2C359_DCM_ERR_NOLOCKED; // not LOCKED
return rslt;
int rslt=multisensor_set_phase (sensor_port, reg_addr, resetDCM, newPhase, oldPhase);
unsigned long status=0;
int channel=-1;
if (rslt <0) return rslt;
switch (reg_addr) {
case I2C359_DCM_SDRAM: channel=0;break;
case I2C359_DCM_SENSOR1:channel=1;break;
case I2C359_DCM_SENSOR2:channel=2;break;
case I2C359_DCM_SENSOR3:channel=3;break;
}
if (channel<0) rslt= -I2C359_DCM_ERR_UNKNOWN; // unknown DCM
#ifdef NC353
multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_DCM_STATUS, &status, 2);
#else
X3X3_I2C_RCV2(sensor_port,I2C359_SLAVEADDR, I2C359_DCM_STATUS, &status);
#endif
if ( I2C359_DCM_OFL(0,status)) rslt= -I2C359_DCM_ERR_OVFL; // overflow
if (!I2C359_DCM_DONE(0,status)) rslt= -I2C359_DCM_ERR_NODONE; // not DONE - seems to bee too far - reset and put maximum (by abs value)
if (!I2C359_DCM_LOCKED(0,status)) rslt= -I2C359_DCM_ERR_NOLOCKED; // not LOCKED
return rslt;
}
/** Set 10359A clock phase, try to recover from overflows */
......@@ -1582,45 +1577,54 @@ int multisensor_set_phase_recover(int sensor_port, ///< sensor port nu
///< - -4 - not DONE (why?)
///< - -5 - not LOCKED
{
int rslt=multisensor_set_phase (sensor_port, reg_addr, resetDCM, newPhase, oldPhase);
unsigned long status=0;
int channel=-1;
if (rslt <0) return rslt;
switch (reg_addr) {
case I2C359_DCM_SDRAM: channel=0;break;
case I2C359_DCM_SENSOR1:channel=1;break;
case I2C359_DCM_SENSOR2:channel=2;break;
case I2C359_DCM_SENSOR3:channel=3;break;
}
if (channel<0) rslt= -I2C359_DCM_ERR_UNKNOWN; // unknown DCM
multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_DCM_STATUS, &status, 2);
if ( I2C359_DCM_OFL(0,status)) rslt= -I2C359_DCM_ERR_OVFL; // overflow
if (!I2C359_DCM_DONE(0,status)) rslt= -I2C359_DCM_ERR_NODONE; // not DONE - seems to bee too far - reset and put maximum (by abs value)
if (!I2C359_DCM_LOCKED(0,status)) rslt= -I2C359_DCM_ERR_NOLOCKED; // not LOCKED
if ((rslt == -I2C359_DCM_ERR_NODONE) || (rslt== -I2C359_DCM_ERR_OVFL)) { // Not Done - DCM overflow, try reducing the phase (will need reset)
unsigned long goodPhase,badPhase;
short * newPhaseShort= (short *) &newPhase;
short * goodPhaseShort= (short *) &goodPhase;
short * badPhaseShort= (short *) &badPhase;
badPhase=newPhase;
goodPhase = badPhase & 0x30000; // only phase90 is preserved
while ((badPhaseShort[0]< (goodPhaseShort[0]-1)) || (badPhaseShort[0] > (goodPhaseShort[0]+1))) {
newPhaseShort[0]=(badPhaseShort[0]+goodPhaseShort[0])/2;
rslt=multisensor_set_phase (sensor_port, reg_addr, (rslt<0), newPhase, goodPhase);
if (rslt<0) return rslt;
// check DCM status
multisensor_read_i2c(sensor_port, I2C359_SLAVEADDR, I2C359_DCM_STATUS, &status, 2);
if ( I2C359_DCM_OFL(0,status)) rslt= -I2C359_DCM_ERR_OVFL; // overflow
if (!I2C359_DCM_DONE(0,status)) rslt= -I2C359_DCM_ERR_NODONE; // not DONE - seems to bee too far - reset and put maximum (by abs value)
if (!I2C359_DCM_LOCKED(0,status)) rslt= -I2C359_DCM_ERR_NOLOCKED; // not LOCKED
if ((rslt<0) && (rslt != -I2C359_DCM_ERR_NODONE) && (rslt != -I2C359_DCM_ERR_OVFL)) return rslt; // Other errors - consider fatal;
if (rslt<0) badPhase= newPhase;
else goodPhase = newPhase;
int rslt=multisensor_set_phase (sensor_port, reg_addr, resetDCM, newPhase, oldPhase);
unsigned long status=0;
int channel=-1;
if (rslt <0) return rslt;
switch (reg_addr) {
case I2C359_DCM_SDRAM: channel=0;break;
case I2C359_DCM_SENSOR1:channel=1;break;
case I2C359_DCM_SENSOR2:channel=2;break;
case I2C359_DCM_SENSOR3:channel=3;break;
}
rslt=goodPhase;
MDF24(printk("Reduced NewPhase, goodPhase= 0x%lx oldPhase= 0x%lx\r\n", goodPhase, oldPhase ));
}
return rslt;
if (channel<0) rslt= -I2C359_DCM_ERR_UNKNOWN; // unknown DCM
#ifdef NC353
multisensor_read_i2c (I2C359_SLAVEADDR, I2C359_DCM_STATUS, &status, 2);
#else
X3X3_I2C_RCV2(sensor_port,I2C359_SLAVEADDR, I2C359_DCM_STATUS, &status);
#endif
if ( I2C359_DCM_OFL(0,status)) rslt= -I2C359_DCM_ERR_OVFL; // overflow
if (!I2C359_DCM_DONE(0,status)) rslt= -I2C359_DCM_ERR_NODONE; // not DONE - seems to bee too far - reset and put maximum (by abs value)
if (!I2C359_DCM_LOCKED(0,status)) rslt= -I2C359_DCM_ERR_NOLOCKED; // not LOCKED
if ((rslt == -I2C359_DCM_ERR_NODONE) || (rslt== -I2C359_DCM_ERR_OVFL)) { // Not Done - DCM overflow, try reducing the phase (will need reset)
unsigned long goodPhase,badPhase;
short * newPhaseShort= (short *) &newPhase;
short * goodPhaseShort= (short *) &goodPhase;
short * badPhaseShort= (short *) &badPhase;
badPhase=newPhase;
goodPhase = badPhase & 0x30000; // only phase90 is preserved
while ((badPhaseShort[0]< (goodPhaseShort[0]-1)) || (badPhaseShort[0] > (goodPhaseShort[0]+1))) {
newPhaseShort[0]=(badPhaseShort[0]+goodPhaseShort[0])/2;
rslt=multisensor_set_phase (sensor_port, reg_addr, (rslt<0), newPhase, goodPhase);
if (rslt<0) return rslt;
// check DCM status
#ifdef NC353
multisensor_read_i2c(sensor_port, I2C359_SLAVEADDR, I2C359_DCM_STATUS, &status, 2);
#else
X3X3_I2C_RCV2 (sensor_port, I2C359_SLAVEADDR, I2C359_DCM_STATUS, &status);
#endif
if ( I2C359_DCM_OFL(0,status)) rslt= -I2C359_DCM_ERR_OVFL; // overflow
if (!I2C359_DCM_DONE(0,status)) rslt= -I2C359_DCM_ERR_NODONE; // not DONE - seems to bee too far - reset and put maximum (by abs value)
if (!I2C359_DCM_LOCKED(0,status)) rslt= -I2C359_DCM_ERR_NOLOCKED; // not LOCKED
if ((rslt<0) && (rslt != -I2C359_DCM_ERR_NODONE) && (rslt != -I2C359_DCM_ERR_OVFL)) return rslt; // Other errors - consider fatal;
if (rslt<0) badPhase= newPhase;
else goodPhase = newPhase;
}
rslt=goodPhase;
MDF24(printk("Reduced NewPhase, goodPhase= 0x%lx oldPhase= 0x%lx\r\n", goodPhase, oldPhase ));
}
return rslt;
}
......@@ -1906,27 +1910,32 @@ int multisensor_memphase (int sensor_port, ///< Sensor port
MULTISENSOR_WRITE_I2C32(sensor_port, I2C359_SDRAM_CHEN, I2C359_SDRAM_STOP(4) | I2C359_SDRAM_STOP(5)); // initialize write and read channels, reset SDRAM and buffer addresses
MULTISENSOR_WRITE_I2C32(sensor_port, I2C359_SDRAM_CHEN, I2C359_SDRAM_RUN(4) | I2C359_SDRAM_RUN(5)); // enable write and read channels
for (i=0; i<64;i++) {
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_DATA, (((i&7)==3) || ((i&7)==4) || ((i&7)==5))?0xffff:0); // pattern of 5 zeores, 3 ffff-s
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_DATA, (((i&7)==3) || ((i&7)==4) || ((i&7)==5))?0xffff:0); // pattern of 5 zeores, 3 ffff-s
}
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_PAGE_WR, 0); // start page write
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_PAGE_RD, 0); // start page read (expecting i2c to be much slower than page wr/rd
for (i=0; i<64;i++) {
multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_SDRAM_DATA, &data[i], 2);
#ifdef NC353
multisensor_read_i2c (I2C359_SLAVEADDR, I2C359_SDRAM_DATA, &data[i], 2);
#else
X3X3_I2C_RCV2(sensor_port,I2C359_SLAVEADDR, I2C359_SDRAM_DATA, &data[i]);
#endif
}
for (i=0;i<8;i++) setbits[i]=0;
for (n=0;n<64;n++) {
d=data[n];
for (i=0;i<16;i++) {
if (d & 1) {
setbits[n & 7]++;
sx+=(n & 7)-4;
s++;
}
d>>=1;
}
d=data[n];
for (i=0;i<16;i++) {
if (d & 1) {
setbits[n & 7]++;
sx+=(n & 7)-4;
s++;
}
d>>=1;
}
}
int OK=(setbits[0]==0) && (setbits[1]==0) && (setbits[2]==0) && (setbits[3]==0x80) && (setbits[4]==0x80) && (setbits[5]==0x80) && (setbits[6]==0) && (setbits[7]==0);
// for (i=0; i<8;i++) printk (" %03x ",setbits[i]); printk("\n");
// for (i=0; i<8;i++) printk (" %03x ",setbits[i]); printk("\n");
n=(0x10000*sx)/s;
if (centroid0x10000) centroid0x10000[0]=n;
MDF24 (printk("centroid=0x%x, OK=%d\n",n,OK));
......@@ -1945,34 +1954,39 @@ int multisensor_memphase_debug (int sensor_port, ///< Sesnor port number (0..3)
int sx=0;
int rslt=0;
if (write >=0) {
MULTISENSOR_WRITE_I2C32(sensor_port, I2C359_SDRAM_CHEN, I2C359_SDRAM_STOP(4) | I2C359_SDRAM_STOP(5)); // initialize write and read channels, reset SDRAM and buffer addresses
MULTISENSOR_WRITE_I2C32(sensor_port, I2C359_SDRAM_CHEN, I2C359_SDRAM_RUN(4) | I2C359_SDRAM_RUN(5)); // enable write and read channels
if (write) {
for (i=0; i<64;i++) {
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_DATA, (((i&7)==3) || ((i&7)==4) || ((i&7)==5))?0xffff:0); // pattern of 5 zeores, 3 ffff-s
MULTISENSOR_WRITE_I2C32(sensor_port, I2C359_SDRAM_CHEN, I2C359_SDRAM_STOP(4) | I2C359_SDRAM_STOP(5)); // initialize write and read channels, reset SDRAM and buffer addresses
MULTISENSOR_WRITE_I2C32(sensor_port, I2C359_SDRAM_CHEN, I2C359_SDRAM_RUN(4) | I2C359_SDRAM_RUN(5)); // enable write and read channels
if (write) {
for (i=0; i<64;i++) {
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_DATA, (((i&7)==3) || ((i&7)==4) || ((i&7)==5))?0xffff:0); // pattern of 5 zeores, 3 ffff-s
}
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_PAGE_WR, 0); // start page write
}
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_PAGE_WR, 0); // start page write
}
}
MULTISENSOR_WRITE_I2C16(sensor_port, I2C359_SDRAM_PAGE_RD, 0); // start page read (expecting i2c to be much slower than page wr/rd
for (i=0; i<64;i++) {
multisensor_read_i2c(I2C359_SLAVEADDR, I2C359_SDRAM_DATA, &data[i], 2);
#ifdef NC353
multisensor_read_i2c (I2C359_SLAVEADDR, I2C359_SDRAM_DATA, &data[i], 2);
#else
X3X3_I2C_RCV2(sensor_port,I2C359_SLAVEADDR, I2C359_SDRAM_DATA, &data[i]);
#endif
}
for (i=0; i<8;i++) printk (" %02x ",i); printk("\n");
for (n=0;n<64;n+=8) {
for (i=0; i<8;i++) printk ("%04lx ", data[n+i]); printk("\n");
for (i=0; i<8;i++) printk ("%04lx ", data[n+i]); printk("\n");
}
for (i=0;i<8;i++) setbits[i]=0;
for (n=0;n<64;n++) {
d=data[n];
for (i=0;i<16;i++) {
if (d & 1) {
setbits[n & 7]++;
sx+=(n & 7)-4;
s++;
}
d>>=1;
}
d=data[n];
for (i=0;i<16;i++) {
if (d & 1) {
setbits[n & 7]++;
sx+=(n & 7)-4;
s++;
}
d>>=1;
}
}
int OK=(setbits[0]==0) && (setbits[1]==0) && (setbits[2]==0) && (setbits[3]==0x80) && (setbits[4]==0x80) && (setbits[5]==0x80) && (setbits[6]==0) && (setbits[7]==0);
for (i=0; i<8;i++) printk (" %03x ",setbits[i]); printk("\n");
......
......@@ -26,7 +26,7 @@
//multisensor.h
#define I2C359_INC 2 ///< slave address increment between sensors in 10359A board (broadcast, 1,2,3) (7 bits SA)
//#define I2C359_INC 2 //< slave address increment between sensors in 10359A board (broadcast, 1,2,3) (7 bits SA) moved to sensor_common
#define I2C359_SLAVEADDR 0x08 ///< slave address of the 10359A board (move?) - 393 - use el10359 device class (7 bits SA)
#define I2C359_VERSION 0x00 ///< register address: 32-bit FPGA bitstream version
#define I2C359_MINVERSION 0x0359104b ///< Minimal FPGA version compatible with this software
......@@ -130,6 +130,7 @@ each dibit:
//#define I2C359_CLK_NUMBER 4 // system clock number for the 10359A on-board clock generator
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;
......
......@@ -2,24 +2,11 @@
///extern struct sensorproc_t * sensorproc;
#include "sensor_i2c.h"
#define LEGACY_READ_PAGE 0xff
int init_pgm_proc(void);
int add_sensor_proc(int index, int (*sens_func)(int sensor_port, struct sensor_t * , struct framepars_t * , struct framepars_t *, int ));
/** Perform I2C write (8 bits address, a6 bits data in "legacy" mode,
* pages matching slave address should be registered.
*
* TODO: Add registering single sensors as in multi10359. Registering twice is OK.
* Slave address is now 7-bit,old was 8-bit, change (10359 already done)
* @param port - sensor port
* @param frame Frame number to apply, <0 - ASAP
* @param sa7 I2C slave address, 7 bit
* @param reg sensor register address (8-bit)
* @param data value to set (16 bits) */
#define X3X3_I2C_SEND2(port,frame,sa7,reg,data) write_xi2c_reg16_abs_asap(port,sa7,frame,reg,data)
/** Tells if parameter is modifies
* @param x parameter index to test
......
......@@ -202,7 +202,7 @@ struct sensorproc_t * copy_sensorproc (int sensor_port, struct sensorproc_t * co
//#ifdef TEST_DISABLE_CODE
///
//
// initializes structures for the image acquisition parameter
// initializes hardware i2c controller and the command sequencer (leaves them stopped to ignore any frame syncs)
// sets some default acquisition parameters
......@@ -210,9 +210,9 @@ struct sensorproc_t * copy_sensorproc (int sensor_port, struct sensorproc_t * co
// TODO: Take care while turning off reset on i2c and cmd_sequencer so there will be no sensor vsync lost
// (easier to do in FPGA)
// Done:
///#define CCAM_VSYNC_ON port_csp0_addr[X313_WA_DCR1]=X353_DCR1(BLOCKVSYNC,0)
///#define CCAM_VSYNC_OFF port_csp0_addr[X313_WA_DCR1]=X353_DCR1(BLOCKVSYNC,1)
///
// #define CCAM_VSYNC_ON port_csp0_addr[X313_WA_DCR1]=X353_DCR1(BLOCKVSYNC,0)
// #define CCAM_VSYNC_OFF port_csp0_addr[X313_WA_DCR1]=X353_DCR1(BLOCKVSYNC,1)
//
int init_acq_sensor(void); // Never used?
//DECLARE_TASKLET(tasklet_fpga, tasklet_fpga_function, 0); // 0 - no arguments for now
......@@ -893,6 +893,38 @@ int image_acq_stop(struct platform_device *pdev)
return 0;
}
//#define I2C359_INC 2 ///< slave address increment between sensors in 10359A board (broadcast, 1,2,3)
/** Register i2c pages equal to slave address,
* Use to convert 353 code */
int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
///< @return 0 (may add errors)
{
int sensor_port, subchn;
x393_i2c_device_t *class_10359, *class_sensor, dev_sensor;
class_10359 = xi2c_dev_get(name_10359);
BUG_ON(!class_10359);
class_sensor= xi2c_dev_get(name_sensor);
BUG_ON(!class_sensor);
memcpy(&dev_sensor, class_sensor, sizeof(class_sensor));
for (sensor_port=1; sensor_port< SENSOR_PORTS; sensor_port++) if (ports & (1 << sensor_port)) {
i2c_page_register(sensor_port, class_10359->slave7);
set_xi2c_wrc(class_10359, sensor_port, class_10359->slave7, 0);
for (subchn = 0; subchn <4; subchn++){ // subchn == 0 - broadcast
dev_sensor.slave7 = class_sensor->slave7 + I2C359_INC * subchn;
i2c_page_register(sensor_port, dev_sensor.slave7);
set_xi2c_wrc(&dev_sensor, sensor_port, dev_sensor.slave7, 0);
}
// Now register one page for reading 10359 and the sensor using sensor speed data
memcpy(&dev_sensor, class_sensor, sizeof(class_sensor));
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE2, 0);
dev_sensor->data_bytes=4; // for reading 10359 in 32-bit mode
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4, 0);
}
return 0;
}
//static const struct of_device_id elphel393_sensor_of_match[] = {
// { .compatible = "elphel,elphel393-sensor-1.00" },
// { /* end of list */ }
......
......@@ -67,4 +67,60 @@ long long get_frame_counter(unsigned int chn);
long long get_frame_pos(unsigned int chn, unsigned int pos);
/* end of debug code */
#define LEGACY_READ_PAGE2 0xff
#define LEGACY_READ_PAGE4 0xfe
#define name_10359 "el10359" // Get name from DT (together with port mask)
#define name_sensor "mt9p006" // Get name from DT (together with port mask)
#define I2C359_INC 2 ///< slave address increment between sensors in 10359A board (broadcast, 1,2,3) (7 bits SA)
/** Perform I2C write (8 bits address, 16 bits data in "legacy" mode,
* pages matching slave address should be registered.
*
* TODO: Add registering single sensors as in multi10359. Registering twice is OK.
* Slave address is now 7-bit,old was 8-bit, change (10359 already done)
* @param port - sensor port
* @param frame Frame number to apply, <0 - ASAP
* @param sa7 I2C slave address, 7 bit
* @param reg sensor register address (8-bit)
* @param data value to set (16 bits) */
#define X3X3_I2C_SEND2(port,frame,sa7,reg,data) write_xi2c_reg16_abs_asap((port),(sa7),(frame),(reg),(data))
/** Perform I2C write in immediate mode (8 bits address, 16 bits data in "legacy" mode,
* pages matching slave address should be registered.
*
* Slave address is now 7-bit,old was 8-bit, change (10359 already done)
* @param port - sensor port
* @param sa7 I2C slave address, 7 bit
* @param reg sensor register address (8-bit)
* @param data value to set (16 bits) */
#define X3X3_I2C_SEND2_ASAP(port,sa7,reg,data) write_xi2c_reg16((port),(sa7),(reg),(data))
/** Perform I2C read (8 bits address, 16 bits data in "legacy" mode (sensors and 10359),
* page LEGACY_READ_PAGE2 (==0xff) should be registered - legacy_i2c.
*
* Slave address is now 7-bit,old was 8-bit, change (10359 already done)
* @param port - sensor port
* @param sa7 I2C slave address, 7 bit
* @param reg sensor register address (8-bit)
* @param datap pointer to receive data
* @return 0 on success, < 0 - error (ETIMEDOUT) */
#define X3X3_I2C_RCV2(port,sa7,reg,datap) legacy_read_i2c_reg((port),(LEGACY_READ_PAGE2),(sa7),(reg),2,(datap))
/** Perform I2C read (8 bits address, 32 bits data in "legacy" mode (10359 in 32-bit mode),
* page LEGACY_READ_PAGE2 (==0xff) should be registered - legacy_i2c.
*
* Slave address is now 7-bit,old was 8-bit, change (10359 already done)
* @param port - sensor port
* @param sa7 I2C slave address, 7 bit
* @param reg sensor register address (8-bit)
* @param datap pointer to receive data
* @return 0 on success, < 0 - error (ETIMEDOUT) */
#define X3X3_I2C_RCV4(port,sa7,reg,datap) legacy_read_i2c_reg((port),(LEGACY_READ_PAGE4),(sa7),(reg),4,(datap))
int legacy_i2c (int ports);
#endif
......@@ -416,10 +416,10 @@ void write_xi2c_reg16_abs_asap (int chn, ///< sensor port
u32 data) ///< 16 or 8-bit data (LSB aligned)
{
u32 dw = ((page & 0xff) << 24) | ((addr & 0xff) << 16) | (data & 0xffff);
if (frame<0) x393_sensi2c_abs (dw, chn, 0);
if (frame<0) x393_sensi2c_rel (dw, chn, 0);
else x393_sensi2c_abs (dw, chn, frame & PARS_FRAMES_MASK);
}
EXPORT_SYMBOL_GPL(write_xi2c_reg16_abs);
EXPORT_SYMBOL_GPL(write_xi2c_reg16_abs_asap);
/** Initiate sensor i2c read in immediate mode (data itself has to be read from FIFO with read_xi2c_fifo)
......@@ -603,6 +603,51 @@ int x393_xi2c_read_reg( const char * cname, ///< device class name
}
EXPORT_SYMBOL_GPL(x393_xi2c_read_reg);
/** Single-command i2c read register compatible with legacy code. Device class(es) should already be registered, len parameter should
* match pre-programmed length */
int legacy_read_i2c_reg( int chn, ///< sensor port number
int page, ///< i2c table page registerd for read operation
int sa7, ///< slave address (7-bit) of the device
///< Offset is non-zero when multiple devices of the same class are present.
int reg_addr, ///< register address (width is defined by class)
int len, ///< number of bytes to read.
int * datap) ///< pointer to a data receiver (read data width is defined by class)
///< @return 0 on success, < 0 - error (ETIMEDOUT)
{
int i, db=-1;
unsigned long timeout_end;
*datap = 0;
/* Initiate i2c read */
read_xi2c_sa7 (chn,
page & 0xff, // page (8 bits)
sa7 & 0x7f, // 7-bit i2c slave address
reg_addr & 0xffff); // 8/16 bit address
/* Now read required number of bytes with timeout */
dev_dbg(sdev, "Trying to get FIFO data for channel %d\n",chn);
for (i = 0; i< len; i++) {
timeout_end = jiffies + tenth_sec;
while (jiffies < timeout_end){
db = read_xi2c_fifo(chn);
if (db >=0)
break;
}
if (db < 0) {
dev_dbg(sdev, "Timeout waiting for i2c fifo read data for channel %d, freeing page %d\n",chn,page);
return -ETIMEDOUT;
}
*datap = (*datap <<8) | (db & 0xff);
}
return 0;
}
EXPORT_SYMBOL_GPL(legacy_read_i2c_reg);
/* Handling classes of i2c devices */
/** Find device list entry by device class name */
struct x393_i2c_device_list * i2c_dev_get(const char * name) ///< Device class name as string
......@@ -720,6 +765,7 @@ static ssize_t i2c_class_store(struct device *dev, ///< Linux kerne
int ni, sa7, num_addr, num_data, khz;
struct device_attribute *new_attr;
int rslt;
char * dname;
ni = sscanf(buf,"%31s %i %i %i %i", name, &sa7, &num_addr, &num_data, &khz);
if (ni < 5) {
dev_err(dev, "Requires 5 parameters: name, slave addr (7 bit), address width (bytes), data width (bytes), max SCL frequency (kHz)\n");
......@@ -733,8 +779,12 @@ static ssize_t i2c_class_store(struct device *dev, ///< Linux kerne
new_attr = devm_kzalloc(dev, sizeof(new_attr[0]), GFP_KERNEL);
if (!new_attr)
return -ENOMEM;
new_attr->attr.name = devm_kzalloc(dev, strlen(name)+1, GFP_KERNEL);
strcpy(new_attr->attr.name, (const char *) name);
// new_attr->attr.name = devm_kzalloc(dev, strlen(name)+1, GFP_KERNEL);
// strcpy(new_attr->attr.name, (const char *) name); // warning that it disqualifies const
dname = devm_kzalloc(dev, strlen(name)+1, GFP_KERNEL);
strcpy(dname, name);
new_attr->attr.name= (const char *) dname;
new_attr->attr.mode = SYSFS_PERMISSIONS;
new_attr->show = i2c_member_show;
new_attr->store = i2c_member_store;
......
......@@ -14,8 +14,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
#ifndef SENSOR_I2C.H
#define SENSOR_I2C.H
#ifndef SENSOR_I2C_H
#define SENSOR_I2C_H
/** I2C device description to be used with i2c sequencer*/
typedef struct{
char name[32]; ///< Device class name (up to 31 characters)
......@@ -149,4 +150,13 @@ int x393_xi2c_read_reg( const char * cname, // device class name
int sa7_offs, // slave address (7-bit) offset from the class defined slave address
int reg_addr, // register address (width is defined by class)
int * datap); // pointer to a data receiver (read data width is defined by class)
int legacy_read_i2c_reg(int chn, // sensor port number
int page, // i2c table page registerd for read operation
int sa7, // slave address (7-bit) of the device
// Offset is non-zero when multiple devices of the same class are present.
int reg_addr, // register address (width is defined by class)
int len, // number of bytes to read.
int * datap); // pointer to a data receiver (read data width is defined by class)
// @return 0 on success, < 0 - error (ETIMEDOUT)
#endif
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