Commit 804b8db1 authored by Andrey Filippov's avatar Andrey Filippov

added detect_sensor module

parent 4f108db9
...@@ -32,3 +32,4 @@ obj-$(CONFIG_ELPHEL393) += imu_log393.o ...@@ -32,3 +32,4 @@ obj-$(CONFIG_ELPHEL393) += imu_log393.o
obj-$(CONFIG_ELPHEL393) += cxi2c.o obj-$(CONFIG_ELPHEL393) += cxi2c.o
obj-$(CONFIG_ELPHEL393) += x393_videomem.o obj-$(CONFIG_ELPHEL393) += x393_videomem.o
obj-$(CONFIG_ELPHEL393) += detect_sensors.o
\ No newline at end of file
/***************************************************************************//**
* @file detect_sensors.c
* @brief Determine sensor boards attached to each of the ports. Use
* Device Tree, sysfs to set sensor types per port. Add autodetection
* (using pullup/pull downs) later
* @copyright Copyright 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/>.
*******************************************************************************/
//#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/string.h>
//#include <asm/outercache.h> // TODO: Implement cache operations for the membridge !!!!
//#include <asm/cacheflush.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include "x393.h"
//#include "x393_detect_sensors.h"
#include <elphel/driver_numbers.h>
#include <elphel/c313a.h>
#include "mt9x001.h"
#include "multi10359.h"
#include "detect_sensors.h"
#define DETECT_SENSORS_MODULE_DESCRIPTION "Detect sensor type(s) attached to each of the ports"
#define DETECT_SENSORS_DRIVER_NAME "detect_sensors"
#define OF_PREFIX_NAME "elphel393-detect_sensors"
struct sensor_port_config_t
{
u32 mux; ///< sensor multiplexer, currently 0 (SENSOR_DETECT, SENSOR_MUX_10359 or SENSOR_NONE)
u32 sensor[MAX_SENSORS]; ///< Without mux only [0] is used, with 10359 - 0..2 are used (i2c addressing is shifted so 0 is broadcast)
};
static struct sensor_port_config_t sensorPortConfig[] = {
{.mux=SENSOR_NONE,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}},
{.mux=SENSOR_NONE,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}},
{.mux=SENSOR_NONE,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}},
{.mux=SENSOR_NONE,.sensor={SENSOR_NONE,SENSOR_NONE,SENSOR_NONE,SENSOR_NONE}}
};
//struct sensor_port_config_t *pSensorPortConfig;
static const struct of_device_id elphel393_detect_sensors_of_match[];
static struct device *g_dev_ptr; ///< Global pointer to basic device structure. This pointer is used in debugfs output functions
struct sensor_name_t {
const char * name;
u32 code;
int type; ///< +1 - applicable to sensors, +2 - applicable to multiplexers
};
const struct sensor_name_t sensor_names[] ={
{.name="detect", .type=3, .code = 0}, // to be automatically detected
{.name="none", .type=3, .code = SENSOR_NONE}, // no device attached
{.name="mux10359", .type=2, .code = SENSOR_MUX_10359}, // no device attached
{.name="zr32112", .type=1, .code = SENSOR_ZR32112}, // Zoran ZR32112
{.name="zr32212", .type=1, .code = SENSOR_ZR32212}, // Zoran ZR32212
{.name="kac1310", .type=1, .code = SENSOR_KAC1310}, // Kodak KAC1310
{.name="kac5000", .type=1, .code = SENSOR_KAC5000}, // Kodak KAC5000
{.name="mi1300", .type=1, .code = SENSOR_MI1300}, // Micron MI1300
{.name="mt9m001", .type=1, .code = SENSOR_MT9M001}, // MT9M001
{.name="mt9d001", .type=1, .code = SENSOR_MT9D001}, // MT9D001
{.name="mt9t001", .type=1, .code = SENSOR_MT9T001}, // MT9T001
{.name="mt9p006", .type=1, .code = SENSOR_MT9P006}, // MT9P006
{.name="mt9f002", .type=1, .code = SENSOR_MT9F002}, // MT9F002
{.name="ibis51300", .type=1, .code = SENSOR_IBIS51300}, // FillFactory IBIS51300
{.name="kai11002", .type=1, .code = SENSOR_KAI11000}, // Kodak KAI11002
{.name=NULL, .type=0, .code = 0} // end of list
};
//#define DETECT_SENSOR 1 ///< Include sensors, May be OR-ed when looking for sensor/multiplexer code/name
//#define DETECT_MUX 2 ///< Include multiplexers, May be OR-ed when looking for sensor/multiplexer code/name
/** Get sensor/multiplexer code (SENSOR_*) by name */
int get_code_by_name(const char * name, ///< sensor name
int type) ///< valid type [DETECT_SENSOR]|[DETECT_MUX]
///< @return sensor code or -EINVAL for invalid name
{
int i;
if (name) for (i = 0; sensor_names[i].name; i++){
if ((sensor_names[i].type & type) && (!strncmp(sensor_names[i].name,name,80))){
return sensor_names[i].code;
}
}
return -EINVAL;
}
/** Get sensor/multiplexer name (SENSOR_*) by code */
const char * get_name_by_code(int code, ///< sensor code
int type) ///< valid type [DETECT_SENSOR]|[DETECT_MUX]
///< @return sensor name or NULL for invalid code
{
int i;
for (i = 0; sensor_names[i].name; i++){
if ((sensor_names[i].type & type) && (sensor_names[i].code == code)){
return sensor_names[i].name;
}
}
return NULL;
}
/** Get sensor port multiplexer type */
int get_detected_mux_code(int port) ///< Sensor port number (0..3)
///< @return port multiplexer code (SENSOR_DETECT, SENSOR_MUX_10359 or SENSOR_NONE)
{
return sensorPortConfig[port & 3].mux;
}
/** Get sensor type */
int get_detected_sensor_code(int port, ///< Sensor port number (0..3)
int sub_chn) ///< Sensor subchannel (0..3)
///< @return sensor code (SENSOR_DETECT, SENSOR_NONE, or SENSOR_*)
{
return sensorPortConfig[port&3].sensor[sub_chn & 3];
}
/** Set sensor port multiplexer type */
int set_detected_mux_code(int port, ///< Sensor port number (0..3)
int mux_type) ///< Sensor multiplexer type (SENSOR_DETECT, SENSOR_MUX_10359 or SENSOR_NONE)
///< @return 0 - OK, -EINVAL if mux_type is invalid
{
if (mux_type < 0)
return mux_type;
if (!get_name_by_code(mux_type, DETECT_MUX)){
pr_err("%s: Invalid port multiplexer code for port %d: 0x%x\n", __func__, port, mux_type);
return -EINVAL;
}
sensorPortConfig[port & 3].mux = mux_type;
return 0;
}
/** Set sensor port multiplexer type */
int set_detected_sensor_code(int port, ///< Sensor port number (0..3)
int sub_chn, ///< Sensor subchannel (0..3)
int sens_type) ///< Sensor code (SENSOR_DETECT, SENSOR_NONE, or SENSOR_*)
///< @return 0 - OK, -EINVAL if mux_type is invalid)
{
if (sens_type < 0)
return sens_type;
if (!get_name_by_code(sens_type, DETECT_SENSOR)){
pr_err("%s: Invalid sensor code for port %d, subchannel %d: 0x%x\n", __func__, port, sens_type);
return -EINVAL;
}
sensorPortConfig[port & 3].sensor[sub_chn] = sens_type;
return 0;
}
// SysFS interface to read/modify video memory map
#define SYSFS_PERMISSIONS 0644 /* default permissions for sysfs files */
#define SYSFS_READONLY 0444
#define SYSFS_WRITEONLY 0222
/** Sysfs helper function - get channel number from the last character of the attribute name*/
static int get_channel_from_name(struct device_attribute *attr) ///< Linux kernel interface for exporting device attributes
///< @return channel number
{
int reg = 0;
sscanf(attr->attr.name + (strlen(attr->attr.name)-1), "%du", &reg);
return reg;
}
/** Sysfs helper function - get channel and sub-channel numbers from the last 2 characters of the attribute name*/
static int get_channel_sub_from_name(struct device_attribute *attr) ///< Linux kernel interface for exporting device attributes
///< @return channel * 16 + sub_channel
{
int reg = 0;
sscanf(attr->attr.name + (strlen(attr->attr.name)-2), "%du", &reg);
reg += (reg/10) * 6;
return reg;
}
static ssize_t show_port_mux(struct device *dev, struct device_attribute *attr, char *buf)
{
int i;
const char * name = get_name_by_code(sensorPortConfig[get_channel_from_name(attr)].mux, DETECT_MUX);
if (name) return sprintf(buf,"%s\n", name);
// Should never get here
return sprintf(buf,"0x%x\n", sensorPortConfig[get_channel_from_name(attr)].mux);
}
static ssize_t show_sensor(struct device *dev, struct device_attribute *attr, char *buf)
{
int i;
int psch = get_channel_sub_from_name(attr);
int port = (psch>>4) &3;
int sub_chn = psch &3;
const char * name = get_name_by_code(sensorPortConfig[port].sensor[sub_chn], DETECT_SENSOR);
if (name) return sprintf(buf,"%s\n", name);
// Should never get here
return sprintf(buf,"0x%x\n", sensorPortConfig[(psch>>4) & 3].sensor[psch & 3]);
}
static ssize_t store_port_mux(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
size_t len;
char name[80];
int port = get_channel_from_name(attr);
int i, code, rslt;
if (sscanf(buf, "%79s", name, &len)){
if ((rslt = set_detected_mux_code( port, get_code_by_name(name, DETECT_MUX)))<0)
return rslt;
}
return count;
}
static ssize_t store_sensor(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
size_t len;
char name[80];
int psch = get_channel_sub_from_name(attr);
int port = (psch>>4) &3;
int sub_chn = psch &3;
int i, rslt;
if (sscanf(buf, "%79s", name, &len)){
if ((rslt = set_detected_sensor_code(port, sub_chn, get_code_by_name(name, DETECT_SENSOR)))<0)
return rslt;
}
return count;
}
static DEVICE_ATTR(port_mux0, SYSFS_PERMISSIONS, show_port_mux, store_port_mux);
static DEVICE_ATTR(port_mux1, SYSFS_PERMISSIONS, show_port_mux, store_port_mux);
static DEVICE_ATTR(port_mux2, SYSFS_PERMISSIONS, show_port_mux, store_port_mux);
static DEVICE_ATTR(port_mux3, SYSFS_PERMISSIONS, show_port_mux, store_port_mux);
static DEVICE_ATTR(sensor00, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor01, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor02, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor03, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor10, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor11, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor12, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor13, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor20, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor21, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor22, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor23, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor30, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor31, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor32, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static DEVICE_ATTR(sensor33, SYSFS_PERMISSIONS, show_sensor, store_sensor);
static struct attribute *root_dev_attrs[] = {
&dev_attr_port_mux0.attr,
&dev_attr_port_mux1.attr,
&dev_attr_port_mux2.attr,
&dev_attr_port_mux3.attr,
&dev_attr_sensor00.attr,
&dev_attr_sensor01.attr,
&dev_attr_sensor02.attr,
&dev_attr_sensor03.attr,
&dev_attr_sensor10.attr,
&dev_attr_sensor11.attr,
&dev_attr_sensor12.attr,
&dev_attr_sensor13.attr,
&dev_attr_sensor20.attr,
&dev_attr_sensor21.attr,
&dev_attr_sensor22.attr,
&dev_attr_sensor23.attr,
&dev_attr_sensor30.attr,
&dev_attr_sensor31.attr,
&dev_attr_sensor32.attr,
&dev_attr_sensor33.attr,
NULL
};
static const struct attribute_group dev_attr_root_group = {
.attrs = root_dev_attrs,
.name = NULL,
};
static int elphel393_detect_sensors_sysfs_register(struct platform_device *pdev)
{
int retval=0;
struct device *dev = &pdev->dev;
if (&dev->kobj) {
if (((retval = sysfs_create_group(&dev->kobj, &dev_attr_root_group)))<0) return retval;
}
return retval;
}
/** Initialize this driver from the Device Tree.
* Read per-port multiplexers and sensors. */
static void detect_sensors_init_of(struct platform_device *pdev) ///< Platform device structure for this driver
///< @return 0 on success, or negative error.
{
const char * config_string;
// struct x393_i2c_device_list * dl;
char names[4][80];
// int rslt;
// int num_devs, nd, ni, sa7, num_addr, num_data, khz;
struct device_node *node = pdev->dev.of_node;
// struct device_attribute *new_attr;
// struct device *dev =&pdev->dev;
int num_ports, port, num_sub, sub_chn;
if (node) {
if (num_ports > SENSOR_PORTS)
num_ports = SENSOR_PORTS;
config_string = of_get_property(node, OF_PREFIX_NAME",ports", NULL); // &len);
num_ports = sscanf(config_string,"%79s %79s %79s %79s", names[0], names[1], names[2], names[3]);
for (port = 0; port < num_ports; port++){
set_detected_mux_code(port, get_code_by_name(names[sub_chn], DETECT_MUX));
}
num_ports = of_property_count_strings(node,OF_PREFIX_NAME",sensors");
for (port = 0; port < num_ports; port++){
if (of_property_read_string_index(node, OF_PREFIX_NAME",sensors", port, &config_string)) {
pr_err("%s: No data for selected port\n", __func__);
BUG();
}
num_sub = sscanf(config_string,"%79s %79s %79s %79s", names[0], names[1], names[2], names[3]);
for (sub_chn = 0; sub_chn < num_sub; sub_chn++){
set_detected_sensor_code(port, sub_chn, get_code_by_name(names[sub_chn], DETECT_SENSOR));
}
}
}
}
static int detect_sensors_probe(struct platform_device *pdev)
{
unsigned int irq;
int res;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
const __be32 *bufsize_be;
struct device_node *node;
// pSensorPortConfig = sensorPortConfig;
elphel393_detect_sensors_sysfs_register(pdev);
match = of_match_device(elphel393_detect_sensors_of_match, dev);
if (!match)
pr_err("Detect sensors ERROR: No device tree for '%s' node found\n",elphel393_detect_sensors_of_match[0].compatible);
return -EINVAL;
detect_sensors_init_of(pdev);
// dev_dbg(dev, "Registering character device with name "DETECT_SENSORS_DRIVER_NAME);
// res = register_chrdev(DETECT_SENSORS_MAJOR, DETECT_SENSORS_DRIVER_NAME, &detect_sensors_fops);
// if(res < 0) {
// dev_err(dev, "\nlogger_init: couldn't get a major number %d.\n ",DETECT_SENSORS_MAJOR);
// return res;
// }
g_dev_ptr = dev; // for debugfs
return 0;
}
/** IMU/GPS logger driver remove function */
static int detect_sensors_remove(struct platform_device *pdev) ///< [in] pointer to @e platform_device structure
///< @return always 0
{
// unregister_chrdev(DETECT_SENSORS_MAJOR, DETECT_SENSORS_DRIVER_NAME);
return 0;
}
static const struct of_device_id elphel393_detect_sensors_of_match[] = {
{ .compatible = "elphel,elphel393-detect_sensors-1.00" },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, elphel393_detect_sensors_of_match);
static struct platform_driver elphel393_detect_sensors = {
.probe = detect_sensors_probe,
.remove = detect_sensors_remove,
.driver = {
.name = DETECT_SENSORS_DRIVER_NAME,
.of_match_table = elphel393_detect_sensors_of_match,
},
};
module_platform_driver(elphel393_detect_sensors);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(DETECT_SENSORS_MODULE_DESCRIPTION);
/***************************************************************************//**
* @file detect_sensors.h
* @brief Determine sensor boards attached to each of the ports. Use
* Device Tree, sysfs to set sensor types per port. Add autodetection
* (using pullup/pull downs) later
* @copyright Copyright 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 DETECT_SENSOR 1 ///< Include sensors, May be OR-ed when looking for sensor/multiplexer code/name
#define DETECT_MUX 2 ///< Include multiplexers, May be OR-ed when looking for sensor/multiplexer code/name
int get_code_by_name(const char * name, int type);
const char * get_name_by_code(int code, int type);
int get_detected_mux_code(int port);
int get_detected_sensor_code(int port, int sub_chn);
int set_detected_mux_code(int port, int mux_type);
int set_detected_sensor_code(int port, int sub_chn, int mux_type);
...@@ -210,10 +210,17 @@ ...@@ -210,10 +210,17 @@
#include "pgm_functions.h" #include "pgm_functions.h"
#include "jpeghead.h" // to program FPGA Huffman tables #include "jpeghead.h" // to program FPGA Huffman tables
#include "x393.h" #include "x393.h"
#include "legacy_defines.h" // temporarily // #include "legacy_defines.h" // temporarily
#include "sensor_i2c.h" #include "sensor_i2c.h"
#include "x393_videomem.h" #include "x393_videomem.h"
#define COLOR_MARGINS 2 // add this many pixels each side #define COLOR_MARGINS 2 // add this many pixels each side
#define X313_TIMESTAMPLEN 28 // pixels used for timestamp (in linescan mode added after the line)
#define X393_TILEHOR 16
#define X393_TILEVERT 16
#define X393_MAXWIDTH 65536 // 4096 // multiple of 128
#define X393_MAXHEIGHT 65536 // 16384 // multiple of 16 - unsafe - not enough room for black level subtraction
#define X393_MAXHEIGHT_SAFE 65536 // 4096 // multiple of 16 OK for black level subtraction TODO: disable black level if unsafe
/** /**
* @brief optional debug output macros * @brief optional debug output macros
...@@ -356,7 +363,10 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number ( ...@@ -356,7 +363,10 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
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) 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)
// no other initializations, just the sensor-related stuff (starting with lowest sensor clock) // no other initializations, just the sensor-related stuff (starting with lowest sensor clock)
// stop hardware i2c controller, so it will not get stuck when waiting for !busy // stop hardware i2c controller, so it will not get stuck when waiting for !busy
#ifndef NC353
// NC393 - nothing to do here - use a separate module for sensor setup: DT, sysfs, something else (add pin pullup/down)
return 0;
#else
// NOTE: disabling interrupts here !!! // NOTE: disabling interrupts here !!!
camera_interrupts (0); camera_interrupts (0);
...@@ -376,13 +386,11 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number ( ...@@ -376,13 +386,11 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
// Need to set slow clock // Need to set slow clock
// f1=imageParamsR[P_CLK_SENSOR]=20000000; setClockFreq(1, imageParamsR[P_CLK_SENSOR]); X3X3_RSTSENSDCM; // f1=imageParamsR[P_CLK_SENSOR]=20000000; setClockFreq(1, imageParamsR[P_CLK_SENSOR]); X3X3_RSTSENSDCM;
#ifdef NC353
was_sensor_freq=getClockFreq(1); // using clock driver data, not thispars was_sensor_freq=getClockFreq(1); // using clock driver data, not thispars
setFramePar(sensor_port, thispars, P_CLK_FPGA, getClockFreq(0)); // just in case - read the actual fpga clock frequency and store it (no actions) setFramePar(sensor_port, thispars, P_CLK_FPGA, getClockFreq(0)); // just in case - read the actual fpga clock frequency and store it (no actions)
setFramePar(sensor_port, thispars, P_CLK_SENSOR, 48000000); setFramePar(sensor_port, thispars, P_CLK_SENSOR, 48000000);
setClockFreq(1, thispars->pars[P_CLK_SENSOR]); setClockFreq(1, thispars->pars[P_CLK_SENSOR]);
printk("\nsensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]); printk("\nsensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]);
#endif
udelay (100);// 0.0001 sec to stabilize clocks udelay (100);// 0.0001 sec to stabilize clocks
X3X3_RSTSENSDCM; // FPGA DCM can fail after clock change, needs to be reset X3X3_RSTSENSDCM; // FPGA DCM can fail after clock change, needs to be reset
X3X3_SENSDCM_CLK2X_RESET; // reset pclk2x DCM also X3X3_SENSDCM_CLK2X_RESET; // reset pclk2x DCM also
...@@ -402,12 +410,11 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number ( ...@@ -402,12 +410,11 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
printk("removing MRST from the sensor\n"); printk("removing MRST from the sensor\n");
CCAM_MRST_OFF; CCAM_MRST_OFF;
} }
#ifdef CONFIG_ETRAX_ELPHEL_MT9X001
if (thispars->pars[P_SENSOR]==0) { if (thispars->pars[P_SENSOR]==0) {
mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
printk("trying MT9P001\n"); printk("trying MT9P001\n");
} }
#endif
// temporary - disabling old sensors // temporary - disabling old sensors
#define ENABLE_OLD_SENSORS 1 #define ENABLE_OLD_SENSORS 1
#ifdef ENABLE_OLD_SENSORS #ifdef ENABLE_OLD_SENSORS
...@@ -501,8 +508,10 @@ printk ("Inverted MRST\n"); ...@@ -501,8 +508,10 @@ printk ("Inverted MRST\n");
// NOTE: sensor detected - enabling camera interrupts here (actual interrupts will start later) // NOTE: sensor detected - enabling camera interrupts here (actual interrupts will start later)
// Here interrupts are disabled - with camera_interrupts (0) earlier in this function) // Here interrupts are disabled - with camera_interrupts (0) earlier in this function)
camera_interrupts (1); camera_interrupts (1);
return 0; return 0;
#endif
} }
...@@ -884,9 +893,9 @@ int pgm_window_common (int sensor_port, ///< sensor port number ( ...@@ -884,9 +893,9 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
if ((!oversize) && (width > sensor_width)) width= sensor_width; if ((!oversize) && (width > sensor_width)) width= sensor_width;
// make width to be multiple of the compressor tile (before adding margins of 4 pixels) // make width to be multiple of the compressor tile (before adding margins of 4 pixels)
width= (((width/dh) + timestamp_len)/X313_TILEHOR)*X313_TILEHOR-timestamp_len; // divided by dh width= (((width/dh) + timestamp_len)/X393_TILEHOR)*X393_TILEHOR-timestamp_len; // divided by dh
// suppose minimal width refers to decimated output // suppose minimal width refers to decimated output
while (width < sensor->minWidth) width+=X313_TILEHOR; while (width < sensor->minWidth) width+=X393_TILEHOR;
if (unlikely(thispars->pars[P_ACTUAL_WIDTH] != (width+timestamp_len))) { if (unlikely(thispars->pars[P_ACTUAL_WIDTH] != (width+timestamp_len))) {
SETFRAMEPARS_SET(P_ACTUAL_WIDTH, width+timestamp_len); ///full width for the compressor, including timestamp, but excluding margins SETFRAMEPARS_SET(P_ACTUAL_WIDTH, width+timestamp_len); ///full width for the compressor, including timestamp, but excluding margins
} }
...@@ -902,7 +911,7 @@ int pgm_window_common (int sensor_port, ///< sensor port number ( ...@@ -902,7 +911,7 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
if(pfh > 0) { if(pfh > 0) {
if (pfh < sensor->minHeight) pfh = sensor->minHeight; if (pfh < sensor->minHeight) pfh = sensor->minHeight;
if (pfh & 1) pfh++; if (pfh & 1) pfh++;
if (height > X313_MAXHEIGHT*dv) height=X313_MAXHEIGHT*dv; if (height > X393_MAXHEIGHT*dv) height=X393_MAXHEIGHT*dv;
pf_stripes = height / (pfh * dv); pf_stripes = height / (pfh * dv);
if(pf_stripes < 1) pf_stripes = 1; if(pf_stripes < 1) pf_stripes = 1;
if (unlikely(thispars->pars[P_SENSOR_PIXV] != pfh)) { if (unlikely(thispars->pars[P_SENSOR_PIXV] != pfh)) {
...@@ -911,9 +920,9 @@ int pgm_window_common (int sensor_port, ///< sensor port number ( ...@@ -911,9 +920,9 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
} }
} else { } else {
if ((!oversize ) && (height > sensor_height)) height=sensor_height; if ((!oversize ) && (height > sensor_height)) height=sensor_height;
height= ((height/dv)/X313_TILEVERT) * X313_TILEVERT; // divided by dv (before multisensor options) height= ((height/dv)/X393_TILEVERT) * X393_TILEVERT; // divided by dv (before multisensor options)
// suppose minimal height refers to decimated output // suppose minimal height refers to decimated output
while (height < sensor->minHeight) height+=X313_TILEVERT; while (height < sensor->minHeight) height+=X393_TILEVERT;
if (unlikely(thispars->pars[P_SENSOR_PIXV] != height+(2 * COLOR_MARGINS))) if (unlikely(thispars->pars[P_SENSOR_PIXV] != height+(2 * COLOR_MARGINS)))
SETFRAMEPARS_SET(P_SENSOR_PIXV, height+(2 * COLOR_MARGINS)); ///full height for the sensor (after decimation), including margins SETFRAMEPARS_SET(P_SENSOR_PIXV, height+(2 * COLOR_MARGINS)); ///full height for the sensor (after decimation), including margins
height*=dv; height*=dv;
......
//pgm_functions.h /***************************************************************************//**
///extern struct sensorproc_t * sensorproc; * @file pgm_functions.h
* @brief Sensor/FPGA programming functions, called from IRQ/tasklet in
* response to the parameter changes
* @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/>.
*******************************************************************************/
#include "sensor_i2c.h" #include "sensor_i2c.h"
......
...@@ -497,9 +497,9 @@ static int videomem_probe(struct platform_device *pdev) ...@@ -497,9 +497,9 @@ static int videomem_probe(struct platform_device *pdev)
dev_dbg(dev, "Registering character device with name "VIDEOMEM_DRIVER_NAME); dev_dbg(dev, "Registering character device with name "VIDEOMEM_DRIVER_NAME);
res = register_chrdev(LOGGER_MAJOR, VIDEOMEM_DRIVER_NAME, &videomem_fops); res = register_chrdev(VIDEOMEM_MAJOR, VIDEOMEM_DRIVER_NAME, &videomem_fops);
if(res < 0) { if(res < 0) {
dev_err(dev, "\nlogger_init: couldn't get a major number %d.\n ",VIDEOMEM_MAJOR); dev_err(dev, "\videomem_probe: couldn't get a major number %d.\n ",VIDEOMEM_MAJOR);
return res; return res;
} }
// Setup interrupt // Setup interrupt
...@@ -513,13 +513,13 @@ static int videomem_probe(struct platform_device *pdev) ...@@ -513,13 +513,13 @@ static int videomem_probe(struct platform_device *pdev)
dev_err(dev, "can not allocate interrupts for %s\n","membridge_irq"); dev_err(dev, "can not allocate interrupts for %s\n","membridge_irq");
return -EBUSY; return -EBUSY;
} }
init_waitqueue_head(&videomem_wait_queue); // wait queue for logger init_waitqueue_head(&videomem_wait_queue); // wait queue for video memory driver
g_dev_ptr = dev; // for debugfs g_dev_ptr = dev; // for debugfs
return 0; return 0;
} }
/** IMU/GPS logger driver remove function */ /** Video memory driver remove function */
static int videomem_remove(struct platform_device *pdev) ///< [in] pointer to @e platform_device structure static int videomem_remove(struct platform_device *pdev) ///< [in] pointer to @e platform_device structure
///< @return always 0 ///< @return always 0
{ {
......
...@@ -224,15 +224,22 @@ ...@@ -224,15 +224,22 @@
// leave it here - may be used in user applications // leave it here - may be used in user applications
#define SENSOR_MASK 0xfc ///< Mask to apply for distinguish between different sensor groups (of similar devices) #define SENSOR_MASK 0xfc ///< Mask to apply for distinguish between different sensor groups (of similar devices)
#define SENSOR_DETECT 0x00 ///< Unknown sensor, try to autodetect
#define SENSOR_ZR32112 0x04 ///< Zoran ZR32112 #define SENSOR_ZR32112 0x04 ///< Zoran ZR32112
#define SENSOR_ZR32212 0x08 ///< Zoran ZR32212 #define SENSOR_ZR32212 0x08 ///< Zoran ZR32212
#define SENSOR_KAC1310 0x20 ///< Kodak KAC1310 #define SENSOR_KAC1310 0x20 ///< Kodak KAC1310
#define SENSOR_KAC5000 0x24 ///< Kodak KAC5000 #define SENSOR_KAC5000 0x24 ///< Kodak KAC5000
#define SENSOR_MI1300 0x30 ///< Micron MI1300 #define SENSOR_MI1300 0x30 ///< Micron MI1300
#define SENSOR_MT9X001 0x30 ///< Micron: MT9M001 - 31, MT9D001 - 32, MT9T001 - 33, MT9P001 - 34 #define SENSOR_MT9X001 0x30 ///< Micron: MT9M001 - 31, MT9D001 - 32, MT9T001 - 33, MT9P001 - 34
#define SENSOR_MT9Y001 0x34 ///< Micron/Aptina/Onsemi MT9P001 - 34 #define SENSOR_MT9M001 0x31 ///< MT9M001
#define SENSOR_MT9D001 0x32 ///< MT9D001
#define SENSOR_MT9T001 0x33 ///< MT9T001
#define SENSOR_MT9P006 0x34 ///< MT9P006
#define SENSOR_MT9F002 0x38 ///< MT9F002
//#define SENSOR_MT9Y001 0x34 ///< Micron/Aptina/Onsemi MT9P001 - 34
#define SENSOR_IBIS51300 0x40 ///< FillFactory IBIS51300 #define SENSOR_IBIS51300 0x40 ///< FillFactory IBIS51300
#define SENSOR_KAI11000 0x80 ///< Kodak KAI11002 #define SENSOR_KAI11000 0x80 ///< Kodak KAI11002
#define SENSOR_MUX_10359 0xe0 ///< Sensor multiplexer 10359
#define SENSOR_NONE 0xfc ///< No sensor present #define SENSOR_NONE 0xfc ///< No sensor present
// sensor sizes: // sensor sizes:
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define IMAGEACQ_MAJOR 140 #define IMAGEACQ_MAJOR 140
#define LOGGER_MAJOR 141 #define LOGGER_MAJOR 141
#define VIDEOMEM_MAJOR 142 // implement raw access to memory and/or 16-bit image buffers over membridge interface #define VIDEOMEM_MAJOR 142 // implement raw access to memory and/or 16-bit image buffers over membridge interface
#define DETECT_SENSORS_MAJOR 143 // Maybe not needed?
/// MINORS /// MINORS
......
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