Commit 37a49a7a authored by Mikhail Karpenko's avatar Mikhail Karpenko

WIP: start adding interrupt handlers

This commit should not compile and was made just to save current state.
framepars and sensor_common were converted to platform dirver, some file
headers were updated and ad-hoc updates to doxygen comments were
introduced.
parent 2b37bcdf
......@@ -8,7 +8,7 @@ obj-$(CONFIG_ELPHELDRVONMICROZED) += elphel393-mem.o
obj-$(CONFIG_ELPHEL393_INIT) += elphel393-init.o
obj-$(CONFIG_ELPHEL393) += framepars.o
obj-$(CONFIG_ELPHEL393) += sensor_common.o
obj-$(CONFIG_ELPHEL393) += sensor_common.o x393.o
obj-$(CONFIG_ELPHEL393) += quantization_tables.o
obj-$(CONFIG_ELPHEL393) += circbuf.o jpeghead.o
......@@ -18,4 +18,4 @@ obj-$(CONFIG_ELPHEL393) += circbuf.o jpeghead.o
#obj-$(CONFIG_ELPHEL393_EXTERNAL) += fpars.o
#obj-$(CONFIG_ELPHEL393_EXTERNAL) += sc.o
#obj-$(CONFIG_ELPHEL393_EXTERNAL) += cbuf.o
#obj-$(CONFIG_ELPHEL393_EXTERNAL) += circbuf.o jpeghead.o quantization_tables.o
#obj-$(CONFIG_ELPHEL393_EXTERNAL) += circbuf.o jpeghead.o quantization_tables.o
\ No newline at end of file
/*!***************************************************************************
*! FILE NAME : circbuf.c
*! DESCRIPTION: drivers to manipulate large circular buffer that holds compressed
*! images/video. Buffer frame data is filled in by the FPGA, frame pointers and
*! essential frames metadata filled during servicing of the interruptsl
*! This code is based on the code from cxdma.c
*! TODO: Add buffer reset, JPEG header generation here
*!
*! Copyright (C) 2002-2007 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/>.
*! -----------------------------------------------------------------------------**
*! $Log: circbuf.c,v $
*! Revision 1.3 2010/08/08 21:14:04 elphel
*! 8.0.8.38
*!
*! Revision 1.2 2008/11/28 08:17:09 elphel
*! keeping Doxygen a little happier
*!
*! Revision 1.1.1.1 2008/11/27 20:04:00 elphel
*!
*!
*! Revision 1.20 2008/11/20 07:06:24 elphel
*! started more poll options
*!
*! Revision 1.19 2008/11/03 20:51:49 elphel
*! minor bug fix
*!
*! Revision 1.18 2008/10/29 04:18:28 elphel
*! v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
*!
*! Revision 1.17 2008/10/25 19:59:48 elphel
*! added lseek() calls to enable/disable daemons at events (compressed frame available, any frame available, histogram-Y and histograms-C available)
*!
*! Revision 1.16 2008/10/23 08:01:30 elphel
*! comments
*!
*! Revision 1.15 2008/10/19 06:50:03 elphel
*! removed couple # if 0
*!
*! Revision 1.14 2008/10/13 16:55:53 elphel
*! removed (some) obsolete P_* parameters, renamed CIRCLSEEK to LSEEK_CIRC constants (same as other similar)
*!
*! Revision 1.13 2008/10/12 16:46:22 elphel
*! snapshot
*!
*! Revision 1.12 2008/10/06 08:31:08 elphel
*! snapshot, first images
*!
*! Revision 1.11 2008/09/22 22:55:47 elphel
*! snapshot
*!
*! Revision 1.10 2008/09/20 00:29:49 elphel
*! moved driver major/minor numbers to a single file - include/asm-cris/elphel/driver_numbers.h
*!
*! Revision 1.9 2008/09/12 20:40:11 elphel
*! snapshot
*!
*! Revision 1.8 2008/09/12 00:23:58 elphel
*! removed cc353.c, cc353.h
*!
*! Revision 1.7 2008/09/11 01:05:29 elphel
*! snapshot
*!
*! Revision 1.6 2008/09/07 19:48:08 elphel
*! snapshot
*!
*! Revision 1.5 2008/09/05 23:20:26 elphel
*! just a snapshot
*!
*! Revision 1.4 2008/05/26 23:32:59 elphel
*! Added driver to handle multi-frame parameters
*!
*! Revision 1.3 2008/05/24 05:31:02 elphel
*! removed seek to current hardware write pointer after opening file, so now ftp-ing circbuf file works correctly
*!
*! Revision 1.2 2008/05/16 06:06:27 elphel
*! adjusting drivers to the fpga code (03533020)
*!
*! Revision 1.10 2008/04/11 23:16:51 elphel
*! removed unneeded local_irq_disable() after local_irq_save_flags()
*!
*! Revision 1.8 2007/12/03 08:28:46 elphel
*! Multiple changes, mostly cleanup
*!
*! Revision 1.7 2007/11/16 08:56:19 elphel
*! Added support for 2 additional commands to check circbuf usage
*!
*! Revision 1.6 2007/11/05 06:08:25 elphel
*! fixed "first/second" bug introduced while fixing the previous one
*!
*! Revision 1.5 2007/11/05 01:40:51 elphel
*! fixed wrong count of frames available, "second" frame
*!
*! Revision 1.4 2007/11/04 05:46:06 elphel
*! removed debug, rearranged code to avoid a warning
*!
*! Revision 1.3 2007/11/01 18:59:37 elphel
*! debugging mmap/caching problems
*!
*! Revision 1.2 2007/10/27 00:55:32 elphel
*! untested revision - need to go
*!
*! Revision 1.1.1.1 2007/10/02 23:54:58 elphel
*! This is a fresh tree based on elphel353-2.10
*!
*! Revision 1.6 2007/10/02 23:54:58 elphel
*! LSEEK_CIRC_LAST will now return just write pointer, not an error if there are no frames yet available. Moving to previous will still generate error.
*!
*! Revision 1.5 2007/10/02 22:29:38 elphel
*! made that only 0,SEEK_END can move beyond circbuf, fro SEEK_CUR and SEET_SET it will roll over to 0
*!
*! Revision 1.4 2007/10/02 19:35:15 elphel
*! minor circbuf interface changes, bug fixes
*!
*! Revision 1.3 2007/09/30 07:07:08 elphel
*! minor bug fix, disabled debug output
*!
*! Revision 1.2 2007/09/30 03:19:56 elphel
*! Cleanup, fixed broken acquisition of individual JPEG images into circbuf (in mode 7)
*!
*! Revision 1.1 2007/09/29 18:33:29 elphel
*! Split cxdma.c - /dev/circbuf is now in a separate circbuf.c file. New device driver does not support ioctl, so some curernt applications are updated to use other drivers to control the camera
*!
*/
/****************** INCLUDE FILES SECTION ***********************************/
/** @file circbuf.c
*
* @brief drivers to manipulate large circular buffer that holds compressed
* images/video. Buffer frame data is filled in by the FPGA, frame pointers and
* essential frames metadata filled during servicing of the interrupts.
*
* Copyright (C) 2016 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/>.
* -----------------------------------------------------------------------------**
*/
#include <linux/module.h>
#include <linux/mm.h>
......@@ -175,6 +57,7 @@
#include <asm/uaccess.h>
#include <elphel/driver_numbers.h>
#include <elphel/c313a.h>
#include <elphel/elphel393-mem.h>
#include "framepars.h" // just for ELPHEL_DEBUG bit mask
......@@ -182,8 +65,8 @@
#include "jpeghead.h"
#include "circbuf.h"
#include "exif.h"
#include "x313_macro.h"
#include <elphel/elphel393-mem.h>
#include "x393_macro.h"
#include "x393.h"
#if ELPHEL_DEBUG
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
......@@ -622,28 +505,78 @@ MD12(int dbg_i);
return file->f_pos ;
}
/**
* @brief This function handles write operations for circbuf file
* @param[in] file pointer to <em>struct file</em>
* @param[in] buf pointer to buffer containing data
* @param[in] count number of bytes in buffer
* @param[in] off offset
* @return number of bytes read form \e buf
*/
ssize_t circbuf_write(struct file * file, const char * buf, size_t count, loff_t *off) {
unsigned long p;
char *char_pb = (char *)ccam_dma_buf;
D(printk("circbuf_write\n"));
/// ************* NOTE: Never use file->f_pos in write() and read() !!!
p = *off;
if(p >= (CCAM_DMA_SIZE << 2))
p = (CCAM_DMA_SIZE << 2);
if((p + count) > (CCAM_DMA_SIZE << 2)) { // truncate count
count = (CCAM_DMA_SIZE << 2) - p;
}
if(count) {
if(copy_from_user(&char_pb[p], buf, count))
return -EFAULT;
*off += count;
}
return count;
void __iomem *mmio;
x393_afimux_status_t val;
int port;
unsigned long p;
char *char_pb = (char *)ccam_dma_buf;
struct circbuf_pd *priv = file->private_data;
// convert char to number
port = buf[0] - 0x30;
/*mmio = ioremap(0x40002060, 16);
if (!mmio) {
printk(KERN_DEBUG "ERROR: can not ioremap region");
return count;
}*/
if (init_mmio_ptr() < 0) {
printk(KERN_DEBUG "ERROR: can not remap IO region\n");
}
if (port >= 0 && port < 4) {
val = x393_afimux0_status(port);
//val.d32 = readl((void*) (0x40002060 + 0x4 * port));
//val.d32 = ioread32(mmio + 0x4 * port);
} else {
printk(KERN_DEBUG "Unrecognized port number\n");
}
printk(KERN_DEBUG "AFI MUX0 port: %d, AFI MUX0 offset: 0x%x, AFI MUX0 sequence number: %d\n", port, val.offset256 * 32, val.seq_num);
printk(KERN_DEBUG "AFI MUX0 raw value: 0x%x\n", val.d32);
printk(KERN_DEBUG "AFI MUX0 offset265: 0x%x, seq_num: 0x%x\n", val.offset256, val.seq_num);
iounmap(mmio);
mmio = NULL;
return count;
D(printk("circbuf_write\n"));
/// ************* NOTE: Never use file->f_pos in write() and read() !!!
p = *off;
if(p >= (CCAM_DMA_SIZE << 2))
p = (CCAM_DMA_SIZE << 2);
if((p + count) > (CCAM_DMA_SIZE << 2)) { // truncate count
count = (CCAM_DMA_SIZE << 2) - p;
}
if(count) {
if(copy_from_user(&char_pb[p], buf, count))
return -EFAULT;
*off += count;
}
return count;
}
/**
* @brief This function handles read operations for circbuf file
* @param[in] file pointer to <em>struct file</em>
* @param[in] buf pointer to buffer where data will be written to
* @param[in] count number of bytes written to \e buf
* @param[in] off offset
* @return number of bytes written to \e buf
*/
ssize_t circbuf_read(struct file * file, char * buf, size_t count, loff_t *off) {
unsigned long p;
char * char_pb = (char *) ccam_dma_buf;
struct circbuf_pd *priv = file->private_data;
printk(KERN_DEBUG "%s\n", __func__);
p = *off;
D(printk("circbuf_read pos=%d,count=%d, off=%d\r\n",p,count,off ));
if (p >= (CCAM_DMA_SIZE<<2)) p = (CCAM_DMA_SIZE<<2);
......@@ -708,6 +641,11 @@ unsigned int circbuf_poll (struct file *file, poll_table *wait) {
return 0; // nothing ready
}
/**
* @brief cirbuf driver probing function
* @param[in] pdev pointer to \b platform_device structure
* @return 0 on success or negative error code otherwise
*/
static int circbuf_all_init(struct platform_device *pdev)
{
int res;
......@@ -719,7 +657,6 @@ static int circbuf_all_init(struct platform_device *pdev)
if (!match)
return -EINVAL;
dev_info(dev, "loading circbuf driver\n");
MDF19(printk("\n"));
res = register_chrdev(CIRCBUF_MAJOR, "circbuf_operations", &circbuf_fops);
if(res < 0) {
......@@ -733,23 +670,11 @@ static int circbuf_all_init(struct platform_device *pdev)
return -ENOMEM;
}
// init other modules: framepars, sensor_common
/*res = framepars_init();
if (res < 0) {
dev_err(dev, "unable to init framepars\n");
return res;
}
res = image_acq_init();
if (res < 0) {
dev_err(dev, "unable to init sensor_comon\n");
return res;
}*/
MDF19(printk("init_waitqueue_head()\n"));
init_waitqueue_head(&circbuf_wait_queue);
MDF19(printk("jpeg_htable_init()\n"));
jpeg_htable_init (); /// set default Huffman table, encode it for the FPGA
printk(CIRCBUF_DRIVER_NAME"- %d\n",CIRCBUF_MAJOR);
dev_info(dev, "registered MAJOR: %d\n", CIRCBUF_MAJOR);
return 0;
}
......@@ -772,7 +697,6 @@ static struct platform_driver elphel393_circbuf = {
.remove = circbuf_remove,
.driver = {
.name = CIRCBUF_DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = elphel393_circbuf_of_match,
},
};
......
/** @file framepars.c */
/*!********************************************************************************
*! FILE NAME : framepars.c
*! DESCRIPTION: Handling of frame parameters, making use of FPGA i2c
......@@ -207,6 +208,9 @@
#include <linux/init.h>
//#include <linux/autoconf.h>
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
//#include <asm/system.h>
#include <asm/byteorder.h> // endians
......@@ -230,7 +234,7 @@
/// needed for lseek commands
//#include "cxdma.h" // x313_dma_init
//#include "cci2c.h" // to use void i2c_reset_wait(void), reset shadow static 'i2c_hardware_on'
#include "x393_macro.h"
/**
* \def MDF1(x) optional debug output
......@@ -283,11 +287,11 @@
//#define ELP_KERR(x) printk("%s:%d:%s: ERROR ",__FILE__,__LINE__,__FUNCTION__); x
/**
* \def X3X3_FRAMEPARS_DRIVER_NAME driver name to display
* \def FRAMEPARS_DRIVER_NAME driver name to display
*/
#define FRAMEPARS_DRIVER_NAME "Elphel (R) Model 393 Frame Parameters device driver"
#define X3X3_FRAMEPARS_DRIVER_NAME "Elphel (R) Model 353 Frame Parameters device driver"
static const struct of_device_id elphel393_framepars_of_match[];
static struct framepars_all_t sFrameParsAll __attribute__ ((aligned (PAGE_SIZE))); ///< Sensor Parameters, currently 8 pages all and 2048 pages some, static struct
unsigned long frameParsInitialized; /// set to 0 at startup, 1 after initialization that is triggered by setParsAtomic()
#define thisFrameNumber GLOBALPARS(G_THIS_FRAME) // Current frame number (may lag from the hardware)
......@@ -332,7 +336,6 @@ int framepars_release(struct inode *inode, struct file *filp);
loff_t framepars_lseek (struct file * file, loff_t offset, int orig);
ssize_t framepars_write (struct file * file, const char * buf, size_t count, loff_t *off);
int framepars_mmap (struct file *file, struct vm_area_struct *vma);
static int __init framepars_init(void);
/**
* @brief Reset hardware sequencers (i2c, command) and initialize framepars structure
......@@ -1321,27 +1324,61 @@ int framepars_mmap (struct file *file, struct vm_area_struct *vma) {
}
/**
* @brief framepars driver init
* @return 0
* @brief framepars driver probing function
* @param[in] pdev pointer to \b platform_device structure
* @return 0 on success or negative error code otherwise
*/
static int __init framepars_init(void) {
static int framepars_init(struct platform_device *pdev)
{
int res;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
/* sanity check */
match = of_match_device(elphel393_framepars_of_match, dev);
if (!match)
return -EINVAL;
init_framepars_ptr();
initGlobalPars(); /// sets default debug if enabled - not anymore. Add here?
initMultiPars(); /// just clear - needs to be called again when sensor is recognized
frameParsInitialized=0;
res = register_chrdev(FRAMEPARS_MAJOR, "framepars_operations", &framepars_fops);
if(res < 0) {
printk(KERN_ERR "\nframepars_init: couldn't get a major number %d.\n",FRAMEPARS_MAJOR);
return res;
}
init_waitqueue_head(&framepars_wait_queue);
printk(X3X3_FRAMEPARS_DRIVER_NAME" - %d \n",FRAMEPARS_MAJOR);
dev_info(dev, "registered MAJOR: %d\n", FRAMEPARS_MAJOR);
return 0;
}
static int framepars_remove(struct platform_device *pdev)
{
unregister_chrdev(FRAMEPARS_MAJOR, "framepars_operations");
return 0;
}
static const struct of_device_id elphel393_framepars_of_match[] = {
{ .compatible = "elphel,elphel393-framepars-1.00" },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, elphel393_framepars_of_match);
static struct platform_driver elphel393_framepars = {
.probe = framepars_init,
.remove = framepars_remove,
.driver = {
.name = FRAMEPARS_DRIVER_NAME,
.of_match_table = elphel393_framepars_of_match,
},
};
module_platform_driver(elphel393_framepars);
module_init(framepars_init);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(X3X3_FRAMEPARS_DRIVER_NAME);
/*!***************************************************************************
*! FILE NAME : jpeghead.c
*! DESCRIPTION: handleng JPEG file headers
*!
*! 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/>.
*! -----------------------------------------------------------------------------**
*! $Log: jpeghead.c,v $
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*!
*!
*! Revision 1.10 2008/11/03 18:43:18 elphel
*! 8.0.alpha12 with working apps/astreamer
*!
*! Revision 1.9 2008/10/29 04:18:28 elphel
*! v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
*!
*! Revision 1.8 2008/10/12 16:46:22 elphel
*! snapshot
*!
*! Revision 1.7 2008/10/06 08:31:08 elphel
*! snapshot, first images
*!
*! Revision 1.6 2008/09/22 22:55:48 elphel
*! snapshot
*!
*! Revision 1.5 2008/09/19 04:37:25 elphel
*! snapshot
*!
*! Revision 1.4 2008/09/12 20:40:12 elphel
*! snapshot
*!
*! Revision 1.3 2008/09/12 00:23:59 elphel
*! removed cc353.c, cc353.h
*!
*! Revision 1.2 2008/09/11 01:05:32 elphel
*! snapshot
*!
*! Revision 1.1 2008/09/07 19:48:09 elphel
*! snapshot
*!
/** @file jpeghead.c
*
* @brief This file contains methods for JPEG tables and headers generation and
* JPEG files composition from data compressed by FPGA.
*
* Copyright (C) 2016 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/>.
*/
/****************** INCLUDE FILES SECTION ***********************************/
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/sched.h>
......@@ -98,8 +60,8 @@
//#include "cxdma.h"
//#include "circbuf.h"
//#include "sensor_common.h"
#include "x313_macro.h"
#include "exif.h"
#include "x393_macro.h"
#if ELPHEL_DEBUG
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__ );x ;}
......
/*!********************************************************************************
*! FILE NAME : sensor_common.c
*! DESCRIPTION: Sensor discovery, initialization, programming - common
*! for all sensors
*! Now most is moved to other files, here will be
*! - system initialization
*! - compressor write (and global read) pointers
*! - populating 32-byte interframe data
*! - something for Exif?
*! - where are histograms? ->histograms.c
*! - interrupt loop
*! - tasklets
*! - device driver that includes waiting for the next frame regardless of compression
*! - anything else?
*!
*!
*! 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/>.
*! -----------------------------------------------------------------------------**
*! $Log: sensor_common.c,v $
*! Revision 1.11 2012/04/08 04:09:23 elphel
*! added temperatures to MakerNote
*!
*! Revision 1.10 2010/08/10 21:14:31 elphel
*! 8.0.8.39 - added EEPROM support for multiplexor and sensor boards, so autocampars.php uses application-specific defaults. Exif Orientation tag support, camera Model reflects application and optional mode (i.e. camera number in Eyesis)
*!
*! Revision 1.9 2010/08/03 23:37:34 elphel
*! rev 8.0.8.37, portrait mode support
*!
*! Revision 1.8 2010/08/01 19:29:24 elphel
*! files updated to support coring function for noise filtering
*!
*! Revision 1.7 2010/07/20 20:13:34 elphel
*! 8.0.8.33 - added MakerNote info for composite images made with multisensor cameras (with 10359 board)
*!
*! Revision 1.6 2010/05/16 02:03:47 elphel
*! 8.0.8.4 - driver working with individual/broadcast sensor registers
*!
*! Revision 1.5 2010/05/13 03:39:31 elphel
*! 8.0.8.12 - drivers modified for multi-sensor operation
*!
*! Revision 1.4 2010/03/04 06:41:40 elphel
*! 8.0.7.3 - more data to makerNote
*!
*! Revision 1.3 2009/12/28 06:24:17 elphel
*! 8.0.6.6 - added MakerNote to Exif, it icludes channels gains and gammas/black levels
*!
*! Revision 1.2 2008/11/30 21:56:39 elphel
*! Added enforcing limit on the overall gains in the color channels, storage of exposure and gains in the histograms cache (to be used with autoexposure/white balance)
*!
*! Revision 1.1.1.1 2008/11/27 20:04:00 elphel
*!
*!
*! Revision 1.33 2008/11/20 07:04:47 elphel
*! made silent when debug is 0
*!
*! Revision 1.32 2008/11/14 07:06:54 elphel
*! fixed wrong timing for servicing histogram requests
*!
*! Revision 1.31 2008/11/13 05:40:45 elphel
*! 8.0.alpha16 - modified histogram storage, profiling
*!
*! Revision 1.30 2008/11/10 19:47:46 elphel
*! added TODO abut reducing CPU load by decimating histogram calculations (not each frame)
*!
*! Revision 1.29 2008/10/29 04:18:28 elphel
*! v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
*!
*! Revision 1.28 2008/10/26 05:54:45 elphel
*! changed value of frame counters for histograms to compensate for 1 frame latency of histograms
*!
*! Revision 1.27 2008/10/25 19:55:00 elphel
*! made the histograms calculations relate to previous, not this frame.
*!
*! Revision 1.26 2008/10/23 08:09:02 elphel
*! support for histogram wait queues
*!
*! Revision 1.25 2008/10/19 06:56:05 elphel
*! elphel_wait_frame() now works only for compressed frames, new elphel_skip_frames() and elphel_wait_frame_abs() wait sequencer frames (all sensor frames, even those that are not compressed)
*!
*! Revision 1.24 2008/10/15 22:28:56 elphel
*! snapshot 8.0.alpha2
*!
*! Revision 1.23 2008/10/13 16:55:53 elphel
*! removed (some) obsolete P_* parameters, renamed CIRCLSEEK to LSEEK_CIRC constants (same as other similar)
*!
*! Revision 1.22 2008/10/12 16:46:22 elphel
*! snapshot
*!
*! Revision 1.21 2008/10/11 18:46:07 elphel
*! snapshot
*!
*! Revision 1.20 2008/10/10 17:06:59 elphel
*! just a snapshot
*!
*! Revision 1.19 2008/10/08 21:26:25 elphel
*! snapsot 7.2.0.pre4 - first images (actually - second)
*!
*! Revision 1.18 2008/10/05 05:13:33 elphel
*! snapshot003
*!
*! Revision 1.17 2008/10/04 16:10:12 elphel
*! snapshot
*!
*! Revision 1.16 2008/09/28 00:31:57 elphel
*! snapshot
*!
*! Revision 1.15 2008/09/25 00:58:12 elphel
*! snapshot
*!
*! Revision 1.14 2008/09/22 22:55:49 elphel
*! snapshot
*!
*! Revision 1.13 2008/09/20 00:29:50 elphel
*! moved driver major/minor numbers to a single file - include/asm-cris/elphel/driver_numbers.h
*!
*! Revision 1.12 2008/09/19 04:37:26 elphel
*! snapshot
*!
*! Revision 1.11 2008/09/16 00:49:32 elphel
*! snapshot
*!
*! Revision 1.10 2008/09/12 00:24:00 elphel
*! removed cc353.c, cc353.h
*!
*! Revision 1.9 2008/09/07 19:48:09 elphel
*! snapshot
*!
*! Revision 1.8 2008/09/05 23:20:26 elphel
*! just a snapshot
*!
*! Revision 1.7 2008/09/02 21:01:07 elphel
*! just next...
*!
*! Revision 1.6 2008/07/29 01:15:07 elphel
*! another snapshot
*!
*! Revision 1.5 2008/07/27 23:25:07 elphel
*! next snapshot
*!
*! Revision 1.4 2008/07/27 04:27:49 elphel
*! next snapshot
*!
*! Revision 1.3 2008/06/24 00:43:44 elphel
*! just a snapshot
*!
*! Revision 1.2 2008/06/20 03:54:21 elphel
*! another snapshot
*!
*! Revision 1.1 2008/06/16 06:51:21 elphel
*! work in progress, intermediate commit
*!
*!
*/
/** @file sensor_common.h
* @brief This module handles sensor discovery, initialization and programming tasks
* common for all sensors. Task that are implemented:
* - system initialization (?)
* - compressor write (and global read) pointers
* - populating 32-byte interframe data
* - interrupts handling
* - tasklets
* - device driver that includes waiting for the next frame regardless of compression
*
* Copyright (C) 2016 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/>.
*/
//copied from cxi2c.c - TODO:remove unneeded
......@@ -180,6 +38,9 @@
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
//#include <asm/system.h>
#include <asm/byteorder.h> // endians
......@@ -195,6 +56,8 @@
#include <elphel/c313a.h>
//#include <asm/elphel/fpgaconfa.h>
#include <elphel/exifa.h>
//#include <elphel/x393_types.h>
#include "x393.h"
//#include "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr
//#include "fpga_sdram.h" // use a single fpga_initSDRAM(void)
......@@ -210,6 +73,7 @@
//#include "histograms.h"
//#include "gamma_tables.h"
#include "quantization_tables.h"
#include "x393_macro.h"
#if ELPHEL_DEBUG
#define ELPHEL_DEBUG_THIS 0
......@@ -233,10 +97,38 @@
#define MD13(x)
#endif
/**@struct jpeg_ptr_t
* @brief \e jpeg_ptr_t structure contains read and write pointers along with
* IRQ number for a single channel
* @var jpeg_ptr_t::jpeg_wr
* JPEG write pointer
* @var jpeg_ptr_t::jpeg_rp
* JPEG read pointer
* @var jpeg_ptr_t::fpga_cntr_prev
* This field contains previous value of the FPGA transfer counter which is used
* to find out if it has changed
* @var jpeg_ptr_t::irq_num_comp
* IRQ number associated with compressor
* @var jpeg_ptr_t::irq_num_sens
* IRQ number associated with sensor
*/
struct jpeg_ptr_t {
volatile int jpeg_wp;
volatile int jpeg_rp;
int fpga_cntr_prev;
unsigned int irq_num_comp;
unsigned int irq_num_sens;
};
/**@struct image_acq_pd_t
* @brief \e image_acq_pd contains private data for the image acquisition driver
*/
struct image_acq_pd_t {
int minor;
struct jpeg_ptr_t jpeg_ptr[IMAGE_CHN_NUM];
};
#define X3X3_ELPHEL_DRIVER_NAME "Elphel (R) Model 353 Camera Driver"
static const char elphel_cam_name[] = "elphelcam353";
static struct image_acq_pd_t image_acq_priv;
static volatile int JPEG_wp;
static volatile int JPEG_rp;
......@@ -250,17 +142,6 @@ static int fpga_counter_prev=0; /// Previous value of the FPGA transfer counter
int Photo_MakerNote;
} meta_offsets;
///Defines/macros moved from the cc353.h
// #define EN_INTERRUPT(x) port_csp0_addr[X313_WA_IRQ_ENA]= (1<< x )
// #define DIS_INTERRUPT(x) {port_csp0_addr[X313_WA_IRQ_DIS]= (1<< x ); port_csp0_addr[X313_WA_IRQ_RST]= (1<< x );}
// #define DIS_INTERRUPTS {port_csp0_addr[X313_WA_IRQ_DIS]= 0xffff; port_csp0_addr[X313_WA_IRQ_RST]= 0xffff;}
int camSeqGetJPEG_wp(void) {return JPEG_wp;}
int camSeqGetJPEG_rp(void) {return JPEG_rp;}
void camSeqSetJPEG_rp(int p) {
......@@ -271,42 +152,39 @@ void camSeqSetJPEG_rp(int p) {
get_globalParam(G_CIRCBUFSIZE):0)+ get_globalParam(G_CIRCBUFRP))
- get_globalParam(G_CIRCBUFWP));
}
//EXPORT_SYMBOL_GPL(camSeqGetJPEG_wp);
//EXPORT_SYMBOL_GPL(camSeqGetJPEG_rp);
//EXPORT_SYMBOL_GPL(camSeqSetJPEG_rp);
/*!
End of compressor-related code - TODO: move to a separate file?
*/
/**
* @brief driver name to display in log messages
*/
#define IMAGEACQ_DRIVER_NAME "Elphel (R) Model 393 Image Acquisition device driver"
#define X3X3_IMAGEACQ_DRIVER_NAME "Elphel (R) Model 353 Image Acquisition device driver"
static const struct of_device_id elphel393_sensor_of_match[];
static struct sensorproc_t s_sensorproc; // sensor parameters and functions to call
struct sensorproc_t * sensorproc = NULL;
//EXPORT_SYMBOL_GPL(sensorproc);
//wait_queue_head_t image_acq_wait_queue; /// queue for the sensor frame interrupts
struct image_acq_pd {
int minor;
// struct wait_queue *image_acq_wait_queue;
// something else to be added here?
};
void tasklet_fpga_function(unsigned long arg);
/**
* @brief Copy sensorproc structure, needed for multisensor board to be able to replace some of the functions
* @param copy - pointer to a copy structure
* @return pointer to a copy structure
* @brief Copy #sensorproc structure, needed for multisensor board to be able
* to replace some of the functions
* @param[in] copy pointer to a copy structure
* @return pointer to a \b copy structure
*/
struct sensorproc_t * copy_sensorproc (struct sensorproc_t * copy) {
memcpy(copy, sensorproc, sizeof(struct sensorproc_t)); /// copy sensor functions
return copy;
struct sensorproc_t * copy_sensorproc (struct sensorproc_t * copy)
{
/** copy sensor functions */
memcpy(copy, sensorproc, sizeof(struct sensorproc_t));
return copy;
}
#ifdef TEST_DISABLE_CODE
//#ifdef TEST_DISABLE_CODE
/// When should it be called?
//int init_sensor(void);
......@@ -352,8 +230,6 @@ int init_FPGA(void) { //will check FPGA version, init SDRAM (if needed) and sens
///
int init_acq_sensor(void);
static int __init image_acq_init(void);
DECLARE_TASKLET(tasklet_fpga, tasklet_fpga_function, 0); /// 0 - no arguments for now
......@@ -533,6 +409,33 @@ static irqreturn_t elphel_FPGA_interrupt(int irq, void *dev_id) {
return IRQ_HANDLED;
}
/**
* @brief Handle interrupts from sensor channels. This handler is installed without SA_INTERRUPT
* flag meaning that interrupts are enabled during processing. Such behavior is recommended in LDD3.
* @param[in] irq interrupt number
* @param[in] dev_id pointer to driver's private data structure #jpeg_ptr_t corresponding to
* the channel which raise interrupt
* @return \e IRQ_HANDLED if interrupt was processed and \e IRQ_NONE otherwise
*/
static irqreturn_t frame_sync_irq_handler(int irq, void *dev_id)
{
update_frame_pars();
return IRQ_HANDLED;
}
/**
* @brief Handle interrupts from JPEG compressor channels. This handler is installed without SA_INTERRUPT
* flag meaning that interrupts are enabled during processing. Such behavior is recommended in LDD3.
* @param[in] irq interrupt number
* @param[in] dev_id pointer to driver's private data structure #jpeg_ptr_t corresponding to
* the channel which raise interrupt
* @return \e IRQ_HANDLED if interrupt was processed and \e IRQ_NONE otherwise
*/
static irqreturn_t compressor_irq_handler(int irq, void *dev_id)
{
return IRQ_HANDLED;
}
/**
* @brief Tasklet - software interrupt
* lower priority tasks
......@@ -655,7 +558,7 @@ GLOBALPARS(0x1044)=thisFrameNumber;
#endif
}
#endif /* TEST_DISABLE_CODE */
//#endif /* TEST_DISABLE_CODE */
/**
* @brief resets compressor and buffer pointers
......@@ -697,85 +600,118 @@ void camera_interrupts (int on) {
intr_mask.ext = on ? 1 : 0;
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
#endif /* TEST_DISABLE_CODE */
x393_arbite_pri_t val;
val = get_x393_mcntrl_arbiter_priority(0);
if (val.d32 == 1)
printk("1");
else
printk("2");
}
//EXPORT_SYMBOL_GPL(camera_interrupts);
int image_acq_open(struct inode *inode, struct file *filp) ;
int image_acq_release(struct inode *inode, struct file *filp) ;
loff_t image_acq_fops_lseek (struct file * file, loff_t offset, int orig) ;
ssize_t image_acq_fops_write(struct file * file, const char * buf, size_t count, loff_t *off) ;
int image_acq_mmap (struct file *file, struct vm_area_struct *vma) ;
static struct file_operations image_acq_fops = {
owner: THIS_MODULE,
llseek: image_acq_fops_lseek,
// read: image_acq_fops_read,
write: image_acq_fops_write,
// ioctl: image_acq_ioctl,
open: image_acq_open,
mmap: image_acq_mmap,
release: image_acq_release
};
static int __init image_acq_init(void) {
int res;
sensorproc= &s_sensorproc;
MDD1(printk("sensorproc=0x%x\n",(int) sensorproc));
//init_ccam_dma_buf_ptr(); /// should it be done here? Why not in circbuf.c?
/// init_histograms(); - other initializations?
res = register_chrdev(ELPHEL_MAJOR, elphel_cam_name, &image_acq_fops);
if(res < 0) {
printk(KERN_ERR "image_acq_init: couldn't get a major number %d.\n",ELPHEL_MAJOR);
return res;
}
/**
* @brief sensor_common driver probing function
* @param[in] pdev pointer to \b platform_device structure
* @return 0 on success or negative error code otherwise
*/
static int image_acq_init(struct platform_device *pdev)
{
int i;
int res;
unsigned int irq;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
const char **frame_sync_irq_names = { "frame_sync_irq_0", "frame_sync_irq_1",
"frame_sync_irq_2", "frame_sync_irq_3" };
const char **compressor_irq_names = { "compr_irq_0", "compr_irq_1",
"compr_irq_2", "compr_irq_3"
};
/* sanity check */
match = of_match_device(elphel393_sensor_of_match, dev);
if (!match)
return -EINVAL;
sensorproc= &s_sensorproc;
MDD1(printk("sensorproc=0x%x\n",(int) sensorproc));
for (i = 0; i < IMAGE_CHN_NUM; i++) {
irq = platform_get_irq_byname(pdev, frame_sync_irq_names[i]);
if (request_irq(irq,
frame_sync_irq_handler,
0, // no flags
frame_sync_irq_names[i],
&image_acq_priv.jpeg_ptr[i])) {
printk(KERN_ERR "Can not allocate Elphel FPGA interrupts");
return -EBUSY;
}
image_acq_priv.jpeg_ptr[i].irq_num_sens = irq;
}
for (i = 0; i < IMAGE_CHN_NUM; i++) {
irq = platform_get_irq_byname(pdev, compressor_irq_names[i]);
if (request_irq(irq,
compressor_irq_handler,
0, // no flags
compressor_irq_names[i],
&image_acq_priv.jpeg_ptr[i])) {
printk(KERN_ERR "Can not allocate Elphel FPGA interrupts");
return -EBUSY;
}
image_acq_priv.jpeg_ptr[i].irq_num_comp = irq;
}
#ifdef TEST_DISABLE_CODE
if(request_irq(EXT_INTR_VECT,
elphel_FPGA_interrupt,
SA_INTERRUPT, // SA_SHIRQ | SA_INTERRUPT if it is a shared one.
"Elphel FPGA interrupts",
NULL)) {
printk(KERN_ERR "Can't allocate Elphel FPGA interrupts");
return -EBUSY;
}
if(request_irq(EXT_INTR_VECT,
elphel_FPGA_interrupt,
SA_INTERRUPT, // SA_SHIRQ | SA_INTERRUPT if it is a shared one.
"Elphel FPGA interrupts",
NULL)) {
printk(KERN_ERR "Can't allocate Elphel FPGA interrupts");
return -EBUSY;
}
#endif
printk("Elphel FPGA interrupts initialized\n");
// init_waitqueue_head(&image_acq_wait_queue);
// DMA_buf_start=x313_dma_init();
MDD1(printk("reset_compressor()\n"));
reset_compressor(); /// reset compressor and buffer pointers
MDD1(printk("x313_dma_init()\n"));
//x313_dma_init(); /// initialize ETRAX FS DMA
MDD1(printk("init_pgm_proc ()\n"));
//init_pgm_proc (); /// setup pointers to functions (not sensor-specific)
MDD1(printk("reset_qtables()\n"));
reset_qtables(); /// force initialization at next access
printk(X3X3_ELPHEL_DRIVER_NAME" - %d\n",ELPHEL_MAJOR);
return 0;
printk("Elphel FPGA interrupts initialized\n");
// init_waitqueue_head(&image_acq_wait_queue);
// DMA_buf_start=x313_dma_init();
MDD1(printk("reset_compressor()\n"));
reset_compressor(); /// reset compressor and buffer pointers
MDD1(printk("x313_dma_init()\n"));
//x313_dma_init(); /// initialize ETRAX FS DMA
MDD1(printk("init_pgm_proc ()\n"));
//init_pgm_proc (); /// setup pointers to functions (not sensor-specific)
MDD1(printk("reset_qtables()\n"));
reset_qtables(); /// force initialization at next access
return 0;
}
int image_acq_open(struct inode *inode, struct file *filp) {
return 0;
}
int image_acq_release(struct inode *inode, struct file *filp) {
return 0;
}
loff_t image_acq_fops_lseek (struct file * file, loff_t offset, int orig) {
return 0;
}
ssize_t image_acq_fops_write(struct file * file, const char * buf, size_t count, loff_t *off) {
return 0;
}
int image_acq_mmap (struct file *file, struct vm_area_struct *vma) {
return 0;
static int image_acq_stop(struct platform_device *pdev)
{
return 0;
}
static const struct of_device_id elphel393_sensor_of_match[] = {
{ .compatible = "elphel,elphel393-sensor-1.00" },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, elphel393_sensor_of_match);
static struct platform_driver elphel393_sensor_common = {
.probe = image_acq_init,
.remove = image_acq_stop,
.driver = {
.name = IMAGEACQ_DRIVER_NAME,
.of_match_table = elphel393_sensor_of_match,
}
};
module_platform_driver(elphel393_sensor_common);
module_init(image_acq_init);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(X3X3_IMAGEACQ_DRIVER_NAME);
MODULE_DESCRIPTION(IMAGEACQ_DRIVER_NAME);
#ifndef _X313_MACRO
#define _X313_MACRO
/**
* @file x393_macro.h
* @brief This file contains various macros used in multiple files.
*/
#ifndef _X393_MACRO
#define _X393_MACRO
/** @brief Number of image channels*/
#define IMAGE_CHN_NUM 4
/* These macro were removed from sensor_common.h*/
#define X313_LENGTH_MASK 0xff000000
......@@ -7,4 +14,4 @@
#define X313_BUFFSUB(x,y) (((x)>=(y))? ((x)-(y)) : ((x)+ (CCAM_DMA_SIZE-(y))))
#define X313_BUFFADD(x,y) ((((x) + (y))<=CCAM_DMA_SIZE)? ((x) + (y)) : ((x) - (CCAM_DMA_SIZE-(y))))
#endif /* _X313_MACRO */
#endif /* _X393_MACRO */
......@@ -9,8 +9,8 @@
//#define ELPHEL_DEBUG 0 //global debug on/off in multiple files
//#define ELPHEL_DEBUG_STARTUP 000a4c00 ;
//#define ELPHEL_DEBUG_STARTUP 0 ; // removed - add write to fpga init script
//#define ELPHEL_DEBUG 0 //global debug on/off in multiple files
#define ELPHEL_DEBUG 1 //global debug on/off in multiple files
#define ELPHEL_DEBUG 0 //global debug on/off in multiple files
//#define ELPHEL_DEBUG 1 //global debug on/off in multiple files
#define ELPHEL_DEBUG_DELAY 100000 //delay after some printk-s
#define ELP_KERR(x) printk("%s:%d:%s: ERROR ",__FILE__,__LINE__,__FUNCTION__);x
#define ELP_FERR(x) fprintf(stderr,"%s:%d:%s: ERROR ",__FILE__,__LINE__,__FUNCTION__);x
......
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