18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* Linux driver for Philips webcam
38c2ecf20Sopenharmony_ci   Decompression for chipset version 2 et 3
48c2ecf20Sopenharmony_ci   (C) 2004-2006  Luc Saillard (luc@saillard.org)
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
78c2ecf20Sopenharmony_ci   driver and thus may have bugs that are not present in the original version.
88c2ecf20Sopenharmony_ci   Please send bug reports and support requests to <luc@saillard.org>.
98c2ecf20Sopenharmony_ci   The decompression routines have been implemented by reverse-engineering the
108c2ecf20Sopenharmony_ci   Nemosoft binary pwcx module. Caveat emptor.
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci*/
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include "pwc-timon.h"
168c2ecf20Sopenharmony_ci#include "pwc-kiara.h"
178c2ecf20Sopenharmony_ci#include "pwc-dec23.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <linux/string.h>
208c2ecf20Sopenharmony_ci#include <linux/slab.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/*
238c2ecf20Sopenharmony_ci * USE_LOOKUP_TABLE_TO_CLAMP
248c2ecf20Sopenharmony_ci *   0: use a C version of this tests:  {  a<0?0:(a>255?255:a) }
258c2ecf20Sopenharmony_ci *   1: use a faster lookup table for cpu with a big cache (intel)
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_ci#define USE_LOOKUP_TABLE_TO_CLAMP	1
288c2ecf20Sopenharmony_ci/*
298c2ecf20Sopenharmony_ci * UNROLL_LOOP_FOR_COPYING_BLOCK
308c2ecf20Sopenharmony_ci *   0: use a loop for a smaller code (but little slower)
318c2ecf20Sopenharmony_ci *   1: when unrolling the loop, gcc produces some faster code (perhaps only
328c2ecf20Sopenharmony_ci *   valid for intel processor class). Activating this option, automatically
338c2ecf20Sopenharmony_ci *   activate USE_LOOKUP_TABLE_TO_CLAMP
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_ci#define UNROLL_LOOP_FOR_COPY		1
368c2ecf20Sopenharmony_ci#if UNROLL_LOOP_FOR_COPY
378c2ecf20Sopenharmony_ci# undef USE_LOOKUP_TABLE_TO_CLAMP
388c2ecf20Sopenharmony_ci# define USE_LOOKUP_TABLE_TO_CLAMP 1
398c2ecf20Sopenharmony_ci#endif
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic void build_subblock_pattern(struct pwc_dec23_private *pdec)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	static const unsigned int initial_values[12] = {
448c2ecf20Sopenharmony_ci		-0x526500, -0x221200, 0x221200, 0x526500,
458c2ecf20Sopenharmony_ci			   -0x3de200, 0x3de200,
468c2ecf20Sopenharmony_ci		-0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
478c2ecf20Sopenharmony_ci			   -0x12c200, 0x12c200
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	};
508c2ecf20Sopenharmony_ci	static const unsigned int values_derivated[12] = {
518c2ecf20Sopenharmony_ci		0xa4ca, 0x4424, -0x4424, -0xa4ca,
528c2ecf20Sopenharmony_ci			0x7bc4, -0x7bc4,
538c2ecf20Sopenharmony_ci		0xdb69, 0x5aba, -0x5aba, -0xdb69,
548c2ecf20Sopenharmony_ci			0x2584, -0x2584
558c2ecf20Sopenharmony_ci	};
568c2ecf20Sopenharmony_ci	unsigned int temp_values[12];
578c2ecf20Sopenharmony_ci	int i, j;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	memcpy(temp_values, initial_values, sizeof(initial_values));
608c2ecf20Sopenharmony_ci	for (i = 0; i < 256; i++) {
618c2ecf20Sopenharmony_ci		for (j = 0; j < 12; j++) {
628c2ecf20Sopenharmony_ci			pdec->table_subblock[i][j] = temp_values[j];
638c2ecf20Sopenharmony_ci			temp_values[j] += values_derivated[j];
648c2ecf20Sopenharmony_ci		}
658c2ecf20Sopenharmony_ci	}
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic void build_bit_powermask_table(struct pwc_dec23_private *pdec)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	unsigned char *p;
718c2ecf20Sopenharmony_ci	unsigned int bit, byte, mask, val;
728c2ecf20Sopenharmony_ci	unsigned int bitpower = 1;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	for (bit = 0; bit < 8; bit++) {
758c2ecf20Sopenharmony_ci		mask = bitpower - 1;
768c2ecf20Sopenharmony_ci		p = pdec->table_bitpowermask[bit];
778c2ecf20Sopenharmony_ci		for (byte = 0; byte < 256; byte++) {
788c2ecf20Sopenharmony_ci			val = (byte & mask);
798c2ecf20Sopenharmony_ci			if (byte & bitpower)
808c2ecf20Sopenharmony_ci				val = -val;
818c2ecf20Sopenharmony_ci			*p++ = val;
828c2ecf20Sopenharmony_ci		}
838c2ecf20Sopenharmony_ci		bitpower<<=1;
848c2ecf20Sopenharmony_ci	}
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic void build_table_color(const unsigned int romtable[16][8],
898c2ecf20Sopenharmony_ci			      unsigned char p0004[16][1024],
908c2ecf20Sopenharmony_ci			      unsigned char p8004[16][256])
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	int compression_mode, j, k, bit, pw;
938c2ecf20Sopenharmony_ci	unsigned char *p0, *p8;
948c2ecf20Sopenharmony_ci	const unsigned int *r;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	/* We have 16 compressions tables */
978c2ecf20Sopenharmony_ci	for (compression_mode = 0; compression_mode < 16; compression_mode++) {
988c2ecf20Sopenharmony_ci		p0 = p0004[compression_mode];
998c2ecf20Sopenharmony_ci		p8 = p8004[compression_mode];
1008c2ecf20Sopenharmony_ci		r  = romtable[compression_mode];
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci		for (j = 0; j < 8; j++, r++, p0 += 128) {
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci			for (k = 0; k < 16; k++) {
1058c2ecf20Sopenharmony_ci				if (k == 0)
1068c2ecf20Sopenharmony_ci					bit = 1;
1078c2ecf20Sopenharmony_ci				else if (k >= 1 && k < 3)
1088c2ecf20Sopenharmony_ci					bit = (r[0] >> 15) & 7;
1098c2ecf20Sopenharmony_ci				else if (k >= 3 && k < 6)
1108c2ecf20Sopenharmony_ci					bit = (r[0] >> 12) & 7;
1118c2ecf20Sopenharmony_ci				else if (k >= 6 && k < 10)
1128c2ecf20Sopenharmony_ci					bit = (r[0] >> 9) & 7;
1138c2ecf20Sopenharmony_ci				else if (k >= 10 && k < 13)
1148c2ecf20Sopenharmony_ci					bit = (r[0] >> 6) & 7;
1158c2ecf20Sopenharmony_ci				else if (k >= 13 && k < 15)
1168c2ecf20Sopenharmony_ci					bit = (r[0] >> 3) & 7;
1178c2ecf20Sopenharmony_ci				else
1188c2ecf20Sopenharmony_ci					bit = (r[0]) & 7;
1198c2ecf20Sopenharmony_ci				if (k == 0)
1208c2ecf20Sopenharmony_ci					*p8++ = 8;
1218c2ecf20Sopenharmony_ci				else
1228c2ecf20Sopenharmony_ci					*p8++ = j - bit;
1238c2ecf20Sopenharmony_ci				*p8++ = bit;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci				pw = 1 << bit;
1268c2ecf20Sopenharmony_ci				p0[k + 0x00] = (1 * pw) + 0x80;
1278c2ecf20Sopenharmony_ci				p0[k + 0x10] = (2 * pw) + 0x80;
1288c2ecf20Sopenharmony_ci				p0[k + 0x20] = (3 * pw) + 0x80;
1298c2ecf20Sopenharmony_ci				p0[k + 0x30] = (4 * pw) + 0x80;
1308c2ecf20Sopenharmony_ci				p0[k + 0x40] = (-1 * pw) + 0x80;
1318c2ecf20Sopenharmony_ci				p0[k + 0x50] = (-2 * pw) + 0x80;
1328c2ecf20Sopenharmony_ci				p0[k + 0x60] = (-3 * pw) + 0x80;
1338c2ecf20Sopenharmony_ci				p0[k + 0x70] = (-4 * pw) + 0x80;
1348c2ecf20Sopenharmony_ci			}	/* end of for (k=0; k<16; k++, p8++) */
1358c2ecf20Sopenharmony_ci		}	/* end of for (j=0; j<8; j++ , table++) */
1368c2ecf20Sopenharmony_ci	} /* end of foreach compression_mode */
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci/*
1408c2ecf20Sopenharmony_ci *
1418c2ecf20Sopenharmony_ci */
1428c2ecf20Sopenharmony_cistatic void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci#define SCALEBITS 15
1458c2ecf20Sopenharmony_ci#define ONE_HALF  (1UL << (SCALEBITS - 1))
1468c2ecf20Sopenharmony_ci	int i;
1478c2ecf20Sopenharmony_ci	unsigned int offset1 = ONE_HALF;
1488c2ecf20Sopenharmony_ci	unsigned int offset2 = 0x0000;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	for (i=0; i<256; i++) {
1518c2ecf20Sopenharmony_ci		pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
1528c2ecf20Sopenharmony_ci		pdec->table_d800[i] = offset2;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci		offset1 += 0x7bc4;
1558c2ecf20Sopenharmony_ci		offset2 += 0x7bc4;
1568c2ecf20Sopenharmony_ci	}
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci/*
1608c2ecf20Sopenharmony_ci * To decode the stream:
1618c2ecf20Sopenharmony_ci *   if look_bits(2) == 0:	# op == 2 in the lookup table
1628c2ecf20Sopenharmony_ci *      skip_bits(2)
1638c2ecf20Sopenharmony_ci *      end of the stream
1648c2ecf20Sopenharmony_ci *   elif look_bits(3) == 7:	# op == 1 in the lookup table
1658c2ecf20Sopenharmony_ci *      skip_bits(3)
1668c2ecf20Sopenharmony_ci *      yyyy = get_bits(4)
1678c2ecf20Sopenharmony_ci *      xxxx = get_bits(8)
1688c2ecf20Sopenharmony_ci *   else:			# op == 0 in the lookup table
1698c2ecf20Sopenharmony_ci *      skip_bits(x)
1708c2ecf20Sopenharmony_ci *
1718c2ecf20Sopenharmony_ci * For speedup processing, we build a lookup table and we takes the first 6 bits.
1728c2ecf20Sopenharmony_ci *
1738c2ecf20Sopenharmony_ci * struct {
1748c2ecf20Sopenharmony_ci *   unsigned char op;	    // operation to execute
1758c2ecf20Sopenharmony_ci *   unsigned char bits;    // bits use to perform operation
1768c2ecf20Sopenharmony_ci *   unsigned char offset1; // offset to add to access in the table_0004 % 16
1778c2ecf20Sopenharmony_ci *   unsigned char offset2; // offset to add to access in the table_0004
1788c2ecf20Sopenharmony_ci * }
1798c2ecf20Sopenharmony_ci *
1808c2ecf20Sopenharmony_ci * How to build this table ?
1818c2ecf20Sopenharmony_ci *   op == 2 when (i%4)==0
1828c2ecf20Sopenharmony_ci *   op == 1 when (i%8)==7
1838c2ecf20Sopenharmony_ci *   op == 0 otherwise
1848c2ecf20Sopenharmony_ci *
1858c2ecf20Sopenharmony_ci */
1868c2ecf20Sopenharmony_cistatic const unsigned char hash_table_ops[64*4] = {
1878c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
1888c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x00,
1898c2ecf20Sopenharmony_ci	0x00, 0x04, 0x01, 0x10,
1908c2ecf20Sopenharmony_ci	0x00, 0x06, 0x01, 0x30,
1918c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
1928c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x40,
1938c2ecf20Sopenharmony_ci	0x00, 0x05, 0x01, 0x20,
1948c2ecf20Sopenharmony_ci	0x01, 0x00, 0x00, 0x00,
1958c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
1968c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x00,
1978c2ecf20Sopenharmony_ci	0x00, 0x04, 0x01, 0x50,
1988c2ecf20Sopenharmony_ci	0x00, 0x05, 0x02, 0x00,
1998c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2008c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x40,
2018c2ecf20Sopenharmony_ci	0x00, 0x05, 0x03, 0x00,
2028c2ecf20Sopenharmony_ci	0x01, 0x00, 0x00, 0x00,
2038c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2048c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x00,
2058c2ecf20Sopenharmony_ci	0x00, 0x04, 0x01, 0x10,
2068c2ecf20Sopenharmony_ci	0x00, 0x06, 0x02, 0x10,
2078c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2088c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x40,
2098c2ecf20Sopenharmony_ci	0x00, 0x05, 0x01, 0x60,
2108c2ecf20Sopenharmony_ci	0x01, 0x00, 0x00, 0x00,
2118c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2128c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x00,
2138c2ecf20Sopenharmony_ci	0x00, 0x04, 0x01, 0x50,
2148c2ecf20Sopenharmony_ci	0x00, 0x05, 0x02, 0x40,
2158c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2168c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x40,
2178c2ecf20Sopenharmony_ci	0x00, 0x05, 0x03, 0x40,
2188c2ecf20Sopenharmony_ci	0x01, 0x00, 0x00, 0x00,
2198c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2208c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x00,
2218c2ecf20Sopenharmony_ci	0x00, 0x04, 0x01, 0x10,
2228c2ecf20Sopenharmony_ci	0x00, 0x06, 0x01, 0x70,
2238c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2248c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x40,
2258c2ecf20Sopenharmony_ci	0x00, 0x05, 0x01, 0x20,
2268c2ecf20Sopenharmony_ci	0x01, 0x00, 0x00, 0x00,
2278c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2288c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x00,
2298c2ecf20Sopenharmony_ci	0x00, 0x04, 0x01, 0x50,
2308c2ecf20Sopenharmony_ci	0x00, 0x05, 0x02, 0x00,
2318c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2328c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x40,
2338c2ecf20Sopenharmony_ci	0x00, 0x05, 0x03, 0x00,
2348c2ecf20Sopenharmony_ci	0x01, 0x00, 0x00, 0x00,
2358c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2368c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x00,
2378c2ecf20Sopenharmony_ci	0x00, 0x04, 0x01, 0x10,
2388c2ecf20Sopenharmony_ci	0x00, 0x06, 0x02, 0x50,
2398c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2408c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x40,
2418c2ecf20Sopenharmony_ci	0x00, 0x05, 0x01, 0x60,
2428c2ecf20Sopenharmony_ci	0x01, 0x00, 0x00, 0x00,
2438c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2448c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x00,
2458c2ecf20Sopenharmony_ci	0x00, 0x04, 0x01, 0x50,
2468c2ecf20Sopenharmony_ci	0x00, 0x05, 0x02, 0x40,
2478c2ecf20Sopenharmony_ci	0x02, 0x00, 0x00, 0x00,
2488c2ecf20Sopenharmony_ci	0x00, 0x03, 0x01, 0x40,
2498c2ecf20Sopenharmony_ci	0x00, 0x05, 0x03, 0x40,
2508c2ecf20Sopenharmony_ci	0x01, 0x00, 0x00, 0x00
2518c2ecf20Sopenharmony_ci};
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci/*
2548c2ecf20Sopenharmony_ci *
2558c2ecf20Sopenharmony_ci */
2568c2ecf20Sopenharmony_cistatic const unsigned int MulIdx[16][16] = {
2578c2ecf20Sopenharmony_ci	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
2588c2ecf20Sopenharmony_ci	{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
2598c2ecf20Sopenharmony_ci	{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
2608c2ecf20Sopenharmony_ci	{4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
2618c2ecf20Sopenharmony_ci	{6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
2628c2ecf20Sopenharmony_ci	{4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
2638c2ecf20Sopenharmony_ci	{1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
2648c2ecf20Sopenharmony_ci	{0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
2658c2ecf20Sopenharmony_ci	{0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
2668c2ecf20Sopenharmony_ci	{1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
2678c2ecf20Sopenharmony_ci	{7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
2688c2ecf20Sopenharmony_ci	{4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
2698c2ecf20Sopenharmony_ci	{7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
2708c2ecf20Sopenharmony_ci	{1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
2718c2ecf20Sopenharmony_ci	{1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
2728c2ecf20Sopenharmony_ci	{10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
2738c2ecf20Sopenharmony_ci};
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci#if USE_LOOKUP_TABLE_TO_CLAMP
2768c2ecf20Sopenharmony_ci#define MAX_OUTER_CROP_VALUE	(512)
2778c2ecf20Sopenharmony_cistatic unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
2788c2ecf20Sopenharmony_ci#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
2798c2ecf20Sopenharmony_ci#else
2808c2ecf20Sopenharmony_ci#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
2818c2ecf20Sopenharmony_ci#endif
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci/* If the type or the command change, we rebuild the lookup table */
2858c2ecf20Sopenharmony_civoid pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	int flags, version, shift, i;
2888c2ecf20Sopenharmony_ci	struct pwc_dec23_private *pdec = &pdev->dec23;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	mutex_init(&pdec->lock);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
2938c2ecf20Sopenharmony_ci		return;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	if (DEVICE_USE_CODEC3(pdev->type)) {
2968c2ecf20Sopenharmony_ci		flags = cmd[2] & 0x18;
2978c2ecf20Sopenharmony_ci		if (flags == 8)
2988c2ecf20Sopenharmony_ci			pdec->nbits = 7;	/* More bits, mean more bits to encode the stream, but better quality */
2998c2ecf20Sopenharmony_ci		else if (flags == 0x10)
3008c2ecf20Sopenharmony_ci			pdec->nbits = 8;
3018c2ecf20Sopenharmony_ci		else
3028c2ecf20Sopenharmony_ci			pdec->nbits = 6;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci		version = cmd[2] >> 5;
3058c2ecf20Sopenharmony_ci		build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
3068c2ecf20Sopenharmony_ci		build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	} else {
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci		flags = cmd[2] & 6;
3118c2ecf20Sopenharmony_ci		if (flags == 2)
3128c2ecf20Sopenharmony_ci			pdec->nbits = 7;
3138c2ecf20Sopenharmony_ci		else if (flags == 4)
3148c2ecf20Sopenharmony_ci			pdec->nbits = 8;
3158c2ecf20Sopenharmony_ci		else
3168c2ecf20Sopenharmony_ci			pdec->nbits = 6;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci		version = cmd[2] >> 3;
3198c2ecf20Sopenharmony_ci		build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
3208c2ecf20Sopenharmony_ci		build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
3218c2ecf20Sopenharmony_ci	}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	/* Information can be coded on a variable number of bits but never less than 8 */
3248c2ecf20Sopenharmony_ci	shift = 8 - pdec->nbits;
3258c2ecf20Sopenharmony_ci	pdec->scalebits = SCALEBITS - shift;
3268c2ecf20Sopenharmony_ci	pdec->nbitsmask = 0xFF >> shift;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	fill_table_dc00_d800(pdec);
3298c2ecf20Sopenharmony_ci	build_subblock_pattern(pdec);
3308c2ecf20Sopenharmony_ci	build_bit_powermask_table(pdec);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci#if USE_LOOKUP_TABLE_TO_CLAMP
3338c2ecf20Sopenharmony_ci	/* Build the static table to clamp value [0-255] */
3348c2ecf20Sopenharmony_ci	for (i=0;i<MAX_OUTER_CROP_VALUE;i++)
3358c2ecf20Sopenharmony_ci		pwc_crop_table[i] = 0;
3368c2ecf20Sopenharmony_ci	for (i=0; i<256; i++)
3378c2ecf20Sopenharmony_ci		pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
3388c2ecf20Sopenharmony_ci	for (i=0; i<MAX_OUTER_CROP_VALUE; i++)
3398c2ecf20Sopenharmony_ci		pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
3408c2ecf20Sopenharmony_ci#endif
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	pdec->last_cmd = cmd[2];
3438c2ecf20Sopenharmony_ci	pdec->last_cmd_valid = 1;
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci/*
3478c2ecf20Sopenharmony_ci * Copy the 4x4 image block to Y plane buffer
3488c2ecf20Sopenharmony_ci */
3498c2ecf20Sopenharmony_cistatic void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
3508c2ecf20Sopenharmony_ci{
3518c2ecf20Sopenharmony_ci#if UNROLL_LOOP_FOR_COPY
3528c2ecf20Sopenharmony_ci	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
3538c2ecf20Sopenharmony_ci	const int *c = src;
3548c2ecf20Sopenharmony_ci	unsigned char *d = dst;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	*d++ = cm[c[0] >> scalebits];
3578c2ecf20Sopenharmony_ci	*d++ = cm[c[1] >> scalebits];
3588c2ecf20Sopenharmony_ci	*d++ = cm[c[2] >> scalebits];
3598c2ecf20Sopenharmony_ci	*d++ = cm[c[3] >> scalebits];
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	d = dst + bytes_per_line;
3628c2ecf20Sopenharmony_ci	*d++ = cm[c[4] >> scalebits];
3638c2ecf20Sopenharmony_ci	*d++ = cm[c[5] >> scalebits];
3648c2ecf20Sopenharmony_ci	*d++ = cm[c[6] >> scalebits];
3658c2ecf20Sopenharmony_ci	*d++ = cm[c[7] >> scalebits];
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	d = dst + bytes_per_line*2;
3688c2ecf20Sopenharmony_ci	*d++ = cm[c[8] >> scalebits];
3698c2ecf20Sopenharmony_ci	*d++ = cm[c[9] >> scalebits];
3708c2ecf20Sopenharmony_ci	*d++ = cm[c[10] >> scalebits];
3718c2ecf20Sopenharmony_ci	*d++ = cm[c[11] >> scalebits];
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	d = dst + bytes_per_line*3;
3748c2ecf20Sopenharmony_ci	*d++ = cm[c[12] >> scalebits];
3758c2ecf20Sopenharmony_ci	*d++ = cm[c[13] >> scalebits];
3768c2ecf20Sopenharmony_ci	*d++ = cm[c[14] >> scalebits];
3778c2ecf20Sopenharmony_ci	*d++ = cm[c[15] >> scalebits];
3788c2ecf20Sopenharmony_ci#else
3798c2ecf20Sopenharmony_ci	int i;
3808c2ecf20Sopenharmony_ci	const int *c = src;
3818c2ecf20Sopenharmony_ci	unsigned char *d = dst;
3828c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++, c++)
3838c2ecf20Sopenharmony_ci		*d++ = CLAMP((*c) >> scalebits);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	d = dst + bytes_per_line;
3868c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++, c++)
3878c2ecf20Sopenharmony_ci		*d++ = CLAMP((*c) >> scalebits);
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	d = dst + bytes_per_line*2;
3908c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++, c++)
3918c2ecf20Sopenharmony_ci		*d++ = CLAMP((*c) >> scalebits);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	d = dst + bytes_per_line*3;
3948c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++, c++)
3958c2ecf20Sopenharmony_ci		*d++ = CLAMP((*c) >> scalebits);
3968c2ecf20Sopenharmony_ci#endif
3978c2ecf20Sopenharmony_ci}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci/*
4008c2ecf20Sopenharmony_ci * Copy the 4x4 image block to a CrCb plane buffer
4018c2ecf20Sopenharmony_ci *
4028c2ecf20Sopenharmony_ci */
4038c2ecf20Sopenharmony_cistatic void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci#if UNROLL_LOOP_FOR_COPY
4068c2ecf20Sopenharmony_ci	/* Unroll all loops */
4078c2ecf20Sopenharmony_ci	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
4088c2ecf20Sopenharmony_ci	const int *c = src;
4098c2ecf20Sopenharmony_ci	unsigned char *d = dst;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	*d++ = cm[c[0] >> scalebits];
4128c2ecf20Sopenharmony_ci	*d++ = cm[c[4] >> scalebits];
4138c2ecf20Sopenharmony_ci	*d++ = cm[c[1] >> scalebits];
4148c2ecf20Sopenharmony_ci	*d++ = cm[c[5] >> scalebits];
4158c2ecf20Sopenharmony_ci	*d++ = cm[c[2] >> scalebits];
4168c2ecf20Sopenharmony_ci	*d++ = cm[c[6] >> scalebits];
4178c2ecf20Sopenharmony_ci	*d++ = cm[c[3] >> scalebits];
4188c2ecf20Sopenharmony_ci	*d++ = cm[c[7] >> scalebits];
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	d = dst + bytes_per_line;
4218c2ecf20Sopenharmony_ci	*d++ = cm[c[12] >> scalebits];
4228c2ecf20Sopenharmony_ci	*d++ = cm[c[8] >> scalebits];
4238c2ecf20Sopenharmony_ci	*d++ = cm[c[13] >> scalebits];
4248c2ecf20Sopenharmony_ci	*d++ = cm[c[9] >> scalebits];
4258c2ecf20Sopenharmony_ci	*d++ = cm[c[14] >> scalebits];
4268c2ecf20Sopenharmony_ci	*d++ = cm[c[10] >> scalebits];
4278c2ecf20Sopenharmony_ci	*d++ = cm[c[15] >> scalebits];
4288c2ecf20Sopenharmony_ci	*d++ = cm[c[11] >> scalebits];
4298c2ecf20Sopenharmony_ci#else
4308c2ecf20Sopenharmony_ci	int i;
4318c2ecf20Sopenharmony_ci	const int *c1 = src;
4328c2ecf20Sopenharmony_ci	const int *c2 = src + 4;
4338c2ecf20Sopenharmony_ci	unsigned char *d = dst;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++, c1++, c2++) {
4368c2ecf20Sopenharmony_ci		*d++ = CLAMP((*c1) >> scalebits);
4378c2ecf20Sopenharmony_ci		*d++ = CLAMP((*c2) >> scalebits);
4388c2ecf20Sopenharmony_ci	}
4398c2ecf20Sopenharmony_ci	c1 = src + 12;
4408c2ecf20Sopenharmony_ci	d = dst + bytes_per_line;
4418c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++, c1++, c2++) {
4428c2ecf20Sopenharmony_ci		*d++ = CLAMP((*c1) >> scalebits);
4438c2ecf20Sopenharmony_ci		*d++ = CLAMP((*c2) >> scalebits);
4448c2ecf20Sopenharmony_ci	}
4458c2ecf20Sopenharmony_ci#endif
4468c2ecf20Sopenharmony_ci}
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci/*
4498c2ecf20Sopenharmony_ci * To manage the stream, we keep bits in a 32 bits register.
4508c2ecf20Sopenharmony_ci * fill_nbits(n): fill the reservoir with at least n bits
4518c2ecf20Sopenharmony_ci * skip_bits(n): discard n bits from the reservoir
4528c2ecf20Sopenharmony_ci * get_bits(n): fill the reservoir, returns the first n bits and discard the
4538c2ecf20Sopenharmony_ci *              bits from the reservoir.
4548c2ecf20Sopenharmony_ci * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
4558c2ecf20Sopenharmony_ci *                 contains at least n bits. bits returned is discarded.
4568c2ecf20Sopenharmony_ci */
4578c2ecf20Sopenharmony_ci#define fill_nbits(pdec, nbits_wanted) do { \
4588c2ecf20Sopenharmony_ci   while (pdec->nbits_in_reservoir<(nbits_wanted)) \
4598c2ecf20Sopenharmony_ci    { \
4608c2ecf20Sopenharmony_ci      pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
4618c2ecf20Sopenharmony_ci      pdec->nbits_in_reservoir += 8; \
4628c2ecf20Sopenharmony_ci    } \
4638c2ecf20Sopenharmony_ci}  while(0);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci#define skip_nbits(pdec, nbits_to_skip) do { \
4668c2ecf20Sopenharmony_ci   pdec->reservoir >>= (nbits_to_skip); \
4678c2ecf20Sopenharmony_ci   pdec->nbits_in_reservoir -= (nbits_to_skip); \
4688c2ecf20Sopenharmony_ci}  while(0);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci#define get_nbits(pdec, nbits_wanted, result) do { \
4718c2ecf20Sopenharmony_ci   fill_nbits(pdec, nbits_wanted); \
4728c2ecf20Sopenharmony_ci   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
4738c2ecf20Sopenharmony_ci   skip_nbits(pdec, nbits_wanted); \
4748c2ecf20Sopenharmony_ci}  while(0);
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci#define __get_nbits(pdec, nbits_wanted, result) do { \
4778c2ecf20Sopenharmony_ci   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
4788c2ecf20Sopenharmony_ci   skip_nbits(pdec, nbits_wanted); \
4798c2ecf20Sopenharmony_ci}  while(0);
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci#define look_nbits(pdec, nbits_wanted) \
4828c2ecf20Sopenharmony_ci   ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci/*
4858c2ecf20Sopenharmony_ci * Decode a 4x4 pixel block
4868c2ecf20Sopenharmony_ci */
4878c2ecf20Sopenharmony_cistatic void decode_block(struct pwc_dec23_private *pdec,
4888c2ecf20Sopenharmony_ci			 const unsigned char *ptable0004,
4898c2ecf20Sopenharmony_ci			 const unsigned char *ptable8004)
4908c2ecf20Sopenharmony_ci{
4918c2ecf20Sopenharmony_ci	unsigned int primary_color;
4928c2ecf20Sopenharmony_ci	unsigned int channel_v, offset1, op;
4938c2ecf20Sopenharmony_ci	int i;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	fill_nbits(pdec, 16);
4968c2ecf20Sopenharmony_ci	__get_nbits(pdec, pdec->nbits, primary_color);
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	if (look_nbits(pdec,2) == 0) {
4998c2ecf20Sopenharmony_ci		skip_nbits(pdec, 2);
5008c2ecf20Sopenharmony_ci		/* Very simple, the color is the same for all pixels of the square */
5018c2ecf20Sopenharmony_ci		for (i = 0; i < 16; i++)
5028c2ecf20Sopenharmony_ci			pdec->temp_colors[i] = pdec->table_dc00[primary_color];
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci		return;
5058c2ecf20Sopenharmony_ci	}
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	/* This block is encoded with small pattern */
5088c2ecf20Sopenharmony_ci	for (i = 0; i < 16; i++)
5098c2ecf20Sopenharmony_ci		pdec->temp_colors[i] = pdec->table_d800[primary_color];
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	__get_nbits(pdec, 3, channel_v);
5128c2ecf20Sopenharmony_ci	channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	ptable0004 += (channel_v * 128);
5158c2ecf20Sopenharmony_ci	ptable8004 += (channel_v * 32);
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	offset1 = 0;
5188c2ecf20Sopenharmony_ci	do
5198c2ecf20Sopenharmony_ci	{
5208c2ecf20Sopenharmony_ci		unsigned int htable_idx, rows = 0;
5218c2ecf20Sopenharmony_ci		const unsigned int *block;
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci		/* [  zzzz y x x ]
5248c2ecf20Sopenharmony_ci		 *     xx == 00 :=> end of the block def, remove the two bits from the stream
5258c2ecf20Sopenharmony_ci		 *    yxx == 111
5268c2ecf20Sopenharmony_ci		 *    yxx == any other value
5278c2ecf20Sopenharmony_ci		 *
5288c2ecf20Sopenharmony_ci		 */
5298c2ecf20Sopenharmony_ci		fill_nbits(pdec, 16);
5308c2ecf20Sopenharmony_ci		htable_idx = look_nbits(pdec, 6);
5318c2ecf20Sopenharmony_ci		op = hash_table_ops[htable_idx * 4];
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci		if (op == 2) {
5348c2ecf20Sopenharmony_ci			skip_nbits(pdec, 2);
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci		} else if (op == 1) {
5378c2ecf20Sopenharmony_ci			/* 15bits [ xxxx xxxx yyyy 111 ]
5388c2ecf20Sopenharmony_ci			 * yyy => offset in the table8004
5398c2ecf20Sopenharmony_ci			 * xxx => offset in the tabled004 (tree)
5408c2ecf20Sopenharmony_ci			 */
5418c2ecf20Sopenharmony_ci			unsigned int mask, shift;
5428c2ecf20Sopenharmony_ci			unsigned int nbits, col1;
5438c2ecf20Sopenharmony_ci			unsigned int yyyy;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci			skip_nbits(pdec, 3);
5468c2ecf20Sopenharmony_ci			/* offset1 += yyyy */
5478c2ecf20Sopenharmony_ci			__get_nbits(pdec, 4, yyyy);
5488c2ecf20Sopenharmony_ci			offset1 += 1 + yyyy;
5498c2ecf20Sopenharmony_ci			offset1 &= 0x0F;
5508c2ecf20Sopenharmony_ci			nbits = ptable8004[offset1 * 2];
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci			/* col1 = xxxx xxxx */
5538c2ecf20Sopenharmony_ci			__get_nbits(pdec, nbits+1, col1);
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci			/* Bit mask table */
5568c2ecf20Sopenharmony_ci			mask = pdec->table_bitpowermask[nbits][col1];
5578c2ecf20Sopenharmony_ci			shift = ptable8004[offset1 * 2 + 1];
5588c2ecf20Sopenharmony_ci			rows = ((mask << shift) + 0x80) & 0xFF;
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci			block = pdec->table_subblock[rows];
5618c2ecf20Sopenharmony_ci			for (i = 0; i < 16; i++)
5628c2ecf20Sopenharmony_ci				pdec->temp_colors[i] += block[MulIdx[offset1][i]];
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci		} else {
5658c2ecf20Sopenharmony_ci			/* op == 0
5668c2ecf20Sopenharmony_ci			 * offset1 is coded on 3 bits
5678c2ecf20Sopenharmony_ci			 */
5688c2ecf20Sopenharmony_ci			unsigned int shift;
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci			offset1 += hash_table_ops [htable_idx * 4 + 2];
5718c2ecf20Sopenharmony_ci			offset1 &= 0x0F;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci			rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]];
5748c2ecf20Sopenharmony_ci			block = pdec->table_subblock[rows];
5758c2ecf20Sopenharmony_ci			for (i = 0; i < 16; i++)
5768c2ecf20Sopenharmony_ci				pdec->temp_colors[i] += block[MulIdx[offset1][i]];
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci			shift = hash_table_ops[htable_idx * 4 + 1];
5798c2ecf20Sopenharmony_ci			skip_nbits(pdec, shift);
5808c2ecf20Sopenharmony_ci		}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	} while (op != 2);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_cistatic void DecompressBand23(struct pwc_dec23_private *pdec,
5878c2ecf20Sopenharmony_ci			     const unsigned char *rawyuv,
5888c2ecf20Sopenharmony_ci			     unsigned char *planar_y,
5898c2ecf20Sopenharmony_ci			     unsigned char *planar_u,
5908c2ecf20Sopenharmony_ci			     unsigned char *planar_v,
5918c2ecf20Sopenharmony_ci			     unsigned int   compressed_image_width,
5928c2ecf20Sopenharmony_ci			     unsigned int   real_image_width)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	int compression_index, nblocks;
5958c2ecf20Sopenharmony_ci	const unsigned char *ptable0004;
5968c2ecf20Sopenharmony_ci	const unsigned char *ptable8004;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	pdec->reservoir = 0;
5998c2ecf20Sopenharmony_ci	pdec->nbits_in_reservoir = 0;
6008c2ecf20Sopenharmony_ci	pdec->stream = rawyuv + 1;	/* The first byte of the stream is skipped */
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	get_nbits(pdec, 4, compression_index);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	/* pass 1: uncompress Y component */
6058c2ecf20Sopenharmony_ci	nblocks = compressed_image_width / 4;
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	ptable0004 = pdec->table_0004_pass1[compression_index];
6088c2ecf20Sopenharmony_ci	ptable8004 = pdec->table_8004_pass1[compression_index];
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	/* Each block decode a square of 4x4 */
6118c2ecf20Sopenharmony_ci	while (nblocks) {
6128c2ecf20Sopenharmony_ci		decode_block(pdec, ptable0004, ptable8004);
6138c2ecf20Sopenharmony_ci		copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
6148c2ecf20Sopenharmony_ci		planar_y += 4;
6158c2ecf20Sopenharmony_ci		nblocks--;
6168c2ecf20Sopenharmony_ci	}
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	/* pass 2: uncompress UV component */
6198c2ecf20Sopenharmony_ci	nblocks = compressed_image_width / 8;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	ptable0004 = pdec->table_0004_pass2[compression_index];
6228c2ecf20Sopenharmony_ci	ptable8004 = pdec->table_8004_pass2[compression_index];
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	/* Each block decode a square of 4x4 */
6258c2ecf20Sopenharmony_ci	while (nblocks) {
6268c2ecf20Sopenharmony_ci		decode_block(pdec, ptable0004, ptable8004);
6278c2ecf20Sopenharmony_ci		copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci		decode_block(pdec, ptable0004, ptable8004);
6308c2ecf20Sopenharmony_ci		copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci		planar_v += 8;
6338c2ecf20Sopenharmony_ci		planar_u += 8;
6348c2ecf20Sopenharmony_ci		nblocks -= 2;
6358c2ecf20Sopenharmony_ci	}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci/**
6408c2ecf20Sopenharmony_ci * Uncompress a pwc23 buffer.
6418c2ecf20Sopenharmony_ci * @pdev: pointer to pwc device's internal struct
6428c2ecf20Sopenharmony_ci * @src: raw data
6438c2ecf20Sopenharmony_ci * @dst: image output
6448c2ecf20Sopenharmony_ci */
6458c2ecf20Sopenharmony_civoid pwc_dec23_decompress(struct pwc_device *pdev,
6468c2ecf20Sopenharmony_ci			  const void *src,
6478c2ecf20Sopenharmony_ci			  void *dst)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	int bandlines_left, bytes_per_block;
6508c2ecf20Sopenharmony_ci	struct pwc_dec23_private *pdec = &pdev->dec23;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	/* YUV420P image format */
6538c2ecf20Sopenharmony_ci	unsigned char *pout_planar_y;
6548c2ecf20Sopenharmony_ci	unsigned char *pout_planar_u;
6558c2ecf20Sopenharmony_ci	unsigned char *pout_planar_v;
6568c2ecf20Sopenharmony_ci	unsigned int   plane_size;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	mutex_lock(&pdec->lock);
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	bandlines_left = pdev->height / 4;
6618c2ecf20Sopenharmony_ci	bytes_per_block = pdev->width * 4;
6628c2ecf20Sopenharmony_ci	plane_size = pdev->height * pdev->width;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	pout_planar_y = dst;
6658c2ecf20Sopenharmony_ci	pout_planar_u = dst + plane_size;
6668c2ecf20Sopenharmony_ci	pout_planar_v = dst + plane_size + plane_size / 4;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	while (bandlines_left--) {
6698c2ecf20Sopenharmony_ci		DecompressBand23(pdec, src,
6708c2ecf20Sopenharmony_ci				 pout_planar_y, pout_planar_u, pout_planar_v,
6718c2ecf20Sopenharmony_ci				 pdev->width, pdev->width);
6728c2ecf20Sopenharmony_ci		src += pdev->vbandlength;
6738c2ecf20Sopenharmony_ci		pout_planar_y += bytes_per_block;
6748c2ecf20Sopenharmony_ci		pout_planar_u += pdev->width;
6758c2ecf20Sopenharmony_ci		pout_planar_v += pdev->width;
6768c2ecf20Sopenharmony_ci	}
6778c2ecf20Sopenharmony_ci	mutex_unlock(&pdec->lock);
6788c2ecf20Sopenharmony_ci}
679