📄 spca5xx.c
字号:
/* x , y , Code, Value (6), Value (7), pipe */ {1024, 768, 0x00, 0, 0, 1023}, {640, 480, 0x01, 1, 0, 1023}, {352, 288, 0x02, 2, 0, 896}, {320, 240, 0x03, 3, 0, 896}, {176, 144, 0x04, 4, 0, 768},/* { 160, 120, 0x05, 5, 0, 768 }, */ {0, 0, 0, 0, 0}};static __u16 spca561_ext_modes[][6] = { {352, 288, 0x00, 0x27, 0x00, 1023}, {320, 240, 0x01, 0x27, 0x00, 1023}, //{ 176, 144, 0x11, 0x27, 0x00, 1023}, //{ 160, 120, 0x11, 0x27, 0x00, 1023}, {176, 144, 0x02, 0x23, 0x00, 1023}, // software mode hardware seem buggy slow shift in video {160, 120, 0x03, 0x23, 0x00, 1023}, {0, 0, 0, 0, 0}};/* default value used for spca505 and spca505b */static __u16 spca50x_ext_modes[][6] = { /* x , y , Code, Value (6), Value (7), pipe */ {640, 480, 0, 0x10, 0x10, 1023}, /* Tested spca505b+VGA sensor */ {352, 288, 1, 0x1a, 0x1a, 1023}, /* Tested */ {320, 240, 2, 0x1c, 0x1d, 896}, /* Tested 20:01:2004 */ {176, 144, 4, 0x34, 0x34, 512}, /* Tested */ {160, 120, 5, 0x40, 0x40, 384}, /* Tested */ {0, 0, 0, 0, 0}};static __u16 spca506_ext_modes[][6] = { /* In this table, element 3 (clk) controls the * clock, and gets written to 0x8700. */ /* x , y , Code, clk, n/a, pipe */ {640, 480, 0x00, 0x10, 0x10, 1023}, {352, 288, 0x01, 0x1a, 0x1a, 1023}, {320, 240, 0x02, 0x1c, 0x1c, 1023}, //896 {176, 144, 0x04, 0x34, 0x34, 1023}, {160, 120, 0x05, 0x40, 0x40, 1023}, {0, 0, 0, 0, 0}};// 1a 1b 20 static __u16 spca508_ext_modes[][6] = { /* In this table, element 3 (clk) controls the * clock, and gets written to 0x8700. */ /* x , y , Code, clk, n/a, pipe */ {352, 288, 0x00, 0x28, 0x00, 1023}, {320, 240, 0x01, 0x28, 0x00, 1023}, {176, 144, 0x02, 0x23, 0x00, 1023}, {160, 120, 0x03, 0x23, 0x00, 1023}, {0, 0, 0, 0, 0}};static __u16 tv8532_ext_modes[][6] = { /* x , y , Code, clk, n/a, pipe */ {352, 288, 0x00, 0x28, 0x00, 1023}, {320, 240, 0x10, 0x28, 0x00, 1023}, {176, 144, 0x01, 0x23, 0x00, 1023}, /*{160, 120, 0x03, 0x23, 0x00, 1023}, */ {0, 0, 0, 0, 0}};#ifdef CONFIG_PROC_FS/* Not sure what we should do with this. I think it is V4L level 2 stuff *//* Currently only use RGB24 */static struct palette_list plist[] = { {VIDEO_PALETTE_GREY, "GREY"}, {VIDEO_PALETTE_HI240, "HI240"}, {VIDEO_PALETTE_RGB565, "RGB565"}, {VIDEO_PALETTE_RGB24, "RGB24"}, {VIDEO_PALETTE_RGB32, "RGB32"}, {VIDEO_PALETTE_RGB555, "RGB555"}, {VIDEO_PALETTE_YUV422, "YUV422"}, {VIDEO_PALETTE_YUYV, "YUYV"}, {VIDEO_PALETTE_UYVY, "UYVY"}, {VIDEO_PALETTE_YUV420, "YUV420"}, {VIDEO_PALETTE_YUV411, "YUV411"}, {VIDEO_PALETTE_RAW, "RAW"}, {VIDEO_PALETTE_YUV422P, "YUV422P"}, {VIDEO_PALETTE_YUV411P, "YUV411P"}, {VIDEO_PALETTE_YUV420P, "YUV420P"}, {VIDEO_PALETTE_YUV410P, "YUV410P"}, {VIDEO_PALETTE_RAW_JPEG, "RJPG"}, {VIDEO_PALETTE_JPEG, "JPEG"}, {-1, NULL}};#endif /* CONFIG_PROC_FS *//* struct for the tasklet */void outpict_do_tasklet (unsigned long ptr);DECLARE_TASKLET (outpicttasklet, outpict_do_tasklet, (unsigned long) NULL);/********************************************************************** * * 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 * * So I copied it again for the ov511 driver -claudio * And again for the spca50x driver -jcrisp **********************************************************************//* Given PGD from the address space's page table, return the kernel * virtual mapping of the physical memory mapped at ADR. */#ifndef RH9_REMAPstatic inline unsigned longuvirt_to_kva (pgd_t * pgd, unsigned long adr){ unsigned long ret = 0UL; pmd_t *pmd; pte_t *ptep, pte; if (!pgd_none (*pgd)) {#if PUD_SHIFT pud_t *pud = pud_offset (pgd, adr); if (!pud_none (*pud)) { pmd = pmd_offset (pud, adr);#else pmd = pmd_offset (pgd, adr);#endif if (!pmd_none (*pmd)) { /* WOLT kernels appear to have changed pte_offset to pte_offset_kernel */#ifdef pte_offset ptep = pte_offset (pmd, adr);#else /* pte_offset */ ptep = pte_offset_kernel (pmd, adr);#endif /* pte_offset */ pte = *ptep; if (pte_present (pte)) { ret = (unsigned long) page_address (pte_page (pte)); ret |= (adr & (PAGE_SIZE - 1)); }#if PUD_SHIFT }#endif }}return ret;}#endif /* RH9_REMAP *//* 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. */#ifdef RH9_REMAPstatic inline unsigned longkvirt_to_pa (unsigned long adr){ unsigned long kva, ret; kva = (unsigned long) page_address (vmalloc_to_page ((void *) adr)); kva |= adr & (PAGE_SIZE - 1); /* restore the offset */ ret = __pa (kva); return ret;}#else /* RH9_REMAP */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)static inline unsigned longkvirt_to_pa (unsigned long adr){ unsigned long kva, ret; kva = (unsigned long) page_address (vmalloc_to_page ((void *) adr)); kva |= adr & (PAGE_SIZE - 1); ret = __pa (kva); return ret;}#elsestatic inline unsigned longkvirt_to_pa (unsigned long adr){ unsigned long va, kva, ret; va = VMALLOC_VMADDR (adr); kva = uvirt_to_kva (pgd_offset_k (va), va); ret = __pa (kva); return ret;}#endif#endif /* RH9_REMAP */static void *rvmalloc (unsigned long size){ void *mem; unsigned long adr;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 23)unsigned long page;#endif 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 ((long) size > 0) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 68) SetPageReserved (vmalloc_to_page ((void *) adr));#else#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23) mem_map_reserve (vmalloc_to_page ((void *) adr));#else page = kvirt_to_pa (adr); mem_map_reserve(VIRT_TO_PAGE(__va (page)));#endif#endif adr += PAGE_SIZE; size -= PAGE_SIZE; } return mem;}static voidrvfree (void *mem, unsigned long size){ unsigned long adr;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 23)unsigned long page;#endif if (!mem) return; adr = (unsigned long) mem; while ((long) size > 0) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 68) ClearPageReserved (vmalloc_to_page ((void *) adr));#else#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23) mem_map_unreserve (vmalloc_to_page ((void *) adr));#else page = kvirt_to_pa (adr); mem_map_unreserve(VIRT_TO_PAGE(__va (page)));#endif#endif adr += PAGE_SIZE; size -= PAGE_SIZE; } vfree (mem);}/********************************************************************** * Get average luminance **********************************************************************/static inline __u8get_avg_lum (struct usb_spca50x *spca50x){ __u8 luminance; //The average luminance from camera switch (spca50x->bridge) { case BRIDGE_SPCA501: luminance = spca50x_reg_read (spca50x->dev, SPCA501_REG_CCDSP, 0x26, 2) >> 8; break;#ifdef SPCA50X_ENABLE_EXP_BRIGHTNESS case BRIDGE_SPCA561: case BRIDGE_SPCA508: luminance = spca50x_reg_read (spca50x->dev, 0, 0x8621, 1); break;#endif /* SPCA50X_ENABLE_EXP_BRIGHTNESS */ default: luminance = 0; break; } return luminance;}/********************************************************************** * Get average R-G and B-G **********************************************************************/static inline __u8get_avg_RG (struct usb_spca50x *spca50x){ __u8 rg; //The average R-G for window5 switch (spca50x->bridge) { case BRIDGE_SPCA501: rg = spca50x_reg_read (spca50x->dev, SPCA501_REG_CCDSP, 0x30, 2) >> 8; break; default: rg = 0; break; } return rg;}/********************************************************************** * Get average B-G **********************************************************************/static inline __u8get_avg_BG (struct usb_spca50x *spca50x){ __u8 bg; //The average B-G for window5 switch (spca50x->bridge) { case BRIDGE_SPCA501: bg = spca50x_reg_read (spca50x->dev, SPCA501_REG_CCDSP, 0x2f, 2) >> 8; break; default: bg = 0; break; } return bg;}/********************************************************************** * /proc interface * Based on the CPiA driver version 0.7.4 -claudio * ..and again copied from the ov511 driver for the SPCA50x driver - jac **********************************************************************/#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry *spca50x_proc_entry = NULL;#ifdef CONFIG_VIDEO_PROC_FSextern struct proc_dir_entry *video_proc_entry;#endif /* CONFIG_VIDEO_PROC_FS */#define YES_NO(x) ((x) ? "yes" : "no")static intspca50x_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data){ char *out = page; int i, j, len; struct usb_spca50x *spca50x = data; /* IMPORTANT: This output MUST be kept under PAGE_SIZE * or we need to get more sophisticated. */ out += sprintf (out, "driver : SPCA50X USB Camera\n"); out += sprintf (out, "driver_version : %s\n", version); out += sprintf (out, "model : %s\n", (spca50x->desc) ? clist[spca50x->desc].description : "unknown"); out += sprintf (out, "streaming : %s\n", YES_NO (spca50x->streaming)); out += sprintf (out, "grabbing : %s\n", YES_NO (spca50x->grabbing)); out += sprintf (out, "compress : %s\n", YES_NO (spca50x->compress)); out += sprintf (out, "data_format : %s\n", spca50x->force_rgb ? "RGB" : "BGR"); out += sprintf (out, "brightness : %d\n", spca50x->brightness >> 8); out += sprintf (out, "colour : %d\n", spca50x->colour >> 8); out += sprintf (out, "hue : %d\n", spca50x->hue >> 8); out += sprintf (out, "contrast : %d\n", spca50x->contrast); out += sprintf (out, "num_frames : %d\n", SPCA50X_NUMFRAMES); out += sprintf (out, "curframe : %d\n", spca50x->curframe); out += sprintf (out, "lastFrameRead : %d\n", spca50x->lastFrameRead); spca50x->avg_lum = get_avg_lum (spca50x); out += sprintf (out, "Avg. luminance : 0x%X %d\n", spca50x->avg_lum, spca50x->avg_lum); for (i = 0; i < SPCA50X_NUMFRAMES; i++) { out += sprintf (out, "frame : %d\n", i); out += sprintf (out, " sequence : %d\n", spca50x->frame[i].seq); out += sprintf (out, " grabstate : %d\n", spca50x->frame[i].grabstate); out += sprintf (out, " depth : %d\n", spca50x->frame[i].depth); out += sprintf (out, " size : %d %d\n", spca50x->frame[i].width, spca50x->frame[i].height); out += sprintf (out, " format : "); for (j = 0; plist[j].num >= 0; j++) { if (plist[j].num == spca50x->frame[i].format) { out += sprintf (out, "%s\n", plist[j].name); break; } } if (plist[j].num < 0) out += sprintf (out, "unknown\n"); out += sprintf (out, " data_buffer : 0x%p\n", spca50x->frame[i].data); } out += sprintf (out, "snap_enabled : %s\n", YES_NO (spca50x->snap_enabled)); out += sprintf (out, "packet_size : %d\n", spca50x->packet_size); out += sprintf (out, "internal ccd : %s\n", YES_NO (!spca50x->ccd)); out += sprintf (out, "framebuffer : 0x%p\n", spca50x->fbuf);#ifdef SPCA50X_ENABLE_EXPERIMENTAL out += sprintf (out, "stable : %d\n", spca50x->nstable); out += sprintf (out, "unstable : %d\n", spca50x->nunstable); out += sprintf (out, "whiteness : %d\n", spca50x->whiteness >> 12); spca50x->avg_rg = get_avg_RG (spca50x); spca50x->avg_bg = get_avg_BG (spca50x); out += sprintf (out, "Avg. R-G/B-G : 0x%X/0x%X %d/%d\n", spca50x->avg_rg, spca50x->avg_bg, (char) spca50x->avg_rg, (char) spca50x->avg_bg);#endif /* SPCA50X_ENABLE_EXPERIMENTAL */ len = out - page; len -= off; if (len < count) { *eof = 1; if (len <= 0) return 0; } else len = count; *start = page + off; return len;}static int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -