| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Zoran ZR36050 basic configuration functions | 
 | 3 |  * | 
 | 4 |  * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at> | 
 | 5 |  * | 
 | 6 |  * $Id: zr36050.c,v 1.1.2.11 2003/08/03 14:54:53 rbultje Exp $ | 
 | 7 |  * | 
 | 8 |  * ------------------------------------------------------------------------ | 
 | 9 |  * | 
 | 10 |  * This program is free software; you can redistribute it and/or modify | 
 | 11 |  * it under the terms of the GNU General Public License as published by | 
 | 12 |  * the Free Software Foundation; either version 2 of the License, or | 
 | 13 |  * (at your option) any later version. | 
 | 14 |  * | 
 | 15 |  * This program is distributed in the hope that it will be useful, | 
 | 16 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 17 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 | 18 |  * GNU General Public License for more details. | 
 | 19 |  * | 
 | 20 |  * You should have received a copy of the GNU General Public License | 
 | 21 |  * along with this program; if not, write to the Free Software | 
 | 22 |  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
 | 23 |  * | 
 | 24 |  * ------------------------------------------------------------------------ | 
 | 25 |  */ | 
 | 26 |  | 
 | 27 | #define ZR050_VERSION "v0.7.1" | 
 | 28 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 29 | #include <linux/module.h> | 
 | 30 | #include <linux/init.h> | 
 | 31 | #include <linux/slab.h> | 
 | 32 | #include <linux/delay.h> | 
 | 33 |  | 
 | 34 | #include <linux/types.h> | 
 | 35 | #include <linux/wait.h> | 
 | 36 |  | 
 | 37 | /* includes for structures and defines regarding video  | 
 | 38 |    #include<linux/videodev.h> */ | 
 | 39 |  | 
 | 40 | /* I/O commands, error codes */ | 
 | 41 | #include<asm/io.h> | 
 | 42 | //#include<errno.h> | 
 | 43 |  | 
 | 44 | /* headerfile of this module */ | 
 | 45 | #include"zr36050.h" | 
 | 46 |  | 
 | 47 | /* codec io API */ | 
 | 48 | #include"videocodec.h" | 
 | 49 |  | 
 | 50 | /* it doesn't make sense to have more than 20 or so, | 
 | 51 |   just to prevent some unwanted loops */ | 
 | 52 | #define MAX_CODECS 20 | 
 | 53 |  | 
 | 54 | /* amount of chips attached via this driver */ | 
 | 55 | static int zr36050_codecs = 0; | 
 | 56 |  | 
 | 57 | /* debugging is available via module parameter */ | 
 | 58 |  | 
 | 59 | static int debug = 0; | 
 | 60 | module_param(debug, int, 0); | 
 | 61 | MODULE_PARM_DESC(debug, "Debug level (0-4)"); | 
 | 62 |  | 
 | 63 | #define dprintk(num, format, args...) \ | 
 | 64 | 	do { \ | 
 | 65 | 		if (debug >= num) \ | 
 | 66 | 			printk(format, ##args); \ | 
 | 67 | 	} while (0) | 
 | 68 |  | 
 | 69 | /* ========================================================================= | 
 | 70 |    Local hardware I/O functions: | 
 | 71 |  | 
 | 72 |    read/write via codec layer (registers are located in the master device) | 
 | 73 |    ========================================================================= */ | 
 | 74 |  | 
 | 75 | /* read and write functions */ | 
 | 76 | static u8 | 
 | 77 | zr36050_read (struct zr36050 *ptr, | 
 | 78 | 	      u16             reg) | 
 | 79 | { | 
 | 80 | 	u8 value = 0; | 
 | 81 |  | 
 | 82 | 	// just in case something is wrong... | 
 | 83 | 	if (ptr->codec->master_data->readreg) | 
 | 84 | 		value = (ptr->codec->master_data->readreg(ptr->codec, | 
 | 85 | 							  reg)) & 0xFF; | 
 | 86 | 	else | 
 | 87 | 		dprintk(1, | 
 | 88 | 			KERN_ERR "%s: invalid I/O setup, nothing read!\n", | 
 | 89 | 			ptr->name); | 
 | 90 |  | 
 | 91 | 	dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg, | 
 | 92 | 		value); | 
 | 93 |  | 
 | 94 | 	return value; | 
 | 95 | } | 
 | 96 |  | 
 | 97 | static void | 
 | 98 | zr36050_write (struct zr36050 *ptr, | 
 | 99 | 	       u16             reg, | 
 | 100 | 	       u8              value) | 
 | 101 | { | 
 | 102 | 	dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value, | 
 | 103 | 		reg); | 
 | 104 |  | 
 | 105 | 	// just in case something is wrong... | 
 | 106 | 	if (ptr->codec->master_data->writereg) | 
 | 107 | 		ptr->codec->master_data->writereg(ptr->codec, reg, value); | 
 | 108 | 	else | 
 | 109 | 		dprintk(1, | 
 | 110 | 			KERN_ERR | 
 | 111 | 			"%s: invalid I/O setup, nothing written!\n", | 
 | 112 | 			ptr->name); | 
 | 113 | } | 
 | 114 |  | 
 | 115 | /* ========================================================================= | 
 | 116 |    Local helper function: | 
 | 117 |  | 
 | 118 |    status read | 
 | 119 |    ========================================================================= */ | 
 | 120 |  | 
 | 121 | /* status is kept in datastructure */ | 
 | 122 | static u8 | 
 | 123 | zr36050_read_status1 (struct zr36050 *ptr) | 
 | 124 | { | 
 | 125 | 	ptr->status1 = zr36050_read(ptr, ZR050_STATUS_1); | 
 | 126 |  | 
 | 127 | 	zr36050_read(ptr, 0); | 
 | 128 | 	return ptr->status1; | 
 | 129 | } | 
 | 130 |  | 
 | 131 | /* ========================================================================= | 
 | 132 |    Local helper function: | 
 | 133 |  | 
 | 134 |    scale factor read | 
 | 135 |    ========================================================================= */ | 
 | 136 |  | 
 | 137 | /* scale factor is kept in datastructure */ | 
 | 138 | static u16 | 
 | 139 | zr36050_read_scalefactor (struct zr36050 *ptr) | 
 | 140 | { | 
 | 141 | 	ptr->scalefact = (zr36050_read(ptr, ZR050_SF_HI) << 8) | | 
 | 142 | 			 (zr36050_read(ptr, ZR050_SF_LO) & 0xFF); | 
 | 143 |  | 
 | 144 | 	/* leave 0 selected for an eventually GO from master */ | 
 | 145 | 	zr36050_read(ptr, 0); | 
 | 146 | 	return ptr->scalefact; | 
 | 147 | } | 
 | 148 |  | 
 | 149 | /* ========================================================================= | 
 | 150 |    Local helper function: | 
 | 151 |  | 
 | 152 |    wait if codec is ready to proceed (end of processing) or time is over | 
 | 153 |    ========================================================================= */ | 
 | 154 |  | 
 | 155 | static void | 
 | 156 | zr36050_wait_end (struct zr36050 *ptr) | 
 | 157 | { | 
 | 158 | 	int i = 0; | 
 | 159 |  | 
 | 160 | 	while (!(zr36050_read_status1(ptr) & 0x4)) { | 
 | 161 | 		udelay(1); | 
 | 162 | 		if (i++ > 200000) {	// 200ms, there is for shure something wrong!!! | 
 | 163 | 			dprintk(1, | 
 | 164 | 				"%s: timout at wait_end (last status: 0x%02x)\n", | 
 | 165 | 				ptr->name, ptr->status1); | 
 | 166 | 			break; | 
 | 167 | 		} | 
 | 168 | 	} | 
 | 169 | } | 
 | 170 |  | 
 | 171 | /* ========================================================================= | 
 | 172 |    Local helper function: | 
 | 173 |  | 
 | 174 |    basic test of "connectivity", writes/reads to/from memory the SOF marker  | 
 | 175 |    ========================================================================= */ | 
 | 176 |  | 
 | 177 | static int | 
 | 178 | zr36050_basic_test (struct zr36050 *ptr) | 
 | 179 | { | 
 | 180 | 	zr36050_write(ptr, ZR050_SOF_IDX, 0x00); | 
 | 181 | 	zr36050_write(ptr, ZR050_SOF_IDX + 1, 0x00); | 
 | 182 | 	if ((zr36050_read(ptr, ZR050_SOF_IDX) | | 
 | 183 | 	     zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0x0000) { | 
 | 184 | 		dprintk(1, | 
 | 185 | 			KERN_ERR | 
 | 186 | 			"%s: attach failed, can't connect to jpeg processor!\n", | 
 | 187 | 			ptr->name); | 
 | 188 | 		return -ENXIO; | 
 | 189 | 	} | 
 | 190 | 	zr36050_write(ptr, ZR050_SOF_IDX, 0xff); | 
 | 191 | 	zr36050_write(ptr, ZR050_SOF_IDX + 1, 0xc0); | 
 | 192 | 	if (((zr36050_read(ptr, ZR050_SOF_IDX) << 8) | | 
 | 193 | 	     zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0xffc0) { | 
 | 194 | 		dprintk(1, | 
 | 195 | 			KERN_ERR | 
 | 196 | 			"%s: attach failed, can't connect to jpeg processor!\n", | 
 | 197 | 			ptr->name); | 
 | 198 | 		return -ENXIO; | 
 | 199 | 	} | 
 | 200 |  | 
 | 201 | 	zr36050_wait_end(ptr); | 
 | 202 | 	if ((ptr->status1 & 0x4) == 0) { | 
 | 203 | 		dprintk(1, | 
 | 204 | 			KERN_ERR | 
 | 205 | 			"%s: attach failed, jpeg processor failed (end flag)!\n", | 
 | 206 | 			ptr->name); | 
 | 207 | 		return -EBUSY; | 
 | 208 | 	} | 
 | 209 |  | 
 | 210 | 	return 0;		/* looks good! */ | 
 | 211 | } | 
 | 212 |  | 
 | 213 | /* ========================================================================= | 
 | 214 |    Local helper function: | 
 | 215 |  | 
 | 216 |    simple loop for pushing the init datasets | 
 | 217 |    ========================================================================= */ | 
 | 218 |  | 
 | 219 | static int | 
 | 220 | zr36050_pushit (struct zr36050 *ptr, | 
 | 221 | 	        u16             startreg, | 
 | 222 | 	        u16             len, | 
 | 223 | 	        const char     *data) | 
 | 224 | { | 
 | 225 | 	int i = 0; | 
 | 226 |  | 
 | 227 | 	dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name, | 
 | 228 | 		startreg, len); | 
 | 229 | 	while (i < len) { | 
 | 230 | 		zr36050_write(ptr, startreg++, data[i++]); | 
 | 231 | 	} | 
 | 232 |  | 
 | 233 | 	return i; | 
 | 234 | } | 
 | 235 |  | 
 | 236 | /* ========================================================================= | 
 | 237 |    Basic datasets: | 
 | 238 |  | 
 | 239 |    jpeg baseline setup data (you find it on lots places in internet, or just | 
 | 240 |    extract it from any regular .jpg image...) | 
 | 241 |  | 
 | 242 |    Could be variable, but until it's not needed it they are just fixed to save | 
 | 243 |    memory. Otherwise expand zr36050 structure with arrays, push the values to | 
 | 244 |    it and initalize from there, as e.g. the linux zr36057/60 driver does it. | 
 | 245 |    ========================================================================= */ | 
 | 246 |  | 
 | 247 | static const char zr36050_dqt[0x86] = { | 
 | 248 | 	0xff, 0xdb,		//Marker: DQT | 
 | 249 | 	0x00, 0x84,		//Length: 2*65+2 | 
 | 250 | 	0x00,			//Pq,Tq first table | 
 | 251 | 	0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, | 
 | 252 | 	0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, | 
 | 253 | 	0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, | 
 | 254 | 	0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, | 
 | 255 | 	0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44, | 
 | 256 | 	0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, | 
 | 257 | 	0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, | 
 | 258 | 	0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, | 
 | 259 | 	0x01,			//Pq,Tq second table | 
 | 260 | 	0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, | 
 | 261 | 	0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, | 
 | 262 | 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | 
 | 263 | 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | 
 | 264 | 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | 
 | 265 | 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | 
 | 266 | 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | 
 | 267 | 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 | 
 | 268 | }; | 
 | 269 |  | 
 | 270 | static const char zr36050_dht[0x1a4] = { | 
 | 271 | 	0xff, 0xc4,		//Marker: DHT | 
 | 272 | 	0x01, 0xa2,		//Length: 2*AC, 2*DC | 
 | 273 | 	0x00,			//DC first table | 
 | 274 | 	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, | 
 | 275 | 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, | 
 | 276 | 	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, | 
 | 277 | 	0x01,			//DC second table | 
 | 278 | 	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | 
 | 279 | 	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, | 
 | 280 | 	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, | 
 | 281 | 	0x10,			//AC first table | 
 | 282 | 	0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, | 
 | 283 | 	0x05, 0x05, 0x04, 0x04, 0x00, 0x00, | 
 | 284 | 	0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, | 
 | 285 | 	0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, | 
 | 286 | 	0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, | 
 | 287 | 	0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, | 
 | 288 | 	0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, | 
 | 289 | 	0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, | 
 | 290 | 	0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, | 
 | 291 | 	0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, | 
 | 292 | 	0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, | 
 | 293 | 	0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, | 
 | 294 | 	0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, | 
 | 295 | 	0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, | 
 | 296 | 	0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, | 
 | 297 | 	0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, | 
 | 298 | 	0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, | 
 | 299 | 	0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, | 
 | 300 | 	0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, | 
 | 301 | 	0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, | 
 | 302 | 	0xF8, 0xF9, 0xFA, | 
 | 303 | 	0x11,			//AC second table | 
 | 304 | 	0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, | 
 | 305 | 	0x07, 0x05, 0x04, 0x04, 0x00, 0x01, | 
 | 306 | 	0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, | 
 | 307 | 	0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, | 
 | 308 | 	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, | 
 | 309 | 	0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, | 
 | 310 | 	0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, | 
 | 311 | 	0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, | 
 | 312 | 	0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, | 
 | 313 | 	0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, | 
 | 314 | 	0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, | 
 | 315 | 	0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, | 
 | 316 | 	0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, | 
 | 317 | 	0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, | 
 | 318 | 	0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, | 
 | 319 | 	0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, | 
 | 320 | 	0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, | 
 | 321 | 	0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, | 
 | 322 | 	0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, | 
 | 323 | 	0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, | 
 | 324 | 	0xF9, 0xFA | 
 | 325 | }; | 
 | 326 |  | 
 | 327 | /* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */ | 
 | 328 | #define NO_OF_COMPONENTS          0x3	//Y,U,V | 
 | 329 | #define BASELINE_PRECISION        0x8	//MCU size (?) | 
 | 330 | static const char zr36050_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };	//table idx's QT | 
 | 331 | static const char zr36050_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };	//table idx's DC | 
 | 332 | static const char zr36050_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };	//table idx's AC | 
 | 333 |  | 
 | 334 | /* horizontal 422 decimation setup (maybe we support 411 or so later, too) */ | 
 | 335 | static const char zr36050_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 }; | 
 | 336 | static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 }; | 
 | 337 |  | 
 | 338 | /* ========================================================================= | 
 | 339 |    Local helper functions: | 
 | 340 |  | 
 | 341 |    calculation and setup of parameter-dependent JPEG baseline segments | 
 | 342 |    (needed for compression only) | 
 | 343 |    ========================================================================= */ | 
 | 344 |  | 
 | 345 | /* ------------------------------------------------------------------------- */ | 
 | 346 |  | 
 | 347 | /* SOF (start of frame) segment depends on width, height and sampling ratio | 
 | 348 |                          of each color component */ | 
 | 349 |  | 
 | 350 | static int | 
 | 351 | zr36050_set_sof (struct zr36050 *ptr) | 
 | 352 | { | 
 | 353 | 	char sof_data[34];	// max. size of register set | 
 | 354 | 	int i; | 
 | 355 |  | 
 | 356 | 	dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name, | 
 | 357 | 		ptr->width, ptr->height, NO_OF_COMPONENTS); | 
 | 358 | 	sof_data[0] = 0xff; | 
 | 359 | 	sof_data[1] = 0xc0; | 
 | 360 | 	sof_data[2] = 0x00; | 
 | 361 | 	sof_data[3] = (3 * NO_OF_COMPONENTS) + 8; | 
 | 362 | 	sof_data[4] = BASELINE_PRECISION;	// only '8' possible with zr36050 | 
 | 363 | 	sof_data[5] = (ptr->height) >> 8; | 
 | 364 | 	sof_data[6] = (ptr->height) & 0xff; | 
 | 365 | 	sof_data[7] = (ptr->width) >> 8; | 
 | 366 | 	sof_data[8] = (ptr->width) & 0xff; | 
 | 367 | 	sof_data[9] = NO_OF_COMPONENTS; | 
 | 368 | 	for (i = 0; i < NO_OF_COMPONENTS; i++) { | 
 | 369 | 		sof_data[10 + (i * 3)] = i;	// index identifier | 
 | 370 | 		sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) | (ptr->v_samp_ratio[i]);	// sampling ratios | 
 | 371 | 		sof_data[12 + (i * 3)] = zr36050_tq[i];	// Q table selection | 
 | 372 | 	} | 
 | 373 | 	return zr36050_pushit(ptr, ZR050_SOF_IDX, | 
 | 374 | 			      (3 * NO_OF_COMPONENTS) + 10, sof_data); | 
 | 375 | } | 
 | 376 |  | 
 | 377 | /* ------------------------------------------------------------------------- */ | 
 | 378 |  | 
 | 379 | /* SOS (start of scan) segment depends on the used scan components  | 
 | 380 |                         of each color component */ | 
 | 381 |  | 
 | 382 | static int | 
 | 383 | zr36050_set_sos (struct zr36050 *ptr) | 
 | 384 | { | 
 | 385 | 	char sos_data[16];	// max. size of register set | 
 | 386 | 	int i; | 
 | 387 |  | 
 | 388 | 	dprintk(3, "%s: write SOS\n", ptr->name); | 
 | 389 | 	sos_data[0] = 0xff; | 
 | 390 | 	sos_data[1] = 0xda; | 
 | 391 | 	sos_data[2] = 0x00; | 
 | 392 | 	sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3; | 
 | 393 | 	sos_data[4] = NO_OF_COMPONENTS; | 
 | 394 | 	for (i = 0; i < NO_OF_COMPONENTS; i++) { | 
 | 395 | 		sos_data[5 + (i * 2)] = i;	// index | 
 | 396 | 		sos_data[6 + (i * 2)] = (zr36050_td[i] << 4) | zr36050_ta[i];	// AC/DC tbl.sel. | 
 | 397 | 	} | 
 | 398 | 	sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;	// scan start | 
 | 399 | 	sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3F; | 
 | 400 | 	sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00; | 
 | 401 | 	return zr36050_pushit(ptr, ZR050_SOS1_IDX, | 
 | 402 | 			      4 + 1 + (2 * NO_OF_COMPONENTS) + 3, | 
 | 403 | 			      sos_data); | 
 | 404 | } | 
 | 405 |  | 
 | 406 | /* ------------------------------------------------------------------------- */ | 
 | 407 |  | 
 | 408 | /* DRI (define restart interval) */ | 
 | 409 |  | 
 | 410 | static int | 
 | 411 | zr36050_set_dri (struct zr36050 *ptr) | 
 | 412 | { | 
 | 413 | 	char dri_data[6];	// max. size of register set | 
 | 414 |  | 
 | 415 | 	dprintk(3, "%s: write DRI\n", ptr->name); | 
 | 416 | 	dri_data[0] = 0xff; | 
 | 417 | 	dri_data[1] = 0xdd; | 
 | 418 | 	dri_data[2] = 0x00; | 
 | 419 | 	dri_data[3] = 0x04; | 
 | 420 | 	dri_data[4] = ptr->dri >> 8; | 
 | 421 | 	dri_data[5] = ptr->dri & 0xff; | 
 | 422 | 	return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data); | 
 | 423 | } | 
 | 424 |  | 
 | 425 | /* ========================================================================= | 
 | 426 |    Setup function: | 
 | 427 |  | 
 | 428 |    Setup compression/decompression of Zoran's JPEG processor | 
 | 429 |    ( see also zoran 36050 manual ) | 
 | 430 |  | 
 | 431 |    ... sorry for the spaghetti code ... | 
 | 432 |    ========================================================================= */ | 
 | 433 | static void | 
 | 434 | zr36050_init (struct zr36050 *ptr) | 
 | 435 | { | 
 | 436 | 	int sum = 0; | 
 | 437 | 	long bitcnt, tmp; | 
 | 438 |  | 
 | 439 | 	if (ptr->mode == CODEC_DO_COMPRESSION) { | 
 | 440 | 		dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name); | 
 | 441 |  | 
 | 442 | 		/* 050 communicates with 057 in master mode */ | 
 | 443 | 		zr36050_write(ptr, ZR050_HARDWARE, ZR050_HW_MSTR); | 
 | 444 |  | 
 | 445 | 		/* encoding table preload for compression */ | 
 | 446 | 		zr36050_write(ptr, ZR050_MODE, | 
 | 447 | 			      ZR050_MO_COMP | ZR050_MO_TLM); | 
 | 448 | 		zr36050_write(ptr, ZR050_OPTIONS, 0); | 
 | 449 |  | 
 | 450 | 		/* disable all IRQs */ | 
 | 451 | 		zr36050_write(ptr, ZR050_INT_REQ_0, 0); | 
 | 452 | 		zr36050_write(ptr, ZR050_INT_REQ_1, 3);	// low 2 bits always 1 | 
 | 453 |  | 
 | 454 | 		/* volume control settings */ | 
 | 455 | 		/*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/ | 
 | 456 | 		zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8); | 
 | 457 | 		zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff); | 
 | 458 |  | 
 | 459 | 		zr36050_write(ptr, ZR050_AF_HI, 0xff); | 
 | 460 | 		zr36050_write(ptr, ZR050_AF_M, 0xff); | 
 | 461 | 		zr36050_write(ptr, ZR050_AF_LO, 0xff); | 
 | 462 |  | 
 | 463 | 		/* setup the variable jpeg tables */ | 
 | 464 | 		sum += zr36050_set_sof(ptr); | 
 | 465 | 		sum += zr36050_set_sos(ptr); | 
 | 466 | 		sum += zr36050_set_dri(ptr); | 
 | 467 |  | 
 | 468 | 		/* setup the fixed jpeg tables - maybe variable, though - | 
 | 469 | 		 * (see table init section above) */ | 
 | 470 | 		dprintk(3, "%s: write DQT, DHT, APP\n", ptr->name); | 
 | 471 | 		sum += zr36050_pushit(ptr, ZR050_DQT_IDX, | 
 | 472 | 				      sizeof(zr36050_dqt), zr36050_dqt); | 
 | 473 | 		sum += zr36050_pushit(ptr, ZR050_DHT_IDX, | 
 | 474 | 				      sizeof(zr36050_dht), zr36050_dht); | 
 | 475 | 		zr36050_write(ptr, ZR050_APP_IDX, 0xff); | 
 | 476 | 		zr36050_write(ptr, ZR050_APP_IDX + 1, 0xe0 + ptr->app.appn); | 
 | 477 | 		zr36050_write(ptr, ZR050_APP_IDX + 2, 0x00); | 
 | 478 | 		zr36050_write(ptr, ZR050_APP_IDX + 3, ptr->app.len + 2); | 
 | 479 | 		sum += zr36050_pushit(ptr, ZR050_APP_IDX + 4, 60, | 
 | 480 | 				      ptr->app.data) + 4; | 
 | 481 | 		zr36050_write(ptr, ZR050_COM_IDX, 0xff); | 
 | 482 | 		zr36050_write(ptr, ZR050_COM_IDX + 1, 0xfe); | 
 | 483 | 		zr36050_write(ptr, ZR050_COM_IDX + 2, 0x00); | 
 | 484 | 		zr36050_write(ptr, ZR050_COM_IDX + 3, ptr->com.len + 2); | 
 | 485 | 		sum += zr36050_pushit(ptr, ZR050_COM_IDX + 4, 60, | 
 | 486 | 				      ptr->com.data) + 4; | 
 | 487 |  | 
 | 488 | 		/* do the internal huffman table preload */ | 
 | 489 | 		zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI); | 
 | 490 |  | 
 | 491 | 		zr36050_write(ptr, ZR050_GO, 1);	// launch codec | 
 | 492 | 		zr36050_wait_end(ptr); | 
 | 493 | 		dprintk(2, "%s: Status after table preload: 0x%02x\n", | 
 | 494 | 			ptr->name, ptr->status1); | 
 | 495 |  | 
 | 496 | 		if ((ptr->status1 & 0x4) == 0) { | 
 | 497 | 			dprintk(1, KERN_ERR "%s: init aborted!\n", | 
 | 498 | 				ptr->name); | 
 | 499 | 			return;	// something is wrong, its timed out!!!! | 
 | 500 | 		} | 
 | 501 |  | 
 | 502 | 		/* setup misc. data for compression (target code sizes) */ | 
 | 503 |  | 
 | 504 | 		/* size of compressed code to reach without header data */ | 
 | 505 | 		sum = ptr->real_code_vol - sum; | 
 | 506 | 		bitcnt = sum << 3;	/* need the size in bits */ | 
 | 507 |  | 
 | 508 | 		tmp = bitcnt >> 16; | 
 | 509 | 		dprintk(3, | 
 | 510 | 			"%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n", | 
 | 511 | 			ptr->name, sum, ptr->real_code_vol, bitcnt, tmp); | 
 | 512 | 		zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8); | 
 | 513 | 		zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff); | 
 | 514 | 		tmp = bitcnt & 0xffff; | 
 | 515 | 		zr36050_write(ptr, ZR050_TCV_NET_ML, tmp >> 8); | 
 | 516 | 		zr36050_write(ptr, ZR050_TCV_NET_LO, tmp & 0xff); | 
 | 517 |  | 
 | 518 | 		bitcnt -= bitcnt >> 7;	// bits without stuffing | 
 | 519 | 		bitcnt -= ((bitcnt * 5) >> 6);	// bits without eob | 
 | 520 |  | 
 | 521 | 		tmp = bitcnt >> 16; | 
 | 522 | 		dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n", | 
 | 523 | 			ptr->name, bitcnt, tmp); | 
 | 524 | 		zr36050_write(ptr, ZR050_TCV_DATA_HI, tmp >> 8); | 
 | 525 | 		zr36050_write(ptr, ZR050_TCV_DATA_MH, tmp & 0xff); | 
 | 526 | 		tmp = bitcnt & 0xffff; | 
 | 527 | 		zr36050_write(ptr, ZR050_TCV_DATA_ML, tmp >> 8); | 
 | 528 | 		zr36050_write(ptr, ZR050_TCV_DATA_LO, tmp & 0xff); | 
 | 529 |  | 
 | 530 | 		/* compression setup with or without bitrate control */ | 
 | 531 | 		zr36050_write(ptr, ZR050_MODE, | 
 | 532 | 			      ZR050_MO_COMP | ZR050_MO_PASS2 | | 
 | 533 | 			      (ptr->bitrate_ctrl ? ZR050_MO_BRC : 0)); | 
 | 534 |  | 
 | 535 | 		/* this headers seem to deliver "valid AVI" jpeg frames */ | 
 | 536 | 		zr36050_write(ptr, ZR050_MARKERS_EN, | 
 | 537 | 			      ZR050_ME_DQT | ZR050_ME_DHT | | 
 | 538 | 			      ((ptr->app.len > 0) ? ZR050_ME_APP : 0) | | 
 | 539 | 			      ((ptr->com.len > 0) ? ZR050_ME_COM : 0)); | 
 | 540 | 	} else { | 
 | 541 | 		dprintk(2, "%s: EXPANSION SETUP\n", ptr->name); | 
 | 542 |  | 
 | 543 | 		/* 050 communicates with 055 in master mode */ | 
 | 544 | 		zr36050_write(ptr, ZR050_HARDWARE, | 
 | 545 | 			      ZR050_HW_MSTR | ZR050_HW_CFIS_2_CLK); | 
 | 546 |  | 
 | 547 | 		/* encoding table preload */ | 
 | 548 | 		zr36050_write(ptr, ZR050_MODE, ZR050_MO_TLM); | 
 | 549 |  | 
 | 550 | 		/* disable all IRQs */ | 
 | 551 | 		zr36050_write(ptr, ZR050_INT_REQ_0, 0); | 
 | 552 | 		zr36050_write(ptr, ZR050_INT_REQ_1, 3);	// low 2 bits always 1 | 
 | 553 |  | 
 | 554 | 		dprintk(3, "%s: write DHT\n", ptr->name); | 
 | 555 | 		zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht), | 
 | 556 | 			       zr36050_dht); | 
 | 557 |  | 
 | 558 | 		/* do the internal huffman table preload */ | 
 | 559 | 		zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI); | 
 | 560 |  | 
 | 561 | 		zr36050_write(ptr, ZR050_GO, 1);	// launch codec | 
 | 562 | 		zr36050_wait_end(ptr); | 
 | 563 | 		dprintk(2, "%s: Status after table preload: 0x%02x\n", | 
 | 564 | 			ptr->name, ptr->status1); | 
 | 565 |  | 
 | 566 | 		if ((ptr->status1 & 0x4) == 0) { | 
 | 567 | 			dprintk(1, KERN_ERR "%s: init aborted!\n", | 
 | 568 | 				ptr->name); | 
 | 569 | 			return;	// something is wrong, its timed out!!!! | 
 | 570 | 		} | 
 | 571 |  | 
 | 572 | 		/* setup misc. data for expansion */ | 
 | 573 | 		zr36050_write(ptr, ZR050_MODE, 0); | 
 | 574 | 		zr36050_write(ptr, ZR050_MARKERS_EN, 0); | 
 | 575 | 	} | 
 | 576 |  | 
 | 577 | 	/* adr on selected, to allow GO from master */ | 
 | 578 | 	zr36050_read(ptr, 0); | 
 | 579 | } | 
 | 580 |  | 
 | 581 | /* ========================================================================= | 
 | 582 |    CODEC API FUNCTIONS | 
 | 583 |  | 
 | 584 |    this functions are accessed by the master via the API structure | 
 | 585 |    ========================================================================= */ | 
 | 586 |  | 
 | 587 | /* set compression/expansion mode and launches codec - | 
 | 588 |    this should be the last call from the master before starting processing */ | 
 | 589 | static int | 
 | 590 | zr36050_set_mode (struct videocodec *codec, | 
 | 591 | 		  int                mode) | 
 | 592 | { | 
 | 593 | 	struct zr36050 *ptr = (struct zr36050 *) codec->data; | 
 | 594 |  | 
 | 595 | 	dprintk(2, "%s: set_mode %d call\n", ptr->name, mode); | 
 | 596 |  | 
 | 597 | 	if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION)) | 
 | 598 | 		return -EINVAL; | 
 | 599 |  | 
 | 600 | 	ptr->mode = mode; | 
 | 601 | 	zr36050_init(ptr); | 
 | 602 |  | 
 | 603 | 	return 0; | 
 | 604 | } | 
 | 605 |  | 
 | 606 | /* set picture size (norm is ignored as the codec doesn't know about it) */ | 
 | 607 | static int | 
 | 608 | zr36050_set_video (struct videocodec   *codec, | 
 | 609 | 		   struct tvnorm       *norm, | 
 | 610 | 		   struct vfe_settings *cap, | 
 | 611 | 		   struct vfe_polarity *pol) | 
 | 612 | { | 
 | 613 | 	struct zr36050 *ptr = (struct zr36050 *) codec->data; | 
 | 614 | 	int size; | 
 | 615 |  | 
 | 616 | 	dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n", | 
 | 617 | 		ptr->name, norm->HStart, norm->VStart, | 
 | 618 | 		cap->x, cap->y, cap->width, cap->height, | 
 | 619 | 		cap->decimation, cap->quality); | 
 | 620 | 	/* if () return -EINVAL; | 
 | 621 | 	 * trust the master driver that it knows what it does - so | 
 | 622 | 	 * we allow invalid startx/y and norm for now ... */ | 
 | 623 | 	ptr->width = cap->width / (cap->decimation & 0xff); | 
 | 624 | 	ptr->height = cap->height / ((cap->decimation >> 8) & 0xff); | 
 | 625 |  | 
 | 626 | 	/* (KM) JPEG quality */ | 
 | 627 | 	size = ptr->width * ptr->height; | 
 | 628 | 	size *= 16; /* size in bits */ | 
 | 629 | 	/* apply quality setting */ | 
 | 630 | 	size = size * cap->quality / 200; | 
 | 631 |  | 
 | 632 | 	/* Minimum: 1kb */ | 
 | 633 | 	if (size < 8192) | 
 | 634 | 		size = 8192; | 
 | 635 | 	/* Maximum: 7/8 of code buffer */ | 
 | 636 | 	if (size > ptr->total_code_vol * 7) | 
 | 637 | 		size = ptr->total_code_vol * 7; | 
 | 638 |  | 
 | 639 | 	ptr->real_code_vol = size >> 3; /* in bytes */ | 
 | 640 |  | 
 | 641 | 	/* Set max_block_vol here (previously in zr36050_init, moved | 
 | 642 | 	 * here for consistency with zr36060 code */ | 
 | 643 | 	zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol); | 
 | 644 |  | 
 | 645 | 	return 0; | 
 | 646 | } | 
 | 647 |  | 
 | 648 | /* additional control functions */ | 
 | 649 | static int | 
 | 650 | zr36050_control (struct videocodec *codec, | 
 | 651 | 		 int                type, | 
 | 652 | 		 int                size, | 
 | 653 | 		 void              *data) | 
 | 654 | { | 
 | 655 | 	struct zr36050 *ptr = (struct zr36050 *) codec->data; | 
 | 656 | 	int *ival = (int *) data; | 
 | 657 |  | 
 | 658 | 	dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type, | 
 | 659 | 		size); | 
 | 660 |  | 
 | 661 | 	switch (type) { | 
 | 662 | 	case CODEC_G_STATUS:	/* get last status */ | 
 | 663 | 		if (size != sizeof(int)) | 
 | 664 | 			return -EFAULT; | 
 | 665 | 		zr36050_read_status1(ptr); | 
 | 666 | 		*ival = ptr->status1; | 
 | 667 | 		break; | 
 | 668 |  | 
 | 669 | 	case CODEC_G_CODEC_MODE: | 
 | 670 | 		if (size != sizeof(int)) | 
 | 671 | 			return -EFAULT; | 
 | 672 | 		*ival = CODEC_MODE_BJPG; | 
 | 673 | 		break; | 
 | 674 |  | 
 | 675 | 	case CODEC_S_CODEC_MODE: | 
 | 676 | 		if (size != sizeof(int)) | 
 | 677 | 			return -EFAULT; | 
 | 678 | 		if (*ival != CODEC_MODE_BJPG) | 
 | 679 | 			return -EINVAL; | 
 | 680 | 		/* not needed, do nothing */ | 
 | 681 | 		return 0; | 
 | 682 |  | 
 | 683 | 	case CODEC_G_VFE: | 
 | 684 | 	case CODEC_S_VFE: | 
 | 685 | 		/* not needed, do nothing */ | 
 | 686 | 		return 0; | 
 | 687 |  | 
 | 688 | 	case CODEC_S_MMAP: | 
 | 689 | 		/* not available, give an error */ | 
 | 690 | 		return -ENXIO; | 
 | 691 |  | 
 | 692 | 	case CODEC_G_JPEG_TDS_BYTE:	/* get target volume in byte */ | 
 | 693 | 		if (size != sizeof(int)) | 
 | 694 | 			return -EFAULT; | 
 | 695 | 		*ival = ptr->total_code_vol; | 
 | 696 | 		break; | 
 | 697 |  | 
 | 698 | 	case CODEC_S_JPEG_TDS_BYTE:	/* get target volume in byte */ | 
 | 699 | 		if (size != sizeof(int)) | 
 | 700 | 			return -EFAULT; | 
 | 701 | 		ptr->total_code_vol = *ival; | 
 | 702 | 		/* (Kieran Morrissey) | 
 | 703 | 		 * code copied from zr36060.c to ensure proper bitrate */ | 
 | 704 | 		ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3; | 
 | 705 | 		break; | 
 | 706 |  | 
 | 707 | 	case CODEC_G_JPEG_SCALE:	/* get scaling factor */ | 
 | 708 | 		if (size != sizeof(int)) | 
 | 709 | 			return -EFAULT; | 
 | 710 | 		*ival = zr36050_read_scalefactor(ptr); | 
 | 711 | 		break; | 
 | 712 |  | 
 | 713 | 	case CODEC_S_JPEG_SCALE:	/* set scaling factor */ | 
 | 714 | 		if (size != sizeof(int)) | 
 | 715 | 			return -EFAULT; | 
 | 716 | 		ptr->scalefact = *ival; | 
 | 717 | 		break; | 
 | 718 |  | 
 | 719 | 	case CODEC_G_JPEG_APP_DATA: {	/* get appn marker data */ | 
 | 720 | 		struct jpeg_app_marker *app = data; | 
 | 721 |  | 
 | 722 | 		if (size != sizeof(struct jpeg_app_marker)) | 
 | 723 | 			return -EFAULT; | 
 | 724 |  | 
 | 725 | 		*app = ptr->app; | 
 | 726 | 		break; | 
 | 727 | 	} | 
 | 728 |  | 
 | 729 | 	case CODEC_S_JPEG_APP_DATA: {	 /* set appn marker data */ | 
 | 730 | 		struct jpeg_app_marker *app = data; | 
 | 731 |  | 
 | 732 | 		if (size != sizeof(struct jpeg_app_marker)) | 
 | 733 | 			return -EFAULT; | 
 | 734 |  | 
 | 735 | 		ptr->app = *app; | 
 | 736 | 		break; | 
 | 737 | 	} | 
 | 738 |  | 
 | 739 | 	case CODEC_G_JPEG_COM_DATA: {	/* get comment marker data */ | 
 | 740 | 		struct jpeg_com_marker *com = data; | 
 | 741 |  | 
 | 742 | 		if (size != sizeof(struct jpeg_com_marker)) | 
 | 743 | 			return -EFAULT; | 
 | 744 |  | 
 | 745 | 		*com = ptr->com; | 
 | 746 | 		break; | 
 | 747 | 	} | 
 | 748 |  | 
 | 749 | 	case CODEC_S_JPEG_COM_DATA: {	/* set comment marker data */ | 
 | 750 | 		struct jpeg_com_marker *com = data; | 
 | 751 |  | 
 | 752 | 		if (size != sizeof(struct jpeg_com_marker)) | 
 | 753 | 			return -EFAULT; | 
 | 754 |  | 
 | 755 | 		ptr->com = *com; | 
 | 756 | 		break; | 
 | 757 | 	} | 
 | 758 |  | 
 | 759 | 	default: | 
 | 760 | 		return -EINVAL; | 
 | 761 | 	} | 
 | 762 |  | 
 | 763 | 	return size; | 
 | 764 | } | 
 | 765 |  | 
 | 766 | /* ========================================================================= | 
 | 767 |    Exit and unregister function: | 
 | 768 |  | 
 | 769 |    Deinitializes Zoran's JPEG processor | 
 | 770 |    ========================================================================= */ | 
 | 771 |  | 
 | 772 | static int | 
 | 773 | zr36050_unset (struct videocodec *codec) | 
 | 774 | { | 
 | 775 | 	struct zr36050 *ptr = codec->data; | 
 | 776 |  | 
 | 777 | 	if (ptr) { | 
 | 778 | 		/* do wee need some codec deinit here, too ???? */ | 
 | 779 |  | 
 | 780 | 		dprintk(1, "%s: finished codec #%d\n", ptr->name, | 
 | 781 | 			ptr->num); | 
 | 782 | 		kfree(ptr); | 
 | 783 | 		codec->data = NULL; | 
 | 784 |  | 
 | 785 | 		zr36050_codecs--; | 
 | 786 | 		return 0; | 
 | 787 | 	} | 
 | 788 |  | 
 | 789 | 	return -EFAULT; | 
 | 790 | } | 
 | 791 |  | 
 | 792 | /* ========================================================================= | 
 | 793 |    Setup and registry function: | 
 | 794 |  | 
 | 795 |    Initializes Zoran's JPEG processor | 
 | 796 |  | 
 | 797 |    Also sets pixel size, average code size, mode (compr./decompr.) | 
 | 798 |    (the given size is determined by the processor with the video interface) | 
 | 799 |    ========================================================================= */ | 
 | 800 |  | 
 | 801 | static int | 
 | 802 | zr36050_setup (struct videocodec *codec) | 
 | 803 | { | 
 | 804 | 	struct zr36050 *ptr; | 
 | 805 | 	int res; | 
 | 806 |  | 
 | 807 | 	dprintk(2, "zr36050: initializing MJPEG subsystem #%d.\n", | 
 | 808 | 		zr36050_codecs); | 
 | 809 |  | 
 | 810 | 	if (zr36050_codecs == MAX_CODECS) { | 
 | 811 | 		dprintk(1, | 
 | 812 | 			KERN_ERR "zr36050: Can't attach more codecs!\n"); | 
 | 813 | 		return -ENOSPC; | 
 | 814 | 	} | 
 | 815 | 	//mem structure init | 
| Panagiotis Issaris | 7408187 | 2006-01-11 19:40:56 -0200 | [diff] [blame] | 816 | 	codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 817 | 	if (NULL == ptr) { | 
 | 818 | 		dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n"); | 
 | 819 | 		return -ENOMEM; | 
 | 820 | 	} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 821 |  | 
 | 822 | 	snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]", | 
 | 823 | 		 zr36050_codecs); | 
 | 824 | 	ptr->num = zr36050_codecs++; | 
 | 825 | 	ptr->codec = codec; | 
 | 826 |  | 
 | 827 | 	//testing | 
 | 828 | 	res = zr36050_basic_test(ptr); | 
 | 829 | 	if (res < 0) { | 
 | 830 | 		zr36050_unset(codec); | 
 | 831 | 		return res; | 
 | 832 | 	} | 
 | 833 | 	//final setup | 
 | 834 | 	memcpy(ptr->h_samp_ratio, zr36050_decimation_h, 8); | 
 | 835 | 	memcpy(ptr->v_samp_ratio, zr36050_decimation_v, 8); | 
 | 836 |  | 
 | 837 | 	ptr->bitrate_ctrl = 0;	/* 0 or 1 - fixed file size flag | 
 | 838 | 				 * (what is the difference?) */ | 
 | 839 | 	ptr->mode = CODEC_DO_COMPRESSION; | 
 | 840 | 	ptr->width = 384; | 
 | 841 | 	ptr->height = 288; | 
 | 842 | 	ptr->total_code_vol = 16000; | 
 | 843 | 	ptr->max_block_vol = 240; | 
 | 844 | 	ptr->scalefact = 0x100; | 
 | 845 | 	ptr->dri = 1; | 
 | 846 |  | 
 | 847 | 	/* no app/com marker by default */ | 
 | 848 | 	ptr->app.appn = 0; | 
 | 849 | 	ptr->app.len = 0; | 
 | 850 | 	ptr->com.len = 0; | 
 | 851 |  | 
 | 852 | 	zr36050_init(ptr); | 
 | 853 |  | 
 | 854 | 	dprintk(1, KERN_INFO "%s: codec attached and running\n", | 
 | 855 | 		ptr->name); | 
 | 856 |  | 
 | 857 | 	return 0; | 
 | 858 | } | 
 | 859 |  | 
 | 860 | static const struct videocodec zr36050_codec = { | 
 | 861 | 	.owner = THIS_MODULE, | 
 | 862 | 	.name = "zr36050", | 
 | 863 | 	.magic = 0L,		// magic not used | 
 | 864 | 	.flags = | 
 | 865 | 	    CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER | | 
 | 866 | 	    CODEC_FLAG_DECODER, | 
 | 867 | 	.type = CODEC_TYPE_ZR36050, | 
 | 868 | 	.setup = zr36050_setup,	// functionality | 
 | 869 | 	.unset = zr36050_unset, | 
 | 870 | 	.set_mode = zr36050_set_mode, | 
 | 871 | 	.set_video = zr36050_set_video, | 
 | 872 | 	.control = zr36050_control, | 
 | 873 | 	// others are not used | 
 | 874 | }; | 
 | 875 |  | 
 | 876 | /* ========================================================================= | 
 | 877 |    HOOK IN DRIVER AS KERNEL MODULE | 
 | 878 |    ========================================================================= */ | 
 | 879 |  | 
 | 880 | static int __init | 
 | 881 | zr36050_init_module (void) | 
 | 882 | { | 
 | 883 | 	//dprintk(1, "ZR36050 driver %s\n",ZR050_VERSION); | 
 | 884 | 	zr36050_codecs = 0; | 
 | 885 | 	return videocodec_register(&zr36050_codec); | 
 | 886 | } | 
 | 887 |  | 
 | 888 | static void __exit | 
 | 889 | zr36050_cleanup_module (void) | 
 | 890 | { | 
 | 891 | 	if (zr36050_codecs) { | 
 | 892 | 		dprintk(1, | 
 | 893 | 			"zr36050: something's wrong - %d codecs left somehow.\n", | 
 | 894 | 			zr36050_codecs); | 
 | 895 | 	} | 
 | 896 | 	videocodec_unregister(&zr36050_codec); | 
 | 897 | } | 
 | 898 |  | 
 | 899 | module_init(zr36050_init_module); | 
 | 900 | module_exit(zr36050_cleanup_module); | 
 | 901 |  | 
 | 902 | MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>"); | 
 | 903 | MODULE_DESCRIPTION("Driver module for ZR36050 jpeg processors " | 
 | 904 | 		   ZR050_VERSION); | 
 | 905 | MODULE_LICENSE("GPL"); |