📄 h3600_backpaq_core.c
字号:
int retval; if ( cam->i2c_status == I2C_BUSY ) return EBUSY; ENABLE_I2C_INT; BackpaqFPGACameraI2C_SlaveAddr = address; BackpaqFPGACameraI2C_RegAddr = subaddress; BackpaqFPGACameraI2C_Data = data; BackpaqFPGACameraI2C_CR1 = START_I2C_TRANSACTION; cam->i2c_status = I2C_BUSY; PRINTDEBUG(": I2C CR1=0x%X\n", BackpaqFPGACameraI2C_CR1 ); /* Wait for I2C completion */ retval = wait_event_interruptible( cam->i2cq, !(cam->i2c_status & I2C_BUSY) ); if( !(cam->i2c_status & I2C_ACK_SLAVE_ADDRESS) ) CAMERROR(": I2C, no acknowledge on slave address\n"); if( !(cam->i2c_status & I2C_ACK_REG_ADDRESS) ) CAMERROR(": I2C, no acknowledge on register address\n"); if( !(cam->i2c_status & I2C_ACK_DATA) ) CAMERROR(": I2C, no acknowledge on data\n"); DISABLE_I2C_INT; return retval;}// SUBROW marcos#define SUBROWMASK ( 1 << 6 )#define SET_SUBROWMODE( x ) ( x |= SUBROWMASK )#define UNSET_SUBROWMODE( x ) ( x &= ~SUBROWMASK )#define CHECK_SUBROWMODE( x ) ( x & SUBROWMASK )static void setup_ph_upa1021_cam( struct h3600_camera_struct *cam ){ int i; int lines_per_frame; /* Set all I2C resisters of the UPA1021 */ if ( cam->param_mask & PARAM_IMAGER_PH_ALLREGS ) { BackpaqFPGACameraI2C_CR2 = I2C_FAST_SPEED; for ( i = 0 ; i < sizeof(upa1021_i2c_regs); i++ ) WriteI2C( cam, UPA1021_BASEADDRESS, i, upa1021_i2c_regs[i] ); } /* Electronic shutter value in # of line times */ if ( cam->param_mask & PARAM_IMAGER_PH_ESHUTTER ) { // Prevent field stretching of UPA1022 lines_per_frame = upa1021_i2c_regs[UPA1021_LINFIL] | (upa1021_i2c_regs[UPA1021_HCKLFL] & 0xF); if( cam->electronic_shutter > lines_per_frame ) cam->electronic_shutter = lines_per_frame; PRINTDEBUG( ": setting electronic shutter (row_exposure)= 0x%x\n", cam->electronic_shutter); /* Low byte */ upa1021_i2c_regs[UPA1021_REL] = cam->electronic_shutter & 0xFF; WriteI2C( cam, UPA1021_BASEADDRESS, UPA1021_REL, upa1021_i2c_regs[UPA1021_REL] ); /* High byte */ upa1021_i2c_regs[UPA1021_REH] = cam->electronic_shutter >> 8; PRINTDEBUG( ": setting REH= 0x%x\n", upa1021_i2c_regs[UPA1021_REH]); WriteI2C( cam, UPA1021_BASEADDRESS, UPA1021_REH, upa1021_i2c_regs[UPA1021_REH] ); } /* Subrow electronic shutter value */ if ( cam->param_mask & PARAM_IMAGER_PH_SUBROW ) { PRINTDEBUG( ": setting subrow = 0x%x\n", cam->subrow); if( cam->subrow != 0 ) { if( !CHECK_SUBROWMODE( upa1021_i2c_regs[UPA1021_CR1]) ) { SET_SUBROWMODE( upa1021_i2c_regs[UPA1021_CR1] ); WriteI2C( cam, UPA1021_BASEADDRESS, UPA1021_CR1, upa1021_i2c_regs[UPA1021_CR1] ); PRINTDEBUG( ": setting subrow mode CR1=0x%X\n", upa1021_i2c_regs[UPA1021_CR1] ); } } else { if( CHECK_SUBROWMODE( upa1021_i2c_regs[UPA1021_CR1]) ) { UNSET_SUBROWMODE( upa1021_i2c_regs[UPA1021_CR1] ); WriteI2C( cam, UPA1021_BASEADDRESS, UPA1021_CR1, upa1021_i2c_regs[UPA1021_CR1] ); PRINTDEBUG( ": unsetting subrow mode CR1=0x%X\n", upa1021_i2c_regs[UPA1021_CR1] ); } } upa1021_i2c_regs[UPA1021_SRER] = cam->subrow; WriteI2C( cam, UPA1021_BASEADDRESS, UPA1021_SRER, upa1021_i2c_regs[UPA1021_SRER] ); } /* programmable Gain Amp value */ if ( cam->param_mask & PARAM_IMAGER_PH_PGA ) { PRINTDEBUG( ": setting contrast (GOEB) = 0x%x\n", cam->vpic.contrast); upa1021_i2c_regs[UPA1021_GOEB] = cam->vpic.contrast; WriteI2C( cam, UPA1021_BASEADDRESS, UPA1021_GOEB, upa1021_i2c_regs[UPA1021_GOEB] ); } }static void setup_ph_upa1022_cam( struct h3600_camera_struct *cam ){ int i; int lines_per_frame; PRINTDEBUG(": setup_ph_upa1022_cam\n" ); /* Set all I2C resisters of the UPA1022 */ if ( cam->param_mask & PARAM_IMAGER_PH_ALLREGS ) { BackpaqFPGACameraI2C_CR2 = I2C_FAST_SPEED; for ( i = 0 ; i < sizeof(upa1022_i2c_regs); i++ ) WriteI2C( cam, UPA1022_BASEADDRESS, i, upa1022_i2c_regs[i] ); } /* Electronic shutter value in # of line times */ if ( cam->param_mask & PARAM_IMAGER_PH_ESHUTTER ) { // Prevent field stretching of UPA1022 lines_per_frame = upa1022_i2c_regs[UPA1022_LINFIL] | (upa1022_i2c_regs[UPA1022_HCKLFL] & 0xF); if( cam->electronic_shutter > lines_per_frame ) cam->electronic_shutter = lines_per_frame; PRINTDEBUG( ": setting electronic shutter (row_exposure)= 0x%x\n", cam->electronic_shutter); /* Low byte */ upa1022_i2c_regs[UPA1022_REL] = cam->electronic_shutter & 0xFF; WriteI2C( cam, UPA1022_BASEADDRESS, UPA1022_REL, upa1022_i2c_regs[UPA1022_REL] ); /* High byte */ upa1022_i2c_regs[UPA1022_REH] = cam->electronic_shutter >> 8; PRINTDEBUG( ": setting REH= 0x%x\n", upa1022_i2c_regs[UPA1022_REH]); WriteI2C( cam, UPA1022_BASEADDRESS, UPA1022_REH, upa1022_i2c_regs[UPA1022_REH] ); } /* Subrow electronic shutter value */ if ( cam->param_mask & PARAM_IMAGER_PH_SUBROW ) { PRINTDEBUG( ": setting subrow = 0x%x\n", cam->subrow); if( cam->subrow != 0 ) { if( !CHECK_SUBROWMODE( upa1022_i2c_regs[UPA1022_CR1]) ) { SET_SUBROWMODE( upa1022_i2c_regs[UPA1022_CR1] ); WriteI2C( cam, UPA1022_BASEADDRESS, UPA1022_CR1, upa1022_i2c_regs[UPA1022_CR1] ); PRINTDEBUG( ": setting subrow mode CR1=0x%X\n", upa1022_i2c_regs[UPA1022_CR1] ); } } else { if( CHECK_SUBROWMODE( upa1022_i2c_regs[UPA1022_CR1]) ) { UNSET_SUBROWMODE( upa1022_i2c_regs[UPA1022_CR1] ); WriteI2C( cam, UPA1022_BASEADDRESS, UPA1022_CR1, upa1022_i2c_regs[UPA1022_CR1] ); PRINTDEBUG( ": unsetting subrow mode CR1=0x%X\n", upa1022_i2c_regs[UPA1022_CR1] ); } } upa1022_i2c_regs[UPA1022_SRER] = cam->subrow; WriteI2C( cam, UPA1022_BASEADDRESS, UPA1022_SRER, upa1022_i2c_regs[UPA1022_SRER] ); } /* programmable Gain Amp value */ if ( cam->param_mask & PARAM_IMAGER_PH_PGA ) { PRINTDEBUG( ": setting contrast (GOEB) = 0x%x\n", cam->vpic.contrast); upa1022_i2c_regs[UPA1022_GOEB] = cam->vpic.contrast; WriteI2C( cam, UPA1022_BASEADDRESS, UPA1022_GOEB, upa1022_i2c_regs[UPA1022_GOEB] ); } }static void setup_camera( struct h3600_camera_struct *cam ){ if (0) PRINTDEBUG( " param_mask=0x%04x\n", cam->param_mask); if ( cam->param_mask & PARAM_FPGA_CLOCK_DIVISOR ) BackpaqFPGACameraClockDivisor = cam->clock_divisor; if ( cam->param_mask & PARAM_FPGA_INTERRUPT_FIFO ) BackpaqFPGACameraInterruptFifo = cam->interrupt_fifo; if ( cam->param_mask & PARAM_FPGA_LIVE_MODE ) BackpaqFPGACameraLiveMode = 0x01; /* Turn on live video mode */ /* Settings specific to the type of image sensor connected */ switch ( cam->ctype ) { case H3600_SMAL: setup_small_cam( cam ); break; case H3600_PHILIPS: switch( cam->cam_sub_type ) { case PHILIPS_UPA1021: setup_ph_upa1021_cam( cam ); break; case PHILIPS_UPA1022: setup_ph_upa1022_cam( cam ); break; } break; } if ( cam->param_mask & PARAM_FPGA_DECIMATION_MODE ) { if ( decimate_mode ) BackpaqFPGACameraDecimationMode = fpga_mode_to_decimation[cam->mode]; else BackpaqFPGACameraDecimationMode = 0; } cam->param_mask = 0; /* Clear all parameters */}static void stop_capture( struct h3600_camera_struct *cam ){ unsigned long flags; save_flags_cli(flags); DISABLE_BOTH_INT; /* Shut off interrupts */ cam->capture_state = CAPTURE_OFF; restore_flags(flags);}static void start_capture( struct h3600_camera_struct *cam ){ unsigned long flags; save_flags_cli(flags); cam->capture_state = CAPTURE_WAIT_FOR_REFRESH; DISABLE_FIFO_INT; ENABLE_VBLANK_INT; restore_flags(flags);}/****************************************************************************** * * Capture routines * * These routines are called by V4L interface and are "locked" (i.e., only * one can be called at a time). It is quite likely that interrupts are running. * ******************************************************************************//* Called by ioctl routines that change camera parameters */static void update_camera_params( struct h3600_camera_struct *cam ){ unsigned long flags; if ( cam->state == HC_V4L_STREAMING ) { save_flags_cli(flags); if ( cam->param_mask & PARAM_FPGA_DECIMATION_MODE ) { cam->capture_state = CAPTURE_WAIT_FOR_REFRESH; DISABLE_FIFO_INT; ENABLE_VBLANK_INT; } setup_camera( cam ); restore_flags(flags); } else { setup_camera( cam ); }}/* Called by "read" */static long grab_frame( struct h3600_camera_struct *cam ){ struct frame *frame; int retval; stop_capture(cam); /* Turn off interrupt routines */ setup_camera(cam); /* Fix the camera parameters */ clear_capture_buffers(cam); /* Clear all capture buffers */ cam->state = HC_V4L_GRABBING; /* Set our state */ queue_capture_buffer(cam,0); /* Queue up buffer #0 */ start_capture(cam); /* Turn on interrupt routines */ retval = wait_event_interruptible(cam->capq, cam->capture_state == CAPTURE_OFF ); stop_capture(cam); cam->state = HC_V4L_IDLE; if ( retval < 0 ) { CAMDEBUG(": Grab value error %d\n", retval); return retval; } frame = &(cam->frame[0]); if (!frame->state == FRAME_FULL) { CAMDEBUG(": Unable to capture a good frame\n"); return -ERESTART; }#ifdef BACKPAQ_CAMERA_DEBUG// printk(KERN_ALERT __FILE__ ": Read image (size %d)\n" // " Number of interrupts: FIFO=%d VBLANK=%d\n"// " On interrupt, fifo min=%d max=%d status=%x\n",// frame->bytes_read,// cam->capture_stats.fifo_count, cam->capture_stats.vblank_count,// cam->capture_stats.fifo_low, cam->capture_stats.fifo_high,// BackpaqFPGAInterruptStatus);#endif return frame->bytes_read;}/* Called by "read in polling mode" */static long grab_frame_polling( struct h3600_camera_struct *cam ){ int retval; struct frame *frame; stop_capture(cam); /* Turn off any running interrupt routines */ setup_camera(cam); /* Fix camera parameters */ clear_capture_buffers(cam); /* Clear all capture buffers */ cam->state = HC_V4L_IDLE; queue_capture_buffer(cam,0); frame = &cam->frame[0]; /* Wait until rowcount == 1 */ while ( BackpaqFPGACameraRowCount != 1 ) ; do { retval = get_fpga_data( cam ); } while ( retval > 0 ); if ( retval < 0 ) { CAMDEBUG(": Fifo overrun %d\n", retval); CAMDEBUG(": Bytes read %d\n", frame->bytes_read ); CAMDEBUG(": Bytes we're supposed to read %d\n", frame->bytes_to_read); return retval; }#ifdef BACKPAQ_CAMERA_DEBUG// printk(KERN_ALERT __FILE__ ": Polling read image (size %d)\n" // " Fifo min=%d max=%d\n",// frame->bytes_read,// cam->capture_stats.fifo_low, cam->capture_stats.fifo_high ); // printk(KERN_ALERT __FILE__ ": fifo status = %x\n", // BackpaqFPGAInterruptStatus);#endif return frame->bytes_read;}/* Called by "capture" */static int grab_streaming_frame( struct h3600_camera_struct *cam, int index ){ int retval = 0; struct frame *frame = &cam->frame[index]; /* Allocate virtual memory if we haven't already */ if (!cam->frame_buf) { /* we do lazy allocation */ if ((retval = allocate_frame_buf(cam))) return retval; } /* If we're not currently streaming, start, and queue a buffer */ if ( cam->state != HC_V4L_STREAMING ) { stop_capture(cam); /* Turn off any running captures */ setup_camera(cam); /* Fix camera parameters */ clear_capture_buffers(cam); /* Clear all capture buffers */ cam->state = HC_V4L_STREAMING; queue_capture_buffer(cam,index); start_capture(cam); } /* Wait until our capture buffer is finished */ /* This may be interrupted by suspending the iPAQ */ retval = wait_event_interruptible(cam->capq, cam->capture_state == CAPTURE_OFF || frame->state == FRAME_DONE || frame->state == FRAME_FULL ); if ( cam->capture_state == CAPTURE_OFF ) return -EINTR; return retval;}/* Called by "sync" */static int sync_frame( struct h3600_camera_struct *cam, int index ){ int retval = 0; if ( cam->state != HC_V4L_STREAMING ) {// CAMDEBUG(" Not streaming, but syncing frame %d\n", index );/* stop_capture(cam); setup_camera(cam); clear_capture_buffers(cam); queue_capture_buffer(cam,index); cam->state = HC_V4L_STREAMING; start_capture(cam); */ } else { unsigned long flags; int depth; save_flags_cli(flags); depth = queue_capture_buffer(cam,index); restore_flags(flags); } return retval;}/* Called at initialization and by the RESET function */static void set_camera_type( struct h3600_camera_struct *cam ){ switch (h3600_backpaq_eeprom_shadow.camera & BACKPAQ_EEPROM_CAMERA_TYPE_MASK) { case BACKPAQ_CAMERA_SMAL_ORIGINAL_GREY: case BACKPAQ_CAMERA_SMAL_ORIGINAL_COLOR: case BACKPAQ_CAMERA_SMAL_RELEASE_COLOR: case BACKPAQ_CAMERA_SMAL_AUTOBRITE_09: cam->ctype = H3600_SMAL; break; case BACKPAQ_CAMERA_PHILIPS_UPA1021: cam->ctype = H3600_PHILIPS; cam->cam_sub_type = PHILIPS_UPA1021; break; case BACKPAQ_CAMERA_PHILIPS_UPA1022: cam->ctype = H3600_PHILIPS; cam->cam_sub_type = PHILIPS_UPA1022; break; break; }}static void set_default_params( struct h3600_camera_struct *cam ){ set_camera_type( cam ); cam->vpic.brightness = 0x8000; cam->vpic.contrast = 0x8000; set_camera_resolution( cam, VIDEO_PALETTE_RGB24, 10000, 10000 ); /* Will set to 640 x 480 */ cam->flip = 0; /* Don't flip */ cam->read_polling_mode = 0; switch ( cam->ctype ) { case H3600_SMAL: cam->clock_divisor = H3600_BACKPAQ_CAMERA_DEFAULT_CLOCK_DIVISOR; cam->interrupt_fifo = H3600_BACKPAQ_CAMERA_DEFAULT_INTERRUPT_FIFO; cam->power_setting = H3600_BACKPAQ_CAMERA_DEFAULT_POWER_SETTING; cam->gain_format = H3600_BACKPAQ_CAMERA_DEFAULT_GAIN_FORMAT; cam->power_mgmt = H3600_BACKPAQ_CAMERA_DEFAULT_POWER_MGMT; cam->special_modes = H3600_BACKPAQ_CAMERA_DEFAULT_SPECIAL_MODES; cam->autobright = H3600_BACKPAQ_CAMERA_DEFAULT_AUTOBRIGHT; break; case H3600_PHILIPS: cam->clock_divisor = H3600_BACKPAQ_CAMERA_PHILIPS_CLOCK_DIVISOR; cam->interrupt_fifo = H3600_BACKPAQ_CAMERA_PHILIPS_INTERRUPT_FIFO; cam->electronic_shutter = H3600_BACKPAQ_CAMERA_PHILIPS_ELECTRONIC_SHUTTER; cam->subrow = H3600_BACKPAQ_CAMERA_PHILIPS_SUBROW; break; } cam->param_mask = 0xffff;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -