1/* Linux driver for Philips webcam 2 Decompression frontend. 3 (C) 1999-2003 Nemosoft Unv. 4 (C) 2004-2006 Luc Saillard (luc@saillard.org) 5 6 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx 7 driver and thus may have bugs that are not present in the original version. 8 Please send bug reports and support requests to <luc@saillard.org>. 9 The decompression routines have been implemented by reverse-engineering the 10 Nemosoft binary pwcx module. Caveat emptor. 11 12 This program is free software; you can redistribute it and/or modify 13 it under the terms of the GNU General Public License as published by 14 the Free Software Foundation; either version 2 of the License, or 15 (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 26 vim: set ts=8: 27*/ 28 29#include <asm/current.h> 30#include <asm/types.h> 31 32#include "pwc.h" 33#include "pwc-uncompress.h" 34#include "pwc-dec1.h" 35#include "pwc-dec23.h" 36 37int pwc_decompress(struct pwc_device *pdev) 38{ 39 struct pwc_frame_buf *fbuf; 40 int n, line, col, stride; 41 void *yuv, *image; 42 u16 *src; 43 u16 *dsty, *dstu, *dstv; 44 45 if (pdev == NULL) 46 return -EFAULT; 47 48 fbuf = pdev->read_frame; 49 if (fbuf == NULL) 50 return -EFAULT; 51 image = pdev->image_data; 52 image += pdev->images[pdev->fill_image].offset; 53 54 yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ 55 56 /* Raw format; that's easy... */ 57 if (pdev->vpalette == VIDEO_PALETTE_RAW) 58 { 59 struct pwc_raw_frame *raw_frame = image; 60 raw_frame->type = cpu_to_le16(pdev->type); 61 raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength); 62 /* cmd_buf is always 4 bytes, but sometimes, only the 63 * first 3 bytes is filled (Nala case). We can 64 * determine this using the type of the webcam */ 65 memcpy(raw_frame->cmd, pdev->cmd_buf, 4); 66 memcpy(raw_frame+1, yuv, pdev->frame_size); 67 return 0; 68 } 69 70 if (pdev->vbandlength == 0) { 71 /* Uncompressed mode. 72 * We copy the data into the output buffer, using the viewport 73 * size (which may be larger than the image size). 74 * Unfortunately we have to do a bit of byte stuffing to get 75 * the desired output format/size. 76 * 77 * We do some byte shuffling here to go from the 78 * native format to YUV420P. 79 */ 80 src = (u16 *)yuv; 81 n = pdev->view.x * pdev->view.y; 82 83 /* offset in Y plane */ 84 stride = pdev->view.x * pdev->offset.y + pdev->offset.x; 85 dsty = (u16 *)(image + stride); 86 87 /* offsets in U/V planes */ 88 stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; 89 dstu = (u16 *)(image + n + stride); 90 dstv = (u16 *)(image + n + n / 4 + stride); 91 92 /* increment after each line */ 93 stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ 94 95 for (line = 0; line < pdev->image.y; line++) { 96 for (col = 0; col < pdev->image.x; col += 4) { 97 *dsty++ = *src++; 98 *dsty++ = *src++; 99 if (line & 1) 100 *dstv++ = *src++; 101 else 102 *dstu++ = *src++; 103 } 104 dsty += stride; 105 if (line & 1) 106 dstv += (stride >> 1); 107 else 108 dstu += (stride >> 1); 109 } 110 111 return 0; 112 } 113 114 /* 115 * Compressed; 116 * the decompressor routines will write the data in planar format 117 * immediately. 118 */ 119 if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) { 120 PWC_ERROR("Mode Bayer is not supported for now\n"); 121 /* flags |= PWCX_FLAG_BAYER; */ 122 return -ENXIO; /* No such device or address: missing decompressor */ 123 } 124 125 if (DEVICE_USE_CODEC1(pdev->type)) { 126 127 PWC_ERROR("This chipset is not supported for now\n"); 128 return -ENXIO; /* No such device or address: missing decompressor */ 129 130 } else { 131 pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR); 132 } 133 return 0; 134} 135 136 137/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ 138