sn9c102_core.c
字号:
/*************************************************************************** * V4L2 driver for SN9C1xx PC Camera Controllers * * * * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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. * ***************************************************************************/#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/param.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/device.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/compiler.h>#include <linux/ioctl.h>#include <linux/poll.h>#include <linux/stat.h>#include <linux/mm.h>#include <linux/vmalloc.h>#include <linux/page-flags.h>#include <asm/byteorder.h>#include <asm/page.h>#include <asm/uaccess.h>#include "sn9c102.h"/*****************************************************************************/#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers"#define SN9C102_MODULE_ALIAS "sn9c1xx"#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"#define SN9C102_MODULE_LICENSE "GPL"#define SN9C102_MODULE_VERSION "1:1.47pre49"#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 47)/*****************************************************************************/MODULE_DEVICE_TABLE(usb, sn9c102_id_table);MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);MODULE_DESCRIPTION(SN9C102_MODULE_NAME);MODULE_ALIAS(SN9C102_MODULE_ALIAS);MODULE_VERSION(SN9C102_MODULE_VERSION);MODULE_LICENSE(SN9C102_MODULE_LICENSE);static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};module_param_array(video_nr, short, NULL, 0444);MODULE_PARM_DESC(video_nr, " <-1|n[,...]>" "\nSpecify V4L2 minor mode number." "\n-1 = use next available (default)" "\n n = use minor number n (integer >= 0)" "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) " cameras this way." "\nFor example:" "\nvideo_nr=-1,2,-1 would assign minor number 2 to" "\nthe second camera and use auto for the first" "\none and for every other camera." "\n");static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = SN9C102_FORCE_MUNMAP};module_param_array(force_munmap, bool, NULL, 0444);MODULE_PARM_DESC(force_munmap, " <0|1[,...]>" "\nForce the application to unmap previously" "\nmapped buffer memory before calling any VIDIOC_S_CROP or" "\nVIDIOC_S_FMT ioctl's. Not all the applications support" "\nthis feature. This parameter is specific for each" "\ndetected camera." "\n0 = do not force memory unmapping" "\n1 = force memory unmapping (save memory)" "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." "\n");static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = SN9C102_FRAME_TIMEOUT};module_param_array(frame_timeout, uint, NULL, 0644);MODULE_PARM_DESC(frame_timeout, " <0|n[,...]>" "\nTimeout for a video frame in seconds before" "\nreturning an I/O error; 0 for infinity." "\nThis parameter is specific for each detected camera." "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." "\n");#ifdef SN9C102_DEBUGstatic unsigned short debug = SN9C102_DEBUG_LEVEL;module_param(debug, ushort, 0644);MODULE_PARM_DESC(debug, " <n>" "\nDebugging information level, from 0 to 3:" "\n0 = none (use carefully)" "\n1 = critical errors" "\n2 = significant informations" "\n3 = more verbose messages" "\nLevel 3 is useful for testing only." "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." "\n");#endif/* Add the probe entries to this table. Be sure to add the entry in the right place, since, on failure, the next probing routine is called according to the order of the list below, from top to bottom.*/static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = { &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */ &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */};/*****************************************************************************/static u32sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, enum sn9c102_io_method io){ struct v4l2_pix_format* p = &(cam->sensor.pix_format); struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? (p->width * p->height * p->priv) / 8 : (r->width * r->height * p->priv) / 8; void* buff = NULL; u32 i; if (count > SN9C102_MAX_FRAMES) count = SN9C102_MAX_FRAMES; if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120) imagesize += 589 + 2; /* length of JPEG header + EOI marker */ cam->nbuffers = count; while (cam->nbuffers > 0) { if ((buff = vmalloc_32_user(cam->nbuffers * PAGE_ALIGN(imagesize)))) break; cam->nbuffers--; } for (i = 0; i < cam->nbuffers; i++) { cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); cam->frame[i].buf.index = i; cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); cam->frame[i].buf.length = imagesize; cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; cam->frame[i].buf.sequence = 0; cam->frame[i].buf.field = V4L2_FIELD_NONE; cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; cam->frame[i].buf.flags = 0; } return cam->nbuffers;}static void sn9c102_release_buffers(struct sn9c102_device* cam){ if (cam->nbuffers) { vfree(cam->frame[0].bufmem); cam->nbuffers = 0; } cam->frame_current = NULL;}static void sn9c102_empty_framequeues(struct sn9c102_device* cam){ u32 i; INIT_LIST_HEAD(&cam->inqueue); INIT_LIST_HEAD(&cam->outqueue); for (i = 0; i < SN9C102_MAX_FRAMES; i++) { cam->frame[i].state = F_UNUSED; cam->frame[i].buf.bytesused = 0; }}static void sn9c102_requeue_outqueue(struct sn9c102_device* cam){ struct sn9c102_frame_t *i; list_for_each_entry(i, &cam->outqueue, frame) { i->state = F_QUEUED; list_add(&i->frame, &cam->inqueue); } INIT_LIST_HEAD(&cam->outqueue);}static void sn9c102_queue_unusedframes(struct sn9c102_device* cam){ unsigned long lock_flags; u32 i; for (i = 0; i < cam->nbuffers; i++) if (cam->frame[i].state == F_UNUSED) { cam->frame[i].state = F_QUEUED; spin_lock_irqsave(&cam->queue_lock, lock_flags); list_add_tail(&cam->frame[i].frame, &cam->inqueue); spin_unlock_irqrestore(&cam->queue_lock, lock_flags); }}/*****************************************************************************//* Write a sequence of count value/register pairs. Returns -1 after the first failed write, or 0 for no errors.*/int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2], int count){ struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; int i, res; for (i = 0; i < count; i++) { u8 index = valreg[i][1]; /* index is a u8, so it must be <256 and can't be out of range. If we put in a check anyway, gcc annoys us with a warning hat our check is useless. People get all uppity when they see warnings in the kernel compile. */ *buff = valreg[i][0]; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) { DBG(3, "Failed to write a register (value 0x%02X, " "index 0x%02X, error %d)", *buff, index, res); return -1; } cam->reg[index] = *buff; } return 0;}int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index){ struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; int res; if (index >= ARRAY_SIZE(cam->reg)) return -1; *buff = value; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) { DBG(3, "Failed to write a register (value 0x%02X, index " "0x%02X, error %d)", value, index, res); return -1; } cam->reg[index] = value; return 0;}/* NOTE: with the SN9C10[123] reading some registers always returns 0 */int sn9c102_read_reg(struct sn9c102_device* cam, u16 index){ struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; int res; res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) DBG(3, "Failed to read a register (index 0x%02X, error %d)", index, res); return (res >= 0) ? (int)(*buff) : -1;}int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index){ if (index >= ARRAY_SIZE(cam->reg)) return -1; return cam->reg[index];}static intsn9c102_i2c_wait(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor){ int i, r; for (i = 1; i <= 5; i++) { r = sn9c102_read_reg(cam, 0x08); if (r < 0) return -EIO; if (r & 0x04) return 0; if (sensor->frequency & SN9C102_I2C_400KHZ) udelay(5*16); else udelay(16*16); } return -EBUSY;}static intsn9c102_i2c_detect_read_error(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor){ int r , err = 0; r = sn9c102_read_reg(cam, 0x08); if (r < 0) err += r; if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { if (!(r & 0x08)) err += -1; } else { if (r & 0x08) err += -1; } return err ? -EIO : 0;}static intsn9c102_i2c_detect_write_error(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor){ int r; r = sn9c102_read_reg(cam, 0x08); return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0;}intsn9c102_i2c_try_raw_read(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor, u8 data0, u8 data1, u8 n, u8 buffer[]){ struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; int i = 0, err = 0, res; /* Write cycle */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10; data[1] = data0; /* I2C slave id */ data[2] = data1; /* address */ data[7] = 0x10; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; err += sn9c102_i2c_wait(cam, sensor); /* Read cycle - n bytes */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | (n << 4) | 0x02; data[1] = data0; data[7] = 0x10; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; err += sn9c102_i2c_wait(cam, sensor); /* The first read byte will be placed in data[4] */ res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; err += sn9c102_i2c_detect_read_error(cam, sensor); PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1, data[4]); if (err) { DBG(3, "I2C read failed for %s image sensor", sensor->name); return -1; } if (buffer) for (i = 0; i < n && i < 5; i++) buffer[n-i-1] = data[4-i]; return (int)data[4];}intsn9c102_i2c_try_raw_write(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor, u8 n, u8 data0, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5){ struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; int err = 0, res; /* Write cycle. It usually is address + value */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | ((n - 1) << 4); data[1] = data0; data[2] = data1; data[3] = data2; data[4] = data3; data[5] = data4; data[6] = data5; data[7] = 0x17; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; err += sn9c102_i2c_wait(cam, sensor); err += sn9c102_i2c_detect_write_error(cam, sensor); if (err) DBG(3, "I2C write failed for %s image sensor", sensor->name); PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, " "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X", n, data0, data1, data2, data3, data4, data5); return err ? -1 : 0;}intsn9c102_i2c_try_read(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor, u8 address){ return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, address, 1, NULL);}static int sn9c102_i2c_try_write(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor, u8 address, u8 value){ return sn9c102_i2c_try_raw_write(cam, sensor, 3, sensor->i2c_slave_id, address, value, 0, 0, 0);}int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address){ return sn9c102_i2c_try_read(cam, &cam->sensor, address);}int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value){ return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);}/*****************************************************************************/static size_t sn9c102_sof_length(struct sn9c102_device* cam){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -