Commit 2b37bcdf authored by Mikhail Karpenko's avatar Mikhail Karpenko

Kernel loads built in circbuf

circbuf driver was converted to platform driver, some unused lines of
code were commented out to delete them in the future. Currently the
driver is built in into kernel as I could not easily split it to
separate external modules due to various dependencies and issues during
linking stage.
parent 7dbb2bc0
......@@ -7,14 +7,15 @@ obj-$(CONFIG_ELPHEL393) += elphel393-mem.o
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) += quantization_tables.o
#obj-$(CONFIG_ELPHEL393) += circbuf.o jpeghead.o
obj-$(CONFIG_ELPHEL393) += framepars.o
obj-$(CONFIG_ELPHEL393) += sensor_common.o
obj-$(CONFIG_ELPHEL393) += quantization_tables.o
obj-$(CONFIG_ELPHEL393) += circbuf.o jpeghead.o
framepars-objs := sensor_common.o
sensor_common-objs := quantization_tables.o
circbuf-objs := jpeghead.o
obj-$(CONFIG_ELPHEL393_EXTERNAL) += framepars.o
obj-$(CONFIG_ELPHEL393_EXTERNAL) += sensor_common.o
obj-$(CONFIG_ELPHEL393_EXTERNAL) += circbuf.o
\ No newline at end of file
#fpars-y := framepars.o sensor_common.o
#sc-y := sensor_common.o quantization_tables.o framepars.o
#cbuf-y := circbuf.o fpars.o sc.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
......@@ -151,7 +151,9 @@
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
//#include <asm/system.h>
//#include <asm/arch/memmap.h>
......@@ -180,6 +182,9 @@
#include "jpeghead.h"
#include "circbuf.h"
#include "exif.h"
#include "x313_macro.h"
#include <elphel/elphel393-mem.h>
#if ELPHEL_DEBUG
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
#define D19(x) { if (GLOBALPARS(G_DEBUG) & (1 <<19)) {x; } ; }
......@@ -206,27 +211,42 @@
//#define MD11(x) printk("%s:%d:",__FILE__,__LINE__);x
#define MD11(x)
static const struct of_device_id elphel393_circbuf_of_match[];
/* really huge static DMA buffer (1288+8)*1032/3=445824 long-s */
// DMA_SIZE - in 32-bit words, not bytes
//static unsigned long ccam_dma_buf[CCAM_DMA_SIZE + (PAGE_SIZE>>2)] __attribute__ ((aligned (PAGE_SIZE)));
static unsigned long *ccam_dma_buf = NULL;
//!Without "static" system hangs after "Uncompressing Linux...
unsigned long * ccam_dma_buf_ptr = NULL;
unsigned long * ccam_dma = NULL; //! still used in autoexposure or something - why is in needed there?
//EXPORT_SYMBOL_GPL(ccam_dma_buf_ptr);
//unsigned long * ccam_dma = NULL; //! still used in autoexposure or something - why is in needed there?
int init_ccam_dma_buf_ptr(void) {
dma_addr_t *dma_handle;
int init_ccam_dma_buf_ptr(struct platform_device *pdev) {
dma_addr_t dma_handle;
const size_t dma_size = (CCAM_DMA_SIZE + (PAGE_SIZE >> 2)) * sizeof(int);
struct device *dev = &pdev->dev;
//ccam_dma_buf_ptr = ccam_dma_buf;
//ccam_dma = ccam_dma_buf; //&ccam_dma_buf[0]; Use in autoexposure
ccam_dma_buf_ptr = dma_alloc_coherent(NULL, (CCAM_DMA_SIZE + (PAGE_SIZE >> 2)), dma_handle, GFP_KERNEL);
if (!ccam_dma_buf_ptr) {
return -ENOMEM;
} else {
printk(KERN_DEBUG "%s: dma memory allocated at 0x%08x", __func__, dma_handle);
}
// use Elphel_buf if it was allocated
if (pElphel_buf != NULL) {
ccam_dma_buf_ptr = pElphel_buf->vaddr;
dma_handle = pElphel_buf->paddr;
dev_info(dev, "using %d bytes of DMA memory from pElphel_buf at address 0x%08p", pElphel_buf->size * PAGE_SIZE, dma_handle);
} else {
ccam_dma_buf_ptr = dmam_alloc_coherent(dev, dma_size, &dma_handle, GFP_KERNEL);
if (!ccam_dma_buf_ptr) {
dev_err(dev, "unable to allocate DMA buffer\n");
return -ENOMEM;
} else {
dev_info(dev, "%d bytes of DMA memory allocated at address 0x%08p", dma_size , dma_handle);
}
}
ccam_dma_buf = ccam_dma_buf_ptr;
return 0;
}
extern struct interframe_params_t frame_params; // cc353.c
//extern struct interframe_params_t frame_params; // cc353.c
/*!======================================================================================
*! Wait queue for the processes waiting for a new frame to appear in the circular buffer
*!======================================================================================*/
......@@ -304,10 +324,18 @@ int circbuf_all_release(struct inode *inode, struct file *filp) {
loff_t circbuf_all_lseek(struct file * file, loff_t offset, int orig) {
struct circbuf_pd * privData;
privData = (struct circbuf_pd *) file->private_data;
struct interframe_params_t *fp = NULL;
int rp;
MD10(printk("circbuf_all_lseek, minor=0x%x\n",privData-> minor));
switch (privData->minor) {
case CMOSCAM_MINOR_CIRCBUF : return circbuf_lseek (file, offset, orig);
case CMOSCAM_MINOR_JPEAGHEAD : return jpeghead_lseek (file, offset, orig);
case CMOSCAM_MINOR_JPEAGHEAD :
if (orig == SEEK_END && offset > 0) {
rp= (offset >>2) & (~7); // convert to index to long, align to 32-bytes
fp = (struct interframe_params_t *) &ccam_dma_buf_ptr[X313_BUFFSUB(rp, 8)]; //! 32 bytes before the frame pointer, may roll-over to the end of ccam_dma_buf_ptr
}
return jpeghead_lseek (file, offset, orig, fp);
case CMOSCAM_MINOR_HUFFMAN : return huffman_lseek (file, offset, orig);
default: return -EINVAL;
}
......@@ -680,10 +708,18 @@ unsigned int circbuf_poll (struct file *file, poll_table *wait) {
return 0; // nothing ready
}
static int __init circbuf_all_init(void) {
static int circbuf_all_init(struct platform_device *pdev)
{
int res;
printk(KERN_DEBUG "Loading %s", __func__);
struct device *dev = &pdev->dev;
const struct of_device_id *match;
/* sanity check */
match = of_match_device(elphel393_circbuf_of_match, dev);
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) {
......@@ -691,23 +727,58 @@ static int __init circbuf_all_init(void) {
return res;
}
res = init_ccam_dma_buf_ptr();
res = init_ccam_dma_buf_ptr(pdev);
if (res < 0) {
printk(KERN_ERR "%s: ERROR allocating coherent DMA buffer\n", __func__);
dev_err(dev, "ERROR allocating coherent DMA buffer\n");
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);
return 0;
}
static int circbuf_remove(struct platform_device *pdev)
{
unregister_chrdev(CIRCBUF_MAJOR, "circbuf_operations");
return 0;
}
static const struct of_device_id elphel393_circbuf_of_match[] = {
{ .compatible = "elphel,elphel393-circbuf-1.00" },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, elphel393_circbuf_of_match);
static struct platform_driver elphel393_circbuf = {
.probe = circbuf_all_init,
.remove = circbuf_remove,
.driver = {
.name = CIRCBUF_DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = elphel393_circbuf_of_match,
},
};
module_platform_driver(elphel393_circbuf);
module_init(circbuf_all_init);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(CIRCBUF_DRIVER_NAME);
......@@ -25,12 +25,13 @@ ssize_t circbuf_read (struct file * file, char * buf, size_t count, loff_t
int circbuf_mmap (struct file *file, struct vm_area_struct *vma);
unsigned int circbuf_poll (struct file *file, poll_table *wait);
int init_ccam_dma_buf_ptr(void);
//int init_ccam_dma_buf_ptr(void);
/*!======================================================================================
*! Wait queue for the processes waiting for a new frame to appear in the circular buffer
*!======================================================================================*/
extern wait_queue_head_t circbuf_wait_queue;
unsigned long *ccam_dma_buf_ptr;
extern unsigned long *ccam_dma_buf_ptr;
//unsigned long *circbuf_get_ccam_ptr(void);
#endif /* _CIRCBUF_H */
......@@ -446,7 +446,7 @@ static struct of_device_id elphel393_mem_of_match[] = {
{ .compatible = "elphel,elphel393-mem-1.00", },
{ /* end of table */}
};
MODULE_DEVICE_TABLE(of, elphel393_pwr_of_match);
MODULE_DEVICE_TABLE(of, elphel393_mem_of_match);
static struct platform_driver elphel393_mem = {
.probe = elphel393_mem_probe,
......
......@@ -291,7 +291,7 @@
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)
#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)
struct framepars_all_t *frameparsall=NULL; /// - will be mmap-ed
struct framepars_t *framepars= NULL; ///< getting rid of static to be able to use extern
......@@ -302,8 +302,6 @@ unsigned long *multiSensIndex= NULL; /// index for per-sensor alternat
unsigned long *multiSensRvrsIndex=NULL; /// reverse index (to parent) for the multiSensIndex
wait_queue_head_t framepars_wait_queue; /// used to wait for the frame to be acquired
extern struct sensorproc_t * sensorproc;
/**
* @brief file private data
*/
......@@ -434,7 +432,7 @@ int initMultiPars(void) {
inline unsigned long get_imageParamsThis (int n) {
return framepars[thisFrameNumber & PARS_FRAMES_MASK].pars[n] ;
}
EXPORT_SYMBOL_GPL(get_imageParamsThis);
//EXPORT_SYMBOL_GPL(get_imageParamsThis);
/**
* @brief reads parameters from the previous frame (matching hardware index) - used to determine if historam was needed
......@@ -464,7 +462,7 @@ inline void set_imageParamsThis (int n,unsigned long d) {
inline unsigned long get_globalParam (int n) {
return GLOBALPARS(n) ;
}
EXPORT_SYMBOL_GPL(get_globalParam);
//EXPORT_SYMBOL_GPL(get_globalParam);
/**
* @brief sets global (not related to particular frames) parameters
* @param n number of a parameter to set (numbers start from FRAMEPAR_GLOBALS)
......@@ -474,7 +472,7 @@ EXPORT_SYMBOL_GPL(get_globalParam);
inline void set_globalParam (int n, unsigned long d) {
GLOBALPARS(n)=d;
}
EXPORT_SYMBOL_GPL(set_globalParam);
//EXPORT_SYMBOL_GPL(set_globalParam);
/**
* @brief set same parameters in all frames
......
......@@ -4,7 +4,7 @@
//extern struct framepars_t (*framepars)[PARS_FRAMES];
extern struct framepars_t *framepars;
extern struct framepars_past_t *pastpars;
unsigned long *globalPars;
extern unsigned long *globalPars;
extern unsigned long *multiSensIndex;
extern unsigned long *multiSensRvrsIndex;
......@@ -60,4 +60,5 @@ inline void processParsSeq (struct sensorproc_t * sensorproc, int frame8, int ma
void processPars (struct sensorproc_t * sensorproc, int frame8, int maxahead);
///*** TODO: Add option (flag?) to write "single" (like single compress, single sensor) so it will not make all the next frames "single"
#endif
......@@ -96,8 +96,9 @@
//#include "x3x3.h"
//#include "cc3x3.h"
//#include "cxdma.h"
#include "circbuf.h"
#include "sensor_common.h"
//#include "circbuf.h"
//#include "sensor_common.h"
#include "x313_macro.h"
#include "exif.h"
#if ELPHEL_DEBUG
......@@ -118,7 +119,6 @@
#define JPEG_HEADER_MAX_SIZE 0x300
static int huffman_fpga_programmed=0;
extern unsigned long *ccam_dma_buf_ptr;
/// All huffman tabels data to be read/written from the application
static struct huff_tables_t {
......@@ -151,10 +151,8 @@ static struct huff_tables_t {
*/
int qtables_create(struct interframe_params_t * params, unsigned char * buf) {
MDF18(printk("params->quality2=0x%x",params->quality2));
#ifdef TEST_DISABLE_CODE
int rslt=get_qtable(params->quality2, &buf[0], &buf[64]); /// will copy both quantization tables
if (rslt <0) return rslt; /// bad quality table
#endif
return 128;
}
/**
......@@ -238,10 +236,8 @@ int jpegheader_create(struct interframe_params_t * params, unsigned char * buf)
memcpy((void *) &buf[0], (void *) jfif1, sizeof (jfif1)); /// including DQT0 header
memcpy((void *) &buf[header_cqtable_hd], (void *) jfif2, sizeof (jfif2)); /// DQT1 header
#ifdef TEST_DISABLE_CODE
rslt=get_qtable(params->quality2, &buf[header_yqtable], &buf[header_cqtable]); /// will copy both quantization tables
if (rslt <0) return rslt; /// bad quality table
#endif
bp=header_sof;
buf[bp++]=0xff; buf[bp++]=0xc0;
buf[bp++]=0; /// high byte length - always 0
......@@ -388,11 +384,12 @@ EXPORT_SYMBOL_GPL(jpeghead_open);
*!================================================================*/
loff_t jpeghead_lseek(struct file * file, loff_t offset, int orig){
loff_t jpeghead_lseek(struct file * file, loff_t offset, int orig,
struct interframe_params_t *fp){
int rp;
struct jpeghead_pd * privData;
struct interframe_params_t * fp;
//struct interframe_params_t * fp;
privData = (struct jpeghead_pd *) file->private_data;
MDF17(printk("orig=%d, offst=0x%x\n",orig,(int) offset));
......@@ -409,8 +406,11 @@ loff_t jpeghead_lseek(struct file * file, loff_t offset, int orig){
file->f_pos = privData->size + offset;
} else { //! New functionality
file->f_pos=0; // anyway reset it to 0
/*
* move below two lines to circbuf_all_lseek to remove ccam_dma_buf_ptr and simplify dependencies
rp= (offset >>2) & (~7); // convert to index to long, align to 32-bytes
fp = (struct interframe_params_t *) &ccam_dma_buf_ptr[X313_BUFFSUB(rp, 8)]; //! 32 bytes before the frame pointer, may roll-over to the end of ccam_dma_buf_ptr
*/
if ((fp->signffff != 0xffff) || //! signature is overwritten
((fp->timestamp_sec) & X313_LENGTH_MASK)) return -EINVAL; //! acquisition of this frame is not done yet - length word high byte is non-zero
......
// FILE NAME : jpeghead.h
///Structure used for FPGA data - lower 16 bits - code value, next 5 - code length (1..16).
///Actually FPGA only uses 20 bits, length 0 is interpreted as 16
#ifndef _JPEGHEAD
#define _JPEGHEAD
struct huffman_fpga_code_t {
unsigned short value; /// code value
unsigned short length; /// code length
......@@ -8,7 +12,7 @@ struct huffman_fpga_code_t {
int qtables_create (struct interframe_params_t * params, unsigned char * buf);
int jpegheader_create(struct interframe_params_t * params, unsigned char * buf);
int jpeghead_open (struct inode *inode, struct file *filp); // set filesize
loff_t jpeghead_lseek (struct file * file, loff_t offset, int orig);
loff_t jpeghead_lseek (struct file * file, loff_t offset, int orig, struct interframe_params_t *fp);
ssize_t jpeghead_read (struct file * file, char * buf, size_t count, loff_t *off);
int huffman_open (struct inode *inode, struct file *filp); // set filesize
......@@ -18,7 +22,7 @@ ssize_t huffman_read (struct file * file, char * buf, size_t count, loff_t *of
ssize_t huffman_write (struct file * file, const char * buf, size_t count, loff_t *off);
extern unsigned long * ccam_dma_buf_ptr;
//extern unsigned long * ccam_dma_buf_ptr;
//void init_ccam_dma_buf_ptr(void);
#define JPEG_HEADER_MAXSIZE 0x300
struct jpeghead_pd {
......@@ -36,3 +40,5 @@ void jpeg_htable_init (void);
int jpeg_htable_fpga_encode (void);
void jpeg_htable_fpga_pgm (void);
int jpeg_prep_htable (struct huffman_encoded_t * htable, struct huffman_fpga_code_t * hcodes);
#endif /* _JPEGHEAD */
......@@ -198,7 +198,7 @@ void reset_qtables(void) {
qtable_cache_initialized=0;
qtable_fpga_initialized=0;
}
//EXPORT_SYMBOL_GPL(reset_qtables);
/**
* @brief initialization of quantization tables (direct - JPEG header ones) cache
......@@ -319,6 +319,7 @@ int get_qtable (int quality2, unsigned char *y_tab, unsigned char *c_tab) {
MDF15(if (c_tab) {printk("c_tab\n"); for (i=0;i<64;i++){if ((i & 7)==0) printk("\n");printk(" %02x",(int) c_tab[i]);} printk("\n");});
return rslt;
}
//EXPORT_SYMBOL_GPL(get_qtable);
/**
* @brief initialization of quantization tables (reverse, for the FPGA) cache
......
......@@ -271,9 +271,9 @@ 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);
//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?
......@@ -283,6 +283,7 @@ EXPORT_SYMBOL_GPL(camSeqSetJPEG_rp);
#define X3X3_IMAGEACQ_DRIVER_NAME "Elphel (R) Model 353 Image Acquisition device driver"
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
......@@ -674,7 +675,7 @@ void reset_compressor(void) {
fpga_counter_prev=0;
local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(reset_compressor);
//EXPORT_SYMBOL_GPL(reset_compressor);
/**
* @brief Camera interrupts on/off (currently both in the FPGA and in the CPU)
......@@ -697,7 +698,7 @@ void camera_interrupts (int on) {
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
#endif /* TEST_DISABLE_CODE */
}
EXPORT_SYMBOL_GPL(camera_interrupts);
//EXPORT_SYMBOL_GPL(camera_interrupts);
int image_acq_open(struct inode *inode, struct file *filp) ;
......
......@@ -2,7 +2,7 @@
#define _SENSOR_COMMON_H
//extern struct sensor_t sensor; // current sensor (will be copied to by sensor driver), made external for the cc353.c to read/write i2c
struct sensorproc_t * sensorproc;
extern struct sensorproc_t * sensorproc;
/// IRQ-safe "nice" FPGA table write and histogram read functions - they split the data in chunks of fixed size,
/// disable IRQ, transfer a chunk, then reenable interrupt before proceedg to the next chunk
#define FPGA_TABLE_CHUNK 64 // up to 64 words to send to the table/from histogram on a single IRQ-off transfer
......@@ -16,11 +16,14 @@ int camSeqGetJPEG_wp(void);
int camSeqGetJPEG_rp(void);
void camSeqSetJPEG_rp(int p);
///CIRCBUF macros
extern unsigned long * ccam_dma_buf_ptr;
//extern unsigned long * ccam_dma_buf_ptr;
/* move these lines to x313_macro.h
#define X313_LENGTH_MASK 0xff000000
#define X313_PADDED_FRAME(x)((((x)+67+CCAM_MMAP_META ) >>2) & 0xfffffff8)
#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))))
*/
//int init_FPGA(void); /// can be initialized only after FPGA is configured, not at module init (NOTE was static??)
///can be verified with if (!X313_IS_SDRAM_ON)
......
#ifndef _X313_MACRO
#define _X313_MACRO
/* These macro were removed from sensor_common.h*/
#define X313_LENGTH_MASK 0xff000000
#define X313_PADDED_FRAME(x)((((x)+67+CCAM_MMAP_META ) >>2) & 0xfffffff8)
#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 */
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