Commit f423b9a8 authored by Luca Risolia's avatar Luca Risolia Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (5474): SN9C1xx driver updates



@ Don't assume that SOF headers can't cross packets boundaries
@ Fix compression quality selection
+ Add support for MI-0360 image sensor
* Documentation updates
@ Fix sysfs
@ MI0343 rewritten
* HV7131R color fixes and add new ABLC control
* Rename the archive from "sn9c102" to "sn9c1xx"
* fix typos
* better support for TAS5110D
@ fix OV7630 wrong colors
@ Don't return an error if no input buffers are enqueued yet on VIDIOC_STREAMON
* Add informations about colorspaces
* More appropriate error codes in case of failure of some system calls
* More precise hardware detection
* Add more informations about supported hardware in the documentation
+ More supported devices
+ Add support for HV7131R image sensor

Signed-off-by: default avatarLuca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 9ab7e323
Loading
Loading
Loading
Loading
+38 −26
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ Index

1. Copyright
============
Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>
Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>


2. Disclaimer
@@ -216,10 +216,10 @@ Description: Debugging information level, from 0 to 3:
		1 = critical errors
		2 = significant informations
		3 = more verbose messages
		Level 3 is useful for testing only, when only one device
		is used. It also shows some more informations about the
		hardware being detected. This parameter can be changed at
		runtime thanks to the /sys filesystem interface.
		Level 3 is useful for testing only. It also shows some more
		informations about the hardware being detected.
		This parameter can be changed at runtime thanks to the /sys
		filesystem interface.
Default:        2
-------------------------------------------------------------------------------

@@ -235,7 +235,7 @@ created in the /sys/class/video4linux/videoX directory. You can set the green
channel's gain by writing the desired value to it. The value may range from 0
to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103,
SN9C105 and SN9C120 bridges.
Similarly, only for the SN9C103, SN9C105 and SN9120 controllers, blue and red
Similarly, only for the SN9C103, SN9C105 and SN9C120 controllers, blue and red
gain control files are available in the same directory, for which accepted
values may range from 0 to 127.

@@ -402,38 +402,49 @@ Vendor ID Product ID
0x0c45     0x60bc
0x0c45     0x60be
0x0c45     0x60c0
0x0c45     0x60c2
0x0c45     0x60c8
0x0c45     0x60cc
0x0c45     0x60ea
0x0c45     0x60ec
0x0c45     0x60ef
0x0c45     0x60fa
0x0c45     0x60fb
0x0c45     0x60fc
0x0c45     0x60fe
0x0c45     0x6102
0x0c45     0x6108
0x0c45     0x610f
0x0c45     0x6130
0x0c45     0x6138
0x0c45     0x613a
0x0c45     0x613b
0x0c45     0x613c
0x0c45     0x613e

The list above does not imply that all those devices work with this driver: up
until now only the ones that assemble the following image sensors are
supported; kernel messages will always tell you whether this is the case (see
"Module loading" paragraph):

Model       Manufacturer
-----       ------------
HV7131D     Hynix Semiconductor, Inc.
MI-0343     Micron Technology, Inc.
OV7630      OmniVision Technologies, Inc.
OV7660      OmniVision Technologies, Inc.
PAS106B     PixArt Imaging, Inc.
PAS202BCA   PixArt Imaging, Inc.
PAS202BCB   PixArt Imaging, Inc.
TAS5110C1B  Taiwan Advanced Sensor Corporation
TAS5130D1B  Taiwan Advanced Sensor Corporation

Some of the available control settings of each image sensor are supported
until now only the ones that assemble the following pairs of SN9C1xx bridges
and image sensors are supported; kernel messages will always tell you whether
this is the case (see "Module loading" paragraph):

