📄 h3600_backpaq_camera.c
字号:
case VIDEO_PALETTE_GREY: buf += 352 * (288 - 1); break; case VIDEO_PALETTE_YUV422: buf += 352 * (288 - 1) * 2; break; } WRITE_CIF_IMAGE(REVERSE); } else { WRITE_CIF_IMAGE(FORWARD); } return result;}static unsigned long write_qcif( struct frame *frame, unsigned char *buf, int streaming, int flipped, int palette ){ unsigned char *source = frame->data; register int row_width = frame->width; unsigned char temp_buf[176 * 3]; register unsigned char *to; register unsigned char *from; unsigned long result = 0; int source_row = 0; if ( flipped ) { switch (palette) { case VIDEO_PALETTE_RGB24: buf += 176 * (144 - 1) * 3; break; case VIDEO_PALETTE_GREY: buf += 176 * (144 - 1); break; case VIDEO_PALETTE_YUV422: buf += 176 * (144 - 1) * 2; break; } WRITE_QCIF_IMAGE(REVERSE); } else { WRITE_QCIF_IMAGE(FORWARD); } return result;}/* Write the state out into a buffer *//* We've already checked that the buffer is of the required size and has been verified *//* There are a couple of possible states: 1. The frame has already written into shared memory and no processing is required 2. The frame needs to be written to shared memory (buf == NULL) 3. The frame needs to be copied into buf.*/static long process_frame( struct h3600_camera_struct *cam, unsigned char *dest, int index ){ struct frame *frame = &(cam->frame[index]); unsigned long result = 0; int streaming; unsigned char *buf; if ( frame->state == FRAME_DONE ) { CAMERROR("Trying to process DONE frame\n"); return -EINVAL; } if ( dest ) { buf = dest; streaming = 0; } else { buf = cam->frame[index].shared_data; streaming = 1; } switch (cam->mode) { case HC_MODE_RAW: if ( !streaming ) __copy_to_user( buf, frame->data, HC_RAW_BUFFER_SIZE ); result = HC_RAW_BUFFER_SIZE; break; case HC_MODE_RAW_DECIMATED: if ( !streaming ) __copy_to_user( buf, frame->data, HC_DECIMATED_BUFFER_SIZE ); result = HC_DECIMATED_BUFFER_SIZE; break; case HC_MODE_DECIMATION_1: result = write_vga(frame,buf,streaming,cam->params.flip,cam->vpic.palette); break; case HC_MODE_DECIMATION_4: decimate( frame ); /* Intentional fall through */ case HC_MODE_DECIMATION_2: if ( !decimate_mode ) decimate( frame ); result = write_qvga(frame,buf,streaming,cam->params.flip,cam->vpic.palette); break; case HC_MODE_CIF: result = write_cif(frame,buf,streaming,cam->params.flip,cam->vpic.palette); break; case HC_MODE_QCIF: if ( !decimate_mode ) decimate(frame); result = write_qcif(frame,buf,streaming,cam->params.flip,cam->vpic.palette); break; } frame->state = FRAME_DONE; return result;}/****************************************************************************** * * Read data from the camera. This may be run at interrupt time or * from a polling routine. Return "-1" if the FIFO goes over its maximum * depth. Otherwise, return "N" where "N" is the number of bytes left to read. * ******************************************************************************/#define MAXIMUM_FIFO_DEPTH 255static int get_fpga_data( struct h3600_camera_struct *cam ){ struct frame *frame = cam->active; unsigned int *lbuf = (unsigned int *) (frame->data + frame->bytes_read); unsigned short data_avail; int i, count; unsigned short fifo_info = BackpaqSocketCameraFifoInfo; int bytes_per_unit = (fifo_info & BACKPAQ_CAMERA_FIFO_INFO_BPC) >> 8; int fifo_width = (fifo_info & BACKPAQ_CAMERA_FIFO_INFO_WIDTH); unsigned short *sbuf = (unsigned short *) lbuf; volatile unsigned short *fifo_data = (unsigned short *) &(BackpaqSocketCameraFifoData); while (frame->bytes_read < frame->bytes_to_read) { data_avail = BackpaqSocketCameraFifoDataAvail; if ( data_avail >= MAXIMUM_FIFO_DEPTH ) return -1; if ( data_avail > cam->capture_stats.fifo_high ) cam->capture_stats.fifo_high = data_avail; if ( data_avail < cam->capture_stats.fifo_low ) cam->capture_stats.fifo_low = data_avail; if ( data_avail <= 0 ) return frame->bytes_to_read - frame->bytes_read; count = data_avail * bytes_per_unit; if ( count + frame->bytes_read > frame->bytes_to_read ) count = frame->bytes_to_read - frame->bytes_read; if ( fifo_width == 16 ) for ( i = 0 ; i < count ; i+=2 ) /* We read 2 bytes at a time */ *sbuf++ = *fifo_data; else for ( i = 0 ; i < count ; i+=4 ) *lbuf++ = BackpaqSocketCameraFifoData; frame->bytes_read += i; } return frame->bytes_to_read - frame->bytes_read;}/****************************************************************************** * * Interrupt routines * ******************************************************************************/#define ENABLE_OPT_INT(x) \ BackpaqSocketFPGAInterruptMask &= ~(x)#define DISABLE_OPT_INT(x) \ BackpaqSocketFPGAInterruptMask |= (x)#define READ_OPT_INT(x) \ BackpaqSocketFPGAInterruptStatus & (x) \ & ~BackpaqSocketFPGAInterruptMask#define ENABLE_VBLANK_INT ENABLE_OPT_INT(BACKPAQ_SOCKET_INT_VBLANK)#define DISABLE_VBLANK_INT DISABLE_OPT_INT(BACKPAQ_SOCKET_INT_VBLANK)#define READ_VBLANK_INT READ_OPT_INT(BACKPAQ_SOCKET_INT_VBLANK)#define ENABLE_FIFO_INT ENABLE_OPT_INT(BACKPAQ_SOCKET_INT_FIFO)#define DISABLE_FIFO_INT DISABLE_OPT_INT(BACKPAQ_SOCKET_INT_FIFO)#define READ_FIFO_INT READ_OPT_INT(BACKPAQ_SOCKET_INT_FIFO)#define ENABLE_BOTH_INT ENABLE_OPT_INT(BACKPAQ_SOCKET_INT_FIFO | BACKPAQ_SOCKET_INT_VBLANK)#define DISABLE_BOTH_INT DISABLE_OPT_INT(BACKPAQ_SOCKET_INT_FIFO | BACKPAQ_SOCKET_INT_VBLANK)#define READ_BOTH_INT READ_OPT_INT(BACKPAQ_SOCKET_INT_FIFO | BACKPAQ_SOCKET_INT_VBLANK)static void capture_buffer_complete( struct h3600_camera_struct *cam ){ cam->active->state = FRAME_FULL; cam->active = cam->active->next; cam->capture_stats.complete_frames++; /* Now, branch based on our state */ switch (cam->state) { case HC_V4L_IDLE: CAMERROR("Capture buffer complete when in IDLE state\n"); break; case HC_V4L_GRABBING: wake_up_interruptible(&cam->capq); DISABLE_BOTH_INT; cam->capture_state = CAPTURE_OFF; break; case HC_V4L_STREAMING: wake_up_interruptible(&cam->capq); break; }} static void fpga_fifo_interrupt( struct h3600_camera_struct *cam ){ int retval; DISABLE_FIFO_INT; /* We must re-enable FIFO for the appropriate states */ cam->capture_stats.fifo_count++; switch (cam->capture_state) { case CAPTURE_OFF: CAMERROR(": FIFO interrupt when capture is off?!?!\n"); break; case CAPTURE_WAIT_FOR_REFRESH: CAMERROR(": FIFO interrupt when capture is waiting for VBLANK!\n"); break; case CAPTURE_WAIT_FOR_FIFO: ENABLE_VBLANK_INT; /* No matter what, we're interested in VBLANK again */ if ( !cam->active ) { /* No buffer! */ cam->capture_state = CAPTURE_WAIT_FOR_REFRESH; cam->capture_stats.ef_no_capture_buffer++; return; /* The FIFO_INT is still disabled */ } cam->capture_state = CAPTURE_ACTIVE; cam->active->state = FRAME_ACTIVE; /* Deliberate fall-through */ case CAPTURE_ACTIVE: retval = get_fpga_data(cam); if ( retval < 0 ) { cam->active->bytes_read = 0; cam->active->state = FRAME_PENDING; cam->capture_state = CAPTURE_WAIT_FOR_REFRESH; cam->capture_stats.ef_fifo_overrun++; return; /* The FIFO_INT is still disabled */ } else if ( retval > 0 ) ENABLE_FIFO_INT; /* More data still to be read */ else { cam->capture_state = CAPTURE_WAIT_FOR_REFRESH; capture_buffer_complete( cam ); } break; }}static void fpga_vblank_interrupt( struct h3600_camera_struct *cam ){ int retval; cam->capture_stats.vblank_count++; switch (cam->capture_state) { case CAPTURE_WAIT_FOR_REFRESH: ENABLE_FIFO_INT; cam->capture_state = CAPTURE_WAIT_FOR_FIFO; break; case CAPTURE_WAIT_FOR_FIFO: cam->capture_stats.ef_extra_vblank++; break; case CAPTURE_ACTIVE: /* Suck in the last bit of data */ DISABLE_FIFO_INT; /* Shut off the FIFO interrupt */ retval = get_fpga_data(cam); if ( retval < 0 ) { cam->active->bytes_read = 0; cam->active->state = FRAME_PENDING; cam->capture_state = CAPTURE_WAIT_FOR_FIFO; cam->capture_stats.ef_fifo_overrun++; ENABLE_FIFO_INT; } else if ( retval > 0 ) { cam->active->bytes_read = 0; cam->active->state = FRAME_PENDING; cam->capture_state = CAPTURE_WAIT_FOR_FIFO; cam->capture_stats.ef_incomplete_frames++; ENABLE_FIFO_INT; } else { cam->capture_state = CAPTURE_WAIT_FOR_FIFO; ENABLE_FIFO_INT; capture_buffer_complete( cam ); } break; case CAPTURE_OFF: CAMERROR(": Received VBLANK interrupt when capture was off\n"); break; }}static void fpga_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct h3600_camera_struct *cam = (struct h3600_camera_struct *) dev_id; unsigned short irq_value = READ_BOTH_INT; if (!cam ) { printk(KERN_ALERT __FILE__ ": interrupt %d without valid cam\n",irq); return; } if ( irq != IRQ_GPIO_H3600_OPT_IRQ ) { printk(KERN_ALERT __FILE__ ": Unknown IRQ %d\n",irq); return; } /* Handle the FIFO interrupt */ if ( irq_value & BACKPAQ_SOCKET_INT_FIFO ) fpga_fifo_interrupt(cam); /* Handle the VBLANK interrupt */ if ( irq_value & BACKPAQ_SOCKET_INT_VBLANK ) fpga_vblank_interrupt(cam); /* Do some sanity checking */ if ( cam->state == HC_V4L_GRABBING && cam->capture_stats.complete_frames == 0 && ( cam->capture_stats.ef_extra_vblank + cam->capture_stats.ef_fifo_overrun + cam->capture_stats.ef_incomplete_frames + cam->capture_stats.ef_no_capture_buffer ) >= 3 ) { /* Too many errors...abort the GRAB */ wake_up_interruptible(&cam->capq); DISABLE_BOTH_INT; cam->capture_state = CAPTURE_OFF; } GEDR = GPIO_H3600_OPT_IRQ; /* Clear the interrupt */}/****************************************************************************** * * Turn on and off capture states * ******************************************************************************//* Add this capture buffer to the "pending" list *//* Call this with interrupts disabled */static int queue_capture_buffer( struct h3600_camera_struct *cam, int index ){ int result = 0; struct frame *frame = &(cam->frame[index]); switch (frame->state) { case FRAME_DONE: case FRAME_FULL: if ( cam->active ) { struct frame *a = cam->active; while ( a->next ) a = a->next; a->next = frame; } else cam->active = frame; frame->next = NULL; frame->state = FRAME_PENDING; break; case FRAME_ACTIVE: frame->state = FRAME_PENDING; cam->capture_state = CAPTURE_WAIT_FOR_REFRESH; DISABLE_FIFO_INT; ENABLE_VBLANK_INT; break; case FRAME_PENDING: /* Do nothing */ break; } if ( cam->state == HC_V4L_STREAMING && (cam->mode == HC_MODE_RAW || cam->mode == HC_MODE_RAW_DECIMATED )) frame->data = frame->shared_data; else frame->data = frame->local_data; frame->bytes_read = 0; frame->bytes_to_read = hc_raw[fpga_mode_to_decimation[cam->mode]].bytes; frame->width = hc_raw[fpga_mode_to_decimation[cam->mode]].width; frame->height = hc_raw[fpga_mode_to_decimation[cam->mode]].height; if ( cam->active ) { struct frame *a = cam->active; result++; while ( a->next ) { a = a->next; result++; } } return result;}/* Call this with interrupts disabled *//* This resets each capture buffer AND all of the statistics */stati
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -