brintos

brintos / linux-shallow public Read only

0
0
Text · 18.0 KiB · a3aa8c7 Raw
679 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* Linux driver for Philips webcam3   Decompression for chipset version 2 et 34   (C) 2004-2006  Luc Saillard (luc@saillard.org)5 6   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx7   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 the10   Nemosoft binary pwcx module. Caveat emptor.11 12 13*/14 15#include "pwc-timon.h"16#include "pwc-kiara.h"17#include "pwc-dec23.h"18 19#include <linux/string.h>20#include <linux/slab.h>21 22/*23 * USE_LOOKUP_TABLE_TO_CLAMP24 *   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)26 */27#define USE_LOOKUP_TABLE_TO_CLAMP	128/*29 * UNROLL_LOOP_FOR_COPYING_BLOCK30 *   0: use a loop for a smaller code (but little slower)31 *   1: when unrolling the loop, gcc produces some faster code (perhaps only32 *   valid for intel processor class). Activating this option, automatically33 *   activate USE_LOOKUP_TABLE_TO_CLAMP34 */35#define UNROLL_LOOP_FOR_COPY		136#if UNROLL_LOOP_FOR_COPY37# undef USE_LOOKUP_TABLE_TO_CLAMP38# define USE_LOOKUP_TABLE_TO_CLAMP 139#endif40 41static void build_subblock_pattern(struct pwc_dec23_private *pdec)42{43	static const unsigned int initial_values[12] = {44		-0x526500, -0x221200, 0x221200, 0x526500,45			   -0x3de200, 0x3de200,46		-0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,47			   -0x12c200, 0x12c20048 49	};50	static const unsigned int values_derivated[12] = {51		0xa4ca, 0x4424, -0x4424, -0xa4ca,52			0x7bc4, -0x7bc4,53		0xdb69, 0x5aba, -0x5aba, -0xdb69,54			0x2584, -0x258455	};56	unsigned int temp_values[12];57	int i, j;58 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];64		}65	}66}67 68static void build_bit_powermask_table(struct pwc_dec23_private *pdec)69{70	unsigned char *p;71	unsigned int bit, byte, mask, val;72	unsigned int bitpower = 1;73 74	for (bit = 0; bit < 8; bit++) {75		mask = bitpower - 1;76		p = pdec->table_bitpowermask[bit];77		for (byte = 0; byte < 256; byte++) {78			val = (byte & mask);79			if (byte & bitpower)80				val = -val;81			*p++ = val;82		}83		bitpower<<=1;84	}85}86 87 88static void build_table_color(const unsigned int romtable[16][8],89			      unsigned char p0004[16][1024],90			      unsigned char p8004[16][256])91{92	int compression_mode, j, k, bit, pw;93	unsigned char *p0, *p8;94	const unsigned int *r;95 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];101 102		for (j = 0; j < 8; j++, r++, p0 += 128) {103 104			for (k = 0; k < 16; k++) {105				if (k == 0)106					bit = 1;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;117				else118					bit = (r[0]) & 7;119				if (k == 0)120					*p8++ = 8;121				else122					*p8++ = j - bit;123				*p8++ = bit;124 125				pw = 1 << bit;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 */137}138 139/*140 *141 */142static void fill_table_dc00_d800(struct pwc_dec23_private *pdec)143{144#define SCALEBITS 15145#define ONE_HALF  (1UL << (SCALEBITS - 1))146	int i;147	unsigned int offset1 = ONE_HALF;148	unsigned int offset2 = 0x0000;149 150	for (i=0; i<256; i++) {151		pdec->table_dc00[i] = offset1 & ~(ONE_HALF);152		pdec->table_d800[i] = offset2;153 154		offset1 += 0x7bc4;155		offset2 += 0x7bc4;156	}157}158 159/*160 * To decode the stream:161 *   if look_bits(2) == 0:	# op == 2 in the lookup table162 *      skip_bits(2)163 *      end of the stream164 *   elif look_bits(3) == 7:	# op == 1 in the lookup table165 *      skip_bits(3)166 *      yyyy = get_bits(4)167 *      xxxx = get_bits(8)168 *   else:			# op == 0 in the lookup table169 *      skip_bits(x)170 *171 * For speedup processing, we build a lookup table and we takes the first 6 bits.172 *173 * struct {174 *   unsigned char op;	    // operation to execute175 *   unsigned char bits;    // bits use to perform operation176 *   unsigned char offset1; // offset to add to access in the table_0004 % 16177 *   unsigned char offset2; // offset to add to access in the table_0004178 * }179 *180 * How to build this table ?181 *   op == 2 when (i%4)==0182 *   op == 1 when (i%8)==7183 *   op == 0 otherwise184 *185 */186static 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, 0x00251};252 253/*254 *255 */256static 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}273};274 275#if USE_LOOKUP_TABLE_TO_CLAMP276#define MAX_OUTER_CROP_VALUE	(512)277static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];278#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])279#else280#define CLAMP(x) ((x)>255?255:((x)<0?0:x))281#endif282 283 284/* If the type or the command change, we rebuild the lookup table */285void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)286{287	int flags, version, shift, i;288	struct pwc_dec23_private *pdec = &pdev->dec23;289 290	mutex_init(&pdec->lock);291 292	if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])293		return;294 295	if (DEVICE_USE_CODEC3(pdev->type)) {296		flags = cmd[2] & 0x18;297		if (flags == 8)298			pdec->nbits = 7;	/* More bits, mean more bits to encode the stream, but better quality */299		else if (flags == 0x10)300			pdec->nbits = 8;301		else302			pdec->nbits = 6;303 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);307 308	} else {309 310		flags = cmd[2] & 6;311		if (flags == 2)312			pdec->nbits = 7;313		else if (flags == 4)314			pdec->nbits = 8;315		else316			pdec->nbits = 6;317 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);321	}322 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;327 328	fill_table_dc00_d800(pdec);329	build_subblock_pattern(pdec);330	build_bit_powermask_table(pdec);331 332#if USE_LOOKUP_TABLE_TO_CLAMP333	/* 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;340#endif341 342	pdec->last_cmd = cmd[2];343	pdec->last_cmd_valid = 1;344}345 346/*347 * Copy the 4x4 image block to Y plane buffer348 */349static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)350{351#if UNROLL_LOOP_FOR_COPY352	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;353	const int *c = src;354	unsigned char *d = dst;355 356	*d++ = cm[c[0] >> scalebits];357	*d++ = cm[c[1] >> scalebits];358	*d++ = cm[c[2] >> scalebits];359	*d++ = cm[c[3] >> scalebits];360 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];366 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];372 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];378#else379	int i;380	const int *c = src;381	unsigned char *d = dst;382	for (i = 0; i < 4; i++, c++)383		*d++ = CLAMP((*c) >> scalebits);384 385	d = dst + bytes_per_line;386	for (i = 0; i < 4; i++, c++)387		*d++ = CLAMP((*c) >> scalebits);388 389	d = dst + bytes_per_line*2;390	for (i = 0; i < 4; i++, c++)391		*d++ = CLAMP((*c) >> scalebits);392 393	d = dst + bytes_per_line*3;394	for (i = 0; i < 4; i++, c++)395		*d++ = CLAMP((*c) >> scalebits);396#endif397}398 399/*400 * Copy the 4x4 image block to a CrCb plane buffer401 *402 */403static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)404{405#if UNROLL_LOOP_FOR_COPY406	/* Unroll all loops */407	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;408	const int *c = src;409	unsigned char *d = dst;410 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];419 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];429#else430	int i;431	const int *c1 = src;432	const int *c2 = src + 4;433	unsigned char *d = dst;434 435	for (i = 0; i < 4; i++, c1++, c2++) {436		*d++ = CLAMP((*c1) >> scalebits);437		*d++ = CLAMP((*c2) >> scalebits);438	}439	c1 = src + 12;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);444	}445#endif446}447 448/*449 * To manage the stream, we keep bits in a 32 bits register.450 * fill_nbits(n): fill the reservoir with at least n bits451 * skip_bits(n): discard n bits from the reservoir452 * get_bits(n): fill the reservoir, returns the first n bits and discard the453 *              bits from the reservoir.454 * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir455 *                 contains at least n bits. bits returned is discarded.456 */457#define fill_nbits(pdec, nbits_wanted) do { \458   while (pdec->nbits_in_reservoir<(nbits_wanted)) \459    { \460      pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \461      pdec->nbits_in_reservoir += 8; \462    } \463}  while(0);464 465#define skip_nbits(pdec, nbits_to_skip) do { \466   pdec->reservoir >>= (nbits_to_skip); \467   pdec->nbits_in_reservoir -= (nbits_to_skip); \468}  while(0);469 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); \474}  while(0);475 476#define __get_nbits(pdec, nbits_wanted, result) do { \477   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \478   skip_nbits(pdec, nbits_wanted); \479}  while(0);480 481#define look_nbits(pdec, nbits_wanted) \482   ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))483 484/*485 * Decode a 4x4 pixel block486 */487static void decode_block(struct pwc_dec23_private *pdec,488			 const unsigned char *ptable0004,489			 const unsigned char *ptable8004)490{491	unsigned int primary_color;492	unsigned int channel_v, offset1, op;493	int i;494 495	fill_nbits(pdec, 16);496	__get_nbits(pdec, pdec->nbits, primary_color);497 498	if (look_nbits(pdec,2) == 0) {499		skip_nbits(pdec, 2);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];503 504		return;505	}506 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];510 511	__get_nbits(pdec, 3, channel_v);512	channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);513 514	ptable0004 += (channel_v * 128);515	ptable8004 += (channel_v * 32);516 517	offset1 = 0;518	do519	{520		unsigned int htable_idx, rows = 0;521		const unsigned int *block;522 523		/* [  zzzz y x x ]524		 *     xx == 00 :=> end of the block def, remove the two bits from the stream525		 *    yxx == 111526		 *    yxx == any other value527		 *528		 */529		fill_nbits(pdec, 16);530		htable_idx = look_nbits(pdec, 6);531		op = hash_table_ops[htable_idx * 4];532 533		if (op == 2) {534			skip_nbits(pdec, 2);535 536		} else if (op == 1) {537			/* 15bits [ xxxx xxxx yyyy 111 ]538			 * yyy => offset in the table8004539			 * xxx => offset in the tabled004 (tree)540			 */541			unsigned int mask, shift;542			unsigned int nbits, col1;543			unsigned int yyyy;544 545			skip_nbits(pdec, 3);546			/* offset1 += yyyy */547			__get_nbits(pdec, 4, yyyy);548			offset1 += 1 + yyyy;549			offset1 &= 0x0F;550			nbits = ptable8004[offset1 * 2];551 552			/* col1 = xxxx xxxx */553			__get_nbits(pdec, nbits+1, col1);554 555			/* Bit mask table */556			mask = pdec->table_bitpowermask[nbits][col1];557			shift = ptable8004[offset1 * 2 + 1];558			rows = ((mask << shift) + 0x80) & 0xFF;559 560			block = pdec->table_subblock[rows];561			for (i = 0; i < 16; i++)562				pdec->temp_colors[i] += block[MulIdx[offset1][i]];563 564		} else {565			/* op == 0566			 * offset1 is coded on 3 bits567			 */568			unsigned int shift;569 570			offset1 += hash_table_ops [htable_idx * 4 + 2];571			offset1 &= 0x0F;572 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]];577 578			shift = hash_table_ops[htable_idx * 4 + 1];579			skip_nbits(pdec, shift);580		}581 582	} while (op != 2);583 584}585 586static 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)593{594	int compression_index, nblocks;595	const unsigned char *ptable0004;596	const unsigned char *ptable8004;597 598	pdec->reservoir = 0;599	pdec->nbits_in_reservoir = 0;600	pdec->stream = rawyuv + 1;	/* The first byte of the stream is skipped */601 602	get_nbits(pdec, 4, compression_index);603 604	/* pass 1: uncompress Y component */605	nblocks = compressed_image_width / 4;606 607	ptable0004 = pdec->table_0004_pass1[compression_index];608	ptable8004 = pdec->table_8004_pass1[compression_index];609 610	/* Each block decode a square of 4x4 */611	while (nblocks) {612		decode_block(pdec, ptable0004, ptable8004);613		copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);614		planar_y += 4;615		nblocks--;616	}617 618	/* pass 2: uncompress UV component */619	nblocks = compressed_image_width / 8;620 621	ptable0004 = pdec->table_0004_pass2[compression_index];622	ptable8004 = pdec->table_8004_pass2[compression_index];623 624	/* Each block decode a square of 4x4 */625	while (nblocks) {626		decode_block(pdec, ptable0004, ptable8004);627		copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);628 629		decode_block(pdec, ptable0004, ptable8004);630		copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);631 632		planar_v += 8;633		planar_u += 8;634		nblocks -= 2;635	}636 637}638 639/**640 * pwc_dec23_decompress - Uncompress a pwc23 buffer.641 * @pdev: pointer to pwc device's internal struct642 * @src: raw data643 * @dst: image output644 */645void pwc_dec23_decompress(struct pwc_device *pdev,646			  const void *src,647			  void *dst)648{649	int bandlines_left, bytes_per_block;650	struct pwc_dec23_private *pdec = &pdev->dec23;651 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;657 658	mutex_lock(&pdec->lock);659 660	bandlines_left = pdev->height / 4;661	bytes_per_block = pdev->width * 4;662	plane_size = pdev->height * pdev->width;663 664	pout_planar_y = dst;665	pout_planar_u = dst + plane_size;666	pout_planar_v = dst + plane_size + plane_size / 4;667 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;676	}677	mutex_unlock(&pdec->lock);678}679