Image sensor / SN9C1xx bridge      | SN9C10[12]  SN9C103  SN9C105  SN9C120
-------------------------------------------------------------------------------
HV7131D    Hynix Semiconductor     | Yes         No       No       No
HV7131R    Hynix Semiconductor     | No          Yes      Yes      Yes
MI-0343    Micron Technology       | Yes         No       No       No
MI-0360    Micron Technology       | No          Yes      No       No
OV7630     OmniVision Technologies | Yes         Yes      No       No
OV7660     OmniVision Technologies | No          No       Yes      Yes
PAS106B    PixArt Imaging          | Yes         No       No       No
PAS202B    PixArt Imaging          | Yes         Yes      No       No
TAS5110C1B Taiwan Advanced Sensor  | Yes         No       No       No
TAS5110D   Taiwan Advanced Sensor  | Yes         No       No       No
TAS5130D1B Taiwan Advanced Sensor  | Yes         No       No       No

"Yes" means that the pair is supported by the driver, while "No" means that the
pair does not exist or is not supported by the driver.

Only some of the available control settings of each image sensor are supported
through the V4L2 interface.

Donations of new models for further testing and support would be much
@@ -482,8 +493,8 @@ The SN9C1xx PC Camera Controllers can send images in two possible video
formats over the USB: either native "Sequential RGB Bayer" or compressed.
The compression is used to achieve high frame rates. With regard to the
SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding
algorithm described below, while the SN9C105 and SN9C120 the compression is
based on the JPEG standard.
algorithm described below, while with regard to the SN9C105 and SN9C120 the
compression is based on the JPEG standard.
The current video format may be selected or queried from the user application
by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2
API specifications.
@@ -573,4 +584,5 @@ order):
- Mizuno Takafumi for the donation of a webcam;
- an "anonymous" donator (who didn't want his name to be revealed) for the
  donation of a webcam.
- an anonymous donator for the donation of four webcams.
- an anonymous donator for the donation of four webcams and two boards with ten
  image sensors.
+1 −1
Original line number Diff line number Diff line
@@ -3606,7 +3606,7 @@ L: linux-usb-devel@lists.sourceforge.net
W:	http://www.connecttech.com
S:	Supported

USB SN9C10x DRIVER
USB SN9C1xx DRIVER
P:	Luca Risolia
M:	luca.risolia@studio.unibo.it
L:	linux-usb-devel@lists.sourceforge.net
+12 −5
Original line number Diff line number Diff line
sn9c102-objs    := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
		   sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \
		   sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
sn9c102-objs := sn9c102_core.o \
		sn9c102_hv7131d.o \
		sn9c102_hv7131r.o \
		sn9c102_mi0343.o \
		sn9c102_mi0360.o \
		sn9c102_ov7630.o \
		sn9c102_ov7660.o \
		sn9c102_pas106b.o \
		sn9c102_pas202bcb.o \
		sn9c102_tas5110c1b.o \
		sn9c102_tas5110d.o \
		sn9c102_tas5130d1b.o

obj-$(CONFIG_USB_SN9C102)       += sn9c102.o
+11 −6
Original line number Diff line number Diff line
@@ -78,8 +78,13 @@ enum sn9c102_stream_state {

typedef char sn9c102_sof_header_t[62];

struct sn9c102_sof_t {
	sn9c102_sof_header_t header;
	u16 bytesread;
};

struct sn9c102_sysfs_attr {
	u8 reg, i2c_reg;
	u16 reg, i2c_reg;
	sn9c102_sof_header_t frame_header;
};

@@ -112,7 +117,7 @@ struct sn9c102_device {
	struct v4l2_jpegcompression compression;

	struct sn9c102_sysfs_attr sysfs;
	sn9c102_sof_header_t sof_header;
	struct sn9c102_sof_t sof;
	u16 reg[384];

	struct sn9c102_module_param module_param;
@@ -182,8 +187,8 @@ do { \
		if ((level) == 1 || (level) == 2)                             \
			pr_info("sn9c102: " fmt "\n", ## args);               \
		else if ((level) == 3)                                        \
			pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__,  \
				 __LINE__ , ## args);                         \
			pr_debug("sn9c102: [%s:%d] " fmt "\n",                \
				 __FUNCTION__, __LINE__ , ## args);           \
	}                                                                     \
} while (0)
#else
@@ -194,8 +199,8 @@ do { \

#undef PDBG
#define PDBG(fmt, args...)                                                    \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",                              \
	 __FUNCTION__, __LINE__ , ## args)
dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
	 __LINE__ , ## args)

#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+123 −76
Original line number Diff line number Diff line
@@ -44,11 +44,12 @@
/*****************************************************************************/

#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C1xx PC Camera Controllers"
#define SN9C102_MODULE_AUTHOR   "(C) 2004-2006 Luca Risolia"
#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.34"
#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 34)
#define SN9C102_MODULE_VERSION  "1:1.39"
#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 39)

/*****************************************************************************/

@@ -56,6 +57,7 @@ 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);

@@ -106,8 +108,7 @@ MODULE_PARM_DESC(debug,
		 "\n1 = critical errors"
		 "\n2 = significant informations"
		 "\n3 = more verbose messages"
		 "\nLevel 3 is useful for testing only, when only "
		 "one device is used."
		 "\nLevel 3 is useful for testing only."
		 "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
		 "\n");
#endif
@@ -485,17 +486,42 @@ static size_t sn9c102_sof_length(struct sn9c102_device* cam)
static void*
sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
{
	char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
	size_t soflen = 0, i;
	const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
	const char *m = mem;
	size_t soflen = 0, i, j;

	soflen = sn9c102_sof_length(cam);

	for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
		if (!memcmp(mem + i, sof_header, sizeof(sof_header))) {
			memcpy(cam->sof_header, mem + i,
			       sizeof(sn9c102_sof_header_t));
				/* Skip the header */
				return mem + i + soflen;
	for (i = 0; i < len; i++) {
		size_t b;

		/* Read the variable part of the header */
		if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
			cam->sof.header[cam->sof.bytesread] = *(m+i);
			if (++cam->sof.bytesread == soflen) {
				cam->sof.bytesread = 0;
				return mem + i;
			}
			continue;
		}

		/* Search for the SOF marker (fixed part) in the header */
		for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
			if (unlikely(i+j) == len)
				return NULL;
			if (*(m+i+j) == marker[cam->sof.bytesread]) {
				cam->sof.header[cam->sof.bytesread] = *(m+i+j);
				if (++cam->sof.bytesread == sizeof(marker)) {
					PDBGG("Bytes to analyze: %zd. SOF "
					      "starts at byte #%zd", len, i);
					i += j+1;
					break;
				}
			} else {
				cam->sof.bytesread = 0;
				break;
			}
		}
	}

	return NULL;
@@ -513,10 +539,16 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
	};
	size_t i, j;

	/* The EOF header does not exist in compressed data */
	if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
	    cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
		return NULL; /* EOF header does not exist in compressed data */
		return NULL;

	/*
	   The EOF header might cross the packet boundary, but this is not a
	   problem, since the end of a frame is determined by checking its size
	   in the first place.
	*/
	for (i = 0; (len >= 4) && (i <= len - 4); i++)
		for (j = 0; j < ARRAY_SIZE(eof_header); j++)
			if (!memcmp(mem + i, eof_header[j], 4))
@@ -639,6 +671,7 @@ static void sn9c102_urb_complete(struct urb *urb)
		cam->stream = STREAM_OFF;
		if ((*f))
			(*f)->state = F_QUEUED;
		cam->sof.bytesread = 0;
		DBG(3, "Stream interrupted by application");
		wake_up(&cam->wait_stream);
	}
@@ -676,6 +709,7 @@ static void sn9c102_urb_complete(struct urb *urb)
		if (status) {
			DBG(3, "Error in isochronous frame");
			(*f)->state = F_ERROR;
			cam->sof.bytesread = 0;
			continue;
		}

@@ -697,8 +731,8 @@ static void sn9c102_urb_complete(struct urb *urb)
					b = (*f)->buf.bytesused + img -
					    imagesize;
					img = imagesize - (*f)->buf.bytesused;
					DBG(3, "Expected EOF not found: "
					       "video frame cut");
					PDBGG("Expected EOF not found: video "
					      "frame cut");
					if (eof)
						DBG(3, "Exceeded limit: +%u "
						       "bytes", (unsigned)(b));
@@ -719,11 +753,6 @@ static void sn9c102_urb_complete(struct urb *urb)
				      V4L2_PIX_FMT_JPEG) && eof)) {
					u32 b;

					if (cam->sensor.pix_format.pixelformat
					    == V4L2_PIX_FMT_JPEG)
						sn9c102_write_eoimarker(cam,
									(*f));

					b = (*f)->buf.bytesused;
					(*f)->state = F_DONE;
					(*f)->buf.sequence= ++cam->frame_count;
@@ -741,7 +770,7 @@ static void sn9c102_urb_complete(struct urb *urb)
					spin_unlock(&cam->queue_lock);

					memcpy(cam->sysfs.frame_header,
					       cam->sof_header, soflen);
					       cam->sof.header, soflen);

					DBG(3, "Video frame captured: %lu "
					       "bytes", (unsigned long)(b));
