add idl4k kernel firmware version 1.13.0.105

This commit is contained in:
Jaroslav Kysela
2015-03-26 17:22:37 +01:00
parent 5194d2792e
commit e9070cdc77
31064 changed files with 12769984 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
config VIDEO_CPIA2
tristate "CPiA2 Video For Linux"
depends on VIDEO_DEV && USB && VIDEO_V4L1
---help---
This is the video4linux driver for cameras based on Vision's CPiA2
(Colour Processor Interface ASIC), such as the Digital Blue QX5
Microscope. If you have one of these cameras, say Y here
This driver is also available as a module (cpia2).

View File

@@ -0,0 +1,3 @@
cpia2-objs := cpia2_v4l.o cpia2_usb.o cpia2_core.o
obj-$(CONFIG_VIDEO_CPIA2) += cpia2.o

View File

@@ -0,0 +1,494 @@
/****************************************************************************
*
* Filename: cpia2.h
*
* Copyright 2001, STMicrolectronics, Inc.
*
* Contact: steve.miller@st.com
*
* Description:
* This is a USB driver for CPiA2 based video cameras.
*
* This driver is modelled on the cpia usb driver by
* Jochen Scharrlach and Johannes Erdfeldt.
*
* 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 2 of the License, or
* (at your option) any later version.
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
****************************************************************************/
#ifndef __CPIA2_H__
#define __CPIA2_H__
#include <linux/version.h>
#include <linux/videodev.h>
#include <media/v4l2-common.h>
#include <linux/usb.h>
#include <linux/poll.h>
#include "cpia2dev.h"
#include "cpia2_registers.h"
/* define for verbose debug output */
//#define _CPIA2_DEBUG_
#define CPIA2_MAJ_VER 2
#define CPIA2_MIN_VER 0
#define CPIA2_PATCH_VER 0
/***
* Image defines
***/
/* Misc constants */
#define ALLOW_CORRUPT 0 /* Causes collater to discard checksum */
/* USB Transfer mode */
#define XFER_ISOC 0
#define XFER_BULK 1
/* USB Alternates */
#define USBIF_CMDONLY 0
#define USBIF_BULK 1
#define USBIF_ISO_1 2 /* 128 bytes/ms */
#define USBIF_ISO_2 3 /* 384 bytes/ms */
#define USBIF_ISO_3 4 /* 640 bytes/ms */
#define USBIF_ISO_4 5 /* 768 bytes/ms */
#define USBIF_ISO_5 6 /* 896 bytes/ms */
#define USBIF_ISO_6 7 /* 1023 bytes/ms */
/* Flicker Modes */
#define NEVER_FLICKER 0
#define ANTI_FLICKER_ON 1
#define FLICKER_60 60
#define FLICKER_50 50
/* Debug flags */
#define DEBUG_NONE 0
#define DEBUG_REG 0x00000001
#define DEBUG_DUMP_PATCH 0x00000002
#define DEBUG_DUMP_REGS 0x00000004
/***
* Video frame sizes
***/
enum {
VIDEOSIZE_VGA = 0, /* 640x480 */
VIDEOSIZE_CIF, /* 352x288 */
VIDEOSIZE_QVGA, /* 320x240 */
VIDEOSIZE_QCIF, /* 176x144 */
VIDEOSIZE_288_216,
VIDEOSIZE_256_192,
VIDEOSIZE_224_168,
VIDEOSIZE_192_144,
};
#define STV_IMAGE_CIF_ROWS 288
#define STV_IMAGE_CIF_COLS 352
#define STV_IMAGE_QCIF_ROWS 144
#define STV_IMAGE_QCIF_COLS 176
#define STV_IMAGE_VGA_ROWS 480
#define STV_IMAGE_VGA_COLS 640
#define STV_IMAGE_QVGA_ROWS 240
#define STV_IMAGE_QVGA_COLS 320
#define JPEG_MARKER_COM (1<<6) /* Comment segment */
/***
* Enums
***/
/* Sensor types available with cpia2 asics */
enum sensors {
CPIA2_SENSOR_410,
CPIA2_SENSOR_500
};
/* Asic types available in the CPiA2 architecture */
#define CPIA2_ASIC_672 0x67
/* Device types (stv672, stv676, etc) */
#define DEVICE_STV_672 0x0001
#define DEVICE_STV_676 0x0002
enum frame_status {
FRAME_EMPTY,
FRAME_READING, /* In the process of being grabbed into */
FRAME_READY, /* Ready to be read */
FRAME_ERROR,
};
/***
* Register access (for USB request byte)
***/
enum {
CAMERAACCESS_SYSTEM = 0,
CAMERAACCESS_VC,
CAMERAACCESS_VP,
CAMERAACCESS_IDATA
};
#define CAMERAACCESS_TYPE_BLOCK 0x00
#define CAMERAACCESS_TYPE_RANDOM 0x04
#define CAMERAACCESS_TYPE_MASK 0x08
#define CAMERAACCESS_TYPE_REPEAT 0x0C
#define TRANSFER_READ 0
#define TRANSFER_WRITE 1
#define DEFAULT_ALT USBIF_ISO_6
#define DEFAULT_BRIGHTNESS 0x46
#define DEFAULT_CONTRAST 0x93
#define DEFAULT_SATURATION 0x7f
#define DEFAULT_TARGET_KB 0x30
/* Power state */
#define HI_POWER_MODE CPIA2_SYSTEM_CONTROL_HIGH_POWER
#define LO_POWER_MODE CPIA2_SYSTEM_CONTROL_LOW_POWER
/********
* Commands
*******/
enum {
CPIA2_CMD_NONE = 0,
CPIA2_CMD_GET_VERSION,
CPIA2_CMD_GET_PNP_ID,
CPIA2_CMD_GET_ASIC_TYPE,
CPIA2_CMD_GET_SENSOR,
CPIA2_CMD_GET_VP_DEVICE,
CPIA2_CMD_GET_VP_BRIGHTNESS,
CPIA2_CMD_SET_VP_BRIGHTNESS,
CPIA2_CMD_GET_CONTRAST,
CPIA2_CMD_SET_CONTRAST,
CPIA2_CMD_GET_VP_SATURATION,
CPIA2_CMD_SET_VP_SATURATION,
CPIA2_CMD_GET_VP_GPIO_DIRECTION,
CPIA2_CMD_SET_VP_GPIO_DIRECTION,
CPIA2_CMD_GET_VP_GPIO_DATA,
CPIA2_CMD_SET_VP_GPIO_DATA,
CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION,
CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION,
CPIA2_CMD_GET_VC_MP_GPIO_DATA,
CPIA2_CMD_SET_VC_MP_GPIO_DATA,
CPIA2_CMD_ENABLE_PACKET_CTRL,
CPIA2_CMD_GET_FLICKER_MODES,
CPIA2_CMD_SET_FLICKER_MODES,
CPIA2_CMD_RESET_FIFO, /* clear fifo and enable stream block */
CPIA2_CMD_SET_HI_POWER,
CPIA2_CMD_SET_LOW_POWER,
CPIA2_CMD_CLEAR_V2W_ERR,
CPIA2_CMD_SET_USER_MODE,
CPIA2_CMD_GET_USER_MODE,
CPIA2_CMD_FRAMERATE_REQ,
CPIA2_CMD_SET_COMPRESSION_STATE,
CPIA2_CMD_GET_WAKEUP,
CPIA2_CMD_SET_WAKEUP,
CPIA2_CMD_GET_PW_CONTROL,
CPIA2_CMD_SET_PW_CONTROL,
CPIA2_CMD_GET_SYSTEM_CTRL,
CPIA2_CMD_SET_SYSTEM_CTRL,
CPIA2_CMD_GET_VP_SYSTEM_STATE,
CPIA2_CMD_GET_VP_SYSTEM_CTRL,
CPIA2_CMD_SET_VP_SYSTEM_CTRL,
CPIA2_CMD_GET_VP_EXP_MODES,
CPIA2_CMD_SET_VP_EXP_MODES,
CPIA2_CMD_GET_DEVICE_CONFIG,
CPIA2_CMD_SET_DEVICE_CONFIG,
CPIA2_CMD_SET_SERIAL_ADDR,
CPIA2_CMD_SET_SENSOR_CR1,
CPIA2_CMD_GET_VC_CONTROL,
CPIA2_CMD_SET_VC_CONTROL,
CPIA2_CMD_SET_TARGET_KB,
CPIA2_CMD_SET_DEF_JPEG_OPT,
CPIA2_CMD_REHASH_VP4,
CPIA2_CMD_GET_USER_EFFECTS,
CPIA2_CMD_SET_USER_EFFECTS
};
enum user_cmd {
COMMAND_NONE = 0x00000001,
COMMAND_SET_FPS = 0x00000002,
COMMAND_SET_COLOR_PARAMS = 0x00000004,
COMMAND_GET_COLOR_PARAMS = 0x00000008,
COMMAND_SET_FORMAT = 0x00000010, /* size, etc */
COMMAND_SET_FLICKER = 0x00000020
};
/***
* Some defines specific to the 676 chip
***/
#define CAMACC_CIF 0x01
#define CAMACC_VGA 0x02
#define CAMACC_QCIF 0x04
#define CAMACC_QVGA 0x08
struct cpia2_register {
u8 index;
u8 value;
};
struct cpia2_reg_mask {
u8 index;
u8 and_mask;
u8 or_mask;
u8 fill;
};
struct cpia2_command {
u32 command;
u8 req_mode; /* (Block or random) | registerBank */
u8 reg_count;
u8 direction;
u8 start;
union reg_types {
struct cpia2_register registers[32];
struct cpia2_reg_mask masks[16];
u8 block_data[64];
u8 *patch_data; /* points to function defined block */
} buffer;
};
struct camera_params {
struct {
u8 firmware_revision_hi; /* For system register set (bank 0) */
u8 firmware_revision_lo;
u8 asic_id; /* Video Compressor set (bank 1) */
u8 asic_rev;
u8 vp_device_hi; /* Video Processor set (bank 2) */
u8 vp_device_lo;
u8 sensor_flags;
u8 sensor_rev;
} version;
struct {
u32 device_type; /* enumerated from vendor/product ids.
* Currently, either STV_672 or STV_676 */
u16 vendor;
u16 product;
u16 device_revision;
} pnp_id;
struct {
u8 brightness; /* CPIA2_VP_EXPOSURE_TARGET */
u8 contrast; /* Note: this is CPIA2_VP_YRANGE */
u8 saturation; /* CPIA2_VP_SATURATION */
} color_params;
struct {
u8 cam_register;
u8 flicker_mode_req; /* 1 if flicker on, else never flicker */
int mains_frequency;
} flicker_control;
struct {
u8 jpeg_options;
u8 creep_period;
u8 user_squeeze;
u8 inhibit_htables;
} compression;
struct {
u8 ohsize; /* output image size */
u8 ovsize;
u8 hcrop; /* cropping start_pos/4 */
u8 vcrop;
u8 hphase; /* scaling registers */
u8 vphase;
u8 hispan;
u8 vispan;
u8 hicrop;
u8 vicrop;
u8 hifraction;
u8 vifraction;
} image_size;
struct {
int width; /* actual window width */
int height; /* actual window height */
} roi;
struct {
u8 video_mode;
u8 frame_rate;
u8 video_size; /* Not a register, just a convenience for cropped sizes */
u8 gpio_direction;
u8 gpio_data;
u8 system_ctrl;
u8 system_state;
u8 lowlight_boost; /* Bool: 0 = off, 1 = on */
u8 device_config;
u8 exposure_modes;
u8 user_effects;
} vp_params;
struct {
u8 pw_control;
u8 wakeup;
u8 vc_control;
u8 vc_mp_direction;
u8 vc_mp_data;
u8 target_kb;
} vc_params;
struct {
u8 power_mode;
u8 system_ctrl;
u8 stream_mode; /* This is the current alternate for usb drivers */
u8 allow_corrupt;
} camera_state;
};
#define NUM_SBUF 2
struct cpia2_sbuf {
char *data;
struct urb *urb;
};
struct framebuf {
struct timeval timestamp;
unsigned long seq;
int num;
int length;
int max_length;
volatile enum frame_status status;
u8 *data;
struct framebuf *next;
};
struct cpia2_fh {
enum v4l2_priority prio;
u8 mmapped;
};
struct camera_data {
/* locks */
struct mutex busy_lock; /* guard against SMP multithreading */
struct v4l2_prio_state prio;
/* camera status */
volatile int present; /* Is the camera still present? */
int open_count; /* # of process that have camera open */
int first_image_seen;
u8 mains_freq; /* for flicker control */
enum sensors sensor_type;
u8 flush;
u8 mmapped;
int streaming; /* 0 = no, 1 = yes */
int xfer_mode; /* XFER_BULK or XFER_ISOC */
struct camera_params params; /* camera settings */
/* v4l */
int video_size; /* VIDEO_SIZE_ */
struct video_device *vdev; /* v4l videodev */
struct video_picture vp; /* v4l camera settings */
struct video_window vw; /* v4l capture area */
__u32 pixelformat; /* Format fourcc */
/* USB */
struct usb_device *dev;
unsigned char iface;
unsigned int cur_alt;
unsigned int old_alt;
struct cpia2_sbuf sbuf[NUM_SBUF]; /* Double buffering */
wait_queue_head_t wq_stream;
/* Buffering */
u32 frame_size;
int num_frames;
unsigned long frame_count;
u8 *frame_buffer; /* frame buffer data */
struct framebuf *buffers;
struct framebuf * volatile curbuff;
struct framebuf *workbuff;
/* MJPEG Extension */
int APPn; /* Number of APP segment to be written, must be 0..15 */
int APP_len; /* Length of data in JPEG APPn segment */
char APP_data[60]; /* Data in the JPEG APPn segment. */
int COM_len; /* Length of data in JPEG COM segment */
char COM_data[60]; /* Data in JPEG COM segment */
};
/* v4l */
int cpia2_register_camera(struct camera_data *cam);
void cpia2_unregister_camera(struct camera_data *cam);
/* core */
int cpia2_reset_camera(struct camera_data *cam);
int cpia2_set_low_power(struct camera_data *cam);
void cpia2_dbg_dump_registers(struct camera_data *cam);
int cpia2_match_video_size(int width, int height);
void cpia2_set_camera_state(struct camera_data *cam);
void cpia2_save_camera_state(struct camera_data *cam);
void cpia2_set_color_params(struct camera_data *cam);
void cpia2_set_brightness(struct camera_data *cam, unsigned char value);
void cpia2_set_contrast(struct camera_data *cam, unsigned char value);
void cpia2_set_saturation(struct camera_data *cam, unsigned char value);
int cpia2_set_flicker_mode(struct camera_data *cam, int mode);
void cpia2_set_format(struct camera_data *cam);
int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd);
int cpia2_do_command(struct camera_data *cam,
unsigned int command,
unsigned char direction, unsigned char param);
struct camera_data *cpia2_init_camera_struct(void);
int cpia2_init_camera(struct camera_data *cam);
int cpia2_allocate_buffers(struct camera_data *cam);
void cpia2_free_buffers(struct camera_data *cam);
long cpia2_read(struct camera_data *cam,
char __user *buf, unsigned long count, int noblock);
unsigned int cpia2_poll(struct camera_data *cam,
struct file *filp, poll_table *wait);
int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma);
void cpia2_set_property_flip(struct camera_data *cam, int prop_val);
void cpia2_set_property_mirror(struct camera_data *cam, int prop_val);
int cpia2_set_target_kb(struct camera_data *cam, unsigned char value);
int cpia2_set_gpio(struct camera_data *cam, unsigned char setting);
int cpia2_set_fps(struct camera_data *cam, int framerate);
/* usb */
int cpia2_usb_init(void);
void cpia2_usb_cleanup(void);
int cpia2_usb_transfer_cmd(struct camera_data *cam, void *registers,
u8 request, u8 start, u8 count, u8 direction);
int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate);
int cpia2_usb_stream_stop(struct camera_data *cam);
int cpia2_usb_stream_pause(struct camera_data *cam);
int cpia2_usb_stream_resume(struct camera_data *cam);
int cpia2_usb_change_streaming_alternate(struct camera_data *cam,
unsigned int alt);
/* ----------------------- debug functions ---------------------- */
#ifdef _CPIA2_DEBUG_
#define ALOG(lev, fmt, args...) printk(lev "%s:%d %s(): " fmt, __FILE__, __LINE__, __func__, ## args)
#define LOG(fmt, args...) ALOG(KERN_INFO, fmt, ## args)
#define ERR(fmt, args...) ALOG(KERN_ERR, fmt, ## args)
#define DBG(fmt, args...) ALOG(KERN_DEBUG, fmt, ## args)
#else
#define ALOG(fmt,args...) printk(fmt,##args)
#define LOG(fmt,args...) ALOG(KERN_INFO "cpia2: "fmt,##args)
#define ERR(fmt,args...) ALOG(KERN_ERR "cpia2: "fmt,##args)
#define DBG(fmn,args...) do {} while(0)
#endif
/* No function or lineno, for shorter lines */
#define KINFO(fmt, args...) printk(KERN_INFO fmt,##args)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,476 @@
/****************************************************************************
*
* Filename: cpia2registers.h
*
* Copyright 2001, STMicrolectronics, Inc.
*
* Description:
* Definitions for the CPia2 register set
*
* 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 2 of the License, or
* (at your option) any later version.
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
****************************************************************************/
#ifndef CPIA2_REGISTER_HEADER
#define CPIA2_REGISTER_HEADER
/***
* System register set (Bank 0)
***/
#define CPIA2_SYSTEM_DEVICE_HI 0x00
#define CPIA2_SYSTEM_DEVICE_LO 0x01
#define CPIA2_SYSTEM_SYSTEM_CONTROL 0x02
#define CPIA2_SYSTEM_CONTROL_LOW_POWER 0x00
#define CPIA2_SYSTEM_CONTROL_HIGH_POWER 0x01
#define CPIA2_SYSTEM_CONTROL_SUSPEND 0x02
#define CPIA2_SYSTEM_CONTROL_V2W_ERR 0x10
#define CPIA2_SYSTEM_CONTROL_RB_ERR 0x10
#define CPIA2_SYSTEM_CONTROL_CLEAR_ERR 0x80
#define CPIA2_SYSTEM_INT_PACKET_CTRL 0x04
#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX 0x01
#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_EOF 0x02
#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_INT1 0x04
#define CPIA2_SYSTEM_CACHE_CTRL 0x05
#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_RESET 0x01
#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_FLUSH 0x02
#define CPIA2_SYSTEM_SERIAL_CTRL 0x06
#define CPIA2_SYSTEM_SERIAL_CTRL_NULL_CMD 0x00
#define CPIA2_SYSTEM_SERIAL_CTRL_START_CMD 0x01
#define CPIA2_SYSTEM_SERIAL_CTRL_STOP_CMD 0x02
#define CPIA2_SYSTEM_SERIAL_CTRL_WRITE_CMD 0x03
#define CPIA2_SYSTEM_SERIAL_CTRL_READ_ACK_CMD 0x04
#define CPIA2_SYSTEM_SERIAL_CTRL_READ_NACK_CMD 0x05
#define CPIA2_SYSTEM_SERIAL_DATA 0x07
#define CPIA2_SYSTEM_VP_SERIAL_ADDR 0x08
/***
* I2C addresses for various devices in CPiA2
***/
#define CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR 0x20
#define CPIA2_SYSTEM_VP_SERIAL_ADDR_VP 0x88
#define CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP 0x8A
#define CPIA2_SYSTEM_SPARE_REG1 0x09
#define CPIA2_SYSTEM_SPARE_REG2 0x0A
#define CPIA2_SYSTEM_SPARE_REG3 0x0B
#define CPIA2_SYSTEM_MC_PORT_0 0x0C
#define CPIA2_SYSTEM_MC_PORT_1 0x0D
#define CPIA2_SYSTEM_MC_PORT_2 0x0E
#define CPIA2_SYSTEM_MC_PORT_3 0x0F
#define CPIA2_SYSTEM_STATUS_PKT 0x20
#define CPIA2_SYSTEM_STATUS_PKT_END 0x27
#define CPIA2_SYSTEM_DESCRIP_VID_HI 0x30
#define CPIA2_SYSTEM_DESCRIP_VID_LO 0x31
#define CPIA2_SYSTEM_DESCRIP_PID_HI 0x32
#define CPIA2_SYSTEM_DESCRIP_PID_LO 0x33
#define CPIA2_SYSTEM_FW_VERSION_HI 0x34
#define CPIA2_SYSTEM_FW_VERSION_LO 0x35
#define CPIA2_SYSTEM_CACHE_START_INDEX 0x80
#define CPIA2_SYSTEM_CACHE_MAX_WRITES 0x10
/***
* VC register set (Bank 1)
***/
#define CPIA2_VC_ASIC_ID 0x80
#define CPIA2_VC_ASIC_REV 0x81
#define CPIA2_VC_PW_CTRL 0x82
#define CPIA2_VC_PW_CTRL_COLDSTART 0x01
#define CPIA2_VC_PW_CTRL_CP_CLK_EN 0x02
#define CPIA2_VC_PW_CTRL_VP_RESET_N 0x04
#define CPIA2_VC_PW_CTRL_VC_CLK_EN 0x08
#define CPIA2_VC_PW_CTRL_VC_RESET_N 0x10
#define CPIA2_VC_PW_CTRL_GOTO_SUSPEND 0x20
#define CPIA2_VC_PW_CTRL_UDC_SUSPEND 0x40
#define CPIA2_VC_PW_CTRL_PWR_DOWN 0x80
#define CPIA2_VC_WAKEUP 0x83
#define CPIA2_VC_WAKEUP_SW_ENABLE 0x01
#define CPIA2_VC_WAKEUP_XX_ENABLE 0x02
#define CPIA2_VC_WAKEUP_SW_ATWAKEUP 0x04
#define CPIA2_VC_WAKEUP_XX_ATWAKEUP 0x08
#define CPIA2_VC_CLOCK_CTRL 0x84
#define CPIA2_VC_CLOCK_CTRL_TESTUP72 0x01
#define CPIA2_VC_INT_ENABLE 0x88
#define CPIA2_VC_INT_ENABLE_XX_IE 0x01
#define CPIA2_VC_INT_ENABLE_SW_IE 0x02
#define CPIA2_VC_INT_ENABLE_VC_IE 0x04
#define CPIA2_VC_INT_ENABLE_USBDATA_IE 0x08
#define CPIA2_VC_INT_ENABLE_USBSETUP_IE 0x10
#define CPIA2_VC_INT_ENABLE_USBCFG_IE 0x20
#define CPIA2_VC_INT_FLAG 0x89
#define CPIA2_VC_INT_ENABLE_XX_FLAG 0x01
#define CPIA2_VC_INT_ENABLE_SW_FLAG 0x02
#define CPIA2_VC_INT_ENABLE_VC_FLAG 0x04
#define CPIA2_VC_INT_ENABLE_USBDATA_FLAG 0x08
#define CPIA2_VC_INT_ENABLE_USBSETUP_FLAG 0x10
#define CPIA2_VC_INT_ENABLE_USBCFG_FLAG 0x20
#define CPIA2_VC_INT_ENABLE_SET_RESET_BIT 0x80
#define CPIA2_VC_INT_STATE 0x8A
#define CPIA2_VC_INT_STATE_XX_STATE 0x01
#define CPIA2_VC_INT_STATE_SW_STATE 0x02
#define CPIA2_VC_MP_DIR 0x90
#define CPIA2_VC_MP_DIR_INPUT 0x00
#define CPIA2_VC_MP_DIR_OUTPUT 0x01
#define CPIA2_VC_MP_DATA 0x91
#define CPIA2_VC_DP_CTRL 0x98
#define CPIA2_VC_DP_CTRL_MODE_0 0x00
#define CPIA2_VC_DP_CTRL_MODE_A 0x01
#define CPIA2_VC_DP_CTRL_MODE_B 0x02
#define CPIA2_VC_DP_CTRL_MODE_C 0x03
#define CPIA2_VC_DP_CTRL_FAKE_FST 0x04
#define CPIA2_VC_AD_CTRL 0x99
#define CPIA2_VC_AD_CTRL_SRC_0 0x00
#define CPIA2_VC_AD_CTRL_SRC_DIGI_A 0x01
#define CPIA2_VC_AD_CTRL_SRC_REG 0x02
#define CPIA2_VC_AD_CTRL_DST_USB 0x00
#define CPIA2_VC_AD_CTRL_DST_REG 0x04
#define CPIA2_VC_AD_TEST_IN 0x9B
#define CPIA2_VC_AD_TEST_OUT 0x9C
#define CPIA2_VC_AD_STATUS 0x9D
#define CPIA2_VC_AD_STATUS_EMPTY 0x01
#define CPIA2_VC_AD_STATUS_FULL 0x02
#define CPIA2_VC_DP_DATA 0x9E
#define CPIA2_VC_ST_CTRL 0xA0
#define CPIA2_VC_ST_CTRL_SRC_VC 0x00
#define CPIA2_VC_ST_CTRL_SRC_DP 0x01
#define CPIA2_VC_ST_CTRL_SRC_REG 0x02
#define CPIA2_VC_ST_CTRL_RAW_SELECT 0x04
#define CPIA2_VC_ST_CTRL_DST_USB 0x00
#define CPIA2_VC_ST_CTRL_DST_DP 0x08
#define CPIA2_VC_ST_CTRL_DST_REG 0x10
#define CPIA2_VC_ST_CTRL_FIFO_ENABLE 0x20
#define CPIA2_VC_ST_CTRL_EOF_DETECT 0x40
#define CPIA2_VC_ST_TEST 0xA1
#define CPIA2_VC_ST_TEST_MODE_MANUAL 0x00
#define CPIA2_VC_ST_TEST_MODE_INCREMENT 0x02
#define CPIA2_VC_ST_TEST_AUTO_FILL 0x08
#define CPIA2_VC_ST_TEST_REPEAT_FIFO 0x10
#define CPIA2_VC_ST_TEST_IN 0xA2
#define CPIA2_VC_ST_TEST_OUT 0xA3
#define CPIA2_VC_ST_STATUS 0xA4
#define CPIA2_VC_ST_STATUS_EMPTY 0x01
#define CPIA2_VC_ST_STATUS_FULL 0x02
#define CPIA2_VC_ST_FRAME_DETECT_1 0xA5
#define CPIA2_VC_ST_FRAME_DETECT_2 0xA6
#define CPIA2_VC_USB_CTRL 0xA8
#define CPIA2_VC_USB_CTRL_CMD_STALLED 0x01
#define CPIA2_VC_USB_CTRL_CMD_READY 0x02
#define CPIA2_VC_USB_CTRL_CMD_STATUS 0x04
#define CPIA2_VC_USB_CTRL_CMD_STATUS_DIR 0x08
#define CPIA2_VC_USB_CTRL_CMD_NO_CLASH 0x10
#define CPIA2_VC_USB_CTRL_CMD_MICRO_ACCESS 0x80
#define CPIA2_VC_USB_STRM 0xA9
#define CPIA2_VC_USB_STRM_ISO_ENABLE 0x01
#define CPIA2_VC_USB_STRM_BLK_ENABLE 0x02
#define CPIA2_VC_USB_STRM_INT_ENABLE 0x04
#define CPIA2_VC_USB_STRM_AUD_ENABLE 0x08
#define CPIA2_VC_USB_STATUS 0xAA
#define CPIA2_VC_USB_STATUS_CMD_IN_PROGRESS 0x01
#define CPIA2_VC_USB_STATUS_CMD_STATUS_STALL 0x02
#define CPIA2_VC_USB_STATUS_CMD_HANDSHAKE 0x04
#define CPIA2_VC_USB_STATUS_CMD_OVERRIDE 0x08
#define CPIA2_VC_USB_STATUS_CMD_FIFO_BUSY 0x10
#define CPIA2_VC_USB_STATUS_BULK_REPEAT_TXN 0x20
#define CPIA2_VC_USB_STATUS_CONFIG_DONE 0x40
#define CPIA2_VC_USB_STATUS_USB_SUSPEND 0x80
#define CPIA2_VC_USB_CMDW 0xAB
#define CPIA2_VC_USB_DATARW 0xAC
#define CPIA2_VC_USB_INFO 0xAD
#define CPIA2_VC_USB_CONFIG 0xAE
#define CPIA2_VC_USB_SETTINGS 0xAF
#define CPIA2_VC_USB_SETTINGS_CONFIG_MASK 0x03
#define CPIA2_VC_USB_SETTINGS_INTERFACE_MASK 0x0C
#define CPIA2_VC_USB_SETTINGS_ALTERNATE_MASK 0x70
#define CPIA2_VC_USB_ISOLIM 0xB0
#define CPIA2_VC_USB_ISOFAILS 0xB1
#define CPIA2_VC_USB_ISOMAXPKTHI 0xB2
#define CPIA2_VC_USB_ISOMAXPKTLO 0xB3
#define CPIA2_VC_V2W_CTRL 0xB8
#define CPIA2_VC_V2W_SELECT 0x01
#define CPIA2_VC_V2W_SCL 0xB9
#define CPIA2_VC_V2W_SDA 0xBA
#define CPIA2_VC_VC_CTRL 0xC0
#define CPIA2_VC_VC_CTRL_RUN 0x01
#define CPIA2_VC_VC_CTRL_SINGLESHOT 0x02
#define CPIA2_VC_VC_CTRL_IDLING 0x04
#define CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES 0x10
#define CPIA2_VC_VC_CTRL_INHIBIT_Q_TABLES 0x20
#define CPIA2_VC_VC_CTRL_INHIBIT_PRIVATE 0x40
#define CPIA2_VC_VC_RESTART_IVAL_HI 0xC1
#define CPIA2_VC_VC_RESTART_IVAL_LO 0xC2
#define CPIA2_VC_VC_FORMAT 0xC3
#define CPIA2_VC_VC_FORMAT_UFIRST 0x01
#define CPIA2_VC_VC_FORMAT_MONO 0x02
#define CPIA2_VC_VC_FORMAT_DECIMATING 0x04
#define CPIA2_VC_VC_FORMAT_SHORTLINE 0x08
#define CPIA2_VC_VC_FORMAT_SELFTEST 0x10
#define CPIA2_VC_VC_CLOCKS 0xC4
#define CPIA2_VC_VC_CLOCKS_CLKDIV_MASK 0x03
#define CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 0x04
#define CPIA2_VC_VC_672_CLOCKS_SCALING 0x08
#define CPIA2_VC_VC_CLOCKS_LOGDIV0 0x00
#define CPIA2_VC_VC_CLOCKS_LOGDIV1 0x01
#define CPIA2_VC_VC_CLOCKS_LOGDIV2 0x02
#define CPIA2_VC_VC_CLOCKS_LOGDIV3 0x03
#define CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 0x08
#define CPIA2_VC_VC_676_CLOCKS_SCALING 0x10
#define CPIA2_VC_VC_IHSIZE_LO 0xC5
#define CPIA2_VC_VC_XLIM_HI 0xC6
#define CPIA2_VC_VC_XLIM_LO 0xC7
#define CPIA2_VC_VC_YLIM_HI 0xC8
#define CPIA2_VC_VC_YLIM_LO 0xC9
#define CPIA2_VC_VC_OHSIZE 0xCA
#define CPIA2_VC_VC_OVSIZE 0xCB
#define CPIA2_VC_VC_HCROP 0xCC
#define CPIA2_VC_VC_VCROP 0xCD
#define CPIA2_VC_VC_HPHASE 0xCE
#define CPIA2_VC_VC_VPHASE 0xCF
#define CPIA2_VC_VC_HISPAN 0xD0
#define CPIA2_VC_VC_VISPAN 0xD1
#define CPIA2_VC_VC_HICROP 0xD2
#define CPIA2_VC_VC_VICROP 0xD3
#define CPIA2_VC_VC_HFRACT 0xD4
#define CPIA2_VC_VC_HFRACT_DEN_MASK 0x0F
#define CPIA2_VC_VC_HFRACT_NUM_MASK 0xF0
#define CPIA2_VC_VC_VFRACT 0xD5
#define CPIA2_VC_VC_VFRACT_DEN_MASK 0x0F
#define CPIA2_VC_VC_VFRACT_NUM_MASK 0xF0
#define CPIA2_VC_VC_JPEG_OPT 0xD6
#define CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE 0x01
#define CPIA2_VC_VC_JPEG_OPT_NO_DC_AUTO_SQUEEZE 0x02
#define CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE 0x04
#define CPIA2_VC_VC_JPEG_OPT_DEFAULT (CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE|\
CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE)
#define CPIA2_VC_VC_CREEP_PERIOD 0xD7
#define CPIA2_VC_VC_USER_SQUEEZE 0xD8
#define CPIA2_VC_VC_TARGET_KB 0xD9
#define CPIA2_VC_VC_AUTO_SQUEEZE 0xE6
/***
* VP register set (Bank 2)
***/
#define CPIA2_VP_DEVICEH 0
#define CPIA2_VP_DEVICEL 1
#define CPIA2_VP_SYSTEMSTATE 0x02
#define CPIA2_VP_SYSTEMSTATE_HK_ALIVE 0x01
#define CPIA2_VP_SYSTEMCTRL 0x03
#define CPIA2_VP_SYSTEMCTRL_REQ_CLEAR_ERROR 0x80
#define CPIA2_VP_SYSTEMCTRL_POWER_DOWN_PLL 0x20
#define CPIA2_VP_SYSTEMCTRL_REQ_SUSPEND_STATE 0x10
#define CPIA2_VP_SYSTEMCTRL_REQ_SERIAL_WAKEUP 0x08
#define CPIA2_VP_SYSTEMCTRL_REQ_AUTOLOAD 0x04
#define CPIA2_VP_SYSTEMCTRL_HK_CONTROL 0x02
#define CPIA2_VP_SYSTEMCTRL_POWER_CONTROL 0x01
#define CPIA2_VP_SENSOR_FLAGS 0x05
#define CPIA2_VP_SENSOR_FLAGS_404 0x01
#define CPIA2_VP_SENSOR_FLAGS_407 0x02
#define CPIA2_VP_SENSOR_FLAGS_409 0x04
#define CPIA2_VP_SENSOR_FLAGS_410 0x08
#define CPIA2_VP_SENSOR_FLAGS_500 0x10
#define CPIA2_VP_SENSOR_REV 0x06
#define CPIA2_VP_DEVICE_CONFIG 0x07
#define CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE 0x01
#define CPIA2_VP_GPIO_DIRECTION 0x08
#define CPIA2_VP_GPIO_READ 0xFF
#define CPIA2_VP_GPIO_WRITE 0x00
#define CPIA2_VP_GPIO_DATA 0x09
#define CPIA2_VP_RAM_ADDR_H 0x0A
#define CPIA2_VP_RAM_ADDR_L 0x0B
#define CPIA2_VP_RAM_DATA 0x0C
#define CPIA2_VP_PATCH_REV 0x0F
#define CPIA2_VP4_USER_MODE 0x10
#define CPIA2_VP5_USER_MODE 0x13
#define CPIA2_VP_USER_MODE_CIF 0x01
#define CPIA2_VP_USER_MODE_QCIFDS 0x02
#define CPIA2_VP_USER_MODE_QCIFPTC 0x04
#define CPIA2_VP_USER_MODE_QVGADS 0x08
#define CPIA2_VP_USER_MODE_QVGAPTC 0x10
#define CPIA2_VP_USER_MODE_VGA 0x20
#define CPIA2_VP4_FRAMERATE_REQUEST 0x11
#define CPIA2_VP5_FRAMERATE_REQUEST 0x14
#define CPIA2_VP_FRAMERATE_60 0x80
#define CPIA2_VP_FRAMERATE_50 0x40
#define CPIA2_VP_FRAMERATE_30 0x20
#define CPIA2_VP_FRAMERATE_25 0x10
#define CPIA2_VP_FRAMERATE_15 0x08
#define CPIA2_VP_FRAMERATE_12_5 0x04
#define CPIA2_VP_FRAMERATE_7_5 0x02
#define CPIA2_VP_FRAMERATE_6_25 0x01
#define CPIA2_VP4_USER_EFFECTS 0x12
#define CPIA2_VP5_USER_EFFECTS 0x15
#define CPIA2_VP_USER_EFFECTS_COLBARS 0x01
#define CPIA2_VP_USER_EFFECTS_COLBARS_GRAD 0x02
#define CPIA2_VP_USER_EFFECTS_MIRROR 0x04
#define CPIA2_VP_USER_EFFECTS_FLIP 0x40 // VP5 only
/* NOTE: CPIA2_VP_EXPOSURE_MODES shares the same register as VP5 User
* Effects */
#define CPIA2_VP_EXPOSURE_MODES 0x15
#define CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER 0x20
#define CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP 0x10
#define CPIA2_VP4_EXPOSURE_TARGET 0x16 // VP4
#define CPIA2_VP5_EXPOSURE_TARGET 0x20 // VP5
#define CPIA2_VP_FLICKER_MODES 0x1B
#define CPIA2_VP_FLICKER_MODES_50HZ 0x80
#define CPIA2_VP_FLICKER_MODES_CUSTOM_FLT_FFREQ 0x40
#define CPIA2_VP_FLICKER_MODES_NEVER_FLICKER 0x20
#define CPIA2_VP_FLICKER_MODES_INHIBIT_RUB 0x10
#define CPIA2_VP_FLICKER_MODES_ADJUST_LINE_FREQ 0x08
#define CPIA2_VP_FLICKER_MODES_CUSTOM_INT_FFREQ 0x04
#define CPIA2_VP_UMISC 0x1D
#define CPIA2_VP_UMISC_FORCE_MONO 0x80
#define CPIA2_VP_UMISC_FORCE_ID_MASK 0x40
#define CPIA2_VP_UMISC_INHIBIT_AUTO_FGS 0x20
#define CPIA2_VP_UMISC_INHIBIT_AUTO_DIMS 0x08
#define CPIA2_VP_UMISC_OPT_FOR_SENSOR_DS 0x04
#define CPIA2_VP_UMISC_INHIBIT_AUTO_MODE_INT 0x02
#define CPIA2_VP5_ANTIFLKRSETUP 0x22 //34
#define CPIA2_VP_INTERPOLATION 0x24
#define CPIA2_VP_INTERPOLATION_EVEN_FIRST 0x40
#define CPIA2_VP_INTERPOLATION_HJOG 0x20
#define CPIA2_VP_INTERPOLATION_VJOG 0x10
#define CPIA2_VP_GAMMA 0x25
#define CPIA2_VP_DEFAULT_GAMMA 0x10
#define CPIA2_VP_YRANGE 0x26
#define CPIA2_VP_SATURATION 0x27
#define CPIA2_VP5_MYBLACK_LEVEL 0x3A //58
#define CPIA2_VP5_MCYRANGE 0x3B //59
#define CPIA2_VP5_MYCEILING 0x3C //60
#define CPIA2_VP5_MCUVSATURATION 0x3D //61
#define CPIA2_VP_REHASH_VALUES 0x60
/***
* Common sensor registers
***/
#define CPIA2_SENSOR_DEVICE_H 0x00
#define CPIA2_SENSOR_DEVICE_L 0x01
#define CPIA2_SENSOR_DATA_FORMAT 0x16
#define CPIA2_SENSOR_DATA_FORMAT_HMIRROR 0x08
#define CPIA2_SENSOR_DATA_FORMAT_VMIRROR 0x10
#define CPIA2_SENSOR_CR1 0x76
#define CPIA2_SENSOR_CR1_STAND_BY 0x01
#define CPIA2_SENSOR_CR1_DOWN_RAMP_GEN 0x02
#define CPIA2_SENSOR_CR1_DOWN_COLUMN_ADC 0x04
#define CPIA2_SENSOR_CR1_DOWN_CAB_REGULATOR 0x08
#define CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR 0x10
#define CPIA2_SENSOR_CR1_DOWN_VRT_AMP 0x20
#define CPIA2_SENSOR_CR1_DOWN_BAND_GAP 0x40
#endif

