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 ...@@ -8,7 +8,7 @@ obj-$(CONFIG_ELPHELDRVONMICROZED) += elphel393-mem.o
obj-$(CONFIG_ELPHEL393_INIT) += elphel393-init.o obj-$(CONFIG_ELPHEL393_INIT) += elphel393-init.o
obj-$(CONFIG_ELPHEL393) += framepars.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) += quantization_tables.o
obj-$(CONFIG_ELPHEL393) += circbuf.o jpeghead.o obj-$(CONFIG_ELPHEL393) += circbuf.o jpeghead.o
...@@ -18,4 +18,4 @@ 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) += fpars.o
#obj-$(CONFIG_ELPHEL393_EXTERNAL) += sc.o #obj-$(CONFIG_ELPHEL393_EXTERNAL) += sc.o
#obj-$(CONFIG_ELPHEL393_EXTERNAL) += cbuf.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 circbuf.c
*! FILE NAME : circbuf.c *
*! DESCRIPTION: drivers to manipulate large circular buffer that holds compressed * @brief drivers to manipulate large circular buffer that holds compressed
*! images/video. Buffer frame data is filled in by the FPGA, frame pointers and * images/video. Buffer frame data is filled in by the FPGA, frame pointers and
*! essential frames metadata filled during servicing of the interruptsl * essential frames metadata filled during servicing of the interrupts.
*! This code is based on the code from cxdma.c *
*! TODO: Add buffer reset, JPEG header generation here * Copyright (C) 2016 Elphel, Inc
*! *
*! 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
*! This program is free software: you can redistribute it and/or modify * (at your option) any later version.
*! it under the terms of the GNU General Public License as published by *
*! the Free Software Foundation, either version 3 of the License, or * This program is distributed in the hope that it will be useful,
*! (at your option) any later version. * but WITHOUT ANY WARRANTY; without even the implied warranty of
*! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! This program is distributed in the hope that it will be useful, * GNU General Public License for more details.
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License
*! GNU General Public License for more details. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*! * -----------------------------------------------------------------------------**
*! 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 ***********************************/
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -175,6 +57,7 @@ ...@@ -175,6 +57,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <elphel/driver_numbers.h> #include <elphel/driver_numbers.h>
#include <elphel/c313a.h> #include <elphel/c313a.h>
#include <elphel/elphel393-mem.h>
#include "framepars.h" // just for ELPHEL_DEBUG bit mask #include "framepars.h" // just for ELPHEL_DEBUG bit mask
...@@ -182,8 +65,8 @@ ...@@ -182,8 +65,8 @@
#include "jpeghead.h" #include "jpeghead.h"
#include "circbuf.h" #include "circbuf.h"
#include "exif.h" #include "exif.h"
#include "x313_macro.h" #include "x393_macro.h"
#include <elphel/elphel393-mem.h> #include "x393.h"
#if ELPHEL_DEBUG #if ELPHEL_DEBUG
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;} #define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
...@@ -622,28 +505,78 @@ MD12(int dbg_i); ...@@ -622,28 +505,78 @@ MD12(int dbg_i);
return file->f_pos ; 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) { ssize_t circbuf_write(struct file * file, const char * buf, size_t count, loff_t *off) {
unsigned long p; void __iomem *mmio;
char *char_pb = (char *)ccam_dma_buf; x393_afimux_status_t val;
D(printk("circbuf_write\n")); int port;
/// ************* NOTE: Never use file->f_pos in write() and read() !!!
p = *off; unsigned long p;
if(p >= (CCAM_DMA_SIZE << 2)) char *char_pb = (char *)ccam_dma_buf;
p = (CCAM_DMA_SIZE << 2); struct circbuf_pd *priv = file->private_data;
if((p + count) > (CCAM_DMA_SIZE << 2)) { // truncate count
count = (CCAM_DMA_SIZE << 2) - p; // convert char to number
} port = buf[0] - 0x30;
if(count) { /*mmio = ioremap(0x40002060, 16);
if(copy_from_user(&char_pb[p], buf, count)) if (!mmio) {
return -EFAULT; printk(KERN_DEBUG "ERROR: can not ioremap region");
*off += count; return count;
} }*/
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) { ssize_t circbuf_read(struct file * file, char * buf, size_t count, loff_t *off) {
unsigned long p; unsigned long p;
char * char_pb = (char *) ccam_dma_buf; char * char_pb = (char *) ccam_dma_buf;
struct circbuf_pd *priv = file->private_data;
printk(KERN_DEBUG "%s\n", __func__);
p = *off; p = *off;
D(printk("circbuf_read pos=%d,count=%d, off=%d\r\n",p,count,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); 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) { ...@@ -708,6 +641,11 @@ unsigned int circbuf_poll (struct file *file, poll_table *wait) {
return 0; // nothing ready 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) static int circbuf_all_init(struct platform_device *pdev)
{ {
int res; int res;
...@@ -719,7 +657,6 @@ static int circbuf_all_init(struct platform_device *pdev) ...@@ -719,7 +657,6 @@ static int circbuf_all_init(struct platform_device *pdev)
if (!match) if (!match)
return -EINVAL; return -EINVAL;
dev_info(dev, "loading circbuf driver\n");
MDF19(printk("\n")); MDF19(printk("\n"));
res = register_chrdev(CIRCBUF_MAJOR, "circbuf_operations", &circbuf_fops); res = register_chrdev(CIRCBUF_MAJOR, "circbuf_operations", &circbuf_fops);
if(res < 0) { if(res < 0) {
...@@ -733,23 +670,11 @@ static int circbuf_all_init(struct platform_device *pdev) ...@@ -733,23 +670,11 @@ static int circbuf_all_init(struct platform_device *pdev)
return -ENOMEM; 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")); MDF19(printk("init_waitqueue_head()\n"));
init_waitqueue_head(&circbuf_wait_queue); init_waitqueue_head(&circbuf_wait_queue);
MDF19(printk("jpeg_htable_init()\n")); MDF19(printk("jpeg_htable_init()\n"));
jpeg_htable_init (); /// set default Huffman table, encode it for the FPGA 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; return 0;
} }
...@@ -772,7 +697,6 @@ static struct platform_driver elphel393_circbuf = { ...@@ -772,7 +697,6 @@ static struct platform_driver elphel393_circbuf = {
.remove = circbuf_remove, .remove = circbuf_remove,
.driver = { .driver = {
.name = CIRCBUF_DRIVER_NAME, .name = CIRCBUF_DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = elphel393_circbuf_of_match, .of_match_table = elphel393_circbuf_of_match,
}, },
}; };
......
/** @file framepars.c */
/*!******************************************************************************** /*!********************************************************************************
*! FILE NAME : framepars.c *! FILE NAME : framepars.c
*! DESCRIPTION: Handling of frame parameters, making use of FPGA i2c *! DESCRIPTION: Handling of frame parameters, making use of FPGA i2c
...@@ -207,6 +208,9 @@ ...@@ -207,6 +208,9 @@
#include <linux/init.h> #include <linux/init.h>
//#include <linux/autoconf.h> //#include <linux/autoconf.h>
#include <linux/vmalloc.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/system.h>
#include <asm/byteorder.h> // endians #include <asm/byteorder.h> // endians
...@@ -230,7 +234,7 @@ ...@@ -230,7 +234,7 @@
/// needed for lseek commands /// needed for lseek commands
//#include "cxdma.h" // x313_dma_init //#include "cxdma.h" // x313_dma_init
//#include "cci2c.h" // to use void i2c_reset_wait(void), reset shadow static 'i2c_hardware_on' //#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 * \def MDF1(x) optional debug output
...@@ -283,11 +287,11 @@ ...@@ -283,11 +287,11 @@
//#define ELP_KERR(x) printk("%s:%d:%s: ERROR ",__FILE__,__LINE__,__FUNCTION__); x //#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 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() 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) #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); ...@@ -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); 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); 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); 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 * @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) { ...@@ -1321,27 +1324,61 @@ int framepars_mmap (struct file *file, struct vm_area_struct *vma) {
} }
/** /**
* @brief framepars driver init * @brief framepars driver probing function
* @return 0 * @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; 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(); init_framepars_ptr();
initGlobalPars(); /// sets default debug if enabled - not anymore. Add here? initGlobalPars(); /// sets default debug if enabled - not anymore. Add here?
initMultiPars(); /// just clear - needs to be called again when sensor is recognized initMultiPars(); /// just clear - needs to be called again when sensor is recognized
frameParsInitialized=0; frameParsInitialized=0;
res = register_chrdev(FRAMEPARS_MAJOR, "framepars_operations", &framepars_fops); res = register_chrdev(FRAMEPARS_MAJOR, "framepars_operations", &framepars_fops);
if(res < 0) { if(res < 0) {
printk(KERN_ERR "\nframepars_init: couldn't get a major number %d.\n",FRAMEPARS_MAJOR); printk(KERN_ERR "\nframepars_init: couldn't get a major number %d.\n",FRAMEPARS_MAJOR);
return res; return res;
} }
init_waitqueue_head(&framepars_wait_queue); 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; 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_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>."); MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(X3X3_FRAMEPARS_DRIVER_NAME); MODULE_DESCRIPTION(X3X3_FRAMEPARS_DRIVER_NAME);
/*!*************************************************************************** /** @file jpeghead.c
*! FILE NAME : jpeghead.c *
*! DESCRIPTION: handleng JPEG file headers * @brief This file contains methods for JPEG tables and headers generation and
*! * JPEG files composition from data compressed by FPGA.
*! Copyright (C) 2008 Elphel, Inc *
*! -----------------------------------------------------------------------------** * Copyright (C) 2016 Elphel, Inc
*! *
*! This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. * (at your option) any later version.
*! *
*! This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. * GNU General Public License for more details.
*! *
*! You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. * 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
*!
*/ */
/****************** INCLUDE FILES SECTION ***********************************/
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -98,8 +60,8 @@ ...@@ -98,8 +60,8 @@
//#include "cxdma.h" //#include "cxdma.h"
//#include "circbuf.h" //#include "circbuf.h"
//#include "sensor_common.h" //#include "sensor_common.h"
#include "x313_macro.h"
#include "exif.h" #include "exif.h"
#include "x393_macro.h"
#if ELPHEL_DEBUG #if ELPHEL_DEBUG
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__ );x ;} #define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__ );x ;}
......
/*!******************************************************************************** /** @file sensor_common.h
*! FILE NAME : sensor_common.c * @brief This module handles sensor discovery, initialization and programming tasks
*! DESCRIPTION: Sensor discovery, initialization, programming - common * common for all sensors. Task that are implemented:
*! for all sensors * - system initialization (?)
*! Now most is moved to other files, here will be * - compressor write (and global read) pointers
*! - system initialization * - populating 32-byte interframe data
*! - compressor write (and global read) pointers * - interrupts handling
*! - populating 32-byte interframe data * - tasklets
*! - something for Exif? * - device driver that includes waiting for the next frame regardless of compression
*! - where are histograms? ->histograms.c *
*! - interrupt loop * Copyright (C) 2016 Elphel, Inc.
*! - tasklets *
*! - device driver that includes waiting for the next frame regardless of compression * This program is free software: you can redistribute it and/or modify
*! - anything else? * 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.
*! Copyright (C) 2008 Elphel, Inc. *
*! -----------------------------------------------------------------------------** * This program is distributed in the hope that it will be useful,
*! * but WITHOUT ANY WARRANTY; without even the implied warranty of
*! This program is free software: you can redistribute it and/or modify * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! it under the terms of the GNU General Public License as published by * GNU General Public License for more details.
*! the Free Software Foundation, either version 3 of the License, or *
*! (at your option) any later version. * You should have received a copy of the GNU General Public License
*! * along with this program. If not, see <http://www.gnu.org/licenses/>.
*! 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
*!
*!
*/
//copied from cxi2c.c - TODO:remove unneeded //copied from cxi2c.c - TODO:remove unneeded
...@@ -180,6 +38,9 @@ ...@@ -180,6 +38,9 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/vmalloc.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/system.h>
#include <asm/byteorder.h> // endians #include <asm/byteorder.h> // endians
...@@ -195,6 +56,8 @@ ...@@ -195,6 +56,8 @@
#include <elphel/c313a.h> #include <elphel/c313a.h>
//#include <asm/elphel/fpgaconfa.h> //#include <asm/elphel/fpgaconfa.h>
#include <elphel/exifa.h> #include <elphel/exifa.h>
//#include <elphel/x393_types.h>
#include "x393.h"
//#include "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr //#include "fpgactrl.h" // defines port_csp0_addr, port_csp4_addr
//#include "fpga_sdram.h" // use a single fpga_initSDRAM(void) //#include "fpga_sdram.h" // use a single fpga_initSDRAM(void)
...@@ -210,6 +73,7 @@ ...@@ -210,6 +73,7 @@
//#include "histograms.h" //#include "histograms.h"
//#include "gamma_tables.h" //#include "gamma_tables.h"
#include "quantization_tables.h" #include "quantization_tables.h"
#include "x393_macro.h"
#if ELPHEL_DEBUG #if ELPHEL_DEBUG
#define ELPHEL_DEBUG_THIS 0 #define ELPHEL_DEBUG_THIS 0
...@@ -233,10 +97,38 @@ ...@@ -233,10 +97,38 @@
#define MD13(x) #define MD13(x)
#endif #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 struct image_acq_pd_t image_acq_priv;
static const char elphel_cam_name[] = "elphelcam353";
static volatile int JPEG_wp; static volatile int JPEG_wp;
static volatile int JPEG_rp; static volatile int JPEG_rp;
...@@ -250,17 +142,6 @@ static int fpga_counter_prev=0; /// Previous value of the FPGA transfer counter ...@@ -250,17 +142,6 @@ static int fpga_counter_prev=0; /// Previous value of the FPGA transfer counter
int Photo_MakerNote; int Photo_MakerNote;
} meta_offsets; } 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_wp(void) {return JPEG_wp;}
int camSeqGetJPEG_rp(void) {return JPEG_rp;} int camSeqGetJPEG_rp(void) {return JPEG_rp;}
void camSeqSetJPEG_rp(int p) { void camSeqSetJPEG_rp(int p) {
...@@ -271,42 +152,39 @@ 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_CIRCBUFSIZE):0)+ get_globalParam(G_CIRCBUFRP))
- get_globalParam(G_CIRCBUFWP)); - 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? 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 static struct sensorproc_t s_sensorproc; // sensor parameters and functions to call
struct sensorproc_t * sensorproc = NULL; struct sensorproc_t * sensorproc = NULL;
//EXPORT_SYMBOL_GPL(sensorproc); //EXPORT_SYMBOL_GPL(sensorproc);
//wait_queue_head_t image_acq_wait_queue; /// queue for the sensor frame interrupts //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); void tasklet_fpga_function(unsigned long arg);
/** /**
* @brief Copy sensorproc structure, needed for multisensor board to be able to replace some of the functions * @brief Copy #sensorproc structure, needed for multisensor board to be able
* @param copy - pointer to a copy structure * to replace some of the functions
* @return pointer to a copy structure * @param[in] copy pointer to a copy structure
* @return pointer to a \b copy structure
*/ */
struct sensorproc_t * copy_sensorproc (struct sensorproc_t * copy)
struct sensorproc_t * copy_sensorproc (struct sensorproc_t * copy) { {
memcpy(copy, sensorproc, sizeof(struct sensorproc_t)); /// copy sensor functions /** copy sensor functions */
return copy; memcpy(copy, sensorproc, sizeof(struct sensorproc_t));
return copy;
} }
#ifdef TEST_DISABLE_CODE //#ifdef TEST_DISABLE_CODE
/// When should it be called? /// When should it be called?
//int init_sensor(void); //int init_sensor(void);
...@@ -352,8 +230,6 @@ int init_FPGA(void) { //will check FPGA version, init SDRAM (if needed) and sens ...@@ -352,8 +230,6 @@ int init_FPGA(void) { //will check FPGA version, init SDRAM (if needed) and sens
/// ///
int init_acq_sensor(void); 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 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) { ...@@ -533,6 +409,33 @@ static irqreturn_t elphel_FPGA_interrupt(int irq, void *dev_id) {
return IRQ_HANDLED; 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 * @brief Tasklet - software interrupt
* lower priority tasks * lower priority tasks
...@@ -655,7 +558,7 @@ GLOBALPARS(0x1044)=thisFrameNumber; ...@@ -655,7 +558,7 @@ GLOBALPARS(0x1044)=thisFrameNumber;
#endif #endif
} }
#endif /* TEST_DISABLE_CODE */ //#endif /* TEST_DISABLE_CODE */
/** /**
* @brief resets compressor and buffer pointers * @brief resets compressor and buffer pointers
...@@ -697,85 +600,118 @@ void camera_interrupts (int on) { ...@@ -697,85 +600,118 @@ void camera_interrupts (int on) {
intr_mask.ext = on ? 1 : 0; intr_mask.ext = on ? 1 : 0;
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
#endif /* TEST_DISABLE_CODE */ #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); //EXPORT_SYMBOL_GPL(camera_interrupts);
/**
int image_acq_open(struct inode *inode, struct file *filp) ; * @brief sensor_common driver probing function
int image_acq_release(struct inode *inode, struct file *filp) ; * @param[in] pdev pointer to \b platform_device structure
loff_t image_acq_fops_lseek (struct file * file, loff_t offset, int orig) ; * @return 0 on success or negative error code otherwise
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 int image_acq_init(struct platform_device *pdev)
{
static struct file_operations image_acq_fops = { int i;
owner: THIS_MODULE, int res;
llseek: image_acq_fops_lseek, unsigned int irq;
// read: image_acq_fops_read, struct device *dev = &pdev->dev;
write: image_acq_fops_write, const struct of_device_id *match;
// ioctl: image_acq_ioctl, const char **frame_sync_irq_names = { "frame_sync_irq_0", "frame_sync_irq_1",
open: image_acq_open, "frame_sync_irq_2", "frame_sync_irq_3" };
mmap: image_acq_mmap, const char **compressor_irq_names = { "compr_irq_0", "compr_irq_1",
release: image_acq_release "compr_irq_2", "compr_irq_3"
}; };
static int __init image_acq_init(void) {
int res; /* sanity check */
sensorproc= &s_sensorproc; match = of_match_device(elphel393_sensor_of_match, dev);
MDD1(printk("sensorproc=0x%x\n",(int) sensorproc)); if (!match)
//init_ccam_dma_buf_ptr(); /// should it be done here? Why not in circbuf.c? return -EINVAL;
/// init_histograms(); - other initializations?
res = register_chrdev(ELPHEL_MAJOR, elphel_cam_name, &image_acq_fops); sensorproc= &s_sensorproc;
if(res < 0) { MDD1(printk("sensorproc=0x%x\n",(int) sensorproc));
printk(KERN_ERR "image_acq_init: couldn't get a major number %d.\n",ELPHEL_MAJOR);
return res; 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 #ifdef TEST_DISABLE_CODE
if(request_irq(EXT_INTR_VECT, if(request_irq(EXT_INTR_VECT,
elphel_FPGA_interrupt, elphel_FPGA_interrupt,
SA_INTERRUPT, // SA_SHIRQ | SA_INTERRUPT if it is a shared one. SA_INTERRUPT, // SA_SHIRQ | SA_INTERRUPT if it is a shared one.
"Elphel FPGA interrupts", "Elphel FPGA interrupts",
NULL)) { NULL)) {
printk(KERN_ERR "Can't allocate Elphel FPGA interrupts"); printk(KERN_ERR "Can't allocate Elphel FPGA interrupts");
return -EBUSY; return -EBUSY;
} }
#endif #endif
printk("Elphel FPGA interrupts initialized\n"); printk("Elphel FPGA interrupts initialized\n");
// init_waitqueue_head(&image_acq_wait_queue); // init_waitqueue_head(&image_acq_wait_queue);
// DMA_buf_start=x313_dma_init(); // DMA_buf_start=x313_dma_init();
MDD1(printk("reset_compressor()\n")); MDD1(printk("reset_compressor()\n"));
reset_compressor(); /// reset compressor and buffer pointers reset_compressor(); /// reset compressor and buffer pointers
MDD1(printk("x313_dma_init()\n")); MDD1(printk("x313_dma_init()\n"));
//x313_dma_init(); /// initialize ETRAX FS DMA //x313_dma_init(); /// initialize ETRAX FS DMA
MDD1(printk("init_pgm_proc ()\n")); MDD1(printk("init_pgm_proc ()\n"));
//init_pgm_proc (); /// setup pointers to functions (not sensor-specific) //init_pgm_proc (); /// setup pointers to functions (not sensor-specific)
MDD1(printk("reset_qtables()\n")); MDD1(printk("reset_qtables()\n"));
reset_qtables(); /// force initialization at next access reset_qtables(); /// force initialization at next access
printk(X3X3_ELPHEL_DRIVER_NAME" - %d\n",ELPHEL_MAJOR);
return 0; return 0;
} }
static int image_acq_stop(struct platform_device *pdev)
int image_acq_open(struct inode *inode, struct file *filp) { {
return 0; 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 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_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>."); 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*/ /* These macro were removed from sensor_common.h*/
#define X313_LENGTH_MASK 0xff000000 #define X313_LENGTH_MASK 0xff000000
...@@ -7,4 +14,4 @@ ...@@ -7,4 +14,4 @@
#define X313_BUFFSUB(x,y) (((x)>=(y))? ((x)-(y)) : ((x)+ (CCAM_DMA_SIZE-(y)))) #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)))) #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 @@ ...@@ -9,8 +9,8 @@
//#define ELPHEL_DEBUG 0 //global debug on/off in multiple files //#define ELPHEL_DEBUG 0 //global debug on/off in multiple files
//#define ELPHEL_DEBUG_STARTUP 000a4c00 ; //#define ELPHEL_DEBUG_STARTUP 000a4c00 ;
//#define ELPHEL_DEBUG_STARTUP 0 ; // removed - add write to fpga init script //#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 0 //global debug on/off in multiple files
#define ELPHEL_DEBUG 1 //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 ELPHEL_DEBUG_DELAY 100000 //delay after some printk-s
#define ELP_KERR(x) printk("%s:%d:%s: ERROR ",__FILE__,__LINE__,__FUNCTION__);x #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 #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