@@ -791,7 +820,13 @@ static void sn9c102_urb_complete(struct urb *urb)
				    V4L2_PIX_FMT_SN9C10X ||
				    cam->sensor.pix_format.pixelformat ==
				    V4L2_PIX_FMT_JPEG) {
					if (sof - pos >= soflen) {
						eof = sof - soflen;
					} else { /* remove header */
						eof = pos;
						(*f)->buf.bytesused -=
							(soflen - (sof - pos));
					}
					goto end_of_frame;
				} else {
					DBG(3, "SOF before expected EOF after "
@@ -878,6 +913,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
	}

	cam->frame_current = NULL;
	cam->sof.bytesread = 0;

	for (i = 0; i < SN9C102_URBS; i++) {
		err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
@@ -959,9 +995,9 @@ static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)

	if (len < 6) {
		strncpy(str, buff, len);
		str[len+1] = '\0';
		str[len] = '\0';
	} else {
		strncpy(str, buff, 4);
		strncpy(str, buff, 6);
		str[6] = '\0';
	}

@@ -1062,7 +1098,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)

	count = sprintf(buf, "%d\n", val);

	DBG(3, "Read bytes: %zd", count);
	DBG(3, "Read bytes: %zd, value: %d", count, val);

	mutex_unlock(&sn9c102_sysfs_lock);