View File

@@ -0,0 +1,914 @@
/****************************************************************************
*
* Filename: cpia2_usb.c
*
* Copyright 2001, STMicrolectronics, Inc.
* Contact: steve.miller@st.com
*
* Description:
* This is a USB driver for CPia2 based video cameras.
* The infrastructure of this driver is based on the cpia usb driver by
* Jochen Scharrlach and Johannes Erdfeldt.
*
* 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 2 of the License, or
* (at your option) any later version.
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Stripped of 2.4 stuff ready for main kernel submit by
* Alan Cox <alan@lxorguk.ukuu.org.uk>
****************************************************************************/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include "cpia2.h"
static int frame_sizes[] = {
0, // USBIF_CMDONLY
0, // USBIF_BULK
128, // USBIF_ISO_1
384, // USBIF_ISO_2
640, // USBIF_ISO_3
768, // USBIF_ISO_4
896, // USBIF_ISO_5
1023, // USBIF_ISO_6
};
#define FRAMES_PER_DESC 10
#define FRAME_SIZE_PER_DESC frame_sizes[cam->cur_alt]
static void process_frame(struct camera_data *cam);
static void cpia2_usb_complete(struct urb *urb);
static int cpia2_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id);
static void cpia2_usb_disconnect(struct usb_interface *intf);
static void free_sbufs(struct camera_data *cam);
static void add_APPn(struct camera_data *cam);
static void add_COM(struct camera_data *cam);
static int submit_urbs(struct camera_data *cam);
static int set_alternate(struct camera_data *cam, unsigned int alt);
static int configure_transfer_mode(struct camera_data *cam, unsigned int alt);
static struct usb_device_id cpia2_id_table[] = {
{USB_DEVICE(0x0553, 0x0100)},
{USB_DEVICE(0x0553, 0x0140)},
{USB_DEVICE(0x0553, 0x0151)}, /* STV0676 */
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, cpia2_id_table);
static struct usb_driver cpia2_driver = {
.name = "cpia2",
.probe = cpia2_usb_probe,
.disconnect = cpia2_usb_disconnect,
.id_table = cpia2_id_table
};
/******************************************************************************
*
* process_frame
*
*****************************************************************************/
static void process_frame(struct camera_data *cam)
{
static int frame_count;
unsigned char *inbuff = cam->workbuff->data;
DBG("Processing frame #%d, current:%d\n",
cam->workbuff->num, cam->curbuff->num);
if(cam->workbuff->length > cam->workbuff->max_length)
cam->workbuff->max_length = cam->workbuff->length;
if ((inbuff[0] == 0xFF) && (inbuff[1] == 0xD8)) {
frame_count++;
} else {
cam->workbuff->status = FRAME_ERROR;
DBG("Start of frame not found\n");
return;
}
/***
* Now the output buffer should have a JPEG image in it.
***/
if(!cam->first_image_seen) {
/* Always skip the first image after streaming
* starts. It is almost certainly corrupt. */
cam->first_image_seen = 1;
cam->workbuff->status = FRAME_EMPTY;
return;
}
if (cam->workbuff->length > 3) {
if(cam->mmapped &&
cam->workbuff->length < cam->workbuff->max_length) {
/* No junk in the buffers */
memset(cam->workbuff->data+cam->workbuff->length,
0, cam->workbuff->max_length-
cam->workbuff->length);
}
cam->workbuff->max_length = cam->workbuff->length;
cam->workbuff->status = FRAME_READY;
if(!cam->mmapped && cam->num_frames > 2) {
/* During normal reading, the most recent
* frame will be read. If the current frame
* hasn't started reading yet, it will never
* be read, so mark it empty. If the buffer is
* mmapped, or we have few buffers, we need to
* wait for the user to free the buffer.
*
* NOTE: This is not entirely foolproof with 3
* buffers, but it would take an EXTREMELY
* overloaded system to cause problems (possible
* image data corruption). Basically, it would
* need to take more time to execute cpia2_read
* than it would for the camera to send
* cam->num_frames-2 frames before problems
* could occur.
*/
cam->curbuff->status = FRAME_EMPTY;
}
cam->curbuff = cam->workbuff;
cam->workbuff = cam->workbuff->next;
DBG("Changed buffers, work:%d, current:%d\n",
cam->workbuff->num, cam->curbuff->num);
return;
} else {
DBG("Not enough data for an image.\n");
}
cam->workbuff->status = FRAME_ERROR;
return;
}
/******************************************************************************
*
* add_APPn
*
* Adds a user specified APPn record
*****************************************************************************/
static void add_APPn(struct camera_data *cam)
{
if(cam->APP_len > 0) {
cam->workbuff->data[cam->workbuff->length++] = 0xFF;
cam->workbuff->data[cam->workbuff->length++] = 0xE0+cam->APPn;
cam->workbuff->data[cam->workbuff->length++] = 0;
cam->workbuff->data[cam->workbuff->length++] = cam->APP_len+2;
memcpy(cam->workbuff->data+cam->workbuff->length,
cam->APP_data, cam->APP_len);
cam->workbuff->length += cam->APP_len;
}
}
/******************************************************************************
*
* add_COM
*
* Adds a user specified COM record
*****************************************************************************/
static void add_COM(struct camera_data *cam)
{
if(cam->COM_len > 0) {
cam->workbuff->data[cam->workbuff->length++] = 0xFF;
cam->workbuff->data[cam->workbuff->length++] = 0xFE;
cam->workbuff->data[cam->workbuff->length++] = 0;
cam->workbuff->data[cam->workbuff->length++] = cam->COM_len+2;
memcpy(cam->workbuff->data+cam->workbuff->length,
cam->COM_data, cam->COM_len);
cam->workbuff->length += cam->COM_len;
}
}
/******************************************************************************
*
* cpia2_usb_complete
*
* callback when incoming packet is received
*****************************************************************************/
static void cpia2_usb_complete(struct urb *urb)
{
int i;
unsigned char *cdata;
static int frame_ready = false;
struct camera_data *cam = (struct camera_data *) urb->context;
if (urb->status!=0) {
if (!(urb->status == -ENOENT ||
urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN))
{
DBG("urb->status = %d!\n", urb->status);
}
DBG("Stopping streaming\n");
return;
}
if (!cam->streaming || !cam->present || cam->open_count == 0) {
LOG("Will now stop the streaming: streaming = %d, "
"present=%d, open_count=%d\n",
cam->streaming, cam->present, cam->open_count);
return;
}
/***
* Packet collater
***/
//DBG("Collating %d packets\n", urb->number_of_packets);
for (i = 0; i < urb->number_of_packets; i++) {
u16 checksum, iso_checksum;
int j;
int n = urb->iso_frame_desc[i].actual_length;
int st = urb->iso_frame_desc[i].status;
if(cam->workbuff->status == FRAME_READY) {
struct framebuf *ptr;
/* Try to find an available buffer */
DBG("workbuff full, searching\n");
for (ptr = cam->workbuff->next;
ptr != cam->workbuff;
ptr = ptr->next)
{
if (ptr->status == FRAME_EMPTY) {
ptr->status = FRAME_READING;
ptr->length = 0;
break;
}
}
if (ptr == cam->workbuff)
break; /* No READING or EMPTY buffers left */
cam->workbuff = ptr;
}
if (cam->workbuff->status == FRAME_EMPTY ||
cam->workbuff->status == FRAME_ERROR) {
cam->workbuff->status = FRAME_READING;
cam->workbuff->length = 0;
}
//DBG(" Packet %d length = %d, status = %d\n", i, n, st);
cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
if (st) {
LOG("cpia2 data error: [%d] len=%d, status = %d\n",
i, n, st);
if(!ALLOW_CORRUPT)
cam->workbuff->status = FRAME_ERROR;
continue;
}
if(n<=2)
continue;
checksum = 0;
for(j=0; j<n-2; ++j)
checksum += cdata[j];
iso_checksum = cdata[j] + cdata[j+1]*256;
if(checksum != iso_checksum) {
LOG("checksum mismatch: [%d] len=%d, calculated = %x, checksum = %x\n",
i, n, (int)checksum, (int)iso_checksum);
if(!ALLOW_CORRUPT) {
cam->workbuff->status = FRAME_ERROR;
continue;
}
}
n -= 2;
if(cam->workbuff->status != FRAME_READING) {
if((0xFF == cdata[0] && 0xD8 == cdata[1]) ||
(0xD8 == cdata[0] && 0xFF == cdata[1] &&
0 != cdata[2])) {
/* frame is skipped, but increment total
* frame count anyway */
cam->frame_count++;
}
DBG("workbuff not reading, status=%d\n",
cam->workbuff->status);
continue;
}
if (cam->frame_size < cam->workbuff->length + n) {
ERR("buffer overflow! length: %d, n: %d\n",
cam->workbuff->length, n);
cam->workbuff->status = FRAME_ERROR;
if(cam->workbuff->length > cam->workbuff->max_length)
cam->workbuff->max_length =
cam->workbuff->length;
continue;
}
if (cam->workbuff->length == 0) {
int data_offset;
if ((0xD8 == cdata[0]) && (0xFF == cdata[1])) {
data_offset = 1;
} else if((0xFF == cdata[0]) && (0xD8 == cdata[1])
&& (0xFF == cdata[2])) {
data_offset = 2;
} else {
DBG("Ignoring packet, not beginning!\n");
continue;
}
DBG("Start of frame pattern found\n");
do_gettimeofday(&cam->workbuff->timestamp);
cam->workbuff->seq = cam->frame_count++;
cam->workbuff->data[0] = 0xFF;
cam->workbuff->data[1] = 0xD8;
cam->workbuff->length = 2;
add_APPn(cam);
add_COM(cam);
memcpy(cam->workbuff->data+cam->workbuff->length,
cdata+data_offset, n-data_offset);
cam->workbuff->length += n-data_offset;
} else if (cam->workbuff->length > 0) {
memcpy(cam->workbuff->data + cam->workbuff->length,
cdata, n);
cam->workbuff->length += n;
}
if ((cam->workbuff->length >= 3) &&
(cam->workbuff->data[cam->workbuff->length - 3] == 0xFF) &&
(cam->workbuff->data[cam->workbuff->length - 2] == 0xD9) &&
(cam->workbuff->data[cam->workbuff->length - 1] == 0xFF)) {
frame_ready = true;
cam->workbuff->data[cam->workbuff->length - 1] = 0;
cam->workbuff->length -= 1;
} else if ((cam->workbuff->length >= 2) &&
(cam->workbuff->data[cam->workbuff->length - 2] == 0xFF) &&
(cam->workbuff->data[cam->workbuff->length - 1] == 0xD9)) {
frame_ready = true;
}
if (frame_ready) {
DBG("Workbuff image size = %d\n",cam->workbuff->length);
process_frame(cam);
frame_ready = false;
if (waitqueue_active(&cam->wq_stream))
wake_up_interruptible(&cam->wq_stream);
}
}
if(cam->streaming) {
/* resubmit */
urb->dev = cam->dev;
if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
ERR("%s: usb_submit_urb ret %d!\n", __func__, i);
}
}
/******************************************************************************
*
* configure_transfer_mode
*
*****************************************************************************/
static int configure_transfer_mode(struct camera_data *cam, unsigned int alt)
{
static unsigned char iso_regs[8][4] = {
{0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00},
{0xB9, 0x00, 0x00, 0x7E},
{0xB9, 0x00, 0x01, 0x7E},
{0xB9, 0x00, 0x02, 0x7E},
{0xB9, 0x00, 0x02, 0xFE},
{0xB9, 0x00, 0x03, 0x7E},
{0xB9, 0x00, 0x03, 0xFD}
};
struct cpia2_command cmd;
unsigned char reg;
if(!cam->present)
return -ENODEV;
/***
* Write the isoc registers according to the alternate selected
***/
cmd.direction = TRANSFER_WRITE;
cmd.buffer.block_data[0] = iso_regs[alt][0];
cmd.buffer.block_data[1] = iso_regs[alt][1];
cmd.buffer.block_data[2] = iso_regs[alt][2];
cmd.buffer.block_data[3] = iso_regs[alt][3];
cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
cmd.start = CPIA2_VC_USB_ISOLIM;
cmd.reg_count = 4;
cpia2_send_command(cam, &cmd);
/***
* Enable relevant streams before starting polling.
* First read USB Stream Config Register.
***/
cmd.direction = TRANSFER_READ;
cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
cmd.start = CPIA2_VC_USB_STRM;
cmd.reg_count = 1;
cpia2_send_command(cam, &cmd);
reg = cmd.buffer.block_data[0];
/* Clear iso, bulk, and int */
reg &= ~(CPIA2_VC_USB_STRM_BLK_ENABLE |
CPIA2_VC_USB_STRM_ISO_ENABLE |
CPIA2_VC_USB_STRM_INT_ENABLE);
if (alt == USBIF_BULK) {
DBG("Enabling bulk xfer\n");
reg |= CPIA2_VC_USB_STRM_BLK_ENABLE; /* Enable Bulk */
cam->xfer_mode = XFER_BULK;
} else if (alt >= USBIF_ISO_1) {
DBG("Enabling ISOC xfer\n");
reg |= CPIA2_VC_USB_STRM_ISO_ENABLE;
cam->xfer_mode = XFER_ISOC;
}
cmd.buffer.block_data[0] = reg;
cmd.direction = TRANSFER_WRITE;
cmd.start = CPIA2_VC_USB_STRM;
cmd.reg_count = 1;
cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
cpia2_send_command(cam, &cmd);
return 0;
}
/******************************************************************************
*
* cpia2_usb_change_streaming_alternate
*
*****************************************************************************/
int cpia2_usb_change_streaming_alternate(struct camera_data *cam,
unsigned int alt)
{
int ret = 0;
if(alt < USBIF_ISO_1 || alt > USBIF_ISO_6)
return -EINVAL;
if(alt == cam->params.camera_state.stream_mode)
return 0;
cpia2_usb_stream_pause(cam);
configure_transfer_mode(cam, alt);
cam->params.camera_state.stream_mode = alt;
/* Reset the camera to prevent image quality degradation */
cpia2_reset_camera(cam);
cpia2_usb_stream_resume(cam);
return ret;
}
/******************************************************************************
*
* set_alternate
*
*****************************************************************************/
static int set_alternate(struct camera_data *cam, unsigned int alt)
{
int ret = 0;
if(alt == cam->cur_alt)
return 0;
if (cam->cur_alt != USBIF_CMDONLY) {
DBG("Changing from alt %d to %d\n", cam->cur_alt, USBIF_CMDONLY);
ret = usb_set_interface(cam->dev, cam->iface, USBIF_CMDONLY);
if (ret != 0)
return ret;
}
if (alt != USBIF_CMDONLY) {
DBG("Changing from alt %d to %d\n", USBIF_CMDONLY, alt);
ret = usb_set_interface(cam->dev, cam->iface, alt);
if (ret != 0)
return ret;
}
cam->old_alt = cam->cur_alt;
cam->cur_alt = alt;
return ret;
}
/******************************************************************************
*
* free_sbufs
*
* Free all cam->sbuf[]. All non-NULL .data and .urb members that are non-NULL
* are assumed to be allocated. Non-NULL .urb members are also assumed to be
* submitted (and must therefore be killed before they are freed).
*****************************************************************************/
static void free_sbufs(struct camera_data *cam)
{
int i;
for (i = 0; i < NUM_SBUF; i++) {
if(cam->sbuf[i].urb) {
usb_kill_urb(cam->sbuf[i].urb);
usb_free_urb(cam->sbuf[i].urb);
cam->sbuf[i].urb = NULL;
}
if(cam->sbuf[i].data) {
kfree(cam->sbuf[i].data);
cam->sbuf[i].data = NULL;
}
}
}
/*******
* Convenience functions
*******/
/****************************************************************************
*
* write_packet
*
***************************************************************************/
static int write_packet(struct usb_device *udev,
u8 request, u8 * registers, u16 start, size_t size)
{
if (!registers || size <= 0)
return -EINVAL;
return usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
request,
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
start, /* value */
0, /* index */
registers, /* buffer */
size,
HZ);
}
/****************************************************************************
*
* read_packet
*
***************************************************************************/
static int read_packet(struct usb_device *udev,
u8 request, u8 * registers, u16 start, size_t size)
{
if (!registers || size <= 0)
return -EINVAL;
return usb_control_msg(udev,
usb_rcvctrlpipe(udev, 0),
request,
USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
start, /* value */
0, /* index */
registers, /* buffer */
size,
HZ);
}
/******************************************************************************
*
* cpia2_usb_transfer_cmd
*
*****************************************************************************/
int cpia2_usb_transfer_cmd(struct camera_data *cam,
void *registers,
u8 request, u8 start, u8 count, u8 direction)
{
int err = 0;
struct usb_device *udev = cam->dev;
if (!udev) {
ERR("%s: Internal driver error: udev is NULL\n", __func__);
return -EINVAL;
}
if (!registers) {
ERR("%s: Internal driver error: register array is NULL\n", __func__);
return -EINVAL;
}
if (direction == TRANSFER_READ) {
err = read_packet(udev, request, (u8 *)registers, start, count);
if (err > 0)
err = 0;
} else if (direction == TRANSFER_WRITE) {
err =write_packet(udev, request, (u8 *)registers, start, count);
if (err < 0) {
LOG("Control message failed, err val = %d\n", err);
LOG("Message: request = 0x%0X, start = 0x%0X\n",
request, start);
LOG("Message: count = %d, register[0] = 0x%0X\n",
count, ((unsigned char *) registers)[0]);
} else
err=0;
} else {
LOG("Unexpected first byte of direction: %d\n",
direction);
return -EINVAL;
}
if(err != 0)
LOG("Unexpected error: %d\n", err);
return err;
}
/******************************************************************************
*
* submit_urbs
*
*****************************************************************************/
static int submit_urbs(struct camera_data *cam)
{
struct urb *urb;
int fx, err, i, j;
for(i=0; i<NUM_SBUF; ++i) {
if (cam->sbuf[i].data)
continue;
cam->sbuf[i].data =
kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
if (!cam->sbuf[i].data) {
while (--i >= 0) {
kfree(cam->sbuf[i].data);
cam->sbuf[i].data = NULL;
}
return -ENOMEM;
}
}
/* We double buffer the Isoc lists, and also know the polling
* interval is every frame (1 == (1 << (bInterval -1))).
*/
for(i=0; i<NUM_SBUF; ++i) {
if(cam->sbuf[i].urb) {
continue;
}
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
if (!urb) {
ERR("%s: usb_alloc_urb error!\n", __func__);
for (j = 0; j < i; j++)
usb_free_urb(cam->sbuf[j].urb);
return -ENOMEM;
}
cam->sbuf[i].urb = urb;
urb->dev = cam->dev;
urb->context = cam;
urb->pipe = usb_rcvisocpipe(cam->dev, 1 /*ISOC endpoint*/);
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = cam->sbuf[i].data;
urb->complete = cpia2_usb_complete;
urb->number_of_packets = FRAMES_PER_DESC;
urb->interval = 1;
urb->transfer_buffer_length =
FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
urb->iso_frame_desc[fx].offset =
FRAME_SIZE_PER_DESC * fx;
urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;
}
}
/* Queue the ISO urbs, and resubmit in the completion handler */
for(i=0; i<NUM_SBUF; ++i) {
err = usb_submit_urb(cam->sbuf[i].urb, GFP_KERNEL);
if (err) {
ERR("usb_submit_urb[%d]() = %d\n", i, err);
return err;
}
}
return 0;
}
/******************************************************************************
*
* cpia2_usb_stream_start
*
*****************************************************************************/
int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate)
{
int ret;
int old_alt;
if(cam->streaming)
return 0;
if (cam->flush) {
int i;
DBG("Flushing buffers\n");
for(i=0; i<cam->num_frames; ++i) {
cam->buffers[i].status = FRAME_EMPTY;
cam->buffers[i].length = 0;
}
cam->curbuff = &cam->buffers[0];
cam->workbuff = cam->curbuff->next;
cam->flush = false;
}
old_alt = cam->params.camera_state.stream_mode;
cam->params.camera_state.stream_mode = 0;
ret = cpia2_usb_change_streaming_alternate(cam, alternate);
if (ret < 0) {
int ret2;
ERR("cpia2_usb_change_streaming_alternate() = %d!\n", ret);
cam->params.camera_state.stream_mode = old_alt;
ret2 = set_alternate(cam, USBIF_CMDONLY);
if (ret2 < 0) {
ERR("cpia2_usb_change_streaming_alternate(%d) =%d has already "
"failed. Then tried to call "
"set_alternate(USBIF_CMDONLY) = %d.\n",
alternate, ret, ret2);
}
} else {
cam->frame_count = 0;
cam->streaming = 1;
ret = cpia2_usb_stream_resume(cam);
}
return ret;
}
/******************************************************************************
*
* cpia2_usb_stream_pause
*
*****************************************************************************/
int cpia2_usb_stream_pause(struct camera_data *cam)
{
int ret = 0;
if(cam->streaming) {
ret = set_alternate(cam, USBIF_CMDONLY);
free_sbufs(cam);
}
return ret;
}
/******************************************************************************
*
* cpia2_usb_stream_resume
*
*****************************************************************************/
int cpia2_usb_stream_resume(struct camera_data *cam)
{
int ret = 0;
if(cam->streaming) {
cam->first_image_seen = 0;
ret = set_alternate(cam, cam->params.camera_state.stream_mode);
if(ret == 0) {
ret = submit_urbs(cam);
}
}
return ret;
}
/******************************************************************************
*
* cpia2_usb_stream_stop
*
*****************************************************************************/
int cpia2_usb_stream_stop(struct camera_data *cam)
{
int ret;
ret = cpia2_usb_stream_pause(cam);
cam->streaming = 0;
configure_transfer_mode(cam, 0);
return ret;
}
/******************************************************************************
*
* cpia2_usb_probe
*
* Probe and initialize.
*****************************************************************************/
static int cpia2_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_interface_descriptor *interface;
struct camera_data *cam;
int ret;
/* A multi-config CPiA2 camera? */
if (udev->descriptor.bNumConfigurations != 1)
return -ENODEV;
interface = &intf->cur_altsetting->desc;
/* If we get to this point, we found a CPiA2 camera */
LOG("CPiA2 USB camera found\n");
if((cam = cpia2_init_camera_struct()) == NULL)
return -ENOMEM;
cam->dev = udev;
cam->iface = interface->bInterfaceNumber;
ret = set_alternate(cam, USBIF_CMDONLY);
if (ret < 0) {
ERR("%s: usb_set_interface error (ret = %d)\n", __func__, ret);
kfree(cam);
return ret;
}
if ((ret = cpia2_register_camera(cam)) < 0) {
ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret);
kfree(cam);
return ret;
}
if((ret = cpia2_init_camera(cam)) < 0) {
ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret);
cpia2_unregister_camera(cam);
kfree(cam);
return ret;
}
LOG(" CPiA Version: %d.%02d (%d.%d)\n",
cam->params.version.firmware_revision_hi,
cam->params.version.firmware_revision_lo,
cam->params.version.asic_id,
cam->params.version.asic_rev);
LOG(" CPiA PnP-ID: %04x:%04x:%04x\n",
cam->params.pnp_id.vendor,
cam->params.pnp_id.product,
cam->params.pnp_id.device_revision);
LOG(" SensorID: %d.(version %d)\n",
cam->params.version.sensor_flags,
cam->params.version.sensor_rev);
usb_set_intfdata(intf, cam);
return 0;
}
/******************************************************************************
*
* cpia2_disconnect
*
*****************************************************************************/
static void cpia2_usb_disconnect(struct usb_interface *intf)
{
struct camera_data *cam = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
cam->present = 0;
DBG("Stopping stream\n");
cpia2_usb_stream_stop(cam);
DBG("Unregistering camera\n");
cpia2_unregister_camera(cam);
if(cam->buffers) {
DBG("Wakeup waiting processes\n");
cam->curbuff->status = FRAME_READY;
cam->curbuff->length = 0;
if (waitqueue_active(&cam->wq_stream))
wake_up_interruptible(&cam->wq_stream);
}
DBG("Releasing interface\n");
usb_driver_release_interface(&cpia2_driver, intf);
if (cam->open_count == 0) {
DBG("Freeing camera structure\n");
kfree(cam);
}
LOG("CPiA2 camera disconnected.\n");
}
/******************************************************************************
*
* usb_cpia2_init
*
*****************************************************************************/
int cpia2_usb_init(void)
{
return usb_register(&cpia2_driver);
}
/******************************************************************************
*
* usb_cpia_cleanup
*
*****************************************************************************/
void cpia2_usb_cleanup(void)
{
schedule_timeout(2 * HZ);
usb_deregister(&cpia2_driver);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
/****************************************************************************
*
* Filename: cpia2dev.h
*
* Copyright 2001, STMicrolectronics, Inc.
*
* Contact: steve.miller@st.com
*
* Description:
* This file provides definitions for applications wanting to use the
* cpia2 driver beyond the generic v4l capabilities.
*
* 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 2 of the License, or
* (at your option) any later version.
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
****************************************************************************/
#ifndef CPIA2_DEV_HEADER
#define CPIA2_DEV_HEADER
#include <linux/videodev.h>
/***
* The following defines are ioctl numbers based on video4linux private ioctls,
* which can range from 192 (BASE_VIDIOCPRIVATE) to 255. All of these take int
* args
*/
#define CPIA2_IOC_SET_GPIO _IOW('v', BASE_VIDIOCPRIVATE + 17, __u32)
/* V4L2 driver specific controls */
#define CPIA2_CID_TARGET_KB (V4L2_CID_PRIVATE_BASE+0)
#define CPIA2_CID_GPIO (V4L2_CID_PRIVATE_BASE+1)
#define CPIA2_CID_FLICKER_MODE (V4L2_CID_PRIVATE_BASE+2)
#define CPIA2_CID_FRAMERATE (V4L2_CID_PRIVATE_BASE+3)
#define CPIA2_CID_USB_ALT (V4L2_CID_PRIVATE_BASE+4)
#define CPIA2_CID_LIGHTS (V4L2_CID_PRIVATE_BASE+5)
#define CPIA2_CID_RESET_CAMERA (V4L2_CID_PRIVATE_BASE+6)
#endif