Commit 04b6f91f authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

started implementing lseek

parent b844e2fa
......@@ -46,6 +46,21 @@
#define MEMBRIDGE_CMD_IRQ_EN 0x3
// like in framepars.c
// lock membridge run
#undef LOCK_BH_PROCESSPARS
#define LOCK_BH_FRAMEPARS
#ifdef LOCK_BH_FRAMEPARS
#define FLAGS_IBH
#define LOCK_IBH(x) spin_lock_bh(x)
#define UNLOCK_IBH(x) spin_unlock_bh(x)
#else
#define FLAGS_IBH unsigned long flags;
#define LOCK_IBH(x) spin_lock_irqsave(x,flags)
#define UNLOCK_IBH(x) spin_unlock_irqrestore(x,flags)
#endif
static const struct of_device_id elphel393_videomem_of_match[];
static struct device *g_dev_ptr; ///< Global pointer to basic device structure. This pointer is used in debugfs output functions
wait_queue_head_t videomem_wait_queue;
......@@ -87,10 +102,6 @@ static struct elphel_video_buf_t buffer_settings = { ///< some default settings,
static int membridge_sensor_port = 0; // 0..3
static int membridge_direction = 0; // 0 - from pl to ps, 1 - from ps to pl
// Membridge can be only accessed by a single source - TODO: use this lock
static bool membridge_lock = false;
static int hardware_initialized = 0;
/** Setup memory bridge system memory */
......@@ -662,12 +673,85 @@ u16 get_memchannel_priority(int chn) ///< Memory channel (0..16). When usi
/** @brief Videomem buffer private data */
struct raw_priv_t {
int minor; ///< device file minor number
int sensor_num; ///< sensor number
unsigned long *buf_ptr; ///< pointer to raw buffer memory region
unsigned long buf_size; ///< circular region size in bytes
unsigned long buf_size32; ///< circular region size in dwords
dma_addr_t phys_addr; ///< physical address of memory region reported by memory driver
};
int membridge_start(struct file * file){
struct raw_priv_t * privData = (struct raw_priv_t*) file -> private_data;
int p_color, p_pf_height;
int width_marg, height_marg, width_bursts;
int frame_number;
// no need
frame_number = GLOBALPARS(privData->sensor_num,G_THIS_FRAME) & PARS_FRAMES_MASK;
//calculate things
//if (frame16 >= PARS_FRAMES) return -1; // wrong frame
width_marg = get_imageParamsThis(privData->sensor_num,P_ACTUAL_WIDTH);
height_marg = get_imageParamsThis(privData->sensor_num,P_ACTUAL_HEIGHT);
p_color = get_imageParamsThis(membridge_sensor_port,P_COLOR);
p_pf_height = get_imageParamsThis(privData->sensor_num,P_PF_HEIGHT);
switch(p_color){
case COLORMODE_COLOR:
case COLORMODE_COLOR20:
width_marg += (2 * COLOR_MARGINS);
if ((p_pf_height & 0xffff)==0) { // not a photofinish
height_marg += (2 * COLOR_MARGINS);
}
break;
}
width_bursts = (width_marg >> 4) + ((width_marg & 0xf) ? 1 : 0);
/** shorter version: */
//width_bursts = (width_marg+0xf)>>4;
setup_membridge_memory(privData->sensor_num, ///< sensor port number (0..3)
0, ///< 0 - from fpga mem to system mem, 1 - otherwise
width_bursts, ///< 13-bit - in 8*16=128 bit bursts
height_marg, ///< 16-bit window height (in scan lines)
0, ///< 13-bit window left margin in 8-bursts (16 bytes)
0, ///< 16-bit window top margin (in scan lines)
0, ///< START X ...
0, ///< START Y ...
DIRECT, ///< how to apply commands - directly or through channel sequencer
frame_number); ///< Frame number the command should be applied to (if not immediate mode)
// setup membridge system memory - everything is in QW
setup_membridge_system_memory(
(privData->phys_addr)>>3,
(privData->buf_size)>>3,
0, // start offset?
(width_bursts<<1)*height_marg,
(width_bursts<<1)
);
control_membridge_memory(membridge_sensor_port,1,DIRECT,frame_number);
//NOTES:
//// get this frame number
//#define thisFrameNumber(p) GLOBALPARS(p,G_THIS_FRAME) // Current frame number (may lag from the hardware)
//#define thisCompressorFrameNumber(p) GLOBALPARS(p,G_COMPRESSOR_FRAME) // Current compressed frame number (lags from thisFrameNumber)
//// wait for certain frame number
// wait_event_interruptible(aframepars_wait_queue[sensor_port], getThisFrameNumber(sensor_port) >= target_frame);
//// get frame sizes
//unsigned long get_imageParamsPast(int sensor_port, int n, int frame);
return 0;
}
/**
* @brief This function handles read operations for raw files.
* @param[in] file pointer to <em>struct file</em>
......@@ -730,10 +814,62 @@ ssize_t vm_read(struct file *file, char *buf, size_t count, loff_t *off)
// TODO: Implement file operations using membridge for both raw memory access and per-channel image raw (including 16-bit)
//static int videomem_open (struct inode *inode, struct file *filp) {return 0;}
//static int videomem_release (struct inode *inode, struct file *filp) {return 0;}
static loff_t videomem_lseek (struct file * file, loff_t offset, int orig) {return 0;}
//static loff_t videomem_lseek (struct file * file, loff_t offset, int orig) {return 0;}
//static ssize_t videomem_read (struct file * file, char * buf, size_t count, loff_t *off) {return 0;}
static ssize_t videomem_write (struct file * file, const char * buf, size_t count, loff_t *off) {return 0;}
/**
* @brief Driver LSEEK method (and execute commands)
* - lseek (SEEK_SET, value) - set absolute frame number
* - lseek (SEEK_CUR, value) - set frame number relative to the current frame number (thisFrameNumber),
* - lseek (SEEK_CUR, 0) - (used by ftell()) DOES NOT modify file pointer, returns thisFrameNumber,
* - lseek (SEEK_END, value <= 0) - do nothing?, do not modify file pointer
* - lseek (SEEK_END, value > 0) - execute commands, do not modify file pointer (and actually use it - frame number the command applies to)
* - no commands yet
* @param file
* @param offset
* @param orig SEEK_SET, SEEK_CUR or SEEK_SET END
* @return file position (absolute frame number)
*/
static loff_t videomem_lseek(struct file * file, loff_t offset, int orig){
unsigned long target_frame;
struct raw_priv_t * privData = (struct raw_priv_t*) file -> private_data;
int sensor_port = privData->sensor_num;
//sec_usec_t sec_usec;
int res;
pr_debug("(videomem_lseek) offset=0x%x, orig=0x%x, sensor_port = %d\n", (int)offset, (int)orig, sensor_port);
switch (orig) {
case SEEK_SET:
file->f_pos = offset;
break;
case SEEK_CUR:
if (offset == 0) return getThisFrameNumber(sensor_port); // do not modify frame number
file->f_pos = getThisFrameNumber(sensor_port) + offset; // modifies frame number, but it is better to use absolute SEEK SET
break;
case SEEK_END:
if (offset <= 0) {
file->f_pos = privData->buf_size + offset;
} else {
switch (offset) {
case LSEEK_VIDEOMEM_START:
// Check lock here:
membridge_start(file);
break;
}
}
break;
default:
return -EINVAL;
}
// roll-over position
//while (file->f_pos < 0) file->f_pos+= circbuf_priv_ptr[chn].buf_size;
//while (file->f_pos > circbuf_priv_ptr[chn].buf_size) file->f_pos-= circbuf_priv_ptr[chn].buf_size;
return file->f_pos;
}
/**
* @brief Process raw buffer file opening.
* @param[in] inode
......@@ -744,10 +880,6 @@ static int videomem_open(struct inode *inode, struct file *filp)
{
struct raw_priv_t *privData;
int p_color, p_pf_height;
int width_marg, height_marg, width_bursts;
int frame_number;
// to enable interrupt
x393_membridge_ctrl_irq_t membridge_irq_en = {.d32=0};
membridge_irq_en.interrupt_cmd = MEMBRIDGE_CMD_IRQ_EN;
......@@ -782,6 +914,8 @@ static int videomem_open(struct inode *inode, struct file *filp)
membridge_sensor_port = 0;
}
privData->sensor_num = membridge_sensor_port;
switch(privData->minor){
case DEV393_MINOR(DEV393_IMAGE_RAW0):
privData->buf_ptr = pElphel_buf->raw_chn0_vaddr;
......@@ -812,96 +946,8 @@ static int videomem_open(struct inode *inode, struct file *filp)
privData->buf_size32 = (privData->buf_size)>>2;
// no need
frame_number = GLOBALPARS(membridge_sensor_port,G_THIS_FRAME) & PARS_FRAMES_MASK;
//calculate things
//if (frame16 >= PARS_FRAMES) return -1; // wrong frame
width_marg = get_imageParamsThis(membridge_sensor_port,P_ACTUAL_WIDTH);
height_marg = get_imageParamsThis(membridge_sensor_port,P_ACTUAL_HEIGHT);
p_color = get_imageParamsThis(membridge_sensor_port,P_COLOR);
p_pf_height = get_imageParamsThis(membridge_sensor_port,P_PF_HEIGHT);
switch(p_color){
case COLORMODE_COLOR:
case COLORMODE_COLOR20:
width_marg += (2 * COLOR_MARGINS);
if ((p_pf_height & 0xffff)==0) { // not a photofinish
height_marg += (2 * COLOR_MARGINS);
}
break;
}
width_bursts = (width_marg >> 4) + ((width_marg & 0xf) ? 1 : 0);
/** shorter version: */
//width_bursts = (width_marg+0xf)>>4;
//int setup_sensor_memory (int num_sensor, ///< sensor port number (0..3)
// int window_width, ///< 13-bit - in 8*16=128 bit bursts
// int window_height, ///< 16-bit window height (in scan lines)
// int window_left, ///< 13-bit window left margin in 8-bursts (16 bytes)
// int window_top, ///< 16-bit window top margin (in scan lines)
// x393cmd_t x393cmd, ///< how to apply commands - directly or through channel sequencer
// int frame16) ///< Frame number the command should be applied to (if not immediate mode)
//setup_sensor_memory (sensor_port, // sensor port number (0..3)
// width_bursts, // 13-bit - in 8*16=128 bit bursts
// height_marg, // 16-bit window height (in scan lines)
// 0, // 13-bit window left margin in 8-bursts (16 bytes)
// 0, // 16-bit window top margin (in scan lines)
// (frame16<0)? ASAP: ABSOLUTE, // how to apply commands - directly or through channel sequencer
// frame16); // Frame number the command should be applied to (if not immediate mode)
// setup membridge fpga memory
//int setup_membridge_memory(
// int num_sensor, ///< sensor port number (0..3)
// int write_direction, ///< 0 - from fpga mem to system mem, 1 - otherwise
// int window_width, ///< 13-bit - in 8*16=128 bit bursts
// int window_height, ///< 16-bit window height (in scan lines)
// int window_left, ///< 13-bit window left margin in 8-bursts (16 bytes)
// int window_top, ///< 16-bit window top margin (in scan lines)
// int start_x, ///< START X ...
// int start_y, ///< START Y ...
// x393cmd_t x393cmd, ///< how to apply commands - directly or through channel sequencer
// int frame16) ///< Frame number the command should be applied to (if not immediate mode)
setup_membridge_memory(membridge_sensor_port, ///< sensor port number (0..3)
0, ///< 0 - from fpga mem to system mem, 1 - otherwise
width_bursts, ///< 13-bit - in 8*16=128 bit bursts
height_marg, ///< 16-bit window height (in scan lines)
0, ///< 13-bit window left margin in 8-bursts (16 bytes)
0, ///< 16-bit window top margin (in scan lines)
0, ///< START X ...
0, ///< START Y ...
DIRECT, ///< how to apply commands - directly or through channel sequencer
frame_number); ///< Frame number the command should be applied to (if not immediate mode)
// setup membridge system memory - everything is in QW
setup_membridge_system_memory(
(privData->phys_addr)>>3,
(privData->buf_size)>>3,
0, // start offset?
(width_bursts<<1)*height_marg,
(width_bursts<<1)
);
control_membridge_memory(membridge_sensor_port,1,DIRECT,frame_number);
//NOTES:
//// get this frame number
//#define thisFrameNumber(p) GLOBALPARS(p,G_THIS_FRAME) // Current frame number (may lag from the hardware)
//#define thisCompressorFrameNumber(p) GLOBALPARS(p,G_COMPRESSOR_FRAME) // Current compressed frame number (lags from thisFrameNumber)
//// wait for certain frame number
// wait_event_interruptible(aframepars_wait_queue[sensor_port], getThisFrameNumber(sensor_port) >= target_frame);
//// get frame sizes
//unsigned long get_imageParamsPast(int sensor_port, int n, int frame);
// TODO: remove once lseek is tested
membridge_start(filp);
return 0;
}
......
......@@ -38,3 +38,5 @@ int frames_in_buffer_minus_one (int num_sensor);
void memchan_enable (int chn, int enable);
void set_memchannel_priority (int chn, u16 priority);
u16 get_memchannel_priority (int chn);
loff_t videomem_lseek (struct file * file, loff_t offset, int orig);
......@@ -1552,6 +1552,9 @@ struct p_names_t {
#define LSEEK_FSDRAM_RESET 0x01 // re-program FSDRAM (to be programmed again when accessed)
// Videomem/raw image commands
#define LSEEK_VIDEOMEM_START 0x10 // setup and start membridge transfer
#define JPEG_CTRL_MONOCHROME 0x400
#define JPEG_CTRL_MONOCHROME_BLOCKED 0x1000
#define JPEG_CTRL_NOMOSAIC 0x1000
......
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