@@ -1197,7 +1233,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)

	count = sprintf(buf, "%d\n", val);

	DBG(3, "Read bytes: %zd", count);
	DBG(3, "Read bytes: %zd, value: %d", count, val);

	mutex_unlock(&sn9c102_sysfs_lock);

@@ -1489,10 +1525,10 @@ sn9c102_set_compression(struct sn9c102_device* cam,
		if (compression->quality == 0) {
			for (i = 0; i <= 63; i++) {
				err += sn9c102_write_reg(cam,
							 SN9C102_Y_QTABLE0[i],
							 SN9C102_Y_QTABLE1[i],
							 0x100 + i);
				err += sn9c102_write_reg(cam,
							 SN9C102_UV_QTABLE0[i],
							 SN9C102_UV_QTABLE1[i],
							 0x140 + i);
			}
			err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
@@ -1597,9 +1633,13 @@ static int sn9c102_init(struct sn9c102_device* cam)
		if (cam->bridge == BRIDGE_SN9C101 ||
		    cam->bridge == BRIDGE_SN9C102 ||
		    cam->bridge == BRIDGE_SN9C103) {
			if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
				s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8;
			cam->compression.quality =  cam->reg[0x17] & 0x01 ?
						    0 : 1;
		} else {
			if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
				s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
			cam->compression.quality =  cam->reg[0x18] & 0x40 ?
						    0 : 1;
			err += sn9c102_set_compression(cam, &cam->compression);
@@ -1805,7 +1845,7 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
		DBG(3, "Close and open the device again to choose "
		       "the read method");
		mutex_unlock(&cam->fileop_mutex);
		return -EINVAL;
		return -EBUSY;
	}

	if (cam->io == IO_NONE) {
@@ -2001,7 +2041,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
		return -EIO;
	}

	if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
	if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
		mutex_unlock(&cam->fileop_mutex);
		return -EACCES;
	}

	if (cam->io != IO_MMAP ||
	    size != PAGE_ALIGN(cam->frame[0].buf.length)) {
		mutex_unlock(&cam->fileop_mutex);
		return -EINVAL;
@@ -2267,7 +2312,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
			if (cam->frame[i].vma_use_count) {
				DBG(3, "VIDIOC_S_CROP failed. "
				       "Unmap the buffers first.");
				return -EINVAL;
				return -EBUSY;
			}

	/* Preserve R,G or B origin */
@@ -2445,6 +2490,8 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;

	pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
			   V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
	pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
			      pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
			     ? 0 : (pfmt->width * pfmt->priv) / 8;
@@ -2533,7 +2580,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
		break;
	}
	pix->priv = pfmt->priv; /* bpp */
	pix->colorspace = pfmt->colorspace;
	pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
			  V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
	pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
			     pix->pixelformat == V4L2_PIX_FMT_JPEG)
			    ? 0 : (pix->width * pix->priv) / 8;
