[go: nahoru, domu]

12b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/* Linux driver for Philips webcam
22b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   Decompression for chipset version 2 et 3
32b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   (C) 2004-2006  Luc Saillard (luc@saillard.org)
42b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
52b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
62b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   driver and thus may have bugs that are not present in the original version.
72b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   Please send bug reports and support requests to <luc@saillard.org>.
82b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   The decompression routines have been implemented by reverse-engineering the
92b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   Nemosoft binary pwcx module. Caveat emptor.
102b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
112b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   This program is free software; you can redistribute it and/or modify
122b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   it under the terms of the GNU General Public License as published by
132b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   the Free Software Foundation; either version 2 of the License, or
142b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   (at your option) any later version.
152b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
162b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   This program is distributed in the hope that it will be useful,
172b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   but WITHOUT ANY WARRANTY; without even the implied warranty of
182b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
192b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   GNU General Public License for more details.
202b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
212b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   You should have received a copy of the GNU General Public License
222b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   along with this program; if not, write to the Free Software
232b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
242b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
252b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard*/
262b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
272b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#include "pwc-timon.h"
282b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#include "pwc-kiara.h"
292b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#include "pwc-dec23.h"
302b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
312b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#include <linux/string.h>
325a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
332b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
342b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/*
352b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * USE_LOOKUP_TABLE_TO_CLAMP
362b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   0: use a C version of this tests:  {  a<0?0:(a>255?255:a) }
372b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   1: use a faster lookup table for cpu with a big cache (intel)
382b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
392b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define USE_LOOKUP_TABLE_TO_CLAMP	1
402b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/*
412b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * UNROLL_LOOP_FOR_COPYING_BLOCK
422b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   0: use a loop for a smaller code (but little slower)
432b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   1: when unrolling the loop, gcc produces some faster code (perhaps only
442b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   valid for intel processor class). Activating this option, automaticaly
452b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   activate USE_LOOKUP_TABLE_TO_CLAMP
462b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
472b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define UNROLL_LOOP_FOR_COPY		1
482b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#if UNROLL_LOOP_FOR_COPY
492b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard# undef USE_LOOKUP_TABLE_TO_CLAMP
502b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard# define USE_LOOKUP_TABLE_TO_CLAMP 1
512b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#endif
522b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
532b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic void build_subblock_pattern(struct pwc_dec23_private *pdec)
542b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
552b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	static const unsigned int initial_values[12] = {
562b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		-0x526500, -0x221200, 0x221200, 0x526500,
572b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			   -0x3de200, 0x3de200,
582b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		-0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
592b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			   -0x12c200, 0x12c200
602b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
612b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	};
622b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	static const unsigned int values_derivated[12] = {
632b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		0xa4ca, 0x4424, -0x4424, -0xa4ca,
642b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			0x7bc4, -0x7bc4,
652b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		0xdb69, 0x5aba, -0x5aba, -0xdb69,
662b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			0x2584, -0x2584
672b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	};
682b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned int temp_values[12];
692b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	int i, j;
702b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
712b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	memcpy(temp_values, initial_values, sizeof(initial_values));
722b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i = 0; i < 256; i++) {
732b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		for (j = 0; j < 12; j++) {
742b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			pdec->table_subblock[i][j] = temp_values[j];
752b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			temp_values[j] += values_derivated[j];
762b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		}
772b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
782b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
792b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
802b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic void build_bit_powermask_table(struct pwc_dec23_private *pdec)
812b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
822b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned char *p;
832b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned int bit, byte, mask, val;
842b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned int bitpower = 1;
852b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
862b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (bit = 0; bit < 8; bit++) {
872b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		mask = bitpower - 1;
882b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		p = pdec->table_bitpowermask[bit];
892b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		for (byte = 0; byte < 256; byte++) {
902b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			val = (byte & mask);
912b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			if (byte & bitpower)
922b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				val = -val;
932b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			*p++ = val;
942b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		}
952b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		bitpower<<=1;
962b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
972b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
982b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
992b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
1002b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic void build_table_color(const unsigned int romtable[16][8],
101657de3cd32285831a56f9f96deb85c64205c42fcTrent Piepho			      unsigned char p0004[16][1024],
1022b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			      unsigned char p8004[16][256])
1032b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
1042b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	int compression_mode, j, k, bit, pw;
1052b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned char *p0, *p8;
1062b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const unsigned int *r;
1072b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
1082b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	/* We have 16 compressions tables */
1092b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (compression_mode = 0; compression_mode < 16; compression_mode++) {
1102b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		p0 = p0004[compression_mode];
1112b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		p8 = p8004[compression_mode];
1122b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		r  = romtable[compression_mode];
1132b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
1142b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		for (j = 0; j < 8; j++, r++, p0 += 128) {
1152b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
1162b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			for (k = 0; k < 16; k++) {
1172b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				if (k == 0)
1182b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard					bit = 1;
1192b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				else if (k >= 1 && k < 3)
1202b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard					bit = (r[0] >> 15) & 7;
1212b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				else if (k >= 3 && k < 6)
1222b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard					bit = (r[0] >> 12) & 7;
1232b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				else if (k >= 6 && k < 10)
1242b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard					bit = (r[0] >> 9) & 7;
1252b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				else if (k >= 10 && k < 13)
1262b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard					bit = (r[0] >> 6) & 7;
1272b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				else if (k >= 13 && k < 15)
1282b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard					bit = (r[0] >> 3) & 7;
1292b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				else
1302b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard					bit = (r[0]) & 7;
1312b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				if (k == 0)
1322b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard					*p8++ = 8;
1332b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				else
1342b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard					*p8++ = j - bit;
1352b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				*p8++ = bit;
1362b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
1372b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				pw = 1 << bit;
1382b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				p0[k + 0x00] = (1 * pw) + 0x80;
1392b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				p0[k + 0x10] = (2 * pw) + 0x80;
1402b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				p0[k + 0x20] = (3 * pw) + 0x80;
1412b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				p0[k + 0x30] = (4 * pw) + 0x80;
1422b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				p0[k + 0x40] = (-1 * pw) + 0x80;
1432b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				p0[k + 0x50] = (-2 * pw) + 0x80;
1442b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				p0[k + 0x60] = (-3 * pw) + 0x80;
1452b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				p0[k + 0x70] = (-4 * pw) + 0x80;
1462b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			}	/* end of for (k=0; k<16; k++, p8++) */
1472b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		}	/* end of for (j=0; j<8; j++ , table++) */
1482b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	} /* end of foreach compression_mode */
1492b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
1502b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
1512b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/*
1522b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *
1532b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
1542b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
1552b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
1562b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define SCALEBITS 15
1572b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define ONE_HALF  (1UL << (SCALEBITS - 1))
1582b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	int i;
1592b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned int offset1 = ONE_HALF;
1602b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned int offset2 = 0x0000;
1612b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
1622b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i=0; i<256; i++) {
1632b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
1642b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		pdec->table_d800[i] = offset2;
1652b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
1662b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		offset1 += 0x7bc4;
1672b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		offset2 += 0x7bc4;
1682b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
1692b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
1702b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
1712b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/*
1722b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * To decode the stream:
1732b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   if look_bits(2) == 0:	# op == 2 in the lookup table
1742b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *      skip_bits(2)
1752b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *      end of the stream
1762b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   elif look_bits(3) == 7:	# op == 1 in the lookup table
1772b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *      skip_bits(3)
1782b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *      yyyy = get_bits(4)
1792b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *      xxxx = get_bits(8)
1802b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   else:			# op == 0 in the lookup table
1812b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *      skip_bits(x)
1822b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *
1832b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * For speedup processing, we build a lookup table and we takes the first 6 bits.
1842b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *
1852b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * struct {
1862b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   unsigned char op;	    // operation to execute
1872b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   unsigned char bits;    // bits use to perform operation
1882b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   unsigned char offset1; // offset to add to access in the table_0004 % 16
1892b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   unsigned char offset2; // offset to add to access in the table_0004
1902b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * }
1912b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *
1922b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * How to build this table ?
1932b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   op == 2 when (i%4)==0
1942b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   op == 1 when (i%8)==7
1952b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *   op == 0 otherwise
1962b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *
1972b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
1982b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic const unsigned char hash_table_ops[64*4] = {
1992b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2002b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x00,
2012b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x04, 0x01, 0x10,
2022b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x06, 0x01, 0x30,
2032b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2042b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x40,
2052b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x01, 0x20,
2062b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x01, 0x00, 0x00, 0x00,
2072b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2082b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x00,
2092b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x04, 0x01, 0x50,
2102b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x02, 0x00,
2112b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2122b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x40,
2132b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x03, 0x00,
2142b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x01, 0x00, 0x00, 0x00,
2152b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2162b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x00,
2172b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x04, 0x01, 0x10,
2182b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x06, 0x02, 0x10,
2192b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2202b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x40,
2212b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x01, 0x60,
2222b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x01, 0x00, 0x00, 0x00,
2232b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2242b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x00,
2252b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x04, 0x01, 0x50,
2262b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x02, 0x40,
2272b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2282b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x40,
2292b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x03, 0x40,
2302b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x01, 0x00, 0x00, 0x00,
2312b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2322b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x00,
2332b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x04, 0x01, 0x10,
2342b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x06, 0x01, 0x70,
2352b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2362b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x40,
2372b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x01, 0x20,
2382b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x01, 0x00, 0x00, 0x00,
2392b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2402b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x00,
2412b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x04, 0x01, 0x50,
2422b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x02, 0x00,
2432b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2442b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x40,
2452b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x03, 0x00,
2462b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x01, 0x00, 0x00, 0x00,
2472b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2482b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x00,
2492b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x04, 0x01, 0x10,
2502b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x06, 0x02, 0x50,
2512b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2522b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x40,
2532b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x01, 0x60,
2542b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x01, 0x00, 0x00, 0x00,
2552b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2562b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x00,
2572b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x04, 0x01, 0x50,
2582b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x02, 0x40,
2592b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x02, 0x00, 0x00, 0x00,
2602b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x03, 0x01, 0x40,
2612b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x00, 0x05, 0x03, 0x40,
2622b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	0x01, 0x00, 0x00, 0x00
2632b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard};
2642b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
2652b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/*
2662b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *
2672b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
2682b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic const unsigned int MulIdx[16][16] = {
2692b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
2702b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
2712b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
2722b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
2732b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
2742b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
2752b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
2762b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
2772b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
2782b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
2792b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
2802b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
2812b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
2822b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
2832b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
2842b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
2852b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard};
2862b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
2872b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#if USE_LOOKUP_TABLE_TO_CLAMP
2882b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define MAX_OUTER_CROP_VALUE	(512)
2892b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
2902b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
2912b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#else
2922b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
2932b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#endif
2942b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
2952b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
2962b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/* If the type or the command change, we rebuild the lookup table */
29724be689bfbbcd6c047d7918784ff810e97648006Hans de Goedevoid pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
2982b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
2992b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	int flags, version, shift, i;
30056ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede	struct pwc_dec23_private *pdec = &pdev->dec23;
3012b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
302c20d78cde37018caa0313469c9320424995cc489Hans de Goede	mutex_init(&pdec->lock);
303c20d78cde37018caa0313469c9320424995cc489Hans de Goede
3041c852201a28601b1379857f615e99071211294c6Hans de Goede	if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
3051c852201a28601b1379857f615e99071211294c6Hans de Goede		return;
3061c852201a28601b1379857f615e99071211294c6Hans de Goede
30756ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede	if (DEVICE_USE_CODEC3(pdev->type)) {
3082b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		flags = cmd[2] & 0x18;
3092b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		if (flags == 8)
3102b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			pdec->nbits = 7;	/* More bits, mean more bits to encode the stream, but better quality */
3112b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		else if (flags == 0x10)
3122b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			pdec->nbits = 8;
3132b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		else
3142b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			pdec->nbits = 6;
3152b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3162b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		version = cmd[2] >> 5;
3172b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
3182b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
3192b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3202b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	} else {
3212b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3222b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		flags = cmd[2] & 6;
3232b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		if (flags == 2)
3242b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			pdec->nbits = 7;
3252b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		else if (flags == 4)
3262b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			pdec->nbits = 8;
3272b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		else
3282b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			pdec->nbits = 6;
3292b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3302b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		version = cmd[2] >> 3;
3312b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
3322b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
3332b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
3342b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3352b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	/* Informations can be coded on a variable number of bits but never less than 8 */
3362b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	shift = 8 - pdec->nbits;
3372b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	pdec->scalebits = SCALEBITS - shift;
3382b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	pdec->nbitsmask = 0xFF >> shift;
3392b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3402b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	fill_table_dc00_d800(pdec);
3412b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	build_subblock_pattern(pdec);
3422b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	build_bit_powermask_table(pdec);
3432b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3442b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#if USE_LOOKUP_TABLE_TO_CLAMP
3452b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	/* Build the static table to clamp value [0-255] */
3462b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i=0;i<MAX_OUTER_CROP_VALUE;i++)
3472b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		pwc_crop_table[i] = 0;
3482b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i=0; i<256; i++)
3492b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
3502b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i=0; i<MAX_OUTER_CROP_VALUE; i++)
3512b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
3522b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#endif
3531c852201a28601b1379857f615e99071211294c6Hans de Goede
3541c852201a28601b1379857f615e99071211294c6Hans de Goede	pdec->last_cmd = cmd[2];
3551c852201a28601b1379857f615e99071211294c6Hans de Goede	pdec->last_cmd_valid = 1;
3562b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
3572b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3582b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/*
3592b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * Copy the 4x4 image block to Y plane buffer
3602b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
3612b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
3622b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
3632b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#if UNROLL_LOOP_FOR_COPY
3642b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
3652b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const int *c = src;
3662b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned char *d = dst;
3672b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3682b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[0] >> scalebits];
3692b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[1] >> scalebits];
3702b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[2] >> scalebits];
3712b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[3] >> scalebits];
3722b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3732b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	d = dst + bytes_per_line;
3742b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[4] >> scalebits];
3752b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[5] >> scalebits];
3762b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[6] >> scalebits];
3772b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[7] >> scalebits];
3782b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3792b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	d = dst + bytes_per_line*2;
3802b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[8] >> scalebits];
3812b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[9] >> scalebits];
3822b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[10] >> scalebits];
3832b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[11] >> scalebits];
3842b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3852b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	d = dst + bytes_per_line*3;
3862b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[12] >> scalebits];
3872b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[13] >> scalebits];
3882b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[14] >> scalebits];
3892b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[15] >> scalebits];
3902b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#else
3912b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	int i;
3922b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const int *c = src;
3932b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned char *d = dst;
3942b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i = 0; i < 4; i++, c++)
3952b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		*d++ = CLAMP((*c) >> scalebits);
3962b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
3972b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	d = dst + bytes_per_line;
3982b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i = 0; i < 4; i++, c++)
3992b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		*d++ = CLAMP((*c) >> scalebits);
4002b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4012b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	d = dst + bytes_per_line*2;
4022b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i = 0; i < 4; i++, c++)
4032b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		*d++ = CLAMP((*c) >> scalebits);
4042b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4052b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	d = dst + bytes_per_line*3;
4062b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i = 0; i < 4; i++, c++)
4072b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		*d++ = CLAMP((*c) >> scalebits);
4082b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#endif
4092b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
4102b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4112b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/*
4122b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * Copy the 4x4 image block to a CrCb plane buffer
4132b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *
4142b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
4152b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
4162b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
4172b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#if UNROLL_LOOP_FOR_COPY
4182b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	/* Unroll all loops */
4192b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
4202b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const int *c = src;
4212b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned char *d = dst;
4222b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4232b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[0] >> scalebits];
4242b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[4] >> scalebits];
4252b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[1] >> scalebits];
4262b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[5] >> scalebits];
4272b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[2] >> scalebits];
4282b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[6] >> scalebits];
4292b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[3] >> scalebits];
4302b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[7] >> scalebits];
4312b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4322b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	d = dst + bytes_per_line;
4332b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[12] >> scalebits];
4342b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[8] >> scalebits];
4352b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[13] >> scalebits];
4362b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[9] >> scalebits];
4372b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[14] >> scalebits];
4382b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[10] >> scalebits];
4392b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[15] >> scalebits];
4402b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	*d++ = cm[c[11] >> scalebits];
4412b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#else
4422b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	int i;
4432b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const int *c1 = src;
4442b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const int *c2 = src + 4;
4452b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned char *d = dst;
4462b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4472b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i = 0; i < 4; i++, c1++, c2++) {
4482b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		*d++ = CLAMP((*c1) >> scalebits);
4492b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		*d++ = CLAMP((*c2) >> scalebits);
4502b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
4512b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	c1 = src + 12;
4522b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	d = dst + bytes_per_line;
4532b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i = 0; i < 4; i++, c1++, c2++) {
4542b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		*d++ = CLAMP((*c1) >> scalebits);
4552b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		*d++ = CLAMP((*c2) >> scalebits);
4562b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
4572b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#endif
4582b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
4592b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4602b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/*
4612b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * To manage the stream, we keep bits in a 32 bits register.
4622b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * fill_nbits(n): fill the reservoir with at least n bits
4632b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * skip_bits(n): discard n bits from the reservoir
4642b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * get_bits(n): fill the reservoir, returns the first n bits and discard the
4652b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *              bits from the reservoir.
4662b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
4672b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *                 contains at least n bits. bits returned is discarded.
4682b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
4692b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define fill_nbits(pdec, nbits_wanted) do { \
4702b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   while (pdec->nbits_in_reservoir<(nbits_wanted)) \
4712b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard    { \
4722b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard      pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
4732b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard      pdec->nbits_in_reservoir += 8; \
4742b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard    } \
4752b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}  while(0);
4762b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4772b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define skip_nbits(pdec, nbits_to_skip) do { \
4782b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   pdec->reservoir >>= (nbits_to_skip); \
4792b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   pdec->nbits_in_reservoir -= (nbits_to_skip); \
4802b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}  while(0);
4812b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4822b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define get_nbits(pdec, nbits_wanted, result) do { \
4832b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   fill_nbits(pdec, nbits_wanted); \
4842b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
4852b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   skip_nbits(pdec, nbits_wanted); \
4862b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}  while(0);
4872b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4882b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define __get_nbits(pdec, nbits_wanted, result) do { \
4892b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
4902b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   skip_nbits(pdec, nbits_wanted); \
4912b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}  while(0);
4922b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4932b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define look_nbits(pdec, nbits_wanted) \
4942b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard   ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
4952b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
4962b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/*
4972b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * Decode a 4x4 pixel block
4982b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
4992b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic void decode_block(struct pwc_dec23_private *pdec,
5002b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			 const unsigned char *ptable0004,
5012b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			 const unsigned char *ptable8004)
5022b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
5032b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned int primary_color;
5042b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	unsigned int channel_v, offset1, op;
5052b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	int i;
5062b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5072b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	fill_nbits(pdec, 16);
5082b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	__get_nbits(pdec, pdec->nbits, primary_color);
5092b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5102b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	if (look_nbits(pdec,2) == 0) {
5112b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		skip_nbits(pdec, 2);
5122b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		/* Very simple, the color is the same for all pixels of the square */
5132b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		for (i = 0; i < 16; i++)
5142b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			pdec->temp_colors[i] = pdec->table_dc00[primary_color];
5152b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5162b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		return;
5172b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
5182b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5192b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	/* This block is encoded with small pattern */
5202b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	for (i = 0; i < 16; i++)
5212b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		pdec->temp_colors[i] = pdec->table_d800[primary_color];
5222b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5232b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	__get_nbits(pdec, 3, channel_v);
5242b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);
5252b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5262b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	ptable0004 += (channel_v * 128);
5272b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	ptable8004 += (channel_v * 32);
5282b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5292b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	offset1 = 0;
5302b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	do
5312b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	{
5322b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		unsigned int htable_idx, rows = 0;
5332b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		const unsigned int *block;
5342b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5352b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		/* [  zzzz y x x ]
5362b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		 *     xx == 00 :=> end of the block def, remove the two bits from the stream
5372b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		 *    yxx == 111
5382b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		 *    yxx == any other value
5392b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		 *
5402b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		 */
5412b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		fill_nbits(pdec, 16);
5422b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		htable_idx = look_nbits(pdec, 6);
5432b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		op = hash_table_ops[htable_idx * 4];
5442b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5452b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		if (op == 2) {
5462b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			skip_nbits(pdec, 2);
5472b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5482b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		} else if (op == 1) {
5492b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			/* 15bits [ xxxx xxxx yyyy 111 ]
5502b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			 * yyy => offset in the table8004
5512b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			 * xxx => offset in the tabled004 (tree)
5522b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			 */
5532b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			unsigned int mask, shift;
5542b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			unsigned int nbits, col1;
5552b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			unsigned int yyyy;
5562b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5572b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			skip_nbits(pdec, 3);
5582b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			/* offset1 += yyyy */
5592b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			__get_nbits(pdec, 4, yyyy);
5602b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			offset1 += 1 + yyyy;
5612b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			offset1 &= 0x0F;
5622b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			nbits = ptable8004[offset1 * 2];
5632b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5642b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			/* col1 = xxxx xxxx */
5652b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			__get_nbits(pdec, nbits+1, col1);
5662b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5672b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			/* Bit mask table */
5682b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			mask = pdec->table_bitpowermask[nbits][col1];
5692b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			shift = ptable8004[offset1 * 2 + 1];
5702b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			rows = ((mask << shift) + 0x80) & 0xFF;
5712b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5722b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			block = pdec->table_subblock[rows];
5732b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			for (i = 0; i < 16; i++)
5742b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				pdec->temp_colors[i] += block[MulIdx[offset1][i]];
5752b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5762b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		} else {
5772b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			/* op == 0
5782b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			 * offset1 is coded on 3 bits
5792b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			 */
5802b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			unsigned int shift;
5812b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5822b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			offset1 += hash_table_ops [htable_idx * 4 + 2];
5832b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			offset1 &= 0x0F;
5842b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5852b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]];
5862b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			block = pdec->table_subblock[rows];
5872b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			for (i = 0; i < 16; i++)
5882b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard				pdec->temp_colors[i] += block[MulIdx[offset1][i]];
5892b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5902b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			shift = hash_table_ops[htable_idx * 4 + 1];
5912b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			skip_nbits(pdec, shift);
5922b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		}
5932b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5942b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	} while (op != 2);
5952b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5962b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
5972b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
5982b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillardstatic void DecompressBand23(struct pwc_dec23_private *pdec,
5992b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			     const unsigned char *rawyuv,
6002b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			     unsigned char *planar_y,
6012b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			     unsigned char *planar_u,
6022b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			     unsigned char *planar_v,
6032b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			     unsigned int   compressed_image_width,
6042b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			     unsigned int   real_image_width)
6052b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
6062b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	int compression_index, nblocks;
6072b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const unsigned char *ptable0004;
6082b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	const unsigned char *ptable8004;
6092b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6102b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	pdec->reservoir = 0;
6112b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	pdec->nbits_in_reservoir = 0;
6122b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	pdec->stream = rawyuv + 1;	/* The first byte of the stream is skipped */
6132b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6142b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	get_nbits(pdec, 4, compression_index);
6152b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6162b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	/* pass 1: uncompress Y component */
6172b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	nblocks = compressed_image_width / 4;
6182b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6192b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	ptable0004 = pdec->table_0004_pass1[compression_index];
6202b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	ptable8004 = pdec->table_8004_pass1[compression_index];
6212b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6222b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	/* Each block decode a square of 4x4 */
6232b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	while (nblocks) {
6242b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		decode_block(pdec, ptable0004, ptable8004);
6252b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
6262b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		planar_y += 4;
6272b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		nblocks--;
6282b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
6292b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6302b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	/* pass 2: uncompress UV component */
6312b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	nblocks = compressed_image_width / 8;
6322b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6332b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	ptable0004 = pdec->table_0004_pass2[compression_index];
6342b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	ptable8004 = pdec->table_8004_pass2[compression_index];
6352b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6362b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	/* Each block decode a square of 4x4 */
6372b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	while (nblocks) {
6382b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		decode_block(pdec, ptable0004, ptable8004);
6392b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);
6402b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6412b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		decode_block(pdec, ptable0004, ptable8004);
6422b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);
6432b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6442b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		planar_v += 8;
6452b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		planar_u += 8;
6462b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard		nblocks -= 2;
6472b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
6482b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6492b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
6502b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
6512b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard/**
6522b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *
6532b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * Uncompress a pwc23 buffer.
6542b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard *
6552b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * src: raw data
6562b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard * dst: image output
6572b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard */
65856ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goedevoid pwc_dec23_decompress(struct pwc_device *pdev,
6592b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard			  const void *src,
660dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede			  void *dst)
6612b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard{
662795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede	int bandlines_left, bytes_per_block;
66356ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede	struct pwc_dec23_private *pdec = &pdev->dec23;
664c20d78cde37018caa0313469c9320424995cc489Hans de Goede
665dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede	/* YUV420P image format */
666dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede	unsigned char *pout_planar_y;
667dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede	unsigned char *pout_planar_u;
668dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede	unsigned char *pout_planar_v;
669dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede	unsigned int   plane_size;
670dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede
671c20d78cde37018caa0313469c9320424995cc489Hans de Goede	mutex_lock(&pdec->lock);
6722b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard
67356ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede	bandlines_left = pdev->height / 4;
67456ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede	bytes_per_block = pdev->width * 4;
67556ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede	plane_size = pdev->height * pdev->width;
676dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede
677795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede	pout_planar_y = dst;
678795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede	pout_planar_u = dst + plane_size;
679795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede	pout_planar_v = dst + plane_size + plane_size / 4;
680dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede
681dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede	while (bandlines_left--) {
68256ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede		DecompressBand23(pdec, src,
683dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede				 pout_planar_y, pout_planar_u, pout_planar_v,
68456ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede				 pdev->width, pdev->width);
68556ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede		src += pdev->vbandlength;
686dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede		pout_planar_y += bytes_per_block;
68756ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede		pout_planar_u += pdev->width;
68856ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede		pout_planar_v += pdev->width;
6892b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard	}
690c20d78cde37018caa0313469c9320424995cc489Hans de Goede	mutex_unlock(&pdec->lock);
6912b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard}
692