Commit 128b5975 authored by Andrey Filippov's avatar Andrey Filippov

working on lepton driver

parent 87b9b1b0
/**/
/ {
chosen {
bootargs = "earlycon cma=336M root=/dev/mmcblk0p2 rw rootwait rootfstype=ext4";
bootargs = "earlycon cma=336M root=/dev/mmcblk0p2 rw rootwait rootfstype=ext4 debug";
stdout-path = "serial0:115200n8";
};
};
This diff is collapsed.
......@@ -308,6 +308,10 @@
compatible = "elphel,elphel393-mt9f002-1.00";
};
elphel393_lepton: elphel393-lepton@0 {
compatible = "elphel,elphel393-lepton-1.00";
};
elphel393_clock10359:elphel393-clock10359@0{
compatible = "elphel,elphel393_clock10359-1.00";
};
......
......@@ -27,6 +27,7 @@ obj-$(CONFIG_ELPHEL393) += histograms.o
obj-$(CONFIG_ELPHEL393) += pgm_functions.o
obj-$(CONFIG_ELPHEL393) += mt9x001.o
obj-$(CONFIG_ELPHEL393) += mt9f002.o
obj-$(CONFIG_ELPHEL393) += lepton.o
obj-$(CONFIG_ELPHEL393) += multi10359.o
obj-$(CONFIG_ELPHEL393) += imu_log393.o
......
......@@ -37,6 +37,7 @@
#include "mt9x001.h"
#include "mt9f002.h"
#include "multi10359.h"
#include "lepton.h"
#include "detect_sensors.h"
#define DETECT_SENSORS_MODULE_DESCRIPTION "Detect sensor type(s) attached to each of the ports"
......@@ -78,7 +79,7 @@ const struct sensor_name_t sensor_names[] ={
{.name="mt9f002", .type=1, .iface=HISPI4, .code = SENSOR_MT9F002}, // MT9F002
{.name="ibis51300", .type=1, .iface=PARALLEL12, .code = SENSOR_IBIS51300}, // FillFactory IBIS51300
{.name="kai11002", .type=1, .iface=PARALLEL12, .code = SENSOR_KAI11000}, // Kodak KAI11002
{.name="lepton3.5", .type=1, .iface=VOSPI, .code = SENSOR_LEPTON35}, // Kodak KAI11002
{.name="lepton35", .type=1, .iface=VOSPI, .code = SENSOR_LEPTON35}, // Kodak KAI11002
{.name=NULL, .type=0, .iface=NONE, .code = 0} // end of list
};
static sens_iface_t port_iface[SENSOR_PORTS];
......@@ -370,6 +371,7 @@ static int elphel393_detect_sensors_sysfs_register(struct platform_device *pdev)
char names[4][80];
struct device_node *node = pdev->dev.of_node;
int num_ports, port, num_sub, sub_chn;
int scode;
if (node) {
config_string = of_get_property(node, OF_PREFIX_NAME",port-mux", NULL); // &len);
pr_info ("Mux config_string = %s (was looking for '%s')\n",config_string, OF_PREFIX_NAME",port-mux");
......@@ -397,6 +399,10 @@ static int elphel393_detect_sensors_sysfs_register(struct platform_device *pdev)
num_sub = sscanf(config_string,"%79s %79s %79s %79s", names[0], names[1], names[2], names[3]);
pr_info ("port %d : %d subchannels\n",port, num_sub);
for (sub_chn = 0; sub_chn < num_sub; sub_chn++){
scode = get_code_by_name(names[sub_chn], DETECT_SENSOR);
if (scode < 0){
pr_err("Invalid sensor/mux name found in device tree: %s\n",names[sub_chn]);
}
pr_info ("Setting sensor %d:%d '%s' (0x%x)\n",port, sub_chn, names[sub_chn], get_code_by_name(names[sub_chn], DETECT_SENSOR));
set_detected_sensor_code(port, sub_chn, get_code_by_name(names[sub_chn], DETECT_SENSOR));
init_port_ahead_table(port,sub_chn);
......@@ -459,7 +465,7 @@ int detect_sensors_par2addr_init(int port,int sub_chn){
u16 haddr2rec[MAX_SENSORS][MAX_FPGA_RECS]; ///< Big LUT (but almost empty). Sensor's page address (haddr of reg addr) to fpga i2c record number (fpga line#)
};
*/
dev_info(g_dev_ptr,"detect_sensors_par2addr_init(): sensorPortConfig[%d].sensor[%d] = 0x%x\n",port, sub_chn, sensorPortConfig[port].sensor[sub_chn]);
switch (sensorPortConfig[port].sensor[sub_chn]) {
case SENSOR_MT9P006:
// get sensor table
......@@ -473,6 +479,11 @@ int detect_sensors_par2addr_init(int port,int sub_chn){
pages = mt9f002_pages;
atab = mt9f002_ahead_tab;
break;
case SENSOR_LEPTON35:
par2addr = lepton_par2addr;
pages = lepton_pages;
atab = lepton_ahead_tab;
break;
}
if (par2addr){
// convert to key-value
......@@ -484,44 +495,6 @@ int detect_sensors_par2addr_init(int port,int sub_chn){
sensorPortConfig[port].ahead_tab[sub_chn] = atab;
}
/*
// all .mux and .sensor are already filled out
for (portx = 0; portx < SENSOR_PORTS; portx++){
// that's from device tree, fpga is not programmed yet
dev_dbg(g_dev_ptr,"port: %d mux: %d sensors: %d %d %d %d\n",
portx,
sensorPortConfig[portx].mux,
sensorPortConfig[portx].sensor[0],
sensorPortConfig[portx].sensor[1],
sensorPortConfig[portx].sensor[2],
sensorPortConfig[portx].sensor[3]
);
// sub_chn = 3 is never used
for (sub_chn = 0; sub_chn < 4; sub_chn++){
//sensorPortConfig[port].sensor[sub_chn];
switch (sensorPortConfig[portx].sensor[sub_chn]) {
case SENSOR_MT9P006:
// get sensor table
par2addr = mt9x001_par2addr;
pages = mt9x001_pages;
break;
case SENSOR_MT9F002:
// get sensor table
par2addr = mt9f002_par2addr;
pages = mt9f002_pages;
break;
}
if (par2addr){
// convert to key-value
par2addr_fill(par2addr,sensorPortConfig[portx].par2addr[sub_chn]);
// save pointer to static LUT
sensorPortConfig[portx].pages_ptr[sub_chn] = pages;
}
}
}
*/
return 0;
}
......
This diff is collapsed.
/***************************************************************************//**
* @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/>.
*******************************************************************************/
#ifndef _LEPTON_H
#define _LEPTON_H
#define LEPTON35_I2C_ADDR 0x2a ///< Lepton I2C slave address (7 bit)
/* i2c Lepton 3.5 registers will be defined here. Only even addresses are used by Lepton */
#define P_LEPTON_POWER 0x00 ///< Power On/Off register
#define P_LEPTON_STATUS 0x02 ///< Status register
#define P_LEPTON_COMMAND_ID 0x04 ///< Command ID register
#define P_LEPTON_DATA_LENGTH 0x06 ///< Data length register
#define P_LEPTON_DATA00 0x08 ///< Data0
#define P_LEPTON_DATA01 0x0a ///< Data1
#define P_LEPTON_DATA02 0x0c ///< Data2
#define P_LEPTON_DATA03 0x0e ///< Data3
#define P_LEPTON_DATA04 0x10 ///< Data4
#define P_LEPTON_DATA05 0x12 ///< Data5
#define P_LEPTON_DATA06 0x14 ///< Data6
#define P_LEPTON_DATA07 0x16 ///< Data7
#define P_LEPTON_DATA08 0x18 ///< Data8
#define P_LEPTON_DATA09 0x1a ///< Data9
#define P_LEPTON_DATA10 0x1c ///< Data10
#define P_LEPTON_DATA11 0x1e ///< Data11
#define P_LEPTON_DATA12 0x20 ///< Data12
#define P_LEPTON_DATA13 0x22 ///< Data13
#define P_LEPTON_DATA14 0x24 ///< Data14
#define P_LEPTON_DATA15 0x26 ///< Data15
// Data model for Lepton does not match 393 convention (1 page for "important" registers,
// so just 1 register of each of the 256-words is registered
#define P_LEPTON_DATAF8 0xf8 ///< 0xf800 to 0xf8ff
#define P_LEPTON_DATAF9 0xf9 ///< 0xf900 to 0xf9ff
#define P_LEPTON_DATAFA 0xfa ///< 0xfa00 to 0xfaff
#define P_LEPTON_DATAFB 0xfb ///< 0xfb00 to 0xfbff
#define P_LEPTON_DATAFC 0xfc ///< 0xfc00 to 0xfcff
#define P_LEPTON_DATAFD 0xfd ///< 0xfd00 to 0xfdff
#define P_LEPTON_DATAFE 0xfe ///< 0xfe00 to 0xfeff
#define P_LEPTON_DATAFF 0xff ///< 0xff00 to 0xffff
// Actual register address ranges (probably, only even are used too?)
#define P_REG_LEPTON_DATAF8 0xf800 ///< 0xf800 to 0xf8ff
#define P_REG_LEPTON_DATAF9 0xf900 ///< 0xf900 to 0xf9ff
#define P_REG_LEPTON_DATAFA 0xfa00 ///< 0xfa00 to 0xfaff
#define P_REG_LEPTON_DATAFB 0xfb00 ///< 0xfb00 to 0xfbff
#define P_REG_LEPTON_DATAFC 0xfc00 ///< 0xfc00 to 0xfcff
#define P_REG_LEPTON_DATAFD 0xfd00 ///< 0xfd00 to 0xfdff
#define P_REG_LEPTON_DATAFE 0xfe00 ///< 0xfe00 to 0xfeff
#define P_REG_LEPTON_DATAFF 0xff00 ///< 0xff00 to 0xffff
typedef union {
struct {
u32 busy: 1; // [ 0] BUSY bit (should be zero before issuing commands)
u32 boot_mode: 1; // [ 1] Boot Mode (should be 1 - booted from internal ROM)
u32 boot_status: 1; // [ 2] 1 - booted, 0 - in progress
u32 rsv5: 5; // [ 7: 3] Reserved, should read zero
u32 error: 8; // [15 8] Error code
};
struct {
u32 d32:16; // [15: 0] (0) cast to u32
};
} lepton_status_t;
typedef union {
struct {
u32 type: 2; // [ 1: 0] 0 - get, 1 - set, 2 - run, 3 - invalid
u32 id: 6; // [ 7: 2] command ID
u32 module: 4; // [11: 8] module: 1-AGC, 2-SYS, 3-VID, 8-OEM, 0xe - RAD
u32 : 2; // [13:12] Reserved
u32 protection: 1; // [ 14] OEM bit, set for modules: RAD and OEM
u32 : 1; // [ 15] Reserved
};
struct {
u32 d32:16; // [15: 0] (0) cast to u32
};
} lepton_command_t;
typedef enum LEPTON_MODULES {
LEPTON_AGC = 1,
LEPTON_SYS = 2,
LEPTON_VID = 3,
LEPTON_OEM = 8,
LEPTON_RAD = 14
} lepton_modules_t;
typedef enum LEPTON_TYPES {
LEPTON_GET = 0,
LEPTON_SET = 1,
LEPTON_RUN = 2
} lepton_types_t;
// large segments - 0xf800-0xfbff, 0xfc00 -0xffff not yet supported
/**
LUT to map SENSOR_REGSxxx to internal sensor register addresses
* needed for any sensor
* For better manual mapping:
- even elements are SENSOR_REGSxxx,
- odd elements are sensor's register addresses.
* has to be at least 16-bit/entry for 16 bit addresses
* (for MT9X001 it's a 1-to-1 mapping)
*/
extern const unsigned short lepton_par2addr[];
extern const unsigned short lepton_pages[];
extern const unsigned short lepton_ahead_tab[];
int lepton_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
;
void lepton_set_device(struct device *dev);
int lepton_wait_ready (int sensor_port, ///< sensor port number (0..3)
int sa7, ///< I2C slave address
int num_retries ); ///< number of retries, 0 - forever
///< @return > 0 number of retries0 - OK, negative - error
void lepton_set_reg_nowait(int sensor_port, ///< sensor port number (0..3)
int frame, ///< frame number to apply, <0 - ASAP
lepton_modules_t cmd_module, ///< Lepton command module
int cmd_id, ///< Lepton command id
int data ); ///< data to write
#endif
......@@ -1004,6 +1004,9 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
if (frame16 >= 0) return -1; // should be ASAP
// reset sensor by applying MRST (low):
// CCAM_MRST_ON;
//FIXME: No master reset here? Should it be here regardless of debug? ****
if (debug_delays & 0xff) {
dev_dbg(g_dev_ptr,"Resetting MT9X001 sensor, port=%d\n",sensor_port);
sensio_ctl.mrst = 0;
......
......@@ -208,6 +208,7 @@
#include "multi10359.h"
#include "mt9x001.h"
#include "mt9f002.h"
#include "lepton.h"
#include "gamma_tables.h"
#include "quantization_tables.h"
//#include "latency.h"
......@@ -378,6 +379,7 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
int qperiod;
int i2cbytes;
int mux,sens;
int fpga_interface = x393_sensor_interface();
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n",sensor_port,frame16);
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
......@@ -413,14 +415,15 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
if ((mux == SENSOR_NONE) && (sens == SENSOR_NONE))
return 0; // no sensor/mux enabled on this port
//TODO NC393: turn on both sequencers why MRST is active, then i2c frame will definitely match ? Or is it already done in FPGA?
//TODO NC393: turn on both sequencers while MRST is active, then i2c frame will definitely match ? Or is it already done in FPGA?
dev_dbg(g_dev_ptr,"Restarting both command and i2c sequencers for port %d\n",sensor_port);
sequencer_stop_run_reset(sensor_port, SEQ_CMD_RESET);
sequencer_stop_run_reset(sensor_port, SEQ_CMD_RUN); // also programs status update
i2c_stop_run_reset (sensor_port, I2C_CMD_RESET);
dev_dbg(g_dev_ptr,"Setting i2c drive mode for port %d\n",sensor_port);
// dev_dbg(g_dev_ptr,"Setting i2c drive mode for port %d\n",sensor_port);
dev_info(g_dev_ptr,"Setting i2c drive mode for port %d\n",sensor_port);
i2c_drive_mode (sensor_port, SDA_DRIVE_HIGH, SDA_RELEASE);
i2c_stop_run_reset (sensor_port, I2C_CMD_RUN); // also programs status update
......@@ -453,6 +456,7 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
//mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
if (mux != SENSOR_NONE) {
if (fpga_interface == FPGA_PAR12) {
dev_dbg(g_dev_ptr,"Mux mode for port %d is %d, tryng 10359\n",sensor_port, mux);
MDP(DBGB_PADD, sensor_port,"Mux mode for port %d is %d, tryng 10359\n",sensor_port, mux)
// try multisensor here (before removing MRST)
......@@ -465,6 +469,9 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
// ************************************************************************************************
// ************************************************************************************************
// ************************************************************************************************
} else {
dev_dbg(g_dev_ptr,"Incompatible FPGA interface for 10359 on port %d\n",sensor_port);
}
} else {
dev_dbg(g_dev_ptr,"Mux mode for port %d SENSOR_NONE, skipping 10359 detection\n",sensor_port);
......@@ -473,7 +480,8 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
//if ((thispars->pars[P_SENSOR]==0) || // multisensor not detected
// ((thispars->pars[P_SENSOR] & SENSOR_MASK) == SENSOR_MT9X001)) { // or is (from DT) SENSOR_MT9X001
if ((thispars->pars[P_SENSOR]==0) && // multisensor not detected
if ((fpga_interface == FPGA_PAR12) &&
(thispars->pars[P_SENSOR]==0) && // multisensor not detected
(((sens & SENSOR_MASK) == SENSOR_MT9X001) || // and from DT it is some SENSOR_MT9*001
((sens & SENSOR_MASK) == SENSOR_MT9P006) )) { // or SENSOR_MT9P006 or friends
......@@ -491,21 +499,26 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
}
if ((thispars->pars[P_SENSOR]==0) &&
if ( (fpga_interface == FPGA_HISPI) &&
(thispars->pars[P_SENSOR]==0) &&
((sens & SENSOR_MASK) == SENSOR_MT9F002)){
dev_dbg(g_dev_ptr,"trying MT9F002, port=%d\n",sensor_port);
MDP(DBGB_PADD, sensor_port,"trying MT9F002, port=%d\n",sensor_port)
// TODO: move to sensor driver
// ************************************************************************************************
// ********************************* MT9x00x SENSOR (5MP) *****************************************
// ************************************************************************************************
mt9f002_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16);
// ************************************************************************************************
// ************************************************************************************************
// ************************************************************************************************
}
if ( (fpga_interface == FPGA_VOSPI) &&
(thispars->pars[P_SENSOR]==0) &&
((sens & SENSOR_MASK) == SENSOR_LEPTON35)){
dev_dbg(g_dev_ptr,"trying Lepton 3.5, port=%d\n",sensor_port);
dev_info(g_dev_ptr,"trying Lepton 3.5, port=%d\n",sensor_port);
MDP(DBGB_PADD, sensor_port,"trying Lepton 3.5, port=%d\n",sensor_port)
lepton_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16);
}
//setFramePar(sensor_port, thispars, P_CLK_FPGA, 200000000); // FIXME: NC393
setFramePar(sensor_port, thispars, P_CLK_FPGA, 240000000);
......@@ -1025,6 +1038,7 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
struct frameparspair_t pars_to_update[18]; // 15 needed, increase if more entries will be added
int nupdate=0;
int clearHeight;
int tile_vert = X393_TILEVERT;
dev_dbg(g_dev_ptr,"{%d} frame16=%d\n", sensor_port,frame16);
dev_dbg(g_dev_ptr,"{%d} thispars->pars[P_WOI_HEIGHT]=%lx thispars->pars[P_WOI_WIDTH]=%lx\n", sensor_port,thispars->pars[P_WOI_HEIGHT], thispars->pars[P_WOI_WIDTH]);
// if (GLOBALPARS(G_SENS_AVAIL) ) multisensor_pgm_window_common0 (sensor, thispars, prevpars, frame16);
......@@ -1043,6 +1057,9 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
case COLORMODE_COLOR:
case COLORMODE_COLOR20:
margins = COLOR_MARGINS;
break;
case COLORMODE_RAW:
tile_vert = 1;
}
// flips changed?
if (FRAMEPAR_MODIFIED(P_FLIPH)) {
......@@ -1125,9 +1142,9 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
}
} else {
if ((!oversize ) && (height > sensor_height)) height=sensor_height;
height= ((height/dv)/X393_TILEVERT) * X393_TILEVERT; // divided by dv (before multisensor options)
height= ((height/dv)/tile_vert) * tile_vert; // divided by dv (before multisensor options)
// suppose minimal height refers to decimated output
while (height < sensor->minHeight) height+=X393_TILEVERT;
while (height < sensor->minHeight) height+=tile_vert;
if (unlikely(thispars->pars[P_SENSOR_PIXV] != height+(2 * margins)))
SETFRAMEPARS_SET(P_SENSOR_PIXV, height+(2 * margins)); ///full height for the sensor (after decimation), including margins
height*=dv;
......
......@@ -92,10 +92,12 @@ long long get_frame_pos(unsigned int chn, unsigned int pos);
#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 name_mt9p006 "mt9p006" // Get name from DT (together with port mask)
#define name_mt9f002 "mt9f002" // Get name from DT (together with port mask)
// never used?
#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 name_mt9p006 "mt9p006" // Get name from DT (together with port mask)
#define name_mt9f002 "mt9f002" // Get name from DT (together with port mask)
#define name_lepton35 "lepton35" // 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)
......
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