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

converting sensor-related code

parent af248eb3
This diff is collapsed.
//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.
This diff is collapsed.
......@@ -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) {
......@@ -1562,7 +1553,11 @@ int multisensor_set_phase_verify (int sensor_port, ///< sensor port nu
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
......@@ -1593,7 +1588,12 @@ int multisensor_set_phase_recover(int sensor_port, ///< sensor port nu
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);
#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
......@@ -1608,8 +1608,12 @@ int multisensor_set_phase_recover(int sensor_port, ///< sensor port nu
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
// 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
......@@ -1911,7 +1915,12 @@ int multisensor_memphase (int sensor_port, ///< Sensor port
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++) {
......@@ -1926,7 +1935,7 @@ int multisensor_memphase (int sensor_port, ///< Sensor port
}
}
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));
......@@ -1956,7 +1965,12 @@ int multisensor_memphase_debug (int sensor_port, ///< Sesnor port number (0..3)
}
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) {
......
......@@ -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