@@ -2551,7 +2599,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
			if (cam->frame[i].vma_use_count) {
				DBG(3, "VIDIOC_S_FMT failed. Unmap the "
				       "buffers first.");
				return -EINVAL;
				return -EBUSY;
			}

	if (cam->stream == STREAM_ON)
@@ -2666,14 +2714,14 @@ sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
	if (cam->io == IO_READ) {
		DBG(3, "Close and open the device again to choose the mmap "
		       "I/O method");
		return -EINVAL;
		return -EBUSY;
	}

	for (i = 0; i < cam->nbuffers; i++)
		if (cam->frame[i].vma_use_count) {
			DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
			       "still mapped.");
			return -EINVAL;
			return -EBUSY;
		}

	if (cam->stream == STREAM_ON)
@@ -2837,9 +2885,6 @@ sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
		return -EINVAL;

	if (list_empty(&cam->inqueue))
		return -EINVAL;

	cam->stream = STREAM_ON;

	DBG(3, "Stream on");
@@ -3166,8 +3211,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)

	r = sn9c102_read_reg(cam, 0x00);
	if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
		DBG(1, "Sorry, this is not a SN9C1xx based camera "
		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		DBG(1, "Sorry, this is not a SN9C1xx-based camera "
		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		err = -ENODEV;
		goto fail;
	}
@@ -3177,19 +3222,19 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
	case BRIDGE_SN9C101:
	case BRIDGE_SN9C102:
		DBG(2, "SN9C10[12] PC Camera Controller detected "
		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		break;
	case BRIDGE_SN9C103:
		DBG(2, "SN9C103 PC Camera Controller detected "
		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		break;
	case BRIDGE_SN9C105:
		DBG(2, "SN9C105 PC Camera Controller detected "
		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		break;
	case BRIDGE_SN9C120:
		DBG(2, "SN9C120 PC Camera Controller detected "
		       "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		       "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
		break;
	}

@@ -3260,6 +3305,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
		       "device controlling. Error #%d", err);
#else
	DBG(2, "Optional device control through 'sysfs' interface disabled");
	DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
	       "configuration option to enable it.");
#endif

	usb_set_intfdata(intf, cam);
Loading