patch-2.4.20 linux-2.4.20/drivers/media/video/cpia.c
Next file: linux-2.4.20/drivers/media/video/cpia.h
Previous file: linux-2.4.20/drivers/media/video/bttvp.h
Back to the patch index
Back to the overall index
- Lines: 503
- Date:
Thu Nov 28 15:53:13 2002
- Orig file:
linux-2.4.19/drivers/media/video/cpia.c
- Orig date:
Thu Oct 25 13:53:47 2001
diff -urN linux-2.4.19/drivers/media/video/cpia.c linux-2.4.20/drivers/media/video/cpia.c
@@ -56,7 +56,7 @@
#ifdef MODULE
MODULE_PARM(video_nr,"i");
-MODULE_AUTHOR("Scott J. Bertin <sbertin@mindspring.com> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <jerdfelt@valinux.com>");
+MODULE_AUTHOR("Scott J. Bertin <sbertin@securenym.net> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <johannes@erdfeld.com>");
MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("video");
@@ -163,6 +163,7 @@
#define COMMAND_SETAPCOR 0x1000
#define COMMAND_SETFLICKERCTRL 0x2000
#define COMMAND_SETVLOFFSET 0x4000
+#define COMMAND_SETLIGHTS 0x8000
/* Developer's Guide Table 5 p 3-34
* indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
@@ -178,50 +179,17 @@
*
* Memory management
*
- * This is a shameless copy from the USB-cpia driver (linux kernel
- * version 2.3.29 or so, I have no idea what this code actually does ;).
- * Actually it seems to be a copy of a shameless copy of the bttv-driver.
- * Or that is a copy of a shameless copy of ... (To the powers: is there
- * no generic kernel-function to do this sort of stuff?)
- *
- * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
- * there will be one, but apparentely not yet - jerdfelt
- *
**********************************************************************/
-/* Given PGD from the address space's page table, return the kernel
- * virtual mapping of the physical memory mapped at ADR.
- */
-static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
-{
- unsigned long ret = 0UL;
- pmd_t *pmd;
- pte_t *ptep, pte;
-
- if (!pgd_none(*pgd)) {
- pmd = pmd_offset(pgd, adr);
- if (!pmd_none(*pmd)) {
- ptep = pte_offset(pmd, adr);
- pte = *ptep;
- if (pte_present(pte)) {
- ret = (unsigned long) page_address(pte_page(pte));
- ret |= (adr & (PAGE_SIZE-1));
- }
- }
- }
- return ret;
-}
-
/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
- unsigned long va, kva, ret;
+ unsigned long kva, ret;
- va = VMALLOC_VMADDR(adr);
- kva = uvirt_to_kva(pgd_offset_k(va), va);
+ kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+ kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva);
return ret;
}
@@ -229,12 +197,9 @@
static void *rvmalloc(unsigned long size)
{
void *mem;
- unsigned long adr, page;
-
- /* Round it off to PAGE_SIZE */
- size += (PAGE_SIZE - 1);
- size &= ~(PAGE_SIZE - 1);
+ unsigned long adr;
+ size = PAGE_ALIGN(size);
mem = vmalloc_32(size);
if (!mem)
return NULL;
@@ -242,13 +207,9 @@
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr = (unsigned long) mem;
while (size > 0) {
- page = kvirt_to_pa(adr);
- mem_map_reserve(virt_to_page(__va(page)));
+ mem_map_reserve(vmalloc_to_page((void *)adr));
adr += PAGE_SIZE;
- if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
- else
- size = 0;
+ size -= PAGE_SIZE;
}
return mem;
@@ -256,23 +217,16 @@
static void rvfree(void *mem, unsigned long size)
{
- unsigned long adr, page;
+ unsigned long adr;
if (!mem)
return;
- size += (PAGE_SIZE - 1);
- size &= ~(PAGE_SIZE - 1);
-
adr = (unsigned long) mem;
- while (size > 0) {
- page = kvirt_to_pa(adr);
- mem_map_unreserve(virt_to_page(__va(page)));
+ while ((long) size > 0) {
+ mem_map_unreserve(vmalloc_to_page((void *)adr));
adr += PAGE_SIZE;
- if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
- else
- size = 0;
+ size -= PAGE_SIZE;
}
vfree(mem);
}
@@ -291,7 +245,7 @@
char *out = page;
int len, tmp;
struct cam_data *cam = data;
- char tmpstr[20];
+ char tmpstr[29];
/* IMPORTANT: This output MUST be kept under PAGE_SIZE
* or we need to get more sophisticated. */
@@ -328,6 +282,13 @@
cam->params.status.vpStatus);
out += sprintf(out, "error_code: %#04x\n",
cam->params.status.errorCode);
+ /* QX3 specific entries */
+ if (cam->params.qx3.qx3_detected) {
+ out += sprintf(out, "button: %4d\n",
+ cam->params.qx3.button);
+ out += sprintf(out, "cradled: %4d\n",
+ cam->params.qx3.cradled);
+ }
out += sprintf(out, "video_size: %s\n",
cam->params.format.videoSize == VIDEOSIZE_CIF ?
"CIF " : "QCIF");
@@ -392,16 +353,17 @@
if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2)
/* 1-02 firmware limits gain to 2 */
- sprintf(tmpstr, "%8d %8d", 1, 2);
+ sprintf(tmpstr, "%8d %8d %8d", 1, 2, 2);
else
- sprintf(tmpstr, "1,2,4,8");
+ sprintf(tmpstr, "%8d %8d %8d", 1, 8, 2);
if (cam->params.exposure.gainMode == 0)
- out += sprintf(out, "max_gain: unknown %18s"
- " %8d\n", tmpstr, 2);
+ out += sprintf(out, "max_gain: unknown %28s"
+ " powers of 2\n", tmpstr);
else
- out += sprintf(out, "max_gain: %8d %18s %8d\n",
- 1<<(cam->params.exposure.gainMode-1), tmpstr, 2);
+ out += sprintf(out, "max_gain: %8d %28s"
+ " 1,2,4 or 8 \n",
+ 1<<(cam->params.exposure.gainMode-1), tmpstr);
switch(cam->params.exposure.expMode) {
case 1:
@@ -528,6 +490,15 @@
out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n",
cam->params.compressionParams.decimationThreshMod,
0, 255, 2);
+ /* QX3 specific entries */
+ if (cam->params.qx3.qx3_detected) {
+ out += sprintf(out, "toplight: %8s %8s %8s %8s\n",
+ cam->params.qx3.toplight ? "on" : "off",
+ "off", "on", "off");
+ out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n",
+ cam->params.qx3.bottomlight ? "on" : "off",
+ "off", "on", "off");
+ }
len = out - page;
len -= off;
@@ -541,18 +512,45 @@
return len;
}
-static int cpia_write_proc(struct file *file, const char *buffer,
+static int cpia_write_proc(struct file *file, const char *buf,
unsigned long count, void *data)
{
- return -EINVAL;
-#if 0
struct cam_data *cam = data;
struct cam_params new_params;
+ char *page, *buffer;
int retval, find_colon;
int size = count;
- unsigned long val;
+ 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 %lu > %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 (down_interruptible(&cam->param_lock))
return -ERESTARTSYS;
@@ -1210,6 +1208,22 @@
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;
@@ -1221,7 +1235,10 @@
++buffer;
}
if (count) {
- if (*buffer != '\n' && *buffer != ';')
+ if (*buffer == '\0' && count != 1)
+ retval = -EINVAL;
+ else if (*buffer != '\n' && *buffer != ';' &&
+ *buffer != '\0')
retval = -EINVAL;
else {
--count;
@@ -1255,8 +1272,9 @@
up(&cam->param_lock);
+out:
+ free_page((unsigned long)page);
return retval;
-#endif
}
static void create_proc_cpia_cam(struct cam_data *cam)
@@ -1276,7 +1294,12 @@
ent->data = cam;
ent->read_proc = cpia_read_proc;
ent->write_proc = cpia_write_proc;
- ent->size = 3626;
+ /*
+ size of the proc entry is 3672 bytes for the standard webcam;
+ the extra features of the QX3 microscope add 188 bytes.
+ (we have not yet probed the camera to see which type it is).
+ */
+ ent->size = 3672 + 188;
cam->proc_entry = ent;
}
@@ -1570,6 +1593,10 @@
down(&cam->param_lock);
datasize=8;
break;
+ case CPIA_COMMAND_ReadMCPorts:
+ case CPIA_COMMAND_ReadVCRegs:
+ datasize = 4;
+ break;
default:
datasize=0;
break;
@@ -1667,6 +1694,22 @@
}
up(&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;
}
@@ -1826,6 +1869,7 @@
{
switch(fmt) {
case VIDEO_PALETTE_GREY:
+ return count;
case VIDEO_PALETTE_RGB555:
case VIDEO_PALETTE_RGB565:
case VIDEO_PALETTE_YUV422:
@@ -2106,6 +2150,13 @@
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);
+ }
+
up(&cam->param_lock);
cam->cmd_queue = COMMAND_NONE;
return;
@@ -2182,9 +2233,10 @@
/* camera idle now so dispatch queued commands */
dispatch_commands(cam);
- /* Update our knowledge of the camera state - FIXME: necessary? */
+ /* 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
@@ -2396,7 +2448,11 @@
get_version_information(cam);
if (cam->params.version.firmwareVersion != 1)
return -ENODEV;
-
+
+ /* 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) */
@@ -2526,7 +2582,7 @@
/* GotoLoPower */
goto_low_power(cam);
- /* Update the camera ststus */
+ /* Update the camera status */
do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
/* cleanup internal state stuff */
@@ -2566,7 +2622,7 @@
{
struct cam_data *cam = dev->priv;
- /* make this _really_ smp and multithredi-safe */
+ /* make this _really_ smp and multithread-safe */
if (down_interruptible(&cam->busy_lock))
return -EINTR;
@@ -2793,7 +2849,6 @@
cam->cmd_queue |= COMMAND_SETFORMAT;
}
- // FIXME needed??? memcpy(&cam->vw, &vw, sizeof(vw));
up(&cam->param_lock);
/* setformat ignored by camera during streaming,
@@ -2835,10 +2890,8 @@
retval = -EFAULT;
break;
}
-#if 1
DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm.format, vm.frame,
vm.width, vm.height);
-#endif
if (vm.frame<0||vm.frame>=FRAME_NUM) {
retval = -EINVAL;
break;
@@ -2848,6 +2901,8 @@
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:
@@ -2880,10 +2935,6 @@
cam->cmd_queue |= COMMAND_SETFORMAT;
dispatch_commands(cam);
}
-#if 0
- DBG("VIDIOCMCAPTURE: %d / %d/%d\n", cam->video_size,
- cam->vw.width, cam->vw.height);
-#endif
/* according to v4l-spec we must start streaming here */
cam->mmap_kludge = 1;
retval = capture_frame(cam, &vm);
@@ -3035,7 +3086,7 @@
owner: THIS_MODULE,
name: "CPiA Camera",
type: VID_TYPE_CAPTURE,
- hardware: VID_HARDWARE_CPIA, /* FIXME */
+ hardware: VID_HARDWARE_CPIA,
open: cpia_open,
close: cpia_close,
read: cpia_read,
@@ -3100,8 +3151,8 @@
cam->params.sensorFps.divisor = 1;
cam->params.sensorFps.baserate = 1;
- cam->params.yuvThreshold.yThreshold = 15; /* FIXME? */
- cam->params.yuvThreshold.uvThreshold = 15; /* FIXME? */
+ 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;
@@ -3109,8 +3160,14 @@
cam->params.compression.mode = CPIA_COMPRESSION_AUTO;
cam->params.compressionTarget.frTargeting =
CPIA_COMPRESSION_TARGET_QUALITY;
- cam->params.compressionTarget.targetFR = 7; /* FIXME? */
- cam->params.compressionTarget.targetQ = 10; /* FIXME? */
+ 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;
@@ -3119,8 +3176,8 @@
cam->vp.brightness = 32768; /* 50% */
cam->vp.contrast = 32768; /* 50% */
cam->vp.whiteness = 0; /* not used -> grayscale only */
- cam->vp.depth = 0; /* FIXME: to be set by user? */
- cam->vp.palette = VIDEO_PALETTE_RGB24; /* FIXME: to be set by user? */
+ cam->vp.depth = 24; /* to be set by user */
+ cam->vp.palette = VIDEO_PALETTE_RGB24; /* to be set by user */
cam->vw.x = 0;
cam->vw.y = 0;
@@ -3209,12 +3266,6 @@
/* close cpia */
camera->ops->close(camera->lowlevel_data);
-/* Eh? Feeling happy? - jerdfelt */
-/*
- camera->ops->open(camera->lowlevel_data);
- camera->ops->close(camera->lowlevel_data);
-*/
-
printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n",
camera->params.version.firmwareVersion,
camera->params.version.firmwareRevision,
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)