xref: /openbmc/linux/drivers/media/pci/zoran/zr36060.c (revision 519b58bb)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Zoran ZR36060 basic configuration functions
4  *
5  * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
6  */
7 
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/slab.h>
11 #include <linux/delay.h>
12 
13 #include <linux/types.h>
14 #include <linux/wait.h>
15 
16 /* I/O commands, error codes */
17 #include <linux/io.h>
18 
19 /* headerfile of this module */
20 #include "zr36060.h"
21 
22 /* codec io API */
23 #include "videocodec.h"
24 
25 /* it doesn't make sense to have more than 20 or so, just to prevent some unwanted loops */
26 #define MAX_CODECS 20
27 
28 /* amount of chips attached via this driver */
29 static int zr36060_codecs;
30 
31 static bool low_bitrate;
32 module_param(low_bitrate, bool, 0);
33 MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
34 
35 /* =========================================================================
36  * Local hardware I/O functions:
37  * read/write via codec layer (registers are located in the master device)
38  * =========================================================================
39  */
40 
41 static u8 zr36060_read(struct zr36060 *ptr, u16 reg)
42 {
43 	u8 value = 0;
44 	struct zoran *zr = videocodec_to_zoran(ptr->codec);
45 
46 	// just in case something is wrong...
47 	if (ptr->codec->master_data->readreg)
48 		value = (ptr->codec->master_data->readreg(ptr->codec, reg)) & 0xff;
49 	else
50 		zrdev_err(zr, "%s: invalid I/O setup, nothing read!\n", ptr->name);
51 
52 	return value;
53 }
54 
55 static void zr36060_write(struct zr36060 *ptr, u16 reg, u8 value)
56 {
57 	struct zoran *zr = videocodec_to_zoran(ptr->codec);
58 
59 	zrdev_dbg(zr, "0x%02x @0x%04x\n", value, reg);
60 
61 	// just in case something is wrong...
62 	if (ptr->codec->master_data->writereg)
63 		ptr->codec->master_data->writereg(ptr->codec, reg, value);
64 	else
65 		zrdev_err(zr, "%s: invalid I/O setup, nothing written!\n", ptr->name);
66 }
67 
68 /* =========================================================================
69  * Local helper function:
70  * status read
71  * =========================================================================
72  */
73 
74 /* status is kept in datastructure */
75 static u8 zr36060_read_status(struct zr36060 *ptr)
76 {
77 	ptr->status = zr36060_read(ptr, ZR060_CFSR);
78 
79 	zr36060_read(ptr, 0);
80 	return ptr->status;
81 }
82 
83 /* scale factor is kept in datastructure */
84 static u16 zr36060_read_scalefactor(struct zr36060 *ptr)
85 {
86 	ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
87 			 (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
88 
89 	/* leave 0 selected for an eventually GO from master */
90 	zr36060_read(ptr, 0);
91 	return ptr->scalefact;
92 }
93 
94 /* wait if codec is ready to proceed (end of processing) or time is over */
95 static void zr36060_wait_end(struct zr36060 *ptr)
96 {
97 	struct zoran *zr = videocodec_to_zoran(ptr->codec);
98 	int i = 0;
99 
100 	while (zr36060_read_status(ptr) & ZR060_CFSR_BUSY) {
101 		udelay(1);
102 		if (i++ > 200000) {	// 200ms, there is for sure something wrong!!!
103 			zrdev_dbg(zr,
104 				  "%s: timeout at wait_end (last status: 0x%02x)\n",
105 				  ptr->name, ptr->status);
106 			break;
107 		}
108 	}
109 }
110 
111 /* Basic test of "connectivity", writes/reads to/from memory the SOF marker */
112 static int zr36060_basic_test(struct zr36060 *ptr)
113 {
114 	struct zoran *zr = videocodec_to_zoran(ptr->codec);
115 
116 	if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
117 	    (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
118 		zrdev_err(zr, "%s: attach failed, can't connect to jpeg processor!\n", ptr->name);
119 		return -ENXIO;
120 	}
121 
122 	zr36060_wait_end(ptr);
123 	if (ptr->status & ZR060_CFSR_BUSY) {
124 		zrdev_err(zr, "%s: attach failed, jpeg processor failed (end flag)!\n", ptr->name);
125 		return -EBUSY;
126 	}
127 
128 	return 0;		/* looks good! */
129 }
130 
131 /* simple loop for pushing the init datasets */
132 static int zr36060_pushit(struct zr36060 *ptr, u16 startreg, u16 len, const char *data)
133 {
134 	struct zoran *zr = videocodec_to_zoran(ptr->codec);
135 	int i = 0;
136 
137 	zrdev_dbg(zr, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
138 		  startreg, len);
139 	while (i < len)
140 		zr36060_write(ptr, startreg++, data[i++]);
141 
142 	return i;
143 }
144 
145 /* =========================================================================
146  * Basic datasets:
147  * jpeg baseline setup data (you find it on lots places in internet, or just
148  * extract it from any regular .jpg image...)
149  *
150  * Could be variable, but until it's not needed it they are just fixed to save
151  * memory. Otherwise expand zr36060 structure with arrays, push the values to
152  * it and initialize from there, as e.g. the linux zr36057/60 driver does it.
153  * =========================================================================
154  */
155 static const char zr36060_dqt[0x86] = {
156 	0xff, 0xdb,		//Marker: DQT
157 	0x00, 0x84,		//Length: 2*65+2
158 	0x00,			//Pq,Tq first table
159 	0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
160 	0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
161 	0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
162 	0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
163 	0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
164 	0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
165 	0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
166 	0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
167 	0x01,			//Pq,Tq second table
168 	0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
169 	0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
170 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
171 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
172 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
173 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
174 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
175 	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
176 };
177 
178 static const char zr36060_dht[0x1a4] = {
179 	0xff, 0xc4,		//Marker: DHT
180 	0x01, 0xa2,		//Length: 2*AC, 2*DC
181 	0x00,			//DC first table
182 	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
183 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
184 	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
185 	0x01,			//DC second table
186 	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
187 	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
188 	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
189 	0x10,			//AC first table
190 	0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
191 	0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
192 	0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
193 	0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
194 	0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
195 	0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
196 	0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
197 	0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
198 	0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
199 	0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
200 	0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
201 	0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
202 	0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
203 	0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
204 	0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
205 	0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
206 	0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
207 	0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
208 	0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
209 	0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
210 	0xF8, 0xF9, 0xFA,
211 	0x11,			//AC second table
212 	0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
213 	0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
214 	0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
215 	0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
216 	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
217 	0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
218 	0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
219 	0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
220 	0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
221 	0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
222 	0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
223 	0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
224 	0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
225 	0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
226 	0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
227 	0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
228 	0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
229 	0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
230 	0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
231 	0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
232 	0xF9, 0xFA
233 };
234 
235 /* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
236 #define NO_OF_COMPONENTS          0x3	//Y,U,V
237 #define BASELINE_PRECISION        0x8	//MCU size (?)
238 static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };	//table idx's QT
239 static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };	//table idx's DC
240 static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };	//table idx's AC
241 
242 /* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
243 static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
244 static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
245 
246 /*
247  * SOF (start of frame) segment depends on width, height and sampling ratio
248  * of each color component
249  */
250 static int zr36060_set_sof(struct zr36060 *ptr)
251 {
252 	struct zoran *zr = videocodec_to_zoran(ptr->codec);
253 	char sof_data[34];	// max. size of register set
254 	int i;
255 
256 	zrdev_dbg(zr, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
257 		  ptr->width, ptr->height, NO_OF_COMPONENTS);
258 	sof_data[0] = 0xff;
259 	sof_data[1] = 0xc0;
260 	sof_data[2] = 0x00;
261 	sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
262 	sof_data[4] = BASELINE_PRECISION;	// only '8' possible with zr36060
263 	sof_data[5] = (ptr->height) >> 8;
264 	sof_data[6] = (ptr->height) & 0xff;
265 	sof_data[7] = (ptr->width) >> 8;
266 	sof_data[8] = (ptr->width) & 0xff;
267 	sof_data[9] = NO_OF_COMPONENTS;
268 	for (i = 0; i < NO_OF_COMPONENTS; i++) {
269 		sof_data[10 + (i * 3)] = i;	// index identifier
270 		sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
271 					 (ptr->v_samp_ratio[i]); // sampling ratios
272 		sof_data[12 + (i * 3)] = zr36060_tq[i];	// Q table selection
273 	}
274 	return zr36060_pushit(ptr, ZR060_SOF_IDX,
275 			      (3 * NO_OF_COMPONENTS) + 10, sof_data);
276 }
277 
278 /* SOS (start of scan) segment depends on the used scan components of each color component */
279 static int zr36060_set_sos(struct zr36060 *ptr)
280 {
281 	struct zoran *zr = videocodec_to_zoran(ptr->codec);
282 	char sos_data[16];	// max. size of register set
283 	int i;
284 
285 	zrdev_dbg(zr, "%s: write SOS\n", ptr->name);
286 	sos_data[0] = 0xff;
287 	sos_data[1] = 0xda;
288 	sos_data[2] = 0x00;
289 	sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
290 	sos_data[4] = NO_OF_COMPONENTS;
291 	for (i = 0; i < NO_OF_COMPONENTS; i++) {
292 		sos_data[5 + (i * 2)] = i;	// index
293 		sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
294 					zr36060_ta[i]; // AC/DC tbl.sel.
295 	}
296 	sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;	// scan start
297 	sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
298 	sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
299 	return zr36060_pushit(ptr, ZR060_SOS_IDX,
300 			      4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
301 			      sos_data);
302 }
303 
304 /* DRI (define restart interval) */
305 static int zr36060_set_dri(struct zr36060 *ptr)
306 {
307 	struct zoran *zr = videocodec_to_zoran(ptr->codec);
308 	char dri_data[6];	// max. size of register set
309 
310 	zrdev_dbg(zr, "%s: write DRI\n", ptr->name);
311 	dri_data[0] = 0xff;
312 	dri_data[1] = 0xdd;
313 	dri_data[2] = 0x00;
314 	dri_data[3] = 0x04;
315 	dri_data[4] = (ptr->dri) >> 8;
316 	dri_data[5] = (ptr->dri) & 0xff;
317 	return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
318 }
319 
320 /* Setup compression/decompression of Zoran's JPEG processor ( see also zoran 36060 manual )
321  * ... sorry for the spaghetti code ...
322  */
323 static void zr36060_init(struct zr36060 *ptr)
324 {
325 	int sum = 0;
326 	long bitcnt, tmp;
327 	struct zoran *zr = videocodec_to_zoran(ptr->codec);
328 
329 	if (ptr->mode == CODEC_DO_COMPRESSION) {
330 		zrdev_dbg(zr, "%s: COMPRESSION SETUP\n", ptr->name);
331 
332 		zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
333 
334 		/* 060 communicates with 067 in master mode */
335 		zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
336 
337 		/* Compression with or without variable scale factor */
338 		/*FIXME: What about ptr->bitrate_ctrl? */
339 		zr36060_write(ptr, ZR060_CMR, ZR060_CMR_COMP | ZR060_CMR_PASS2 | ZR060_CMR_BRB);
340 
341 		/* Must be zero */
342 		zr36060_write(ptr, ZR060_MBZ, 0x00);
343 		zr36060_write(ptr, ZR060_TCR_HI, 0x00);
344 		zr36060_write(ptr, ZR060_TCR_LO, 0x00);
345 
346 		/* Disable all IRQs - no DataErr means autoreset */
347 		zr36060_write(ptr, ZR060_IMR, 0);
348 
349 		/* volume control settings */
350 		zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
351 		zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
352 
353 		zr36060_write(ptr, ZR060_AF_HI, 0xff);
354 		zr36060_write(ptr, ZR060_AF_M, 0xff);
355 		zr36060_write(ptr, ZR060_AF_LO, 0xff);
356 
357 		/* setup the variable jpeg tables */
358 		sum += zr36060_set_sof(ptr);
359 		sum += zr36060_set_sos(ptr);
360 		sum += zr36060_set_dri(ptr);
361 
362 /* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
363 		sum += zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt), zr36060_dqt);
364 		sum += zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
365 		zr36060_write(ptr, ZR060_APP_IDX, 0xff);
366 		zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
367 		zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
368 		zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
369 		sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60, ptr->app.data) + 4;
370 		zr36060_write(ptr, ZR060_COM_IDX, 0xff);
371 		zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
372 		zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
373 		zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
374 		sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60, ptr->com.data) + 4;
375 
376 		/* setup misc. data for compression (target code sizes) */
377 
378 		/* size of compressed code to reach without header data */
379 		sum = ptr->real_code_vol - sum;
380 		bitcnt = sum << 3;	/* need the size in bits */
381 
382 		tmp = bitcnt >> 16;
383 		zrdev_dbg(zr,
384 			  "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
385 			  ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
386 		zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
387 		zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
388 		tmp = bitcnt & 0xffff;
389 		zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
390 		zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
391 
392 		bitcnt -= bitcnt >> 7;	// bits without stuffing
393 		bitcnt -= ((bitcnt * 5) >> 6);	// bits without eob
394 
395 		tmp = bitcnt >> 16;
396 		zrdev_dbg(zr, "%s: code: nettobit=%ld, highnettobits=%ld\n",
397 			  ptr->name, bitcnt, tmp);
398 		zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
399 		zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
400 		tmp = bitcnt & 0xffff;
401 		zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
402 		zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
403 
404 		/* JPEG markers to be included in the compressed stream */
405 		zr36060_write(ptr, ZR060_MER,
406 			      ZR060_MER_DQT | ZR060_MER_DHT |
407 			      ((ptr->com.len > 0) ? ZR060_MER_COM : 0) |
408 			      ((ptr->app.len > 0) ? ZR060_MER_APP : 0));
409 
410 		/* Setup the Video Frontend */
411 		/* Limit pixel range to 16..235 as per CCIR-601 */
412 		zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
413 
414 	} else {
415 		zrdev_dbg(zr, "%s: EXPANSION SETUP\n", ptr->name);
416 
417 		zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
418 
419 		/* 060 communicates with 067 in master mode */
420 		zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
421 
422 		/* Decompression */
423 		zr36060_write(ptr, ZR060_CMR, 0);
424 
425 		/* Must be zero */
426 		zr36060_write(ptr, ZR060_MBZ, 0x00);
427 		zr36060_write(ptr, ZR060_TCR_HI, 0x00);
428 		zr36060_write(ptr, ZR060_TCR_LO, 0x00);
429 
430 		/* Disable all IRQs - no DataErr means autoreset */
431 		zr36060_write(ptr, ZR060_IMR, 0);
432 
433 		/* setup misc. data for expansion */
434 		zr36060_write(ptr, ZR060_MER, 0);
435 
436 /* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
437 		zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
438 
439 		/* Setup the Video Frontend */
440 		//zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FI_EXT);
441 		//this doesn't seem right and doesn't work...
442 		zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
443 	}
444 
445 	/* Load the tables */
446 	zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST | ZR060_LOAD_LOAD);
447 	zr36060_wait_end(ptr);
448 	zrdev_dbg(zr, "%s: Status after table preload: 0x%02x\n",
449 		  ptr->name, ptr->status);
450 
451 	if (ptr->status & ZR060_CFSR_BUSY) {
452 		zrdev_err(zr, "%s: init aborted!\n", ptr->name);
453 		return;		// something is wrong, its timed out!!!!
454 	}
455 }
456 
457 /* =========================================================================
458  * CODEC API FUNCTIONS
459  * this functions are accessed by the master via the API structure
460  * =========================================================================
461  */
462 
463 /* set compressiion/expansion mode and launches codec -
464  * this should be the last call from the master before starting processing
465  */
466 static int zr36060_set_mode(struct videocodec *codec, int mode)
467 {
468 	struct zr36060 *ptr = (struct zr36060 *)codec->data;
469 	struct zoran *zr = videocodec_to_zoran(codec);
470 
471 	zrdev_dbg(zr, "%s: set_mode %d call\n", ptr->name, mode);
472 
473 	if (mode != CODEC_DO_EXPANSION && mode != CODEC_DO_COMPRESSION)
474 		return -EINVAL;
475 
476 	ptr->mode = mode;
477 	zr36060_init(ptr);
478 
479 	return 0;
480 }
481 
482 /* set picture size (norm is ignored as the codec doesn't know about it) */
483 static int zr36060_set_video(struct videocodec *codec, const struct tvnorm *norm,
484 			     struct vfe_settings *cap, struct vfe_polarity *pol)
485 {
486 	struct zr36060 *ptr = (struct zr36060 *)codec->data;
487 	struct zoran *zr = videocodec_to_zoran(codec);
488 	u32 reg;
489 	int size;
490 
491 	zrdev_dbg(zr, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
492 		  cap->x, cap->y, cap->width, cap->height, cap->decimation);
493 
494 	/* if () return -EINVAL;
495 	 * trust the master driver that it knows what it does - so
496 	 * we allow invalid startx/y and norm for now ...
497 	 */
498 	ptr->width = cap->width / (cap->decimation & 0xff);
499 	ptr->height = cap->height / (cap->decimation >> 8);
500 
501 	zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
502 
503 	/* Note that VSPol/HSPol bits in zr36060 have the opposite
504 	 * meaning of their zr360x7 counterparts with the same names
505 	 * N.b. for VSPol this is only true if FIVEdge = 0 (default,
506 	 * left unchanged here - in accordance with datasheet).
507 	 */
508 	reg = (!pol->vsync_pol ? ZR060_VPR_VS_POL : 0)
509 	    | (!pol->hsync_pol ? ZR060_VPR_HS_POL : 0)
510 	    | (pol->field_pol ? ZR060_VPR_FI_POL : 0)
511 	    | (pol->blank_pol ? ZR060_VPR_BL_POL : 0)
512 	    | (pol->subimg_pol ? ZR060_VPR_S_IMG_POL : 0)
513 	    | (pol->poe_pol ? ZR060_VPR_POE_POL : 0)
514 	    | (pol->pvalid_pol ? ZR060_VPR_P_VAL_POL : 0)
515 	    | (pol->vclk_pol ? ZR060_VPR_VCLK_POL : 0);
516 	zr36060_write(ptr, ZR060_VPR, reg);
517 
518 	reg = 0;
519 	switch (cap->decimation & 0xff) {
520 	default:
521 	case 1:
522 		break;
523 
524 	case 2:
525 		reg |= ZR060_SR_H_SCALE2;
526 		break;
527 
528 	case 4:
529 		reg |= ZR060_SR_H_SCALE4;
530 		break;
531 	}
532 
533 	switch (cap->decimation >> 8) {
534 	default:
535 	case 1:
536 		break;
537 
538 	case 2:
539 		reg |= ZR060_SR_V_SCALE;
540 		break;
541 	}
542 	zr36060_write(ptr, ZR060_SR, reg);
543 
544 	zr36060_write(ptr, ZR060_BCR_Y, 0x00);
545 	zr36060_write(ptr, ZR060_BCR_U, 0x80);
546 	zr36060_write(ptr, ZR060_BCR_V, 0x80);
547 
548 	/* sync generator */
549 
550 	reg = norm->ht - 1;	/* Vtotal */
551 	zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
552 	zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
553 
554 	reg = norm->wt - 1;	/* Htotal */
555 	zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
556 	zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
557 
558 	reg = 6 - 1;		/* VsyncSize */
559 	zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
560 
561 	reg = 68;
562 	zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
563 
564 	reg = norm->v_start - 1;	/* BVstart */
565 	zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
566 
567 	reg += norm->ha / 2;	/* BVend */
568 	zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
569 	zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
570 
571 	reg = norm->h_start - 1;	/* BHstart */
572 	zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
573 
574 	reg += norm->wa;	/* BHend */
575 	zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
576 	zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
577 
578 	/* active area */
579 	reg = cap->y + norm->v_start;	/* Vstart */
580 	zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
581 	zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
582 
583 	reg += cap->height;	/* Vend */
584 	zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
585 	zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
586 
587 	reg = cap->x + norm->h_start;	/* Hstart */
588 	zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
589 	zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
590 
591 	reg += cap->width;	/* Hend */
592 	zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
593 	zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
594 
595 	/* subimage area */
596 	reg = norm->v_start - 4;	/* SVstart */
597 	zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
598 	zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
599 
600 	reg += norm->ha / 2 + 8;	/* SVend */
601 	zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
602 	zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
603 
604 	reg = norm->h_start /*+ 64 */  - 4;	/* SHstart */
605 	zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
606 	zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
607 
608 	reg += norm->wa + 8;	/* SHend */
609 	zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
610 	zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
611 
612 	size = ptr->width * ptr->height;
613 	/* Target compressed field size in bits: */
614 	size = size * 16;	/* uncompressed size in bits */
615 	/* (Ronald) by default, quality = 100 is a compression
616 	 * ratio 1:2. Setting low_bitrate (insmod option) sets
617 	 * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
618 	 * buz can't handle more at decimation=1... Use low_bitrate if
619 	 * you have a Buz, unless you know what you're doing
620 	 */
621 	size = size * cap->quality / (low_bitrate ? 400 : 200);
622 	/* Lower limit (arbitrary, 1 KB) */
623 	if (size < 8192)
624 		size = 8192;
625 	/* Upper limit: 7/8 of the code buffers */
626 	if (size > ptr->total_code_vol * 7)
627 		size = ptr->total_code_vol * 7;
628 
629 	ptr->real_code_vol = size >> 3;	/* in bytes */
630 
631 	/* the MBCVR is the *maximum* block volume, according to the
632 	 * JPEG ISO specs, this shouldn't be used, since that allows
633 	 * for the best encoding quality. So set it to it's max value
634 	 */
635 	reg = ptr->max_block_vol;
636 	zr36060_write(ptr, ZR060_MBCVR, reg);
637 
638 	return 0;
639 }
640 
641 /* additional control functions */
642 static int zr36060_control(struct videocodec *codec, int type, int size, void *data)
643 {
644 	struct zr36060 *ptr = (struct zr36060 *)codec->data;
645 	struct zoran *zr = videocodec_to_zoran(codec);
646 	int *ival = (int *)data;
647 
648 	zrdev_dbg(zr, "%s: control %d call with %d byte\n", ptr->name, type,
649 		  size);
650 
651 	switch (type) {
652 	case CODEC_G_STATUS:	/* get last status */
653 		if (size != sizeof(int))
654 			return -EFAULT;
655 		zr36060_read_status(ptr);
656 		*ival = ptr->status;
657 		break;
658 
659 	case CODEC_G_CODEC_MODE:
660 		if (size != sizeof(int))
661 			return -EFAULT;
662 		*ival = CODEC_MODE_BJPG;
663 		break;
664 
665 	case CODEC_S_CODEC_MODE:
666 		if (size != sizeof(int))
667 			return -EFAULT;
668 		if (*ival != CODEC_MODE_BJPG)
669 			return -EINVAL;
670 		/* not needed, do nothing */
671 		return 0;
672 
673 	case CODEC_G_VFE:
674 	case CODEC_S_VFE:
675 		/* not needed, do nothing */
676 		return 0;
677 
678 	case CODEC_S_MMAP:
679 		/* not available, give an error */
680 		return -ENXIO;
681 
682 	case CODEC_G_JPEG_TDS_BYTE:	/* get target volume in byte */
683 		if (size != sizeof(int))
684 			return -EFAULT;
685 		*ival = ptr->total_code_vol;
686 		break;
687 
688 	case CODEC_S_JPEG_TDS_BYTE:	/* get target volume in byte */
689 		if (size != sizeof(int))
690 			return -EFAULT;
691 		ptr->total_code_vol = *ival;
692 		ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
693 		break;
694 
695 	case CODEC_G_JPEG_SCALE:	/* get scaling factor */
696 		if (size != sizeof(int))
697 			return -EFAULT;
698 		*ival = zr36060_read_scalefactor(ptr);
699 		break;
700 
701 	case CODEC_S_JPEG_SCALE:	/* set scaling factor */
702 		if (size != sizeof(int))
703 			return -EFAULT;
704 		ptr->scalefact = *ival;
705 		break;
706 
707 	case CODEC_G_JPEG_APP_DATA: {	/* get appn marker data */
708 		struct jpeg_app_marker *app = data;
709 
710 		if (size != sizeof(struct jpeg_app_marker))
711 			return -EFAULT;
712 
713 		*app = ptr->app;
714 		break;
715 	}
716 
717 	case CODEC_S_JPEG_APP_DATA: {	/* set appn marker data */
718 		struct jpeg_app_marker *app = data;
719 
720 		if (size != sizeof(struct jpeg_app_marker))
721 			return -EFAULT;
722 
723 		ptr->app = *app;
724 		break;
725 	}
726 
727 	case CODEC_G_JPEG_COM_DATA: {	/* get comment marker data */
728 		struct jpeg_com_marker *com = data;
729 
730 		if (size != sizeof(struct jpeg_com_marker))
731 			return -EFAULT;
732 
733 		*com = ptr->com;
734 		break;
735 	}
736 
737 	case CODEC_S_JPEG_COM_DATA: {	/* set comment marker data */
738 		struct jpeg_com_marker *com = data;
739 
740 		if (size != sizeof(struct jpeg_com_marker))
741 			return -EFAULT;
742 
743 		ptr->com = *com;
744 		break;
745 	}
746 
747 	default:
748 		return -EINVAL;
749 	}
750 
751 	return size;
752 }
753 
754 /* =========================================================================
755  * Exit and unregister function:
756  * Deinitializes Zoran's JPEG processor
757  * =========================================================================
758  */
759 static int zr36060_unset(struct videocodec *codec)
760 {
761 	struct zr36060 *ptr = codec->data;
762 	struct zoran *zr = videocodec_to_zoran(codec);
763 
764 	if (ptr) {
765 		/* do wee need some codec deinit here, too ???? */
766 
767 		zrdev_dbg(zr, "%s: finished codec #%d\n", ptr->name, ptr->num);
768 		kfree(ptr);
769 		codec->data = NULL;
770 
771 		zr36060_codecs--;
772 		return 0;
773 	}
774 
775 	return -EFAULT;
776 }
777 
778 /* =========================================================================
779  * Setup and registry function:
780  * Initializes Zoran's JPEG processor
781  * Also sets pixel size, average code size, mode (compr./decompr.)
782  * (the given size is determined by the processor with the video interface)
783  * =========================================================================
784  */
785 static int zr36060_setup(struct videocodec *codec)
786 {
787 	struct zr36060 *ptr;
788 	struct zoran *zr = videocodec_to_zoran(codec);
789 	int res;
790 
791 	zrdev_dbg(zr, "zr36060: initializing MJPEG subsystem #%d.\n",
792 		  zr36060_codecs);
793 
794 	if (zr36060_codecs == MAX_CODECS) {
795 		zrdev_err(zr, "zr36060: Can't attach more codecs!\n");
796 		return -ENOSPC;
797 	}
798 	//mem structure init
799 	ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
800 	codec->data = ptr;
801 	if (!ptr)
802 		return -ENOMEM;
803 
804 	snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]", zr36060_codecs);
805 	ptr->num = zr36060_codecs++;
806 	ptr->codec = codec;
807 
808 	//testing
809 	res = zr36060_basic_test(ptr);
810 	if (res < 0) {
811 		zr36060_unset(codec);
812 		return res;
813 	}
814 	//final setup
815 	memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
816 	memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
817 
818 	ptr->bitrate_ctrl = 0;	/* 0 or 1 - fixed file size flag (what is the difference?) */
819 	ptr->mode = CODEC_DO_COMPRESSION;
820 	ptr->width = 384;
821 	ptr->height = 288;
822 	ptr->total_code_vol = 16000;	/* CHECKME */
823 	ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
824 	ptr->max_block_vol = 240;	/* CHECKME, was 120 is 240 */
825 	ptr->scalefact = 0x100;
826 	ptr->dri = 1;		/* CHECKME, was 8 is 1 */
827 
828 	/* by default, no COM or APP markers - app should set those */
829 	ptr->com.len = 0;
830 	ptr->app.appn = 0;
831 	ptr->app.len = 0;
832 
833 	zr36060_init(ptr);
834 
835 	zrdev_info(zr, "%s: codec attached and running\n", ptr->name);
836 
837 	return 0;
838 }
839 
840 static const struct videocodec zr36060_codec = {
841 	.name = "zr36060",
842 	.magic = 0L,		// magic not used
843 	.flags =
844 	    CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
845 	    CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
846 	.type = CODEC_TYPE_ZR36060,
847 	.setup = zr36060_setup,	// functionality
848 	.unset = zr36060_unset,
849 	.set_mode = zr36060_set_mode,
850 	.set_video = zr36060_set_video,
851 	.control = zr36060_control,
852 	// others are not used
853 };
854 
855 int zr36060_init_module(void)
856 {
857 	zr36060_codecs = 0;
858 	return videocodec_register(&zr36060_codec);
859 }
860 
861 void zr36060_cleanup_module(void)
862 {
863 	if (zr36060_codecs) {
864 		pr_debug("zr36060: something's wrong - %d codecs left somehow.\n",
865 			 zr36060_codecs);
866 	}
867 
868 	/* however, we can't just stay alive */
869 	videocodec_unregister(&zr36060_codec);
870 }
871