aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/usb/pwc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 17:49:05 +0900
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 17:49:05 +0900
commit0b8e74c6f44094189dbe78baf4101acc7570c6af (patch)
tree6440561d09fb71ba5928664604ec92f29940be6b /drivers/media/usb/pwc
parent7f60ba388f5b9dd8b0da463b394412dace3ab814 (diff)
parentbd0d10498826ed150da5e4c45baf8b9c7088fb71 (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "The first part of the media updates for Kernel 3.7. This series contain: - A major tree renaming patch series: now, drivers are organized internally by their used bus, instead of by V4L2 and/or DVB API, providing a cleaner driver location for hybrid drivers that implement both APIs, and allowing to cleanup the Kconfig items and make them more intuitive for the end user; - Media Kernel developers are typically very lazy with their duties of keeping the MAINTAINERS entries for their drivers updated. As now the tree is more organized, we're doing an effort to add/update those entries for the drivers that aren't currently orphan; - Several DVB USB drivers got moved to a new DVB USB v2 core; the new core fixes several bugs (as the existing one that got bitroted). Now, suspend/resume finally started to work fine (at least with some devices - we should expect more work with regards to it); - added multistream support for DVB-T2, and unified the API for DVB-S2 and ISDB-S. Backward binary support is preserved; - as usual, a few new drivers, some V4L2 core improvements and lots of drivers improvements and fixes. There are some points to notice on this series: 1) you should expect a trivial merge conflict on your tree, with the removal of Documentation/feature-removal-schedule.txt: this series would be adding two additional entries there. I opted to not rebase it due to this recent change; 2) With regards to the PCTV 520e udev-related breakage, I opted to fix it in a way that the patches can be backported to 3.5 even without your firmware fix patch. This way, Greg doesn't need to rush backporting your patch (as there are still the firmware cache and firmware path customization issues to be addressed there). I'll send later a patch (likely after the end of the merge window) reverting the rest of the DRX-K async firmware request, fully restoring its original behaviour to allow media drivers to initialize everything serialized as before for 3.7 and upper. 3) I'm planning to work on this weekend to test the DMABUF patches for V4L2. The patches are on my queue for several Kernel cycles, but, up to now, there is/was no way to test the series locally. I have some concerns about this particular changeset with regards to security issues, and with regards to the replacement of the old VIDIOC_OVERLAY ioctl's that is broken on modern systems, due to GPU drivers change. The Overlay API allows direct PCI2PCI transfers from a media capture card into the GPU framebuffer, but its API is crappy. Also, the only existing X11 driver that implements it requires a XV extension that is not available anymore on modern drivers. The DMABUF can do the same thing, but with it is promising to be a properly-designed API. If I can successfully test this series and be happy with it, I should be asking you to pull them next week." * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (717 commits) em28xx: regression fix: use DRX-K sync firmware requests on em28xx drxk: allow loading firmware synchrousnously em28xx: Make all em28xx extensions to be initialized asynchronously [media] tda18271: properly report read errors in tda18271_get_id [media] tda18271: delay IR & RF calibration until init() if delay_cal is set [media] MAINTAINERS: add Michael Krufky as tda827x maintainer [media] MAINTAINERS: add Michael Krufky as tda8290 maintainer [media] MAINTAINERS: add Michael Krufky as cxusb maintainer [media] MAINTAINERS: add Michael Krufky as lg2160 maintainer [media] MAINTAINERS: add Michael Krufky as lgdt3305 maintainer [media] MAINTAINERS: add Michael Krufky as mxl111sf maintainer [media] MAINTAINERS: add Michael Krufky as mxl5007t maintainer [media] MAINTAINERS: add Michael Krufky as tda18271 maintainer [media] s5p-tv: Report only multi-plane capabilities in vidioc_querycap [media] s5p-mfc: Fix misplaced return statement in s5p_mfc_suspend() [media] exynos-gsc: Add missing static storage class specifiers [media] exynos-gsc: Remove <linux/version.h> header file inclusion [media] s5p-fimc: Fix incorrect condition in fimc_lite_reqbufs() [media] s5p-tv: Fix potential NULL pointer dereference error [media] s5k6aa: Fix possible NULL pointer dereference ...
Diffstat (limited to 'drivers/media/usb/pwc')
-rw-r--r--drivers/media/usb/pwc/Kconfig48
-rw-r--r--drivers/media/usb/pwc/Makefile4
-rw-r--r--drivers/media/usb/pwc/philips.txt236
-rw-r--r--drivers/media/usb/pwc/pwc-ctrl.c553
-rw-r--r--drivers/media/usb/pwc/pwc-dec1.c32
-rw-r--r--drivers/media/usb/pwc/pwc-dec1.h39
-rw-r--r--drivers/media/usb/pwc/pwc-dec23.c691
-rw-r--r--drivers/media/usb/pwc/pwc-dec23.h61
-rw-r--r--drivers/media/usb/pwc/pwc-if.c1164
-rw-r--r--drivers/media/usb/pwc/pwc-kiara.c892
-rw-r--r--drivers/media/usb/pwc/pwc-kiara.h48
-rw-r--r--drivers/media/usb/pwc/pwc-misc.c93
-rw-r--r--drivers/media/usb/pwc/pwc-nala.h66
-rw-r--r--drivers/media/usb/pwc/pwc-timon.c1448
-rw-r--r--drivers/media/usb/pwc/pwc-timon.h63
-rw-r--r--drivers/media/usb/pwc/pwc-uncompress.c107
-rw-r--r--drivers/media/usb/pwc/pwc-v4l.c1053
-rw-r--r--drivers/media/usb/pwc/pwc.h393
18 files changed, 6991 insertions, 0 deletions
diff --git a/drivers/media/usb/pwc/Kconfig b/drivers/media/usb/pwc/Kconfig
new file mode 100644
index 00000000000..d63d0a85003
--- /dev/null
+++ b/drivers/media/usb/pwc/Kconfig
@@ -0,0 +1,48 @@
+config USB_PWC
+ tristate "USB Philips Cameras"
+ depends on VIDEO_V4L2
+ select VIDEOBUF2_VMALLOC
+ ---help---
+ Say Y or M here if you want to use one of these Philips & OEM
+ webcams:
+ * Philips PCA645, PCA646
+ * Philips PCVC675, PCVC680, PCVC690
+ * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+ * Philips SPC900NC
+ * Askey VC010
+ * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
+ and 'Orbit'/'Sphere'
+ * Samsung MPC-C10, MPC-C30
+ * Creative Webcam 5, Pro Ex
+ * SOTEC Afina Eye
+ * Visionite VCS-UC300, VCS-UM100
+
+ The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
+ and never will be, but the 665 and 720/20 are supported by other
+ drivers.
+
+ Some newer logitech webcams are not handled by this driver but by the
+ Usb Video Class driver (linux-uvc).
+
+ The built-in microphone is enabled by selecting USB Audio support.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pwc.
+
+config USB_PWC_DEBUG
+ bool "USB Philips Cameras verbose debug"
+ depends on USB_PWC
+ help
+ Say Y here in order to have the pwc driver generate verbose debugging
+ messages.
+ A special module options 'trace' is used to control the verbosity.
+
+config USB_PWC_INPUT_EVDEV
+ bool "USB Philips Cameras input events device support"
+ default y
+ depends on USB_PWC && (USB_PWC=INPUT || INPUT=y)
+ ---help---
+ This option makes USB Philips cameras register the snapshot button as
+ an input device to report button events.
+
+ If you are in doubt, say Y.
diff --git a/drivers/media/usb/pwc/Makefile b/drivers/media/usb/pwc/Makefile
new file mode 100644
index 00000000000..d7fdbcb9edd
--- /dev/null
+++ b/drivers/media/usb/pwc/Makefile
@@ -0,0 +1,4 @@
+pwc-objs += pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
+pwc-objs += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
+
+obj-$(CONFIG_USB_PWC) += pwc.o
diff --git a/drivers/media/usb/pwc/philips.txt b/drivers/media/usb/pwc/philips.txt
new file mode 100644
index 00000000000..d38dd791511
--- /dev/null
+++ b/drivers/media/usb/pwc/philips.txt
@@ -0,0 +1,236 @@
+This file contains some additional information for the Philips and OEM webcams.
+E-mail: webcam@smcc.demon.nl Last updated: 2004-01-19
+Site: http://www.smcc.demon.nl/webcam/
+
+As of this moment, the following cameras are supported:
+ * Philips PCA645
+ * Philips PCA646
+ * Philips PCVC675
+ * Philips PCVC680
+ * Philips PCVC690
+ * Philips PCVC720/40
+ * Philips PCVC730
+ * Philips PCVC740
+ * Philips PCVC750
+ * Askey VC010
+ * Creative Labs Webcam 5
+ * Creative Labs Webcam Pro Ex
+ * Logitech QuickCam 3000 Pro
+ * Logitech QuickCam 4000 Pro
+ * Logitech QuickCam Notebook Pro
+ * Logitech QuickCam Zoom
+ * Logitech QuickCam Orbit
+ * Logitech QuickCam Sphere
+ * Samsung MPC-C10
+ * Samsung MPC-C30
+ * Sotec Afina Eye
+ * AME CU-001
+ * Visionite VCS-UM100
+ * Visionite VCS-UC300
+
+The main webpage for the Philips driver is at the address above. It contains
+a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
+contains decompression routines that allow you to use higher image sizes and
+framerates; in addition the webcam uses less bandwidth on the USB bus (handy
+if you want to run more than 1 camera simultaneously). These routines fall
+under a NDA, and may therefore not be distributed as source; however, its use
+is completely optional.
+
+You can build this code either into your kernel, or as a module. I recommend
+the latter, since it makes troubleshooting a lot easier. The built-in
+microphone is supported through the USB Audio class.
+
+When you load the module you can set some default settings for the
+camera; some programs depend on a particular image-size or -format and
+don't know how to set it properly in the driver. The options are:
+
+size
+ Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
+ 'vga', for an image size of resp. 128x96, 160x120, 176x144,
+ 320x240, 352x288 and 640x480 (of course, only for those cameras that
+ support these resolutions).
+
+fps
+ Specifies the desired framerate. Is an integer in the range of 4-30.
+
+fbufs
+ This parameter specifies the number of internal buffers to use for storing
+ frames from the cam. This will help if the process that reads images from
+ the cam is a bit slow or momentarily busy. However, on slow machines it
+ only introduces lag, so choose carefully. The default is 3, which is
+ reasonable. You can set it between 2 and 5.
+
+mbufs
+ This is an integer between 1 and 10. It will tell the module the number of
+ buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
+ The default is 2, which is adequate for most applications (double
+ buffering).
+
+ Should you experience a lot of 'Dumping frame...' messages during
+ grabbing with a tool that uses mmap(), you might want to increase if.
+ However, it doesn't really buffer images, it just gives you a bit more
+ slack when your program is behind. But you need a multi-threaded or
+ forked program to really take advantage of these buffers.
+
+ The absolute maximum is 10, but don't set it too high! Every buffer takes
+ up 460 KB of RAM, so unless you have a lot of memory setting this to
+ something more than 4 is an absolute waste. This memory is only
+ allocated during open(), so nothing is wasted when the camera is not in
+ use.
+
+power_save
+ When power_save is enabled (set to 1), the module will try to shut down
+ the cam on close() and re-activate on open(). This will save power and
+ turn off the LED. Not all cameras support this though (the 645 and 646
+ don't have power saving at all), and some models don't work either (they
+ will shut down, but never wake up). Consider this experimental. By
+ default this option is disabled.
+
+compression (only useful with the plugin)
+ With this option you can control the compression factor that the camera
+ uses to squeeze the image through the USB bus. You can set the
+ parameter between 0 and 3:
+ 0 = prefer uncompressed images; if the requested mode is not available
+ in an uncompressed format, the driver will silently switch to low
+ compression.
+ 1 = low compression.
+ 2 = medium compression.
+ 3 = high compression.
+
+ High compression takes less bandwidth of course, but it could also
+ introduce some unwanted artefacts. The default is 2, medium compression.
+ See the FAQ on the website for an overview of which modes require
+ compression.
+
+ The compression parameter does not apply to the 645 and 646 cameras
+ and OEM models derived from those (only a few). Most cams honour this
+ parameter.
+
+leds
+ This settings takes 2 integers, that define the on/off time for the LED
+ (in milliseconds). One of the interesting things that you can do with
+ this is let the LED blink while the camera is in use. This:
+
+ leds=500,500
+
+ will blink the LED once every second. But with:
+
+ leds=0,0
+
+ the LED never goes on, making it suitable for silent surveillance.
+
+ By default the camera's LED is on solid while in use, and turned off
+ when the camera is not used anymore.
+
+ This parameter works only with the ToUCam range of cameras (720, 730, 740,
+ 750) and OEMs. For other cameras this command is silently ignored, and
+ the LED cannot be controlled.
+
+ Finally: this parameters does not take effect UNTIL the first time you
+ open the camera device. Until then, the LED remains on.
+
+dev_hint
+ A long standing problem with USB devices is their dynamic nature: you
+ never know what device a camera gets assigned; it depends on module load
+ order, the hub configuration, the order in which devices are plugged in,
+ and the phase of the moon (i.e. it can be random). With this option you
+ can give the driver a hint as to what video device node (/dev/videoX) it
+ should use with a specific camera. This is also handy if you have two
+ cameras of the same model.
+
+ A camera is specified by its type (the number from the camera model,
+ like PCA645, PCVC750VC, etc) and optionally the serial number (visible
+ in /proc/bus/usb/devices). A hint consists of a string with the following
+ format:
+
+ [type[.serialnumber]:]node
+
+ The square brackets mean that both the type and the serialnumber are
+ optional, but a serialnumber cannot be specified without a type (which
+ would be rather pointless). The serialnumber is separated from the type
+ by a '.'; the node number by a ':'.
+
+ This somewhat cryptic syntax is best explained by a few examples:
+
+ dev_hint=3,5 The first detected cam gets assigned
+ /dev/video3, the second /dev/video5. Any
+ other cameras will get the first free
+ available slot (see below).
+
+ dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1,
+ and a PCVC680 /dev/video2.
+
+ dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
+ 0123 goes to /dev/video3, the same
+ camera model with the 4567 serial
+ gets /dev/video0.
+
+ dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the
+ next 3 Philips cams will use /dev/video4
+ through /dev/video6.
+
+ Some points worth knowing:
+ - Serialnumbers are case sensitive and must be written full, including
+ leading zeroes (it's treated as a string).
+ - If a device node is already occupied, registration will fail and
+ the webcam is not available.
+ - You can have up to 64 video devices; be sure to make enough device
+ nodes in /dev if you want to spread the numbers.
+ After /dev/video9 comes /dev/video10 (not /dev/videoA).
+ - If a camera does not match any dev_hint, it will simply get assigned
+ the first available device node, just as it used to be.
+
+trace
+ In order to better detect problems, it is now possible to turn on a
+ 'trace' of some of the calls the module makes; it logs all items in your
+ kernel log at debug level.
+
+ The trace variable is a bitmask; each bit represents a certain feature.
+ If you want to trace something, look up the bit value(s) in the table
+ below, add the values together and supply that to the trace variable.
+
+ Value Value Description Default
+ (dec) (hex)
+ 1 0x1 Module initialization; this will log messages On
+ while loading and unloading the module
+
+ 2 0x2 probe() and disconnect() traces On
+
+ 4 0x4 Trace open() and close() calls Off
+
+ 8 0x8 read(), mmap() and associated ioctl() calls Off
+
+ 16 0x10 Memory allocation of buffers, etc. Off
+
+ 32 0x20 Showing underflow, overflow and Dumping frame On
+ messages
+
+ 64 0x40 Show viewport and image sizes Off
+
+ 128 0x80 PWCX debugging Off
+
+ For example, to trace the open() & read() functions, sum 8 + 4 = 12,
+ so you would supply trace=12 during insmod or modprobe. If
+ you want to turn the initialization and probing tracing off, set trace=0.
+ The default value for trace is 35 (0x23).
+
+
+
+Example:
+
+ # modprobe pwc size=cif fps=15 power_save=1
+
+The fbufs, mbufs and trace parameters are global and apply to all connected
+cameras. Each camera has its own set of buffers.
+
+size and fps only specify defaults when you open() the device; this is to
+accommodate some tools that don't set the size. You can change these
+settings after open() with the Video4Linux ioctl() calls. The default of
+defaults is QCIF size at 10 fps.
+
+The compression parameter is semiglobal; it sets the initial compression
+preference for all camera's, but this parameter can be set per camera with
+the VIDIOCPWCSCQUAL ioctl() call.
+
+All parameters are optional.
+
diff --git a/drivers/media/usb/pwc/pwc-ctrl.c b/drivers/media/usb/pwc/pwc-ctrl.c
new file mode 100644
index 00000000000..1f506fde97d
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-ctrl.c
@@ -0,0 +1,553 @@
+/* Driver for Philips webcam
+ Functions that send various control messages to the webcam, including
+ video modes.
+ (C) 1999-2003 Nemosoft Unv.
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+ (C) 2011 Hans de Goede <hdegoede@redhat.com>
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ Changes
+ 2001/08/03 Alvarado Added methods for changing white balance and
+ red/green gains
+ */
+
+/* Control functions for the cam; brightness, contrast, video mode, etc. */
+
+#ifdef __KERNEL__
+#include <asm/uaccess.h>
+#endif
+#include <asm/errno.h>
+
+#include "pwc.h"
+#include "pwc-kiara.h"
+#include "pwc-timon.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+/* Selectors for status controls used only in this file */
+#define GET_STATUS_B00 0x0B00
+#define SENSOR_TYPE_FORMATTER1 0x0C00
+#define GET_STATUS_3000 0x3000
+#define READ_RAW_Y_MEAN_FORMATTER 0x3100
+#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
+#define MIRROR_IMAGE_FORMATTER 0x3300
+#define LED_FORMATTER 0x3400
+#define LOWLIGHT 0x3500
+#define GET_STATUS_3600 0x3600
+#define SENSOR_TYPE_FORMATTER2 0x3700
+#define GET_STATUS_3800 0x3800
+#define GET_STATUS_4000 0x4000
+#define GET_STATUS_4100 0x4100 /* Get */
+#define CTL_STATUS_4200 0x4200 /* [GS] 1 */
+
+/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
+#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
+
+static const char *size2name[PSZ_MAX] =
+{
+ "subQCIF",
+ "QSIF",
+ "QCIF",
+ "SIF",
+ "CIF",
+ "VGA",
+};
+
+/********/
+
+/* Entries for the Nala (645/646) camera; the Nala doesn't have compression
+ preferences, so you either get compressed or non-compressed streams.
+
+ An alternate value of 0 means this mode is not available at all.
+ */
+
+#define PWC_FPS_MAX_NALA 8
+
+struct Nala_table_entry {
+ char alternate; /* USB alternate setting */
+ int compressed; /* Compressed yes/no */
+
+ unsigned char mode[3]; /* precomputed mode table */
+};
+
+static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
+
+static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
+{
+#include "pwc-nala.h"
+};
+
+/****************************************************************************/
+
+static int recv_control_msg(struct pwc_device *pdev,
+ u8 request, u16 value, int recv_count)
+{
+ int rc;
+
+ rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ request,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, pdev->vcinterface,
+ pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
+ if (rc < 0)
+ PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
+ rc, request, value);
+ return rc;
+}
+
+static inline int send_video_command(struct pwc_device *pdev,
+ int index, const unsigned char *buf, int buflen)
+{
+ int rc;
+
+ memcpy(pdev->ctrl_buf, buf, buflen);
+
+ rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_EP_STREAM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ VIDEO_OUTPUT_CONTROL_FORMATTER, index,
+ pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
+ if (rc >= 0)
+ memcpy(pdev->cmd_buf, buf, buflen);
+ else
+ PWC_ERROR("send_video_command error %d\n", rc);
+
+ return rc;
+}
+
+int send_control_msg(struct pwc_device *pdev,
+ u8 request, u16 value, void *buf, int buflen)
+{
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ request,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, pdev->vcinterface,
+ buf, buflen, USB_CTRL_SET_TIMEOUT);
+}
+
+static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
+ int frames, int *compression, int send_to_cam)
+{
+ int fps, ret = 0;
+ struct Nala_table_entry *pEntry;
+ int frames2frames[31] =
+ { /* closest match of framerate */
+ 0, 0, 0, 0, 4, /* 0-4 */
+ 5, 5, 7, 7, 10, /* 5-9 */
+ 10, 10, 12, 12, 15, /* 10-14 */
+ 15, 15, 15, 20, 20, /* 15-19 */
+ 20, 20, 20, 24, 24, /* 20-24 */
+ 24, 24, 24, 24, 24, /* 25-29 */
+ 24 /* 30 */
+ };
+ int frames2table[31] =
+ { 0, 0, 0, 0, 0, /* 0-4 */
+ 1, 1, 1, 2, 2, /* 5-9 */
+ 3, 3, 4, 4, 4, /* 10-14 */
+ 5, 5, 5, 5, 5, /* 15-19 */
+ 6, 6, 6, 6, 7, /* 20-24 */
+ 7, 7, 7, 7, 7, /* 25-29 */
+ 7 /* 30 */
+ };
+
+ if (size < 0 || size > PSZ_CIF)
+ return -EINVAL;
+ if (frames < 4)
+ frames = 4;
+ else if (frames > 25)
+ frames = 25;
+ frames = frames2frames[frames];
+ fps = frames2table[frames];
+ pEntry = &Nala_table[size][fps];
+ if (pEntry->alternate == 0)
+ return -EINVAL;
+
+ if (send_to_cam)
+ ret = send_video_command(pdev, pdev->vendpoint,
+ pEntry->mode, 3);
+ if (ret < 0)
+ return ret;
+
+ if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
+ pwc_dec1_init(pdev, pEntry->mode);
+
+ /* Set various parameters */
+ pdev->pixfmt = pixfmt;
+ pdev->vframes = frames;
+ pdev->valternate = pEntry->alternate;
+ pdev->width = pwc_image_sizes[size][0];
+ pdev->height = pwc_image_sizes[size][1];
+ pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
+ if (pEntry->compressed) {
+ if (pdev->release < 5) { /* 4 fold compression */
+ pdev->vbandlength = 528;
+ pdev->frame_size /= 4;
+ }
+ else {
+ pdev->vbandlength = 704;
+ pdev->frame_size /= 3;
+ }
+ }
+ else
+ pdev->vbandlength = 0;
+
+ /* Let pwc-if.c:isoc_init know we don't support higher compression */
+ *compression = 3;
+
+ return 0;
+}
+
+
+static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
+ int frames, int *compression, int send_to_cam)
+{
+ const struct Timon_table_entry *pChoose;
+ int fps, ret = 0;
+
+ if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
+ return -EINVAL;
+ if (frames < 5)
+ frames = 5;
+ else if (size == PSZ_VGA && frames > 15)
+ frames = 15;
+ else if (frames > 30)
+ frames = 30;
+ fps = (frames / 5) - 1;
+
+ /* Find a supported framerate with progressively higher compression */
+ pChoose = NULL;
+ while (*compression <= 3) {
+ pChoose = &Timon_table[size][fps][*compression];
+ if (pChoose->alternate != 0)
+ break;
+ (*compression)++;
+ }
+ if (pChoose == NULL || pChoose->alternate == 0)
+ return -ENOENT; /* Not supported. */
+
+ if (send_to_cam)
+ ret = send_video_command(pdev, pdev->vendpoint,
+ pChoose->mode, 13);
+ if (ret < 0)
+ return ret;
+
+ if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+ pwc_dec23_init(pdev, pChoose->mode);
+
+ /* Set various parameters */
+ pdev->pixfmt = pixfmt;
+ pdev->vframes = (fps + 1) * 5;
+ pdev->valternate = pChoose->alternate;
+ pdev->width = pwc_image_sizes[size][0];
+ pdev->height = pwc_image_sizes[size][1];
+ pdev->vbandlength = pChoose->bandlength;
+ if (pChoose->bandlength > 0)
+ pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
+ else
+ pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
+ return 0;
+}
+
+
+static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
+ int frames, int *compression, int send_to_cam)
+{
+ const struct Kiara_table_entry *pChoose = NULL;
+ int fps, ret = 0;
+
+ if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
+ return -EINVAL;
+ if (frames < 5)
+ frames = 5;
+ else if (size == PSZ_VGA && frames > 15)
+ frames = 15;
+ else if (frames > 30)
+ frames = 30;
+ fps = (frames / 5) - 1;
+
+ /* Find a supported framerate with progressively higher compression */
+ while (*compression <= 3) {
+ pChoose = &Kiara_table[size][fps][*compression];
+ if (pChoose->alternate != 0)
+ break;
+ (*compression)++;
+ }
+ if (pChoose == NULL || pChoose->alternate == 0)
+ return -ENOENT; /* Not supported. */
+
+ /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
+ if (send_to_cam)
+ ret = send_video_command(pdev, 4, pChoose->mode, 12);
+ if (ret < 0)
+ return ret;
+
+ if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+ pwc_dec23_init(pdev, pChoose->mode);
+
+ /* All set and go */
+ pdev->pixfmt = pixfmt;
+ pdev->vframes = (fps + 1) * 5;
+ pdev->valternate = pChoose->alternate;
+ pdev->width = pwc_image_sizes[size][0];
+ pdev->height = pwc_image_sizes[size][1];
+ pdev->vbandlength = pChoose->bandlength;
+ if (pdev->vbandlength > 0)
+ pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
+ else
+ pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
+ PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
+ pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
+ return 0;
+}
+
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
+ int pixfmt, int frames, int *compression, int send_to_cam)
+{
+ int ret, size;
+
+ PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
+ width, height, frames, pixfmt);
+ size = pwc_get_size(pdev, width, height);
+ PWC_TRACE("decode_size = %d.\n", size);
+
+ if (DEVICE_USE_CODEC1(pdev->type)) {
+ ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
+ compression, send_to_cam);
+ } else if (DEVICE_USE_CODEC3(pdev->type)) {
+ ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
+ compression, send_to_cam);
+ } else {
+ ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
+ compression, send_to_cam);
+ }
+ if (ret < 0) {
+ PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
+ return ret;
+ }
+ pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
+ PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
+ return 0;
+}
+
+static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
+{
+ unsigned int i;
+
+ for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
+ if (Nala_table[size][i].alternate) {
+ if (index--==0) return Nala_fps_vector[i];
+ }
+ }
+ return 0;
+}
+
+static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
+{
+ unsigned int i;
+
+ for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
+ if (Kiara_table[size][i][3].alternate) {
+ if (index--==0) return Kiara_fps_vector[i];
+ }
+ }
+ return 0;
+}
+
+static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
+{
+ unsigned int i;
+
+ for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
+ if (Timon_table[size][i][3].alternate) {
+ if (index--==0) return Timon_fps_vector[i];
+ }
+ }
+ return 0;
+}
+
+unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
+{
+ unsigned int ret;
+
+ if (DEVICE_USE_CODEC1(pdev->type)) {
+ ret = pwc_get_fps_Nala(pdev, index, size);
+
+ } else if (DEVICE_USE_CODEC3(pdev->type)) {
+ ret = pwc_get_fps_Kiara(pdev, index, size);
+
+ } else {
+ ret = pwc_get_fps_Timon(pdev, index, size);
+ }
+
+ return ret;
+}
+
+int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
+{
+ int ret;
+
+ ret = recv_control_msg(pdev, request, value, 1);
+ if (ret < 0)
+ return ret;
+
+ *data = pdev->ctrl_buf[0];
+ return 0;
+}
+
+int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
+{
+ int ret;
+
+ pdev->ctrl_buf[0] = data;
+ ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
+{
+ int ret;
+
+ ret = recv_control_msg(pdev, request, value, 1);
+ if (ret < 0)
+ return ret;
+
+ *data = ((s8 *)pdev->ctrl_buf)[0];
+ return 0;
+}
+
+int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
+{
+ int ret;
+
+ ret = recv_control_msg(pdev, request, value, 2);
+ if (ret < 0)
+ return ret;
+
+ *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
+ return 0;
+}
+
+int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
+{
+ int ret;
+
+ pdev->ctrl_buf[0] = data & 0xff;
+ pdev->ctrl_buf[1] = data >> 8;
+ ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
+{
+ int ret;
+
+ ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/* POWER */
+void pwc_camera_power(struct pwc_device *pdev, int power)
+{
+ int r;
+
+ if (!pdev->power_save)
+ return;
+
+ if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
+ return; /* Not supported by Nala or Timon < release 6 */
+
+ if (power)
+ pdev->ctrl_buf[0] = 0x00; /* active */
+ else
+ pdev->ctrl_buf[0] = 0xFF; /* power save */
+ r = send_control_msg(pdev, SET_STATUS_CTL,
+ SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
+ if (r < 0)
+ PWC_ERROR("Failed to power %s camera (%d)\n",
+ power ? "on" : "off", r);
+}
+
+int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
+{
+ int r;
+
+ if (pdev->type < 730)
+ return 0;
+ on_value /= 100;
+ off_value /= 100;
+ if (on_value < 0)
+ on_value = 0;
+ if (on_value > 0xff)
+ on_value = 0xff;
+ if (off_value < 0)
+ off_value = 0;
+ if (off_value > 0xff)
+ off_value = 0xff;
+
+ pdev->ctrl_buf[0] = on_value;
+ pdev->ctrl_buf[1] = off_value;
+
+ r = send_control_msg(pdev,
+ SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
+ if (r < 0)
+ PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
+
+ return r;
+}
+
+#ifdef CONFIG_USB_PWC_DEBUG
+int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
+{
+ int ret = -1, request;
+
+ if (pdev->type < 675)
+ request = SENSOR_TYPE_FORMATTER1;
+ else if (pdev->type < 730)
+ return -1; /* The Vesta series doesn't have this call */
+ else
+ request = SENSOR_TYPE_FORMATTER2;
+
+ ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
+ if (ret < 0)
+ return ret;
+ if (pdev->type < 675)
+ *sensor = pdev->ctrl_buf[0] | 0x100;
+ else
+ *sensor = pdev->ctrl_buf[0];
+ return 0;
+}
+#endif
diff --git a/drivers/media/usb/pwc/pwc-dec1.c b/drivers/media/usb/pwc/pwc-dec1.c
new file mode 100644
index 00000000000..e899036aadf
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-dec1.c
@@ -0,0 +1,32 @@
+/* Linux driver for Philips webcam
+ Decompression for chipset version 1
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include "pwc.h"
+
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd)
+{
+ struct pwc_dec1_private *pdec = &pdev->dec1;
+
+ pdec->version = pdev->release;
+}
diff --git a/drivers/media/usb/pwc/pwc-dec1.h b/drivers/media/usb/pwc/pwc-dec1.h
new file mode 100644
index 00000000000..c565ef8f52f
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-dec1.h
@@ -0,0 +1,39 @@
+/* Linux driver for Philips webcam
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef PWC_DEC1_H
+#define PWC_DEC1_H
+
+#include <linux/mutex.h>
+
+struct pwc_device;
+
+struct pwc_dec1_private
+{
+ int version;
+};
+
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd);
+
+#endif
diff --git a/drivers/media/usb/pwc/pwc-dec23.c b/drivers/media/usb/pwc/pwc-dec23.c
new file mode 100644
index 00000000000..3792fedff95
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-dec23.c
@@ -0,0 +1,691 @@
+/* Linux driver for Philips webcam
+ Decompression for chipset version 2 et 3
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "pwc-timon.h"
+#include "pwc-kiara.h"
+#include "pwc-dec23.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/*
+ * USE_LOOKUP_TABLE_TO_CLAMP
+ * 0: use a C version of this tests: { a<0?0:(a>255?255:a) }
+ * 1: use a faster lookup table for cpu with a big cache (intel)
+ */
+#define USE_LOOKUP_TABLE_TO_CLAMP 1
+/*
+ * UNROLL_LOOP_FOR_COPYING_BLOCK
+ * 0: use a loop for a smaller code (but little slower)
+ * 1: when unrolling the loop, gcc produces some faster code (perhaps only
+ * valid for intel processor class). Activating this option, automaticaly
+ * activate USE_LOOKUP_TABLE_TO_CLAMP
+ */
+#define UNROLL_LOOP_FOR_COPY 1
+#if UNROLL_LOOP_FOR_COPY
+# undef USE_LOOKUP_TABLE_TO_CLAMP
+# define USE_LOOKUP_TABLE_TO_CLAMP 1
+#endif
+
+static void build_subblock_pattern(struct pwc_dec23_private *pdec)
+{
+ static const unsigned int initial_values[12] = {
+ -0x526500, -0x221200, 0x221200, 0x526500,
+ -0x3de200, 0x3de200,
+ -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
+ -0x12c200, 0x12c200
+
+ };
+ static const unsigned int values_derivated[12] = {
+ 0xa4ca, 0x4424, -0x4424, -0xa4ca,
+ 0x7bc4, -0x7bc4,
+ 0xdb69, 0x5aba, -0x5aba, -0xdb69,
+ 0x2584, -0x2584
+ };
+ unsigned int temp_values[12];
+ int i, j;
+
+ memcpy(temp_values, initial_values, sizeof(initial_values));
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 12; j++) {
+ pdec->table_subblock[i][j] = temp_values[j];
+ temp_values[j] += values_derivated[j];
+ }
+ }
+}
+
+static void build_bit_powermask_table(struct pwc_dec23_private *pdec)
+{
+ unsigned char *p;
+ unsigned int bit, byte, mask, val;
+ unsigned int bitpower = 1;
+
+ for (bit = 0; bit < 8; bit++) {
+ mask = bitpower - 1;
+ p = pdec->table_bitpowermask[bit];
+ for (byte = 0; byte < 256; byte++) {
+ val = (byte & mask);
+ if (byte & bitpower)
+ val = -val;
+ *p++ = val;
+ }
+ bitpower<<=1;
+ }
+}
+
+
+static void build_table_color(const unsigned int romtable[16][8],
+ unsigned char p0004[16][1024],
+ unsigned char p8004[16][256])
+{
+ int compression_mode, j, k, bit, pw;
+ unsigned char *p0, *p8;
+ const unsigned int *r;
+
+ /* We have 16 compressions tables */
+ for (compression_mode = 0; compression_mode < 16; compression_mode++) {
+ p0 = p0004[compression_mode];
+ p8 = p8004[compression_mode];
+ r = romtable[compression_mode];
+
+ for (j = 0; j < 8; j++, r++, p0 += 128) {
+
+ for (k = 0; k < 16; k++) {
+ if (k == 0)
+ bit = 1;
+ else if (k >= 1 && k < 3)
+ bit = (r[0] >> 15) & 7;
+ else if (k >= 3 && k < 6)
+ bit = (r[0] >> 12) & 7;
+ else if (k >= 6 && k < 10)
+ bit = (r[0] >> 9) & 7;
+ else if (k >= 10 && k < 13)
+ bit = (r[0] >> 6) & 7;
+ else if (k >= 13 && k < 15)
+ bit = (r[0] >> 3) & 7;
+ else
+ bit = (r[0]) & 7;
+ if (k == 0)
+ *p8++ = 8;
+ else
+ *p8++ = j - bit;
+ *p8++ = bit;
+
+ pw = 1 << bit;
+ p0[k + 0x00] = (1 * pw) + 0x80;
+ p0[k + 0x10] = (2 * pw) + 0x80;
+ p0[k + 0x20] = (3 * pw) + 0x80;
+ p0[k + 0x30] = (4 * pw) + 0x80;
+ p0[k + 0x40] = (-1 * pw) + 0x80;
+ p0[k + 0x50] = (-2 * pw) + 0x80;
+ p0[k + 0x60] = (-3 * pw) + 0x80;
+ p0[k + 0x70] = (-4 * pw) + 0x80;
+ } /* end of for (k=0; k<16; k++, p8++) */
+ } /* end of for (j=0; j<8; j++ , table++) */
+ } /* end of foreach compression_mode */
+}
+
+/*
+ *
+ */
+static void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
+{
+#define SCALEBITS 15
+#define ONE_HALF (1UL << (SCALEBITS - 1))
+ int i;
+ unsigned int offset1 = ONE_HALF;
+ unsigned int offset2 = 0x0000;
+
+ for (i=0; i<256; i++) {
+ pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
+ pdec->table_d800[i] = offset2;
+
+ offset1 += 0x7bc4;
+ offset2 += 0x7bc4;
+ }
+}
+
+/*
+ * To decode the stream:
+ * if look_bits(2) == 0: # op == 2 in the lookup table
+ * skip_bits(2)
+ * end of the stream
+ * elif look_bits(3) == 7: # op == 1 in the lookup table
+ * skip_bits(3)
+ * yyyy = get_bits(4)
+ * xxxx = get_bits(8)
+ * else: # op == 0 in the lookup table
+ * skip_bits(x)
+ *
+ * For speedup processing, we build a lookup table and we takes the first 6 bits.
+ *
+ * struct {
+ * unsigned char op; // operation to execute
+ * unsigned char bits; // bits use to perform operation
+ * unsigned char offset1; // offset to add to access in the table_0004 % 16
+ * unsigned char offset2; // offset to add to access in the table_0004
+ * }
+ *
+ * How to build this table ?
+ * op == 2 when (i%4)==0
+ * op == 1 when (i%8)==7
+ * op == 0 otherwise
+ *
+ */
+static const unsigned char hash_table_ops[64*4] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x04, 0x01, 0x10,
+ 0x00, 0x06, 0x01, 0x30,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x40,
+ 0x00, 0x05, 0x01, 0x20,
+ 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x04, 0x01, 0x50,
+ 0x00, 0x05, 0x02, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x40,
+ 0x00, 0x05, 0x03, 0x00,
+ 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x04, 0x01, 0x10,
+ 0x00, 0x06, 0x02, 0x10,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x40,
+ 0x00, 0x05, 0x01, 0x60,
+ 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x04, 0x01, 0x50,
+ 0x00, 0x05, 0x02, 0x40,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x40,
+ 0x00, 0x05, 0x03, 0x40,
+ 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x04, 0x01, 0x10,
+ 0x00, 0x06, 0x01, 0x70,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x40,
+ 0x00, 0x05, 0x01, 0x20,
+ 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x04, 0x01, 0x50,
+ 0x00, 0x05, 0x02, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x40,
+ 0x00, 0x05, 0x03, 0x00,
+ 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x04, 0x01, 0x10,
+ 0x00, 0x06, 0x02, 0x50,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x40,
+ 0x00, 0x05, 0x01, 0x60,
+ 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x04, 0x01, 0x50,
+ 0x00, 0x05, 0x02, 0x40,
+ 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x40,
+ 0x00, 0x05, 0x03, 0x40,
+ 0x01, 0x00, 0x00, 0x00
+};
+
+/*
+ *
+ */
+static const unsigned int MulIdx[16][16] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
+ {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
+ {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
+ {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
+ {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
+ {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
+ {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
+ {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
+ {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
+ {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
+ {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
+ {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
+ {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
+ {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
+ {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
+};
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+#define MAX_OUTER_CROP_VALUE (512)
+static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
+#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
+#else
+#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
+#endif
+
+
+/* If the type or the command change, we rebuild the lookup table */
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
+{
+ int flags, version, shift, i;
+ struct pwc_dec23_private *pdec = &pdev->dec23;
+
+ mutex_init(&pdec->lock);
+
+ if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
+ return;
+
+ if (DEVICE_USE_CODEC3(pdev->type)) {
+ flags = cmd[2] & 0x18;
+ if (flags == 8)
+ pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */
+ else if (flags == 0x10)
+ pdec->nbits = 8;
+ else
+ pdec->nbits = 6;
+
+ version = cmd[2] >> 5;
+ build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+ build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+
+ } else {
+
+ flags = cmd[2] & 6;
+ if (flags == 2)
+ pdec->nbits = 7;
+ else if (flags == 4)
+ pdec->nbits = 8;
+ else
+ pdec->nbits = 6;
+
+ version = cmd[2] >> 3;
+ build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+ build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+ }
+
+ /* Informations can be coded on a variable number of bits but never less than 8 */
+ shift = 8 - pdec->nbits;
+ pdec->scalebits = SCALEBITS - shift;
+ pdec->nbitsmask = 0xFF >> shift;
+
+ fill_table_dc00_d800(pdec);
+ build_subblock_pattern(pdec);
+ build_bit_powermask_table(pdec);
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+ /* Build the static table to clamp value [0-255] */
+ for (i=0;i<MAX_OUTER_CROP_VALUE;i++)
+ pwc_crop_table[i] = 0;
+ for (i=0; i<256; i++)
+ pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
+ for (i=0; i<MAX_OUTER_CROP_VALUE; i++)
+ pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
+#endif
+
+ pdec->last_cmd = cmd[2];
+ pdec->last_cmd_valid = 1;
+}
+
+/*
+ * Copy the 4x4 image block to Y plane buffer
+ */
+static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+ const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+ const int *c = src;
+ unsigned char *d = dst;
+
+ *d++ = cm[c[0] >> scalebits];
+ *d++ = cm[c[1] >> scalebits];
+ *d++ = cm[c[2] >> scalebits];
+ *d++ = cm[c[3] >> scalebits];
+
+ d = dst + bytes_per_line;
+ *d++ = cm[c[4] >> scalebits];
+ *d++ = cm[c[5] >> scalebits];
+ *d++ = cm[c[6] >> scalebits];
+ *d++ = cm[c[7] >> scalebits];
+
+ d = dst + bytes_per_line*2;
+ *d++ = cm[c[8] >> scalebits];
+ *d++ = cm[c[9] >> scalebits];
+ *d++ = cm[c[10] >> scalebits];
+ *d++ = cm[c[11] >> scalebits];
+
+ d = dst + bytes_per_line*3;
+ *d++ = cm[c[12] >> scalebits];
+ *d++ = cm[c[13] >> scalebits];
+ *d++ = cm[c[14] >> scalebits];
+ *d++ = cm[c[15] >> scalebits];
+#else
+ int i;
+ const int *c = src;
+ unsigned char *d = dst;
+ for (i = 0; i < 4; i++, c++)
+ *d++ = CLAMP((*c) >> scalebits);
+
+ d = dst + bytes_per_line;
+ for (i = 0; i < 4; i++, c++)
+ *d++ = CLAMP((*c) >> scalebits);
+
+ d = dst + bytes_per_line*2;
+ for (i = 0; i < 4; i++, c++)
+ *d++ = CLAMP((*c) >> scalebits);
+
+ d = dst + bytes_per_line*3;
+ for (i = 0; i < 4; i++, c++)
+ *d++ = CLAMP((*c) >> scalebits);
+#endif
+}
+
+/*
+ * Copy the 4x4 image block to a CrCb plane buffer
+ *
+ */
+static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+ /* Unroll all loops */
+ const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+ const int *c = src;
+ unsigned char *d = dst;
+
+ *d++ = cm[c[0] >> scalebits];
+ *d++ = cm[c[4] >> scalebits];
+ *d++ = cm[c[1] >> scalebits];
+ *d++ = cm[c[5] >> scalebits];
+ *d++ = cm[c[2] >> scalebits];
+ *d++ = cm[c[6] >> scalebits];
+ *d++ = cm[c[3] >> scalebits];
+ *d++ = cm[c[7] >> scalebits];
+
+ d = dst + bytes_per_line;
+ *d++ = cm[c[12] >> scalebits];
+ *d++ = cm[c[8] >> scalebits];
+ *d++ = cm[c[13] >> scalebits];
+ *d++ = cm[c[9] >> scalebits];
+ *d++ = cm[c[14] >> scalebits];
+ *d++ = cm[c[10] >> scalebits];
+ *d++ = cm[c[15] >> scalebits];
+ *d++ = cm[c[11] >> scalebits];
+#else
+ int i;
+ const int *c1 = src;
+ const int *c2 = src + 4;
+ unsigned char *d = dst;
+
+ for (i = 0; i < 4; i++, c1++, c2++) {
+ *d++ = CLAMP((*c1) >> scalebits);
+ *d++ = CLAMP((*c2) >> scalebits);
+ }
+ c1 = src + 12;
+ d = dst + bytes_per_line;
+ for (i = 0; i < 4; i++, c1++, c2++) {
+ *d++ = CLAMP((*c1) >> scalebits);
+ *d++ = CLAMP((*c2) >> scalebits);
+ }
+#endif
+}
+
+/*
+ * To manage the stream, we keep bits in a 32 bits register.
+ * fill_nbits(n): fill the reservoir with at least n bits
+ * skip_bits(n): discard n bits from the reservoir
+ * get_bits(n): fill the reservoir, returns the first n bits and discard the
+ * bits from the reservoir.
+ * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
+ * contains at least n bits. bits returned is discarded.
+ */
+#define fill_nbits(pdec, nbits_wanted) do { \
+ while (pdec->nbits_in_reservoir<(nbits_wanted)) \
+ { \
+ pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
+ pdec->nbits_in_reservoir += 8; \
+ } \
+} while(0);
+
+#define skip_nbits(pdec, nbits_to_skip) do { \
+ pdec->reservoir >>= (nbits_to_skip); \
+ pdec->nbits_in_reservoir -= (nbits_to_skip); \
+} while(0);
+
+#define get_nbits(pdec, nbits_wanted, result) do { \
+ fill_nbits(pdec, nbits_wanted); \
+ result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+ skip_nbits(pdec, nbits_wanted); \
+} while(0);
+
+#define __get_nbits(pdec, nbits_wanted, result) do { \
+ result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+ skip_nbits(pdec, nbits_wanted); \
+} while(0);
+
+#define look_nbits(pdec, nbits_wanted) \
+ ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
+
+/*
+ * Decode a 4x4 pixel block
+ */
+static void decode_block(struct pwc_dec23_private *pdec,
+ const unsigned char *ptable0004,
+ const unsigned char *ptable8004)
+{
+ unsigned int primary_color;
+ unsigned int channel_v, offset1, op;
+ int i;
+
+ fill_nbits(pdec, 16);
+ __get_nbits(pdec, pdec->nbits, primary_color);
+
+ if (look_nbits(pdec,2) == 0) {
+ skip_nbits(pdec, 2);
+ /* Very simple, the color is the same for all pixels of the square */
+ for (i = 0; i < 16; i++)
+ pdec->temp_colors[i] = pdec->table_dc00[primary_color];
+
+ return;
+ }
+
+ /* This block is encoded with small pattern */
+ for (i = 0; i < 16; i++)
+ pdec->temp_colors[i] = pdec->table_d800[primary_color];
+
+ __get_nbits(pdec, 3, channel_v);
+ channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);
+
+ ptable0004 += (channel_v * 128);
+ ptable8004 += (channel_v * 32);
+
+ offset1 = 0;
+ do
+ {
+ unsigned int htable_idx, rows = 0;
+ const unsigned int *block;
+
+ /* [ zzzz y x x ]
+ * xx == 00 :=> end of the block def, remove the two bits from the stream
+ * yxx == 111
+ * yxx == any other value
+ *
+ */
+ fill_nbits(pdec, 16);
+ htable_idx = look_nbits(pdec, 6);
+ op = hash_table_ops[htable_idx * 4];
+
+ if (op == 2) {
+ skip_nbits(pdec, 2);
+
+ } else if (op == 1) {
+ /* 15bits [ xxxx xxxx yyyy 111 ]
+ * yyy => offset in the table8004
+ * xxx => offset in the tabled004 (tree)
+ */
+ unsigned int mask, shift;
+ unsigned int nbits, col1;
+ unsigned int yyyy;
+
+ skip_nbits(pdec, 3);
+ /* offset1 += yyyy */
+ __get_nbits(pdec, 4, yyyy);
+ offset1 += 1 + yyyy;
+ offset1 &= 0x0F;
+ nbits = ptable8004[offset1 * 2];
+
+ /* col1 = xxxx xxxx */
+ __get_nbits(pdec, nbits+1, col1);
+
+ /* Bit mask table */
+ mask = pdec->table_bitpowermask[nbits][col1];
+ shift = ptable8004[offset1 * 2 + 1];
+ rows = ((mask << shift) + 0x80) & 0xFF;
+
+ block = pdec->table_subblock[rows];
+ for (i = 0; i < 16; i++)
+ pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+ } else {
+ /* op == 0
+ * offset1 is coded on 3 bits
+ */
+ unsigned int shift;
+
+ offset1 += hash_table_ops [htable_idx * 4 + 2];
+ offset1 &= 0x0F;
+
+ rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]];
+ block = pdec->table_subblock[rows];
+ for (i = 0; i < 16; i++)
+ pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+ shift = hash_table_ops[htable_idx * 4 + 1];
+ skip_nbits(pdec, shift);
+ }
+
+ } while (op != 2);
+
+}
+
+static void DecompressBand23(struct pwc_dec23_private *pdec,
+ const unsigned char *rawyuv,
+ unsigned char *planar_y,
+ unsigned char *planar_u,
+ unsigned char *planar_v,
+ unsigned int compressed_image_width,
+ unsigned int real_image_width)
+{
+ int compression_index, nblocks;
+ const unsigned char *ptable0004;
+ const unsigned char *ptable8004;
+
+ pdec->reservoir = 0;
+ pdec->nbits_in_reservoir = 0;
+ pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */
+
+ get_nbits(pdec, 4, compression_index);
+
+ /* pass 1: uncompress Y component */
+ nblocks = compressed_image_width / 4;
+
+ ptable0004 = pdec->table_0004_pass1[compression_index];
+ ptable8004 = pdec->table_8004_pass1[compression_index];
+
+ /* Each block decode a square of 4x4 */
+ while (nblocks) {
+ decode_block(pdec, ptable0004, ptable8004);
+ copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
+ planar_y += 4;
+ nblocks--;
+ }
+
+ /* pass 2: uncompress UV component */
+ nblocks = compressed_image_width / 8;
+
+ ptable0004 = pdec->table_0004_pass2[compression_index];
+ ptable8004 = pdec->table_8004_pass2[compression_index];
+
+ /* Each block decode a square of 4x4 */
+ while (nblocks) {
+ decode_block(pdec, ptable0004, ptable8004);
+ copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);
+
+ decode_block(pdec, ptable0004, ptable8004);
+ copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);
+
+ planar_v += 8;
+ planar_u += 8;
+ nblocks -= 2;
+ }
+
+}
+
+/**
+ *
+ * Uncompress a pwc23 buffer.
+ *
+ * src: raw data
+ * dst: image output
+ */
+void pwc_dec23_decompress(struct pwc_device *pdev,
+ const void *src,
+ void *dst)
+{
+ int bandlines_left, bytes_per_block;
+ struct pwc_dec23_private *pdec = &pdev->dec23;
+
+ /* YUV420P image format */
+ unsigned char *pout_planar_y;
+ unsigned char *pout_planar_u;
+ unsigned char *pout_planar_v;
+ unsigned int plane_size;
+
+ mutex_lock(&pdec->lock);
+
+ bandlines_left = pdev->height / 4;
+ bytes_per_block = pdev->width * 4;
+ plane_size = pdev->height * pdev->width;
+
+ pout_planar_y = dst;
+ pout_planar_u = dst + plane_size;
+ pout_planar_v = dst + plane_size + plane_size / 4;
+
+ while (bandlines_left--) {
+ DecompressBand23(pdec, src,
+ pout_planar_y, pout_planar_u, pout_planar_v,
+ pdev->width, pdev->width);
+ src += pdev->vbandlength;
+ pout_planar_y += bytes_per_block;
+ pout_planar_u += pdev->width;
+ pout_planar_v += pdev->width;
+ }
+ mutex_unlock(&pdec->lock);
+}
diff --git a/drivers/media/usb/pwc/pwc-dec23.h b/drivers/media/usb/pwc/pwc-dec23.h
new file mode 100644
index 00000000000..c655b1c1e6a
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-dec23.h
@@ -0,0 +1,61 @@
+/* Linux driver for Philips webcam
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef PWC_DEC23_H
+#define PWC_DEC23_H
+
+struct pwc_device;
+
+struct pwc_dec23_private
+{
+ struct mutex lock;
+
+ unsigned char last_cmd, last_cmd_valid;
+
+ unsigned int scalebits;
+ unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
+
+ unsigned int reservoir;
+ unsigned int nbits_in_reservoir;
+
+ const unsigned char *stream;
+ int temp_colors[16];
+
+ unsigned char table_0004_pass1[16][1024];
+ unsigned char table_0004_pass2[16][1024];
+ unsigned char table_8004_pass1[16][256];
+ unsigned char table_8004_pass2[16][256];
+ unsigned int table_subblock[256][12];
+
+ unsigned char table_bitpowermask[8][256];
+ unsigned int table_d800[256];
+ unsigned int table_dc00[256];
+
+};
+
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd);
+void pwc_dec23_decompress(struct pwc_device *pdev,
+ const void *src,
+ void *dst);
+#endif
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
new file mode 100644
index 00000000000..42e36bac4d7
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -0,0 +1,1164 @@
+/* Linux driver for Philips webcam
+ USB and Video4Linux interface part.
+ (C) 1999-2004 Nemosoft Unv.
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+ (C) 2011 Hans de Goede <hdegoede@redhat.com>
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+/*
+ This code forms the interface between the USB layers and the Philips
+ specific stuff. Some adanved stuff of the driver falls under an
+ NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
+ is thus not distributed in source form. The binary pwcx.o module
+ contains the code that falls under the NDA.
+
+ In case you're wondering: 'pwc' stands for "Philips WebCam", but
+ I really didn't want to type 'philips_web_cam' every time (I'm lazy as
+ any Linux kernel hacker, but I don't like uncomprehensible abbreviations
+ without explanation).
+
+ Oh yes, convention: to disctinguish between all the various pointers to
+ device-structures, I use these names for the pointer variables:
+ udev: struct usb_device *
+ vdev: struct video_device (member of pwc_dev)
+ pdev: struct pwc_devive *
+*/
+
+/* Contributors:
+ - Alvarado: adding whitebalance code
+ - Alistar Moire: QuickCam 3000 Pro device/product ID
+ - Tony Hoyle: Creative Labs Webcam 5 device/product ID
+ - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
+ - Jk Fang: Sotec Afina Eye ID
+ - Xavier Roche: QuickCam Pro 4000 ID
+ - Jens Knudsen: QuickCam Zoom ID
+ - J. Debert: QuickCam for Notebooks ID
+ - Pham Thanh Nam: webcam snapshot button as an event input device
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+#include <linux/usb/input.h>
+#endif
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <linux/kernel.h> /* simple_strtol() */
+
+#include "pwc.h"
+#include "pwc-kiara.h"
+#include "pwc-timon.h"
+#include "pwc-dec23.h"
+#include "pwc-dec1.h"
+
+/* Function prototypes and driver templates */
+
+/* hotplug device table support */
+static const struct usb_device_id pwc_device_table [] = {
+ { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
+ { USB_DEVICE(0x0471, 0x0303) },
+ { USB_DEVICE(0x0471, 0x0304) },
+ { USB_DEVICE(0x0471, 0x0307) },
+ { USB_DEVICE(0x0471, 0x0308) },
+ { USB_DEVICE(0x0471, 0x030C) },
+ { USB_DEVICE(0x0471, 0x0310) },
+ { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */
+ { USB_DEVICE(0x0471, 0x0312) },
+ { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
+ { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */
+ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
+ { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
+ { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
+ { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */
+ { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */
+ { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */
+ { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */
+ { USB_DEVICE(0x046D, 0x08B6) }, /* Cisco VT Camera */
+ { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech ViewPort AV 100 */
+ { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
+ { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */
+ { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */
+ { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */
+ { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
+ { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
+ { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
+ { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */
+ { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
+ { USB_DEVICE(0x0d81, 0x1900) },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, pwc_device_table);
+
+static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id);
+static void usb_pwc_disconnect(struct usb_interface *intf);
+static void pwc_isoc_cleanup(struct pwc_device *pdev);
+
+static struct usb_driver pwc_driver = {
+ .name = "Philips webcam", /* name */
+ .id_table = pwc_device_table,
+ .probe = usb_pwc_probe, /* probe() */
+ .disconnect = usb_pwc_disconnect, /* disconnect() */
+};
+
+#define MAX_DEV_HINTS 20
+#define MAX_ISOC_ERRORS 20
+
+#ifdef CONFIG_USB_PWC_DEBUG
+ int pwc_trace = PWC_DEBUG_LEVEL;
+#endif
+static int power_save = -1;
+static int leds[2] = { 100, 0 };
+
+/***/
+
+static const struct v4l2_file_operations pwc_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
+ .unlocked_ioctl = video_ioctl2,
+};
+static struct video_device pwc_template = {
+ .name = "Philips Webcam", /* Filled in later */
+ .release = video_device_release_empty,
+ .fops = &pwc_fops,
+ .ioctl_ops = &pwc_ioctl_ops,
+};
+
+/***************************************************************************/
+/* Private functions */
+
+struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
+{
+ unsigned long flags = 0;
+ struct pwc_frame_buf *buf = NULL;
+
+ spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
+ if (list_empty(&pdev->queued_bufs))
+ goto leave;
+
+ buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list);
+ list_del(&buf->list);
+leave:
+ spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
+ return buf;
+}
+
+static void pwc_snapshot_button(struct pwc_device *pdev, int down)
+{
+ if (down) {
+ PWC_TRACE("Snapshot button pressed.\n");
+ } else {
+ PWC_TRACE("Snapshot button released.\n");
+ }
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+ if (pdev->button_dev) {
+ input_report_key(pdev->button_dev, KEY_CAMERA, down);
+ input_sync(pdev->button_dev);
+ }
+#endif
+}
+
+static void pwc_frame_complete(struct pwc_device *pdev)
+{
+ struct pwc_frame_buf *fbuf = pdev->fill_buf;
+
+ /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
+ frames on the USB wire after an exposure change. This conditition is
+ however detected in the cam and a bit is set in the header.
+ */
+ if (pdev->type == 730) {
+ unsigned char *ptr = (unsigned char *)fbuf->data;
+
+ if (ptr[1] == 1 && ptr[0] & 0x10) {
+ PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
+ pdev->drop_frames += 2;
+ }
+ if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+ pwc_snapshot_button(pdev, ptr[0] & 0x01);
+ }
+ if ((ptr[0] ^ pdev->vmirror) & 0x02) {
+ if (ptr[0] & 0x02)
+ PWC_TRACE("Image is mirrored.\n");
+ else
+ PWC_TRACE("Image is normal.\n");
+ }
+ pdev->vmirror = ptr[0] & 0x03;
+ /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
+ after a short frame; this condition is filtered out specifically. A 4 byte
+ frame doesn't make sense anyway.
+ So we get either this sequence:
+ drop_bit set -> 4 byte frame -> short frame -> good frame
+ Or this one:
+ drop_bit set -> short frame -> good frame
+ So we drop either 3 or 2 frames in all!
+ */
+ if (fbuf->filled == 4)
+ pdev->drop_frames++;
+ } else if (pdev->type == 740 || pdev->type == 720) {
+ unsigned char *ptr = (unsigned char *)fbuf->data;
+ if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+ pwc_snapshot_button(pdev, ptr[0] & 0x01);
+ }
+ pdev->vmirror = ptr[0] & 0x03;
+ }
+
+ /* In case we were instructed to drop the frame, do so silently. */
+ if (pdev->drop_frames > 0) {
+ pdev->drop_frames--;
+ } else {
+ /* Check for underflow first */
+ if (fbuf->filled < pdev->frame_total_size) {
+ PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
+ " discarded.\n", fbuf->filled);
+ } else {
+ fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
+ fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
+ vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+ pdev->fill_buf = NULL;
+ pdev->vsync = 0;
+ }
+ } /* !drop_frames */
+ pdev->vframe_count++;
+}
+
+/* This gets called for the Isochronous pipe (video). This is done in
+ * interrupt time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void pwc_isoc_handler(struct urb *urb)
+{
+ struct pwc_device *pdev = (struct pwc_device *)urb->context;
+ int i, fst, flen;
+ unsigned char *iso_buf = NULL;
+
+ if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN) {
+ PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
+ return;
+ }
+
+ if (pdev->fill_buf == NULL)
+ pdev->fill_buf = pwc_get_next_fill_buf(pdev);
+
+ if (urb->status != 0) {
+ const char *errmsg;
+
+ errmsg = "Unknown";
+ switch(urb->status) {
+ case -ENOSR: errmsg = "Buffer error (overrun)"; break;
+ case -EPIPE: errmsg = "Stalled (device not responding)"; break;
+ case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
+ case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
+ case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
+ case -ETIME: errmsg = "Device does not respond"; break;
+ }
+ PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n",
+ urb->status, errmsg);
+ /* Give up after a number of contiguous errors */
+ if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
+ {
+ PWC_ERROR("Too many ISOC errors, bailing out.\n");
+ if (pdev->fill_buf) {
+ vb2_buffer_done(&pdev->fill_buf->vb,
+ VB2_BUF_STATE_ERROR);
+ pdev->fill_buf = NULL;
+ }
+ }
+ pdev->vsync = 0; /* Drop the current frame */
+ goto handler_end;
+ }
+
+ /* Reset ISOC error counter. We did get here, after all. */
+ pdev->visoc_errors = 0;
+
+ /* vsync: 0 = don't copy data
+ 1 = sync-hunt
+ 2 = synched
+ */
+ /* Compact data */
+ for (i = 0; i < urb->number_of_packets; i++) {
+ fst = urb->iso_frame_desc[i].status;
+ flen = urb->iso_frame_desc[i].actual_length;
+ iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+ if (fst != 0) {
+ PWC_ERROR("Iso frame %d has error %d\n", i, fst);
+ continue;
+ }
+ if (flen > 0 && pdev->vsync) {
+ struct pwc_frame_buf *fbuf = pdev->fill_buf;
+
+ if (pdev->vsync == 1) {
+ do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp);
+ pdev->vsync = 2;
+ }
+
+ if (flen + fbuf->filled > pdev->frame_total_size) {
+ PWC_ERROR("Frame overflow (%d > %d)\n",
+ flen + fbuf->filled,
+ pdev->frame_total_size);
+ pdev->vsync = 0; /* Let's wait for an EOF */
+ } else {
+ memcpy(fbuf->data + fbuf->filled, iso_buf,
+ flen);
+ fbuf->filled += flen;
+ }
+ }
+ if (flen < pdev->vlast_packet_size) {
+ /* Shorter packet... end of frame */
+ if (pdev->vsync == 2)
+ pwc_frame_complete(pdev);
+ if (pdev->fill_buf == NULL)
+ pdev->fill_buf = pwc_get_next_fill_buf(pdev);
+ if (pdev->fill_buf) {
+ pdev->fill_buf->filled = 0;
+ pdev->vsync = 1;
+ }
+ }
+ pdev->vlast_packet_size = flen;
+ }
+
+handler_end:
+ i = usb_submit_urb(urb, GFP_ATOMIC);
+ if (i != 0)
+ PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
+}
+
+/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
+static int pwc_isoc_init(struct pwc_device *pdev)
+{
+ struct usb_device *udev;
+ struct urb *urb;
+ int i, j, ret;
+ struct usb_interface *intf;
+ struct usb_host_interface *idesc = NULL;
+ int compression = 0; /* 0..3 = uncompressed..high */
+
+ pdev->vsync = 0;
+ pdev->vlast_packet_size = 0;
+ pdev->fill_buf = NULL;
+ pdev->vframe_count = 0;
+ pdev->visoc_errors = 0;
+ udev = pdev->udev;
+
+retry:
+ /* We first try with low compression and then retry with a higher
+ compression setting if there is not enough bandwidth. */
+ ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+ pdev->vframes, &compression, 1);
+
+ /* Get the current alternate interface, adjust packet size */
+ intf = usb_ifnum_to_if(udev, 0);
+ if (intf)
+ idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
+ if (!idesc)
+ return -EIO;
+
+ /* Search video endpoint */
+ pdev->vmax_packet_size = -1;
+ for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
+ if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
+ pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
+ break;
+ }
+ }
+
+ if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
+ PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
+ return -ENFILE; /* Odd error, that should be noticeable */
+ }
+
+ /* Set alternate interface */
+ PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
+ ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+ if (ret == -ENOSPC && compression < 3) {
+ compression++;
+ goto retry;
+ }
+ if (ret < 0)
+ return ret;
+
+ /* Allocate and init Isochronuous urbs */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
+ if (urb == NULL) {
+ PWC_ERROR("Failed to allocate urb %d\n", i);
+ pwc_isoc_cleanup(pdev);
+ return -ENOMEM;
+ }
+ pdev->urbs[i] = urb;
+ PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
+
+ urb->interval = 1; // devik
+ urb->dev = udev;
+ urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
+ urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+ urb->transfer_buffer = usb_alloc_coherent(udev,
+ ISO_BUFFER_SIZE,
+ GFP_KERNEL,
+ &urb->transfer_dma);
+ if (urb->transfer_buffer == NULL) {
+ PWC_ERROR("Failed to allocate urb buffer %d\n", i);
+ pwc_isoc_cleanup(pdev);
+ return -ENOMEM;
+ }
+ urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+ urb->complete = pwc_isoc_handler;
+ urb->context = pdev;
+ urb->start_frame = 0;
+ urb->number_of_packets = ISO_FRAMES_PER_DESC;
+ for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+ urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+ urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
+ }
+ }
+
+ /* link */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
+ if (ret == -ENOSPC && compression < 3) {
+ compression++;
+ pwc_isoc_cleanup(pdev);
+ goto retry;
+ }
+ if (ret) {
+ PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+ pwc_isoc_cleanup(pdev);
+ return ret;
+ }
+ PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]);
+ }
+
+ /* All is done... */
+ PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
+ return 0;
+}
+
+static void pwc_iso_stop(struct pwc_device *pdev)
+{
+ int i;
+
+ /* Unlinking ISOC buffers one by one */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ if (pdev->urbs[i]) {
+ PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]);
+ usb_kill_urb(pdev->urbs[i]);
+ }
+ }
+}
+
+static void pwc_iso_free(struct pwc_device *pdev)
+{
+ int i;
+
+ /* Freeing ISOC buffers one by one */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ if (pdev->urbs[i]) {
+ PWC_DEBUG_MEMORY("Freeing URB\n");
+ if (pdev->urbs[i]->transfer_buffer) {
+ usb_free_coherent(pdev->udev,
+ pdev->urbs[i]->transfer_buffer_length,
+ pdev->urbs[i]->transfer_buffer,
+ pdev->urbs[i]->transfer_dma);
+ }
+ usb_free_urb(pdev->urbs[i]);
+ pdev->urbs[i] = NULL;
+ }
+ }
+}
+
+/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
+static void pwc_isoc_cleanup(struct pwc_device *pdev)
+{
+ PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
+
+ pwc_iso_stop(pdev);
+ pwc_iso_free(pdev);
+ usb_set_interface(pdev->udev, 0, 0);
+
+ PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
+}
+
+/* Must be called with vb_queue_lock hold */
+static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
+{
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
+ while (!list_empty(&pdev->queued_bufs)) {
+ struct pwc_frame_buf *buf;
+
+ buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf,
+ list);
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
+}
+
+#ifdef CONFIG_USB_PWC_DEBUG
+static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
+{
+ switch(sensor_type) {
+ case 0x00:
+ return "Hyundai CMOS sensor";
+ case 0x20:
+ return "Sony CCD sensor + TDA8787";
+ case 0x2E:
+ return "Sony CCD sensor + Exas 98L59";
+ case 0x2F:
+ return "Sony CCD sensor + ADI 9804";
+ case 0x30:
+ return "Sharp CCD sensor + TDA8787";
+ case 0x3E:
+ return "Sharp CCD sensor + Exas 98L59";
+ case 0x3F:
+ return "Sharp CCD sensor + ADI 9804";
+ case 0x40:
+ return "UPA 1021 sensor";
+ case 0x100:
+ return "VGA sensor";
+ case 0x101:
+ return "PAL MR sensor";
+ default:
+ return "unknown type of sensor";
+ }
+}
+#endif
+
+/***************************************************************************/
+/* Video4Linux functions */
+
+static void pwc_video_release(struct v4l2_device *v)
+{
+ struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
+
+ v4l2_ctrl_handler_free(&pdev->ctrl_handler);
+ v4l2_device_unregister(&pdev->v4l2_dev);
+ kfree(pdev->ctrl_buf);
+ kfree(pdev);
+}
+
+/***************************************************************************/
+/* Videobuf2 operations */
+
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], void *alloc_ctxs[])
+{
+ struct pwc_device *pdev = vb2_get_drv_priv(vq);
+ int size;
+
+ if (*nbuffers < MIN_FRAMES)
+ *nbuffers = MIN_FRAMES;
+ else if (*nbuffers > MAX_FRAMES)
+ *nbuffers = MAX_FRAMES;
+
+ *nplanes = 1;
+
+ size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT);
+ sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] *
+ pwc_image_sizes[size][1] * 3 / 2);
+
+ return 0;
+}
+
+static int buffer_init(struct vb2_buffer *vb)
+{
+ struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+
+ /* need vmalloc since frame buffer > 128K */
+ buf->data = vzalloc(PWC_FRAME_SIZE);
+ if (buf->data == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+ struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+
+ /* Don't allow queing new buffers after device disconnection */
+ if (!pdev->udev)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int buffer_finish(struct vb2_buffer *vb)
+{
+ struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+ struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+
+ /*
+ * Application has called dqbuf and is getting back a buffer we've
+ * filled, take the pwc data we've stored in buf->data and decompress
+ * it into a usable format, storing the result in the vb2_buffer
+ */
+ return pwc_decompress(pdev, buf);
+}
+
+static void buffer_cleanup(struct vb2_buffer *vb)
+{
+ struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+
+ vfree(buf->data);
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+ struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+ struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+ unsigned long flags = 0;
+
+ /* Check the device has not disconnected between prep and queuing */
+ if (!pdev->udev) {
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ return;
+ }
+
+ spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
+ list_add_tail(&buf->list, &pdev->queued_bufs);
+ spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
+}
+
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct pwc_device *pdev = vb2_get_drv_priv(vq);
+ int r;
+
+ if (!pdev->udev)
+ return -ENODEV;
+
+ if (mutex_lock_interruptible(&pdev->v4l2_lock))
+ return -ERESTARTSYS;
+ /* Turn on camera and set LEDS on */
+ pwc_camera_power(pdev, 1);
+ pwc_set_leds(pdev, leds[0], leds[1]);
+
+ r = pwc_isoc_init(pdev);
+ if (r) {
+ /* If we failed turn camera and LEDS back off */
+ pwc_set_leds(pdev, 0, 0);
+ pwc_camera_power(pdev, 0);
+ /* And cleanup any queued bufs!! */
+ pwc_cleanup_queued_bufs(pdev);
+ }
+ mutex_unlock(&pdev->v4l2_lock);
+
+ return r;
+}
+
+static int stop_streaming(struct vb2_queue *vq)
+{
+ struct pwc_device *pdev = vb2_get_drv_priv(vq);
+
+ if (mutex_lock_interruptible(&pdev->v4l2_lock))
+ return -ERESTARTSYS;
+ if (pdev->udev) {
+ pwc_set_leds(pdev, 0, 0);
+ pwc_camera_power(pdev, 0);
+ pwc_isoc_cleanup(pdev);
+ }
+
+ pwc_cleanup_queued_bufs(pdev);
+ mutex_unlock(&pdev->v4l2_lock);
+
+ return 0;
+}
+
+static struct vb2_ops pwc_vb_queue_ops = {
+ .queue_setup = queue_setup,
+ .buf_init = buffer_init,
+ .buf_prepare = buffer_prepare,
+ .buf_finish = buffer_finish,
+ .buf_cleanup = buffer_cleanup,
+ .buf_queue = buffer_queue,
+ .start_streaming = start_streaming,
+ .stop_streaming = stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+};
+
+/***************************************************************************/
+/* USB functions */
+
+/* This function gets called when a new device is plugged in or the usb core
+ * is loaded.
+ */
+
+static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct pwc_device *pdev = NULL;
+ int vendor_id, product_id, type_id;
+ int rc;
+ int features = 0;
+ int compression = 0;
+ int my_power_save = power_save;
+ char serial_number[30], *name;
+
+ vendor_id = le16_to_cpu(udev->descriptor.idVendor);
+ product_id = le16_to_cpu(udev->descriptor.idProduct);
+
+ /* Check if we can handle this device */
+ PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
+ vendor_id, product_id,
+ intf->altsetting->desc.bInterfaceNumber);
+
+ /* the interfaces are probed one by one. We are only interested in the
+ video interface (0) now.
+ Interface 1 is the Audio Control, and interface 2 Audio itself.
+ */
+ if (intf->altsetting->desc.bInterfaceNumber > 0)
+ return -ENODEV;
+
+ if (vendor_id == 0x0471) {
+ switch (product_id) {
+ case 0x0302:
+ PWC_INFO("Philips PCA645VC USB webcam detected.\n");
+ name = "Philips 645 webcam";
+ type_id = 645;
+ break;
+ case 0x0303:
+ PWC_INFO("Philips PCA646VC USB webcam detected.\n");
+ name = "Philips 646 webcam";
+ type_id = 646;
+ break;
+ case 0x0304:
+ PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
+ name = "Askey VC010 webcam";
+ type_id = 646;
+ break;
+ case 0x0307:
+ PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
+ name = "Philips 675 webcam";
+ type_id = 675;
+ break;
+ case 0x0308:
+ PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+ name = "Philips 680 webcam";
+ type_id = 680;
+ break;
+ case 0x030C:
+ PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
+ name = "Philips 690 webcam";
+ type_id = 690;
+ break;
+ case 0x0310:
+ PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
+ name = "Philips 730 webcam";
+ type_id = 730;
+ break;
+ case 0x0311:
+ PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
+ name = "Philips 740 webcam";
+ type_id = 740;
+ break;
+ case 0x0312:
+ PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
+ name = "Philips 750 webcam";
+ type_id = 750;
+ break;
+ case 0x0313:
+ PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
+ name = "Philips 720K/40 webcam";
+ type_id = 720;
+ break;
+ case 0x0329:
+ PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
+ name = "Philips SPC 900NC webcam";
+ type_id = 740;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x069A) {
+ switch(product_id) {
+ case 0x0001:
+ PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
+ name = "Askey VC010 webcam";
+ type_id = 645;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x046d) {
+ switch(product_id) {
+ case 0x08b0:
+ PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
+ name = "Logitech QuickCam Pro 3000";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08b1:
+ PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
+ name = "Logitech QuickCam Notebook Pro";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08b2:
+ PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
+ name = "Logitech QuickCam Pro 4000";
+ type_id = 740; /* CCD sensor */
+ if (my_power_save == -1)
+ my_power_save = 1;
+ break;
+ case 0x08b3:
+ PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
+ name = "Logitech QuickCam Zoom";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08B4:
+ PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
+ name = "Logitech QuickCam Zoom";
+ type_id = 740; /* CCD sensor */
+ if (my_power_save == -1)
+ my_power_save = 1;
+ break;
+ case 0x08b5:
+ PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
+ name = "Logitech QuickCam Orbit";
+ type_id = 740; /* CCD sensor */
+ if (my_power_save == -1)
+ my_power_save = 1;
+ features |= FEATURE_MOTOR_PANTILT;
+ break;
+ case 0x08b6:
+ PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
+ name = "Cisco VT Camera";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08b7:
+ PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
+ name = "Logitech ViewPort AV 100";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08b8: /* Where this released? */
+ PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
+ name = "Logitech QuickCam (res.)";
+ type_id = 730; /* Assuming CMOS */
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x055d) {
+ /* I don't know the difference between the C10 and the C30;
+ I suppose the difference is the sensor, but both cameras
+ work equally well with a type_id of 675
+ */
+ switch(product_id) {
+ case 0x9000:
+ PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
+ name = "Samsung MPC-C10";
+ type_id = 675;
+ break;
+ case 0x9001:
+ PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
+ name = "Samsung MPC-C30";
+ type_id = 675;
+ break;
+ case 0x9002:
+ PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
+ name = "Samsung MPC-C30";
+ type_id = 740;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x041e) {
+ switch(product_id) {
+ case 0x400c:
+ PWC_INFO("Creative Labs Webcam 5 detected.\n");
+ name = "Creative Labs Webcam 5";
+ type_id = 730;
+ if (my_power_save == -1)
+ my_power_save = 1;
+ break;
+ case 0x4011:
+ PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
+ name = "Creative Labs Webcam Pro Ex";
+ type_id = 740;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x04cc) {
+ switch(product_id) {
+ case 0x8116:
+ PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
+ name = "Sotec Afina Eye";
+ type_id = 730;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x06be) {
+ switch(product_id) {
+ case 0x8116:
+ /* This is essentially the same cam as the Sotec Afina Eye */
+ PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
+ name = "AME Co. Afina Eye";
+ type_id = 750;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+
+ }
+ else if (vendor_id == 0x0d81) {
+ switch(product_id) {
+ case 0x1900:
+ PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
+ name = "Visionite VCS-UC300";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x1910:
+ PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
+ name = "Visionite VCS-UM100";
+ type_id = 730; /* CMOS sensor */
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else
+ return -ENODEV; /* Not any of the know types; but the list keeps growing. */
+
+ if (my_power_save == -1)
+ my_power_save = 0;
+
+ memset(serial_number, 0, 30);
+ usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
+ PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
+
+ if (udev->descriptor.bNumConfigurations > 1)
+ PWC_WARNING("Warning: more than 1 configuration available.\n");
+
+ /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
+ pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
+ if (pdev == NULL) {
+ PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
+ return -ENOMEM;
+ }
+ pdev->type = type_id;
+ pdev->features = features;
+ pwc_construct(pdev); /* set min/max sizes correct */
+
+ mutex_init(&pdev->v4l2_lock);
+ mutex_init(&pdev->vb_queue_lock);
+ spin_lock_init(&pdev->queued_bufs_lock);
+ INIT_LIST_HEAD(&pdev->queued_bufs);
+
+ pdev->udev = udev;
+ pdev->power_save = my_power_save;
+
+ /* Init videobuf2 queue structure */
+ pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+ pdev->vb_queue.drv_priv = pdev;
+ pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
+ pdev->vb_queue.ops = &pwc_vb_queue_ops;
+ pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
+ vb2_queue_init(&pdev->vb_queue);
+
+ /* Init video_device structure */
+ memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
+ strcpy(pdev->vdev.name, name);
+ pdev->vdev.queue = &pdev->vb_queue;
+ pdev->vdev.queue->lock = &pdev->vb_queue_lock;
+ set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
+ video_set_drvdata(&pdev->vdev, pdev);
+
+ pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
+ PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
+
+ /* Allocate USB command buffers */
+ pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL);
+ if (!pdev->ctrl_buf) {
+ PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
+ rc = -ENOMEM;
+ goto err_free_mem;
+ }
+
+#ifdef CONFIG_USB_PWC_DEBUG
+ /* Query sensor type */
+ if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
+ PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
+ pdev->vdev.name,
+ pwc_sensor_type_to_string(rc), rc);
+ }
+#endif
+
+ /* Set the leds off */
+ pwc_set_leds(pdev, 0, 0);
+
+ /* Setup intial videomode */
+ rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
+ V4L2_PIX_FMT_YUV420, 30, &compression, 1);
+ if (rc)
+ goto err_free_mem;
+
+ /* Register controls (and read default values from camera */
+ rc = pwc_init_controls(pdev);
+ if (rc) {
+ PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc);
+ goto err_free_mem;
+ }
+
+ /* And powerdown the camera until streaming starts */
+ pwc_camera_power(pdev, 0);
+
+ /* Register the v4l2_device structure */
+ pdev->v4l2_dev.release = pwc_video_release;
+ rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
+ if (rc) {
+ PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
+ goto err_free_controls;
+ }
+
+ pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
+ pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
+ pdev->vdev.lock = &pdev->v4l2_lock;
+
+ rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1);
+ if (rc < 0) {
+ PWC_ERROR("Failed to register as video device (%d).\n", rc);
+ goto err_unregister_v4l2_dev;
+ }
+ PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+ /* register webcam snapshot button input device */
+ pdev->button_dev = input_allocate_device();
+ if (!pdev->button_dev) {
+ PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
+ rc = -ENOMEM;
+ goto err_video_unreg;
+ }
+
+ usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
+ strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
+
+ pdev->button_dev->name = "PWC snapshot button";
+ pdev->button_dev->phys = pdev->button_phys;
+ usb_to_input_id(pdev->udev, &pdev->button_dev->id);
+ pdev->button_dev->dev.parent = &pdev->udev->dev;
+ pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
+ pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
+
+ rc = input_register_device(pdev->button_dev);
+ if (rc) {
+ input_free_device(pdev->button_dev);
+ pdev->button_dev = NULL;
+ goto err_video_unreg;
+ }
+#endif
+
+ return 0;
+
+err_video_unreg:
+ video_unregister_device(&pdev->vdev);
+err_unregister_v4l2_dev:
+ v4l2_device_unregister(&pdev->v4l2_dev);
+err_free_controls:
+ v4l2_ctrl_handler_free(&pdev->ctrl_handler);
+err_free_mem:
+ kfree(pdev->ctrl_buf);
+ kfree(pdev);
+ return rc;
+}
+
+/* The user yanked out the cable... */
+static void usb_pwc_disconnect(struct usb_interface *intf)
+{
+ struct v4l2_device *v = usb_get_intfdata(intf);
+ struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
+
+ mutex_lock(&pdev->vb_queue_lock);
+ mutex_lock(&pdev->v4l2_lock);
+ /* No need to keep the urbs around after disconnection */
+ if (pdev->vb_queue.streaming)
+ pwc_isoc_cleanup(pdev);
+ pdev->udev = NULL;
+ pwc_cleanup_queued_bufs(pdev);
+
+ v4l2_device_disconnect(&pdev->v4l2_dev);
+ video_unregister_device(&pdev->vdev);
+ mutex_unlock(&pdev->v4l2_lock);
+ mutex_unlock(&pdev->vb_queue_lock);
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+ if (pdev->button_dev)
+ input_unregister_device(pdev->button_dev);
+#endif
+
+ v4l2_device_put(&pdev->v4l2_dev);
+}
+
+
+/*
+ * Initialization code & module stuff
+ */
+
+static unsigned int leds_nargs;
+
+#ifdef CONFIG_USB_PWC_DEBUG
+module_param_named(trace, pwc_trace, int, 0644);
+#endif
+module_param(power_save, int, 0644);
+module_param_array(leds, int, &leds_nargs, 0444);
+
+#ifdef CONFIG_USB_PWC_DEBUG
+MODULE_PARM_DESC(trace, "For debugging purposes");
+#endif
+MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
+MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
+
+MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
+MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("pwcx");
+MODULE_VERSION( PWC_VERSION );
+
+module_usb_driver(pwc_driver);
diff --git a/drivers/media/usb/pwc/pwc-kiara.c b/drivers/media/usb/pwc/pwc-kiara.c
new file mode 100644
index 00000000000..e5f4fd81712
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-kiara.c
@@ -0,0 +1,892 @@
+/* Linux driver for Philips webcam
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+/* This tables contains entries for the 730/740/750 (Kiara) camera, with
+ 4 different qualities (no compression, low, medium, high).
+ It lists the bandwidth requirements for said mode by its alternate interface
+ number. An alternate of 0 means that the mode is unavailable.
+
+ There are 6 * 4 * 4 entries:
+ 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+ 6 framerates: 5, 10, 15, 20, 25, 30
+ 4 compression modi: none, low, medium, high
+
+ When an uncompressed mode is not available, the next available compressed mode
+ will be chosen (unless the decompressor is absent). Sometimes there are only
+ 1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+
+#include "pwc-kiara.h"
+
+const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA] = { 5, 10, 15, 20, 25, 30 };
+
+const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
+{
+ /* SQCIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* QSIF */
+ {
+ /* 5 fps */
+ {
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
+ {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+ {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+ {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
+ {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
+ {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
+ {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+ },
+ /* 25 fps */
+ {
+ {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
+ {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
+ {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+ {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
+ },
+ /* 30 fps */
+ {
+ {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
+ {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
+ {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
+ {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+ },
+ },
+ /* QCIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* SIF */
+ {
+ /* 5 fps */
+ {
+ {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
+ {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
+ {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
+ {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
+ {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
+ {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
+ {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
+ {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
+ {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
+ {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
+ {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
+ {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
+ {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
+ {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
+ },
+ },
+ /* CIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* VGA */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
+ {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
+ {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
+ {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
+ {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+ {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+ {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+};
+
+
+/*
+ * Rom table for kiara chips
+ *
+ * 32 roms tables (one for each resolution ?)
+ * 2 tables per roms (one for each passes) (Y, and U&V)
+ * 128 bytes per passes
+ */
+
+const unsigned int KiaraRomTable [8][2][16][8] =
+{
+ { /* version 0 */
+ { /* version 0, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x0000124a,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00009252,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009292,0x00009292,0x00009493,0x000124db},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x0000a493,0x000124db,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x000124db,0x000126dc,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 0, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000001,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00001252},
+ {0x00000000,0x00000000,0x00000049,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009252,0x00009292,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009292,0x00009292,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00009292,
+ 0x00009492,0x00009493,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009252,0x00009493,
+ 0x000126dc,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 1 */
+ { /* version 1, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009252,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00009252,
+ 0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 1, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000009,
+ 0x00000049,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000000},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000049,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009252,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009292,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009292,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009292,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x0000924a,0x0000924a,
+ 0x00009492,0x00009493,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 2 */
+ { /* version 2, passes 0 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009493,0x00009493,0x0000a49b},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 2, passes 1 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x0000a49b,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 3 */
+ { /* version 3, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 3, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 4 */
+ { /* version 4, passes 0 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009252,0x00009493,
+ 0x000124db,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 4, passes 1 */
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000049,0x00000049,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00000249,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009252,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009493,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 5 */
+ { /* version 5, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 5, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009252,0x00009252,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 6 */
+ { /* version 6, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x00012492,0x000126db,
+ 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 6, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 7 */
+ { /* version 7, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b725,0x000124db},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 7, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x00009492,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000136db,
+ 0x0001b724,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000136db,
+ 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000136db,
+ 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ }
+};
+
diff --git a/drivers/media/usb/pwc/pwc-kiara.h b/drivers/media/usb/pwc/pwc-kiara.h
new file mode 100644
index 00000000000..8e02b7ac213
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-kiara.h
@@ -0,0 +1,48 @@
+/* Linux driver for Philips webcam
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/* Entries for the Kiara (730/740/750) camera */
+
+#ifndef PWC_KIARA_H
+#define PWC_KIARA_H
+
+#include "pwc.h"
+
+#define PWC_FPS_MAX_KIARA 6
+
+struct Kiara_table_entry
+{
+ char alternate; /* USB alternate interface */
+ unsigned short packetsize; /* Normal packet size */
+ unsigned short bandlength; /* Bandlength when decompressing */
+ unsigned char mode[12]; /* precomputed mode settings for cam */
+};
+
+extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][PWC_FPS_MAX_KIARA][4];
+extern const unsigned int KiaraRomTable[8][2][16][8];
+extern const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA];
+
+#endif
+
+
diff --git a/drivers/media/usb/pwc/pwc-misc.c b/drivers/media/usb/pwc/pwc-misc.c
new file mode 100644
index 00000000000..9be5adffa87
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-misc.c
@@ -0,0 +1,93 @@
+/* Linux driver for Philips webcam
+ Various miscellaneous functions and tables.
+ (C) 1999-2003 Nemosoft Unv.
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#include "pwc.h"
+
+const int pwc_image_sizes[PSZ_MAX][2] =
+{
+ { 128, 96 }, /* sqcif */
+ { 160, 120 }, /* qsif */
+ { 176, 144 }, /* qcif */
+ { 320, 240 }, /* sif */
+ { 352, 288 }, /* cif */
+ { 640, 480 }, /* vga */
+};
+
+/* x,y -> PSZ_ */
+int pwc_get_size(struct pwc_device *pdev, int width, int height)
+{
+ int i;
+
+ /* Find the largest size supported by the camera that fits into the
+ requested size. */
+ for (i = PSZ_MAX - 1; i >= 0; i--) {
+ if (!(pdev->image_mask & (1 << i)))
+ continue;
+
+ if (pwc_image_sizes[i][0] <= width &&
+ pwc_image_sizes[i][1] <= height)
+ return i;
+ }
+
+ /* No mode found, return the smallest mode we have */
+ for (i = 0; i < PSZ_MAX; i++) {
+ if (pdev->image_mask & (1 << i))
+ return i;
+ }
+
+ /* Never reached there always is atleast one supported mode */
+ return 0;
+}
+
+/* initialize variables depending on type and decompressor */
+void pwc_construct(struct pwc_device *pdev)
+{
+ if (DEVICE_USE_CODEC1(pdev->type)) {
+
+ pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
+ pdev->vcinterface = 2;
+ pdev->vendpoint = 4;
+ pdev->frame_header_size = 0;
+ pdev->frame_trailer_size = 0;
+
+ } else if (DEVICE_USE_CODEC3(pdev->type)) {
+
+ pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+ pdev->vcinterface = 3;
+ pdev->vendpoint = 5;
+ pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+ pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+
+ } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
+
+ pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
+ pdev->vcinterface = 3;
+ pdev->vendpoint = 4;
+ pdev->frame_header_size = 0;
+ pdev->frame_trailer_size = 0;
+ }
+}
diff --git a/drivers/media/usb/pwc/pwc-nala.h b/drivers/media/usb/pwc/pwc-nala.h
new file mode 100644
index 00000000000..168c73ef75d
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-nala.h
@@ -0,0 +1,66 @@
+ /* SQCIF */
+ {
+ {0, 0, {0x04, 0x01, 0x03}},
+ {8, 0, {0x05, 0x01, 0x03}},
+ {7, 0, {0x08, 0x01, 0x03}},
+ {7, 0, {0x0A, 0x01, 0x03}},
+ {6, 0, {0x0C, 0x01, 0x03}},
+ {5, 0, {0x0F, 0x01, 0x03}},
+ {4, 0, {0x14, 0x01, 0x03}},
+ {3, 0, {0x18, 0x01, 0x03}},
+ },
+ /* QSIF */
+ {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ },
+ /* QCIF */
+ {
+ {0, 0, {0x04, 0x01, 0x02}},
+ {8, 0, {0x05, 0x01, 0x02}},
+ {7, 0, {0x08, 0x01, 0x02}},
+ {6, 0, {0x0A, 0x01, 0x02}},
+ {5, 0, {0x0C, 0x01, 0x02}},
+ {4, 0, {0x0F, 0x01, 0x02}},
+ {1, 0, {0x14, 0x01, 0x02}},
+ {1, 0, {0x18, 0x01, 0x02}},
+ },
+ /* SIF */
+ {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ },
+ /* CIF */
+ {
+ {4, 0, {0x04, 0x01, 0x01}},
+ {7, 1, {0x05, 0x03, 0x01}},
+ {6, 1, {0x08, 0x03, 0x01}},
+ {4, 1, {0x0A, 0x03, 0x01}},
+ {3, 1, {0x0C, 0x03, 0x01}},
+ {2, 1, {0x0F, 0x03, 0x01}},
+ {0},
+ {0},
+ },
+ /* VGA */
+ {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ },
diff --git a/drivers/media/usb/pwc/pwc-timon.c b/drivers/media/usb/pwc/pwc-timon.c
new file mode 100644
index 00000000000..c56c174b161
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-timon.c
@@ -0,0 +1,1448 @@
+/* Linux driver for Philips webcam
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+/* This tables contains entries for the 675/680/690 (Timon) camera, with
+ 4 different qualities (no compression, low, medium, high).
+ It lists the bandwidth requirements for said mode by its alternate interface
+ number. An alternate of 0 means that the mode is unavailable.
+
+ There are 6 * 4 * 4 entries:
+ 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+ 6 framerates: 5, 10, 15, 20, 25, 30
+ 4 compression modi: none, low, medium, high
+
+ When an uncompressed mode is not available, the next available compressed mode
+ will be chosen (unless the decompressor is absent). Sometimes there are only
+ 1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+#include "pwc-timon.h"
+
+const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON] = { 5, 10, 15, 20, 25, 30 };
+
+const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4] =
+{
+ /* SQCIF */
+ {
+ /* 5 fps */
+ {
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ },
+ },
+ /* QSIF */
+ {
+ /* 5 fps */
+ {
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
+ {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
+ {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
+ {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
+ {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
+ {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
+ {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+ },
+ },
+ /* QCIF */
+ {
+ /* 5 fps */
+ {
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
+ {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
+ {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
+ {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
+ {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
+ {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
+ {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
+ {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
+ {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ },
+ /* SIF */
+ {
+ /* 5 fps */
+ {
+ {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
+ {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
+ {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
+ {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
+ {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
+ {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
+ {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
+ {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
+ {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
+ {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
+ {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
+ {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
+ {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
+ {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
+ },
+ },
+ /* CIF */
+ {
+ /* 5 fps */
+ {
+ {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
+ {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
+ {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
+ {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
+ {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
+ {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
+ {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
+ {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
+ {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
+ {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
+ {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
+ {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
+ {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
+ {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
+ },
+ },
+ /* VGA */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
+ {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
+ {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
+ {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
+ {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+ {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+ {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+};
+
+/*
+ * 16 versions:
+ * 2 tables (one for Y, and one for U&V)
+ * 16 levels of details per tables
+ * 8 blocs
+ */
+
+const unsigned int TimonRomTable [16][2][16][8] =
+{
+ { /* version 0 */
+ { /* version 0, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000001,0x00000001,
+ 0x00000001,0x00000001,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000001,0x00000001,
+ 0x00000001,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000001,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000009,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x0000124a,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 0, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000001,0x00000001,
+ 0x00000001,0x00000001,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000001,
+ 0x00000001,0x00000009,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000009,
+ 0x00000009,0x00000049,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000009,
+ 0x00000009,0x00000049,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000249,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 1 */
+ { /* version 1, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000001,0x00000001,
+ 0x00000001,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000009,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00001252},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 1, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000001,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000049,0x00000249,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000249,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009252,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 2 */
+ { /* version 2, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009252,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00009252,
+ 0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 2, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000009,
+ 0x00000049,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000000},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000049,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009252,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009292,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009292,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009292,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x0000924a,0x0000924a,
+ 0x00009492,0x00009493,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 3 */
+ { /* version 3, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009292,0x00009292,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00009252,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009292,0x0000a49b,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 3, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x00000049,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009252,0x00009292,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009292,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 4 */
+ { /* version 4, passes 0 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009493,0x00009493,0x0000a49b},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 4, passes 1 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x0000a49b,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 5 */
+ { /* version 5, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009292,0x00009292,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000126dc,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 5, passes 1 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x00009493,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x000124db,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009493,0x000124db,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x000124db,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x000126dc,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 6 */
+ { /* version 6, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 6, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 7 */
+ { /* version 7, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001c96e,0x0002496e},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0002496e},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x0002496d,0x00025bb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 7, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000136e4,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00012492,0x000126db,
+ 0x0001b724,0x0001b925,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 8 */
+ { /* version 8, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000126dc,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x00024b76,0x00024b77},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x0001b925,0x00024b76,0x00025bbf},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x000136e4,0x0001c92d,0x00024b76,0x00025bbf},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 8, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000126dc,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x0002496d,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 9 */
+ { /* version 9, passes 0 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009252,0x00009493,
+ 0x000124db,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 9, passes 1 */
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000049,0x00000049,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00000249,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009252,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009493,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 10 */
+ { /* version 10, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000126dc,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000126dc,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x000136e4,0x0002496d,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 10, passes 1 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00000249,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009252,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x00009493,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009493,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x00009492,0x00009493,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009493,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009252,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 11 */
+ { /* version 11, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 11, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009252,0x00009252,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 12 */
+ { /* version 12, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x00012492,0x000126db,
+ 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 12, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 13 */
+ { /* version 13, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b725,0x000124db},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 13, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x00009492,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000136db,
+ 0x0001b724,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000136db,
+ 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000136db,
+ 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 14 */
+ { /* version 14, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000136e4,0x0001b725,0x000124db},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000126dc,0x0001b724,0x0001b92d,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b924,0x0002496d,0x00024b76,0x00024b77},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 14, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000136e4,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000136e4,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000136e4,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000136e4,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000136e4,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 15 */
+ { /* version 15, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b924,0x0002496d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x00024b6d,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 15, passes 1 */
+ {0x00000000,0x00000000,0x0000924a,0x0000924a,
+ 0x00009292,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000124db,0x0001b724,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x0001b724,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x0001b724,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000136db,
+ 0x0001b724,0x0001b724,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001c924,0x0001b724,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001c924,0x0001b724,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b724,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b925,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x00024924,0x0002496d,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ }
+};
diff --git a/drivers/media/usb/pwc/pwc-timon.h b/drivers/media/usb/pwc/pwc-timon.h
new file mode 100644
index 00000000000..270c5b9010f
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-timon.h
@@ -0,0 +1,63 @@
+/* Linux driver for Philips webcam
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+
+/* This tables contains entries for the 675/680/690 (Timon) camera, with
+ 4 different qualities (no compression, low, medium, high).
+ It lists the bandwidth requirements for said mode by its alternate interface
+ number. An alternate of 0 means that the mode is unavailable.
+
+ There are 6 * 4 * 4 entries:
+ 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+ 6 framerates: 5, 10, 15, 20, 25, 30
+ 4 compression modi: none, low, medium, high
+
+ When an uncompressed mode is not available, the next available compressed mode
+ will be chosen (unless the decompressor is absent). Sometimes there are only
+ 1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+#ifndef PWC_TIMON_H
+#define PWC_TIMON_H
+
+#include "pwc.h"
+
+#define PWC_FPS_MAX_TIMON 6
+
+struct Timon_table_entry
+{
+ char alternate; /* USB alternate interface */
+ unsigned short packetsize; /* Normal packet size */
+ unsigned short bandlength; /* Bandlength when decompressing */
+ unsigned char mode[13]; /* precomputed mode settings for cam */
+};
+
+extern const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4];
+extern const unsigned int TimonRomTable [16][2][16][8];
+extern const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON];
+
+#endif
+
+
diff --git a/drivers/media/usb/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c
new file mode 100644
index 00000000000..b65903fbcf0
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-uncompress.c
@@ -0,0 +1,107 @@
+/* Linux driver for Philips webcam
+ Decompression frontend.
+ (C) 1999-2003 Nemosoft Unv.
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ vim: set ts=8:
+*/
+
+#include <asm/current.h>
+#include <asm/types.h>
+
+#include "pwc.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
+{
+ int n, line, col;
+ void *yuv, *image;
+ u16 *src;
+ u16 *dsty, *dstu, *dstv;
+
+ image = vb2_plane_vaddr(&fbuf->vb, 0);
+
+ yuv = fbuf->data + pdev->frame_header_size; /* Skip header */
+
+ /* Raw format; that's easy... */
+ if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
+ {
+ struct pwc_raw_frame *raw_frame = image;
+ raw_frame->type = cpu_to_le16(pdev->type);
+ raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength);
+ /* cmd_buf is always 4 bytes, but sometimes, only the
+ * first 3 bytes is filled (Nala case). We can
+ * determine this using the type of the webcam */
+ memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
+ memcpy(raw_frame+1, yuv, pdev->frame_size);
+ vb2_set_plane_payload(&fbuf->vb, 0,
+ pdev->frame_size + sizeof(struct pwc_raw_frame));
+ return 0;
+ }
+
+ vb2_set_plane_payload(&fbuf->vb, 0,
+ pdev->width * pdev->height * 3 / 2);
+
+ if (pdev->vbandlength == 0) {
+ /* Uncompressed mode.
+ *
+ * We do some byte shuffling here to go from the
+ * native format to YUV420P.
+ */
+ src = (u16 *)yuv;
+ n = pdev->width * pdev->height;
+ dsty = (u16 *)(image);
+ dstu = (u16 *)(image + n);
+ dstv = (u16 *)(image + n + n / 4);
+
+ for (line = 0; line < pdev->height; line++) {
+ for (col = 0; col < pdev->width; col += 4) {
+ *dsty++ = *src++;
+ *dsty++ = *src++;
+ if (line & 1)
+ *dstv++ = *src++;
+ else
+ *dstu++ = *src++;
+ }
+ }
+
+ return 0;
+ }
+
+ /*
+ * Compressed;
+ * the decompressor routines will write the data in planar format
+ * immediately.
+ */
+ if (DEVICE_USE_CODEC1(pdev->type)) {
+
+ /* TODO & FIXME */
+ PWC_ERROR("This chipset is not supported for now\n");
+ return -ENXIO; /* No such device or address: missing decompressor */
+
+ } else {
+ pwc_dec23_decompress(pdev, yuv, image);
+ }
+ return 0;
+}
diff --git a/drivers/media/usb/pwc/pwc-v4l.c b/drivers/media/usb/pwc/pwc-v4l.c
new file mode 100644
index 00000000000..545e9bbdeed
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc-v4l.c
@@ -0,0 +1,1053 @@
+/* Linux driver for Philips webcam
+ USB and Video4Linux interface part.
+ (C) 1999-2004 Nemosoft Unv.
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+ (C) 2011 Hans de Goede <hdegoede@redhat.com>
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/vmalloc.h>
+#include <linux/jiffies.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+
+#define PWC_CID_CUSTOM(ctrl) ((V4L2_CID_USER_BASE | 0xf000) + custom_ ## ctrl)
+
+static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
+static int pwc_s_ctrl(struct v4l2_ctrl *ctrl);
+
+static const struct v4l2_ctrl_ops pwc_ctrl_ops = {
+ .g_volatile_ctrl = pwc_g_volatile_ctrl,
+ .s_ctrl = pwc_s_ctrl,
+};
+
+enum { awb_indoor, awb_outdoor, awb_fl, awb_manual, awb_auto };
+enum { custom_autocontour, custom_contour, custom_noise_reduction,
+ custom_awb_speed, custom_awb_delay,
+ custom_save_user, custom_restore_user, custom_restore_factory };
+
+const char * const pwc_auto_whitebal_qmenu[] = {
+ "Indoor (Incandescant Lighting) Mode",
+ "Outdoor (Sunlight) Mode",
+ "Indoor (Fluorescent Lighting) Mode",
+ "Manual Mode",
+ "Auto Mode",
+ NULL
+};
+
+static const struct v4l2_ctrl_config pwc_auto_white_balance_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .max = awb_auto,
+ .qmenu = pwc_auto_whitebal_qmenu,
+};
+
+static const struct v4l2_ctrl_config pwc_autocontour_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(autocontour),
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Auto contour",
+ .min = 0,
+ .max = 1,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_contour_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(contour),
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contour",
+ .flags = V4L2_CTRL_FLAG_SLIDER,
+ .min = 0,
+ .max = 63,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_backlight_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = V4L2_CID_BACKLIGHT_COMPENSATION,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_flicker_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = V4L2_CID_BAND_STOP_FILTER,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_noise_reduction_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(noise_reduction),
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Dynamic Noise Reduction",
+ .min = 0,
+ .max = 3,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_save_user_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(save_user),
+ .type = V4L2_CTRL_TYPE_BUTTON,
+ .name = "Save User Settings",
+};
+
+static const struct v4l2_ctrl_config pwc_restore_user_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(restore_user),
+ .type = V4L2_CTRL_TYPE_BUTTON,
+ .name = "Restore User Settings",
+};
+
+static const struct v4l2_ctrl_config pwc_restore_factory_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(restore_factory),
+ .type = V4L2_CTRL_TYPE_BUTTON,
+ .name = "Restore Factory Settings",
+};
+
+static const struct v4l2_ctrl_config pwc_awb_speed_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(awb_speed),
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Auto White Balance Speed",
+ .min = 1,
+ .max = 32,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_awb_delay_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(awb_delay),
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Auto White Balance Delay",
+ .min = 0,
+ .max = 63,
+ .step = 1,
+};
+
+int pwc_init_controls(struct pwc_device *pdev)
+{
+ struct v4l2_ctrl_handler *hdl;
+ struct v4l2_ctrl_config cfg;
+ int r, def;
+
+ hdl = &pdev->ctrl_handler;
+ r = v4l2_ctrl_handler_init(hdl, 20);
+ if (r)
+ return r;
+
+ /* Brightness, contrast, saturation, gamma */
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, BRIGHTNESS_FORMATTER, &def);
+ if (r || def > 127)
+ def = 63;
+ pdev->brightness = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 127, 1, def);
+
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, CONTRAST_FORMATTER, &def);
+ if (r || def > 63)
+ def = 31;
+ pdev->contrast = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 63, 1, def);
+
+ if (pdev->type >= 675) {
+ if (pdev->type < 730)
+ pdev->saturation_fmt = SATURATION_MODE_FORMATTER2;
+ else
+ pdev->saturation_fmt = SATURATION_MODE_FORMATTER1;
+ r = pwc_get_s8_ctrl(pdev, GET_CHROM_CTL, pdev->saturation_fmt,
+ &def);
+ if (r || def < -100 || def > 100)
+ def = 0;
+ pdev->saturation = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_SATURATION, -100, 100, 1, def);
+ }
+
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, GAMMA_FORMATTER, &def);
+ if (r || def > 31)
+ def = 15;
+ pdev->gamma = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_GAMMA, 0, 31, 1, def);
+
+ /* auto white balance, red gain, blue gain */
+ r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, WB_MODE_FORMATTER, &def);
+ if (r || def > awb_auto)
+ def = awb_auto;
+ cfg = pwc_auto_white_balance_cfg;
+ cfg.name = v4l2_ctrl_get_name(cfg.id);
+ cfg.def = def;
+ pdev->auto_white_balance = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+ /* check auto controls to avoid NULL deref in v4l2_ctrl_auto_cluster */
+ if (!pdev->auto_white_balance)
+ return hdl->error;
+
+ r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+ PRESET_MANUAL_RED_GAIN_FORMATTER, &def);
+ if (r)
+ def = 127;
+ pdev->red_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_RED_BALANCE, 0, 255, 1, def);
+
+ r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+ PRESET_MANUAL_BLUE_GAIN_FORMATTER, &def);
+ if (r)
+ def = 127;
+ pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_BLUE_BALANCE, 0, 255, 1, def);
+
+ v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual, true);
+
+ /* autogain, gain */
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def);
+ if (r || (def != 0 && def != 0xff))
+ def = 0;
+ /* Note a register value if 0 means auto gain is on */
+ pdev->autogain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_AUTOGAIN, 0, 1, 1, def == 0);
+ if (!pdev->autogain)
+ return hdl->error;
+
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_AGC_FORMATTER, &def);
+ if (r || def > 63)
+ def = 31;
+ pdev->gain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_GAIN, 0, 63, 1, def);
+
+ /* auto exposure, exposure */
+ if (DEVICE_USE_CODEC2(pdev->type)) {
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, SHUTTER_MODE_FORMATTER,
+ &def);
+ if (r || (def != 0 && def != 0xff))
+ def = 0;
+ /*
+ * def = 0 auto, def = ff manual
+ * menu idx 0 = auto, idx 1 = manual
+ */
+ pdev->exposure_auto = v4l2_ctrl_new_std_menu(hdl,
+ &pwc_ctrl_ops,
+ V4L2_CID_EXPOSURE_AUTO,
+ 1, 0, def != 0);
+ if (!pdev->exposure_auto)
+ return hdl->error;
+
+ /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
+ r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+ READ_SHUTTER_FORMATTER, &def);
+ if (r || def > 655)
+ def = 655;
+ pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_EXPOSURE, 0, 655, 1, def);
+ /* CODEC2: separate auto gain & auto exposure */
+ v4l2_ctrl_auto_cluster(2, &pdev->autogain, 0, true);
+ v4l2_ctrl_auto_cluster(2, &pdev->exposure_auto,
+ V4L2_EXPOSURE_MANUAL, true);
+ } else if (DEVICE_USE_CODEC3(pdev->type)) {
+ /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
+ r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+ READ_SHUTTER_FORMATTER, &def);
+ if (r || def > 255)
+ def = 255;
+ pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_EXPOSURE, 0, 255, 1, def);
+ /* CODEC3: both gain and exposure controlled by autogain */
+ pdev->autogain_expo_cluster[0] = pdev->autogain;
+ pdev->autogain_expo_cluster[1] = pdev->gain;
+ pdev->autogain_expo_cluster[2] = pdev->exposure;
+ v4l2_ctrl_auto_cluster(3, pdev->autogain_expo_cluster,
+ 0, true);
+ }
+
+ /* color / bw setting */
+ r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, COLOUR_MODE_FORMATTER,
+ &def);
+ if (r || (def != 0 && def != 0xff))
+ def = 0xff;
+ /* def = 0 bw, def = ff color, menu idx 0 = color, idx 1 = bw */
+ pdev->colorfx = v4l2_ctrl_new_std_menu(hdl, &pwc_ctrl_ops,
+ V4L2_CID_COLORFX, 1, 0, def == 0);
+
+ /* autocontour, contour */
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &def);
+ if (r || (def != 0 && def != 0xff))
+ def = 0;
+ cfg = pwc_autocontour_cfg;
+ cfg.def = def == 0;
+ pdev->autocontour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+ if (!pdev->autocontour)
+ return hdl->error;
+
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &def);
+ if (r || def > 63)
+ def = 31;
+ cfg = pwc_contour_cfg;
+ cfg.def = def;
+ pdev->contour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+ v4l2_ctrl_auto_cluster(2, &pdev->autocontour, 0, false);
+
+ /* backlight */
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
+ BACK_LIGHT_COMPENSATION_FORMATTER, &def);
+ if (r || (def != 0 && def != 0xff))
+ def = 0;
+ cfg = pwc_backlight_cfg;
+ cfg.name = v4l2_ctrl_get_name(cfg.id);
+ cfg.def = def == 0;
+ pdev->backlight = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+ /* flikker rediction */
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
+ FLICKERLESS_MODE_FORMATTER, &def);
+ if (r || (def != 0 && def != 0xff))
+ def = 0;
+ cfg = pwc_flicker_cfg;
+ cfg.name = v4l2_ctrl_get_name(cfg.id);
+ cfg.def = def == 0;
+ pdev->flicker = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+ /* Dynamic noise reduction */
+ r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
+ DYNAMIC_NOISE_CONTROL_FORMATTER, &def);
+ if (r || def > 3)
+ def = 2;
+ cfg = pwc_noise_reduction_cfg;
+ cfg.def = def;
+ pdev->noise_reduction = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+ /* Save / Restore User / Factory Settings */
+ pdev->save_user = v4l2_ctrl_new_custom(hdl, &pwc_save_user_cfg, NULL);
+ pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg,
+ NULL);
+ if (pdev->restore_user)
+ pdev->restore_user->flags |= V4L2_CTRL_FLAG_UPDATE;
+ pdev->restore_factory = v4l2_ctrl_new_custom(hdl,
+ &pwc_restore_factory_cfg,
+ NULL);
+ if (pdev->restore_factory)
+ pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;
+
+ /* Auto White Balance speed & delay */
+ r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+ AWB_CONTROL_SPEED_FORMATTER, &def);
+ if (r || def < 1 || def > 32)
+ def = 1;
+ cfg = pwc_awb_speed_cfg;
+ cfg.def = def;
+ pdev->awb_speed = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+ r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+ AWB_CONTROL_DELAY_FORMATTER, &def);
+ if (r || def > 63)
+ def = 0;
+ cfg = pwc_awb_delay_cfg;
+ cfg.def = def;
+ pdev->awb_delay = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+ if (!(pdev->features & FEATURE_MOTOR_PANTILT))
+ return hdl->error;
+
+ /* Motor pan / tilt / reset */
+ pdev->motor_pan = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_PAN_RELATIVE, -4480, 4480, 64, 0);
+ if (!pdev->motor_pan)
+ return hdl->error;
+ pdev->motor_tilt = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_TILT_RELATIVE, -1920, 1920, 64, 0);
+ pdev->motor_pan_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_PAN_RESET, 0, 0, 0, 0);
+ pdev->motor_tilt_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+ V4L2_CID_TILT_RESET, 0, 0, 0, 0);
+ v4l2_ctrl_cluster(4, &pdev->motor_pan);
+
+ return hdl->error;
+}
+
+static void pwc_vidioc_fill_fmt(struct v4l2_format *f,
+ int width, int height, u32 pixfmt)
+{
+ memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+ f->fmt.pix.width = width;
+ f->fmt.pix.height = height;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.pixelformat = pixfmt;
+ f->fmt.pix.bytesperline = f->fmt.pix.width;
+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.width * 3 / 2;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+ PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
+ "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
+ f->fmt.pix.width,
+ f->fmt.pix.height,
+ f->fmt.pix.bytesperline,
+ f->fmt.pix.sizeimage,
+ (f->fmt.pix.pixelformat)&255,
+ (f->fmt.pix.pixelformat>>8)&255,
+ (f->fmt.pix.pixelformat>>16)&255,
+ (f->fmt.pix.pixelformat>>24)&255);
+}
+
+/* ioctl(VIDIOC_TRY_FMT) */
+static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+ int size;
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+ return -EINVAL;
+ }
+
+ switch (f->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_YUV420:
+ break;
+ case V4L2_PIX_FMT_PWC1:
+ if (DEVICE_USE_CODEC23(pdev->type)) {
+ PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");
+ return -EINVAL;
+ }
+ break;
+ case V4L2_PIX_FMT_PWC2:
+ if (DEVICE_USE_CODEC1(pdev->type)) {
+ PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ PWC_DEBUG_IOCTL("Unsupported pixel format\n");
+ return -EINVAL;
+
+ }
+
+ size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height);
+ pwc_vidioc_fill_fmt(f,
+ pwc_image_sizes[size][0],
+ pwc_image_sizes[size][1],
+ f->fmt.pix.pixelformat);
+
+ return 0;
+}
+
+/* ioctl(VIDIOC_SET_FMT) */
+
+static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+ int ret, pixelformat, compression = 0;
+
+ ret = pwc_vidioc_try_fmt(pdev, f);
+ if (ret < 0)
+ return ret;
+
+ if (vb2_is_busy(&pdev->vb_queue))
+ return -EBUSY;
+
+ pixelformat = f->fmt.pix.pixelformat;
+
+ PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
+ "format=%c%c%c%c\n",
+ f->fmt.pix.width, f->fmt.pix.height, pdev->vframes,
+ (pixelformat)&255,
+ (pixelformat>>8)&255,
+ (pixelformat>>16)&255,
+ (pixelformat>>24)&255);
+
+ ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height,
+ pixelformat, 30, &compression, 0);
+
+ PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
+
+ pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
+ return ret;
+}
+
+static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+
+ strcpy(cap->driver, PWC_NAME);
+ strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card));
+ usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+ V4L2_CAP_READWRITE;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+ if (i->index) /* Only one INPUT is supported */
+ return -EINVAL;
+
+ strlcpy(i->name, "Camera", sizeof(i->name));
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ return 0;
+}
+
+static int pwc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int pwc_s_input(struct file *file, void *fh, unsigned int i)
+{
+ return i ? -EINVAL : 0;
+}
+
+static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct pwc_device *pdev =
+ container_of(ctrl->handler, struct pwc_device, ctrl_handler);
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ if (pdev->color_bal_valid &&
+ (pdev->auto_white_balance->val != awb_auto ||
+ time_before(jiffies,
+ pdev->last_color_bal_update + HZ / 4))) {
+ pdev->red_balance->val = pdev->last_red_balance;
+ pdev->blue_balance->val = pdev->last_blue_balance;
+ break;
+ }
+ ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+ READ_RED_GAIN_FORMATTER,
+ &pdev->red_balance->val);
+ if (ret)
+ break;
+ ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+ READ_BLUE_GAIN_FORMATTER,
+ &pdev->blue_balance->val);
+ if (ret)
+ break;
+ pdev->last_red_balance = pdev->red_balance->val;
+ pdev->last_blue_balance = pdev->blue_balance->val;
+ pdev->last_color_bal_update = jiffies;
+ pdev->color_bal_valid = true;
+ break;
+ case V4L2_CID_AUTOGAIN:
+ if (pdev->gain_valid && time_before(jiffies,
+ pdev->last_gain_update + HZ / 4)) {
+ pdev->gain->val = pdev->last_gain;
+ break;
+ }
+ ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+ READ_AGC_FORMATTER, &pdev->gain->val);
+ if (ret)
+ break;
+ pdev->last_gain = pdev->gain->val;
+ pdev->last_gain_update = jiffies;
+ pdev->gain_valid = true;
+ if (!DEVICE_USE_CODEC3(pdev->type))
+ break;
+ /* Fall through for CODEC3 where autogain also controls expo */
+ case V4L2_CID_EXPOSURE_AUTO:
+ if (pdev->exposure_valid && time_before(jiffies,
+ pdev->last_exposure_update + HZ / 4)) {
+ pdev->exposure->val = pdev->last_exposure;
+ break;
+ }
+ ret = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+ READ_SHUTTER_FORMATTER,
+ &pdev->exposure->val);
+ if (ret)
+ break;
+ pdev->last_exposure = pdev->exposure->val;
+ pdev->last_exposure_update = jiffies;
+ pdev->exposure_valid = true;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (ret)
+ PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret);
+
+ return ret;
+}
+
+static int pwc_set_awb(struct pwc_device *pdev)
+{
+ int ret;
+
+ if (pdev->auto_white_balance->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+ WB_MODE_FORMATTER,
+ pdev->auto_white_balance->val);
+ if (ret)
+ return ret;
+
+ if (pdev->auto_white_balance->val != awb_manual)
+ pdev->color_bal_valid = false; /* Force cache update */
+
+ /*
+ * If this is a preset, update our red / blue balance values
+ * so that events get generated for the new preset values
+ */
+ if (pdev->auto_white_balance->val == awb_indoor ||
+ pdev->auto_white_balance->val == awb_outdoor ||
+ pdev->auto_white_balance->val == awb_fl)
+ pwc_g_volatile_ctrl(pdev->auto_white_balance);
+ }
+ if (pdev->auto_white_balance->val != awb_manual)
+ return 0;
+
+ if (pdev->red_balance->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+ PRESET_MANUAL_RED_GAIN_FORMATTER,
+ pdev->red_balance->val);
+ if (ret)
+ return ret;
+ }
+
+ if (pdev->blue_balance->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+ PRESET_MANUAL_BLUE_GAIN_FORMATTER,
+ pdev->blue_balance->val);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/* For CODEC2 models which have separate autogain and auto exposure */
+static int pwc_set_autogain(struct pwc_device *pdev)
+{
+ int ret;
+
+ if (pdev->autogain->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ AGC_MODE_FORMATTER,
+ pdev->autogain->val ? 0 : 0xff);
+ if (ret)
+ return ret;
+
+ if (pdev->autogain->val)
+ pdev->gain_valid = false; /* Force cache update */
+ }
+
+ if (pdev->autogain->val)
+ return 0;
+
+ if (pdev->gain->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ PRESET_AGC_FORMATTER,
+ pdev->gain->val);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/* For CODEC2 models which have separate autogain and auto exposure */
+static int pwc_set_exposure_auto(struct pwc_device *pdev)
+{
+ int ret;
+ int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO;
+
+ if (pdev->exposure_auto->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ SHUTTER_MODE_FORMATTER,
+ is_auto ? 0 : 0xff);
+ if (ret)
+ return ret;
+
+ if (is_auto)
+ pdev->exposure_valid = false; /* Force cache update */
+ }
+
+ if (is_auto)
+ return 0;
+
+ if (pdev->exposure->is_new) {
+ ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
+ PRESET_SHUTTER_FORMATTER,
+ pdev->exposure->val);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/* For CODEC3 models which have autogain controlling both gain and exposure */
+static int pwc_set_autogain_expo(struct pwc_device *pdev)
+{
+ int ret;
+
+ if (pdev->autogain->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ AGC_MODE_FORMATTER,
+ pdev->autogain->val ? 0 : 0xff);
+ if (ret)
+ return ret;
+
+ if (pdev->autogain->val) {
+ pdev->gain_valid = false; /* Force cache update */
+ pdev->exposure_valid = false; /* Force cache update */
+ }
+ }
+
+ if (pdev->autogain->val)
+ return 0;
+
+ if (pdev->gain->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ PRESET_AGC_FORMATTER,
+ pdev->gain->val);
+ if (ret)
+ return ret;
+ }
+
+ if (pdev->exposure->is_new) {
+ ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
+ PRESET_SHUTTER_FORMATTER,
+ pdev->exposure->val);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int pwc_set_motor(struct pwc_device *pdev)
+{
+ int ret;
+
+ pdev->ctrl_buf[0] = 0;
+ if (pdev->motor_pan_reset->is_new)
+ pdev->ctrl_buf[0] |= 0x01;
+ if (pdev->motor_tilt_reset->is_new)
+ pdev->ctrl_buf[0] |= 0x02;
+ if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
+ ret = send_control_msg(pdev, SET_MPT_CTL,
+ PT_RESET_CONTROL_FORMATTER,
+ pdev->ctrl_buf, 1);
+ if (ret < 0)
+ return ret;
+ }
+
+ memset(pdev->ctrl_buf, 0, 4);
+ if (pdev->motor_pan->is_new) {
+ pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF;
+ pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8);
+ }
+ if (pdev->motor_tilt->is_new) {
+ pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF;
+ pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8);
+ }
+ if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
+ ret = send_control_msg(pdev, SET_MPT_CTL,
+ PT_RELATIVE_CONTROL_FORMATTER,
+ pdev->ctrl_buf, 4);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct pwc_device *pdev =
+ container_of(ctrl->handler, struct pwc_device, ctrl_handler);
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ BRIGHTNESS_FORMATTER, ctrl->val);
+ break;
+ case V4L2_CID_CONTRAST:
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ CONTRAST_FORMATTER, ctrl->val);
+ break;
+ case V4L2_CID_SATURATION:
+ ret = pwc_set_s8_ctrl(pdev, SET_CHROM_CTL,
+ pdev->saturation_fmt, ctrl->val);
+ break;
+ case V4L2_CID_GAMMA:
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ GAMMA_FORMATTER, ctrl->val);
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ret = pwc_set_awb(pdev);
+ break;
+ case V4L2_CID_AUTOGAIN:
+ if (DEVICE_USE_CODEC2(pdev->type))
+ ret = pwc_set_autogain(pdev);
+ else if (DEVICE_USE_CODEC3(pdev->type))
+ ret = pwc_set_autogain_expo(pdev);
+ else
+ ret = -EINVAL;
+ break;
+ case V4L2_CID_EXPOSURE_AUTO:
+ if (DEVICE_USE_CODEC2(pdev->type))
+ ret = pwc_set_exposure_auto(pdev);
+ else
+ ret = -EINVAL;
+ break;
+ case V4L2_CID_COLORFX:
+ ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+ COLOUR_MODE_FORMATTER,
+ ctrl->val ? 0 : 0xff);
+ break;
+ case PWC_CID_CUSTOM(autocontour):
+ if (pdev->autocontour->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ AUTO_CONTOUR_FORMATTER,
+ pdev->autocontour->val ? 0 : 0xff);
+ }
+ if (ret == 0 && pdev->contour->is_new) {
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ PRESET_CONTOUR_FORMATTER,
+ pdev->contour->val);
+ }
+ break;
+ case V4L2_CID_BACKLIGHT_COMPENSATION:
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ BACK_LIGHT_COMPENSATION_FORMATTER,
+ ctrl->val ? 0 : 0xff);
+ break;
+ case V4L2_CID_BAND_STOP_FILTER:
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ FLICKERLESS_MODE_FORMATTER,
+ ctrl->val ? 0 : 0xff);
+ break;
+ case PWC_CID_CUSTOM(noise_reduction):
+ ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+ DYNAMIC_NOISE_CONTROL_FORMATTER,
+ ctrl->val);
+ break;
+ case PWC_CID_CUSTOM(save_user):
+ ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
+ break;
+ case PWC_CID_CUSTOM(restore_user):
+ ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
+ break;
+ case PWC_CID_CUSTOM(restore_factory):
+ ret = pwc_button_ctrl(pdev,
+ RESTORE_FACTORY_DEFAULTS_FORMATTER);
+ break;
+ case PWC_CID_CUSTOM(awb_speed):
+ ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+ AWB_CONTROL_SPEED_FORMATTER,
+ ctrl->val);
+ break;
+ case PWC_CID_CUSTOM(awb_delay):
+ ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+ AWB_CONTROL_DELAY_FORMATTER,
+ ctrl->val);
+ break;
+ case V4L2_CID_PAN_RELATIVE:
+ ret = pwc_set_motor(pdev);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (ret)
+ PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret);
+
+ return ret;
+}
+
+static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+
+ /* We only support two format: the raw format, and YUV */
+ switch (f->index) {
+ case 0:
+ /* RAW format */
+ f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2;
+ f->flags = V4L2_FMT_FLAG_COMPRESSED;
+ strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description));
+ break;
+ case 1:
+ f->pixelformat = V4L2_PIX_FMT_YUV420;
+ strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description));
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
+ pdev->width, pdev->height);
+ pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
+ return 0;
+}
+
+static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+
+ return pwc_vidioc_try_fmt(pdev, f);
+}
+
+static int pwc_enum_framesizes(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+ unsigned int i = 0, index = fsize->index;
+
+ if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 ||
+ (fsize->pixel_format == V4L2_PIX_FMT_PWC1 &&
+ DEVICE_USE_CODEC1(pdev->type)) ||
+ (fsize->pixel_format == V4L2_PIX_FMT_PWC2 &&
+ DEVICE_USE_CODEC23(pdev->type))) {
+ for (i = 0; i < PSZ_MAX; i++) {
+ if (!(pdev->image_mask & (1UL << i)))
+ continue;
+ if (!index--) {
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = pwc_image_sizes[i][0];
+ fsize->discrete.height = pwc_image_sizes[i][1];
+ return 0;
+ }
+ }
+ }
+ return -EINVAL;
+}
+
+static int pwc_enum_frameintervals(struct file *file, void *fh,
+ struct v4l2_frmivalenum *fival)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+ int size = -1;
+ unsigned int i;
+
+ for (i = 0; i < PSZ_MAX; i++) {
+ if (pwc_image_sizes[i][0] == fival->width &&
+ pwc_image_sizes[i][1] == fival->height) {
+ size = i;
+ break;
+ }
+ }
+
+ /* TODO: Support raw format */
+ if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420)
+ return -EINVAL;
+
+ i = pwc_get_fps(pdev, fival->index, size);
+ if (!i)
+ return -EINVAL;
+
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator = 1;
+ fival->discrete.denominator = i;
+
+ return 0;
+}
+
+static int pwc_g_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *parm)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ memset(parm, 0, sizeof(*parm));
+
+ parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ parm->parm.capture.readbuffers = MIN_FRAMES;
+ parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
+ parm->parm.capture.timeperframe.denominator = pdev->vframes;
+ parm->parm.capture.timeperframe.numerator = 1;
+
+ return 0;
+}
+
+static int pwc_s_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *parm)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+ int compression = 0;
+ int ret, fps;
+
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ /* If timeperframe == 0, then reset the framerate to the nominal value.
+ We pick a high framerate here, and let pwc_set_video_mode() figure
+ out the best match. */
+ if (parm->parm.capture.timeperframe.numerator == 0 ||
+ parm->parm.capture.timeperframe.denominator == 0)
+ fps = 30;
+ else
+ fps = parm->parm.capture.timeperframe.denominator /
+ parm->parm.capture.timeperframe.numerator;
+
+ if (vb2_is_busy(&pdev->vb_queue))
+ return -EBUSY;
+
+ ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+ fps, &compression, 0);
+
+ pwc_g_parm(file, fh, parm);
+
+ return ret;
+}
+
+const struct v4l2_ioctl_ops pwc_ioctl_ops = {
+ .vidioc_querycap = pwc_querycap,
+ .vidioc_enum_input = pwc_enum_input,
+ .vidioc_g_input = pwc_g_input,
+ .vidioc_s_input = pwc_s_input,
+ .vidioc_enum_fmt_vid_cap = pwc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = pwc_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = pwc_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = pwc_try_fmt_vid_cap,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_enum_framesizes = pwc_enum_framesizes,
+ .vidioc_enum_frameintervals = pwc_enum_frameintervals,
+ .vidioc_g_parm = pwc_g_parm,
+ .vidioc_s_parm = pwc_s_parm,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
diff --git a/drivers/media/usb/pwc/pwc.h b/drivers/media/usb/pwc/pwc.h
new file mode 100644
index 00000000000..7a6a0d39c2c
--- /dev/null
+++ b/drivers/media/usb/pwc/pwc.h
@@ -0,0 +1,393 @@
+/* (C) 1999-2003 Nemosoft Unv.
+ (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef PWC_H
+#define PWC_H
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/errno.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+#include <linux/input.h>
+#endif
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+/* Version block */
+#define PWC_VERSION "10.0.15"
+#define PWC_NAME "pwc"
+#define PFX PWC_NAME ": "
+
+
+/* Trace certain actions in the driver */
+#define PWC_DEBUG_LEVEL_MODULE (1<<0)
+#define PWC_DEBUG_LEVEL_PROBE (1<<1)
+#define PWC_DEBUG_LEVEL_OPEN (1<<2)
+#define PWC_DEBUG_LEVEL_READ (1<<3)
+#define PWC_DEBUG_LEVEL_MEMORY (1<<4)
+#define PWC_DEBUG_LEVEL_FLOW (1<<5)
+#define PWC_DEBUG_LEVEL_SIZE (1<<6)
+#define PWC_DEBUG_LEVEL_IOCTL (1<<7)
+#define PWC_DEBUG_LEVEL_TRACE (1<<8)
+
+#define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args)
+#define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args)
+#define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args)
+#define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args)
+#define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args)
+#define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args)
+#define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args)
+#define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args)
+#define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
+
+
+#ifdef CONFIG_USB_PWC_DEBUG
+
+#define PWC_DEBUG_LEVEL (PWC_DEBUG_LEVEL_MODULE)
+
+#define PWC_DEBUG(level, fmt, args...) do {\
+ if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \
+ printk(KERN_DEBUG PFX fmt, ##args); \
+ } while (0)
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
+
+#else /* if ! CONFIG_USB_PWC_DEBUG */
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) do { } while(0)
+#define PWC_DEBUG(level, fmt, args...) do { } while(0)
+
+#define pwc_trace 0
+
+#endif
+
+/* Defines for ToUCam cameras */
+#define TOUCAM_HEADER_SIZE 8
+#define TOUCAM_TRAILER_SIZE 4
+
+#define FEATURE_MOTOR_PANTILT 0x0001
+#define FEATURE_CODEC1 0x0002
+#define FEATURE_CODEC2 0x0004
+
+#define MAX_WIDTH 640
+#define MAX_HEIGHT 480
+
+/* Ignore errors in the first N frames, to allow for startup delays */
+#define FRAME_LOWMARK 5
+
+/* Size and number of buffers for the ISO pipe. */
+#define MAX_ISO_BUFS 3
+#define ISO_FRAMES_PER_DESC 10
+#define ISO_MAX_FRAME_SIZE 960
+#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
+
+/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
+#define PWC_FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
+
+/* Absolute minimum and maximum number of buffers available for mmap() */
+#define MIN_FRAMES 2
+#define MAX_FRAMES 16
+
+/* Some macros to quickly find the type of a webcam */
+#define DEVICE_USE_CODEC1(x) ((x)<675)
+#define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700)
+#define DEVICE_USE_CODEC3(x) ((x)>=700)
+#define DEVICE_USE_CODEC23(x) ((x)>=675)
+
+/* Request types: video */
+#define SET_LUM_CTL 0x01
+#define GET_LUM_CTL 0x02
+#define SET_CHROM_CTL 0x03
+#define GET_CHROM_CTL 0x04
+#define SET_STATUS_CTL 0x05
+#define GET_STATUS_CTL 0x06
+#define SET_EP_STREAM_CTL 0x07
+#define GET_EP_STREAM_CTL 0x08
+#define GET_XX_CTL 0x09
+#define SET_XX_CTL 0x0A
+#define GET_XY_CTL 0x0B
+#define SET_XY_CTL 0x0C
+#define SET_MPT_CTL 0x0D
+#define GET_MPT_CTL 0x0E
+
+/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
+#define AGC_MODE_FORMATTER 0x2000
+#define PRESET_AGC_FORMATTER 0x2100
+#define SHUTTER_MODE_FORMATTER 0x2200
+#define PRESET_SHUTTER_FORMATTER 0x2300
+#define PRESET_CONTOUR_FORMATTER 0x2400
+#define AUTO_CONTOUR_FORMATTER 0x2500
+#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600
+#define CONTRAST_FORMATTER 0x2700
+#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800
+#define FLICKERLESS_MODE_FORMATTER 0x2900
+#define AE_CONTROL_SPEED 0x2A00
+#define BRIGHTNESS_FORMATTER 0x2B00
+#define GAMMA_FORMATTER 0x2C00
+
+/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
+#define WB_MODE_FORMATTER 0x1000
+#define AWB_CONTROL_SPEED_FORMATTER 0x1100
+#define AWB_CONTROL_DELAY_FORMATTER 0x1200
+#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300
+#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400
+#define COLOUR_MODE_FORMATTER 0x1500
+#define SATURATION_MODE_FORMATTER1 0x1600
+#define SATURATION_MODE_FORMATTER2 0x1700
+
+/* Selectors for the Status controls [GS]ET_STATUS_CTL */
+#define SAVE_USER_DEFAULTS_FORMATTER 0x0200
+#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300
+#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400
+#define READ_AGC_FORMATTER 0x0500
+#define READ_SHUTTER_FORMATTER 0x0600
+#define READ_RED_GAIN_FORMATTER 0x0700
+#define READ_BLUE_GAIN_FORMATTER 0x0800
+
+/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
+#define PT_RELATIVE_CONTROL_FORMATTER 0x01
+#define PT_RESET_CONTROL_FORMATTER 0x02
+#define PT_STATUS_FORMATTER 0x03
+
+/* Enumeration of image sizes */
+#define PSZ_SQCIF 0x00
+#define PSZ_QSIF 0x01
+#define PSZ_QCIF 0x02
+#define PSZ_SIF 0x03
+#define PSZ_CIF 0x04
+#define PSZ_VGA 0x05
+#define PSZ_MAX 6
+
+struct pwc_raw_frame {
+ __le16 type; /* type of the webcam */
+ __le16 vbandlength; /* Size of 4 lines compressed (used by the
+ decompressor) */
+ __u8 cmd[4]; /* the four byte of the command (in case of
+ nala, only the first 3 bytes is filled) */
+ __u8 rawframe[0]; /* frame_size = H / 4 * vbandlength */
+} __packed;
+
+/* intermediate buffers with raw data from the USB cam */
+struct pwc_frame_buf
+{
+ struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
+ struct list_head list;
+ void *data;
+ int filled; /* number of bytes filled */
+};
+
+struct pwc_device
+{
+ struct video_device vdev;
+ struct v4l2_device v4l2_dev;
+
+ /* videobuf2 queue and queued buffers list */
+ struct vb2_queue vb_queue;
+ struct list_head queued_bufs;
+ spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+
+ /* Note if taking both locks v4l2_lock must always be locked first! */
+ struct mutex v4l2_lock; /* Protects everything else */
+ struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */
+
+ /* Pointer to our usb_device, will be NULL after unplug */
+ struct usb_device *udev; /* Both mutexes most be hold when setting! */
+
+ /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
+ int type;
+ int release; /* release number */
+ int features; /* feature bits */
+
+ /*** Video data ***/
+ int vendpoint; /* video isoc endpoint */
+ int vcinterface; /* video control interface */
+ int valternate; /* alternate interface needed */
+ int vframes; /* frames-per-second */
+ int pixfmt; /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */
+ int vframe_count; /* received frames */
+ int vmax_packet_size; /* USB maxpacket size */
+ int vlast_packet_size; /* for frame synchronisation */
+ int visoc_errors; /* number of contiguous ISOC errors */
+ int vbandlength; /* compressed band length; 0 is uncompressed */
+ char vsync; /* used by isoc handler */
+ char vmirror; /* for ToUCaM series */
+ char power_save; /* Do powersaving for this cam */
+
+ unsigned char cmd_buf[13];
+ unsigned char *ctrl_buf;
+
+ struct urb *urbs[MAX_ISO_BUFS];
+
+ /*
+ * Frame currently being filled, this only gets touched by the
+ * isoc urb complete handler, and by stream start / stop since
+ * start / stop touch it before / after starting / killing the urbs
+ * no locking is needed around this
+ */
+ struct pwc_frame_buf *fill_buf;
+
+ int frame_header_size, frame_trailer_size;
+ int frame_size;
+ int frame_total_size; /* including header & trailer */
+ int drop_frames;
+
+ union { /* private data for decompression engine */
+ struct pwc_dec1_private dec1;
+ struct pwc_dec23_private dec23;
+ };
+
+ /*
+ * We have an 'image' and a 'view', where 'image' is the fixed-size img
+ * as delivered by the camera, and 'view' is the size requested by the
+ * program. The camera image is centered in this viewport, laced with
+ * a gray or black border. view_min <= image <= view <= view_max;
+ */
+ int image_mask; /* supported sizes */
+ int width, height; /* current resolution */
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+ struct input_dev *button_dev; /* webcam snapshot button input */
+ char button_phys[64];
+#endif
+
+ /* controls */
+ struct v4l2_ctrl_handler ctrl_handler;
+ u16 saturation_fmt;
+ struct v4l2_ctrl *brightness;
+ struct v4l2_ctrl *contrast;
+ struct v4l2_ctrl *saturation;
+ struct v4l2_ctrl *gamma;
+ struct {
+ /* awb / red-blue balance cluster */
+ struct v4l2_ctrl *auto_white_balance;
+ struct v4l2_ctrl *red_balance;
+ struct v4l2_ctrl *blue_balance;
+ /* usb ctrl transfers are slow, so we cache things */
+ int color_bal_valid;
+ unsigned long last_color_bal_update; /* In jiffies */
+ s32 last_red_balance;
+ s32 last_blue_balance;
+ };
+ struct {
+ /* autogain / gain cluster */
+ struct v4l2_ctrl *autogain;
+ struct v4l2_ctrl *gain;
+ int gain_valid;
+ unsigned long last_gain_update; /* In jiffies */
+ s32 last_gain;
+ };
+ struct {
+ /* exposure_auto / exposure cluster */
+ struct v4l2_ctrl *exposure_auto;
+ struct v4l2_ctrl *exposure;
+ int exposure_valid;
+ unsigned long last_exposure_update; /* In jiffies */
+ s32 last_exposure;
+ };
+ struct v4l2_ctrl *colorfx;
+ struct {
+ /* autocontour/contour cluster */
+ struct v4l2_ctrl *autocontour;
+ struct v4l2_ctrl *contour;
+ };
+ struct v4l2_ctrl *backlight;
+ struct v4l2_ctrl *flicker;
+ struct v4l2_ctrl *noise_reduction;
+ struct v4l2_ctrl *save_user;
+ struct v4l2_ctrl *restore_user;
+ struct v4l2_ctrl *restore_factory;
+ struct v4l2_ctrl *awb_speed;
+ struct v4l2_ctrl *awb_delay;
+ struct {
+ /* motor control cluster */
+ struct v4l2_ctrl *motor_pan;
+ struct v4l2_ctrl *motor_tilt;
+ struct v4l2_ctrl *motor_pan_reset;
+ struct v4l2_ctrl *motor_tilt_reset;
+ };
+ /* CODEC3 models have both gain and exposure controlled by autogain */
+ struct v4l2_ctrl *autogain_expo_cluster[3];
+};
+
+/* Global variables */
+#ifdef CONFIG_USB_PWC_DEBUG
+extern int pwc_trace;
+#endif
+
+/** Functions in pwc-misc.c */
+/* sizes in pixels */
+extern const int pwc_image_sizes[PSZ_MAX][2];
+
+int pwc_get_size(struct pwc_device *pdev, int width, int height);
+void pwc_construct(struct pwc_device *pdev);
+
+/** Functions in pwc-ctrl.c */
+/* Request a certain video mode. Returns < 0 if not possible */
+extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
+ int pixfmt, int frames, int *compression, int send_to_cam);
+extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
+extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
+extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
+extern int send_control_msg(struct pwc_device *pdev,
+ u8 request, u16 value, void *buf, int buflen);
+
+/* Control get / set helpers */
+int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
+int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data);
+int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
+#define pwc_set_s8_ctrl pwc_set_u8_ctrl
+int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *dat);
+int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data);
+int pwc_button_ctrl(struct pwc_device *pdev, u16 value);
+int pwc_init_controls(struct pwc_device *pdev);
+
+/* Power down or up the camera; not supported by all models */
+extern void pwc_camera_power(struct pwc_device *pdev, int power);
+
+extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
+
+/** pwc-uncompress.c */
+/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
+int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf);
+
+#endif