V4L/DVB (3376): Add cpia2 camera support
There has been a CPIA2 driver out of kernel for a long time and it has been pretty clean for some time too. This is an import of the sourceforge driver which has been stripped of - 2.4 back compatibility - 2.4 old style MJPEG ioctls A couple of functions have been made static and the docs have been repackaged into Documentation/video4linux. The rvmalloc/free functions now match the cpia driver again. Other than that this is the code as is. Tested on x86-64 with a QX5 microscope. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
f05cce863f
commit
ab33d5071d
|
@ -0,0 +1,130 @@
|
|||
$Id: README,v 1.7 2005/08/29 23:39:57 sbertin Exp $
|
||||
|
||||
1. Introduction
|
||||
|
||||
This is a driver for STMicroelectronics's CPiA2 (second generation
|
||||
Colour Processor Interface ASIC) based cameras. This camera outputs an MJPEG
|
||||
stream at up to vga size. It implements the Video4Linux interface as much as
|
||||
possible. Since the V4L interface does not support compressed formats, only
|
||||
an mjpeg enabled application can be used with the camera. We have modified the
|
||||
gqcam application to view this stream.
|
||||
|
||||
The driver is implemented as two kernel modules. The cpia2 module
|
||||
contains the camera functions and the V4L interface. The cpia2_usb module
|
||||
contains usb specific functions. The main reason for this was the size of the
|
||||
module was getting out of hand, so I separted them. It is not likely that
|
||||
there will be a parallel port version.
|
||||
|
||||
FEATURES:
|
||||
- Supports cameras with the Vision stv6410 (CIF) and stv6500 (VGA) cmos
|
||||
sensors. I only have the vga sensor, so can't test the other.
|
||||
- Image formats: VGA, QVGA, CIF, QCIF, and a number of sizes in between.
|
||||
VGA and QVGA are the native image sizes for the VGA camera. CIF is done
|
||||
in the coprocessor by scaling QVGA. All other sizes are done by clipping.
|
||||
- Palette: YCrCb, compressed with MJPEG.
|
||||
- Some compression parameters are settable.
|
||||
- Sensor framerate is adjustable (up to 30 fps CIF, 15 fps VGA).
|
||||
- Adjust brightness, color, contrast while streaming.
|
||||
- Flicker control settable for 50 or 60 Hz mains frequency.
|
||||
|
||||
2. Making and installing the stv672 driver modules:
|
||||
|
||||
Requirements:
|
||||
-------------
|
||||
This should work with 2.4 (2.4.23 and later) and 2.6 kernels, but has
|
||||
only been tested on 2.6. Video4Linux must be either compiled into the kernel or
|
||||
available as a module. Video4Linux2 is automatically detected and made
|
||||
available at compile time.
|
||||
|
||||
Compiling:
|
||||
----------
|
||||
As root, do a make install. This will compile and install the modules
|
||||
into the media/video directory in the module tree. For 2.4 kernels, use
|
||||
Makefile_2.4 (aka do make -f Makefile_2.4 install).
|
||||
|
||||
Setup:
|
||||
------
|
||||
Use 'modprobe cpia2' to load and 'modprobe -r cpia2' to unload. This
|
||||
may be done automatically by your distribution.
|
||||
|
||||
3. Driver options
|
||||
|
||||
Option Description
|
||||
------ -----------
|
||||
video_nr video device to register (0=/dev/video0, etc)
|
||||
range -1 to 64. default is -1 (first available)
|
||||
If you have more than 1 camera, this MUST be -1.
|
||||
buffer_size Size for each frame buffer in bytes (default 68k)
|
||||
num_buffers Number of frame buffers (1-32, default 3)
|
||||
alternate USB Alternate (2-7, default 7)
|
||||
flicker_freq Frequency for flicker reduction(50 or 60, default 60)
|
||||
flicker_mode 0 to disable, or 1 to enable flicker reduction.
|
||||
(default 0). This is only effective if the camera
|
||||
uses a stv0672 coprocessor.
|
||||
|
||||
Setting the options:
|
||||
--------------------
|
||||
If you are using modules, edit /etc/modules.conf and add an options
|
||||
line like this:
|
||||
options cpia2 num_buffers=3 buffer_size=65535
|
||||
|
||||
If the driver is compiled into the kernel, at boot time specify them
|
||||
like this:
|
||||
cpia2=num_buffers:3,buffer_size:65535
|
||||
|
||||
What buffer size should I use?
|
||||
------------------------------
|
||||
The maximum image size depends on the alternate you choose, and the
|
||||
frame rate achieved by the camera. If the compression engine is able to
|
||||
keep up with the frame rate, the maximum image size is given by the table
|
||||
below.
|
||||
The compression engine starts out at maximum compression, and will
|
||||
increase image quality until it is close to the size in the table. As long
|
||||
as the compression engine can keep up with the frame rate, after a short time
|
||||
the images will all be about the size in the table, regardless of resolution.
|
||||
At low alternate settings, the compression engine may not be able to
|
||||
compress the image enough and will reduce the frame rate by producing larger
|
||||
images.
|
||||
The default of 68k should be good for most users. This will handle
|
||||
any alternate at frame rates down to 15fps. For lower frame rates, it may
|
||||
be necessary to increase the buffer size to avoid having frames dropped due
|
||||
to insufficient space.
|
||||
|
||||
Image size(bytes)
|
||||
Alternate bytes/ms 15fps 30fps
|
||||
2 128 8533 4267
|
||||
3 384 25600 12800
|
||||
4 640 42667 21333
|
||||
5 768 51200 25600
|
||||
6 896 59733 29867
|
||||
7 1023 68200 34100
|
||||
|
||||
How many buffers should I use?
|
||||
------------------------------
|
||||
For normal streaming, 3 should give the best results. With only 2,
|
||||
it is possible for the camera to finish sending one image just after a
|
||||
program has started reading the other. If this happens, the driver must drop
|
||||
a frame. The exception to this is if you have a heavily loaded machine. In
|
||||
this case use 2 buffers. You are probably not reading at the full frame rate.
|
||||
If the camera can send multiple images before a read finishes, it could
|
||||
overwrite the third buffer before the read finishes, leading to a corrupt
|
||||
image. Single and double buffering have extra checks to avoid overwriting.
|
||||
|
||||
4. Using the camera
|
||||
|
||||
We are providing a modified gqcam application to view the output. In
|
||||
order to avoid confusion, here it is called mview. There is also the qx5view
|
||||
program which can also control the lights on the qx5 microscope. MJPEG Tools
|
||||
(http://mjpeg.sourceforge.net) can also be used to record from the camera.
|
||||
|
||||
5. Notes to developers:
|
||||
|
||||
- This is a driver version stripped of the 2.4 back compatibility
|
||||
and old MJPEG ioctl API. See cpia2.sf.net for 2.4 support.
|
||||
|
||||
6. Thanks:
|
||||
|
||||
- Peter Pregler <Peter_Pregler@email.com>,
|
||||
Scott J. Bertin <scottbertin@yahoo.com>, and
|
||||
Jarl Totland <Jarl.Totland@bdc.no> for the original cpia driver, which
|
||||
this one was modelled from.
|
|
@ -0,0 +1,38 @@
|
|||
Programmer's View of Cpia2
|
||||
|
||||
Cpia2 is the second generation video coprocessor from VLSI Vision Ltd (now a
|
||||
division of ST Microelectronics). There are two versions. The first is the
|
||||
STV0672, which is capable of up to 30 frames per second (fps) in frame sizes
|
||||
up to CIF, and 15 fps for VGA frames. The STV0676 is an improved version,
|
||||
which can handle up to 30 fps VGA. Both coprocessors can be attached to two
|
||||
CMOS sensors - the vvl6410 CIF sensor and the vvl6500 VGA sensor. These will
|
||||
be referred to as the 410 and the 500 sensors, or the CIF and VGA sensors.
|
||||
|
||||
The two chipsets operate almost identically. The core is an 8051 processor,
|
||||
running two different versions of firmware. The 672 runs the VP4 video
|
||||
processor code, the 676 runs VP5. There are a few differences in register
|
||||
mappings for the two chips. In these cases, the symbols defined in the
|
||||
header files are marked with VP4 or VP5 as part of the symbol name.
|
||||
|
||||
The cameras appear externally as three sets of registers. Setting register
|
||||
values is the only way to control the camera. Some settings are
|
||||
interdependant, such as the sequence required to power up the camera. I will
|
||||
try to make note of all of these cases.
|
||||
|
||||
The register sets are called blocks. Block 0 is the system block. This
|
||||
section is always powered on when the camera is plugged in. It contains
|
||||
registers that control housekeeping functions such as powering up the video
|
||||
processor. The video processor is the VP block. These registers control
|
||||
how the video from the sensor is processed. Examples are timing registers,
|
||||
user mode (vga, qvga), scaling, cropping, framerates, and so on. The last
|
||||
block is the video compressor (VC). The video stream sent from the camera is
|
||||
compressed as Motion JPEG (JPEGA). The VC controls all of the compression
|
||||
parameters. Looking at the file cpia2_registers.h, you can get a full view
|
||||
of these registers and the possible values for most of them.
|
||||
|
||||
One or more registers can be set or read by sending a usb control message to
|
||||
the camera. There are three modes for this. Block mode requests a number
|
||||
of contiguous registers. Random mode reads or writes random registers with
|
||||
a tuple structure containing address/value pairs. The repeat mode is only
|
||||
used by VP4 to load a firmware patch. It contains a starting address and
|
||||
a sequence of bytes to be written into a gpio port.
|
|
@ -142,6 +142,16 @@ config VIDEO_CPIA_USB
|
|||
otherwise say N. This will not work with the Creative Webcam III.
|
||||
It is also available as a module (cpia_usb).
|
||||
|
||||
config VIDEO_CPIA2
|
||||
tristate "CPiA2 Video For Linux"
|
||||
depends on VIDEO_DEV
|
||||
---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).
|
||||
|
||||
config VIDEO_SAA5246A
|
||||
tristate "SAA5246A, SAA5281 Teletext processor"
|
||||
depends on VIDEO_DEV && I2C
|
||||
|
|
|
@ -47,6 +47,7 @@ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
|
|||
obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o
|
||||
obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o
|
||||
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
|
||||
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
|
||||
obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o
|
||||
obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
|
||||
obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
cpia2-objs := cpia2_v4l.o cpia2_usb.o cpia2_core.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_CPIA2) += cpia2.o
|
|
@ -0,0 +1,497 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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 <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
|
||||
***/
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
/* 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 semaphore 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 *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
|
@ -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
|
|
@ -0,0 +1,907 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* 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@redhat.com>
|
||||
****************************************************************************/
|
||||
|
||||
#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, struct pt_regs *);
|
||||
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 = 0;
|
||||
|
||||
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, struct pt_regs *regs)
|
||||
{
|
||||
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
|
||||
*
|
||||
*****************************************************************************/
|
||||
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;
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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
|
@ -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
|
|
@ -0,0 +1,233 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* Filename: cpia2patch.h
|
||||
*
|
||||
* Copyright 2001, STMicrolectronics, Inc.
|
||||
*
|
||||
* Contact: steve.miller@st.com
|
||||
*
|
||||
* Description:
|
||||
* This file contains patch data for the CPiA2 (stv0672) VP4.
|
||||
*
|
||||
* 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_PATCH_HEADER
|
||||
#define CPIA2_PATCH_HEADER
|
||||
|
||||
typedef struct {
|
||||
unsigned char reg;
|
||||
unsigned char count;
|
||||
const unsigned char *data;
|
||||
} cpia2_patch;
|
||||
|
||||
static const unsigned char start_address_hi[1] = {
|
||||
0x01
|
||||
};
|
||||
|
||||
static const unsigned char start_address_lo[1] = {
|
||||
0xBC
|
||||
};
|
||||
|
||||
static const unsigned char patch_block0[64] = {
|
||||
0xE3, 0x02, 0xE3, 0x03, 0xE3, 0x04, 0xE3, 0x05,
|
||||
0xE3, 0x06, 0xE3, 0x07, 0x93, 0x44, 0x56, 0xD4,
|
||||
0x93, 0x4E, 0x56, 0x51, 0x93, 0x4E, 0x51, 0xD6,
|
||||
0x93, 0x4E, 0x4F, 0x54, 0x93, 0x4E, 0x92, 0x4F,
|
||||
0x92, 0xA4, 0x93, 0x05, 0x92, 0xF4, 0x93, 0x1B,
|
||||
0x92, 0x92, 0x91, 0xE6, 0x92, 0x36, 0x92, 0x74,
|
||||
0x92, 0x4A, 0x92, 0x8C, 0x92, 0x8E, 0xC8, 0xD0,
|
||||
0x0B, 0x42, 0x02, 0xA0, 0xCA, 0x92, 0x09, 0x02
|
||||
};
|
||||
|
||||
static const unsigned char patch_block1[64] = {
|
||||
0xC9, 0x10, 0x0A, 0x0A, 0x0A, 0x81, 0xE3, 0xB8,
|
||||
0xE3, 0xB0, 0xE3, 0xA8, 0xE3, 0xA0, 0xE3, 0x98,
|
||||
0xE3, 0x90, 0xE1, 0x00, 0xCF, 0xD7, 0x0A, 0x12,
|
||||
0xCC, 0x95, 0x08, 0xB2, 0x0A, 0x18, 0xE1, 0x00,
|
||||
0x01, 0xEE, 0x0C, 0x08, 0x4A, 0x12, 0xC8, 0x18,
|
||||
0xF0, 0x9A, 0xC0, 0x22, 0xF3, 0x1C, 0x4A, 0x13,
|
||||
0xF3, 0x14, 0xC8, 0xA0, 0xF2, 0x14, 0xF2, 0x1C,
|
||||
0xEB, 0x13, 0xD3, 0xA2, 0x63, 0x16, 0x48, 0x9E
|
||||
};
|
||||
|
||||
static const unsigned char patch_block2[64] = {
|
||||
0xF0, 0x18, 0xA4, 0x03, 0xF3, 0x93, 0xC0, 0x58,
|
||||
0xF7, 0x13, 0x51, 0x9C, 0xE9, 0x20, 0xCF, 0xEF,
|
||||
0x63, 0xF9, 0x92, 0x2E, 0xD3, 0x5F, 0x63, 0xFA,
|
||||
0x92, 0x2E, 0xD3, 0x67, 0x63, 0xFB, 0x92, 0x2E,
|
||||
0xD3, 0x6F, 0xE9, 0x1A, 0x63, 0x16, 0x48, 0xA7,
|
||||
0xF0, 0x20, 0xA4, 0x06, 0xF3, 0x94, 0xC0, 0x27,
|
||||
0xF7, 0x14, 0xF5, 0x13, 0x51, 0x9D, 0xF6, 0x13,
|
||||
0x63, 0x18, 0xC4, 0x20, 0xCB, 0xEF, 0x63, 0xFC
|
||||
};
|
||||
|
||||
static const unsigned char patch_block3[64] = {
|
||||
0x92, 0x2E, 0xD3, 0x77, 0x63, 0xFD, 0x92, 0x2E,
|
||||
0xD3, 0x7F, 0x63, 0xFE, 0x92, 0x2E, 0xD3, 0x87,
|
||||
0x63, 0xFF, 0x92, 0x2E, 0xD3, 0x8F, 0x64, 0x38,
|
||||
0x92, 0x2E, 0xD3, 0x97, 0x64, 0x39, 0x92, 0x2E,
|
||||
0xD3, 0x9F, 0xE1, 0x00, 0xF5, 0x3A, 0xF4, 0x3B,
|
||||
0xF7, 0xBF, 0xF2, 0xBC, 0xF2, 0x3D, 0xE1, 0x00,
|
||||
0x80, 0x87, 0x90, 0x80, 0x51, 0xD5, 0x02, 0x22,
|
||||
0x02, 0x32, 0x4B, 0xD3, 0xF7, 0x11, 0x0B, 0xDA
|
||||
};
|
||||
|
||||
static const unsigned char patch_block4[64] = {
|
||||
0xE1, 0x00, 0x0E, 0x02, 0x02, 0x40, 0x0D, 0xB5,
|
||||
0xE3, 0x02, 0x48, 0x55, 0xE5, 0x12, 0xA4, 0x01,
|
||||
0xE8, 0x1B, 0xE3, 0x90, 0xF0, 0x18, 0xA4, 0x01,
|
||||
0xE8, 0xBF, 0x8D, 0xB8, 0x4B, 0xD1, 0x4B, 0xD8,
|
||||
0x0B, 0xCB, 0x0B, 0xC2, 0xE1, 0x00, 0xE3, 0x02,
|
||||
0xE3, 0x03, 0x52, 0xD3, 0x60, 0x59, 0xE6, 0x93,
|
||||
0x0D, 0x22, 0x52, 0xD4, 0xE6, 0x93, 0x0D, 0x2A,
|
||||
0xE3, 0x98, 0xE3, 0x90, 0xE1, 0x00, 0x02, 0x5D
|
||||
};
|
||||
|
||||
static const unsigned char patch_block5[64] = {
|
||||
0x02, 0x63, 0xE3, 0x02, 0xC8, 0x12, 0x02, 0xCA,
|
||||
0xC8, 0x52, 0x02, 0xC2, 0x82, 0x68, 0xE3, 0x02,
|
||||
0xC8, 0x14, 0x02, 0xCA, 0xC8, 0x90, 0x02, 0xC2,
|
||||
0x0A, 0xD0, 0xC9, 0x93, 0x0A, 0xDA, 0xCC, 0xD2,
|
||||
0x0A, 0xE2, 0x63, 0x12, 0x02, 0xDA, 0x0A, 0x98,
|
||||
0x0A, 0xA0, 0x0A, 0xA8, 0xE3, 0x90, 0xE1, 0x00,
|
||||
0xE3, 0x02, 0x0A, 0xD0, 0xC9, 0x93, 0x0A, 0xDA,
|
||||
0xCC, 0xD2, 0x0A, 0xE2, 0x63, 0x12, 0x02, 0xDA
|
||||
};
|
||||
|
||||
static const unsigned char patch_block6[64] = {
|
||||
0x0A, 0x98, 0x0A, 0xA0, 0x0A, 0xA8, 0x49, 0x91,
|
||||
0xE5, 0x6A, 0xA4, 0x04, 0xC8, 0x12, 0x02, 0xCA,
|
||||
0xC8, 0x52, 0x82, 0x89, 0xC8, 0x14, 0x02, 0xCA,
|
||||
0xC8, 0x90, 0x02, 0xC2, 0xE3, 0x90, 0xE1, 0x00,
|
||||
0x08, 0x60, 0xE1, 0x00, 0x48, 0x53, 0xE8, 0x97,
|
||||
0x08, 0x5A, 0xE1, 0x00, 0xE3, 0x02, 0xE3, 0x03,
|
||||
0x54, 0xD3, 0x60, 0x59, 0xE6, 0x93, 0x0D, 0x52,
|
||||
0xE3, 0x98, 0xE3, 0x90, 0xE1, 0x00, 0x02, 0x9C
|
||||
};
|
||||
|
||||
static const unsigned char patch_block7[64] = {
|
||||
0xE3, 0x02, 0x55, 0x13, 0x93, 0x17, 0x55, 0x13,
|
||||
0x93, 0x17, 0xE3, 0x90, 0xE1, 0x00, 0x75, 0x30,
|
||||
0xE3, 0x02, 0xE3, 0x03, 0x55, 0x55, 0x60, 0x59,
|
||||
0xE6, 0x93, 0x0D, 0xB2, 0xE3, 0x98, 0xE3, 0x90,
|
||||
0xE1, 0x00, 0x02, 0xAE, 0xE7, 0x92, 0xE9, 0x18,
|
||||
0xEA, 0x9A, 0xE8, 0x98, 0xE8, 0x10, 0xE8, 0x11,
|
||||
0xE8, 0x51, 0xD2, 0xDA, 0xD2, 0xF3, 0xE8, 0x13,
|
||||
0xD2, 0xFA, 0xE8, 0x50, 0xD2, 0xEA, 0xE8, 0xD0
|
||||
};
|
||||
|
||||
static const unsigned char patch_block8[64] = {
|
||||
0xE8, 0xD1, 0xD3, 0x0A, 0x03, 0x09, 0x48, 0x23,
|
||||
0xE5, 0x2C, 0xA0, 0x03, 0x48, 0x24, 0xEA, 0x1C,
|
||||
0x03, 0x08, 0xD2, 0xE3, 0xD3, 0x03, 0xD3, 0x13,
|
||||
0xE1, 0x00, 0x02, 0xCB, 0x05, 0x93, 0x57, 0x93,
|
||||
0xF0, 0x9A, 0xAC, 0x0B, 0xE3, 0x07, 0x92, 0xEA,
|
||||
0xE2, 0x9F, 0xE5, 0x06, 0xE3, 0xB0, 0xA0, 0x02,
|
||||
0xEB, 0x1E, 0x82, 0xD7, 0xEA, 0x1E, 0xE2, 0x3B,
|
||||
0x85, 0x9B, 0xE9, 0x1E, 0xC8, 0x90, 0x85, 0x94
|
||||
};
|
||||
|
||||
static const unsigned char patch_block9[64] = {
|
||||
0x02, 0xDE, 0x05, 0x80, 0x57, 0x93, 0xF0, 0xBA,
|
||||
0xAC, 0x06, 0x92, 0xEA, 0xE2, 0xBF, 0xE5, 0x06,
|
||||
0xA0, 0x01, 0xEB, 0xBF, 0x85, 0x88, 0xE9, 0x3E,
|
||||
0xC8, 0x90, 0x85, 0x81, 0xE9, 0x3E, 0xF0, 0xBA,
|
||||
0xF3, 0x39, 0xF0, 0x3A, 0x60, 0x17, 0xF0, 0x3A,
|
||||
0xC0, 0x90, 0xF0, 0xBA, 0xE1, 0x00, 0x00, 0x3F,
|
||||
0xE3, 0x02, 0xE3, 0x03, 0x58, 0x10, 0x60, 0x59,
|
||||
0xE6, 0x93, 0x0D, 0xA2, 0x58, 0x12, 0xE6, 0x93
|
||||
};
|
||||
|
||||
static const unsigned char patch_block10[64] = {
|
||||
0x0D, 0xAA, 0xE3, 0x98, 0xE3, 0x90, 0xE1, 0x00,
|
||||
0x03, 0x01, 0xE1, 0x00, 0x03, 0x03, 0x9B, 0x7D,
|
||||
0x8B, 0x8B, 0xE3, 0x02, 0xE3, 0x03, 0x58, 0x56,
|
||||
0x60, 0x59, 0xE6, 0x93, 0x0D, 0xBA, 0xE3, 0x98,
|
||||
0xE3, 0x90, 0xE1, 0x00, 0x03, 0x0F, 0x93, 0x11,
|
||||
0xE1, 0x00, 0xE3, 0x02, 0x4A, 0x11, 0x0B, 0x42,
|
||||
0x91, 0xAF, 0xE3, 0x90, 0xE1, 0x00, 0xF2, 0x91,
|
||||
0xF0, 0x91, 0xA3, 0xFE, 0xE1, 0x00, 0x60, 0x92
|
||||
};
|
||||
|
||||
static const unsigned char patch_block11[64] = {
|
||||
0xC0, 0x5F, 0xF0, 0x13, 0xF0, 0x13, 0x59, 0x5B,
|
||||
0xE2, 0x13, 0xF0, 0x11, 0x5A, 0x19, 0xE2, 0x13,
|
||||
0xE1, 0x00, 0x00, 0x00, 0x03, 0x27, 0x68, 0x61,
|
||||
0x76, 0x61, 0x6E, 0x61, 0x00, 0x06, 0x03, 0x2C,
|
||||
0xE3, 0x02, 0xE3, 0x03, 0xE9, 0x38, 0x59, 0x15,
|
||||
0x59, 0x5A, 0xF2, 0x9A, 0xBC, 0x0B, 0xA4, 0x0A,
|
||||
0x59, 0x1E, 0xF3, 0x11, 0xF0, 0x1A, 0xE2, 0xBB,
|
||||
0x59, 0x15, 0xF0, 0x11, 0x19, 0x2A, 0xE5, 0x02
|
||||
};
|
||||
|
||||
static const unsigned char patch_block12[54] = {
|
||||
0xA4, 0x01, 0xEB, 0xBF, 0xE3, 0x98, 0xE3, 0x90,
|
||||
0xE1, 0x00, 0x03, 0x42, 0x19, 0x28, 0xE1, 0x00,
|
||||
0xE9, 0x30, 0x60, 0x79, 0xE1, 0x00, 0xE3, 0x03,
|
||||
0xE3, 0x07, 0x60, 0x79, 0x93, 0x4E, 0xE3, 0xB8,
|
||||
0xE3, 0x98, 0xE1, 0x00, 0xE9, 0x1A, 0xF0, 0x1F,
|
||||
0xE2, 0x33, 0xF0, 0x91, 0xE2, 0x92, 0xE0, 0x32,
|
||||
0xF0, 0x31, 0xE1, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char do_call[1] = {
|
||||
0x01
|
||||
};
|
||||
|
||||
|
||||
#define PATCH_DATA_SIZE 18
|
||||
|
||||
static const cpia2_patch patch_data[PATCH_DATA_SIZE] = {
|
||||
{0x0A, sizeof(start_address_hi), start_address_hi}
|
||||
, // 0
|
||||
{0x0B, sizeof(start_address_lo), start_address_lo}
|
||||
, // 1
|
||||
{0x0C, sizeof(patch_block0), patch_block0}
|
||||
, // 2
|
||||
{0x0C, sizeof(patch_block1), patch_block1}
|
||||
, // 3
|
||||
{0x0C, sizeof(patch_block2), patch_block2}
|
||||
, // 4
|
||||
{0x0C, sizeof(patch_block3), patch_block3}
|
||||
, // 5
|
||||
{0x0C, sizeof(patch_block4), patch_block4}
|
||||
, // 6
|
||||
{0x0C, sizeof(patch_block5), patch_block5}
|
||||
, // 7
|
||||
{0x0C, sizeof(patch_block6), patch_block6}
|
||||
, // 8
|
||||
{0x0C, sizeof(patch_block7), patch_block7}
|
||||
, // 9
|
||||
{0x0C, sizeof(patch_block8), patch_block8}
|
||||
, // 10
|
||||
{0x0C, sizeof(patch_block9), patch_block9}
|
||||
, //11
|
||||
{0x0C, sizeof(patch_block10), patch_block10}
|
||||
, // 12
|
||||
{0x0C, sizeof(patch_block11), patch_block11}
|
||||
, // 13
|
||||
{0x0C, sizeof(patch_block12), patch_block12}
|
||||
, // 14
|
||||
{0x0A, sizeof(start_address_hi), start_address_hi}
|
||||
, // 15
|
||||
{0x0B, sizeof(start_address_lo), start_address_lo}
|
||||
, // 16
|
||||
{0x0D, sizeof(do_call), do_call} //17
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue