1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Linux driver for Philips webcam
3 Decompression for chipset version 2 et 3
4 (C) 2004-2006 Luc Saillard (luc@saillard.org)
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.
15 #include "pwc-timon.h"
16 #include "pwc-kiara.h"
17 #include "pwc-dec23.h"
19 #include <linux/string.h>
20 #include <linux/slab.h>
23 * USE_LOOKUP_TABLE_TO_CLAMP
24 * 0: use a C version of this tests: { a<0?0:(a>255?255:a) }
25 * 1: use a faster lookup table for cpu with a big cache (intel)
27 #define USE_LOOKUP_TABLE_TO_CLAMP 1
29 * UNROLL_LOOP_FOR_COPYING_BLOCK
30 * 0: use a loop for a smaller code (but little slower)
31 * 1: when unrolling the loop, gcc produces some faster code (perhaps only
32 * valid for intel processor class). Activating this option, automatically
33 * activate USE_LOOKUP_TABLE_TO_CLAMP
35 #define UNROLL_LOOP_FOR_COPY 1
36 #if UNROLL_LOOP_FOR_COPY
37 # undef USE_LOOKUP_TABLE_TO_CLAMP
38 # define USE_LOOKUP_TABLE_TO_CLAMP 1
41 static void build_subblock_pattern(struct pwc_dec23_private
*pdec
)
43 static const unsigned int initial_values
[12] = {
44 -0x526500, -0x221200, 0x221200, 0x526500,
46 -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
50 static const unsigned int values_derivated
[12] = {
51 0xa4ca, 0x4424, -0x4424, -0xa4ca,
53 0xdb69, 0x5aba, -0x5aba, -0xdb69,
56 unsigned int temp_values
[12];
59 memcpy(temp_values
, initial_values
, sizeof(initial_values
));
60 for (i
= 0; i
< 256; i
++) {
61 for (j
= 0; j
< 12; j
++) {
62 pdec
->table_subblock
[i
][j
] = temp_values
[j
];
63 temp_values
[j
] += values_derivated
[j
];
68 static void build_bit_powermask_table(struct pwc_dec23_private
*pdec
)
71 unsigned int bit
, byte
, mask
, val
;
72 unsigned int bitpower
= 1;
74 for (bit
= 0; bit
< 8; bit
++) {
76 p
= pdec
->table_bitpowermask
[bit
];
77 for (byte
= 0; byte
< 256; byte
++) {
88 static void build_table_color(const unsigned int romtable
[16][8],
89 unsigned char p0004
[16][1024],
90 unsigned char p8004
[16][256])
92 int compression_mode
, j
, k
, bit
, pw
;
93 unsigned char *p0
, *p8
;
94 const unsigned int *r
;
96 /* We have 16 compressions tables */
97 for (compression_mode
= 0; compression_mode
< 16; compression_mode
++) {
98 p0
= p0004
[compression_mode
];
99 p8
= p8004
[compression_mode
];
100 r
= romtable
[compression_mode
];
102 for (j
= 0; j
< 8; j
++, r
++, p0
+= 128) {
104 for (k
= 0; k
< 16; k
++) {
107 else if (k
>= 1 && k
< 3)
108 bit
= (r
[0] >> 15) & 7;
109 else if (k
>= 3 && k
< 6)
110 bit
= (r
[0] >> 12) & 7;
111 else if (k
>= 6 && k
< 10)
112 bit
= (r
[0] >> 9) & 7;
113 else if (k
>= 10 && k
< 13)
114 bit
= (r
[0] >> 6) & 7;
115 else if (k
>= 13 && k
< 15)
116 bit
= (r
[0] >> 3) & 7;
126 p0
[k
+ 0x00] = (1 * pw
) + 0x80;
127 p0
[k
+ 0x10] = (2 * pw
) + 0x80;
128 p0
[k
+ 0x20] = (3 * pw
) + 0x80;
129 p0
[k
+ 0x30] = (4 * pw
) + 0x80;
130 p0
[k
+ 0x40] = (-1 * pw
) + 0x80;
131 p0
[k
+ 0x50] = (-2 * pw
) + 0x80;
132 p0
[k
+ 0x60] = (-3 * pw
) + 0x80;
133 p0
[k
+ 0x70] = (-4 * pw
) + 0x80;
134 } /* end of for (k=0; k<16; k++, p8++) */
135 } /* end of for (j=0; j<8; j++ , table++) */
136 } /* end of foreach compression_mode */
142 static void fill_table_dc00_d800(struct pwc_dec23_private
*pdec
)
145 #define ONE_HALF (1UL << (SCALEBITS - 1))
147 unsigned int offset1
= ONE_HALF
;
148 unsigned int offset2
= 0x0000;
150 for (i
=0; i
<256; i
++) {
151 pdec
->table_dc00
[i
] = offset1
& ~(ONE_HALF
);
152 pdec
->table_d800
[i
] = offset2
;
160 * To decode the stream:
161 * if look_bits(2) == 0: # op == 2 in the lookup table
164 * elif look_bits(3) == 7: # op == 1 in the lookup table
168 * else: # op == 0 in the lookup table
171 * For speedup processing, we build a lookup table and we takes the first 6 bits.
174 * unsigned char op; // operation to execute
175 * unsigned char bits; // bits use to perform operation
176 * unsigned char offset1; // offset to add to access in the table_0004 % 16
177 * unsigned char offset2; // offset to add to access in the table_0004
180 * How to build this table ?
181 * op == 2 when (i%4)==0
182 * op == 1 when (i%8)==7
186 static const unsigned char hash_table_ops
[64*4] = {
187 0x02, 0x00, 0x00, 0x00,
188 0x00, 0x03, 0x01, 0x00,
189 0x00, 0x04, 0x01, 0x10,
190 0x00, 0x06, 0x01, 0x30,
191 0x02, 0x00, 0x00, 0x00,
192 0x00, 0x03, 0x01, 0x40,
193 0x00, 0x05, 0x01, 0x20,
194 0x01, 0x00, 0x00, 0x00,
195 0x02, 0x00, 0x00, 0x00,
196 0x00, 0x03, 0x01, 0x00,
197 0x00, 0x04, 0x01, 0x50,
198 0x00, 0x05, 0x02, 0x00,
199 0x02, 0x00, 0x00, 0x00,
200 0x00, 0x03, 0x01, 0x40,
201 0x00, 0x05, 0x03, 0x00,
202 0x01, 0x00, 0x00, 0x00,
203 0x02, 0x00, 0x00, 0x00,
204 0x00, 0x03, 0x01, 0x00,
205 0x00, 0x04, 0x01, 0x10,
206 0x00, 0x06, 0x02, 0x10,
207 0x02, 0x00, 0x00, 0x00,
208 0x00, 0x03, 0x01, 0x40,
209 0x00, 0x05, 0x01, 0x60,
210 0x01, 0x00, 0x00, 0x00,
211 0x02, 0x00, 0x00, 0x00,
212 0x00, 0x03, 0x01, 0x00,
213 0x00, 0x04, 0x01, 0x50,
214 0x00, 0x05, 0x02, 0x40,
215 0x02, 0x00, 0x00, 0x00,
216 0x00, 0x03, 0x01, 0x40,
217 0x00, 0x05, 0x03, 0x40,
218 0x01, 0x00, 0x00, 0x00,
219 0x02, 0x00, 0x00, 0x00,
220 0x00, 0x03, 0x01, 0x00,
221 0x00, 0x04, 0x01, 0x10,
222 0x00, 0x06, 0x01, 0x70,
223 0x02, 0x00, 0x00, 0x00,
224 0x00, 0x03, 0x01, 0x40,
225 0x00, 0x05, 0x01, 0x20,
226 0x01, 0x00, 0x00, 0x00,
227 0x02, 0x00, 0x00, 0x00,
228 0x00, 0x03, 0x01, 0x00,
229 0x00, 0x04, 0x01, 0x50,
230 0x00, 0x05, 0x02, 0x00,
231 0x02, 0x00, 0x00, 0x00,
232 0x00, 0x03, 0x01, 0x40,
233 0x00, 0x05, 0x03, 0x00,
234 0x01, 0x00, 0x00, 0x00,
235 0x02, 0x00, 0x00, 0x00,
236 0x00, 0x03, 0x01, 0x00,
237 0x00, 0x04, 0x01, 0x10,
238 0x00, 0x06, 0x02, 0x50,
239 0x02, 0x00, 0x00, 0x00,
240 0x00, 0x03, 0x01, 0x40,
241 0x00, 0x05, 0x01, 0x60,
242 0x01, 0x00, 0x00, 0x00,
243 0x02, 0x00, 0x00, 0x00,
244 0x00, 0x03, 0x01, 0x00,
245 0x00, 0x04, 0x01, 0x50,
246 0x00, 0x05, 0x02, 0x40,
247 0x02, 0x00, 0x00, 0x00,
248 0x00, 0x03, 0x01, 0x40,
249 0x00, 0x05, 0x03, 0x40,
250 0x01, 0x00, 0x00, 0x00
256 static const unsigned int MulIdx
[16][16] = {
257 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
258 {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
259 {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
260 {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
261 {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
262 {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
263 {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
264 {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
265 {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
266 {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
267 {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
268 {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
269 {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
270 {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
271 {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
272 {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
275 #if USE_LOOKUP_TABLE_TO_CLAMP
276 #define MAX_OUTER_CROP_VALUE (512)
277 static unsigned char pwc_crop_table
[256 + 2*MAX_OUTER_CROP_VALUE
];
278 #define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
280 #define CLAMP(x) ((x)>255?255:((x)<0?0:x))
284 /* If the type or the command change, we rebuild the lookup table */
285 void pwc_dec23_init(struct pwc_device
*pdev
, const unsigned char *cmd
)
287 int flags
, version
, shift
, i
;
288 struct pwc_dec23_private
*pdec
= &pdev
->dec23
;
290 mutex_init(&pdec
->lock
);
292 if (pdec
->last_cmd_valid
&& pdec
->last_cmd
== cmd
[2])
295 if (DEVICE_USE_CODEC3(pdev
->type
)) {
296 flags
= cmd
[2] & 0x18;
298 pdec
->nbits
= 7; /* More bits, mean more bits to encode the stream, but better quality */
299 else if (flags
== 0x10)
304 version
= cmd
[2] >> 5;
305 build_table_color(KiaraRomTable
[version
][0], pdec
->table_0004_pass1
, pdec
->table_8004_pass1
);
306 build_table_color(KiaraRomTable
[version
][1], pdec
->table_0004_pass2
, pdec
->table_8004_pass2
);
318 version
= cmd
[2] >> 3;
319 build_table_color(TimonRomTable
[version
][0], pdec
->table_0004_pass1
, pdec
->table_8004_pass1
);
320 build_table_color(TimonRomTable
[version
][1], pdec
->table_0004_pass2
, pdec
->table_8004_pass2
);
323 /* Information can be coded on a variable number of bits but never less than 8 */
324 shift
= 8 - pdec
->nbits
;
325 pdec
->scalebits
= SCALEBITS
- shift
;
326 pdec
->nbitsmask
= 0xFF >> shift
;
328 fill_table_dc00_d800(pdec
);
329 build_subblock_pattern(pdec
);
330 build_bit_powermask_table(pdec
);
332 #if USE_LOOKUP_TABLE_TO_CLAMP
333 /* Build the static table to clamp value [0-255] */
334 for (i
=0;i
<MAX_OUTER_CROP_VALUE
;i
++)
335 pwc_crop_table
[i
] = 0;
336 for (i
=0; i
<256; i
++)
337 pwc_crop_table
[MAX_OUTER_CROP_VALUE
+i
] = i
;
338 for (i
=0; i
<MAX_OUTER_CROP_VALUE
; i
++)
339 pwc_crop_table
[MAX_OUTER_CROP_VALUE
+256+i
] = 255;
342 pdec
->last_cmd
= cmd
[2];
343 pdec
->last_cmd_valid
= 1;
347 * Copy the 4x4 image block to Y plane buffer
349 static void copy_image_block_Y(const int *src
, unsigned char *dst
, unsigned int bytes_per_line
, unsigned int scalebits
)
351 #if UNROLL_LOOP_FOR_COPY
352 const unsigned char *cm
= pwc_crop_table
+MAX_OUTER_CROP_VALUE
;
354 unsigned char *d
= dst
;
356 *d
++ = cm
[c
[0] >> scalebits
];
357 *d
++ = cm
[c
[1] >> scalebits
];
358 *d
++ = cm
[c
[2] >> scalebits
];
359 *d
++ = cm
[c
[3] >> scalebits
];
361 d
= dst
+ bytes_per_line
;
362 *d
++ = cm
[c
[4] >> scalebits
];
363 *d
++ = cm
[c
[5] >> scalebits
];
364 *d
++ = cm
[c
[6] >> scalebits
];
365 *d
++ = cm
[c
[7] >> scalebits
];
367 d
= dst
+ bytes_per_line
*2;
368 *d
++ = cm
[c
[8] >> scalebits
];
369 *d
++ = cm
[c
[9] >> scalebits
];
370 *d
++ = cm
[c
[10] >> scalebits
];
371 *d
++ = cm
[c
[11] >> scalebits
];
373 d
= dst
+ bytes_per_line
*3;
374 *d
++ = cm
[c
[12] >> scalebits
];
375 *d
++ = cm
[c
[13] >> scalebits
];
376 *d
++ = cm
[c
[14] >> scalebits
];
377 *d
++ = cm
[c
[15] >> scalebits
];
381 unsigned char *d
= dst
;
382 for (i
= 0; i
< 4; i
++, c
++)
383 *d
++ = CLAMP((*c
) >> scalebits
);
385 d
= dst
+ bytes_per_line
;
386 for (i
= 0; i
< 4; i
++, c
++)
387 *d
++ = CLAMP((*c
) >> scalebits
);
389 d
= dst
+ bytes_per_line
*2;
390 for (i
= 0; i
< 4; i
++, c
++)
391 *d
++ = CLAMP((*c
) >> scalebits
);
393 d
= dst
+ bytes_per_line
*3;
394 for (i
= 0; i
< 4; i
++, c
++)
395 *d
++ = CLAMP((*c
) >> scalebits
);
400 * Copy the 4x4 image block to a CrCb plane buffer
403 static void copy_image_block_CrCb(const int *src
, unsigned char *dst
, unsigned int bytes_per_line
, unsigned int scalebits
)
405 #if UNROLL_LOOP_FOR_COPY
406 /* Unroll all loops */
407 const unsigned char *cm
= pwc_crop_table
+MAX_OUTER_CROP_VALUE
;
409 unsigned char *d
= dst
;
411 *d
++ = cm
[c
[0] >> scalebits
];
412 *d
++ = cm
[c
[4] >> scalebits
];
413 *d
++ = cm
[c
[1] >> scalebits
];
414 *d
++ = cm
[c
[5] >> scalebits
];
415 *d
++ = cm
[c
[2] >> scalebits
];
416 *d
++ = cm
[c
[6] >> scalebits
];
417 *d
++ = cm
[c
[3] >> scalebits
];
418 *d
++ = cm
[c
[7] >> scalebits
];
420 d
= dst
+ bytes_per_line
;
421 *d
++ = cm
[c
[12] >> scalebits
];
422 *d
++ = cm
[c
[8] >> scalebits
];
423 *d
++ = cm
[c
[13] >> scalebits
];
424 *d
++ = cm
[c
[9] >> scalebits
];
425 *d
++ = cm
[c
[14] >> scalebits
];
426 *d
++ = cm
[c
[10] >> scalebits
];
427 *d
++ = cm
[c
[15] >> scalebits
];
428 *d
++ = cm
[c
[11] >> scalebits
];
432 const int *c2
= src
+ 4;
433 unsigned char *d
= dst
;
435 for (i
= 0; i
< 4; i
++, c1
++, c2
++) {
436 *d
++ = CLAMP((*c1
) >> scalebits
);
437 *d
++ = CLAMP((*c2
) >> scalebits
);
440 d
= dst
+ bytes_per_line
;
441 for (i
= 0; i
< 4; i
++, c1
++, c2
++) {
442 *d
++ = CLAMP((*c1
) >> scalebits
);
443 *d
++ = CLAMP((*c2
) >> scalebits
);
449 * To manage the stream, we keep bits in a 32 bits register.
450 * fill_nbits(n): fill the reservoir with at least n bits
451 * skip_bits(n): discard n bits from the reservoir
452 * get_bits(n): fill the reservoir, returns the first n bits and discard the
453 * bits from the reservoir.
454 * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
455 * contains at least n bits. bits returned is discarded.
457 #define fill_nbits(pdec, nbits_wanted) do { \
458 while (pdec->nbits_in_reservoir<(nbits_wanted)) \
460 pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
461 pdec->nbits_in_reservoir += 8; \
465 #define skip_nbits(pdec, nbits_to_skip) do { \
466 pdec->reservoir >>= (nbits_to_skip); \
467 pdec->nbits_in_reservoir -= (nbits_to_skip); \
470 #define get_nbits(pdec, nbits_wanted, result) do { \
471 fill_nbits(pdec, nbits_wanted); \
472 result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
473 skip_nbits(pdec, nbits_wanted); \
476 #define __get_nbits(pdec, nbits_wanted, result) do { \
477 result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
478 skip_nbits(pdec, nbits_wanted); \
481 #define look_nbits(pdec, nbits_wanted) \
482 ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
485 * Decode a 4x4 pixel block
487 static void decode_block(struct pwc_dec23_private
*pdec
,
488 const unsigned char *ptable0004
,
489 const unsigned char *ptable8004
)
491 unsigned int primary_color
;
492 unsigned int channel_v
, offset1
, op
;
495 fill_nbits(pdec
, 16);
496 __get_nbits(pdec
, pdec
->nbits
, primary_color
);
498 if (look_nbits(pdec
,2) == 0) {
500 /* Very simple, the color is the same for all pixels of the square */
501 for (i
= 0; i
< 16; i
++)
502 pdec
->temp_colors
[i
] = pdec
->table_dc00
[primary_color
];
507 /* This block is encoded with small pattern */
508 for (i
= 0; i
< 16; i
++)
509 pdec
->temp_colors
[i
] = pdec
->table_d800
[primary_color
];
511 __get_nbits(pdec
, 3, channel_v
);
512 channel_v
= ((channel_v
& 1) << 2) | (channel_v
& 2) | ((channel_v
& 4) >> 2);
514 ptable0004
+= (channel_v
* 128);
515 ptable8004
+= (channel_v
* 32);
520 unsigned int htable_idx
, rows
= 0;
521 const unsigned int *block
;
524 * xx == 00 :=> end of the block def, remove the two bits from the stream
526 * yxx == any other value
529 fill_nbits(pdec
, 16);
530 htable_idx
= look_nbits(pdec
, 6);
531 op
= hash_table_ops
[htable_idx
* 4];
536 } else if (op
== 1) {
537 /* 15bits [ xxxx xxxx yyyy 111 ]
538 * yyy => offset in the table8004
539 * xxx => offset in the tabled004 (tree)
541 unsigned int mask
, shift
;
542 unsigned int nbits
, col1
;
546 /* offset1 += yyyy */
547 __get_nbits(pdec
, 4, yyyy
);
550 nbits
= ptable8004
[offset1
* 2];
552 /* col1 = xxxx xxxx */
553 __get_nbits(pdec
, nbits
+1, col1
);
556 mask
= pdec
->table_bitpowermask
[nbits
][col1
];
557 shift
= ptable8004
[offset1
* 2 + 1];
558 rows
= ((mask
<< shift
) + 0x80) & 0xFF;
560 block
= pdec
->table_subblock
[rows
];
561 for (i
= 0; i
< 16; i
++)
562 pdec
->temp_colors
[i
] += block
[MulIdx
[offset1
][i
]];
566 * offset1 is coded on 3 bits
570 offset1
+= hash_table_ops
[htable_idx
* 4 + 2];
573 rows
= ptable0004
[offset1
+ hash_table_ops
[htable_idx
* 4 + 3]];
574 block
= pdec
->table_subblock
[rows
];
575 for (i
= 0; i
< 16; i
++)
576 pdec
->temp_colors
[i
] += block
[MulIdx
[offset1
][i
]];
578 shift
= hash_table_ops
[htable_idx
* 4 + 1];
579 skip_nbits(pdec
, shift
);
586 static void DecompressBand23(struct pwc_dec23_private
*pdec
,
587 const unsigned char *rawyuv
,
588 unsigned char *planar_y
,
589 unsigned char *planar_u
,
590 unsigned char *planar_v
,
591 unsigned int compressed_image_width
,
592 unsigned int real_image_width
)
594 int compression_index
, nblocks
;
595 const unsigned char *ptable0004
;
596 const unsigned char *ptable8004
;
599 pdec
->nbits_in_reservoir
= 0;
600 pdec
->stream
= rawyuv
+ 1; /* The first byte of the stream is skipped */
602 get_nbits(pdec
, 4, compression_index
);
604 /* pass 1: uncompress Y component */
605 nblocks
= compressed_image_width
/ 4;
607 ptable0004
= pdec
->table_0004_pass1
[compression_index
];
608 ptable8004
= pdec
->table_8004_pass1
[compression_index
];
610 /* Each block decode a square of 4x4 */
612 decode_block(pdec
, ptable0004
, ptable8004
);
613 copy_image_block_Y(pdec
->temp_colors
, planar_y
, real_image_width
, pdec
->scalebits
);
618 /* pass 2: uncompress UV component */
619 nblocks
= compressed_image_width
/ 8;
621 ptable0004
= pdec
->table_0004_pass2
[compression_index
];
622 ptable8004
= pdec
->table_8004_pass2
[compression_index
];
624 /* Each block decode a square of 4x4 */
626 decode_block(pdec
, ptable0004
, ptable8004
);
627 copy_image_block_CrCb(pdec
->temp_colors
, planar_u
, real_image_width
/2, pdec
->scalebits
);
629 decode_block(pdec
, ptable0004
, ptable8004
);
630 copy_image_block_CrCb(pdec
->temp_colors
, planar_v
, real_image_width
/2, pdec
->scalebits
);
640 * Uncompress a pwc23 buffer.
641 * @pdev: pointer to pwc device's internal struct
645 void pwc_dec23_decompress(struct pwc_device
*pdev
,
649 int bandlines_left
, bytes_per_block
;
650 struct pwc_dec23_private
*pdec
= &pdev
->dec23
;
652 /* YUV420P image format */
653 unsigned char *pout_planar_y
;
654 unsigned char *pout_planar_u
;
655 unsigned char *pout_planar_v
;
656 unsigned int plane_size
;
658 mutex_lock(&pdec
->lock
);
660 bandlines_left
= pdev
->height
/ 4;
661 bytes_per_block
= pdev
->width
* 4;
662 plane_size
= pdev
->height
* pdev
->width
;
665 pout_planar_u
= dst
+ plane_size
;
666 pout_planar_v
= dst
+ plane_size
+ plane_size
/ 4;
668 while (bandlines_left
--) {
669 DecompressBand23(pdec
, src
,
670 pout_planar_y
, pout_planar_u
, pout_planar_v
,
671 pdev
->width
, pdev
->width
);
672 src
+= pdev
->vbandlength
;
673 pout_planar_y
+= bytes_per_block
;
674 pout_planar_u
+= pdev
->width
;
675 pout_planar_v
+= pdev
->width
;
677 mutex_unlock(&pdec
->lock
);