media: cpia2: remove deprecated driver
The cpia2 driver does not use the vb2 framework for streaming video, instead it implements this in the driver. This is error prone, and nobody stepped in to convert this driver to that framework. The hardware is very old, so the decision was made to remove it altogether. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
parent
ba47652ba6
commit
9ea8a9c72a
|
@ -1,145 +0,0 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
The cpia2 driver
|
||||
================
|
||||
|
||||
Authors: 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.
|
||||
|
||||
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 separated 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.
|
||||
|
||||
Making and installing the stv672 driver modules
|
||||
-----------------------------------------------
|
||||
|
||||
Requirements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Video4Linux must be either compiled into the kernel or
|
||||
available as a module. Video4Linux2 is automatically detected and made
|
||||
available at compile time.
|
||||
|
||||
Setup
|
||||
~~~~~
|
||||
|
||||
Use ``modprobe cpia2`` to load and ``modprobe -r cpia2`` to unload. This
|
||||
may be done automatically by your distribution.
|
||||
|
||||
Driver options
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
.. tabularcolumns:: |p{13ex}|L|
|
||||
|
||||
|
||||
============== ========================================================
|
||||
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 cpia2.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.
|
||||
|
||||
========== ========== ======== =====
|
||||
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
|
||||
========== ========== ======== =====
|
||||
|
||||
Table: Image size(bytes)
|
||||
|
||||
|
||||
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.
|
||||
|
||||
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.
|
|
@ -14,8 +14,6 @@ dvb-as102 nBox DVB-T Dongle 0b89:0007
|
|||
dvb-as102 Sky IT Digital Key (green led) 2137:0001
|
||||
b2c2-flexcop-usb Technisat/B2C2 FlexCop II/IIb/III 0af7:0101
|
||||
Digital TV
|
||||
cpia2 Vision's CPiA2 cameras 0553:0100, 0553:0140,
|
||||
such as the Digital Blue QX5 0553:0151
|
||||
go7007 WIS GO7007 MPEG encoder 1943:a250, 093b:a002,
|
||||
093b:a004, 0eb1:6666,
|
||||
0eb1:6668
|
||||
|
|
|
@ -43,7 +43,6 @@ Driver Name
|
|||
airspy AirSpy
|
||||
au0828 Auvitek AU0828
|
||||
b2c2-flexcop-usb Technisat/B2C2 Air/Sky/Cable2PC USB
|
||||
cpia2 CPiA2 Video For Linux
|
||||
cx231xx Conexant cx231xx USB video capture
|
||||
dvb-as102 Abilis AS102 DVB receiver
|
||||
dvb-ttusb-budget Technotrend/Hauppauge Nova - USB devices
|
||||
|
|
|
@ -11,7 +11,6 @@ Video4Linux (V4L) driver-specific documentation
|
|||
|
||||
bttv
|
||||
cafe_ccic
|
||||
cpia2
|
||||
cx88
|
||||
davinci-vpbe
|
||||
fimc
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
The cpia2 driver
|
||||
================
|
||||
|
||||
Authors: 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.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Programmer's overview of cpia2 driver
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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.
|
|
@ -13,7 +13,6 @@ Video4Linux (V4L) drivers
|
|||
:maxdepth: 5
|
||||
|
||||
bttv-devel
|
||||
cpia2_devel
|
||||
cx2341x-devel
|
||||
cx88-devel
|
||||
davinci-vpbe-devel
|
||||
|
|
|
@ -52,7 +52,6 @@ menuconfig STAGING_MEDIA_DEPRECATED
|
|||
|
||||
if STAGING_MEDIA_DEPRECATED
|
||||
source "drivers/staging/media/deprecated/atmel/Kconfig"
|
||||
source "drivers/staging/media/deprecated/cpia2/Kconfig"
|
||||
source "drivers/staging/media/deprecated/fsl-viu/Kconfig"
|
||||
source "drivers/staging/media/deprecated/saa7146/Kconfig"
|
||||
source "drivers/staging/media/deprecated/stkwebcam/Kconfig"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_VIDEO_ATMEL_ISC_BASE) += deprecated/atmel/
|
||||
obj-$(CONFIG_INTEL_ATOMISP) += atomisp/
|
||||
obj-$(CONFIG_VIDEO_CPIA2) += deprecated/cpia2/
|
||||
obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/
|
||||
obj-$(CONFIG_VIDEO_MAX96712) += max96712/
|
||||
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config VIDEO_CPIA2
|
||||
tristate "CPiA2 Video For Linux (DEPRECATED)"
|
||||
depends on USB && 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 deprecated and is scheduled for removal by
|
||||
the beginning of 2023. See the TODO file for more information.
|
||||
|
||||
This driver is also available as a module (cpia2).
|
|
@ -1,4 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
cpia2-objs := cpia2_v4l.o cpia2_usb.o cpia2_core.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_CPIA2) += cpia2.o
|
|
@ -1,6 +0,0 @@
|
|||
The cpia2 driver does not use the vb2 framework for streaming
|
||||
video, instead it implements this in the driver.
|
||||
|
||||
To prevent removal of this driver early 2023 it has to be
|
||||
converted to use vb2. Contact the linux-media@vger.kernel.org
|
||||
mailing list if you want to do this.
|
|
@ -1,475 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CPIA2_H__
|
||||
#define __CPIA2_H__
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/poll.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
|
||||
#include "cpia2_registers.h"
|
||||
|
||||
/* define for verbose debug output */
|
||||
//#define _CPIA2_DEBUG_
|
||||
|
||||
/***
|
||||
* 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 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
|
||||
|
||||
/* 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 */
|
||||
} 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 quality;
|
||||
} 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 {
|
||||
u64 ts;
|
||||
unsigned long seq;
|
||||
int num;
|
||||
int length;
|
||||
int max_length;
|
||||
volatile enum frame_status status;
|
||||
u8 *data;
|
||||
struct framebuf *next;
|
||||
};
|
||||
|
||||
struct camera_data {
|
||||
/* locks */
|
||||
struct v4l2_device v4l2_dev;
|
||||
struct mutex v4l2_lock; /* serialize file operations */
|
||||
struct v4l2_ctrl_handler hdl;
|
||||
struct {
|
||||
/* Lights control cluster */
|
||||
struct v4l2_ctrl *top_light;
|
||||
struct v4l2_ctrl *bottom_light;
|
||||
};
|
||||
struct v4l2_ctrl *usb_alt;
|
||||
|
||||
/* camera status */
|
||||
int first_image_seen;
|
||||
enum sensors sensor_type;
|
||||
u8 flush;
|
||||
struct v4l2_fh *stream_fh;
|
||||
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 */
|
||||
u32 width;
|
||||
u32 height; /* Its size */
|
||||
__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);
|
||||
void cpia2_camera_release(struct v4l2_device *v4l2_dev);
|
||||
|
||||
/* 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);
|
||||
void cpia2_deinit_camera_struct(struct camera_data *cam, struct usb_interface *intf);
|
||||
struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf);
|
||||
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);
|
||||
__poll_t 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_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
|
@ -1,463 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/****************************************************************************
|
||||
*
|
||||
* Filename: cpia2registers.h
|
||||
*
|
||||
* Copyright 2001, STMicrolectronics, Inc.
|
||||
*
|
||||
* Description:
|
||||
* Definitions for the CPia2 register set
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#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
|
|
@ -1,966 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 <linux/module.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 int cpia2_usb_suspend(struct usb_interface *intf, pm_message_t message);
|
||||
static int cpia2_usb_resume(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 const 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,
|
||||
.suspend = cpia2_usb_suspend,
|
||||
.resume = cpia2_usb_resume,
|
||||
.reset_resume = cpia2_usb_resume,
|
||||
.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 bool 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 || !video_is_registered(&cam->vdev)) {
|
||||
LOG("Will now stop the streaming: streaming = %d, present=%d\n",
|
||||
cam->streaming, video_is_registered(&cam->vdev));
|
||||
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");
|
||||
cam->workbuff->ts = ktime_get_ns();
|
||||
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 (!video_is_registered(&cam->vdev))
|
||||
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)
|
||||
{
|
||||
unsigned char *buf;
|
||||
int ret;
|
||||
|
||||
if (!registers || size <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
buf = kmemdup(registers, size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = usb_control_msg(udev,
|
||||
usb_sndctrlpipe(udev, 0),
|
||||
request,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
start, /* value */
|
||||
0, /* index */
|
||||
buf, /* buffer */
|
||||
size,
|
||||
1000);
|
||||
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* read_packet
|
||||
*
|
||||
***************************************************************************/
|
||||
static int read_packet(struct usb_device *udev,
|
||||
u8 request, u8 * registers, u16 start, size_t size)
|
||||
{
|
||||
unsigned char *buf;
|
||||
int ret;
|
||||
|
||||
if (!registers || size <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
buf = kmalloc(size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = usb_control_msg(udev,
|
||||
usb_rcvctrlpipe(udev, 0),
|
||||
request,
|
||||
USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
|
||||
start, /* value */
|
||||
0, /* index */
|
||||
buf, /* buffer */
|
||||
size,
|
||||
1000);
|
||||
|
||||
if (ret >= 0)
|
||||
memcpy(registers, buf, size);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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_array(FRAME_SIZE_PER_DESC, FRAMES_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) {
|
||||
for (j = 0; j < i; j++)
|
||||
usb_free_urb(cam->sbuf[j].urb);
|
||||
for (j = 0; j < NUM_SBUF; j++) {
|
||||
kfree(cam->sbuf[j].data);
|
||||
cam->sbuf[j].data = NULL;
|
||||
}
|
||||
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) {
|
||||
free_sbufs(cam);
|
||||
ret = set_alternate(cam, USBIF_CMDONLY);
|
||||
}
|
||||
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) {
|
||||
/* for some reason the user effects need to be set
|
||||
again when starting streaming. */
|
||||
cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE,
|
||||
cam->params.vp_params.user_effects);
|
||||
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");
|
||||
|
||||
cam = cpia2_init_camera_struct(intf);
|
||||
if (cam == 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);
|
||||
goto alt_err;
|
||||
}
|
||||
|
||||
|
||||
if((ret = cpia2_init_camera(cam)) < 0) {
|
||||
ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret);
|
||||
goto alt_err;
|
||||
}
|
||||
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);
|
||||
|
||||
ret = cpia2_register_camera(cam);
|
||||
if (ret < 0) {
|
||||
ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret);
|
||||
goto alt_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
alt_err:
|
||||
cpia2_deinit_camera_struct(cam, intf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* cpia2_disconnect
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void cpia2_usb_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct camera_data *cam = usb_get_intfdata(intf);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
|
||||
DBG("Stopping stream\n");
|
||||
cpia2_usb_stream_stop(cam);
|
||||
|
||||
mutex_lock(&cam->v4l2_lock);
|
||||
DBG("Unregistering camera\n");
|
||||
cpia2_unregister_camera(cam);
|
||||
v4l2_device_disconnect(&cam->v4l2_dev);
|
||||
mutex_unlock(&cam->v4l2_lock);
|
||||
|
||||
if(cam->buffers) {
|
||||
DBG("Wakeup waiting processes\n");
|
||||
cam->curbuff->status = FRAME_READY;
|
||||
cam->curbuff->length = 0;
|
||||
wake_up_interruptible(&cam->wq_stream);
|
||||
}
|
||||
|
||||
v4l2_device_put(&cam->v4l2_dev);
|
||||
|
||||
LOG("CPiA2 camera disconnected.\n");
|
||||
}
|
||||
|
||||
static int cpia2_usb_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
{
|
||||
struct camera_data *cam = usb_get_intfdata(intf);
|
||||
|
||||
mutex_lock(&cam->v4l2_lock);
|
||||
if (cam->streaming) {
|
||||
cpia2_usb_stream_stop(cam);
|
||||
cam->streaming = 1;
|
||||
}
|
||||
mutex_unlock(&cam->v4l2_lock);
|
||||
|
||||
dev_info(&intf->dev, "going into suspend..\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Resume device - start device. */
|
||||
static int cpia2_usb_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct camera_data *cam = usb_get_intfdata(intf);
|
||||
|
||||
mutex_lock(&cam->v4l2_lock);
|
||||
v4l2_ctrl_handler_setup(&cam->hdl);
|
||||
if (cam->streaming) {
|
||||
cam->streaming = 0;
|
||||
cpia2_usb_stream_start(cam,
|
||||
cam->params.camera_state.stream_mode);
|
||||
}
|
||||
mutex_unlock(&cam->v4l2_lock);
|
||||
|
||||
dev_info(&intf->dev, "coming out of suspend..\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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
Loading…
Reference in New Issue