summaryrefslogtreecommitdiffstats
path: root/drivers/staging/cpia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/cpia')
-rw-r--r--drivers/staging/cpia/Kconfig39
-rw-r--r--drivers/staging/cpia/Makefile5
-rw-r--r--drivers/staging/cpia/TODO8
-rw-r--r--drivers/staging/cpia/cpia.c4028
-rw-r--r--drivers/staging/cpia/cpia.h432
-rw-r--r--drivers/staging/cpia/cpia_pp.c869
-rw-r--r--drivers/staging/cpia/cpia_usb.c640
7 files changed, 0 insertions, 6021 deletions
diff --git a/drivers/staging/cpia/Kconfig b/drivers/staging/cpia/Kconfig
deleted file mode 100644
index 205d247..0000000
--- a/drivers/staging/cpia/Kconfig
+++ /dev/null
@@ -1,39 +0,0 @@
-config VIDEO_CPIA
- tristate "CPiA Video For Linux (DEPRECATED)"
- depends on VIDEO_V4L1
- default n
- ---help---
- This driver is DEPRECATED please use the gspca cpia1 module
- instead. Note that you need atleast version 0.6.4 of libv4l for
- the cpia1 gspca module.
-
- This is the video4linux driver for cameras based on Vision's CPiA
- (Colour Processor Interface ASIC), such as the Creative Labs Video
- Blaster Webcam II. If you have one of these cameras, say Y here
- and select parallel port and/or USB lowlevel support below,
- otherwise say N. This will not work with the Creative Webcam III.
-
- Please read <file:Documentation/video4linux/README.cpia> for more
- information.
-
- This driver is also available as a module (cpia).
-
-config VIDEO_CPIA_PP
- tristate "CPiA Parallel Port Lowlevel Support"
- depends on PARPORT_1284 && VIDEO_CPIA && PARPORT
- help
- This is the lowlevel parallel port support for cameras based on
- Vision's CPiA (Colour Processor Interface ASIC), such as the
- Creative Webcam II. If you have the parallel port version of one
- of these cameras, say Y here, otherwise say N. It is also available
- as a module (cpia_pp).
-
-config VIDEO_CPIA_USB
- tristate "CPiA USB Lowlevel Support"
- depends on VIDEO_CPIA && USB
- help
- This is the lowlevel USB support for cameras based on Vision's CPiA
- (Colour Processor Interface ASIC), such as the Creative Webcam II.
- If you have the USB version of one of these cameras, say Y here,
- otherwise say N. This will not work with the Creative Webcam III.
- It is also available as a module (cpia_usb).
diff --git a/drivers/staging/cpia/Makefile b/drivers/staging/cpia/Makefile
deleted file mode 100644
index 89e52f1..0000000
--- a/drivers/staging/cpia/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_VIDEO_CPIA) += cpia.o
-obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
-obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o
-
-EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/staging/cpia/TODO b/drivers/staging/cpia/TODO
deleted file mode 100644
index ccb1c07..0000000
--- a/drivers/staging/cpia/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-This is an obsolete driver for some cpia-based webcams that use the parallel port.
-We couldn't find anyone with this hardware in order to port it to use V4L2.
-
-Also, parallel-port webcams are obsolete nowadays.
-
-If nobody take care on it, the driver will be removed for 2.6.38.
-
-Please send patches to linux-media@vger.kernel.org
diff --git a/drivers/staging/cpia/cpia.c b/drivers/staging/cpia/cpia.c
deleted file mode 100644
index 0e740b8..0000000
--- a/drivers/staging/cpia/cpia.c
+++ /dev/null
@@ -1,4028 +0,0 @@
-/*
- * cpia CPiA driver
- *
- * Supports CPiA based Video Camera's.
- *
- * (C) Copyright 1999-2000 Peter Pregler
- * (C) Copyright 1999-2000 Scott J. Bertin
- * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
- * (C) Copyright 2000 STMicroelectronics
- *
- * 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.
- */
-
-/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
-/* #define _CPIA_DEBUG_ 1 */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/ctype.h>
-#include <linux/pagemap.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <linux/mutex.h>
-
-#include "cpia.h"
-
-static int video_nr = -1;
-
-#ifdef MODULE
-module_param(video_nr, int, 0);
-MODULE_AUTHOR("Scott J. Bertin <sbertin@securenym.net> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <johannes@erdfelt.com>");
-MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("video");
-#endif
-
-static unsigned short colorspace_conv;
-module_param(colorspace_conv, ushort, 0444);
-MODULE_PARM_DESC(colorspace_conv,
- " Colorspace conversion:"
- "\n 0 = disable, 1 = enable"
- "\n Default value is 0"
- );
-
-#define ABOUT "V4L-Driver for Vision CPiA based cameras"
-
-#define CPIA_MODULE_CPIA (0<<5)
-#define CPIA_MODULE_SYSTEM (1<<5)
-#define CPIA_MODULE_VP_CTRL (5<<5)
-#define CPIA_MODULE_CAPTURE (6<<5)
-#define CPIA_MODULE_DEBUG (7<<5)
-
-#define INPUT (DATA_IN << 8)
-#define OUTPUT (DATA_OUT << 8)
-
-#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1)
-#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2)
-#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3)
-#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4)
-#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5)
-#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7)
-#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8)
-#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10)
-
-#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1)
-#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2)
-#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3)
-#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4)
-#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5)
-#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6)
-#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7)
-#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8)
-#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9)
-#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10)
-#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11)
-#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12)
-#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13)
-
-#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1)
-#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2)
-#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3)
-#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4)
-#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6)
-#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7)
-#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8)
-#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9)
-#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10)
-#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11)
-#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16)
-#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17)
-#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18)
-#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19)
-#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25)
-#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30)
-#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31)
-
-#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1)
-#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2)
-#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3)
-#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4)
-#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5)
-#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6)
-#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7)
-#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8)
-#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9)
-#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10)
-#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
-#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12)
-#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
-#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14)
-#define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15)
-
-#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1)
-#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4)
-#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5)
-#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6)
-#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8)
-#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9)
-#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10)
-#define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11)
-
-enum {
- FRAME_READY, /* Ready to grab into */
- FRAME_GRABBING, /* In the process of being grabbed into */
- FRAME_DONE, /* Finished grabbing, but not been synced yet */
- FRAME_UNUSED, /* Unused (no MCAPTURE) */
-};
-
-#define COMMAND_NONE 0x0000
-#define COMMAND_SETCOMPRESSION 0x0001
-#define COMMAND_SETCOMPRESSIONTARGET 0x0002
-#define COMMAND_SETCOLOURPARAMS 0x0004
-#define COMMAND_SETFORMAT 0x0008
-#define COMMAND_PAUSE 0x0010
-#define COMMAND_RESUME 0x0020
-#define COMMAND_SETYUVTHRESH 0x0040
-#define COMMAND_SETECPTIMING 0x0080
-#define COMMAND_SETCOMPRESSIONPARAMS 0x0100
-#define COMMAND_SETEXPOSURE 0x0200
-#define COMMAND_SETCOLOURBALANCE 0x0400
-#define COMMAND_SETSENSORFPS 0x0800
-#define COMMAND_SETAPCOR 0x1000
-#define COMMAND_SETFLICKERCTRL 0x2000
-#define COMMAND_SETVLOFFSET 0x4000
-#define COMMAND_SETLIGHTS 0x8000
-
-#define ROUND_UP_EXP_FOR_FLICKER 15
-
-/* Constants for automatic frame rate adjustment */
-#define MAX_EXP 302
-#define MAX_EXP_102 255
-#define LOW_EXP 140
-#define VERY_LOW_EXP 70
-#define TC 94
-#define EXP_ACC_DARK 50
-#define EXP_ACC_LIGHT 90
-#define HIGH_COMP_102 160
-#define MAX_COMP 239
-#define DARK_TIME 3
-#define LIGHT_TIME 3
-
-/* Maximum number of 10ms loops to wait for the stream to become ready */
-#define READY_TIMEOUT 100
-
-/* Developer's Guide Table 5 p 3-34
- * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
-static u8 flicker_jumps[2][2][4] =
-{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
- { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
-};
-
-/* forward declaration of local function */
-static void reset_camera_struct(struct cam_data *cam);
-static int find_over_exposure(int brightness);
-static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
- int on);
-
-
-/**********************************************************************
- *
- * Memory management
- *
- **********************************************************************/
-static void *rvmalloc(unsigned long size)
-{
- void *mem;
- unsigned long adr;
-
- size = PAGE_ALIGN(size);
- mem = vmalloc_32(size);
- if (!mem)
- return NULL;
-
- memset(mem, 0, size); /* Clear the ram out, no junk to the user */
- adr = (unsigned long) mem;
- while (size > 0) {
- SetPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
- unsigned long adr;
-
- if (!mem)
- return;
-
- adr = (unsigned long) mem;
- while ((long) size > 0) {
- ClearPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- vfree(mem);
-}
-
-/**********************************************************************
- *
- * /proc interface
- *
- **********************************************************************/
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *cpia_proc_root=NULL;
-
-static int cpia_proc_show(struct seq_file *m, void *v)
-{
- struct cam_data *cam = m->private;
- int tmp;
- char tmpstr[29];
-
- seq_printf(m, "read-only\n-----------------------\n");
- seq_printf(m, "V4L Driver version: %d.%d.%d\n",
- CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
- seq_printf(m, "CPIA Version: %d.%02d (%d.%d)\n",
- cam->params.version.firmwareVersion,
- cam->params.version.firmwareRevision,
- cam->params.version.vcVersion,
- cam->params.version.vcRevision);
- seq_printf(m, "CPIA PnP-ID: %04x:%04x:%04x\n",
- cam->params.pnpID.vendor, cam->params.pnpID.product,
- cam->params.pnpID.deviceRevision);
- seq_printf(m, "VP-Version: %d.%d %04x\n",
- cam->params.vpVersion.vpVersion,
- cam->params.vpVersion.vpRevision,
- cam->params.vpVersion.cameraHeadID);
-
- seq_printf(m, "system_state: %#04x\n",
- cam->params.status.systemState);
- seq_printf(m, "grab_state: %#04x\n",
- cam->params.status.grabState);
- seq_printf(m, "stream_state: %#04x\n",
- cam->params.status.streamState);
- seq_printf(m, "fatal_error: %#04x\n",
- cam->params.status.fatalError);
- seq_printf(m, "cmd_error: %#04x\n",
- cam->params.status.cmdError);
- seq_printf(m, "debug_flags: %#04x\n",
- cam->params.status.debugFlags);
- seq_printf(m, "vp_status: %#04x\n",
- cam->params.status.vpStatus);
- seq_printf(m, "error_code: %#04x\n",
- cam->params.status.errorCode);
- /* QX3 specific entries */
- if (cam->params.qx3.qx3_detected) {
- seq_printf(m, "button: %4d\n",
- cam->params.qx3.button);
- seq_printf(m, "cradled: %4d\n",
- cam->params.qx3.cradled);
- }
- seq_printf(m, "video_size: %s\n",
- cam->params.format.videoSize == VIDEOSIZE_CIF ?
- "CIF " : "QCIF");
- seq_printf(m, "roi: (%3d, %3d) to (%3d, %3d)\n",
- cam->params.roi.colStart*8,
- cam->params.roi.rowStart*4,
- cam->params.roi.colEnd*8,
- cam->params.roi.rowEnd*4);
- seq_printf(m, "actual_fps: %3d\n", cam->fps);
- seq_printf(m, "transfer_rate: %4dkB/s\n",
- cam->transfer_rate);
-
- seq_printf(m, "\nread-write\n");
- seq_printf(m, "----------------------- current min"
- " max default comment\n");
- seq_printf(m, "brightness: %8d %8d %8d %8d\n",
- cam->params.colourParams.brightness, 0, 100, 50);
- if (cam->params.version.firmwareVersion == 1 &&
- cam->params.version.firmwareRevision == 2)
- /* 1-02 firmware limits contrast to 80 */
- tmp = 80;
- else
- tmp = 96;
-
- seq_printf(m, "contrast: %8d %8d %8d %8d"
- " steps of 8\n",
- cam->params.colourParams.contrast, 0, tmp, 48);
- seq_printf(m, "saturation: %8d %8d %8d %8d\n",
- cam->params.colourParams.saturation, 0, 100, 50);
- tmp = (25000+5000*cam->params.sensorFps.baserate)/
- (1<<cam->params.sensorFps.divisor);
- seq_printf(m, "sensor_fps: %4d.%03d %8d %8d %8d\n",
- tmp/1000, tmp%1000, 3, 30, 15);
- seq_printf(m, "stream_start_line: %8d %8d %8d %8d\n",
- 2*cam->params.streamStartLine, 0,
- cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144,
- cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120);
- seq_printf(m, "sub_sample: %8s %8s %8s %8s\n",
- cam->params.format.subSample == SUBSAMPLE_420 ?
- "420" : "422", "420", "422", "422");
- seq_printf(m, "yuv_order: %8s %8s %8s %8s\n",
- cam->params.format.yuvOrder == YUVORDER_YUYV ?
- "YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV");
- seq_printf(m, "ecp_timing: %8s %8s %8s %8s\n",
- cam->params.ecpTiming ? "slow" : "normal", "slow",
- "normal", "normal");
-
- if (cam->params.colourBalance.balanceMode == 2) {
- sprintf(tmpstr, "auto");
- } else {
- sprintf(tmpstr, "manual");
- }
- seq_printf(m, "color_balance_mode: %8s %8s %8s"
- " %8s\n", tmpstr, "manual", "auto", "auto");
- seq_printf(m, "red_gain: %8d %8d %8d %8d\n",
- cam->params.colourBalance.redGain, 0, 212, 32);
- seq_printf(m, "green_gain: %8d %8d %8d %8d\n",
- cam->params.colourBalance.greenGain, 0, 212, 6);
- seq_printf(m, "blue_gain: %8d %8d %8d %8d\n",
- cam->params.colourBalance.blueGain, 0, 212, 92);
-
- if (cam->params.version.firmwareVersion == 1 &&
- cam->params.version.firmwareRevision == 2)
- /* 1-02 firmware limits gain to 2 */
- sprintf(tmpstr, "%8d %8d %8d", 1, 2, 2);
- else
- sprintf(tmpstr, "%8d %8d %8d", 1, 8, 2);
-
- if (cam->params.exposure.gainMode == 0)
- seq_printf(m, "max_gain: unknown %28s"
- " powers of 2\n", tmpstr);
- else
- seq_printf(m, "max_gain: %8d %28s"
- " 1,2,4 or 8 \n",
- 1<<(cam->params.exposure.gainMode-1), tmpstr);
-
- switch(cam->params.exposure.expMode) {
- case 1:
- case 3:
- sprintf(tmpstr, "manual");
- break;
- case 2:
- sprintf(tmpstr, "auto");
- break;
- default:
- sprintf(tmpstr, "unknown");
- break;
- }
- seq_printf(m, "exposure_mode: %8s %8s %8s"
- " %8s\n", tmpstr, "manual", "auto", "auto");
- seq_printf(m, "centre_weight: %8s %8s %8s %8s\n",
- (2-cam->params.exposure.centreWeight) ? "on" : "off",
- "off", "on", "on");
- seq_printf(m, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n",
- 1<<cam->params.exposure.gain, 1, 1);
- if (cam->params.version.firmwareVersion == 1 &&
- cam->params.version.firmwareRevision == 2)
- /* 1-02 firmware limits fineExp/2 to 127 */
- tmp = 254;
- else
- tmp = 510;
-
- seq_printf(m, "fine_exp: %8d %8d %8d %8d\n",
- cam->params.exposure.fineExp*2, 0, tmp, 0);
- if (cam->params.version.firmwareVersion == 1 &&
- cam->params.version.firmwareRevision == 2)
- /* 1-02 firmware limits coarseExpHi to 0 */
- tmp = MAX_EXP_102;
- else
- tmp = MAX_EXP;
-
- seq_printf(m, "coarse_exp: %8d %8d %8d"
- " %8d\n", cam->params.exposure.coarseExpLo+
- 256*cam->params.exposure.coarseExpHi, 0, tmp, 185);
- seq_printf(m, "red_comp: %8d %8d %8d %8d\n",
- cam->params.exposure.redComp, COMP_RED, 255, COMP_RED);
- seq_printf(m, "green1_comp: %8d %8d %8d %8d\n",
- cam->params.exposure.green1Comp, COMP_GREEN1, 255,
- COMP_GREEN1);
- seq_printf(m, "green2_comp: %8d %8d %8d %8d\n",
- cam->params.exposure.green2Comp, COMP_GREEN2, 255,
- COMP_GREEN2);
- seq_printf(m, "blue_comp: %8d %8d %8d %8d\n",
- cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE);
-
- seq_printf(m, "apcor_gain1: %#8x %#8x %#8x %#8x\n",
- cam->params.apcor.gain1, 0, 0xff, 0x1c);
- seq_printf(m, "apcor_gain2: %#8x %#8x %#8x %#8x\n",
- cam->params.apcor.gain2, 0, 0xff, 0x1a);
- seq_printf(m, "apcor_gain4: %#8x %#8x %#8x %#8x\n",
- cam->params.apcor.gain4, 0, 0xff, 0x2d);
- seq_printf(m, "apcor_gain8: %#8x %#8x %#8x %#8x\n",
- cam->params.apcor.gain8, 0, 0xff, 0x2a);
- seq_printf(m, "vl_offset_gain1: %8d %8d %8d %8d\n",
- cam->params.vlOffset.gain1, 0, 255, 24);
- seq_printf(m, "vl_offset_gain2: %8d %8d %8d %8d\n",
- cam->params.vlOffset.gain2, 0, 255, 28);
- seq_printf(m, "vl_offset_gain4: %8d %8d %8d %8d\n",
- cam->params.vlOffset.gain4, 0, 255, 30);
- seq_printf(m, "vl_offset_gain8: %8d %8d %8d %8d\n",
- cam->params.vlOffset.gain8, 0, 255, 30);
- seq_printf(m, "flicker_control: %8s %8s %8s %8s\n",
- cam->params.flickerControl.flickerMode ? "on" : "off",
- "off", "on", "off");
- seq_printf(m, "mains_frequency: %8d %8d %8d %8d"
- " only 50/60\n",
- cam->mainsFreq ? 60 : 50, 50, 60, 50);
- if(cam->params.flickerControl.allowableOverExposure < 0)
- seq_printf(m, "allowable_overexposure: %4dauto auto %8d auto\n",
- -cam->params.flickerControl.allowableOverExposure,
- 255);
- else
- seq_printf(m, "allowable_overexposure: %8d auto %8d auto\n",
- cam->params.flickerControl.allowableOverExposure,
- 255);
- seq_printf(m, "compression_mode: ");
- switch(cam->params.compression.mode) {
- case CPIA_COMPRESSION_NONE:
- seq_printf(m, "%8s", "none");
- break;
- case CPIA_COMPRESSION_AUTO:
- seq_printf(m, "%8s", "auto");
- break;
- case CPIA_COMPRESSION_MANUAL:
- seq_printf(m, "%8s", "manual");
- break;
- default:
- seq_printf(m, "%8s", "unknown");
- break;
- }
- seq_printf(m, " none,auto,manual auto\n");
- seq_printf(m, "decimation_enable: %8s %8s %8s %8s\n",
- cam->params.compression.decimation ==
- DECIMATION_ENAB ? "on":"off", "off", "on",
- "off");
- seq_printf(m, "compression_target: %9s %9s %9s %9s\n",
- cam->params.compressionTarget.frTargeting ==
- CPIA_COMPRESSION_TARGET_FRAMERATE ?
- "framerate":"quality",
- "framerate", "quality", "quality");
- seq_printf(m, "target_framerate: %8d %8d %8d %8d\n",
- cam->params.compressionTarget.targetFR, 1, 30, 15);
- seq_printf(m, "target_quality: %8d %8d %8d %8d\n",
- cam->params.compressionTarget.targetQ, 1, 64, 5);
- seq_printf(m, "y_threshold: %8d %8d %8d %8d\n",
- cam->params.yuvThreshold.yThreshold, 0, 31, 6);
- seq_printf(m, "uv_threshold: %8d %8d %8d %8d\n",
- cam->params.yuvThreshold.uvThreshold, 0, 31, 6);
- seq_printf(m, "hysteresis: %8d %8d %8d %8d\n",
- cam->params.compressionParams.hysteresis, 0, 255, 3);
- seq_printf(m, "threshold_max: %8d %8d %8d %8d\n",
- cam->params.compressionParams.threshMax, 0, 255, 11);
- seq_printf(m, "small_step: %8d %8d %8d %8d\n",
- cam->params.compressionParams.smallStep, 0, 255, 1);
- seq_printf(m, "large_step: %8d %8d %8d %8d\n",
- cam->params.compressionParams.largeStep, 0, 255, 3);
- seq_printf(m, "decimation_hysteresis: %8d %8d %8d %8d\n",
- cam->params.compressionParams.decimationHysteresis,
- 0, 255, 2);
- seq_printf(m, "fr_diff_step_thresh: %8d %8d %8d %8d\n",
- cam->params.compressionParams.frDiffStepThresh,
- 0, 255, 5);
- seq_printf(m, "q_diff_step_thresh: %8d %8d %8d %8d\n",
- cam->params.compressionParams.qDiffStepThresh,
- 0, 255, 3);
- seq_printf(m, "decimation_thresh_mod: %8d %8d %8d %8d\n",
- cam->params.compressionParams.decimationThreshMod,
- 0, 255, 2);
- /* QX3 specific entries */
- if (cam->params.qx3.qx3_detected) {
- seq_printf(m, "toplight: %8s %8s %8s %8s\n",
- cam->params.qx3.toplight ? "on" : "off",
- "off", "on", "off");
- seq_printf(m, "bottomlight: %8s %8s %8s %8s\n",
- cam->params.qx3.bottomlight ? "on" : "off",
- "off", "on", "off");
- }
-
- return 0;
-}
-
-static int cpia_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, cpia_proc_show, PDE(inode)->data);
-}
-
-static int match(char *checkstr, char **buffer, size_t *count,
- int *find_colon, int *err)
-{
- int ret, colon_found = 1;
- int len = strlen(checkstr);
- ret = (len <= *count && strncmp(*buffer, checkstr, len) == 0);
- if (ret) {
- *buffer += len;
- *count -= len;
- if (*find_colon) {
- colon_found = 0;
- while (*count && (**buffer == ' ' || **buffer == '\t' ||
- (!colon_found && **buffer == ':'))) {
- if (**buffer == ':')
- colon_found = 1;
- --*count;
- ++*buffer;
- }
- if (!*count || !colon_found)
- *err = -EINVAL;
- *find_colon = 0;
- }
- }
- return ret;
-}
-
-static unsigned long int value(char **buffer, size_t *count, int *err)
-{
- char *p;
- unsigned long int ret;
- ret = simple_strtoul(*buffer, &p, 0);
- if (p == *buffer)
- *err = -EINVAL;
- else {
- *count -= p - *buffer;
- *buffer = p;
- }
- return ret;
-}
-
-static ssize_t cpia_proc_write(struct file *file, const char __user *buf,
- size_t count, loff_t *pos)
-{
- struct cam_data *cam = PDE(file->f_path.dentry->d_inode)->data;
- struct cam_params new_params;
- char *page, *buffer;
- int retval, find_colon;
- int size = count;
- unsigned long val = 0;
- u32 command_flags = 0;
- u8 new_mains;
-
- /*
- * This code to copy from buf to page is shamelessly copied
- * from the comx driver
- */
- if (count > PAGE_SIZE) {
- printk(KERN_ERR "count is %zu > %d!!!\n", count, (int)PAGE_SIZE);
- return -ENOSPC;
- }
-
- if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM;
-
- if(copy_from_user(page, buf, count))
- {
- retval = -EFAULT;
- goto out;
- }
-
- if (page[count-1] == '\n')
- page[count-1] = '\0';
- else if (count < PAGE_SIZE)
- page[count] = '\0';
- else if (page[count]) {
- retval = -EINVAL;
- goto out;
- }
-
- buffer = page;
-
- if (mutex_lock_interruptible(&cam->param_lock))
- return -ERESTARTSYS;
-
- /*
- * Skip over leading whitespace
- */
- while (count && isspace(*buffer)) {
- --count;
- ++buffer;
- }
-
- memcpy(&new_params, &cam->params, sizeof(struct cam_params));
- new_mains = cam->mainsFreq;
-
-#define MATCH(x) (match(x, &buffer, &count, &find_colon, &retval))
-#define VALUE (value(&buffer,&count, &retval))
-#define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \
- new_params.version.firmwareRevision == (y))
-
- retval = 0;
- while (count && !retval) {
- find_colon = 1;
- if (MATCH("brightness")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 100)
- new_params.colourParams.brightness = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOLOURPARAMS;
- if(new_params.flickerControl.allowableOverExposure < 0)
- new_params.flickerControl.allowableOverExposure =
- -find_over_exposure(new_params.colourParams.brightness);
- if(new_params.flickerControl.flickerMode != 0)
- command_flags |= COMMAND_SETFLICKERCTRL;
-
- } else if (MATCH("contrast")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 100) {
- /* contrast is in steps of 8, so round*/
- val = ((val + 3) / 8) * 8;
- /* 1-02 firmware limits contrast to 80*/
- if (FIRMWARE_VERSION(1,2) && val > 80)
- val = 80;
-
- new_params.colourParams.contrast = val;
- } else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOLOURPARAMS;
- } else if (MATCH("saturation")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 100)
- new_params.colourParams.saturation = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOLOURPARAMS;
- } else if (MATCH("sensor_fps")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- /* find values so that sensorFPS is minimized,
- * but >= val */
- if (val > 30)
- retval = -EINVAL;
- else if (val > 25) {
- new_params.sensorFps.divisor = 0;
- new_params.sensorFps.baserate = 1;
- } else if (val > 15) {
- new_params.sensorFps.divisor = 0;
- new_params.sensorFps.baserate = 0;
- } else if (val > 12) {
- new_params.sensorFps.divisor = 1;
- new_params.sensorFps.baserate = 1;
- } else if (val > 7) {
- new_params.sensorFps.divisor = 1;
- new_params.sensorFps.baserate = 0;
- } else if (val > 6) {
- new_params.sensorFps.divisor = 2;
- new_params.sensorFps.baserate = 1;
- } else if (val > 3) {
- new_params.sensorFps.divisor = 2;
- new_params.sensorFps.baserate = 0;
- } else {
- new_params.sensorFps.divisor = 3;
- /* Either base rate would work here */
- new_params.sensorFps.baserate = 1;
- }
- new_params.flickerControl.coarseJump =
- flicker_jumps[new_mains]
- [new_params.sensorFps.baserate]
- [new_params.sensorFps.divisor];
- if (new_params.flickerControl.flickerMode)
- command_flags |= COMMAND_SETFLICKERCTRL;
- }
- command_flags |= COMMAND_SETSENSORFPS;
- cam->exposure_status = EXPOSURE_NORMAL;
- } else if (MATCH("stream_start_line")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- int max_line = 288;
-
- if (new_params.format.videoSize == VIDEOSIZE_QCIF)
- max_line = 144;
- if (val <= max_line)
- new_params.streamStartLine = val/2;
- else
- retval = -EINVAL;
- }
- } else if (MATCH("sub_sample")) {
- if (!retval && MATCH("420"))
- new_params.format.subSample = SUBSAMPLE_420;
- else if (!retval && MATCH("422"))
- new_params.format.subSample = SUBSAMPLE_422;
- else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETFORMAT;
- } else if (MATCH("yuv_order")) {
- if (!retval && MATCH("YUYV"))
- new_params.format.yuvOrder = YUVORDER_YUYV;
- else if (!retval && MATCH("UYVY"))
- new_params.format.yuvOrder = YUVORDER_UYVY;
- else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETFORMAT;
- } else if (MATCH("ecp_timing")) {
- if (!retval && MATCH("normal"))
- new_params.ecpTiming = 0;
- else if (!retval && MATCH("slow"))
- new_params.ecpTiming = 1;
- else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETECPTIMING;
- } else if (MATCH("color_balance_mode")) {
- if (!retval && MATCH("manual"))
- new_params.colourBalance.balanceMode = 3;
- else if (!retval && MATCH("auto"))
- new_params.colourBalance.balanceMode = 2;
- else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETCOLOURBALANCE;
- } else if (MATCH("red_gain")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 212) {
- new_params.colourBalance.redGain = val;
- new_params.colourBalance.balanceMode = 1;
- } else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOLOURBALANCE;
- } else if (MATCH("green_gain")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 212) {
- new_params.colourBalance.greenGain = val;
- new_params.colourBalance.balanceMode = 1;
- } else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOLOURBALANCE;
- } else if (MATCH("blue_gain")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 212) {
- new_params.colourBalance.blueGain = val;
- new_params.colourBalance.balanceMode = 1;
- } else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOLOURBALANCE;
- } else if (MATCH("max_gain")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- /* 1-02 firmware limits gain to 2 */
- if (FIRMWARE_VERSION(1,2) && val > 2)
- val = 2;
- switch(val) {
- case 1:
- new_params.exposure.gainMode = 1;
- break;
- case 2:
- new_params.exposure.gainMode = 2;
- break;
- case 4:
- new_params.exposure.gainMode = 3;
- break;
- case 8:
- new_params.exposure.gainMode = 4;
- break;
- default:
- retval = -EINVAL;
- break;
- }
- }
- command_flags |= COMMAND_SETEXPOSURE;
- } else if (MATCH("exposure_mode")) {
- if (!retval && MATCH("auto"))
- new_params.exposure.expMode = 2;
- else if (!retval && MATCH("manual")) {
- if (new_params.exposure.expMode == 2)
- new_params.exposure.expMode = 3;
- if(new_params.flickerControl.flickerMode != 0)
- command_flags |= COMMAND_SETFLICKERCTRL;
- new_params.flickerControl.flickerMode = 0;
- } else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETEXPOSURE;
- } else if (MATCH("centre_weight")) {
- if (!retval && MATCH("on"))
- new_params.exposure.centreWeight = 1;
- else if (!retval && MATCH("off"))
- new_params.exposure.centreWeight = 2;
- else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETEXPOSURE;
- } else if (MATCH("gain")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- switch(val) {
- case 1:
- new_params.exposure.gain = 0;
- break;
- case 2:
- new_params.exposure.gain = 1;
- break;
- case 4:
- new_params.exposure.gain = 2;
- break;
- case 8:
- new_params.exposure.gain = 3;
- break;
- default:
- retval = -EINVAL;
- break;
- }
- new_params.exposure.expMode = 1;
- if(new_params.flickerControl.flickerMode != 0)
- command_flags |= COMMAND_SETFLICKERCTRL;
- new_params.flickerControl.flickerMode = 0;
- command_flags |= COMMAND_SETEXPOSURE;
- if (new_params.exposure.gain >
- new_params.exposure.gainMode-1)
- retval = -EINVAL;
- }
- } else if (MATCH("fine_exp")) {
- if (!retval)
- val = VALUE/2;
-
- if (!retval) {
- if (val < 256) {
- /* 1-02 firmware limits fineExp/2 to 127*/
- if (FIRMWARE_VERSION(1,2) && val > 127)
- val = 127;
- new_params.exposure.fineExp = val;
- new_params.exposure.expMode = 1;
- command_flags |= COMMAND_SETEXPOSURE;
- if(new_params.flickerControl.flickerMode != 0)
- command_flags |= COMMAND_SETFLICKERCTRL;
- new_params.flickerControl.flickerMode = 0;
- command_flags |= COMMAND_SETFLICKERCTRL;
- } else
- retval = -EINVAL;
- }
- } else if (MATCH("coarse_exp")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= MAX_EXP) {
- if (FIRMWARE_VERSION(1,2) &&
- val > MAX_EXP_102)
- val = MAX_EXP_102;
- new_params.exposure.coarseExpLo =
- val & 0xff;
- new_params.exposure.coarseExpHi =
- val >> 8;
- new_params.exposure.expMode = 1;
- command_flags |= COMMAND_SETEXPOSURE;
- if(new_params.flickerControl.flickerMode != 0)
- command_flags |= COMMAND_SETFLICKERCTRL;
- new_params.flickerControl.flickerMode = 0;
- command_flags |= COMMAND_SETFLICKERCTRL;
- } else
- retval = -EINVAL;
- }
- } else if (MATCH("red_comp")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val >= COMP_RED && val <= 255) {
- new_params.exposure.redComp = val;
- new_params.exposure.compMode = 1;
- command_flags |= COMMAND_SETEXPOSURE;
- } else
- retval = -EINVAL;
- }
- } else if (MATCH("green1_comp")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val >= COMP_GREEN1 && val <= 255) {
- new_params.exposure.green1Comp = val;
- new_params.exposure.compMode = 1;
- command_flags |= COMMAND_SETEXPOSURE;
- } else
- retval = -EINVAL;
- }
- } else if (MATCH("green2_comp")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val >= COMP_GREEN2 && val <= 255) {
- new_params.exposure.green2Comp = val;
- new_params.exposure.compMode = 1;
- command_flags |= COMMAND_SETEXPOSURE;
- } else
- retval = -EINVAL;
- }
- } else if (MATCH("blue_comp")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val >= COMP_BLUE && val <= 255) {
- new_params.exposure.blueComp = val;
- new_params.exposure.compMode = 1;
- command_flags |= COMMAND_SETEXPOSURE;
- } else
- retval = -EINVAL;
- }
- } else if (MATCH("apcor_gain1")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- command_flags |= COMMAND_SETAPCOR;
- if (val <= 0xff)
- new_params.apcor.gain1 = val;
- else
- retval = -EINVAL;
- }
- } else if (MATCH("apcor_gain2")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- command_flags |= COMMAND_SETAPCOR;
- if (val <= 0xff)
- new_params.apcor.gain2 = val;
- else
- retval = -EINVAL;
- }
- } else if (MATCH("apcor_gain4")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- command_flags |= COMMAND_SETAPCOR;
- if (val <= 0xff)
- new_params.apcor.gain4 = val;
- else
- retval = -EINVAL;
- }
- } else if (MATCH("apcor_gain8")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- command_flags |= COMMAND_SETAPCOR;
- if (val <= 0xff)
- new_params.apcor.gain8 = val;
- else
- retval = -EINVAL;
- }
- } else if (MATCH("vl_offset_gain1")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.vlOffset.gain1 = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETVLOFFSET;
- } else if (MATCH("vl_offset_gain2")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.vlOffset.gain2 = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETVLOFFSET;
- } else if (MATCH("vl_offset_gain4")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.vlOffset.gain4 = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETVLOFFSET;
- } else if (MATCH("vl_offset_gain8")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.vlOffset.gain8 = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETVLOFFSET;
- } else if (MATCH("flicker_control")) {
- if (!retval && MATCH("on")) {
- set_flicker(&new_params, &command_flags, 1);
- } else if (!retval && MATCH("off")) {
- set_flicker(&new_params, &command_flags, 0);
- } else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETFLICKERCTRL;
- } else if (MATCH("mains_frequency")) {
- if (!retval && MATCH("50")) {
- new_mains = 0;
- new_params.flickerControl.coarseJump =
- flicker_jumps[new_mains]
- [new_params.sensorFps.baserate]
- [new_params.sensorFps.divisor];
- if (new_params.flickerControl.flickerMode)
- command_flags |= COMMAND_SETFLICKERCTRL;
- } else if (!retval && MATCH("60")) {
- new_mains = 1;
- new_params.flickerControl.coarseJump =
- flicker_jumps[new_mains]
- [new_params.sensorFps.baserate]
- [new_params.sensorFps.divisor];
- if (new_params.flickerControl.flickerMode)
- command_flags |= COMMAND_SETFLICKERCTRL;
- } else
- retval = -EINVAL;
- } else if (MATCH("allowable_overexposure")) {
- if (!retval && MATCH("auto")) {
- new_params.flickerControl.allowableOverExposure =
- -find_over_exposure(new_params.colourParams.brightness);
- if(new_params.flickerControl.flickerMode != 0)
- command_flags |= COMMAND_SETFLICKERCTRL;
- } else {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff) {
- new_params.flickerControl.
- allowableOverExposure = val;
- if(new_params.flickerControl.flickerMode != 0)
- command_flags |= COMMAND_SETFLICKERCTRL;
- } else
- retval = -EINVAL;
- }
- }
- } else if (MATCH("compression_mode")) {
- if (!retval && MATCH("none"))
- new_params.compression.mode =
- CPIA_COMPRESSION_NONE;
- else if (!retval && MATCH("auto"))
- new_params.compression.mode =
- CPIA_COMPRESSION_AUTO;
- else if (!retval && MATCH("manual"))
- new_params.compression.mode =
- CPIA_COMPRESSION_MANUAL;
- else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETCOMPRESSION;
- } else if (MATCH("decimation_enable")) {
- if (!retval && MATCH("off"))
- new_params.compression.decimation = 0;
- else if (!retval && MATCH("on"))
- new_params.compression.decimation = 1;
- else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETCOMPRESSION;
- } else if (MATCH("compression_target")) {
- if (!retval && MATCH("quality"))
- new_params.compressionTarget.frTargeting =
- CPIA_COMPRESSION_TARGET_QUALITY;
- else if (!retval && MATCH("framerate"))
- new_params.compressionTarget.frTargeting =
- CPIA_COMPRESSION_TARGET_FRAMERATE;
- else
- retval = -EINVAL;
-
- command_flags |= COMMAND_SETCOMPRESSIONTARGET;
- } else if (MATCH("target_framerate")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if(val > 0 && val <= 30)
- new_params.compressionTarget.targetFR = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONTARGET;
- } else if (MATCH("target_quality")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if(val > 0 && val <= 64)
- new_params.compressionTarget.targetQ = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONTARGET;
- } else if (MATCH("y_threshold")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val < 32)
- new_params.yuvThreshold.yThreshold = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETYUVTHRESH;
- } else if (MATCH("uv_threshold")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val < 32)
- new_params.yuvThreshold.uvThreshold = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETYUVTHRESH;
- } else if (MATCH("hysteresis")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.compressionParams.hysteresis = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
- } else if (MATCH("threshold_max")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.compressionParams.threshMax = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
- } else if (MATCH("small_step")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.compressionParams.smallStep = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
- } else if (MATCH("large_step")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.compressionParams.largeStep = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
- } else if (MATCH("decimation_hysteresis")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.compressionParams.decimationHysteresis = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
- } else if (MATCH("fr_diff_step_thresh")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.compressionParams.frDiffStepThresh = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
- } else if (MATCH("q_diff_step_thresh")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.compressionParams.qDiffStepThresh = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
- } else if (MATCH("decimation_thresh_mod")) {
- if (!retval)
- val = VALUE;
-
- if (!retval) {
- if (val <= 0xff)
- new_params.compressionParams.decimationThreshMod = val;
- else
- retval = -EINVAL;
- }
- command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
- } else if (MATCH("toplight")) {
- if (!retval && MATCH("on"))
- new_params.qx3.toplight = 1;
- else if (!retval && MATCH("off"))
- new_params.qx3.toplight = 0;
- else
- retval = -EINVAL;
- command_flags |= COMMAND_SETLIGHTS;
- } else if (MATCH("bottomlight")) {
- if (!retval && MATCH("on"))
- new_params.qx3.bottomlight = 1;
- else if (!retval && MATCH("off"))
- new_params.qx3.bottomlight = 0;
- else
- retval = -EINVAL;
- command_flags |= COMMAND_SETLIGHTS;
- } else {
- DBG("No match found\n");
- retval = -EINVAL;
- }
-
- if (!retval) {
- while (count && isspace(*buffer) && *buffer != '\n') {
- --count;
- ++buffer;
- }
- if (count) {
- if (*buffer == '\0' && count != 1)
- retval = -EINVAL;
- else if (*buffer != '\n' && *buffer != ';' &&
- *buffer != '\0')
- retval = -EINVAL;
- else {
- --count;
- ++buffer;
- }
- }
- }
- }
-#undef MATCH
-#undef VALUE
-#undef FIRMWARE_VERSION
- if (!retval) {
- if (command_flags & COMMAND_SETCOLOURPARAMS) {
- /* Adjust cam->vp to reflect these changes */
- cam->vp.brightness =
- new_params.colourParams.brightness*65535/100;
- cam->vp.contrast =
- new_params.colourParams.contrast*65535/100;
- cam->vp.colour =
- new_params.colourParams.saturation*65535/100;
- }
- if((command_flags & COMMAND_SETEXPOSURE) &&
- new_params.exposure.expMode == 2)
- cam->exposure_status = EXPOSURE_NORMAL;
-
- memcpy(&cam->params, &new_params, sizeof(struct cam_params));
- cam->mainsFreq = new_mains;
- cam->cmd_queue |= command_flags;
- retval = size;
- } else
- DBG("error: %d\n", retval);
-
- mutex_unlock(&cam->param_lock);
-
-out:
- free_page((unsigned long)page);
- return retval;
-}
-
-static const struct file_operations cpia_proc_fops = {
- .owner = THIS_MODULE,
- .open = cpia_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .write = cpia_proc_write,
-};
-
-static void create_proc_cpia_cam(struct cam_data *cam)
-{
- struct proc_dir_entry *ent;
-
- if (!cpia_proc_root || !cam)
- return;
-
- ent = proc_create_data(video_device_node_name(&cam->vdev),
- S_IRUGO|S_IWUSR, cpia_proc_root,
- &cpia_proc_fops, cam);
- if (!ent)
- return;
-
- /*
- size of the proc entry is 3736 bytes for the standard webcam;
- the extra features of the QX3 microscope add 189 bytes.
- (we have not yet probed the camera to see which type it is).
- */
- ent->size = 3736 + 189;
- cam->proc_entry = ent;
-}
-
-static void destroy_proc_cpia_cam(struct cam_data *cam)
-{
- if (!cam || !cam->proc_entry)
- return;
-
- remove_proc_entry(video_device_node_name(&cam->vdev), cpia_proc_root);
- cam->proc_entry = NULL;
-}
-
-static void proc_cpia_create(void)
-{
- cpia_proc_root = proc_mkdir("cpia", NULL);
-
- if (!cpia_proc_root)
- LOG("Unable to initialise /proc/cpia\n");
-}
-
-static void __exit proc_cpia_destroy(void)
-{
- remove_proc_entry("cpia", NULL);
-}
-#endif /* CONFIG_PROC_FS */
-
-/* ----------------------- debug functions ---------------------- */
-
-#define printstatus(cam) \
- DBG("%02x %02x %02x %02x %02x %02x %02x %02x\n",\
- cam->params.status.systemState, cam->params.status.grabState, \
- cam->params.status.streamState, cam->params.status.fatalError, \
- cam->params.status.cmdError, cam->params.status.debugFlags, \
- cam->params.status.vpStatus, cam->params.status.errorCode);
-
-/* ----------------------- v4l helpers -------------------------- */
-
-/* supported frame palettes and depths */
-static inline int valid_mode(u16 palette, u16 depth)
-{
- if ((palette == VIDEO_PALETTE_YUV422 && depth == 16) ||
- (palette == VIDEO_PALETTE_YUYV && depth == 16))
- return 1;
-
- if (colorspace_conv)
- return (palette == VIDEO_PALETTE_GREY && depth == 8) ||
- (palette == VIDEO_PALETTE_RGB555 && depth == 16) ||
- (palette == VIDEO_PALETTE_RGB565 && depth == 16) ||
- (palette == VIDEO_PALETTE_RGB24 && depth == 24) ||
- (palette == VIDEO_PALETTE_RGB32 && depth == 32) ||
- (palette == VIDEO_PALETTE_UYVY && depth == 16);
-
- return 0;
-}
-
-static int match_videosize( int width, int height )
-{
- /* return the best match, where 'best' is as always
- * the largest that is not bigger than what is requested. */
- if (width>=352 && height>=288)
- return VIDEOSIZE_352_288; /* CIF */
-
- if (width>=320 && height>=240)
- return VIDEOSIZE_320_240; /* SIF */
-
- if (width>=288 && height>=216)
- return VIDEOSIZE_288_216;
-
- if (width>=256 && height>=192)
- return VIDEOSIZE_256_192;
-
- if (width>=224 && height>=168)
- return VIDEOSIZE_224_168;
-
- if (width>=192 && height>=144)
- return VIDEOSIZE_192_144;
-
- if (width>=176 && height>=144)
- return VIDEOSIZE_176_144; /* QCIF */
-
- if (width>=160 && height>=120)
- return VIDEOSIZE_160_120; /* QSIF */
-
- if (width>=128 && height>=96)
- return VIDEOSIZE_128_96;
-
- if (width>=88 && height>=72)
- return VIDEOSIZE_88_72;
-
- if (width>=64 && height>=48)
- return VIDEOSIZE_64_48;
-
- if (width>=48 && height>=48)
- return VIDEOSIZE_48_48;
-
- return -1;
-}
-
-/* these are the capture sizes we support */
-static void set_vw_size(struct cam_data *cam)
-{
- /* the col/row/start/end values are the result of simple math */
- /* study the SetROI-command in cpia developers guide p 2-22 */
- /* streamStartLine is set to the recommended value in the cpia */
- /* developers guide p 3-37 */
- switch(cam->video_size) {
- case VIDEOSIZE_CIF:
- cam->vw.width = 352;
- cam->vw.height = 288;
- cam->params.format.videoSize=VIDEOSIZE_CIF;
- cam->params.roi.colStart=0;
- cam->params.roi.rowStart=0;
- cam->params.streamStartLine = 120;
- break;
- case VIDEOSIZE_SIF:
- cam->vw.width = 320;
- cam->vw.height = 240;
- cam->params.format.videoSize=VIDEOSIZE_CIF;
- cam->params.roi.colStart=2;
- cam->params.roi.rowStart=6;
- cam->params.streamStartLine = 120;
- break;
- case VIDEOSIZE_288_216:
- cam->vw.width = 288;
- cam->vw.height = 216;
- cam->params.format.videoSize=VIDEOSIZE_CIF;
- cam->params.roi.colStart=4;
- cam->params.roi.rowStart=9;
- cam->params.streamStartLine = 120;
- break;
- case VIDEOSIZE_256_192:
- cam->vw.width = 256;
- cam->vw.height = 192;
- cam->params.format.videoSize=VIDEOSIZE_CIF;
- cam->params.roi.colStart=6;
- cam->params.roi.rowStart=12;
- cam->params.streamStartLine = 120;
- break;
- case VIDEOSIZE_224_168:
- cam->vw.width = 224;
- cam->vw.height = 168;
- cam->params.format.videoSize=VIDEOSIZE_CIF;
- cam->params.roi.colStart=8;
- cam->params.roi.rowStart=15;
- cam->params.streamStartLine = 120;
- break;
- case VIDEOSIZE_192_144:
- cam->vw.width = 192;
- cam->vw.height = 144;
- cam->params.format.videoSize=VIDEOSIZE_CIF;
- cam->params.roi.colStart=10;
- cam->params.roi.rowStart=18;
- cam->params.streamStartLine = 120;
- break;
- case VIDEOSIZE_QCIF:
- cam->vw.width = 176;
- cam->vw.height = 144;
- cam->params.format.videoSize=VIDEOSIZE_QCIF;
- cam->params.roi.colStart=0;
- cam->params.roi.rowStart=0;
- cam->params.streamStartLine = 60;
- break;
- case VIDEOSIZE_QSIF:
- cam->vw.width = 160;
- cam->vw.height = 120;
- cam->params.format.videoSize=VIDEOSIZE_QCIF;
- cam->params.roi.colStart=1;
- cam->params.roi.rowStart=3;
- cam->params.streamStartLine = 60;
- break;
- case VIDEOSIZE_128_96:
- cam->vw.width = 128;
- cam->vw.height = 96;
- cam->params.format.videoSize=VIDEOSIZE_QCIF;
- cam->params.roi.colStart=3;
- cam->params.roi.rowStart=6;
- cam->params.streamStartLine = 60;
- break;
- case VIDEOSIZE_88_72:
- cam->vw.width = 88;
- cam->vw.height = 72;
- cam->params.format.videoSize=VIDEOSIZE_QCIF;
- cam->params.roi.colStart=5;
- cam->params.roi.rowStart=9;
- cam->params.streamStartLine = 60;
- break;
- case VIDEOSIZE_64_48:
- cam->vw.width = 64;
- cam->vw.height = 48;
- cam->params.format.videoSize=VIDEOSIZE_QCIF;
- cam->params.roi.colStart=7;
- cam->params.roi.rowStart=12;
- cam->params.streamStartLine = 60;
- break;
- case VIDEOSIZE_48_48:
- cam->vw.width = 48;
- cam->vw.height = 48;
- cam->params.format.videoSize=VIDEOSIZE_QCIF;
- cam->params.roi.colStart=8;
- cam->params.roi.rowStart=6;
- cam->params.streamStartLine = 60;
- break;
- default:
- LOG("bad videosize value: %d\n", cam->video_size);
- return;
- }
-
- if(cam->vc.width == 0)
- cam->vc.width = cam->vw.width;
- if(cam->vc.height == 0)
- cam->vc.height = cam->vw.height;
-
- cam->params.roi.colStart += cam->vc.x >> 3;
- cam->params.roi.colEnd = cam->params.roi.colStart +
- (cam->vc.width >> 3);
- cam->params.roi.rowStart += cam->vc.y >> 2;
- cam->params.roi.rowEnd = cam->params.roi.rowStart +
- (cam->vc.height >> 2);
-
- return;
-}
-
-static int allocate_frame_buf(struct cam_data *cam)
-{
- int i;
-
- cam->frame_buf = rvmalloc(FRAME_NUM * CPIA_MAX_FRAME_SIZE);
- if (!cam->frame_buf)
- return -ENOBUFS;
-
- for (i = 0; i < FRAME_NUM; i++)
- cam->frame[i].data = cam->frame_buf + i * CPIA_MAX_FRAME_SIZE;
-
- return 0;
-}
-
-static int free_frame_buf(struct cam_data *cam)
-{
- int i;
-
- rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE);
- cam->frame_buf = NULL;
- for (i=0; i < FRAME_NUM; i++)
- cam->frame[i].data = NULL;
-
- return 0;
-}
-
-
-static inline void free_frames(struct cpia_frame frame[FRAME_NUM])
-{
- int i;
-
- for (i=0; i < FRAME_NUM; i++)
- frame[i].state = FRAME_UNUSED;
- return;
-}
-
-/**********************************************************************
- *
- * General functions
- *
- **********************************************************************/
-/* send an arbitrary command to the camera */
-static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d)
-{
- int retval, datasize;
- u8 cmd[8], data[8];
-
- switch(command) {
- case CPIA_COMMAND_GetCPIAVersion:
- case CPIA_COMMAND_GetPnPID:
- case CPIA_COMMAND_GetCameraStatus:
- case CPIA_COMMAND_GetVPVersion:
- datasize=8;
- break;
- case CPIA_COMMAND_GetColourParams:
- case CPIA_COMMAND_GetColourBalance:
- case CPIA_COMMAND_GetExposure:
- mutex_lock(&cam->param_lock);
- datasize=8;
- break;
- case CPIA_COMMAND_ReadMCPorts:
- case CPIA_COMMAND_ReadVCRegs:
- datasize = 4;
- break;
- default:
- datasize=0;
- break;
- }
-
- cmd[0] = command>>8;
- cmd[1] = command&0xff;
- cmd[2] = a;
- cmd[3] = b;
- cmd[4] = c;
- cmd[5] = d;
- cmd[6] = datasize;
- cmd[7] = 0;
-
- retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
- if (retval) {
- DBG("%x - failed, retval=%d\n", command, retval);
- if (command == CPIA_COMMAND_GetColourParams ||
- command == CPIA_COMMAND_GetColourBalance ||
- command == CPIA_COMMAND_GetExposure)
- mutex_unlock(&cam->param_lock);
- } else {
- switch(command) {
- case CPIA_COMMAND_GetCPIAVersion:
- cam->params.version.firmwareVersion = data[0];
- cam->params.version.firmwareRevision = data[1];
- cam->params.version.vcVersion = data[2];
- cam->params.version.vcRevision = data[3];
- break;
- case CPIA_COMMAND_GetPnPID:
- cam->params.pnpID.vendor = data[0]+(((u16)data[1])<<8);
- cam->params.pnpID.product = data[2]+(((u16)data[3])<<8);
- cam->params.pnpID.deviceRevision =
- data[4]+(((u16)data[5])<<8);
- break;
- case CPIA_COMMAND_GetCameraStatus:
- cam->params.status.systemState = data[0];
- cam->params.status.grabState = data[1];
- cam->params.status.streamState = data[2];
- cam->params.status.fatalError = data[3];
- cam->params.status.cmdError = data[4];
- cam->params.status.debugFlags = data[5];
- cam->params.status.vpStatus = data[6];
- cam->params.status.errorCode = data[7];
- break;
- case CPIA_COMMAND_GetVPVersion:
- cam->params.vpVersion.vpVersion = data[0];
- cam->params.vpVersion.vpRevision = data[1];
- cam->params.vpVersion.cameraHeadID =
- data[2]+(((u16)data[3])<<8);
- break;
- case CPIA_COMMAND_GetColourParams:
- cam->params.colourParams.brightness = data[0];
- cam->params.colourParams.contrast = data[1];
- cam->params.colourParams.saturation = data[2];
- mutex_unlock(&cam->param_lock);
- break;
- case CPIA_COMMAND_GetColourBalance:
- cam->params.colourBalance.redGain = data[0];
- cam->params.colourBalance.greenGain = data[1];
- cam->params.colourBalance.blueGain = data[2];
- mutex_unlock(&cam->param_lock);
- break;
- case CPIA_COMMAND_GetExposure:
- cam->params.exposure.gain = data[0];
- cam->params.exposure.fineExp = data[1];
- cam->params.exposure.coarseExpLo = data[2];
- cam->params.exposure.coarseExpHi = data[3];
- cam->params.exposure.redComp = data[4];
- cam->params.exposure.green1Comp = data[5];
- cam->params.exposure.green2Comp = data[6];
- cam->params.exposure.blueComp = data[7];
- mutex_unlock(&cam->param_lock);
- break;
-
- case CPIA_COMMAND_ReadMCPorts:
- if (!cam->params.qx3.qx3_detected)
- break;
- /* test button press */
- cam->params.qx3.button = ((data[1] & 0x02) == 0);
- if (cam->params.qx3.button) {
- /* button pressed - unlock the latch */
- do_command(cam,CPIA_COMMAND_WriteMCPort,3,0xDF,0xDF,0);
- do_command(cam,CPIA_COMMAND_WriteMCPort,3,0xFF,0xFF,0);
- }
-
- /* test whether microscope is cradled */
- cam->params.qx3.cradled = ((data[2] & 0x40) == 0);
- break;
-
- default:
- break;
- }
- }
- return retval;
-}
-
-/* send a command to the camera with an additional data transaction */
-static int do_command_extended(struct cam_data *cam, u16 command,
- u8 a, u8 b, u8 c, u8 d,
- u8 e, u8 f, u8 g, u8 h,
- u8 i, u8 j, u8 k, u8 l)
-{
- int retval;
- u8 cmd[8], data[8];
-
- cmd[0] = command>>8;
- cmd[1] = command&0xff;
- cmd[2] = a;
- cmd[3] = b;
- cmd[4] = c;
- cmd[5] = d;
- cmd[6] = 8;
- cmd[7] = 0;
- data[0] = e;
- data[1] = f;
- data[2] = g;
- data[3] = h;
- data[4] = i;
- data[5] = j;
- data[6] = k;
- data[7] = l;
-
- retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
- if (retval)
- DBG("%x - failed\n", command);
-
- return retval;
-}
-
-/**********************************************************************
- *
- * Colorspace conversion
- *
- **********************************************************************/
-#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
-
-static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt,
- int linesize, int mmap_kludge)
-{
- int y, u, v, r, g, b, y1;
-
- /* Odd lines use the same u and v as the previous line.
- * Because of compression, it is necessary to get this
- * information from the decoded image. */
- switch(out_fmt) {
- case VIDEO_PALETTE_RGB555:
- y = (*yuv++ - 16) * 76310;
- y1 = (*yuv - 16) * 76310;
- r = ((*(rgb+1-linesize)) & 0x7c) << 1;
- g = ((*(rgb-linesize)) & 0xe0) >> 4 |
- ((*(rgb+1-linesize)) & 0x03) << 6;
- b = ((*(rgb-linesize)) & 0x1f) << 3;
- u = (-53294 * r - 104635 * g + 157929 * b) / 5756495;
- v = (157968 * r - 132278 * g - 25690 * b) / 5366159;
- r = 104635 * v;
- g = -25690 * u - 53294 * v;
- b = 132278 * u;
- *rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3);
- *rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6);
- *rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3);
- *rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6);
- return 4;
- case VIDEO_PALETTE_RGB565:
- y = (*yuv++ - 16) * 76310;
- y1 = (*yuv - 16) * 76310;
- r = (*(rgb+1-linesize)) & 0xf8;
- g = ((*(rgb-linesize)) & 0xe0) >> 3 |
- ((*(rgb+1-linesize)) & 0x07) << 5;
- b = ((*(rgb-linesize)) & 0x1f) << 3;
- u = (-53294 * r - 104635 * g + 157929 * b) / 5756495;
- v = (157968 * r - 132278 * g - 25690 * b) / 5366159;
- r = 104635 * v;
- g = -25690 * u - 53294 * v;
- b = 132278 * u;
- *rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3);
- *rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5);
- *rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3);
- *rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5);
- return 4;
- break;
- case VIDEO_PALETTE_RGB24:
- case VIDEO_PALETTE_RGB32:
- y = (*yuv++ - 16) * 76310;
- y1 = (*yuv - 16) * 76310;
- if (mmap_kludge) {
- r = *(rgb+2-linesize);
- g = *(rgb+1-linesize);
- b = *(rgb-linesize);
- } else {
- r = *(rgb-linesize);
- g = *(rgb+1-linesize);
- b = *(rgb+2-linesize);
- }
- u = (-53294 * r - 104635 * g + 157929 * b) / 5756495;
- v = (157968 * r - 132278 * g - 25690 * b) / 5366159;
- r = 104635 * v;
- g = -25690 * u + -53294 * v;
- b = 132278 * u;
- if (mmap_kludge) {
- *rgb++ = LIMIT(b+y);
- *rgb++ = LIMIT(g+y);
- *rgb++ = LIMIT(r+y);
- if(out_fmt == VIDEO_PALETTE_RGB32)
- rgb++;
- *rgb++ = LIMIT(b+y1);
- *rgb++ = LIMIT(g+y1);
- *rgb = LIMIT(r+y1);
- } else {
- *rgb++ = LIMIT(r+y);
- *rgb++ = LIMIT(g+y);
- *rgb++ = LIMIT(b+y);
- if(out_fmt == VIDEO_PALETTE_RGB32)
- rgb++;
- *rgb++ = LIMIT(r+y1);
- *rgb++ = LIMIT(g+y1);
- *rgb = LIMIT(b+y1);
- }
- if(out_fmt == VIDEO_PALETTE_RGB32)
- return 8;
- return 6;
- case VIDEO_PALETTE_YUV422:
- case VIDEO_PALETTE_YUYV:
- y = *yuv++;
- u = *(rgb+1-linesize);
- y1 = *yuv;
- v = *(rgb+3-linesize);
- *rgb++ = y;
- *rgb++ = u;
- *rgb++ = y1;
- *rgb = v;
- return 4;
- case VIDEO_PALETTE_UYVY:
- u = *(rgb-linesize);
- y = *yuv++;
- v = *(rgb+2-linesize);
- y1 = *yuv;
- *rgb++ = u;
- *rgb++ = y;
- *rgb++ = v;
- *rgb = y1;
- return 4;
- case VIDEO_PALETTE_GREY:
- *rgb++ = *yuv++;
- *rgb = *yuv;
- return 2;
- default:
- DBG("Empty: %d\n", out_fmt);
- return 0;
- }
-}
-
-
-static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt,
- int in_uyvy, int mmap_kludge)
-{
- int y, u, v, r, g, b, y1;
-
- switch(out_fmt) {
- case VIDEO_PALETTE_RGB555:
- case VIDEO_PALETTE_RGB565:
- case VIDEO_PALETTE_RGB24:
- case VIDEO_PALETTE_RGB32:
- if (in_uyvy) {
- u = *yuv++ - 128;
- y = (*yuv++ - 16) * 76310;
- v = *yuv++ - 128;
- y1 = (*yuv - 16) * 76310;
- } else {
- y = (*yuv++ - 16) * 76310;
- u = *yuv++ - 128;
- y1 = (*yuv++ - 16) * 76310;
- v = *yuv - 128;
- }
- r = 104635 * v;
- g = -25690 * u + -53294 * v;
- b = 132278 * u;
- break;
- default:
- y = *yuv++;
- u = *yuv++;
- y1 = *yuv++;
- v = *yuv;
- /* Just to avoid compiler warnings */
- r = 0;
- g = 0;
- b = 0;
- break;
- }
- switch(out_fmt) {
- case VIDEO_PALETTE_RGB555:
- *rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3);
- *rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6);
- *rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3);
- *rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6);
- return 4;
- case VIDEO_PALETTE_RGB565:
- *rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3);
- *rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5);
- *rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3);
- *rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5);
- return 4;
- case VIDEO_PALETTE_RGB24:
- if (mmap_kludge) {
- *rgb++ = LIMIT(b+y);
- *rgb++ = LIMIT(g+y);
- *rgb++ = LIMIT(r+y);
- *rgb++ = LIMIT(b+y1);
- *rgb++ = LIMIT(g+y1);
- *rgb = LIMIT(r+y1);
- } else {
- *rgb++ = LIMIT(r+y);
- *rgb++ = LIMIT(g+y);
- *rgb++ = LIMIT(b+y);
- *rgb++ = LIMIT(r+y1);
- *rgb++ = LIMIT(g+y1);
- *rgb = LIMIT(b+y1);
- }
- return 6;
- case VIDEO_PALETTE_RGB32:
- if (mmap_kludge) {
- *rgb++ = LIMIT(b+y);
- *rgb++ = LIMIT(g+y);
- *rgb++ = LIMIT(r+y);
- rgb++;
- *rgb++ = LIMIT(b+y1);
- *rgb++ = LIMIT(g+y1);
- *rgb = LIMIT(r+y1);
- } else {
- *rgb++ = LIMIT(r+y);
- *rgb++ = LIMIT(g+y);
- *rgb++ = LIMIT(b+y);
- rgb++;
- *rgb++ = LIMIT(r+y1);
- *rgb++ = LIMIT(g+y1);
- *rgb = LIMIT(b+y1);
- }
- return 8;
- case VIDEO_PALETTE_GREY:
- *rgb++ = y;
- *rgb = y1;
- return 2;
- case VIDEO_PALETTE_YUV422:
- case VIDEO_PALETTE_YUYV:
- *rgb++ = y;
- *rgb++ = u;
- *rgb++ = y1;
- *rgb = v;
- return 4;
- case VIDEO_PALETTE_UYVY:
- *rgb++ = u;
- *rgb++ = y;
- *rgb++ = v;
- *rgb = y1;
- return 4;
- default:
- DBG("Empty: %d\n", out_fmt);
- return 0;
- }
-}
-
-static int skipcount(int count, int fmt)
-{
- switch(fmt) {
- case VIDEO_PALETTE_GREY:
- return count;
- case VIDEO_PALETTE_RGB555:
- case VIDEO_PALETTE_RGB565:
- case VIDEO_PALETTE_YUV422:
- case VIDEO_PALETTE_YUYV:
- case VIDEO_PALETTE_UYVY:
- return 2*count;
- case VIDEO_PALETTE_RGB24:
- return 3*count;
- case VIDEO_PALETTE_RGB32:
- return 4*count;
- default:
- return 0;
- }
-}
-
-static int parse_picture(struct cam_data *cam, int size)
-{
- u8 *obuf, *ibuf, *end_obuf;
- int ll, in_uyvy, compressed, decimation, even_line, origsize, out_fmt;
- int rows, cols, linesize, subsample_422;
-
- /* make sure params don't change while we are decoding */
- mutex_lock(&cam->param_lock);
-
- obuf = cam->decompressed_frame.data;
- end_obuf = obuf+CPIA_MAX_FRAME_SIZE;
- ibuf = cam->raw_image;
- origsize = size;
- out_fmt = cam->vp.palette;
-
- if ((ibuf[0] != MAGIC_0) || (ibuf[1] != MAGIC_1)) {
- LOG("header not found\n");
- mutex_unlock(&cam->param_lock);
- return -1;
- }
-
- if ((ibuf[16] != VIDEOSIZE_QCIF) && (ibuf[16] != VIDEOSIZE_CIF)) {
- LOG("wrong video size\n");
- mutex_unlock(&cam->param_lock);
- return -1;
- }
-
- if (ibuf[17] != SUBSAMPLE_420 && ibuf[17] != SUBSAMPLE_422) {
- LOG("illegal subtype %d\n",ibuf[17]);
- mutex_unlock(&cam->param_lock);
- return -1;
- }
- subsample_422 = ibuf[17] == SUBSAMPLE_422;
-
- if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) {
- LOG("illegal yuvorder %d\n",ibuf[18]);
- mutex_unlock(&cam->param_lock);
- return -1;
- }
- in_uyvy = ibuf[18] == YUVORDER_UYVY;
-
- if ((ibuf[24] != cam->params.roi.colStart) ||
- (ibuf[25] != cam->params.roi.colEnd) ||
- (ibuf[26] != cam->params.roi.rowStart) ||
- (ibuf[27] != cam->params.roi.rowEnd)) {
- LOG("ROI mismatch\n");
- mutex_unlock(&cam->param_lock);
- return -1;
- }
- cols = 8*(ibuf[25] - ibuf[24]);
- rows = 4*(ibuf[27] - ibuf[26]);
-
-
- if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) {
- LOG("illegal compression %d\n",ibuf[28]);
- mutex_unlock(&cam->param_lock);
- return -1;
- }
- compressed = (ibuf[28] == COMPRESSED);
-
- if (ibuf[29] != NO_DECIMATION && ibuf[29] != DECIMATION_ENAB) {
- LOG("illegal decimation %d\n",ibuf[29]);
- mutex_unlock(&cam->param_lock);
- return -1;
- }
- decimation = (ibuf[29] == DECIMATION_ENAB);
-
- cam->params.yuvThreshold.yThreshold = ibuf[30];
- cam->params.yuvThreshold.uvThreshold = ibuf[31];
- cam->params.status.systemState = ibuf[32];
- cam->params.status.grabState = ibuf[33];
- cam->params.status.streamState = ibuf[34];
- cam->params.status.fatalError = ibuf[35];
- cam->params.status.cmdError = ibuf[36];
- cam->params.status.debugFlags = ibuf[37];
- cam->params.status.vpStatus = ibuf[38];
- cam->params.status.errorCode = ibuf[39];
- cam->fps = ibuf[41];
- mutex_unlock(&cam->param_lock);
-
- linesize = skipcount(cols, out_fmt);
- ibuf += FRAME_HEADER_SIZE;
- size -= FRAME_HEADER_SIZE;
- ll = ibuf[0] | (ibuf[1] << 8);
- ibuf += 2;
- even_line = 1;
-
- while (size > 0) {
- size -= (ll+2);
- if (size < 0) {
- LOG("Insufficient data in buffer\n");
- return -1;
- }
-
- while (ll > 1) {
- if (!compressed || (compressed && !(*ibuf & 1))) {
- if(subsample_422 || even_line) {
- obuf += yuvconvert(ibuf, obuf, out_fmt,
- in_uyvy, cam->mmap_kludge);
- ibuf += 4;
- ll -= 4;
- } else {
- /* SUBSAMPLE_420 on an odd line */
- obuf += convert420(ibuf, obuf,
- out_fmt, linesize,
- cam->mmap_kludge);
- ibuf += 2;
- ll -= 2;
- }
- } else {
- /*skip compressed interval from previous frame*/
- obuf += skipcount(*ibuf >> 1, out_fmt);
- if (obuf > end_obuf) {
- LOG("Insufficient buffer size\n");
- return -1;
- }
- ++ibuf;
- ll--;
- }
- }
- if (ll == 1) {
- if (*ibuf != EOL) {
- DBG("EOL not found giving up after %d/%d"
- " bytes\n", origsize-size, origsize);
- return -1;
- }
-
- ++ibuf; /* skip over EOL */
-
- if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) &&
- (ibuf[2] == EOI) && (ibuf[3] == EOI)) {
- size -= 4;
- break;
- }
-
- if(decimation) {
- /* skip the odd lines for now */
- obuf += linesize;
- }
-
- if (size > 1) {
- ll = ibuf[0] | (ibuf[1] << 8);
- ibuf += 2; /* skip over line length */
- }
- if(!decimation)
- even_line = !even_line;
- } else {
- LOG("line length was not 1 but %d after %d/%d bytes\n",
- ll, origsize-size, origsize);
- return -1;
- }
- }
-
- if(decimation) {
- /* interpolate odd rows */
- int i, j;
- u8 *prev, *next;
- prev = cam->decompressed_frame.data;
- obuf = prev+linesize;
- next = obuf+linesize;
- for(i=1; i<rows-1; i+=2) {
- for(j=0; j<linesize; ++j) {
- *obuf++ = ((int)*prev++ + *next++) / 2;
- }
- prev += linesize;
- obuf += linesize;
- next += linesize;
- }
- /* last row is odd, just copy previous row */
- memcpy(obuf, prev, linesize);
- }
-
- cam->decompressed_frame.count = obuf-cam->decompressed_frame.data;
-
- return cam->decompressed_frame.count;
-}
-
-/* InitStreamCap wrapper to select correct start line */
-static inline int init_stream_cap(struct cam_data *cam)
-{
- return do_command(cam, CPIA_COMMAND_InitStreamCap,
- 0, cam->params.streamStartLine, 0, 0);
-}
-
-
-/* find_over_exposure
- * Finds a suitable value of OverExposure for use with SetFlickerCtrl
- * Some calculation is required because this value changes with the brightness
- * set with SetColourParameters
- *
- * Parameters: Brightness - last brightness value set with SetColourParameters
- *
- * Returns: OverExposure value to use with SetFlickerCtrl
- */
-#define FLICKER_MAX_EXPOSURE 250
-#define FLICKER_ALLOWABLE_OVER_EXPOSURE 146
-#define FLICKER_BRIGHTNESS_CONSTANT 59
-static int find_over_exposure(int brightness)
-{
- int MaxAllowableOverExposure, OverExposure;
-
- MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
- FLICKER_BRIGHTNESS_CONSTANT;
-
- if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) {
- OverExposure = MaxAllowableOverExposure;
- } else {
- OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE;
- }
-
- return OverExposure;
-}
-#undef FLICKER_MAX_EXPOSURE
-#undef FLICKER_ALLOWABLE_OVER_EXPOSURE
-#undef FLICKER_BRIGHTNESS_CONSTANT
-
-/* update various camera modes and settings */
-static void dispatch_commands(struct cam_data *cam)
-{
- mutex_lock(&cam->param_lock);
- if (cam->cmd_queue==COMMAND_NONE) {
- mutex_unlock(&cam->param_lock);
- return;
- }
- DEB_BYTE(cam->cmd_queue);
- DEB_BYTE(cam->cmd_queue>>8);
- if (cam->cmd_queue & COMMAND_SETFORMAT) {
- do_command(cam, CPIA_COMMAND_SetFormat,
- cam->params.format.videoSize,
- cam->params.format.subSample,
- cam->params.format.yuvOrder, 0);
- do_command(cam, CPIA_COMMAND_SetROI,
- cam->params.roi.colStart, cam->params.roi.colEnd,
- cam->params.roi.rowStart, cam->params.roi.rowEnd);
- cam->first_frame = 1;
- }
-
- if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS)
- do_command(cam, CPIA_COMMAND_SetColourParams,
- cam->params.colourParams.brightness,
- cam->params.colourParams.contrast,
- cam->params.colourParams.saturation, 0);
-
- if (cam->cmd_queue & COMMAND_SETAPCOR)
- do_command(cam, CPIA_COMMAND_SetApcor,
- cam->params.apcor.gain1,
- cam->params.apcor.gain2,
- cam->params.apcor.gain4,
- cam->params.apcor.gain8);
-
- if (cam->cmd_queue & COMMAND_SETVLOFFSET)
- do_command(cam, CPIA_COMMAND_SetVLOffset,
- cam->params.vlOffset.gain1,
- cam->params.vlOffset.gain2,
- cam->params.vlOffset.gain4,
- cam->params.vlOffset.gain8);
-
- if (cam->cmd_queue & COMMAND_SETEXPOSURE) {
- do_command_extended(cam, CPIA_COMMAND_SetExposure,
- cam->params.exposure.gainMode,
- 1,
- cam->params.exposure.compMode,
- cam->params.exposure.centreWeight,
- cam->params.exposure.gain,
- cam->params.exposure.fineExp,
- cam->params.exposure.coarseExpLo,
- cam->params.exposure.coarseExpHi,
- cam->params.exposure.redComp,
- cam->params.exposure.green1Comp,
- cam->params.exposure.green2Comp,
- cam->params.exposure.blueComp);
- if(cam->params.exposure.expMode != 1) {
- do_command_extended(cam, CPIA_COMMAND_SetExposure,
- 0,
- cam->params.exposure.expMode,
- 0, 0,
- cam->params.exposure.gain,
- cam->params.exposure.fineExp,
- cam->params.exposure.coarseExpLo,
- cam->params.exposure.coarseExpHi,
- 0, 0, 0, 0);
- }
- }
-
- if (cam->cmd_queue & COMMAND_SETCOLOURBALANCE) {
- if (cam->params.colourBalance.balanceMode == 1) {
- do_command(cam, CPIA_COMMAND_SetColourBalance,
- 1,
- cam->params.colourBalance.redGain,
- cam->params.colourBalance.greenGain,
- cam->params.colourBalance.blueGain);
- do_command(cam, CPIA_COMMAND_SetColourBalance,
- 3, 0, 0, 0);
- }
- if (cam->params.colourBalance.balanceMode == 2) {
- do_command(cam, CPIA_COMMAND_SetColourBalance,
- 2, 0, 0, 0);
- }
- if (cam->params.colourBalance.balanceMode == 3) {
- do_command(cam, CPIA_COMMAND_SetColourBalance,
- 3, 0, 0, 0);
- }
- }
-
- if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET)
- do_command(cam, CPIA_COMMAND_SetCompressionTarget,
- cam->params.compressionTarget.frTargeting,
- cam->params.compressionTarget.targetFR,
- cam->params.compressionTarget.targetQ, 0);
-
- if (cam->cmd_queue & COMMAND_SETYUVTHRESH)
- do_command(cam, CPIA_COMMAND_SetYUVThresh,
- cam->params.yuvThreshold.yThreshold,
- cam->params.yuvThreshold.uvThreshold, 0, 0);
-
- if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS)
- do_command_extended(cam, CPIA_COMMAND_SetCompressionParams,
- 0, 0, 0, 0,
- cam->params.compressionParams.hysteresis,
- cam->params.compressionParams.threshMax,
- cam->params.compressionParams.smallStep,
- cam->params.compressionParams.largeStep,
- cam->params.compressionParams.decimationHysteresis,
- cam->params.compressionParams.frDiffStepThresh,
- cam->params.compressionParams.qDiffStepThresh,
- cam->params.compressionParams.decimationThreshMod);
-
- if (cam->cmd_queue & COMMAND_SETCOMPRESSION)
- do_command(cam, CPIA_COMMAND_SetCompression,
- cam->params.compression.mode,
- cam->params.compression.decimation, 0, 0);
-
- if (cam->cmd_queue & COMMAND_SETSENSORFPS)
- do_command(cam, CPIA_COMMAND_SetSensorFPS,
- cam->params.sensorFps.divisor,
- cam->params.sensorFps.baserate, 0, 0);
-
- if (cam->cmd_queue & COMMAND_SETFLICKERCTRL)
- do_command(cam, CPIA_COMMAND_SetFlickerCtrl,
- cam->params.flickerControl.flickerMode,
- cam->params.flickerControl.coarseJump,
- abs(cam->params.flickerControl.allowableOverExposure),
- 0);
-
- if (cam->cmd_queue & COMMAND_SETECPTIMING)
- do_command(cam, CPIA_COMMAND_SetECPTiming,
- cam->params.ecpTiming, 0, 0, 0);
-
- if (cam->cmd_queue & COMMAND_PAUSE)
- do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
-
- if (cam->cmd_queue & COMMAND_RESUME)
- init_stream_cap(cam);
-
- if (cam->cmd_queue & COMMAND_SETLIGHTS && cam->params.qx3.qx3_detected)
- {
- int p1 = (cam->params.qx3.bottomlight == 0) << 1;
- int p2 = (cam->params.qx3.toplight == 0) << 3;
- do_command(cam, CPIA_COMMAND_WriteVCReg, 0x90, 0x8F, 0x50, 0);
- do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0);
- }
-
- cam->cmd_queue = COMMAND_NONE;
- mutex_unlock(&cam->param_lock);
- return;
-}
-
-
-
-static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
- int on)
-{
- /* Everything in here is from the Windows driver */
-#define FIRMWARE_VERSION(x,y) (params->version.firmwareVersion == (x) && \
- params->version.firmwareRevision == (y))
-/* define for compgain calculation */
-#if 0
-#define COMPGAIN(base, curexp, newexp) \
- (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5)
-#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
- (u16)((float)curexp * (float)(u8)(curcomp + 128) / (float)(u8)(basecomp - 128))
-#else
- /* equivalent functions without floating point math */
-#define COMPGAIN(base, curexp, newexp) \
- (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2* newexp)) )
-#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
- (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
-#endif
-
-
- int currentexp = params->exposure.coarseExpLo +
- params->exposure.coarseExpHi*256;
- int startexp;
- if (on) {
- int cj = params->flickerControl.coarseJump;
- params->flickerControl.flickerMode = 1;
- params->flickerControl.disabled = 0;
- if(params->exposure.expMode != 2)
- *command_flags |= COMMAND_SETEXPOSURE;
- params->exposure.expMode = 2;
- currentexp = currentexp << params->exposure.gain;
- params->exposure.gain = 0;
- /* round down current exposure to nearest value */
- startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj;
- if(startexp < 1)
- startexp = 1;
- startexp = (startexp * cj) - 1;
- if(FIRMWARE_VERSION(1,2))
- while(startexp > MAX_EXP_102)
- startexp -= cj;
- else
- while(startexp > MAX_EXP)
- startexp -= cj;
- params->exposure.coarseExpLo = startexp & 0xff;
- params->exposure.coarseExpHi = startexp >> 8;
- if (currentexp > startexp) {
- if (currentexp > (2 * startexp))
- currentexp = 2 * startexp;
- params->exposure.redComp = COMPGAIN (COMP_RED, currentexp, startexp);
- params->exposure.green1Comp = COMPGAIN (COMP_GREEN1, currentexp, startexp);
- params->exposure.green2Comp = COMPGAIN (COMP_GREEN2, currentexp, startexp);
- params->exposure.blueComp = COMPGAIN (COMP_BLUE, currentexp, startexp);
- } else {
- params->exposure.redComp = COMP_RED;
- params->exposure.green1Comp = COMP_GREEN1;
- params->exposure.green2Comp = COMP_GREEN2;
- params->exposure.blueComp = COMP_BLUE;
- }
- if(FIRMWARE_VERSION(1,2))
- params->exposure.compMode = 0;
- else
- params->exposure.compMode = 1;
-
- params->apcor.gain1 = 0x18;
- params->apcor.gain2 = 0x18;
- params->apcor.gain4 = 0x16;
- params->apcor.gain8 = 0x14;
- *command_flags |= COMMAND_SETAPCOR;
- } else {
- params->flickerControl.flickerMode = 0;
- params->flickerControl.disabled = 1;
- /* Coarse = average of equivalent coarse for each comp channel */
- startexp = EXP_FROM_COMP(COMP_RED, params->exposure.redComp, currentexp);
- startexp += EXP_FROM_COMP(COMP_GREEN1, params->exposure.green1Comp, currentexp);
- startexp += EXP_FROM_COMP(COMP_GREEN2, params->exposure.green2Comp, currentexp);
- startexp += EXP_FROM_COMP(COMP_BLUE, params->exposure.blueComp, currentexp);
- startexp = startexp >> 2;
- while(startexp > MAX_EXP &&
- params->exposure.gain < params->exposure.gainMode-1) {
- startexp = startexp >> 1;
- ++params->exposure.gain;
- }
- if(FIRMWARE_VERSION(1,2) && startexp > MAX_EXP_102)
- startexp = MAX_EXP_102;
- if(startexp > MAX_EXP)
- startexp = MAX_EXP;
- params->exposure.coarseExpLo = startexp&0xff;
- params->exposure.coarseExpHi = startexp >> 8;
- params->exposure.redComp = COMP_RED;
- params->exposure.green1Comp = COMP_GREEN1;
- params->exposure.green2Comp = COMP_GREEN2;
- params->exposure.blueComp = COMP_BLUE;
- params->exposure.compMode = 1;
- *command_flags |= COMMAND_SETEXPOSURE;
- params->apcor.gain1 = 0x18;
- params->apcor.gain2 = 0x16;
- params->apcor.gain4 = 0x24;
- params->apcor.gain8 = 0x34;
- *command_flags |= COMMAND_SETAPCOR;
- }
- params->vlOffset.gain1 = 20;
- params->vlOffset.gain2 = 24;
- params->vlOffset.gain4 = 26;
- params->vlOffset.gain8 = 26;
- *command_flags |= COMMAND_SETVLOFFSET;
-#undef FIRMWARE_VERSION
-#undef EXP_FROM_COMP
-#undef COMPGAIN
-}
-
-#define FIRMWARE_VERSION(x,y) (cam->params.version.firmwareVersion == (x) && \
- cam->params.version.firmwareRevision == (y))
-/* monitor the exposure and adjust the sensor frame rate if needed */
-static void monitor_exposure(struct cam_data *cam)
-{
- u8 exp_acc, bcomp, gain, coarseL, cmd[8], data[8];
- int retval, light_exp, dark_exp, very_dark_exp;
- int old_exposure, new_exposure, framerate;
-
- /* get necessary stats and register settings from camera */
- /* do_command can't handle this, so do it ourselves */
- cmd[0] = CPIA_COMMAND_ReadVPRegs>>8;
- cmd[1] = CPIA_COMMAND_ReadVPRegs&0xff;
- cmd[2] = 30;
- cmd[3] = 4;
- cmd[4] = 9;
- cmd[5] = 8;
- cmd[6] = 8;
- cmd[7] = 0;
- retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
- if (retval) {
- LOG("ReadVPRegs(30,4,9,8) - failed, retval=%d\n",
- retval);
- return;
- }
- exp_acc = data[0];
- bcomp = data[1];
- gain = data[2];
- coarseL = data[3];
-
- mutex_lock(&cam->param_lock);
- light_exp = cam->params.colourParams.brightness +
- TC - 50 + EXP_ACC_LIGHT;
- if(light_exp > 255)
- light_exp = 255;
- dark_exp = cam->params.colourParams.brightness +
- TC - 50 - EXP_ACC_DARK;
- if(dark_exp < 0)
- dark_exp = 0;
- very_dark_exp = dark_exp/2;
-
- old_exposure = cam->params.exposure.coarseExpHi * 256 +
- cam->params.exposure.coarseExpLo;
-
- if(!cam->params.flickerControl.disabled) {
- /* Flicker control on */
- int max_comp = FIRMWARE_VERSION(1,2) ? MAX_COMP : HIGH_COMP_102;
- bcomp += 128; /* decode */
- if(bcomp >= max_comp && exp_acc < dark_exp) {
- /* dark */
- if(exp_acc < very_dark_exp) {
- /* very dark */
- if(cam->exposure_status == EXPOSURE_VERY_DARK)
- ++cam->exposure_count;
- else {
- cam->exposure_status = EXPOSURE_VERY_DARK;
- cam->exposure_count = 1;
- }
- } else {
- /* just dark */
- if(cam->exposure_status == EXPOSURE_DARK)
- ++cam->exposure_count;
- else {
- cam->exposure_status = EXPOSURE_DARK;
- cam->exposure_count = 1;
- }
- }
- } else if(old_exposure <= LOW_EXP || exp_acc > light_exp) {
- /* light */
- if(old_exposure <= VERY_LOW_EXP) {
- /* very light */
- if(cam->exposure_status == EXPOSURE_VERY_LIGHT)
- ++cam->exposure_count;
- else {
- cam->exposure_status = EXPOSURE_VERY_LIGHT;
- cam->exposure_count = 1;
- }
- } else {
- /* just light */
- if(cam->exposure_status == EXPOSURE_LIGHT)
- ++cam->exposure_count;
- else {
- cam->exposure_status = EXPOSURE_LIGHT;
- cam->exposure_count = 1;
- }
- }
- } else {
- /* not dark or light */
- cam->exposure_status = EXPOSURE_NORMAL;
- }
- } else {
- /* Flicker control off */
- if(old_exposure >= MAX_EXP && exp_acc < dark_exp) {
- /* dark */
- if(exp_acc < very_dark_exp) {
- /* very dark */
- if(cam->exposure_status == EXPOSURE_VERY_DARK)
- ++cam->exposure_count;
- else {
- cam->exposure_status = EXPOSURE_VERY_DARK;
- cam->exposure_count = 1;
- }
- } else {
- /* just dark */
- if(cam->exposure_status == EXPOSURE_DARK)
- ++cam->exposure_count;
- else {
- cam->exposure_status = EXPOSURE_DARK;
- cam->exposure_count = 1;
- }
- }
- } else if(old_exposure <= LOW_EXP || exp_acc > light_exp) {
- /* light */
- if(old_exposure <= VERY_LOW_EXP) {
- /* very light */
- if(cam->exposure_status == EXPOSURE_VERY_LIGHT)
- ++cam->exposure_count;
- else {
- cam->exposure_status = EXPOSURE_VERY_LIGHT;
- cam->exposure_count = 1;
- }
- } else {
- /* just light */
- if(cam->exposure_status == EXPOSURE_LIGHT)
- ++cam->exposure_count;
- else {
- cam->exposure_status = EXPOSURE_LIGHT;
- cam->exposure_count = 1;
- }
- }
- } else {
- /* not dark or light */
- cam->exposure_status = EXPOSURE_NORMAL;
- }
- }
-
- framerate = cam->fps;
- if(framerate > 30 || framerate < 1)
- framerate = 1;
-
- if(!cam->params.flickerControl.disabled) {
- /* Flicker control on */
- if((cam->exposure_status == EXPOSURE_VERY_DARK ||
- cam->exposure_status == EXPOSURE_DARK) &&
- cam->exposure_count >= DARK_TIME*framerate &&
- cam->params.sensorFps.divisor < 3) {
-
- /* dark for too long */
- ++cam->params.sensorFps.divisor;
- cam->cmd_queue |= COMMAND_SETSENSORFPS;
-
- cam->params.flickerControl.coarseJump =
- flicker_jumps[cam->mainsFreq]
- [cam->params.sensorFps.baserate]
- [cam->params.sensorFps.divisor];
- cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
-
- new_exposure = cam->params.flickerControl.coarseJump-1;
- while(new_exposure < old_exposure/2)
- new_exposure += cam->params.flickerControl.coarseJump;
- cam->params.exposure.coarseExpLo = new_exposure & 0xff;
- cam->params.exposure.coarseExpHi = new_exposure >> 8;
- cam->cmd_queue |= COMMAND_SETEXPOSURE;
- cam->exposure_status = EXPOSURE_NORMAL;
- LOG("Automatically decreasing sensor_fps\n");
-
- } else if((cam->exposure_status == EXPOSURE_VERY_LIGHT ||
- cam->exposure_status == EXPOSURE_LIGHT) &&
- cam->exposure_count >= LIGHT_TIME*framerate &&
- cam->params.sensorFps.divisor > 0) {
-
- /* light for too long */
- int max_exp = FIRMWARE_VERSION(1,2) ? MAX_EXP_102 : MAX_EXP ;
-
- --cam->params.sensorFps.divisor;
- cam->cmd_queue |= COMMAND_SETSENSORFPS;
-
- cam->params.flickerControl.coarseJump =
- flicker_jumps[cam->mainsFreq]
- [cam->params.sensorFps.baserate]
- [cam->params.sensorFps.divisor];
- cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
-
- new_exposure = cam->params.flickerControl.coarseJump-1;
- while(new_exposure < 2*old_exposure &&
- new_exposure+
- cam->params.flickerControl.coarseJump < max_exp)
- new_exposure += cam->params.flickerControl.coarseJump;
- cam->params.exposure.coarseExpLo = new_exposure & 0xff;
- cam->params.exposure.coarseExpHi = new_exposure >> 8;
- cam->cmd_queue |= COMMAND_SETEXPOSURE;
- cam->exposure_status = EXPOSURE_NORMAL;
- LOG("Automatically increasing sensor_fps\n");
- }
- } else {
- /* Flicker control off */
- if((cam->exposure_status == EXPOSURE_VERY_DARK ||
- cam->exposure_status == EXPOSURE_DARK) &&
- cam->exposure_count >= DARK_TIME*framerate &&
- cam->params.sensorFps.divisor < 3) {
-
- /* dark for too long */
- ++cam->params.sensorFps.divisor;
- cam->cmd_queue |= COMMAND_SETSENSORFPS;
-
- if(cam->params.exposure.gain > 0) {
- --cam->params.exposure.gain;
- cam->cmd_queue |= COMMAND_SETEXPOSURE;
- }
- cam->exposure_status = EXPOSURE_NORMAL;
- LOG("Automatically decreasing sensor_fps\n");
-
- } else if((cam->exposure_status == EXPOSURE_VERY_LIGHT ||
- cam->exposure_status == EXPOSURE_LIGHT) &&
- cam->exposure_count >= LIGHT_TIME*framerate &&
- cam->params.sensorFps.divisor > 0) {
-
- /* light for too long */
- --cam->params.sensorFps.divisor;
- cam->cmd_queue |= COMMAND_SETSENSORFPS;
-
- if(cam->params.exposure.gain <
- cam->params.exposure.gainMode-1) {
- ++cam->params.exposure.gain;
- cam->cmd_queue |= COMMAND_SETEXPOSURE;
- }
- cam->exposure_status = EXPOSURE_NORMAL;
- LOG("Automatically increasing sensor_fps\n");
- }
- }
- mutex_unlock(&cam->param_lock);
-}
-
-/*-----------------------------------------------------------------*/
-/* if flicker is switched off, this function switches it back on.It checks,
- however, that conditions are suitable before restarting it.
- This should only be called for firmware version 1.2.
-
- It also adjust the colour balance when an exposure step is detected - as
- long as flicker is running
-*/
-static void restart_flicker(struct cam_data *cam)
-{
- int cam_exposure, old_exp;
- if(!FIRMWARE_VERSION(1,2))
- return;
- mutex_lock(&cam->param_lock);
- if(cam->params.flickerControl.flickerMode == 0 ||
- cam->raw_image[39] == 0) {
- mutex_unlock(&cam->param_lock);
- return;
- }
- cam_exposure = cam->raw_image[39]*2;
- old_exp = cam->params.exposure.coarseExpLo +
- cam->params.exposure.coarseExpHi*256;
- /*
- see how far away camera exposure is from a valid
- flicker exposure value
- */
- cam_exposure %= cam->params.flickerControl.coarseJump;
- if(!cam->params.flickerControl.disabled &&
- cam_exposure <= cam->params.flickerControl.coarseJump - 3) {
- /* Flicker control auto-disabled */
- cam->params.flickerControl.disabled = 1;
- }
-
- if(cam->params.flickerControl.disabled &&
- cam->params.flickerControl.flickerMode &&
- old_exp > cam->params.flickerControl.coarseJump +
- ROUND_UP_EXP_FOR_FLICKER) {
- /* exposure is now high enough to switch
- flicker control back on */
- set_flicker(&cam->params, &cam->cmd_queue, 1);
- if((cam->cmd_queue & COMMAND_SETEXPOSURE) &&
- cam->params.exposure.expMode == 2)
- cam->exposure_status = EXPOSURE_NORMAL;
-
- }
- mutex_unlock(&cam->param_lock);
-}
-#undef FIRMWARE_VERSION
-
-static int clear_stall(struct cam_data *cam)
-{
- /* FIXME: Does this actually work? */
- LOG("Clearing stall\n");
-
- cam->ops->streamRead(cam->lowlevel_data, cam->raw_image, 0);
- do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0);
- return cam->params.status.streamState != STREAM_PAUSED;
-}
-
-/* kernel thread function to read image from camera */
-static int fetch_frame(void *data)
-{
- int image_size, retry;
- struct cam_data *cam = (struct cam_data *)data;
- unsigned long oldjif, rate, diff;
-
- /* Allow up to two bad images in a row to be read and
- * ignored before an error is reported */
- for (retry = 0; retry < 3; ++retry) {
- if (retry)
- DBG("retry=%d\n", retry);
-
- if (!cam->ops)
- continue;
-
- /* load first frame always uncompressed */
- if (cam->first_frame &&
- cam->params.compression.mode != CPIA_COMPRESSION_NONE) {
- do_command(cam, CPIA_COMMAND_SetCompression,
- CPIA_COMPRESSION_NONE,
- NO_DECIMATION, 0, 0);
- /* Trial & error - Discarding a frame prevents the
- first frame from having an error in the data. */
- do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
- }
-
- /* init camera upload */
- if (do_command(cam, CPIA_COMMAND_GrabFrame, 0,
- cam->params.streamStartLine, 0, 0))
- continue;
-
- if (cam->ops->wait_for_stream_ready) {
- /* loop until image ready */
- int count = 0;
- do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0);
- while (cam->params.status.streamState != STREAM_READY) {
- if(++count > READY_TIMEOUT)
- break;
- if(cam->params.status.streamState ==
- STREAM_PAUSED) {
- /* Bad news */
- if(!clear_stall(cam))
- return -EIO;
- }
-
- cond_resched();
-
- /* sleep for 10 ms, hopefully ;) */
- msleep_interruptible(10);
- if (signal_pending(current))
- return -EINTR;
-
- do_command(cam, CPIA_COMMAND_GetCameraStatus,
- 0, 0, 0, 0);
- }
- if(cam->params.status.streamState != STREAM_READY) {
- continue;
- }
- }
-
- cond_resched();
-
- /* grab image from camera */
- oldjif = jiffies;
- image_size = cam->ops->streamRead(cam->lowlevel_data,
- cam->raw_image, 0);
- if (image_size <= 0) {
- DBG("streamRead failed: %d\n", image_size);
- continue;
- }
-
- rate = image_size * HZ / 1024;
- diff = jiffies-oldjif;
- cam->transfer_rate = diff==0 ? rate : rate/diff;
- /* diff==0 ? unlikely but possible */
-
- /* Switch flicker control back on if it got turned off */
- restart_flicker(cam);
-
- /* If AEC is enabled, monitor the exposure and
- adjust the sensor frame rate if needed */
- if(cam->params.exposure.expMode == 2)
- monitor_exposure(cam);
-
- /* camera idle now so dispatch queued commands */
- dispatch_commands(cam);
-
- /* Update our knowledge of the camera state */
- do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
- do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
- do_command(cam, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
-
- /* decompress and convert image to by copying it from
- * raw_image to decompressed_frame
- */
-
- cond_resched();
-
- cam->image_size = parse_picture(cam, image_size);
- if (cam->image_size <= 0) {
- DBG("parse_picture failed %d\n", cam->image_size);
- if(cam->params.compression.mode !=
- CPIA_COMPRESSION_NONE) {
- /* Compression may not work right if we
- had a bad frame, get the next one
- uncompressed. */
- cam->first_frame = 1;
- do_command(cam, CPIA_COMMAND_SetGrabMode,
- CPIA_GRAB_SINGLE, 0, 0, 0);
- /* FIXME: Trial & error - need up to 70ms for
- the grab mode change to complete ? */
- msleep_interruptible(70);
- if (signal_pending(current))
- return -EINTR;
- }
- } else
- break;
- }
-
- if (retry < 3) {
- /* FIXME: this only works for double buffering */
- if (cam->frame[cam->curframe].state == FRAME_READY) {
- memcpy(cam->frame[cam->curframe].data,
- cam->decompressed_frame.data,
- cam->decompressed_frame.count);
- cam->frame[cam->curframe].state = FRAME_DONE;
- } else
- cam->decompressed_frame.state = FRAME_DONE;
-
- if (cam->first_frame) {
- cam->first_frame = 0;
- do_command(cam, CPIA_COMMAND_SetCompression,
- cam->params.compression.mode,
- cam->params.compression.decimation, 0, 0);
-
- /* Switch from single-grab to continuous grab */
- do_command(cam, CPIA_COMMAND_SetGrabMode,
- CPIA_GRAB_CONTINUOUS, 0, 0, 0);
- }
- return 0;
- }
- return -EIO;
-}
-
-static int capture_frame(struct cam_data *cam, struct video_mmap *vm)
-{
- if (!cam->frame_buf) {
- /* we do lazy allocation */
- int err;
- if ((err = allocate_frame_buf(cam)))
- return err;
- }
-
- cam->curframe = vm->frame;
- cam->frame[cam->curframe].state = FRAME_READY;
- return fetch_frame(cam);
-}
-
-static int goto_high_power(struct cam_data *cam)
-{
- if (do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0))
- return -EIO;
- msleep_interruptible(40); /* windows driver does it too */
- if(signal_pending(current))
- return -EINTR;
- if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
- return -EIO;
- if (cam->params.status.systemState == HI_POWER_STATE) {
- DBG("camera now in HIGH power state\n");
- return 0;
- }
- printstatus(cam);
- return -EIO;
-}
-
-static int goto_low_power(struct cam_data *cam)
-{
- if (do_command(cam, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0))
- return -1;
- if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
- return -1;
- if (cam->params.status.systemState == LO_POWER_STATE) {
- DBG("camera now in LOW power state\n");
- return 0;
- }
- printstatus(cam);
- return -1;
-}
-
-static void save_camera_state(struct cam_data *cam)
-{
- if(!(cam->cmd_queue & COMMAND_SETCOLOURBALANCE))
- do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
- if(!(cam->cmd_queue & COMMAND_SETEXPOSURE))
- do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
-
- DBG("%d/%d/%d/%d/%d/%d/%d/%d\n",
- cam->params.exposure.gain,
- cam->params.exposure.fineExp,
- cam->params.exposure.coarseExpLo,
- cam->params.exposure.coarseExpHi,
- cam->params.exposure.redComp,
- cam->params.exposure.green1Comp,
- cam->params.exposure.green2Comp,
- cam->params.exposure.blueComp);
- DBG("%d/%d/%d\n",
- cam->params.colourBalance.redGain,
- cam->params.colourBalance.greenGain,
- cam->params.colourBalance.blueGain);
-}
-
-static int set_camera_state(struct cam_data *cam)
-{
- cam->cmd_queue = COMMAND_SETCOMPRESSION |
- COMMAND_SETCOMPRESSIONTARGET |
- COMMAND_SETCOLOURPARAMS |
- COMMAND_SETFORMAT |
- COMMAND_SETYUVTHRESH |
- COMMAND_SETECPTIMING |
- COMMAND_SETCOMPRESSIONPARAMS |
- COMMAND_SETEXPOSURE |
- COMMAND_SETCOLOURBALANCE |
- COMMAND_SETSENSORFPS |
- COMMAND_SETAPCOR |
- COMMAND_SETFLICKERCTRL |
- COMMAND_SETVLOFFSET;
-
- do_command(cam, CPIA_COMMAND_SetGrabMode, CPIA_GRAB_SINGLE,0,0,0);
- dispatch_commands(cam);
-
- /* Wait 6 frames for the sensor to get all settings and
- AEC/ACB to settle */
- msleep_interruptible(6*(cam->params.sensorFps.baserate ? 33 : 40) *
- (1 << cam->params.sensorFps.divisor) + 10);
-
- if(signal_pending(current))
- return -EINTR;
-
- save_camera_state(cam);
-
- return 0;
-}
-
-static void get_version_information(struct cam_data *cam)
-{
- /* GetCPIAVersion */
- do_command(cam, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
-
- /* GetPnPID */
- do_command(cam, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
-}
-
-/* initialize camera */
-static int reset_camera(struct cam_data *cam)
-{
- int err;
- /* Start the camera in low power mode */
- if (goto_low_power(cam)) {
- if (cam->params.status.systemState != WARM_BOOT_STATE)
- return -ENODEV;
-
- /* FIXME: this is just dirty trial and error */
- err = goto_high_power(cam);
- if(err)
- return err;
- do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
- if (goto_low_power(cam))
- return -ENODEV;
- }
-
- /* procedure described in developer's guide p3-28 */
-
- /* Check the firmware version. */
- cam->params.version.firmwareVersion = 0;
- get_version_information(cam);
- if (cam->params.version.firmwareVersion != 1)
- return -ENODEV;
-
- /* A bug in firmware 1-02 limits gainMode to 2 */
- if(cam->params.version.firmwareRevision <= 2 &&
- cam->params.exposure.gainMode > 2) {
- cam->params.exposure.gainMode = 2;
- }
-
- /* set QX3 detected flag */
- cam->params.qx3.qx3_detected = (cam->params.pnpID.vendor == 0x0813 &&
- cam->params.pnpID.product == 0x0001);
-
- /* The fatal error checking should be done after
- * the camera powers up (developer's guide p 3-38) */
-
- /* Set streamState before transition to high power to avoid bug
- * in firmware 1-02 */
- do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0,
- STREAM_NOT_READY, 0);
-
- /* GotoHiPower */
- err = goto_high_power(cam);
- if (err)
- return err;
-
- /* Check the camera status */
- if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
- return -EIO;
-
- if (cam->params.status.fatalError) {
- DBG("fatal_error: %#04x\n",
- cam->params.status.fatalError);
- DBG("vp_status: %#04x\n",
- cam->params.status.vpStatus);
- if (cam->params.status.fatalError & ~(COM_FLAG|CPIA_FLAG)) {
- /* Fatal error in camera */
- return -EIO;
- } else if (cam->params.status.fatalError & (COM_FLAG|CPIA_FLAG)) {
- /* Firmware 1-02 may do this for parallel port cameras,
- * just clear the flags (developer's guide p 3-38) */
- do_command(cam, CPIA_COMMAND_ModifyCameraStatus,
- FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0);
- }
- }
-
- /* Check the camera status again */
- if (cam->params.status.fatalError) {
- if (cam->params.status.fatalError)
- return -EIO;
- }
-
- /* VPVersion can't be retrieved before the camera is in HiPower,
- * so get it here instead of in get_version_information. */
- do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
-
- /* set camera to a known state */
- return set_camera_state(cam);
-}
-
-static void put_cam(struct cpia_camera_ops* ops)
-{
- module_put(ops->owner);
-}
-
-/* ------------------------- V4L interface --------------------- */
-static int cpia_open(struct file *file)
-{
- struct video_device *dev = video_devdata(file);
- struct cam_data *cam = video_get_drvdata(dev);
- int err;
-
- if (!cam) {
- DBG("Internal error, cam_data not found!\n");
- return -ENODEV;
- }
-
- if (cam->open_count > 0) {
- DBG("Camera already open\n");
- return -EBUSY;
- }
-
- if (!try_module_get(cam->ops->owner))
- return -ENODEV;
-
- mutex_lock(&cam->busy_lock);
- err = -ENOMEM;
- if (!cam->raw_image) {
- cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE);
- if (!cam->raw_image)
- goto oops;
- }
-
- if (!cam->decompressed_frame.data) {
- cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE);
- if (!cam->decompressed_frame.data)
- goto oops;
- }
-
- /* open cpia */
- err = -ENODEV;
- if (cam->ops->open(cam->lowlevel_data))
- goto oops;
-
- /* reset the camera */
- if ((err = reset_camera(cam)) != 0) {
- cam->ops->close(cam->lowlevel_data);
- goto oops;
- }
-
- /* Set ownership of /proc/cpia/videoX to current user */
- if(cam->proc_entry)
- cam->proc_entry->uid = current_euid();
-
- /* set mark for loading first frame uncompressed */
- cam->first_frame = 1;
-
- /* init it to something */
- cam->mmap_kludge = 0;
-
- ++cam->open_count;
- file->private_data = dev;
- mutex_unlock(&cam->busy_lock);
- return 0;
-
- oops:
- if (cam->decompressed_frame.data) {
- rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
- cam->decompressed_frame.data = NULL;
- }
- if (cam->raw_image) {
- rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
- cam->raw_image = NULL;
- }
- mutex_unlock(&cam->busy_lock);
- put_cam(cam->ops);
- return err;
-}
-
-static int cpia_close(struct file *file)
-{
- struct video_device *dev = file->private_data;
- struct cam_data *cam = video_get_drvdata(dev);
-
- if (cam->ops) {
- /* Return ownership of /proc/cpia/videoX to root */
- if(cam->proc_entry)
- cam->proc_entry->uid = 0;
-
- /* save camera state for later open (developers guide ch 3.5.3) */
- save_camera_state(cam);
-
- /* GotoLoPower */
- goto_low_power(cam);
-
- /* Update the camera status */
- do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
-
- /* cleanup internal state stuff */
- free_frames(cam->frame);
-
- /* close cpia */
- cam->ops->close(cam->lowlevel_data);
-
- put_cam(cam->ops);
- }
-
- if (--cam->open_count == 0) {
- /* clean up capture-buffers */
- if (cam->raw_image) {
- rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
- cam->raw_image = NULL;
- }
-
- if (cam->decompressed_frame.data) {
- rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
- cam->decompressed_frame.data = NULL;
- }
-
- if (cam->frame_buf)
- free_frame_buf(cam);
-
- if (!cam->ops)
- kfree(cam);
- }
- file->private_data = NULL;
-
- return 0;
-}
-
-static ssize_t cpia_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct video_device *dev = file->private_data;
- struct cam_data *cam = video_get_drvdata(dev);
- int err;
-
- /* make this _really_ smp and multithread-safe */
- if (mutex_lock_interruptible(&cam->busy_lock))
- return -EINTR;
-
- if (!buf) {
- DBG("buf NULL\n");
- mutex_unlock(&cam->busy_lock);
- return -EINVAL;
- }
-
- if (!count) {
- DBG("count 0\n");
- mutex_unlock(&cam->busy_lock);
- return 0;
- }
-
- if (!cam->ops) {
- DBG("ops NULL\n");
- mutex_unlock(&cam->busy_lock);
- return -ENODEV;
- }
-
- /* upload frame */
- cam->decompressed_frame.state = FRAME_READY;
- cam->mmap_kludge=0;
- if((err = fetch_frame(cam)) != 0) {
- DBG("ERROR from fetch_frame: %d\n", err);
- mutex_unlock(&cam->busy_lock);
- return err;
- }
- cam->decompressed_frame.state = FRAME_UNUSED;
-
- /* copy data to user space */
- if (cam->decompressed_frame.count > count) {
- DBG("count wrong: %d, %lu\n", cam->decompressed_frame.count,
- (unsigned long) count);
- mutex_unlock(&cam->busy_lock);
- return -EFAULT;
- }
- if (copy_to_user(buf, cam->decompressed_frame.data,
- cam->decompressed_frame.count)) {
- DBG("copy_to_user failed\n");
- mutex_unlock(&cam->busy_lock);
- return -EFAULT;
- }
-
- mutex_unlock(&cam->busy_lock);
- return cam->decompressed_frame.count;
-}
-
-static long cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
-{
- struct video_device *dev = file->private_data;
- struct cam_data *cam = video_get_drvdata(dev);
- int retval = 0;
-
- if (!cam || !cam->ops)
- return -ENODEV;
-
- /* make this _really_ smp-safe */
- if (mutex_lock_interruptible(&cam->busy_lock))
- return -EINTR;
-
- /* DBG("cpia_ioctl: %u\n", cmd); */
-
- switch (cmd) {
- /* query capabilities */
- case VIDIOCGCAP:
- {
- struct video_capability *b = arg;
-
- DBG("VIDIOCGCAP\n");
- strcpy(b->name, "CPiA Camera");
- b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
- b->channels = 1;
- b->audios = 0;
- b->maxwidth = 352; /* VIDEOSIZE_CIF */
- b->maxheight = 288;
- b->minwidth = 48; /* VIDEOSIZE_48_48 */
- b->minheight = 48;
- break;
- }
-
- /* get/set video source - we are a camera and nothing else */
- case VIDIOCGCHAN:
- {
- struct video_channel *v = arg;
-
- DBG("VIDIOCGCHAN\n");
- if (v->channel != 0) {
- retval = -EINVAL;
- break;
- }
-
- v->channel = 0;
- strcpy(v->name, "Camera");
- v->tuners = 0;
- v->flags = 0;
- v->type = VIDEO_TYPE_CAMERA;
- v->norm = 0;
- break;
- }
-
- case VIDIOCSCHAN:
- {
- struct video_channel *v = arg;
-
- DBG("VIDIOCSCHAN\n");
- if (v->channel != 0)
- retval = -EINVAL;
- break;
- }
-
- /* image properties */
- case VIDIOCGPICT:
- {
- struct video_picture *pic = arg;
- DBG("VIDIOCGPICT\n");
- *pic = cam->vp;
- break;
- }
-
- case VIDIOCSPICT:
- {
- struct video_picture *vp = arg;
-
- DBG("VIDIOCSPICT\n");
-
- /* check validity */
- DBG("palette: %d\n", vp->palette);
- DBG("depth: %d\n", vp->depth);
- if (!valid_mode(vp->palette, vp->depth)) {
- retval = -EINVAL;
- break;
- }
-
- mutex_lock(&cam->param_lock);
- /* brightness, colour, contrast need no check 0-65535 */
- cam->vp = *vp;
- /* update cam->params.colourParams */
- cam->params.colourParams.brightness = vp->brightness*100/65535;
- cam->params.colourParams.contrast = vp->contrast*100/65535;
- cam->params.colourParams.saturation = vp->colour*100/65535;
- /* contrast is in steps of 8, so round */
- cam->params.colourParams.contrast =
- ((cam->params.colourParams.contrast + 3) / 8) * 8;
- if (cam->params.version.firmwareVersion == 1 &&
- cam->params.version.firmwareRevision == 2 &&
- cam->params.colourParams.contrast > 80) {
- /* 1-02 firmware limits contrast to 80 */
- cam->params.colourParams.contrast = 80;
- }
-
- /* Adjust flicker control if necessary */
- if(cam->params.flickerControl.allowableOverExposure < 0)
- cam->params.flickerControl.allowableOverExposure =
- -find_over_exposure(cam->params.colourParams.brightness);
- if(cam->params.flickerControl.flickerMode != 0)
- cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
-
-
- /* queue command to update camera */
- cam->cmd_queue |= COMMAND_SETCOLOURPARAMS;
- mutex_unlock(&cam->param_lock);
- DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n",
- vp->depth, vp->palette, vp->brightness, vp->hue, vp->colour,
- vp->contrast);
- break;
- }
-
- /* get/set capture window */
- case VIDIOCGWIN:
- {
- struct video_window *vw = arg;
- DBG("VIDIOCGWIN\n");
-
- *vw = cam->vw;
- break;
- }
-
- case VIDIOCSWIN:
- {
- /* copy_from_user, check validity, copy to internal structure */
- struct video_window *vw = arg;
- DBG("VIDIOCSWIN\n");
-
- if (vw->clipcount != 0) { /* clipping not supported */
- retval = -EINVAL;
- break;
- }
- if (vw->clips != NULL) { /* clipping not supported */
- retval = -EINVAL;
- break;
- }
-
- /* we set the video window to something smaller or equal to what
- * is requested by the user???
- */
- mutex_lock(&cam->param_lock);
- if (vw->width != cam->vw.width || vw->height != cam->vw.height) {
- int video_size = match_videosize(vw->width, vw->height);
-
- if (video_size < 0) {
- retval = -EINVAL;
- mutex_unlock(&cam->param_lock);
- break;
- }
- cam->video_size = video_size;
-
- /* video size is changing, reset the subcapture area */
- memset(&cam->vc, 0, sizeof(cam->vc));
-
- set_vw_size(cam);
- DBG("%d / %d\n", cam->vw.width, cam->vw.height);
- cam->cmd_queue |= COMMAND_SETFORMAT;
- }
-
- mutex_unlock(&cam->param_lock);
-
- /* setformat ignored by camera during streaming,
- * so stop/dispatch/start */
- if (cam->cmd_queue & COMMAND_SETFORMAT) {
- DBG("\n");
- dispatch_commands(cam);
- }
- DBG("%d/%d:%d\n", cam->video_size,
- cam->vw.width, cam->vw.height);
- break;
- }
-
- /* mmap interface */
- case VIDIOCGMBUF:
- {
- struct video_mbuf *vm = arg;
- int i;
-
- DBG("VIDIOCGMBUF\n");
- memset(vm, 0, sizeof(*vm));
- vm->size = CPIA_MAX_FRAME_SIZE*FRAME_NUM;
- vm->frames = FRAME_NUM;
- for (i = 0; i < FRAME_NUM; i++)
- vm->offsets[i] = CPIA_MAX_FRAME_SIZE * i;
- break;
- }
-
- case VIDIOCMCAPTURE:
- {
- struct video_mmap *vm = arg;
- int video_size;
-
- DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm->format, vm->frame,
- vm->width, vm->height);
- if (vm->frame<0||vm->frame>=FRAME_NUM) {
- retval = -EINVAL;
- break;
- }
-
- /* set video format */
- cam->vp.palette = vm->format;
- switch(vm->format) {
- case VIDEO_PALETTE_GREY:
- cam->vp.depth=8;
- break;
- case VIDEO_PALETTE_RGB555:
- case VIDEO_PALETTE_RGB565:
- case VIDEO_PALETTE_YUV422:
- case VIDEO_PALETTE_YUYV:
- case VIDEO_PALETTE_UYVY:
- cam->vp.depth = 16;
- break;
- case VIDEO_PALETTE_RGB24:
- cam->vp.depth = 24;
- break;
- case VIDEO_PALETTE_RGB32:
- cam->vp.depth = 32;
- break;
- default:
- retval = -EINVAL;
- break;
- }
- if (retval)
- break;
-
- /* set video size */
- video_size = match_videosize(vm->width, vm->height);
- if (video_size < 0) {
- retval = -EINVAL;
- break;
- }
- if (video_size != cam->video_size) {
- cam->video_size = video_size;
-
- /* video size is changing, reset the subcapture area */
- memset(&cam->vc, 0, sizeof(cam->vc));
-
- set_vw_size(cam);
- cam->cmd_queue |= COMMAND_SETFORMAT;
- dispatch_commands(cam);
- }
- /* according to v4l-spec we must start streaming here */
- cam->mmap_kludge = 1;
- retval = capture_frame(cam, vm);
-
- break;
- }
-
- case VIDIOCSYNC:
- {
- int *frame = arg;
-
- //DBG("VIDIOCSYNC: %d\n", *frame);
-
- if (*frame<0 || *frame >= FRAME_NUM) {
- retval = -EINVAL;
- break;
- }
-
- switch (cam->frame[*frame].state) {
- case FRAME_UNUSED:
- case FRAME_READY:
- case FRAME_GRABBING:
- DBG("sync to unused frame %d\n", *frame);
- retval = -EINVAL;
- break;
-
- case FRAME_DONE:
- cam->frame[*frame].state = FRAME_UNUSED;
- //DBG("VIDIOCSYNC: %d synced\n", *frame);
- break;
- }
- if (retval == -EINTR) {
- /* FIXME - xawtv does not handle this nice */
- retval = 0;
- }
- break;
- }
-
- case VIDIOCGCAPTURE:
- {
- struct video_capture *vc = arg;
-
- DBG("VIDIOCGCAPTURE\n");
-
- *vc = cam->vc;
-
- break;
- }
-
- case VIDIOCSCAPTURE:
- {
- struct video_capture *vc = arg;
-
- DBG("VIDIOCSCAPTURE\n");
-
- if (vc->decimation != 0) { /* How should this be used? */
- retval = -EINVAL;
- break;
- }
- if (vc->flags != 0) { /* Even/odd grab not supported */
- retval = -EINVAL;
- break;
- }
-
- /* Clip to the resolution we can set for the ROI
- (every 8 columns and 4 rows) */
- vc->x = vc->x & ~(__u32)7;
- vc->y = vc->y & ~(__u32)3;
- vc->width = vc->width & ~(__u32)7;
- vc->height = vc->height & ~(__u32)3;
-
- if(vc->width == 0 || vc->height == 0 ||
- vc->x + vc->width > cam->vw.width ||
- vc->y + vc->height > cam->vw.height) {
- retval = -EINVAL;
- break;
- }
-
- DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height);
-
- mutex_lock(&cam->param_lock);
-
- cam->vc.x = vc->x;
- cam->vc.y = vc->y;
- cam->vc.width = vc->width;
- cam->vc.height = vc->height;
-
- set_vw_size(cam);
- cam->cmd_queue |= COMMAND_SETFORMAT;
-
- mutex_unlock(&cam->param_lock);
-
- /* setformat ignored by camera during streaming,
- * so stop/dispatch/start */
- dispatch_commands(cam);
- break;
- }
-
- case VIDIOCGUNIT:
- {
- struct video_unit *vu = arg;
-
- DBG("VIDIOCGUNIT\n");
-
- vu->video = cam->vdev.minor;
- vu->vbi = VIDEO_NO_UNIT;
- vu->radio = VIDEO_NO_UNIT;
- vu->audio = VIDEO_NO_UNIT;
- vu->teletext = VIDEO_NO_UNIT;
-
- break;
- }
-
-
- /* pointless to implement overlay with this camera */
- case VIDIOCCAPTURE:
- case VIDIOCGFBUF:
- case VIDIOCSFBUF:
- case VIDIOCKEY:
- /* tuner interface - we have none */
- case VIDIOCGTUNER:
- case VIDIOCSTUNER:
- case VIDIOCGFREQ:
- case VIDIOCSFREQ:
- /* audio interface - we have none */
- case VIDIOCGAUDIO:
- case VIDIOCSAUDIO:
- retval = -EINVAL;
- break;
- default:
- retval = -ENOIOCTLCMD;
- break;
- }
-
- mutex_unlock(&cam->busy_lock);
- return retval;
-}
-
-static long cpia_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return video_usercopy(file, cmd, arg, cpia_do_ioctl);
-}
-
-
-/* FIXME */
-static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct video_device *dev = file->private_data;
- unsigned long start = vma->vm_start;
- unsigned long size = vma->vm_end - vma->vm_start;
- unsigned long page, pos;
- struct cam_data *cam = video_get_drvdata(dev);
- int retval;
-
- if (!cam || !cam->ops)
- return -ENODEV;
-
- DBG("cpia_mmap: %ld\n", size);
-
- if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE)
- return -EINVAL;
-
- /* make this _really_ smp-safe */
- if (mutex_lock_interruptible(&cam->busy_lock))
- return -EINTR;
-
- if (!cam->frame_buf) { /* we do lazy allocation */
- if ((retval = allocate_frame_buf(cam))) {
- mutex_unlock(&cam->busy_lock);
- return retval;
- }
- }
-
- pos = (unsigned long)(cam->frame_buf);
- while (size > 0) {
- page = vmalloc_to_pfn((void *)pos);
- if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
- mutex_unlock(&cam->busy_lock);
- return -EAGAIN;
- }
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
- if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
- else
- size = 0;
- }
-
- DBG("cpia_mmap: %ld\n", size);
- mutex_unlock(&cam->busy_lock);
-
- return 0;
-}
-
-static const struct v4l2_file_operations cpia_fops = {
- .owner = THIS_MODULE,
- .open = cpia_open,
- .release = cpia_close,
- .read = cpia_read,
- .mmap = cpia_mmap,
- .ioctl = cpia_ioctl,
-};
-
-static struct video_device cpia_template = {
- .name = "CPiA Camera",
- .fops = &cpia_fops,
- .release = video_device_release_empty,
-};
-
-/* initialise cam_data structure */
-static void reset_camera_struct(struct cam_data *cam)
-{
- /* The following parameter values are the defaults from
- * "Software Developer's Guide for CPiA Cameras". Any changes
- * to the defaults are noted in comments. */
- cam->params.colourParams.brightness = 50;
- cam->params.colourParams.contrast = 48;
- cam->params.colourParams.saturation = 50;
- cam->params.exposure.gainMode = 4;
- cam->params.exposure.expMode = 2; /* AEC */
- cam->params.exposure.compMode = 1;
- cam->params.exposure.centreWeight = 1;
- cam->params.exposure.gain = 0;
- cam->params.exposure.fineExp = 0;
- cam->params.exposure.coarseExpLo = 185;
- cam->params.exposure.coarseExpHi = 0;
- cam->params.exposure.redComp = COMP_RED;
- cam->params.exposure.green1Comp = COMP_GREEN1;
- cam->params.exposure.green2Comp = COMP_GREEN2;
- cam->params.exposure.blueComp = COMP_BLUE;
- cam->params.colourBalance.balanceMode = 2; /* ACB */
- cam->params.colourBalance.redGain = 32;
- cam->params.colourBalance.greenGain = 6;
- cam->params.colourBalance.blueGain = 92;
- cam->params.apcor.gain1 = 0x18;
- cam->params.apcor.gain2 = 0x16;
- cam->params.apcor.gain4 = 0x24;
- cam->params.apcor.gain8 = 0x34;
- cam->params.flickerControl.flickerMode = 0;
- cam->params.flickerControl.disabled = 1;
-
- cam->params.flickerControl.coarseJump =
- flicker_jumps[cam->mainsFreq]
- [cam->params.sensorFps.baserate]
- [cam->params.sensorFps.divisor];
- cam->params.flickerControl.allowableOverExposure =
- -find_over_exposure(cam->params.colourParams.brightness);
- cam->params.vlOffset.gain1 = 20;
- cam->params.vlOffset.gain2 = 24;
- cam->params.vlOffset.gain4 = 26;
- cam->params.vlOffset.gain8 = 26;
- cam->params.compressionParams.hysteresis = 3;
- cam->params.compressionParams.threshMax = 11;
- cam->params.compressionParams.smallStep = 1;
- cam->params.compressionParams.largeStep = 3;
- cam->params.compressionParams.decimationHysteresis = 2;
- cam->params.compressionParams.frDiffStepThresh = 5;
- cam->params.compressionParams.qDiffStepThresh = 3;
- cam->params.compressionParams.decimationThreshMod = 2;
- /* End of default values from Software Developer's Guide */
-
- cam->transfer_rate = 0;
- cam->exposure_status = EXPOSURE_NORMAL;
-
- /* Set Sensor FPS to 15fps. This seems better than 30fps
- * for indoor lighting. */
- cam->params.sensorFps.divisor = 1;
- cam->params.sensorFps.baserate = 1;
-
- cam->params.yuvThreshold.yThreshold = 6; /* From windows driver */
- cam->params.yuvThreshold.uvThreshold = 6; /* From windows driver */
-
- cam->params.format.subSample = SUBSAMPLE_422;
- cam->params.format.yuvOrder = YUVORDER_YUYV;
-
- cam->params.compression.mode = CPIA_COMPRESSION_AUTO;
- cam->params.compressionTarget.frTargeting =
- CPIA_COMPRESSION_TARGET_QUALITY;
- cam->params.compressionTarget.targetFR = 15; /* From windows driver */
- cam->params.compressionTarget.targetQ = 5; /* From windows driver */
-
- cam->params.qx3.qx3_detected = 0;
- cam->params.qx3.toplight = 0;
- cam->params.qx3.bottomlight = 0;
- cam->params.qx3.button = 0;
- cam->params.qx3.cradled = 0;
-
- cam->video_size = VIDEOSIZE_CIF;
-
- cam->vp.colour = 32768; /* 50% */
- cam->vp.hue = 32768; /* 50% */
- cam->vp.brightness = 32768; /* 50% */
- cam->vp.contrast = 32768; /* 50% */
- cam->vp.whiteness = 0; /* not used -> grayscale only */
- cam->vp.depth = 24; /* to be set by user */
- cam->vp.palette = VIDEO_PALETTE_RGB24; /* to be set by user */
-
- cam->vc.x = 0;
- cam->vc.y = 0;
- cam->vc.width = 0;
- cam->vc.height = 0;
-
- cam->vw.x = 0;
- cam->vw.y = 0;
- set_vw_size(cam);
- cam->vw.chromakey = 0;
- cam->vw.flags = 0;
- cam->vw.clipcount = 0;
- cam->vw.clips = NULL;
-
- cam->cmd_queue = COMMAND_NONE;
- cam->first_frame = 1;
-
- return;
-}
-
-/* initialize cam_data structure */
-static void init_camera_struct(struct cam_data *cam,
- struct cpia_camera_ops *ops )
-{
- int i;
-
- /* Default everything to 0 */
- memset(cam, 0, sizeof(struct cam_data));
-
- cam->ops = ops;
- mutex_init(&cam->param_lock);
- mutex_init(&cam->busy_lock);
-
- reset_camera_struct(cam);
-
- cam->proc_entry = NULL;
-
- memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template));
- video_set_drvdata(&cam->vdev, cam);
-
- cam->curframe = 0;
- for (i = 0; i < FRAME_NUM; i++) {
- cam->frame[i].width = 0;
- cam->frame[i].height = 0;
- cam->frame[i].state = FRAME_UNUSED;
- cam->frame[i].data = NULL;
- }
- cam->decompressed_frame.width = 0;
- cam->decompressed_frame.height = 0;
- cam->decompressed_frame.state = FRAME_UNUSED;
- cam->decompressed_frame.data = NULL;
-}
-
-struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel)
-{
- struct cam_data *camera;
-
- if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL)
- return NULL;
-
-
- init_camera_struct( camera, ops );
- camera->lowlevel_data = lowlevel;
-
- /* register v4l device */
- if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
- kfree(camera);
- printk(KERN_DEBUG "video_register_device failed\n");
- return NULL;
- }
-
- /* get version information from camera: open/reset/close */
-
- /* open cpia */
- if (camera->ops->open(camera->lowlevel_data))
- return camera;
-
- /* reset the camera */
- if (reset_camera(camera) != 0) {
- camera->ops->close(camera->lowlevel_data);
- return camera;
- }
-
- /* close cpia */
- camera->ops->close(camera->lowlevel_data);
-
-#ifdef CONFIG_PROC_FS
- create_proc_cpia_cam(camera);
-#endif
-
- printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n",
- camera->params.version.firmwareVersion,
- camera->params.version.firmwareRevision,
- camera->params.version.vcVersion,
- camera->params.version.vcRevision);
- printk(KERN_INFO " CPiA PnP-ID: %04x:%04x:%04x\n",
- camera->params.pnpID.vendor,
- camera->params.pnpID.product,
- camera->params.pnpID.deviceRevision);
- printk(KERN_INFO " VP-Version: %d.%d %04x\n",
- camera->params.vpVersion.vpVersion,
- camera->params.vpVersion.vpRevision,
- camera->params.vpVersion.cameraHeadID);
-
- return camera;
-}
-
-void cpia_unregister_camera(struct cam_data *cam)
-{
- DBG("unregistering video\n");
- video_unregister_device(&cam->vdev);
- if (cam->open_count) {
- put_cam(cam->ops);
- DBG("camera open -- setting ops to NULL\n");
- cam->ops = NULL;
- }
-
-#ifdef CONFIG_PROC_FS
- DBG("destroying /proc/cpia/%s\n", video_device_node_name(&cam->vdev));
- destroy_proc_cpia_cam(cam);
-#endif
- if (!cam->open_count) {
- DBG("freeing camera\n");
- kfree(cam);
- }
-}
-
-static int __init cpia_init(void)
-{
- printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT,
- CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
-
- printk(KERN_WARNING "Since in-kernel colorspace conversion is not "
- "allowed, it is disabled by default now. Users should fix the "
- "applications in case they don't work without conversion "
- "reenabled by setting the 'colorspace_conv' module "
- "parameter to 1\n");
-
-#ifdef CONFIG_PROC_FS
- proc_cpia_create();
-#endif
-
- return 0;
-}
-
-static void __exit cpia_exit(void)
-{
-#ifdef CONFIG_PROC_FS
- proc_cpia_destroy();
-#endif
-}
-
-module_init(cpia_init);
-module_exit(cpia_exit);
-
-/* Exported symbols for modules. */
-
-EXPORT_SYMBOL(cpia_register_camera);
-EXPORT_SYMBOL(cpia_unregister_camera);
diff --git a/drivers/staging/cpia/cpia.h b/drivers/staging/cpia/cpia.h
deleted file mode 100644
index 8f0cfee..0000000
--- a/drivers/staging/cpia/cpia.h
+++ /dev/null
@@ -1,432 +0,0 @@
-#ifndef cpia_h
-#define cpia_h
-
-/*
- * CPiA Parallel Port Video4Linux driver
- *
- * Supports CPiA based parallel port Video Camera's.
- *
- * (C) Copyright 1999 Bas Huisman,
- * Peter Pregler,
- * Scott J. Bertin,
- * VLSI Vision Ltd.
- *
- * 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.
- */
-
-#define CPIA_MAJ_VER 1
-#define CPIA_MIN_VER 2
-#define CPIA_PATCH_VER 3
-
-#define CPIA_PP_MAJ_VER CPIA_MAJ_VER
-#define CPIA_PP_MIN_VER CPIA_MIN_VER
-#define CPIA_PP_PATCH_VER CPIA_PATCH_VER
-
-#define CPIA_USB_MAJ_VER CPIA_MAJ_VER
-#define CPIA_USB_MIN_VER CPIA_MIN_VER
-#define CPIA_USB_PATCH_VER CPIA_PATCH_VER
-
-#define CPIA_MAX_FRAME_SIZE_UNALIGNED (352 * 288 * 4) /* CIF at RGB32 */
-#define CPIA_MAX_FRAME_SIZE ((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */
-
-#ifdef __KERNEL__
-
-#include <asm/uaccess.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-
-struct cpia_camera_ops
-{
- /* open sets privdata to point to structure for this camera.
- * Returns negative value on error, otherwise 0.
- */
- int (*open)(void *privdata);
-
- /* Registers callback function cb to be called with cbdata
- * when an image is ready. If cb is NULL, only single image grabs
- * should be used. cb should immediately call streamRead to read
- * the data or data may be lost. Returns negative value on error,
- * otherwise 0.
- */
- int (*registerCallback)(void *privdata, void (*cb)(void *cbdata),
- void *cbdata);
-
- /* transferCmd sends commands to the camera. command MUST point to
- * an 8 byte buffer in kernel space. data can be NULL if no extra
- * data is needed. The size of the data is given by the last 2
- * bytes of command. data must also point to memory in kernel space.
- * Returns negative value on error, otherwise 0.
- */
- int (*transferCmd)(void *privdata, u8 *command, u8 *data);
-
- /* streamStart initiates stream capture mode.
- * Returns negative value on error, otherwise 0.
- */
- int (*streamStart)(void *privdata);
-
- /* streamStop terminates stream capture mode.
- * Returns negative value on error, otherwise 0.
- */
- int (*streamStop)(void *privdata);
-
- /* streamRead reads a frame from the camera. buffer points to a
- * buffer large enough to hold a complete frame in kernel space.
- * noblock indicates if this should be a non blocking read.
- * Returns the number of bytes read, or negative value on error.
- */
- int (*streamRead)(void *privdata, u8 *buffer, int noblock);
-
- /* close disables the device until open() is called again.
- * Returns negative value on error, otherwise 0.
- */
- int (*close)(void *privdata);
-
- /* If wait_for_stream_ready is non-zero, wait until the streamState
- * is STREAM_READY before calling streamRead.
- */
- int wait_for_stream_ready;
-
- /*
- * Used to maintain lowlevel module usage counts
- */
- struct module *owner;
-};
-
-struct cpia_frame {
- u8 *data;
- int count;
- int width;
- int height;
- volatile int state;
-};
-
-struct cam_params {
- struct {
- u8 firmwareVersion;
- u8 firmwareRevision;
- u8 vcVersion;
- u8 vcRevision;
- } version;
- struct {
- u16 vendor;
- u16 product;
- u16 deviceRevision;
- } pnpID;
- struct {
- u8 vpVersion;
- u8 vpRevision;
- u16 cameraHeadID;
- } vpVersion;
- struct {
- u8 systemState;
- u8 grabState;
- u8 streamState;
- u8 fatalError;
- u8 cmdError;
- u8 debugFlags;
- u8 vpStatus;
- u8 errorCode;
- } status;
- struct {
- u8 brightness;
- u8 contrast;
- u8 saturation;
- } colourParams;
- struct {
- u8 gainMode;
- u8 expMode;
- u8 compMode;
- u8 centreWeight;
- u8 gain;
- u8 fineExp;
- u8 coarseExpLo;
- u8 coarseExpHi;
- u8 redComp;
- u8 green1Comp;
- u8 green2Comp;
- u8 blueComp;
- } exposure;
- struct {
- u8 balanceMode;
- u8 redGain;
- u8 greenGain;
- u8 blueGain;
- } colourBalance;
- struct {
- u8 divisor;
- u8 baserate;
- } sensorFps;
- struct {
- u8 gain1;
- u8 gain2;
- u8 gain4;
- u8 gain8;
- } apcor;
- struct {
- u8 disabled;
- u8 flickerMode;
- u8 coarseJump;
- int allowableOverExposure;
- } flickerControl;
- struct {
- u8 gain1;
- u8 gain2;
- u8 gain4;
- u8 gain8;
- } vlOffset;
- struct {
- u8 mode;
- u8 decimation;
- } compression;
- struct {
- u8 frTargeting;
- u8 targetFR;
- u8 targetQ;
- } compressionTarget;
- struct {
- u8 yThreshold;
- u8 uvThreshold;
- } yuvThreshold;
- struct {
- u8 hysteresis;
- u8 threshMax;
- u8 smallStep;
- u8 largeStep;
- u8 decimationHysteresis;
- u8 frDiffStepThresh;
- u8 qDiffStepThresh;
- u8 decimationThreshMod;
- } compressionParams;
- struct {
- u8 videoSize; /* CIF/QCIF */
- u8 subSample;
- u8 yuvOrder;
- } format;
- struct { /* Intel QX3 specific data */
- u8 qx3_detected; /* a QX3 is present */
- u8 toplight; /* top light lit , R/W */
- u8 bottomlight; /* bottom light lit, R/W */
- u8 button; /* snapshot button pressed (R/O) */
- u8 cradled; /* microscope is in cradle (R/O) */
- } qx3;
- struct {
- u8 colStart; /* skip first 8*colStart pixels */
- u8 colEnd; /* finish at 8*colEnd pixels */
- u8 rowStart; /* skip first 4*rowStart lines */
- u8 rowEnd; /* finish at 4*rowEnd lines */
- } roi;
- u8 ecpTiming;
- u8 streamStartLine;
-};
-
-enum v4l_camstates {
- CPIA_V4L_IDLE = 0,
- CPIA_V4L_ERROR,
- CPIA_V4L_COMMAND,
- CPIA_V4L_GRABBING,
- CPIA_V4L_STREAMING,
- CPIA_V4L_STREAMING_PAUSED,
-};
-
-#define FRAME_NUM 2 /* double buffering for now */
-
-struct cam_data {
- struct list_head cam_data_list;
-
- struct mutex busy_lock; /* guard against SMP multithreading */
- struct cpia_camera_ops *ops; /* lowlevel driver operations */
- void *lowlevel_data; /* private data for lowlevel driver */
- u8 *raw_image; /* buffer for raw image data */
- struct cpia_frame decompressed_frame;
- /* buffer to hold decompressed frame */
- int image_size; /* sizeof last decompressed image */
- int open_count; /* # of process that have camera open */
-
- /* camera status */
- int fps; /* actual fps reported by the camera */
- int transfer_rate; /* transfer rate from camera in kB/s */
- u8 mainsFreq; /* for flicker control */
-
- /* proc interface */
- struct mutex param_lock; /* params lock for this camera */
- struct cam_params params; /* camera settings */
- struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */
-
- /* v4l */
- int video_size; /* VIDEO_SIZE_ */
- volatile enum v4l_camstates camstate; /* v4l layer status */
- struct video_device vdev; /* v4l videodev */
- struct video_picture vp; /* v4l camera settings */
- struct video_window vw; /* v4l capture area */
- struct video_capture vc; /* v4l subcapture area */
-
- /* mmap interface */
- int curframe; /* the current frame to grab into */
- u8 *frame_buf; /* frame buffer data */
- struct cpia_frame frame[FRAME_NUM];
- /* FRAME_NUM-buffering, so we need a array */
-
- int first_frame;
- int mmap_kludge; /* 'wrong' byte order for mmap */
- volatile u32 cmd_queue; /* queued commands */
- int exposure_status; /* EXPOSURE_* */
- int exposure_count; /* number of frames at this status */
-};
-
-/* cpia_register_camera is called by low level driver for each camera.
- * A unique camera number is returned, or a negative value on error */
-struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel);
-
-/* cpia_unregister_camera is called by low level driver when a camera
- * is removed. This must not fail. */
-void cpia_unregister_camera(struct cam_data *cam);
-
-/* raw CIF + 64 byte header + (2 bytes line_length + EOL) per line + 4*EOI +
- * one byte 16bit DMA alignment
- */
-#define CPIA_MAX_IMAGE_SIZE ((352*288*2)+64+(288*3)+5)
-
-/* constant value's */
-#define MAGIC_0 0x19
-#define MAGIC_1 0x68
-#define DATA_IN 0xC0
-#define DATA_OUT 0x40
-#define VIDEOSIZE_QCIF 0 /* 176x144 */
-#define VIDEOSIZE_CIF 1 /* 352x288 */
-#define VIDEOSIZE_SIF 2 /* 320x240 */
-#define VIDEOSIZE_QSIF 3 /* 160x120 */
-#define VIDEOSIZE_48_48 4 /* where no one has gone before, iconsize! */
-#define VIDEOSIZE_64_48 5
-#define VIDEOSIZE_128_96 6
-#define VIDEOSIZE_160_120 VIDEOSIZE_QSIF
-#define VIDEOSIZE_176_144 VIDEOSIZE_QCIF
-#define VIDEOSIZE_192_144 7
-#define VIDEOSIZE_224_168 8
-#define VIDEOSIZE_256_192 9
-#define VIDEOSIZE_288_216 10
-#define VIDEOSIZE_320_240 VIDEOSIZE_SIF
-#define VIDEOSIZE_352_288 VIDEOSIZE_CIF
-#define VIDEOSIZE_88_72 11 /* quarter CIF */
-#define SUBSAMPLE_420 0
-#define SUBSAMPLE_422 1
-#define YUVORDER_YUYV 0
-#define YUVORDER_UYVY 1
-#define NOT_COMPRESSED 0
-#define COMPRESSED 1
-#define NO_DECIMATION 0
-#define DECIMATION_ENAB 1
-#define EOI 0xff /* End Of Image */
-#define EOL 0xfd /* End Of Line */
-#define FRAME_HEADER_SIZE 64
-
-/* Image grab modes */
-#define CPIA_GRAB_SINGLE 0
-#define CPIA_GRAB_CONTINUOUS 1
-
-/* Compression parameters */
-#define CPIA_COMPRESSION_NONE 0
-#define CPIA_COMPRESSION_AUTO 1
-#define CPIA_COMPRESSION_MANUAL 2
-#define CPIA_COMPRESSION_TARGET_QUALITY 0
-#define CPIA_COMPRESSION_TARGET_FRAMERATE 1
-
-/* Return offsets for GetCameraState */
-#define SYSTEMSTATE 0
-#define GRABSTATE 1
-#define STREAMSTATE 2
-#define FATALERROR 3
-#define CMDERROR 4
-#define DEBUGFLAGS 5
-#define VPSTATUS 6
-#define ERRORCODE 7
-
-/* SystemState */
-#define UNINITIALISED_STATE 0
-#define PASS_THROUGH_STATE 1
-#define LO_POWER_STATE 2
-#define HI_POWER_STATE 3
-#define WARM_BOOT_STATE 4
-
-/* GrabState */
-#define GRAB_IDLE 0
-#define GRAB_ACTIVE 1
-#define GRAB_DONE 2
-
-/* StreamState */
-#define STREAM_NOT_READY 0
-#define STREAM_READY 1
-#define STREAM_OPEN 2
-#define STREAM_PAUSED 3
-#define STREAM_FINISHED 4
-
-/* Fatal Error, CmdError, and DebugFlags */
-#define CPIA_FLAG 1
-#define SYSTEM_FLAG 2
-#define INT_CTRL_FLAG 4
-#define PROCESS_FLAG 8
-#define COM_FLAG 16
-#define VP_CTRL_FLAG 32
-#define CAPTURE_FLAG 64
-#define DEBUG_FLAG 128
-
-/* VPStatus */
-#define VP_STATE_OK 0x00
-
-#define VP_STATE_FAILED_VIDEOINIT 0x01
-#define VP_STATE_FAILED_AECACBINIT 0x02
-#define VP_STATE_AEC_MAX 0x04
-#define VP_STATE_ACB_BMAX 0x08
-
-#define VP_STATE_ACB_RMIN 0x10
-#define VP_STATE_ACB_GMIN 0x20
-#define VP_STATE_ACB_RMAX 0x40
-#define VP_STATE_ACB_GMAX 0x80
-
-/* default (minimum) compensation values */
-#define COMP_RED 220
-#define COMP_GREEN1 214
-#define COMP_GREEN2 COMP_GREEN1
-#define COMP_BLUE 230
-
-/* exposure status */
-#define EXPOSURE_VERY_LIGHT 0
-#define EXPOSURE_LIGHT 1
-#define EXPOSURE_NORMAL 2
-#define EXPOSURE_DARK 3
-#define EXPOSURE_VERY_DARK 4
-
-/* ErrorCode */
-#define ERROR_FLICKER_BELOW_MIN_EXP 0x01 /*flicker exposure got below minimum exposure */
-#define ALOG(fmt,args...) printk(fmt, ##args)
-#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args)
-
-#ifdef _CPIA_DEBUG_
-#define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
-#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
-#else
-#define DBG(fmn,args...) do {} while(0)
-#endif
-
-#define DEB_BYTE(p)\
- DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\
- (p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\
- (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0);
-
-#endif /* __KERNEL__ */
-
-#endif /* cpia_h */
diff --git a/drivers/staging/cpia/cpia_pp.c b/drivers/staging/cpia/cpia_pp.c
deleted file mode 100644
index f5604c1..0000000
--- a/drivers/staging/cpia/cpia_pp.c
+++ /dev/null
@@ -1,869 +0,0 @@
-/*
- * cpia_pp CPiA Parallel Port driver
- *
- * Supports CPiA based parallel port Video Camera's.
- *
- * (C) Copyright 1999 Bas Huisman <bhuism@cs.utwente.nl>
- * (C) Copyright 1999-2000 Scott J. Bertin <sbertin@securenym.net>,
- * (C) Copyright 1999-2000 Peter Pregler <Peter_Pregler@email.com>
- *
- * 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.
- */
-
-/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
-/* #define _CPIA_DEBUG_ 1 */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <linux/kernel.h>
-#include <linux/parport.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <linux/kmod.h>
-
-/* #define _CPIA_DEBUG_ define for verbose debug output */
-#include "cpia.h"
-
-static int cpia_pp_open(void *privdata);
-static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata),
- void *cbdata);
-static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data);
-static int cpia_pp_streamStart(void *privdata);
-static int cpia_pp_streamStop(void *privdata);
-static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock);
-static int cpia_pp_close(void *privdata);
-
-
-#define ABOUT "Parallel port driver for Vision CPiA based cameras"
-
-#define PACKET_LENGTH 8
-
-/* Magic numbers for defining port-device mappings */
-#define PPCPIA_PARPORT_UNSPEC -4
-#define PPCPIA_PARPORT_AUTO -3
-#define PPCPIA_PARPORT_OFF -2
-#define PPCPIA_PARPORT_NONE -1
-
-static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC};
-static char *parport[PARPORT_MAX] = {NULL,};
-
-MODULE_AUTHOR("B. Huisman <bhuism@cs.utwente.nl> & Peter Pregler <Peter_Pregler@email.com>");
-MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras");
-MODULE_LICENSE("GPL");
-
-module_param_array(parport, charp, NULL, 0);
-MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp.");
-
-struct pp_cam_entry {
- struct pardevice *pdev;
- struct parport *port;
- struct work_struct cb_task;
- void (*cb_func)(void *cbdata);
- void *cb_data;
- int open_count;
- wait_queue_head_t wq_stream;
- /* image state flags */
- int image_ready; /* we got an interrupt */
- int image_complete; /* we have seen 4 EOI */
-
- int streaming; /* we are in streaming mode */
- int stream_irq;
-};
-
-static struct cpia_camera_ops cpia_pp_ops =
-{
- cpia_pp_open,
- cpia_pp_registerCallback,
- cpia_pp_transferCmd,
- cpia_pp_streamStart,
- cpia_pp_streamStop,
- cpia_pp_streamRead,
- cpia_pp_close,
- 1,
- THIS_MODULE
-};
-
-static LIST_HEAD(cam_list);
-static spinlock_t cam_list_lock_pp;
-
-/* FIXME */
-static void cpia_parport_enable_irq( struct parport *port ) {
- parport_enable_irq(port);
- mdelay(10);
- return;
-}
-
-static void cpia_parport_disable_irq( struct parport *port ) {
- parport_disable_irq(port);
- mdelay(10);
- return;
-}
-
-/* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility
- * Link Flag during negotiation */
-#define UPLOAD_FLAG 0x08
-#define NIBBLE_TRANSFER 0x01
-#define ECP_TRANSFER 0x03
-
-#define PARPORT_CHUNK_SIZE PAGE_SIZE
-
-
-static void cpia_pp_run_callback(struct work_struct *work)
-{
- void (*cb_func)(void *cbdata);
- void *cb_data;
- struct pp_cam_entry *cam;
-
- cam = container_of(work, struct pp_cam_entry, cb_task);
- cb_func = cam->cb_func;
- cb_data = cam->cb_data;
-
- cb_func(cb_data);
-}
-
-/****************************************************************************
- *
- * CPiA-specific low-level parport functions for nibble uploads
- *
- ***************************************************************************/
-/* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */
-/* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */
-
-static size_t cpia_read_nibble (struct parport *port,
- void *buffer, size_t len,
- int flags)
-{
- /* adapted verbatim, with one change, from
- parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */
-
- unsigned char *buf = buffer;
- int i;
- unsigned char byte = 0;
-
- len *= 2; /* in nibbles */
- for (i=0; i < len; i++) {
- unsigned char nibble;
-
- /* The CPiA firmware suppresses the use of nDataAvail (nFault LO)
- * after every second nibble to signal that more
- * data is available. (the total number of Bytes that
- * should be sent is known; if too few are received, an error
- * will be recorded after a timeout).
- * This is incompatible with parport_ieee1284_read_nibble(),
- * which expects to find nFault LO after every second nibble.
- */
-
- /* Solution: modify cpia_read_nibble to only check for
- * nDataAvail before the first nibble is sent.
- */
-
- /* Does the error line indicate end of data? */
- if (((i /*& 1*/) == 0) &&
- (parport_read_status(port) & PARPORT_STATUS_ERROR)) {
- DBG("%s: No more nibble data (%d bytes)\n",
- port->name, i/2);
- goto end_of_data;
- }
-
- /* Event 7: Set nAutoFd low. */
- parport_frob_control (port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
-
- /* Event 9: nAck goes low. */
- port->ieee1284.phase = IEEE1284_PH_REV_DATA;
- if (parport_wait_peripheral (port,
- PARPORT_STATUS_ACK, 0)) {
- /* Timeout -- no more data? */
- DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
- port->name, i/2);
- parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
- break;
- }
-
-
- /* Read a nibble. */
- nibble = parport_read_status (port) >> 3;
- nibble &= ~8;
- if ((nibble & 0x10) == 0)
- nibble |= 8;
- nibble &= 0xf;
-
- /* Event 10: Set nAutoFd high. */
- parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-
- /* Event 11: nAck goes high. */
- if (parport_wait_peripheral (port,
- PARPORT_STATUS_ACK,
- PARPORT_STATUS_ACK)) {
- /* Timeout -- no more data? */
- DBG("%s: Nibble timeout at event 11\n",
- port->name);
- break;
- }
-
- if (i & 1) {
- /* Second nibble */
- byte |= nibble << 4;
- *buf++ = byte;
- } else
- byte = nibble;
- }
-
- if (i == len) {
- /* Read the last nibble without checking data avail. */
- if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
- end_of_data:
- /* Go to reverse idle phase. */
- parport_frob_control (port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
- port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
- }
- else
- port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
- }
-
- return i/2;
-}
-
-/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
- * (See CPiA Data sheet p. 31)
- *
- * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a
- * nonstandard variant of nibble mode which allows the same (mediocre)
- * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable
- * parallel ports, but works also for non-TRISTATE-capable ports.
- * (Standard nibble mode only send 4 bits per cycle)
- *
- */
-
-static size_t cpia_read_nibble_stream(struct parport *port,
- void *buffer, size_t len,
- int flags)
-{
- int i;
- unsigned char *buf = buffer;
- int endseen = 0;
-
- for (i=0; i < len; i++) {
- unsigned char nibble[2], byte = 0;
- int j;
-
- /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */
- if (endseen > 3 )
- break;
-
- /* Event 7: Set nAutoFd low. */
- parport_frob_control (port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
-
- /* Event 9: nAck goes low. */
- port->ieee1284.phase = IEEE1284_PH_REV_DATA;
- if (parport_wait_peripheral (port,
- PARPORT_STATUS_ACK, 0)) {
- /* Timeout -- no more data? */
- DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
- port->name, i/2);
- parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
- break;
- }
-
- /* Read lower nibble */
- nibble[0] = parport_read_status (port) >>3;
-
- /* Event 10: Set nAutoFd high. */
- parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-
- /* Event 11: nAck goes high. */
- if (parport_wait_peripheral (port,
- PARPORT_STATUS_ACK,
- PARPORT_STATUS_ACK)) {
- /* Timeout -- no more data? */
- DBG("%s: Nibble timeout at event 11\n",
- port->name);
- break;
- }
-
- /* Read upper nibble */
- nibble[1] = parport_read_status (port) >>3;
-
- /* reassemble the byte */
- for (j = 0; j < 2 ; j++ ) {
- nibble[j] &= ~8;
- if ((nibble[j] & 0x10) == 0)
- nibble[j] |= 8;
- nibble[j] &= 0xf;
- }
- byte = (nibble[0] |(nibble[1] << 4));
- *buf++ = byte;
-
- if(byte == EOI)
- endseen++;
- else
- endseen = 0;
- }
- return i;
-}
-
-/****************************************************************************
- *
- * EndTransferMode
- *
- ***************************************************************************/
-static void EndTransferMode(struct pp_cam_entry *cam)
-{
- parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
-}
-
-/****************************************************************************
- *
- * ForwardSetup
- *
- ***************************************************************************/
-static int ForwardSetup(struct pp_cam_entry *cam)
-{
- int retry;
-
- /* The CPiA uses ECP protocol for Downloads from the Host to the camera.
- * This will be software-emulated if ECP hardware is not present
- */
-
- /* the usual camera maximum response time is 10ms, but after receiving
- * some commands, it needs up to 40ms. (Data Sheet p. 32)*/
-
- for(retry = 0; retry < 4; ++retry) {
- if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) {
- break;
- }
- mdelay(10);
- }
- if(retry == 4) {
- DBG("Unable to negotiate IEEE1284 ECP Download mode\n");
- return -1;
- }
- return 0;
-}
-/****************************************************************************
- *
- * ReverseSetup
- *
- ***************************************************************************/
-static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
-{
- int retry;
- int upload_mode, mode = IEEE1284_MODE_ECP;
- int transfer_mode = ECP_TRANSFER;
-
- if (!(cam->port->modes & PARPORT_MODE_ECP) &&
- !(cam->port->modes & PARPORT_MODE_TRISTATE)) {
- mode = IEEE1284_MODE_NIBBLE;
- transfer_mode = NIBBLE_TRANSFER;
- }
-
- upload_mode = mode;
- if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK;
-
- /* the usual camera maximum response time is 10ms, but after
- * receiving some commands, it needs up to 40ms. */
-
- for(retry = 0; retry < 4; ++retry) {
- if(!parport_negotiate(cam->port, mode)) {
- break;
- }
- mdelay(10);
- }
- if(retry == 4) {
- if(extensibility)
- DBG("Unable to negotiate upload extensibility mode\n");
- else
- DBG("Unable to negotiate upload mode\n");
- return -1;
- }
- if(extensibility) cam->port->ieee1284.mode = upload_mode;
- return 0;
-}
-
-/****************************************************************************
- *
- * WritePacket
- *
- ***************************************************************************/
-static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size)
-{
- int retval=0;
- int size_written;
-
- if (packet == NULL) {
- return -EINVAL;
- }
- if (ForwardSetup(cam)) {
- DBG("Write failed in setup\n");
- return -EIO;
- }
- size_written = parport_write(cam->port, packet, size);
- if(size_written != size) {
- DBG("Write failed, wrote %d/%d\n", size_written, size);
- retval = -EIO;
- }
- EndTransferMode(cam);
- return retval;
-}
-
-/****************************************************************************
- *
- * ReadPacket
- *
- ***************************************************************************/
-static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
-{
- int retval=0;
-
- if (packet == NULL) {
- return -EINVAL;
- }
- if (ReverseSetup(cam, 0)) {
- return -EIO;
- }
-
- /* support for CPiA variant nibble reads */
- if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) {
- if(cpia_read_nibble(cam->port, packet, size, 0) != size)
- retval = -EIO;
- } else {
- if(parport_read(cam->port, packet, size) != size)
- retval = -EIO;
- }
- EndTransferMode(cam);
- return retval;
-}
-
-/****************************************************************************
- *
- * cpia_pp_streamStart
- *
- ***************************************************************************/
-static int cpia_pp_streamStart(void *privdata)
-{
- struct pp_cam_entry *cam = privdata;
- DBG("\n");
- cam->streaming=1;
- cam->image_ready=0;
- //if (ReverseSetup(cam,1)) return -EIO;
- if(cam->stream_irq) cpia_parport_enable_irq(cam->port);
- return 0;
-}
-
-/****************************************************************************
- *
- * cpia_pp_streamStop
- *
- ***************************************************************************/
-static int cpia_pp_streamStop(void *privdata)
-{
- struct pp_cam_entry *cam = privdata;
-
- DBG("\n");
- cam->streaming=0;
- cpia_parport_disable_irq(cam->port);
- //EndTransferMode(cam);
-
- return 0;
-}
-
-/****************************************************************************
- *
- * cpia_pp_streamRead
- *
- ***************************************************************************/
-static int cpia_pp_read(struct parport *port, u8 *buffer, int len)
-{
- int bytes_read;
-
- /* support for CPiA variant "nibble stream" reads */
- if(port->ieee1284.mode == IEEE1284_MODE_NIBBLE)
- bytes_read = cpia_read_nibble_stream(port,buffer,len,0);
- else {
- int new_bytes;
- for(bytes_read=0; bytes_read<len; bytes_read += new_bytes) {
- new_bytes = parport_read(port, buffer+bytes_read,
- len-bytes_read);
- if(new_bytes < 0) break;
- }
- }
- return bytes_read;
-}
-
-static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
-{
- struct pp_cam_entry *cam = privdata;
- int read_bytes = 0;
- int i, endseen, block_size, new_bytes;
-
- if(cam == NULL) {
- DBG("Internal driver error: cam is NULL\n");
- return -EINVAL;
- }
- if(buffer == NULL) {
- DBG("Internal driver error: buffer is NULL\n");
- return -EINVAL;
- }
- //if(cam->streaming) DBG("%d / %d\n", cam->image_ready, noblock);
- if( cam->stream_irq ) {
- DBG("%d\n", cam->image_ready);
- cam->image_ready--;
- }
- cam->image_complete=0;
- if (0/*cam->streaming*/) {
- if(!cam->image_ready) {
- if(noblock) return -EWOULDBLOCK;
- interruptible_sleep_on(&cam->wq_stream);
- if( signal_pending(current) ) return -EINTR;
- DBG("%d\n", cam->image_ready);
- }
- } else {
- if (ReverseSetup(cam, 1)) {
- DBG("unable to ReverseSetup\n");
- return -EIO;
- }
- }
- endseen = 0;
- block_size = PARPORT_CHUNK_SIZE;
- while( !cam->image_complete ) {
- cond_resched();
-
- new_bytes = cpia_pp_read(cam->port, buffer, block_size );
- if( new_bytes <= 0 ) {
- break;
- }
- i=-1;
- while(++i<new_bytes && endseen<4) {
- if(*buffer==EOI) {
- endseen++;
- } else {
- endseen=0;
- }
- buffer++;
- }
- read_bytes += i;
- if( endseen==4 ) {
- cam->image_complete=1;
- break;
- }
- if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) {
- block_size=CPIA_MAX_IMAGE_SIZE-read_bytes;
- }
- }
- EndTransferMode(cam);
- return cam->image_complete ? read_bytes : -EIO;
-}
-/****************************************************************************
- *
- * cpia_pp_transferCmd
- *
- ***************************************************************************/
-static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
-{
- int err;
- int retval=0;
- int databytes;
- struct pp_cam_entry *cam = privdata;
-
- if(cam == NULL) {
- DBG("Internal driver error: cam is NULL\n");
- return -EINVAL;
- }
- if(command == NULL) {
- DBG("Internal driver error: command is NULL\n");
- return -EINVAL;
- }
- databytes = (((int)command[7])<<8) | command[6];
- if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) {
- DBG("Error writing command\n");
- return err;
- }
- if(command[0] == DATA_IN) {
- u8 buffer[8];
- if(data == NULL) {
- DBG("Internal driver error: data is NULL\n");
- return -EINVAL;
- }
- if((err = ReadPacket(cam, buffer, 8)) < 0) {
- DBG("Error reading command result\n");
- return err;
- }
- memcpy(data, buffer, databytes);
- } else if(command[0] == DATA_OUT) {
- if(databytes > 0) {
- if(data == NULL) {
- DBG("Internal driver error: data is NULL\n");
- retval = -EINVAL;
- } else {
- if((err=WritePacket(cam, data, databytes)) < 0){
- DBG("Error writing command data\n");
- return err;
- }
- }
- }
- } else {
- DBG("Unexpected first byte of command: %x\n", command[0]);
- retval = -EINVAL;
- }
- return retval;
-}
-
-/****************************************************************************
- *
- * cpia_pp_open
- *
- ***************************************************************************/
-static int cpia_pp_open(void *privdata)
-{
- struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata;
-
- if (cam == NULL)
- return -EINVAL;
-
- if(cam->open_count == 0) {
- if (parport_claim(cam->pdev)) {
- DBG("failed to claim the port\n");
- return -EBUSY;
- }
- parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
- parport_data_forward(cam->port);
- parport_write_control(cam->port, PARPORT_CONTROL_SELECT);
- udelay(50);
- parport_write_control(cam->port,
- PARPORT_CONTROL_SELECT
- | PARPORT_CONTROL_INIT);
- }
-
- ++cam->open_count;
-
- return 0;
-}
-
-/****************************************************************************
- *
- * cpia_pp_registerCallback
- *
- ***************************************************************************/
-static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata)
-{
- struct pp_cam_entry *cam = privdata;
- int retval = 0;
-
- if(cam->port->irq != PARPORT_IRQ_NONE) {
- cam->cb_func = cb;
- cam->cb_data = cbdata;
- INIT_WORK(&cam->cb_task, cpia_pp_run_callback);
- } else {
- retval = -1;
- }
- return retval;
-}
-
-/****************************************************************************
- *
- * cpia_pp_close
- *
- ***************************************************************************/
-static int cpia_pp_close(void *privdata)
-{
- struct pp_cam_entry *cam = privdata;
- if (--cam->open_count == 0) {
- parport_release(cam->pdev);
- }
- return 0;
-}
-
-/****************************************************************************
- *
- * cpia_pp_register
- *
- ***************************************************************************/
-static int cpia_pp_register(struct parport *port)
-{
- struct pardevice *pdev = NULL;
- struct pp_cam_entry *cam;
- struct cam_data *cpia;
-
- if (!(port->modes & PARPORT_MODE_PCSPP)) {
- LOG("port is not supported by CPiA driver\n");
- return -ENXIO;
- }
-
- cam = kzalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
- if (cam == NULL) {
- LOG("failed to allocate camera structure\n");
- return -ENOMEM;
- }
-
- pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
- NULL, 0, cam);
-
- if (!pdev) {
- LOG("failed to parport_register_device\n");
- kfree(cam);
- return -ENXIO;
- }
-
- cam->pdev = pdev;
- cam->port = port;
- init_waitqueue_head(&cam->wq_stream);
-
- cam->streaming = 0;
- cam->stream_irq = 0;
-
- if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) {
- LOG("failed to cpia_register_camera\n");
- parport_unregister_device(pdev);
- kfree(cam);
- return -ENXIO;
- }
- spin_lock( &cam_list_lock_pp );
- list_add( &cpia->cam_data_list, &cam_list );
- spin_unlock( &cam_list_lock_pp );
-
- return 0;
-}
-
-static void cpia_pp_detach (struct parport *port)
-{
- struct list_head *tmp;
- struct cam_data *cpia = NULL;
- struct pp_cam_entry *cam;
-
- spin_lock( &cam_list_lock_pp );
- list_for_each (tmp, &cam_list) {
- cpia = list_entry(tmp, struct cam_data, cam_data_list);
- cam = (struct pp_cam_entry *) cpia->lowlevel_data;
- if (cam && cam->port->number == port->number) {
- list_del(&cpia->cam_data_list);
- break;
- }
- cpia = NULL;
- }
- spin_unlock( &cam_list_lock_pp );
-
- if (!cpia) {
- DBG("cpia_pp_detach failed to find cam_data in cam_list\n");
- return;
- }
-
- cam = (struct pp_cam_entry *) cpia->lowlevel_data;
- cpia_unregister_camera(cpia);
- if(cam->open_count > 0)
- cpia_pp_close(cam);
- parport_unregister_device(cam->pdev);
- cpia->lowlevel_data = NULL;
- kfree(cam);
-}
-
-static void cpia_pp_attach (struct parport *port)
-{
- unsigned int i;
-
- switch (parport_nr[0])
- {
- case PPCPIA_PARPORT_UNSPEC:
- case PPCPIA_PARPORT_AUTO:
- if (port->probe_info[0].class != PARPORT_CLASS_MEDIA ||
- port->probe_info[0].cmdset == NULL ||
- strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0)
- return;
-
- cpia_pp_register(port);
-
- break;
-
- default:
- for (i = 0; i < PARPORT_MAX; ++i) {
- if (port->number == parport_nr[i]) {
- cpia_pp_register(port);
- break;
- }
- }
- break;
- }
-}
-
-static struct parport_driver cpia_pp_driver = {
- .name = "cpia_pp",
- .attach = cpia_pp_attach,
- .detach = cpia_pp_detach,
-};
-
-static int __init cpia_pp_init(void)
-{
- printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
- CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
-
- if(parport_nr[0] == PPCPIA_PARPORT_OFF) {
- printk(" disabled\n");
- return 0;
- }
-
- spin_lock_init( &cam_list_lock_pp );
-
- if (parport_register_driver (&cpia_pp_driver)) {
- LOG ("unable to register with parport\n");
- return -EIO;
- }
- return 0;
-}
-
-static int __init cpia_init(void)
-{
- if (parport[0]) {
- /* The user gave some parameters. Let's see what they were. */
- if (!strncmp(parport[0], "auto", 4)) {
- parport_nr[0] = PPCPIA_PARPORT_AUTO;
- } else {
- int n;
- for (n = 0; n < PARPORT_MAX && parport[n]; n++) {
- if (!strncmp(parport[n], "none", 4)) {
- parport_nr[n] = PPCPIA_PARPORT_NONE;
- } else {
- char *ep;
- unsigned long r = simple_strtoul(parport[n], &ep, 0);
- if (ep != parport[n]) {
- parport_nr[n] = r;
- } else {
- LOG("bad port specifier `%s'\n", parport[n]);
- return -ENODEV;
- }
- }
- }
- }
- }
- return cpia_pp_init();
-}
-
-static void __exit cpia_cleanup(void)
-{
- parport_unregister_driver(&cpia_pp_driver);
- return;
-}
-
-module_init(cpia_init);
-module_exit(cpia_cleanup);
diff --git a/drivers/staging/cpia/cpia_usb.c b/drivers/staging/cpia/cpia_usb.c
deleted file mode 100644
index 58d193f..0000000
--- a/drivers/staging/cpia/cpia_usb.c
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * cpia_usb CPiA USB driver
- *
- * Supports CPiA based parallel port Video Camera's.
- *
- * Copyright (C) 1999 Jochen Scharrlach <Jochen.Scharrlach@schwaben.de>
- * Copyright (C) 1999, 2000 Johannes Erdfelt <johannes@erdfelt.com>
- *
- * 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.
- */
-
-/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
-/* #define _CPIA_DEBUG_ 1 */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/usb.h>
-
-#include "cpia.h"
-
-#define USB_REQ_CPIA_GRAB_FRAME 0xC1
-#define USB_REQ_CPIA_UPLOAD_FRAME 0xC2
-#define WAIT_FOR_NEXT_FRAME 0
-#define FORCE_FRAME_UPLOAD 1
-
-#define FRAMES_PER_DESC 10
-#define FRAME_SIZE_PER_DESC 960 /* Shouldn't be hardcoded */
-#define CPIA_NUMSBUF 2
-#define STREAM_BUF_SIZE (PAGE_SIZE * 4)
-#define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2)
-
-struct cpia_sbuf {
- char *data;
- struct urb *urb;
-};
-
-#define FRAMEBUF_LEN (CPIA_MAX_FRAME_SIZE+100)
-enum framebuf_status {
- FRAME_EMPTY,
- FRAME_READING,
- FRAME_READY,
- FRAME_ERROR,
-};
-
-struct framebuf {
- int length;
- enum framebuf_status status;
- u8 data[FRAMEBUF_LEN];
- struct framebuf *next;
-};
-
-struct usb_cpia {
- /* Device structure */
- struct usb_device *dev;
-
- unsigned char iface;
- wait_queue_head_t wq_stream;
-
- int cursbuf; /* Current receiving sbuf */
- struct cpia_sbuf sbuf[CPIA_NUMSBUF]; /* Double buffering */
-
- int streaming;
- int open;
- int present;
- struct framebuf *buffers[3];
- struct framebuf *curbuff, *workbuff;
-};
-
-static int cpia_usb_open(void *privdata);
-static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
- void *cbdata);
-static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data);
-static int cpia_usb_streamStart(void *privdata);
-static int cpia_usb_streamStop(void *privdata);
-static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock);
-static int cpia_usb_close(void *privdata);
-
-#define ABOUT "USB driver for Vision CPiA based cameras"
-
-static struct cpia_camera_ops cpia_usb_ops = {
- cpia_usb_open,
- cpia_usb_registerCallback,
- cpia_usb_transferCmd,
- cpia_usb_streamStart,
- cpia_usb_streamStop,
- cpia_usb_streamRead,
- cpia_usb_close,
- 0,
- THIS_MODULE
-};
-
-static LIST_HEAD(cam_list);
-static spinlock_t cam_list_lock_usb;
-
-static void cpia_usb_complete(struct urb *urb)
-{
- int i;
- char *cdata;
- struct usb_cpia *ucpia;
-
- if (!urb || !urb->context)
- return;
-
- ucpia = (struct usb_cpia *) urb->context;
-
- if (!ucpia->dev || !ucpia->streaming || !ucpia->present || !ucpia->open)
- return;
-
- if (ucpia->workbuff->status == FRAME_EMPTY) {
- ucpia->workbuff->status = FRAME_READING;
- ucpia->workbuff->length = 0;
- }
-
- for (i = 0; i < urb->number_of_packets; i++) {
- int n = urb->iso_frame_desc[i].actual_length;
- int st = urb->iso_frame_desc[i].status;
-
- cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
- if (st)
- printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n", i, n, st);
-
- if (FRAMEBUF_LEN < ucpia->workbuff->length + n) {
- printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n);
- return;
- }
-
- if (n) {
- if ((ucpia->workbuff->length > 0) ||
- (0x19 == cdata[0] && 0x68 == cdata[1])) {
- memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n);
- ucpia->workbuff->length += n;
- } else
- DBG("Ignoring packet!\n");
- } else {
- if (ucpia->workbuff->length > 4 &&
- 0xff == ucpia->workbuff->data[ucpia->workbuff->length-1] &&
- 0xff == ucpia->workbuff->data[ucpia->workbuff->length-2] &&
- 0xff == ucpia->workbuff->data[ucpia->workbuff->length-3] &&
- 0xff == ucpia->workbuff->data[ucpia->workbuff->length-4]) {
- ucpia->workbuff->status = FRAME_READY;
- ucpia->curbuff = ucpia->workbuff;
- ucpia->workbuff = ucpia->workbuff->next;
- ucpia->workbuff->status = FRAME_EMPTY;
- ucpia->workbuff->length = 0;
-
- if (waitqueue_active(&ucpia->wq_stream))
- wake_up_interruptible(&ucpia->wq_stream);
- }
- }
- }
-
- /* resubmit */
- urb->dev = ucpia->dev;
- if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
- printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__, i);
-}
-
-static int cpia_usb_open(void *privdata)
-{
- struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
- struct urb *urb;
- int ret, retval = 0, fx, err;
-
- if (!ucpia)
- return -EINVAL;
-
- ucpia->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
- if (!ucpia->sbuf[0].data)
- return -EINVAL;
-
- ucpia->sbuf[1].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
- if (!ucpia->sbuf[1].data) {
- retval = -EINVAL;
- goto error_0;
- }
-
- ret = usb_set_interface(ucpia->dev, ucpia->iface, 3);
- if (ret < 0) {
- printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret);
- retval = -EBUSY;
- goto error_1;
- }
-
- ucpia->buffers[0]->status = FRAME_EMPTY;
- ucpia->buffers[0]->length = 0;
- ucpia->buffers[1]->status = FRAME_EMPTY;
- ucpia->buffers[1]->length = 0;
- ucpia->buffers[2]->status = FRAME_EMPTY;
- ucpia->buffers[2]->length = 0;
- ucpia->curbuff = ucpia->buffers[0];
- ucpia->workbuff = ucpia->buffers[1];
-
- /* We double buffer the Iso lists, and also know the polling
- * interval is every frame (1 == (1 << (bInterval -1))).
- */
- urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
- if (!urb) {
- printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 0\n");
- retval = -ENOMEM;
- goto error_1;
- }
-
- ucpia->sbuf[0].urb = urb;
- urb->dev = ucpia->dev;
- urb->context = ucpia;
- urb->pipe = usb_rcvisocpipe(ucpia->dev, 1);
- urb->transfer_flags = URB_ISO_ASAP;
- urb->transfer_buffer = ucpia->sbuf[0].data;
- urb->complete = cpia_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;
- }
-
- urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
- if (!urb) {
- printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 1\n");
- retval = -ENOMEM;
- goto error_urb0;
- }
-
- ucpia->sbuf[1].urb = urb;
- urb->dev = ucpia->dev;
- urb->context = ucpia;
- urb->pipe = usb_rcvisocpipe(ucpia->dev, 1);
- urb->transfer_flags = URB_ISO_ASAP;
- urb->transfer_buffer = ucpia->sbuf[1].data;
- urb->complete = cpia_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 */
- err = usb_submit_urb(ucpia->sbuf[0].urb, GFP_KERNEL);
- if (err) {
- printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 0 ret %d\n",
- err);
- goto error_urb1;
- }
- err = usb_submit_urb(ucpia->sbuf[1].urb, GFP_KERNEL);
- if (err) {
- printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 1 ret %d\n",
- err);
- goto error_urb1;
- }
-
- ucpia->streaming = 1;
- ucpia->open = 1;
-
- return 0;
-
-error_urb1: /* free urb 1 */
- usb_free_urb(ucpia->sbuf[1].urb);
- ucpia->sbuf[1].urb = NULL;
-error_urb0: /* free urb 0 */
- usb_free_urb(ucpia->sbuf[0].urb);
- ucpia->sbuf[0].urb = NULL;
-error_1:
- kfree (ucpia->sbuf[1].data);
- ucpia->sbuf[1].data = NULL;
-error_0:
- kfree (ucpia->sbuf[0].data);
- ucpia->sbuf[0].data = NULL;
-
- return retval;
-}
-
-//
-// convenience functions
-//
-
-/****************************************************************************
- *
- * WritePacket
- *
- ***************************************************************************/
-static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_t size)
-{
- if (!packet)
- return -EINVAL;
-
- return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- packet[1] + (packet[0] << 8),
- USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- packet[2] + (packet[3] << 8),
- packet[4] + (packet[5] << 8), buf, size, 1000);
-}
-
-/****************************************************************************
- *
- * ReadPacket
- *
- ***************************************************************************/
-static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size)
-{
- if (!packet || size <= 0)
- return -EINVAL;
-
- return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
- packet[1] + (packet[0] << 8),
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- packet[2] + (packet[3] << 8),
- packet[4] + (packet[5] << 8), buf, size, 1000);
-}
-
-static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data)
-{
- int err = 0;
- int databytes;
- struct usb_cpia *ucpia = (struct usb_cpia *)privdata;
- struct usb_device *udev = ucpia->dev;
-
- if (!udev) {
- DBG("Internal driver error: udev is NULL\n");
- return -EINVAL;
- }
-
- if (!command) {
- DBG("Internal driver error: command is NULL\n");
- return -EINVAL;
- }
-
- databytes = (((int)command[7])<<8) | command[6];
-
- if (command[0] == DATA_IN) {
- u8 buffer[8];
-
- if (!data) {
- DBG("Internal driver error: data is NULL\n");
- return -EINVAL;
- }
-
- err = ReadPacket(udev, command, buffer, 8);
- if (err < 0)
- return err;
-
- memcpy(data, buffer, databytes);
- } else if(command[0] == DATA_OUT)
- WritePacket(udev, command, data, databytes);
- else {
- DBG("Unexpected first byte of command: %x\n", command[0]);
- err = -EINVAL;
- }
-
- return 0;
-}
-
-static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
- void *cbdata)
-{
- return -ENODEV;
-}
-
-static int cpia_usb_streamStart(void *privdata)
-{
- return -ENODEV;
-}
-
-static int cpia_usb_streamStop(void *privdata)
-{
- return -ENODEV;
-}
-
-static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock)
-{
- struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
- struct framebuf *mybuff;
-
- if (!ucpia || !ucpia->present)
- return -1;
-
- if (ucpia->curbuff->status != FRAME_READY)
- interruptible_sleep_on(&ucpia->wq_stream);
- else
- DBG("Frame already waiting!\n");
-
- mybuff = ucpia->curbuff;
-
- if (!mybuff)
- return -1;
-
- if (mybuff->status != FRAME_READY || mybuff->length < 4) {
- DBG("Something went wrong!\n");
- return -1;
- }
-
- memcpy(frame, mybuff->data, mybuff->length);
- mybuff->status = FRAME_EMPTY;
-
-/* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */
-/* mybuff->length, frame[0], frame[1], */
-/* frame[mybuff->length-4], frame[mybuff->length-3], */
-/* frame[mybuff->length-2], frame[mybuff->length-1]); */
-
- return mybuff->length;
-}
-
-static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
-{
- if (!ucpia->streaming)
- return;
-
- ucpia->streaming = 0;
-
- /* Set packet size to 0 */
- if (try) {
- int ret;
-
- ret = usb_set_interface(ucpia->dev, ucpia->iface, 0);
- if (ret < 0) {
- printk(KERN_ERR "usb_set_interface error (ret = %d)\n", ret);
- return;
- }
- }
-
- /* Unschedule all of the iso td's */
- if (ucpia->sbuf[1].urb) {
- usb_kill_urb(ucpia->sbuf[1].urb);
- usb_free_urb(ucpia->sbuf[1].urb);
- ucpia->sbuf[1].urb = NULL;
- }
-
- kfree(ucpia->sbuf[1].data);
- ucpia->sbuf[1].data = NULL;
-
- if (ucpia->sbuf[0].urb) {
- usb_kill_urb(ucpia->sbuf[0].urb);
- usb_free_urb(ucpia->sbuf[0].urb);
- ucpia->sbuf[0].urb = NULL;
- }
-
- kfree(ucpia->sbuf[0].data);
- ucpia->sbuf[0].data = NULL;
-}
-
-static int cpia_usb_close(void *privdata)
-{
- struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
-
- if(!ucpia)
- return -ENODEV;
-
- ucpia->open = 0;
-
- /* ucpia->present = 0 protects against trying to reset the
- * alt setting if camera is physically disconnected while open */
- cpia_usb_free_resources(ucpia, ucpia->present);
-
- return 0;
-}
-
-/* Probing and initializing */
-
-static int cpia_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_host_interface *interface;
- struct usb_cpia *ucpia;
- struct cam_data *cam;
- int ret;
-
- /* A multi-config CPiA camera? */
- if (udev->descriptor.bNumConfigurations != 1)
- return -ENODEV;
-
- interface = intf->cur_altsetting;
-
- printk(KERN_INFO "USB CPiA camera found\n");
-
- ucpia = kzalloc(sizeof(*ucpia), GFP_KERNEL);
- if (!ucpia) {
- printk(KERN_ERR "couldn't kmalloc cpia struct\n");
- return -ENOMEM;
- }
-
- ucpia->dev = udev;
- ucpia->iface = interface->desc.bInterfaceNumber;
- init_waitqueue_head(&ucpia->wq_stream);
-
- ucpia->buffers[0] = vmalloc(sizeof(*ucpia->buffers[0]));
- if (!ucpia->buffers[0]) {
- printk(KERN_ERR "couldn't vmalloc frame buffer 0\n");
- goto fail_alloc_0;
- }
-
- ucpia->buffers[1] = vmalloc(sizeof(*ucpia->buffers[1]));
- if (!ucpia->buffers[1]) {
- printk(KERN_ERR "couldn't vmalloc frame buffer 1\n");
- goto fail_alloc_1;
- }
-
- ucpia->buffers[2] = vmalloc(sizeof(*ucpia->buffers[2]));
- if (!ucpia->buffers[2]) {
- printk(KERN_ERR "couldn't vmalloc frame buffer 2\n");
- goto fail_alloc_2;
- }
-
- ucpia->buffers[0]->next = ucpia->buffers[1];
- ucpia->buffers[1]->next = ucpia->buffers[2];
- ucpia->buffers[2]->next = ucpia->buffers[0];
-
- ret = usb_set_interface(udev, ucpia->iface, 0);
- if (ret < 0) {
- printk(KERN_ERR "cpia_probe: usb_set_interface error (ret = %d)\n", ret);
- /* goto fail_all; */
- }
-
- /* Before register_camera, important */
- ucpia->present = 1;
-
- cam = cpia_register_camera(&cpia_usb_ops, ucpia);
- if (!cam) {
- LOG("failed to cpia_register_camera\n");
- goto fail_all;
- }
-
- spin_lock( &cam_list_lock_usb );
- list_add( &cam->cam_data_list, &cam_list );
- spin_unlock( &cam_list_lock_usb );
-
- usb_set_intfdata(intf, cam);
- return 0;
-
-fail_all:
- vfree(ucpia->buffers[2]);
- ucpia->buffers[2] = NULL;
-fail_alloc_2:
- vfree(ucpia->buffers[1]);
- ucpia->buffers[1] = NULL;
-fail_alloc_1:
- vfree(ucpia->buffers[0]);
- ucpia->buffers[0] = NULL;
-fail_alloc_0:
- kfree(ucpia);
- return -EIO;
-}
-
-static void cpia_disconnect(struct usb_interface *intf);
-
-static struct usb_device_id cpia_id_table [] = {
- { USB_DEVICE(0x0553, 0x0002) },
- { USB_DEVICE(0x0813, 0x0001) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, cpia_id_table);
-MODULE_LICENSE("GPL");
-
-
-static struct usb_driver cpia_driver = {
- .name = "cpia",
- .probe = cpia_probe,
- .disconnect = cpia_disconnect,
- .id_table = cpia_id_table,
-};
-
-static void cpia_disconnect(struct usb_interface *intf)
-{
- struct cam_data *cam = usb_get_intfdata(intf);
- struct usb_cpia *ucpia;
-
- usb_set_intfdata(intf, NULL);
- if (!cam)
- return;
-
- ucpia = (struct usb_cpia *) cam->lowlevel_data;
- spin_lock( &cam_list_lock_usb );
- list_del(&cam->cam_data_list);
- spin_unlock( &cam_list_lock_usb );
-
- ucpia->present = 0;
-
- cpia_unregister_camera(cam);
- if(ucpia->open)
- cpia_usb_close(cam->lowlevel_data);
-
- ucpia->curbuff->status = FRAME_ERROR;
-
- if (waitqueue_active(&ucpia->wq_stream))
- wake_up_interruptible(&ucpia->wq_stream);
-
- ucpia->curbuff = ucpia->workbuff = NULL;
-
- vfree(ucpia->buffers[2]);
- ucpia->buffers[2] = NULL;
-
- vfree(ucpia->buffers[1]);
- ucpia->buffers[1] = NULL;
-
- vfree(ucpia->buffers[0]);
- ucpia->buffers[0] = NULL;
-
- cam->lowlevel_data = NULL;
- kfree(ucpia);
-}
-
-static int __init usb_cpia_init(void)
-{
- printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
- CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER);
-
- spin_lock_init(&cam_list_lock_usb);
- return usb_register(&cpia_driver);
-}
-
-static void __exit usb_cpia_cleanup(void)
-{
- usb_deregister(&cpia_driver);
-}
-
-
-module_init (usb_cpia_init);
-module_exit (usb_cpia_cleanup);
-
OpenPOWER on IntegriCloud