Index: stk11xx-dev.c =================================================================== --- stk11xx-dev.c (revision 82) +++ stk11xx-dev.c (working copy) @@ -65,6 +65,9 @@ int ret; switch (dev->webcam_model) { + case SYNTEK_STK_0408: + ret = dev_stk0408_initialize_device(dev); + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: ret = dev_stka311_initialize_device(dev); @@ -117,6 +120,9 @@ int ret; switch (dev->webcam_model) { + case SYNTEK_STK_0408: + ret = dev_stk0408_init_camera(dev); + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: ret = dev_stka311_init_camera(dev); @@ -171,10 +177,9 @@ { int i; int value; - for (i=0; iwebcam_model) { + case SYNTEK_STK_0408: + ret = dev_stk0408_camera_asleep(dev); + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: ret = dev_stka311_camera_asleep(dev); @@ -344,6 +352,9 @@ int ret; switch (dev->webcam_model) { + case SYNTEK_STK_0408: + ret = dev_stk0408_camera_settings(dev); + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: ret = dev_stka311_camera_settings(dev); @@ -399,6 +410,9 @@ int ret; switch (dev->webcam_model) { + case SYNTEK_STK_0408: + ret = dev_stk0408_set_camera_quality(dev); + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: ret = dev_stka311_set_camera_quality(dev); @@ -451,6 +465,9 @@ int ret; switch (dev->webcam_model) { + case SYNTEK_STK_0408: + ret = dev_stk0408_set_camera_fps(dev); + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: ret = dev_stka311_set_camera_fps(dev); @@ -503,6 +520,9 @@ int ret; switch (dev->webcam_model) { + case SYNTEK_STK_0408: + ret = dev_stk0408_start_stream(dev); + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: ret = dev_stka311_start_stream(dev); @@ -554,6 +574,9 @@ int ret; switch (dev->webcam_model) { + case SYNTEK_STK_0408: + ret = dev_stk0408_reconf_camera(dev); + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: ret = dev_stka311_reconf_camera(dev); @@ -606,6 +629,9 @@ int ret; switch (dev->webcam_model) { + case SYNTEK_STK_0408: + ret = dev_stk0408_stop_stream(dev); + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: ret = dev_stka311_stop_stream(dev); @@ -642,3 +668,42 @@ return ret; } +/** + * @param dev Device structure + * + * @returns 0 if all is OK + * + * @brief Decompress/convert a frame from the video stream + * + * @param dev Device structure + */ +int dev_stk11xx_decompress(struct usb_stk11xx *dev) +{ + int ret; + + switch (dev->webcam_model) { + +/* uvyv based video streams */ + case SYNTEK_STK_0408: + ret = dev_stk0408_decode(dev); + break; + +/* Bayer based video streams */ + case SYNTEK_STK_M811: + case SYNTEK_STK_A311: + case SYNTEK_STK_A821: + case SYNTEK_STK_6A31: + case SYNTEK_STK_6A33: + case SYNTEK_STK_6A51: + case SYNTEK_STK_6A54: + case SYNTEK_STK_6D51: + ret = stk11xx_decompress(dev); + break; + + default: + ret = -1; + } + + return ret; +} + Index: stk11xx-dev.h =================================================================== --- stk11xx-dev.h (revision 82) +++ stk11xx-dev.h (working copy) @@ -34,6 +34,18 @@ #ifndef STK11XX_DEV_H #define STK11XX_DEV_H +int dev_stk0408_initialize_device(struct usb_stk11xx *); +int dev_stk0408_configure_device(struct usb_stk11xx *, int); +int dev_stk0408_start_stream(struct usb_stk11xx *); +int dev_stk0408_stop_stream(struct usb_stk11xx *); +int dev_stk0408_camera_asleep(struct usb_stk11xx *); +int dev_stk0408_init_camera(struct usb_stk11xx *); +int dev_stk0408_sensor_settings(struct usb_stk11xx *); +int dev_stk0408_reconf_camera(struct usb_stk11xx *); +int dev_stk0408_camera_settings(struct usb_stk11xx *); +int dev_stk0408_set_camera_quality(struct usb_stk11xx *); +int dev_stk0408_set_camera_fps(struct usb_stk11xx *); +int dev_stk0408_decode(struct usb_stk11xx *); int dev_stka311_initialize_device(struct usb_stk11xx *); int dev_stka311_configure_device(struct usb_stk11xx *, int); Index: stk11xx-usb.c =================================================================== --- stk11xx-usb.c (revision 82) +++ stk11xx-usb.c (working copy) @@ -106,6 +106,7 @@ { USB_DEVICE(USB_SYNTEK1_VENDOR_ID, USB_STK_6D51_PRODUCT_ID) }, { USB_DEVICE(USB_SYNTEK2_VENDOR_ID, USB_STK_0501_PRODUCT_ID) }, + { USB_DEVICE(USB_SYNTEK2_VENDOR_ID, USB_STK_0408_PRODUCT_ID) }, { } }; @@ -368,9 +369,21 @@ skip = 8; } + if (framelen == 8) //odd or even frame flag + { + if (*iso_buf & 0x40) + { + framebuf->odd = true; + } + else + { + framebuf->odd = false; + } + } + // Our buffer is full !!! if (framelen - skip + framebuf->filled > dev->frame_size) { - STK_ERROR("Frame buffer overflow !\n"); + STK_ERROR("Frame buffer overflow %d %d %d!\n", framelen, framelen-skip+framebuf->filled, dev->frame_size); framebuf->errors++; } // All is OK @@ -378,7 +391,7 @@ memcpy(fill, iso_buf + skip, framelen - skip); fill += framelen - skip; } - + // New size of our buffer framebuf->filled += framelen - skip; } @@ -400,7 +413,7 @@ } else dev->vframes_error++; - + awake = 1; framebuf = dev->fill_frame; framebuf->filled = 0; @@ -612,6 +625,17 @@ static int usb_stk11xx_default_settings(struct usb_stk11xx *dev) { switch (dev->webcam_model) { + case SYNTEK_STK_0408: + dev->vsettings.fps = (default_fps == -1) ? 25 : default_fps; + dev->vsettings.vflip = (default_vflip == -1) ? 0 : default_vflip; + dev->vsettings.hflip = (default_hflip == -1) ? 0 : default_hflip; + + dev->vsettings.brightness = (default_brightness == -1) ? STK11XX_PERCENT(50, 0xFFFF) : default_brightness; + dev->vsettings.whiteness = (default_whiteness == -1) ? STK11XX_PERCENT(50, 0xFFFF) : default_whiteness; + dev->vsettings.contrast = (default_contrast == -1) ? STK11XX_PERCENT(50, 0xFFFF) : default_contrast; + dev->vsettings.colour = (default_colour == -1) ? STK11XX_PERCENT(50, 0xFFFF) : default_colour; + dev->vsettings.input = 1; + break; case SYNTEK_STK_M811: case SYNTEK_STK_A311: dev->vsettings.fps = (default_fps == -1) ? 25 : default_fps; @@ -771,6 +795,12 @@ } else if (vendor_id == USB_SYNTEK2_VENDOR_ID) { switch (product_id) { + case USB_STK_0408_PRODUCT_ID: + STK_INFO("Syntek USB2.0 - STK-1160 based device found.\n"); + STK_INFO("Syntek AVStream USB2.0 Video Capture - Product ID 0x0408.\n"); + webcam_model = SYNTEK_STK_0408; + webcam_type = STK11XX_PAL; + break; case USB_STK_0501_PRODUCT_ID: STK_INFO("Syntek USB2.0 - STK-1135 based webcam found.\n"); STK_INFO("Syntek AVStream USB2.0 1.3M WebCam - Product ID 0x0501.\n"); @@ -816,7 +846,7 @@ // Constructor - dev->nbuffers = 2; + dev->nbuffers = 3; dev->len_per_image = PAGE_ALIGN((1280 * 1024 * 4)); Index: stk11xx-v4l.c =================================================================== --- stk11xx-v4l.c (revision 82) +++ stk11xx-v4l.c (working copy) @@ -48,17 +48,19 @@ #include #include #include - #include "stk11xx.h" static struct file_operations v4l_stk11xx_fops; +int dev_stk0408_select_video_mode(struct usb_stk11xx *dev, int width, int height); +int dev_stk0408_select_input(struct usb_stk11xx *dev, int input); /** * @var stk11xx_image_sizes * List of all resolutions supported by the driver */ + const struct stk11xx_coord stk11xx_image_sizes[STK11XX_NBR_SIZES] = { { 80, 60 }, { 128, 96 }, @@ -66,6 +68,7 @@ { 213, 160 }, { 320, 240 }, { 640, 480 }, + { 720, 576 }, { 800, 600 }, { 1024, 768 }, { 1280, 1024 } @@ -113,6 +116,15 @@ .step = 1, .default_value = 0x7f00, }, + { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = 0, + .maximum = 0xff00, + .step = 1, + .default_value = 0x7f00, + }, }; @@ -132,7 +144,14 @@ int i; int find; - +/* + * override select video mode for 408 + */ + if (dev->webcam_model == SYNTEK_STK_0408) + { + return dev_stk0408_select_video_mode(dev, width, height); + } + // Check width and height // Notice : this test is usefull for the Kopete application ! @@ -146,18 +165,18 @@ // Driver can't build an image bigger than the maximal resolution ! switch (dev->webcam_type) { case STK11XX_SXGA: - if ((width > stk11xx_image_sizes[STK11XX_NBR_SIZES-1].x) - || (height > stk11xx_image_sizes[STK11XX_NBR_SIZES-1].y)) { - width = stk11xx_image_sizes[STK11XX_NBR_SIZES-1].x; - height = stk11xx_image_sizes[STK11XX_NBR_SIZES-1].y; + if ((width > stk11xx_image_sizes[STK11XX_1280x1024].x) + || (height > stk11xx_image_sizes[STK11XX_1280x1024].y)) { + width = stk11xx_image_sizes[STK11XX_1280x1024].x; + height = stk11xx_image_sizes[STK11XX_1280x1024].y; } break; case STK11XX_VGA: - if ((width > stk11xx_image_sizes[STK11XX_NBR_SIZES-3-1].x) - || (height > stk11xx_image_sizes[STK11XX_NBR_SIZES-3-1].y)) { - width = stk11xx_image_sizes[STK11XX_NBR_SIZES-3-1].x; - height = stk11xx_image_sizes[STK11XX_NBR_SIZES-3-1].y; + if ((width > stk11xx_image_sizes[STK11XX_640x480].x) + || (height > stk11xx_image_sizes[STK11XX_640x480].y)) { + width = stk11xx_image_sizes[STK11XX_640x480].x; + height = stk11xx_image_sizes[STK11XX_640x480].y; } break; @@ -169,14 +188,14 @@ // Seek the best resolution switch (dev->webcam_type) { case STK11XX_SXGA: - for (i=0, find=0; ivframes_error = 0; dev->vframes_dumped = 0; dev->vsettings.hue = 0xffff; + dev->vsettings.whiteness = 0xffff; dev->vsettings.depth = 24; dev->vsettings.palette = STK11XX_PALETTE_BGR24; @@ -631,6 +651,13 @@ cap->maxheight = stk11xx_image_sizes[STK11XX_1280x1024].y; break; + case STK11XX_PAL: + cap->minwidth = stk11xx_image_sizes[STK11XX_640x480].x; + cap->minheight = stk11xx_image_sizes[STK11XX_640x480].y; + cap->maxwidth = stk11xx_image_sizes[STK11XX_720x576].x; + cap->maxheight = stk11xx_image_sizes[STK11XX_720x576].y; + break; + case STK11XX_VGA: cap->minwidth = stk11xx_image_sizes[STK11XX_80x60].x; cap->minheight = stk11xx_image_sizes[STK11XX_80x60].y; @@ -880,7 +907,7 @@ int *mbuf = arg; STK_DEBUG("VIDIOCSYNC\n"); - + if (*mbuf < 0 || *mbuf >= dev->nbuffers) return -EINVAL; @@ -970,10 +997,34 @@ STK_DEBUG("VIDIOC_ENUMINPUT %d\n", i->index); - if (i->index) - return -EINVAL; - - strlcpy(i->name, "USB", sizeof(i->name)); + if (dev->webcam_model != SYNTEK_STK_0408) + { + if (i->index) + return -EINVAL; + strlcpy(i->name, "USB", sizeof(i->name)); + } + else + { + if (i->index > 3) + return -EINVAL; + + switch(i->index) + { + case 0: + strlcpy(i->name,"Input1", sizeof(i->name)); + break; + case 1: + strlcpy(i->name,"Input2", sizeof(i->name)); + break; + case 2: + strlcpy(i->name,"Input3", sizeof(i->name)); + break; + case 3: + strlcpy(i->name,"Input4", sizeof(i->name)); + break; + } + } + i->type = V4L2_INPUT_TYPE_CAMERA; } break; @@ -984,8 +1035,7 @@ STK_DEBUG("GET INPUT %d\n", i->index); - if (i->index) - return -EINVAL; + return dev->vsettings.input; } break; @@ -995,8 +1045,12 @@ STK_DEBUG("SET INPUT %d\n", i->index); - if (i->index != 0) +/* TODO add input switching */ + + if (i->index > 3) return -EINVAL; + + dev->vsettings.input = i->index; } break; @@ -1038,6 +1092,10 @@ c->value = dev->vsettings.whiteness; break; + case V4L2_CID_HUE: + c->value = dev->vsettings.hue; + break; + case V4L2_CID_SATURATION: c->value = dev->vsettings.colour; break; @@ -1063,8 +1121,8 @@ dev->vsettings.brightness = (0xff00 & c->value); break; - case V4L2_CID_WHITENESS: - dev->vsettings.whiteness = (0xff00 & c->value); + case V4L2_CID_HUE: + dev->vsettings.hue = (0xff00 & c->value); break; case V4L2_CID_SATURATION: @@ -1090,9 +1148,6 @@ STK_DEBUG("VIDIOC_ENUM_FMT %d\n", fmtd->index); - if (fmtd->index != 0) - return -EINVAL; - index = fmtd->index; memset(fmtd, 0, sizeof(*fmtd)); @@ -1163,6 +1218,7 @@ pix_format.height = dev->view.y; pix_format.field = V4L2_FIELD_NONE; pix_format.colorspace = V4L2_COLORSPACE_SRGB; +// pix_format.colorspace = V4L2_COLORSPACE_SMPTE170M; pix_format.priv = 0; switch (dev->vsettings.palette) { @@ -1238,25 +1294,37 @@ switch (dev->webcam_type) { case STK11XX_SXGA: - if (fmtd->fmt.pix.width > stk11xx_image_sizes[STK11XX_NBR_SIZES-1].x) - fmtd->fmt.pix.width = stk11xx_image_sizes[STK11XX_NBR_SIZES-1].x; + if (fmtd->fmt.pix.width > stk11xx_image_sizes[STK11XX_1280x1024].x) + fmtd->fmt.pix.width = stk11xx_image_sizes[STK11XX_1280x1024].x; else if (fmtd->fmt.pix.width < stk11xx_image_sizes[0].x) fmtd->fmt.pix.width = stk11xx_image_sizes[0].x; - if (fmtd->fmt.pix.height > stk11xx_image_sizes[STK11XX_NBR_SIZES-1].y) - fmtd->fmt.pix.height = stk11xx_image_sizes[STK11XX_NBR_SIZES-1].y; + if (fmtd->fmt.pix.height > stk11xx_image_sizes[STK11XX_1280x1024].y) + fmtd->fmt.pix.height = stk11xx_image_sizes[STK11XX_1280x1024].y; else if (fmtd->fmt.pix.height < stk11xx_image_sizes[0].y) fmtd->fmt.pix.height = stk11xx_image_sizes[0].y; break; + case STK11XX_PAL: + if (fmtd->fmt.pix.width > stk11xx_image_sizes[STK11XX_720x576].x) + fmtd->fmt.pix.width = stk11xx_image_sizes[STK11XX_720x576].x; + else if (fmtd->fmt.pix.width < stk11xx_image_sizes[0].x) + fmtd->fmt.pix.width = stk11xx_image_sizes[0].x; + + if (fmtd->fmt.pix.height > stk11xx_image_sizes[STK11XX_720x576].y) + fmtd->fmt.pix.height = stk11xx_image_sizes[STK11XX_720x576].y; + else if (fmtd->fmt.pix.height < stk11xx_image_sizes[0].y) + fmtd->fmt.pix.height = stk11xx_image_sizes[0].y; + break; + case STK11XX_VGA: - if (fmtd->fmt.pix.width > stk11xx_image_sizes[STK11XX_NBR_SIZES-1-3].x) - fmtd->fmt.pix.width = stk11xx_image_sizes[STK11XX_NBR_SIZES-1-3].x; + if (fmtd->fmt.pix.width > stk11xx_image_sizes[STK11XX_640x480].x) + fmtd->fmt.pix.width = stk11xx_image_sizes[STK11XX_640x480].x; else if (fmtd->fmt.pix.width < stk11xx_image_sizes[0].x) fmtd->fmt.pix.width = stk11xx_image_sizes[0].x; - if (fmtd->fmt.pix.height > stk11xx_image_sizes[STK11XX_NBR_SIZES-1-3].y) - fmtd->fmt.pix.height = stk11xx_image_sizes[STK11XX_NBR_SIZES-1-3].y; + if (fmtd->fmt.pix.height > stk11xx_image_sizes[STK11XX_640x480].y) + fmtd->fmt.pix.height = stk11xx_image_sizes[STK11XX_640x480].y; else if (fmtd->fmt.pix.height < stk11xx_image_sizes[0].y) fmtd->fmt.pix.height = stk11xx_image_sizes[0].y; break; @@ -1386,7 +1454,7 @@ std->id = V4L2_STD_UNKNOWN; strncpy(std->name, "webcam", sizeof(std->name)); - + break; } Index: stk11xx-sysfs.c =================================================================== --- stk11xx-sysfs.c (revision 82) +++ stk11xx-sysfs.c (working copy) @@ -170,7 +170,10 @@ width = stk11xx_image_sizes[STK11XX_640x480].x; height = stk11xx_image_sizes[STK11XX_640x480].y; break; - + case STK11XX_720x576: + width = stk11xx_image_sizes[STK11XX_720x576].x; + height = stk11xx_image_sizes[STK11XX_720x576].y; + break; case STK11XX_800x600: case STK11XX_1024x768: case STK11XX_1280x1024: Index: stk11xx.h =================================================================== --- stk11xx.h (revision 82) +++ stk11xx.h (working copy) @@ -54,6 +54,7 @@ #define USB_STK_6D51_PRODUCT_ID 0x6d51 /**< Product ID of the camera DC-NEW */ #define USB_STK_0501_PRODUCT_ID 0x0501 /**< Product ID of the camera DC-1125 */ +#define USB_STK_0408_PRODUCT_ID 0x0408 /**< Product ID of the camera STK-1160 */ /** @@ -131,7 +132,7 @@ * @a Use this function like the function printf. */ #ifndef CONFIG_STK11XX_DEBUG -#define CONFIG_STK11XX_DEBUG 0 +#define CONFIG_STK11XX_DEBUG 1 #endif #if CONFIG_STK11XX_DEBUG @@ -186,7 +187,8 @@ SYNTEK_STK_6A33 = 5, SYNTEK_STK_6A51 = 6, SYNTEK_STK_6A54 = 7, - SYNTEK_STK_6D51 = 8 + SYNTEK_STK_6D51 = 8, + SYNTEK_STK_0408 = 9 } T_SYNTEK_DEVICE; @@ -196,6 +198,7 @@ typedef enum { STK11XX_VGA, /**< For VGA video camera */ STK11XX_SXGA, /**< For SXGA video camera 1.3M */ + STK11XX_PAL, /**< For PAL capture card */ STK11XX_UXGA /**< For UXGA video camera 2M */ } T_STK11XX_VIDEOMODE; @@ -210,6 +213,7 @@ STK11XX_213x160, STK11XX_320x240, STK11XX_640x480, + STK11XX_720x576, STK11XX_800x600, STK11XX_1024x768, STK11XX_1280x1024, @@ -247,6 +251,7 @@ struct stk11xx_frame_buf { int errors; void *data; + volatile bool odd; volatile int filled; struct stk11xx_frame_buf *next; }; @@ -284,6 +289,7 @@ int hue; /**< Hue setting */ int hflip; /**< Horizontal flip */ int vflip; /**< Vertical flip */ + int input; /**< Input for multiinput cards */ }; @@ -410,6 +416,7 @@ int stk11xx_handle_frame(struct usb_stk11xx *); int stk11xx_decompress(struct usb_stk11xx *); +int dev_stk11xx_decompress(struct usb_stk11xx *); #endif Index: stk11xx-dev-0408.c =================================================================== --- stk11xx-dev-0408.c (revision 0) +++ stk11xx-dev-0408.c (revision 0) @@ -0,0 +1,1224 @@ +/** + * @file stk11xx-dev-0408.c + * @author Ivor Hewitt + * @date 2009-01-01 + * @version v1.0.x + * + * @brief Driver for Syntek USB video camera + * + * @note Copyright (C) Nicolas VIVIEN + * Copyright (C) Ivor Hewitt + * + * @par Licences + * + * 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 + * 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 + * + * @par SubVersion + * $Date$ + * $Revision$ + * $Author$ + * $HeadURL$ + */ + +/* + * note currently only supporting 720x576, 704x576 and 640x480 PAL + * other resolutions should work but aren't + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) +#include +#endif + +#include "stk11xx.h" +#include "stk11xx-dev.h" + +int dev_stk0408_check_device(struct usb_stk11xx *dev); +int dev_stk0408_select_input(struct usb_stk11xx *dev, int input); +int dev_stk0408_write0(struct usb_stk11xx *dev, int mask, int val); + +/** + * @param dev Device structure + * + * @returns 0 if all is OK + * + * @brief This function initializes the device. + * + * This function must be called at first. It's the start of the + * initialization process. After this process, the device is + * completly initalized and it's ready. + * + * This function is written from the USB log. + */ +int dev_stk0408_initialize_device(struct usb_stk11xx *dev) +{ + int i; + int retok; + int value; + + STK_INFO("Initialize USB2.0 Syntek Capture device\n"); + +//what is all this writing to register 2 doing? + usb_stk11xx_write_registry(dev, 0x0002, 0x0000); + usb_stk11xx_write_registry(dev, 0x0000, 0x0000); + usb_stk11xx_write_registry(dev, 0x0002, 0x0000); + usb_stk11xx_write_registry(dev, 0x0003, 0x0000); + usb_stk11xx_write_registry(dev, 0x0002, 0x0007); + + usb_stk11xx_read_registry(dev, 0x0002, &value); + usb_stk11xx_read_registry(dev, 0x0000, &value); + + dev_stk0408_write0(dev, 7, 4); + dev_stk0408_write0(dev, 7, 4); + dev_stk0408_write0(dev, 7, 6); + dev_stk0408_write0(dev, 7, 7); + dev_stk0408_write0(dev, 7, 6); + dev_stk0408_write0(dev, 7, 4); + dev_stk0408_write0(dev, 7, 5); + + for (i=0;i<7;i++) + { + dev_stk0408_write0(dev, 7, 4); + dev_stk0408_write0(dev, 7, 4); + dev_stk0408_write0(dev, 7, 5); + } + +/* start set */ + usb_stk11xx_write_registry(dev, 0x0002, 0x0007); + usb_stk11xx_write_registry(dev, 0x0000, 0x0001); + + dev_stk0408_configure_device(dev,1); + dev_stk0408_configure_device(dev,2); + + usb_stk11xx_write_registry(dev, 0x0500, 0x0094); + msleep(10); + + dev_stk0408_camera_asleep(dev); + + usb_stk11xx_write_registry(dev, 0x0002, 0x0078); + usb_stk11xx_write_registry(dev, 0x0000, 0x0000); + usb_stk11xx_write_registry(dev, 0x0203, 0x00a0); + usb_stk11xx_read_registry(dev, 0x0003, &value); + usb_stk11xx_write_registry(dev, 0x0003, 0x0000); + + usb_stk11xx_read_registry(dev, 0x0002, &value); //78? + usb_stk11xx_write_registry(dev, 0x0002, 0x007f); + + usb_stk11xx_read_registry(dev, 0x0002, &value); //7f? + usb_stk11xx_read_registry(dev, 0x0000, &value); //0? + + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x006); + dev_stk0408_write0(dev, 0x07f, 0x007); + dev_stk0408_write0(dev, 0x07f, 0x006); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x005); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x005); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x006); + dev_stk0408_write0(dev, 0x07f, 0x007); + dev_stk0408_write0(dev, 0x07f, 0x006); + dev_stk0408_write0(dev, 0x07f, 0x006); + dev_stk0408_write0(dev, 0x07f, 0x007); + dev_stk0408_write0(dev, 0x07f, 0x006); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x005); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x005); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x005); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x004); + dev_stk0408_write0(dev, 0x07f, 0x005); + + usb_stk11xx_write_registry(dev, 0x0002, 0x007f); + usb_stk11xx_write_registry(dev, 0x0000, 0x0001); + + retok = dev_stk11xx_check_device(dev, 500); + + usb_stk11xx_set_feature(dev, 1); + + // Device is initialized and is ready !!! + STK_INFO("Syntek USB2.0 Capture device is ready\n"); + + return 0; +} + +int dev_stk0408_write0(struct usb_stk11xx *dev, int mask, int val) +{ + int value; + + usb_stk11xx_write_registry(dev, 0x0002, mask); + usb_stk11xx_write_registry(dev, 0x0000, val); + usb_stk11xx_read_registry(dev, 0x0002, &value); + usb_stk11xx_read_registry(dev, 0x0000, &value); + + return 0; +} + +int dev_stk0408_write_208(struct usb_stk11xx *dev, int val) +{ + int value; + int retok; + + usb_stk11xx_read_registry(dev, 0x02ff, &value); + usb_stk11xx_write_registry(dev, 0x02ff, 0x0000); + + usb_stk11xx_write_registry(dev, 0x0208, val); + usb_stk11xx_write_registry(dev, 0x0200, 0x0020); + + retok = dev_stk0408_check_device(dev); + + if (retok != 1) { + return -1; + } + + usb_stk11xx_read_registry(dev, 0x0209, &value); + usb_stk11xx_write_registry(dev, 0x02ff, 0x0000); + + return 1; +} + +int dev_stk0408_write_saa(struct usb_stk11xx *dev, int reg, int val) +{ + int value; + int retok; + + usb_stk11xx_read_registry(dev, 0x02ff, &value); + usb_stk11xx_write_registry(dev, 0x02ff, 0x0000); + + usb_stk11xx_write_registry(dev, 0x0204, reg); + usb_stk11xx_write_registry(dev, 0x0205, val); + usb_stk11xx_write_registry(dev, 0x0200, 0x0001); + + retok = dev_stk0408_check_device(dev); + + if (retok != 1) { + return -1; + } + + usb_stk11xx_write_registry(dev, 0x02ff, 0x0000); + + return 1; +} + +int dev_stk0408_set_resolution(struct usb_stk11xx *dev) +{ +/* + * These registers control the resolution of the capture buffer. + * + * xres = (X - xsub) / 2 + * yres = (Y - ysub) + * + */ + int x,y,xsub,ysub; + + switch (stk11xx_image_sizes[dev->resolution].x) + { + case 720: + x = 0x5a0; + xsub = 0; + break; + + case 704: + case 352: + case 176: + x = 0x584; + xsub = 4; + break; + + case 640: + case 320: + case 160: + x = 0x508; + xsub = 0x08; + break; + + default: + return -1; + } + + switch (stk11xx_image_sizes[dev->resolution].y) + { + case 576: + case 288: + case 144: + y = 0x121; + ysub = 0x1; + break; + + case 480: + y = 0x110; + ysub= 0x20; + break; + + case 120: + case 240: + y = 0x103; + ysub = 0x13; + break; + + default: + return -1; + } + + usb_stk11xx_write_registry(dev, 0x0110, xsub ); // xsub + usb_stk11xx_write_registry(dev, 0x0111, 0 ); + usb_stk11xx_write_registry(dev, 0x0112, ysub ); // ysub + usb_stk11xx_write_registry(dev, 0x0113, 0 ); + usb_stk11xx_write_registry(dev, 0x0114, x ); // X + usb_stk11xx_write_registry(dev, 0x0115, 5 ); + usb_stk11xx_write_registry(dev, 0x0116, y ); // Y + usb_stk11xx_write_registry(dev, 0x0117, 1 ); + + return 0; +} + + +/** + * @param dev Device structure + * @param step The step of configuration [0-6] + * + * @returns 0 if all is OK + * + * @brief This function configures the device. + * + * This is called multiple times through intitialisation and configuration + * there appear to be six distinct steps + * + */ +int dev_stk0408_configure_device(struct usb_stk11xx *dev, int step) +{ + int value; + int asize; + int i; + + + static const int ids[] = { + 0x203,0x00d,0x00f,0x103,0x018,0x01b,0x01c,0x01a,0x019, + 0x300,0x350,0x351,0x352,0x353,0x300,0x018,0x202,0x110, + 0x111,0x112,0x113,0x114,0x115,0x116,0x117 + }; + + static const int values[] = { + 0x04a,0x000,0x002,0x000,0x000,0x00e,0x046,0x014,0x000, + 0x012,0x02d,0x001,0x000,0x000,0x080,0x010,0x00f,0x008, + 0x000,0x013,0x000,0x008,0x005,0x003,0x001 + }; + + if (step != 1) + { + usb_stk11xx_read_registry(dev, 0x0003, &value); + usb_stk11xx_read_registry(dev, 0x0001, &value); + usb_stk11xx_read_registry(dev, 0x0002, &value); + usb_stk11xx_read_registry(dev, 0x0000, &value); + usb_stk11xx_read_registry(dev, 0x0003, &value); + usb_stk11xx_read_registry(dev, 0x0001, &value); + usb_stk11xx_write_registry(dev, 0x0002, 0x0078); + usb_stk11xx_write_registry(dev, 0x0000, 0x0000); + usb_stk11xx_write_registry(dev, 0x0003, 0x0080); + usb_stk11xx_write_registry(dev, 0x0001, 0x0003); + + usb_stk11xx_read_registry(dev, 0x0002, &value); + usb_stk11xx_read_registry(dev, 0x0000, &value); + usb_stk11xx_write_registry(dev, 0x0002, 0x0078); + usb_stk11xx_read_registry(dev, 0x0000, &value); + usb_stk11xx_read_registry(dev, 0x0002, &value); + usb_stk11xx_read_registry(dev, 0x0000, &value); + usb_stk11xx_write_registry(dev, 0x0002, 0x0078); + usb_stk11xx_write_registry(dev, 0x0000, 0x0030); + usb_stk11xx_read_registry(dev, 0x0002, &value); + usb_stk11xx_read_registry(dev, 0x0002, &value); + usb_stk11xx_write_registry(dev, 0x0002, 0x0078); + } + + asize = ARRAY_SIZE(values); + + for(i=0; iresolution == STK11XX_320x240)|| + (dev->resolution == STK11XX_352x288)) + { + usb_stk11xx_write_registry(dev, 0x0104, 0x0000); + usb_stk11xx_write_registry(dev, 0x0105, 0x0000); + } */ + + usb_stk11xx_write_registry(dev, 0x0106, 0x0000); + + dev_stk0408_write_saa(dev, 0x02, 0x80); + dev_stk0408_write_208(dev,0x09); + dev_stk0408_write_saa(dev, 0x09, 0x00); + + break; + } + + if (step == 3) + { + dev_stk0408_write_saa(dev, 0x02, 0x80); + dev_stk0408_write_208(dev,0x09); + dev_stk0408_write_saa(dev, 0x09, 0x00); + + //test and set? + usb_stk11xx_write_registry(dev, 0x0504, 0x0012); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x0012); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0080); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + usb_stk11xx_write_registry(dev, 0x0504, 0x0010); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x0010); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0000); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + usb_stk11xx_write_registry(dev, 0x0504, 0x000e); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x000e); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0000); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + usb_stk11xx_write_registry(dev, 0x0504, 0x0016); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x0016); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0000); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + usb_stk11xx_write_registry(dev, 0x0504, 0x001a); + usb_stk11xx_write_registry(dev, 0x0502, 0x0004); + usb_stk11xx_write_registry(dev, 0x0503, 0x0004); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + usb_stk11xx_write_registry(dev, 0x0504, 0x0002); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x0002); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0080); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + usb_stk11xx_write_registry(dev, 0x0504, 0x001c); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x001c); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0080); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + dev_stk0408_write_saa(dev, 0x02, 0x80); + dev_stk0408_write_208(dev,0x09); + dev_stk0408_write_saa(dev, 0x09, 0x00); + + } + + if ((step == 4 )|| (step == 6)) + { + dev_stk0408_write_saa(dev, 0x02, 0x80); + dev_stk0408_write_208(dev,0x09); + dev_stk0408_write_saa(dev, 0x09, 0x00); + dev_stk0408_write_208(dev,0x0e); + dev_stk0408_write_saa(dev, 0x0e, 0x01); + + dev_stk0408_set_resolution(dev); + + usb_stk11xx_write_registry(dev, 0x0002, 0x0078); + dev_stk0408_set_camera_quality(dev); + } + + if (step == 6) + { + usb_stk11xx_write_registry(dev, 0x0002, 0x0078); + + dev_stk0408_write_208(dev,0x0e); + dev_stk0408_write_saa(dev, 0x0e, 0x01); + + dev_stk0408_set_resolution( dev); + + usb_stk11xx_write_registry(dev, 0x0002, 0x0078); + + dev_stk0408_select_input(dev, dev->vsettings.input); + + dev_stk0408_start_stream(dev); + + usb_stk11xx_write_registry(dev, 0x0504, 0x0002); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x0002); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0080); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + usb_stk11xx_write_registry(dev, 0x0504, 0x001c); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x001c); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0080); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + usb_stk11xx_write_registry(dev, 0x0504, 0x0002); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x0002); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0000); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + usb_stk11xx_write_registry(dev, 0x0504, 0x001c); + usb_stk11xx_write_registry(dev, 0x0500, 0x008b); + usb_stk11xx_write_registry(dev, 0x0504, 0x001c); + usb_stk11xx_write_registry(dev, 0x0502, 0x0000); + usb_stk11xx_write_registry(dev, 0x0503, 0x0000); + usb_stk11xx_write_registry(dev, 0x0500, 0x008c); + + dev_stk0408_start_stream(dev); + + } + + if (step==4) + { + dev_stk11xx_camera_on(dev); + } + + return 0; +} + + +int dev_stk0408_select_input(struct usb_stk11xx *dev, int input) +{ + switch (input) + { + case 1: + usb_stk11xx_write_registry(dev, 0x0000, 0x0098); + break; + case 2: + usb_stk11xx_write_registry(dev, 0x0000, 0x0090); + break; + case 3: + usb_stk11xx_write_registry(dev, 0x0000, 0x0088); + break; + case 4: + usb_stk11xx_write_registry(dev, 0x0000, 0x0080); + break; + } + usb_stk11xx_write_registry(dev, 0x0002, 0x0093); + + return 0; + +} + + +/** + * @param dev Device structure + * + * @returns 0 if all is OK + * + * @brief Wake-up the camera. + * + * This function permits to wake-up the device. + */ +int dev_stk0408_camera_asleep(struct usb_stk11xx *dev) +{ + int value; + int value0; + + usb_stk11xx_read_registry(dev, 0x0104, &value); + usb_stk11xx_read_registry(dev, 0x0105, &value); + usb_stk11xx_read_registry(dev, 0x0106, &value); + + usb_stk11xx_read_registry(dev, 0x0100, &value); + + value = value & 0x7f; + usb_stk11xx_write_registry(dev, 0x0100, value); + + usb_stk11xx_write_registry(dev, 0x0116, 0x0000); + usb_stk11xx_write_registry(dev, 0x0117, 0x0000); + usb_stk11xx_write_registry(dev, 0x0018, 0x0000); + + usb_stk11xx_read_registry(dev, 0x0002, &value); + usb_stk11xx_read_registry(dev, 0x0000, &value0); + usb_stk11xx_write_registry(dev, 0x0002, value); + usb_stk11xx_read_registry(dev, 0x0000, &value0); + + return 0; +} + + +/** + * @param dev Device structure + * + * @returns 0 if all is OK + * + * @brief This function initializes the device for the stream. + * + * It's the start. This function has to be called at first, before + * enabling the video stream. + */ +int dev_stk0408_init_camera(struct usb_stk11xx *dev) +{ + dev_stk0408_camera_asleep(dev); + + dev_stk0408_configure_device(dev, 3); + dev_stk0408_configure_device(dev, 4); + dev_stk0408_configure_device(dev, 5); + + dev_stk0408_configure_device(dev, 6); + + return 0; +} + +int dev_stk0408_check_device(struct usb_stk11xx *dev) +{ + int i; + int value; + const int retry=2; + + for (i=0; i < retry; i++) { + usb_stk11xx_read_registry(dev, 0x201, &value); + +//writes to 204/204 return 4 on success +//writes to 208 return 1 on success + + if (value == 0x04 || value == 0x01) + return 1; + + if (value != 0x00) + { + STK_ERROR("Check device return error (0x0201 = %02X) !\n", value); + return -1; + } +// msleep(10); + } + + return 0; +} + + +/** + * @param dev Device structure + * + * @returns 0 if all is OK + * + * @brief This function sets the default sensor settings + * + * We set some registers in using a I2C bus. + * WARNING, the sensor settings can be different following the situation. + */ +int dev_stk0408_sensor_settings(struct usb_stk11xx *dev) +{ + int i; + int retok; + int asize; + +// PAL registers + static const int registers[] = { + 0x01,0x03,0x04,0x05,0x06,0x07,0x08,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12, + 0x13,0x15,0x16,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c, + 0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b }; + + static const int values[] = { + 0x08,0x33,0x00,0x00,0xe9,0x0d,0x38,0x80,0x47,0x40,0x00,0x01,0x2a,0x00,0x0c,0xe7, + 0x00,0x00,0x00,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xff,0xff,0xff,0x40,0x54,0x07,0x83 }; + + asize = ARRAY_SIZE(values); + + for(i=0; ivsettings.brightness >> 8); //80 +//contrast + dev_stk0408_write_saa(dev, 0x0b, dev->vsettings.contrast >> 9); //40 +//hue + dev_stk0408_write_saa(dev, 0x0d, (dev->vsettings.colour - 32768) >> 8); //00 +//saturation + dev_stk0408_write_saa(dev, 0x0c, (dev->vsettings.hue) >> 9); //40 + + STK_DEBUG("Set colour : %d\n", dev->vsettings.colour); + STK_DEBUG("Set contrast : %d\n", dev->vsettings.contrast); + STK_DEBUG("Set hue : %d\n", dev->vsettings.hue); + STK_DEBUG("Set brightness : %d\n", dev->vsettings.brightness); + + return 1; +} + + +/** + * @param dev Device structure + * + * @returns 0 if all is OK + * + * @brief This function permits to modify the settings of the camera. + * + * This functions permits to modify the frame rate per second. + * + */ +int dev_stk0408_set_camera_fps(struct usb_stk11xx *dev) +{ + //Unknown, setting FPS seems to have no effect + return 0; +} + + +/** + * @param dev Device structure + * + * @returns 0 if all is OK + * + * @brief This function sets the device to start the stream. + * + * After the initialization of the device and the initialization of the video stream, + * this function permits to enable the stream. + */ +int dev_stk0408_start_stream(struct usb_stk11xx *dev) +{ + int value; + int value_116, value_117; + + usb_stk11xx_read_registry(dev, 0x0116, &value_116); + usb_stk11xx_read_registry(dev, 0x0117, &value_117); + + usb_stk11xx_write_registry(dev, 0x0116, 0x0000); + usb_stk11xx_write_registry(dev, 0x0117, 0x0000); + + usb_stk11xx_read_registry(dev, 0x0100, &value); + value |= 0x80; + +// msleep(0x1f4); + usb_stk11xx_write_registry(dev, 0x0100, value); +// msleep(0x64); + + usb_stk11xx_write_registry(dev, 0x0116, value_116); + usb_stk11xx_write_registry(dev, 0x0117, value_117); + + return 0; +} + + +/** + * @param dev Device structure + * + * @returns 0 if all is OK + * + * @brief Reconfigure the camera before the stream. + * + * Before enabling the video stream, you have to reconfigure the device. + */ +int dev_stk0408_reconf_camera(struct usb_stk11xx *dev) +{ + + dev_stk0408_configure_device(dev, 6); + + dev_stk11xx_camera_settings(dev); + + return 0; +} + + +/** + * @param dev Device structure + * + * @returns 0 if all is OK + * + * @brief This function sets the device to stop the stream. + * + * You use the function start_stream to enable the video stream. So you + * have to use the function stop_strem to disable the video stream. + */ +int dev_stk0408_stop_stream(struct usb_stk11xx *dev) +{ + int value; + + usb_stk11xx_read_registry(dev, 0x0100, &value); + value &= 0x7f; + usb_stk11xx_write_registry(dev, 0x0100, value); + msleep(5); + + return 0; +} + +/* + * Needs some more work and optimisation! + */ +void stk11xx_copy_uvyv(uint8_t *src, uint8_t *rgb, + struct stk11xx_coord *image, + struct stk11xx_coord *view, + const int hflip, const int vflip, + const int hfactor, const int vfactor, + bool order, bool field) +{ + int width = image->x; + int height = image->y; + int x; + int y; + + uint8_t *line1; + uint8_t *line2; + + static uint8_t *prev=0; + if (!prev) + prev = rgb; + +// printk("copy image %d - %d %d,%d\n", width, height, hfactor, vfactor); + +// vfactor=1 interlace rows +// vfactor=2 full frame copy, duplicate rows +// vfactor=4 half frame, copy rows + + if (field == false) // odd frame + { + prev += width * 2; + } + + for ( y=0; y < height/2; y++) + { + if (vfactor == 1) + { + if (field == false) // odd frame + {// + line1 = rgb + (y*width*4); + line2 = rgb + (y*width*4) + width*2; + } + else + { + line1 = rgb + (y*width*4)+width*2; + line2 = rgb + (y*width*4); + } + } + else + { + line1 = rgb + (y*width*2); + } + + + for ( x = 0; x < width*2; x+=4) + { + if (order) //yuv order + { + line1[x] = src[0]; + line1[x+1] = src[1]; + line1[x+2] = src[2]; + line1[x+3] = src[3]; + } + else + { + line1[x] = src[1]; + line1[x+1] = src[0]; + line1[x+2] = src[3]; + line1[x+3] = src[2]; + + } + src += (4 * hfactor); + } + + if (vfactor == 1) //interlaced copy from previous frame + { + for ( x = 0; x < width*2; x+=1) + { + line2[x] = (*prev++); //line1[x]; + } + prev += width*2; + } + else if (vfactor == 2) //1 : 1 + { + } + else if (vfactor == 4) // 2 : 1 + { + src += (width*2)*2; + } + } + + prev = rgb; +} + +/* + * needs more work and optimisation! + * + * rgb is horribly slow but just written to check the image is working + * replace with a proper yuv to rgb conversion + */ +#define CLAMP(x) x < 0 ? 0 : x > 255 ? 255 : x + +void stk11xx_copy_rgb(uint8_t *src, uint8_t *rgb, + struct stk11xx_coord *image, + struct stk11xx_coord *view, + const int hflip, const int vflip, + const int hfactor, const int vfactor, + bool order, bool four, bool field) +{ + + int width = image->x; + int height = image->y; + int x; + int y; + int step; + + uint8_t *line1; + uint8_t *line2; + + static uint8_t *prev=0; + if (!prev) + prev = rgb; + + step = four?4:3; + + if (field==false) + { + prev += width * step; + } + + //uvyv + for ( y=0; y < height/2; y++) + { + if (vfactor == 1) + { + if (field == false) // odd frame + {// + line1 = rgb + (y * width * step * 2); + line2 = rgb + (y * width * step * 2) + width * step; + } + else + { + line1 = rgb + (y * width * step * 2) + width * step; + line2 = rgb + (y * width * step * 2); + } + } + else + { + line1 = rgb + (y * width * step); + } + + bool off=false; + for ( x = 0; x < width*step; x+=step) + { +/* + C = Y - 16 + D = U - 128 + E = V - 128 + + R = clip(( 298 * C + 409 * E + 128) >> 8) + G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) + B = clip(( 298 * C + 516 * D + 128) >> 8) +*/ + int c = src[off ? 3 : 1]; + int d = src[0] - 128; + int e = src[2] - 128; + + int R = ((298*c + 409 * e + 128) >>8); + int G = ((298*c - 100 * d - 208 * e + 128)>>8); + int B = ((298*c + 516 * d + 128)>>8); + + R = CLAMP(R); + G = CLAMP(G); + B = CLAMP(B); + + if (order) + { + line1[x] = B; + line1[x+1] = G; + line1[x+2] = R; + } + else + { + line1[x] = R; + line1[x+1] = G; + line1[x+2] = B; + } + if (four) + line1[x+3] = 0; + + if (off) + { + src += (4 * hfactor); + off = false; + } + else + { + off = true; + } + + } + + + if (vfactor == 1) //interlaced copy from previous frame + { + for ( x = 0; x < width * step; x++ ) + { + line2[x] = (*prev++); //line1[x]; + } + prev += width * step; + } + } + + prev = rgb; +} + + +int dev_stk0408_decode(struct usb_stk11xx *dev) +{ + void *data; + void *image; + + int vfactor; + int hfactor; + bool odd; + + struct stk11xx_frame_buf *framebuf; + + if (dev == NULL) + return -EFAULT; + + framebuf = dev->read_frame; + + if (framebuf == NULL) + return -EFAULT; + + image = dev->image_data; + printk("fill image %d\n", dev->fill_image); + + image += dev->images[dev->fill_image].offset; + + data = framebuf->data; + odd = framebuf->odd; + + switch (dev->resolution) { + +/* +//Currently only 1:1 resolutions are working + case STK11XX_160x120: + case STK11XX_176x144: + hfactor = 4; + vfactor = 4; + break; + + case STK11XX_320x240: + case STK11XX_352x240: + case STK11XX_352x288: + hfactor = 2; + vfactor = 2; + break; +*/ + case STK11XX_640x480: +/* case STK11XX_720x480:*/ + case STK11XX_720x576: + hfactor = 1; + vfactor = 1; + break; + + default: + return -EFAULT; + } + + switch (dev->vsettings.palette) { + case STK11XX_PALETTE_RGB24: + stk11xx_copy_rgb(data, image, &dev->image, &dev->view, dev->vsettings.hflip, dev->vsettings.vflip, hfactor, vfactor, false,false,odd); + break; + case STK11XX_PALETTE_RGB32: + stk11xx_copy_rgb(data, image, &dev->image, &dev->view, dev->vsettings.hflip, dev->vsettings.vflip, hfactor, vfactor, false,true,odd); + break; + case STK11XX_PALETTE_BGR24: + stk11xx_copy_rgb(data, image, &dev->image, &dev->view, dev->vsettings.hflip, dev->vsettings.vflip, hfactor, vfactor, true,false,odd); + break; + case STK11XX_PALETTE_BGR32: + stk11xx_copy_rgb(data, image, &dev->image, &dev->view, dev->vsettings.hflip, dev->vsettings.vflip, hfactor, vfactor, true,true,odd); + break; + + case STK11XX_PALETTE_UYVY: + stk11xx_copy_uvyv(data, image, &dev->image, &dev->view,dev->vsettings.hflip, dev->vsettings.vflip, hfactor, vfactor, true,odd); + break; + case STK11XX_PALETTE_YUYV: + stk11xx_copy_uvyv(data, image, &dev->image, &dev->view,dev->vsettings.hflip, dev->vsettings.vflip, hfactor, vfactor, false,odd); + break; + } + + return 0; + +} + +/* + * Want to restrict number of available modes for 0408 based card for + * now. + */ +int dev_stk0408_select_video_mode(struct usb_stk11xx *dev, int width, int height) +{ + int i; + int find; + + if (! (((width == 720) && (height==576))|| + ((width == 720) && (height==480))|| + ((width == 640) && (height==480)))) + { + width = 640; + height = 480; + } + + for (i=0, find=0; i<=STK11XX_720x576; i++) { + if (stk11xx_image_sizes[i].x == width && stk11xx_image_sizes[i].y == height) + find = i; + } + // Save the new resolution + dev->resolution = find; + + STK_INFO("Set mode %d [%dx%d]\n", dev->resolution, + stk11xx_image_sizes[dev->resolution].x, stk11xx_image_sizes[dev->resolution].y); + + // Save the new size + dev->view.x = width; + dev->view.y = height; + + // Calculate the frame size + switch (dev->resolution) { + case STK11XX_640x480: + dev->image.x = stk11xx_image_sizes[dev->resolution].x; + dev->image.y = stk11xx_image_sizes[dev->resolution].y; + dev->frame_size = 640*480; //dev->image.x * dev->image.y; + break; +/* case STK11XX_720x480: + dev->image.x = stk11xx_image_sizes[STK11XX_720x480].x; + dev->image.y = stk11xx_image_sizes[STK11XX_720x480].y; + dev->frame_size = dev->image.x * dev->image.y; + break;*/ + case STK11XX_720x576: + dev->image.x = stk11xx_image_sizes[STK11XX_720x576].x; + dev->image.y = stk11xx_image_sizes[STK11XX_720x576].y; + dev->frame_size = dev->image.x * dev->image.y; + break; + } + // Calculate the image size + switch (dev->vsettings.palette) { + case STK11XX_PALETTE_RGB24: + case STK11XX_PALETTE_BGR24: + dev->view_size = 3 * dev->view.x * dev->view.y; + dev->image_size = 3 * dev->frame_size; + break; + + case STK11XX_PALETTE_RGB32: + case STK11XX_PALETTE_BGR32: + dev->view_size = 3 * dev->view.x * dev->view.y; + dev->image_size = 4 * dev->frame_size; + break; + + case STK11XX_PALETTE_UYVY: + case STK11XX_PALETTE_YUYV: + dev->view_size = 2 * dev->view.x * dev->view.y; + dev->image_size = 2 * dev->frame_size; + break; + } + + return 0; + +} Index: Kbuild =================================================================== --- Kbuild (revision 82) +++ Kbuild (working copy) @@ -5,6 +5,7 @@ stk11xx-objs := stk11xx-usb.o stk11xx-v4l.o stk11xx-sysfs.o stk11xx-dev.o stk11xx-buf.o stk11xx-bayer.o +stk11xx-objs += stk11xx-dev-0408.o stk11xx-objs += stk11xx-dev-a311.o stk11xx-objs += stk11xx-dev-a821.o stk11xx-objs += stk11xx-dev-6a31.o Index: Makefile =================================================================== --- Makefile (revision 82) +++ Makefile (working copy) @@ -1,6 +1,7 @@ stk11xx-objs := stk11xx-usb.o stk11xx-v4l.o stk11xx-sysfs.o stk11xx-dev.o stk11xx-buf.o stk11xx-bayer.o +stk11xx-objs += stk11xx-dev-0408.o stk11xx-objs += stk11xx-dev-a311.o stk11xx-objs += stk11xx-dev-a821.o stk11xx-objs += stk11xx-dev-6a31.o Index: stk11xx-buf.c =================================================================== --- stk11xx-buf.c (revision 82) +++ stk11xx-buf.c (working copy) @@ -45,7 +45,9 @@ #include #include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) #include +#endif #include "stk11xx.h" @@ -430,7 +432,7 @@ if (dev->read_frame != NULL) { spin_unlock_irqrestore(&dev->spinlock, flags); - ret = stk11xx_decompress(dev); + ret = dev_stk11xx_decompress(dev); spin_lock_irqsave(&dev->spinlock, flags); if (dev->empty_frames == NULL) {