This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / usb / media / pwc / pwc-uncompress.c
1 /* Linux driver for Philips webcam
2    Decompression frontend.
3    (C) 1999-2003 Nemosoft Unv.
4    (C) 2004      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
27 #include <asm/current.h>
28 #include <asm/types.h>
29
30 #include "pwc.h"
31 #include "pwc-uncompress.h"
32 #include "pwc-dec1.h"
33 #include "pwc-dec23.h"
34
35 int pwc_decompress(struct pwc_device *pdev)
36 {
37         struct pwc_frame_buf *fbuf;
38         int n, line, col, stride;
39         void *yuv, *image;
40         u16 *src;
41         u16 *dsty, *dstu, *dstv;
42
43         if (pdev == NULL)
44                 return -EFAULT;
45 #if defined(__KERNEL__) && defined(PWC_MAGIC)
46         if (pdev->magic != PWC_MAGIC) {
47                 Err("pwc_decompress(): magic failed.\n");
48                 return -EFAULT;
49         }
50 #endif
51
52         fbuf = pdev->read_frame;
53         if (fbuf == NULL)
54                 return -EFAULT;
55         image = pdev->image_ptr[pdev->fill_image];
56         if (!image)
57                 return -EFAULT;
58
59         yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
60
61         /* Raw format; that's easy... */
62         if (pdev->vpalette == VIDEO_PALETTE_RAW)
63         {
64                 memcpy(image, yuv, pdev->frame_size);
65                 return 0;
66         }
67
68         if (pdev->vbandlength == 0) {
69                 /* Uncompressed mode. We copy the data into the output buffer,
70                    using the viewport size (which may be larger than the image
71                    size). Unfortunately we have to do a bit of byte stuffing
72                    to get the desired output format/size.
73                  */
74                         /*
75                          * We do some byte shuffling here to go from the
76                          * native format to YUV420P.
77                          */
78                         src = (u16 *)yuv;
79                         n = pdev->view.x * pdev->view.y;
80
81                         /* offset in Y plane */
82                         stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
83                         dsty = (u16 *)(image + stride);
84
85                         /* offsets in U/V planes */
86                         stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
87                         dstu = (u16 *)(image + n +         stride);
88                         dstv = (u16 *)(image + n + n / 4 + stride);
89
90                         /* increment after each line */
91                         stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
92
93                         for (line = 0; line < pdev->image.y; line++) {
94                                 for (col = 0; col < pdev->image.x; col += 4) {
95                                         *dsty++ = *src++;
96                                         *dsty++ = *src++;
97                                         if (line & 1)
98                                                 *dstv++ = *src++;
99                                         else
100                                                 *dstu++ = *src++;
101                                 }
102                                 dsty += stride;
103                                 if (line & 1)
104                                         dstv += (stride >> 1);
105                                 else
106                                         dstu += (stride >> 1);
107                         }
108         }
109         else {
110                 /* Compressed; the decompressor routines will write the data
111                    in planar format immediately.
112                  */
113                 int flags;
114                 
115                 flags = PWCX_FLAG_PLANAR;
116                 if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
117                  {
118                    printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
119                    flags |= PWCX_FLAG_BAYER;
120                    return -ENXIO; /* No such device or address: missing decompressor */
121                  }
122
123                 switch (pdev->type)
124                  {
125                   case 675:
126                   case 680:
127                   case 690:
128                   case 720:
129                   case 730:
130                   case 740:
131                   case 750:
132                     pwc_dec23_decompress(&pdev->image, &pdev->view, &pdev->offset,
133                                 yuv, image,
134                                 flags,
135                                 pdev->decompress_data, pdev->vbandlength);
136                     break;
137                   case 645:
138                   case 646:
139                     /* TODO & FIXME */
140                     return -ENXIO; /* No such device or address: missing decompressor */
141                     break;
142                  }
143         }
144         return 0;
145 }
146
147