📄 spca5xx.c
字号:
#include "mr97311.h"#include "pac207.h"/* Mode list for spca50x on external input *//* Must be in descending order as the closest match which is equal or smaller than * the requested size is returned */#if 0/* Trashcan before goes out */(bridge) == BRIDGE_SONIX ? sonix_ext_modes : (bridge) == BRIDGE_ZC3XX ? zc3xx_ext_modes : (bridge) == BRIDGE_ETOMS ? etoms_ext_modes : (bridge) == BRIDGE_SPCA561 ? spca561_ext_modes : (bridge) == BRIDGE_SN9CXXX ? sn9c102p_ext_modes : (bridge) == BRIDGE_SPCA504 ? spca504_ext_modes : (bridge) == BRIDGE_SPCA504B ? spca504_ext_modes : (bridge) == BRIDGE_SPCA504C ? spca504_pccam600_ext_modes : (bridge) == BRIDGE_SPCA533 ? spca533_ext_modes : (bridge) == BRIDGE_SPCA536 ? spca536_ext_modes : static __u16 pcam_ext_modes[][6] = { /* x , y , Code, Value (6), Value (7), pipe */ {1280, 1024, 0x00, 0, 0, 1023}, {640, 480, 0x01, 0, 0, 1023}, {384, 288, 0x11, 16, 12, 1023}, {352, 288, 0x11, 18, 12, 1023}, {320, 240, 0x02, 0, 0, 896}, {192, 144, 0x12, 8, 6, 896}, {176, 144, 0x12, 9, 6, 896}, {0, 0, 0, 0, 0}};static __u16 zc3xx_ext_modes[][6] = { /* x , y , Code, x multiplier, y multiplier, pipe */ {640, 480, 0x00, 0, 0, 1023}, // altersetting 7 endpoint 0x01 {352, 288, 0x10, 0, 0, 1023}, //0x00 SIF sensor {320, 240, 0x01, 0, 0, 1023}, {176, 144, 0x11, 0, 0, 1023}, //0x01 {0, 0, 0, 0, 0, 0}};static __u16 sonix_ext_modes[][6] = { /* x , y , Code, x multiplier, y multiplier, pipe */ {640, 480, 0x00, 0, 0, 1023}, {352, 288, 0x00, 0, 0, 1023}, {320, 240, 0x01, 0, 0, 1023}, {176, 144, 0x01, 0, 0, 1023}, {160, 120, 0x02, 0, 0, 1023}, {0, 0, 0, 0, 0, 0}};static __u16 etoms_ext_modes[][6] = { /* x , y , Code, x, y, pipe */ {352, 288, 0x00, 0, 0, 1000}, {320, 240, 0x01, 0, 0, 1000}, {176, 144, 0x01, 0, 0, 1000}, {0, 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, 0x02, 0x23, 0x00, 1023}, // software mode hardware seem buggy slow shift in video {160, 120, 0x03, 0x23, 0x00, 1023}, {0, 0, 0, 0, 0}};static __u16 sn9c102p_ext_modes[][6] = { /* x , y , Code, x, y, pipe */ {640, 480, 0x00, 0, 0, 1023}, {352, 288, 0x10, 0, 0, 1023}, {320, 240, 0x01, 0, 0, 1023}, {176, 144, 0x11, 0, 0, 1023}, {0, 0, 0, 0, 0, 0} static __u16 spca533_ext_modes[][6] = { /* x , y , Code, Value (6), Value (7), pipe */ //{ 640, 480, 0x41, 1, 0, 1023 }, {464, 480, 0x01, 0, 0, 1023}, //PocketDVII unscaled resolution aspect ratio need to expand x axis {464, 352, 0x01, 0, 0, 1023}, //Gsmart LCD3 feature good aspect ratio {384, 288, 0x11, 5, 4, 1023}, {352, 288, 0x11, 7, 4, 1023}, {320, 240, 0x02, 0, 0, 1023}, {192, 144, 0x12, 8, 6, 1023}, {176, 144, 0x12, 9, 6, 1023}, //{ 160, 120, 0x22, 1, 1, 1023 }, //{ 320, 128, 0x03, 0, 0, 1023 }, /* don't work with megapix V4*/ {0, 0, 0, 0, 0} }; static __u16 spca536_ext_modes[][6] = { /* x , y , Code, Value (6), Value (7), pipe */ {640, 480, 0x01, 1, 0, 1023}, //{ 464, 480, 0x01, 0, 0, 1023 }, //{ 464, 352, 0x01, 0, 0, 1023 }, {384, 288, 0x11, 5, 4, 1023}, {352, 288, 0x11, 7, 4, 1023}, {320, 240, 0x02, 0, 0, 896}, {192, 144, 0x12, 8, 6, 896}, {176, 144, 0x12, 9, 6, 896}, {0, 0, 0, 0, 0} }; static __u16 spca504_ext_modes[][6] = { /* x , y , Code, Value (6), Value (7), pipe */ {640, 480, 0x01, 0, 0, 1023}, {384, 288, 0x11, 16, 12, 1023}, {352, 288, 0x11, 18, 12, 1023}, {320, 240, 0x02, 0, 0, 896}, {192, 144, 0x12, 8, 6, 896}, {176, 144, 0x12, 9, 6, 896}, //{ 160, 120, 0x22, 1, 1, 896 }, {0, 0, 0, 0, 0} }; static __u16 spca504_pccam600_ext_modes[][6] = { /* 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} };};#endif#define GET_EXT_MODES(bridge) (\ (bridge) == BRIDGE_SPCA500 ? spca500_ext_modes : \ (bridge) == BRIDGE_SPCA501 ? spca501_ext_modes : \ (bridge) == BRIDGE_SPCA506 ? spca506_ext_modes : \ (bridge) == BRIDGE_SPCA508 ? spca508_ext_modes : \ (bridge) == BRIDGE_CX11646 ? cx11646_ext_modes : \ (bridge) == BRIDGE_TV8532 ? tv8532_ext_modes : \ spca50x_ext_modes)/* code is used for harware low nibble and software hight nibble */static __u16 cx11646_ext_modes[][6] = { /* x , y , Code, x multiplier, y multiplier, pipe */ {640, 480, 0x00, 0, 0, 1023}, // altersetting 7 endpoint 0x01 {352, 288, 0x01, 0, 0, 1023}, {320, 240, 0x02, 0, 0, 1023}, {176, 144, 0x03, 0, 0, 640}, // alt 4 // {160, 120, 0x04, 0, 0, 512}, // alt 3 only works with external decoding {0, 0, 0, 0, 0, 0}};static __u16 spca500_ext_modes[][6] = { /* x , y , Code, x multiplier, y multiplier, pipe */ {640, 480, 0x00, 40, 30, 1023}, {352, 288, 0x00, 22, 18, 1023}, {320, 240, 0x01, 40, 30, 1023}, {176, 144, 0x01, 22, 18, 1023}, /* 160x120 disable jpeg %16 */ {0, 0, 0, 0, 0, 0}};static __u16 spca501_ext_modes[][6] = { /* x , y , Code, Value (6), Value (7), pipe */ {640, 480, 0, 0x94, 0x004A, 1023}, {352, 288, 0x10, 0x94, 0x004A, 1023}, {320, 240, 0, 0x94, 0x104A, 896}, {176, 144, 0x10, 0x94, 0x104A, 896}, {160, 120, 0, 0x94, 0x204A, 384}, {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 *//* function for the tasklet */void outpict_do_tasklet(unsigned long ptr);/********************************************************************** * * 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 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)) {#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)) { ptep = pte_offset_kernel(pmd, adr); 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 long kvirt_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 long kvirt_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 long kvirt_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 void rvfree(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);}/********************************************************************** * /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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -