2 * Zoran ZR36060 basic configuration functions
4 * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
6 * $Id: zr36060.c,v 1.1.2.22 2003/05/06 09:35:36 rbultje Exp $
8 * ------------------------------------------------------------------------
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.
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.
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.
24 * ------------------------------------------------------------------------
27 #define ZR060_VERSION "v0.7"
29 #include <linux/module.h>
30 #include <linux/init.h>
31 #include <linux/slab.h>
32 #include <linux/delay.h>
34 #include <linux/types.h>
35 #include <linux/wait.h>
37 /* includes for structures and defines regarding video
38 #include<linux/videodev.h> */
40 /* I/O commands, error codes */
44 /* headerfile of this module */
48 #include"videocodec.h"
50 /* it doesn't make sense to have more than 20 or so,
51 just to prevent some unwanted loops */
54 /* amount of chips attached via this driver */
55 static int zr36060_codecs = 0;
57 static int low_bitrate = 0;
58 module_param(low_bitrate, bool, 0);
59 MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
61 /* debugging is available via module parameter */
63 module_param(debug, int, 0);
64 MODULE_PARM_DESC(debug, "Debug level (0-4)");
66 #define dprintk(num, format, args...) \
69 printk(format, ##args); \
72 /* =========================================================================
73 Local hardware I/O functions:
75 read/write via codec layer (registers are located in the master device)
76 ========================================================================= */
78 /* read and write functions */
80 zr36060_read (struct zr36060 *ptr,
85 // just in case something is wrong...
86 if (ptr->codec->master_data->readreg)
87 value = (ptr->codec->master_data->readreg(ptr->codec,
91 KERN_ERR "%s: invalid I/O setup, nothing read!\n",
94 //dprintk(4, "%s: reading from 0x%04x: %02x\n",ptr->name,reg,value);
100 zr36060_write(struct zr36060 *ptr,
104 //dprintk(4, "%s: writing 0x%02x to 0x%04x\n",ptr->name,value,reg);
105 dprintk(4, "0x%02x @0x%04x\n", value, reg);
107 // just in case something is wrong...
108 if (ptr->codec->master_data->writereg)
109 ptr->codec->master_data->writereg(ptr->codec, reg, value);
113 "%s: invalid I/O setup, nothing written!\n",
117 /* =========================================================================
118 Local helper function:
121 ========================================================================= */
123 /* status is kept in datastructure */
125 zr36060_read_status (struct zr36060 *ptr)
127 ptr->status = zr36060_read(ptr, ZR060_CFSR);
129 zr36060_read(ptr, 0);
133 /* =========================================================================
134 Local helper function:
137 ========================================================================= */
139 /* scale factor is kept in datastructure */
141 zr36060_read_scalefactor (struct zr36060 *ptr)
143 ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
144 (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
146 /* leave 0 selected for an eventually GO from master */
147 zr36060_read(ptr, 0);
148 return ptr->scalefact;
151 /* =========================================================================
152 Local helper function:
154 wait if codec is ready to proceed (end of processing) or time is over
155 ========================================================================= */
158 zr36060_wait_end (struct zr36060 *ptr)
162 while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) {
164 if (i++ > 200000) { // 200ms, there is for shure something wrong!!!
166 "%s: timout at wait_end (last status: 0x%02x)\n",
167 ptr->name, ptr->status);
173 /* =========================================================================
174 Local helper function:
176 basic test of "connectivity", writes/reads to/from memory the SOF marker
177 ========================================================================= */
180 zr36060_basic_test (struct zr36060 *ptr)
182 if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
183 (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
186 "%s: attach failed, can't connect to jpeg processor!\n",
191 zr36060_wait_end(ptr);
192 if (ptr->status & ZR060_CFSR_Busy) {
195 "%s: attach failed, jpeg processor failed (end flag)!\n",
200 return 0; /* looks good! */
203 /* =========================================================================
204 Local helper function:
206 simple loop for pushing the init datasets
207 ========================================================================= */
210 zr36060_pushit (struct zr36060 *ptr,
217 dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
220 zr36060_write(ptr, startreg++, data[i++]);
226 /* =========================================================================
229 jpeg baseline setup data (you find it on lots places in internet, or just
230 extract it from any regular .jpg image...)
232 Could be variable, but until it's not needed it they are just fixed to save
233 memory. Otherwise expand zr36060 structure with arrays, push the values to
234 it and initalize from there, as e.g. the linux zr36057/60 driver does it.
235 ========================================================================= */
237 static const char zr36060_dqt[0x86] = {
238 0xff, 0xdb, //Marker: DQT
239 0x00, 0x84, //Length: 2*65+2
240 0x00, //Pq,Tq first table
241 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
242 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
243 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
244 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
245 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
246 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
247 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
248 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
249 0x01, //Pq,Tq second table
250 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
251 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
252 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
253 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
254 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
255 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
256 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
257 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
260 static const char zr36060_dht[0x1a4] = {
261 0xff, 0xc4, //Marker: DHT
262 0x01, 0xa2, //Length: 2*AC, 2*DC
263 0x00, //DC first table
264 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
265 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
266 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
267 0x01, //DC second table
268 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
269 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
270 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
271 0x10, //AC first table
272 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
273 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
274 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
275 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
276 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
277 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
278 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
279 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
280 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
281 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
282 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
283 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
284 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
285 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
286 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
287 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
288 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
289 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
290 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
291 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
293 0x11, //AC second table
294 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
295 0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
296 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
297 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
298 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
299 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
300 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
301 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
302 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
303 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
304 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
305 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
306 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
307 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
308 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
309 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
310 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
311 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
312 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
313 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
317 /* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
318 #define NO_OF_COMPONENTS 0x3 //Y,U,V
319 #define BASELINE_PRECISION 0x8 //MCU size (?)
320 static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's QT
321 static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's DC
322 static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's AC
324 /* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
325 static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
326 static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
328 /* =========================================================================
329 Local helper functions:
331 calculation and setup of parameter-dependent JPEG baseline segments
332 (needed for compression only)
333 ========================================================================= */
335 /* ------------------------------------------------------------------------- */
337 /* SOF (start of frame) segment depends on width, height and sampling ratio
338 of each color component */
341 zr36060_set_sof (struct zr36060 *ptr)
343 char sof_data[34]; // max. size of register set
346 dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
347 ptr->width, ptr->height, NO_OF_COMPONENTS);
351 sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
352 sof_data[4] = BASELINE_PRECISION; // only '8' possible with zr36060
353 sof_data[5] = (ptr->height) >> 8;
354 sof_data[6] = (ptr->height) & 0xff;
355 sof_data[7] = (ptr->width) >> 8;
356 sof_data[8] = (ptr->width) & 0xff;
357 sof_data[9] = NO_OF_COMPONENTS;
358 for (i = 0; i < NO_OF_COMPONENTS; i++) {
359 sof_data[10 + (i * 3)] = i; // index identifier
360 sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
361 (ptr->v_samp_ratio[i]); // sampling ratios
362 sof_data[12 + (i * 3)] = zr36060_tq[i]; // Q table selection
364 return zr36060_pushit(ptr, ZR060_SOF_IDX,
365 (3 * NO_OF_COMPONENTS) + 10, sof_data);
368 /* ------------------------------------------------------------------------- */
370 /* SOS (start of scan) segment depends on the used scan components
371 of each color component */
374 zr36060_set_sos (struct zr36060 *ptr)
376 char sos_data[16]; // max. size of register set
379 dprintk(3, "%s: write SOS\n", ptr->name);
383 sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
384 sos_data[4] = NO_OF_COMPONENTS;
385 for (i = 0; i < NO_OF_COMPONENTS; i++) {
386 sos_data[5 + (i * 2)] = i; // index
387 sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
388 zr36060_ta[i]; // AC/DC tbl.sel.
390 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start
391 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
392 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
393 return zr36060_pushit(ptr, ZR060_SOS_IDX,
394 4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
398 /* ------------------------------------------------------------------------- */
400 /* DRI (define restart interval) */
403 zr36060_set_dri (struct zr36060 *ptr)
405 char dri_data[6]; // max. size of register set
407 dprintk(3, "%s: write DRI\n", ptr->name);
412 dri_data[4] = (ptr->dri) >> 8;
413 dri_data[5] = (ptr->dri) & 0xff;
414 return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
417 /* =========================================================================
420 Setup compression/decompression of Zoran's JPEG processor
421 ( see also zoran 36060 manual )
423 ... sorry for the spaghetti code ...
424 ========================================================================= */
426 zr36060_init (struct zr36060 *ptr)
431 if (ptr->mode == CODEC_DO_COMPRESSION) {
432 dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
434 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
436 /* 060 communicates with 067 in master mode */
437 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
439 /* Compression with or without variable scale factor */
440 /*FIXME: What about ptr->bitrate_ctrl? */
441 zr36060_write(ptr, ZR060_CMR,
442 ZR060_CMR_Comp | ZR060_CMR_Pass2 |
446 zr36060_write(ptr, ZR060_MBZ, 0x00);
447 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
448 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
450 /* Disable all IRQs - no DataErr means autoreset */
451 zr36060_write(ptr, ZR060_IMR, 0);
453 /* volume control settings */
454 zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
455 zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
457 zr36060_write(ptr, ZR060_AF_HI, 0xff);
458 zr36060_write(ptr, ZR060_AF_M, 0xff);
459 zr36060_write(ptr, ZR060_AF_LO, 0xff);
461 /* setup the variable jpeg tables */
462 sum += zr36060_set_sof(ptr);
463 sum += zr36060_set_sos(ptr);
464 sum += zr36060_set_dri(ptr);
466 /* setup the fixed jpeg tables - maybe variable, though -
467 * (see table init section above) */
469 zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt),
472 zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
474 zr36060_write(ptr, ZR060_APP_IDX, 0xff);
475 zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
476 zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
477 zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
478 sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60,
480 zr36060_write(ptr, ZR060_COM_IDX, 0xff);
481 zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
482 zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
483 zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
484 sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60,
487 /* setup misc. data for compression (target code sizes) */
489 /* size of compressed code to reach without header data */
490 sum = ptr->real_code_vol - sum;
491 bitcnt = sum << 3; /* need the size in bits */
495 "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
496 ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
497 zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
498 zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
499 tmp = bitcnt & 0xffff;
500 zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
501 zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
503 bitcnt -= bitcnt >> 7; // bits without stuffing
504 bitcnt -= ((bitcnt * 5) >> 6); // bits without eob
507 dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
508 ptr->name, bitcnt, tmp);
509 zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
510 zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
511 tmp = bitcnt & 0xffff;
512 zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
513 zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
515 /* JPEG markers to be included in the compressed stream */
516 zr36060_write(ptr, ZR060_MER,
517 ZR060_MER_DQT | ZR060_MER_DHT |
518 ((ptr->com.len > 0) ? ZR060_MER_Com : 0) |
519 ((ptr->app.len > 0) ? ZR060_MER_App : 0));
521 /* Setup the Video Frontend */
522 /* Limit pixel range to 16..235 as per CCIR-601 */
523 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
526 dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
528 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
530 /* 060 communicates with 067 in master mode */
531 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
534 zr36060_write(ptr, ZR060_CMR, 0);
537 zr36060_write(ptr, ZR060_MBZ, 0x00);
538 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
539 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
541 /* Disable all IRQs - no DataErr means autoreset */
542 zr36060_write(ptr, ZR060_IMR, 0);
544 /* setup misc. data for expansion */
545 zr36060_write(ptr, ZR060_MER, 0);
547 /* setup the fixed jpeg tables - maybe variable, though -
548 * (see table init section above) */
549 zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
552 /* Setup the Video Frontend */
553 //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FIExt);
554 //this doesn't seem right and doesn't work...
555 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
558 /* Load the tables */
559 zr36060_write(ptr, ZR060_LOAD,
560 ZR060_LOAD_SyncRst | ZR060_LOAD_Load);
561 zr36060_wait_end(ptr);
562 dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name,
565 if (ptr->status & ZR060_CFSR_Busy) {
566 dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name);
567 return; // something is wrong, its timed out!!!!
571 /* =========================================================================
574 this functions are accessed by the master via the API structure
575 ========================================================================= */
577 /* set compression/expansion mode and launches codec -
578 this should be the last call from the master before starting processing */
580 zr36060_set_mode (struct videocodec *codec,
583 struct zr36060 *ptr = (struct zr36060 *) codec->data;
585 dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
587 if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
596 /* set picture size (norm is ignored as the codec doesn't know about it) */
598 zr36060_set_video (struct videocodec *codec,
600 struct vfe_settings *cap,
601 struct vfe_polarity *pol)
603 struct zr36060 *ptr = (struct zr36060 *) codec->data;
607 dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
608 cap->x, cap->y, cap->width, cap->height, cap->decimation);
610 /* if () return -EINVAL;
611 * trust the master driver that it knows what it does - so
612 * we allow invalid startx/y and norm for now ... */
613 ptr->width = cap->width / (cap->decimation & 0xff);
614 ptr->height = cap->height / (cap->decimation >> 8);
616 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
618 /* Note that VSPol/HSPol bits in zr36060 have the opposite
619 * meaning of their zr360x7 counterparts with the same names
620 * N.b. for VSPol this is only true if FIVEdge = 0 (default,
621 * left unchanged here - in accordance with datasheet).
623 reg = (!pol->vsync_pol ? ZR060_VPR_VSPol : 0)
624 | (!pol->hsync_pol ? ZR060_VPR_HSPol : 0)
625 | (pol->field_pol ? ZR060_VPR_FIPol : 0)
626 | (pol->blank_pol ? ZR060_VPR_BLPol : 0)
627 | (pol->subimg_pol ? ZR060_VPR_SImgPol : 0)
628 | (pol->poe_pol ? ZR060_VPR_PoePol : 0)
629 | (pol->pvalid_pol ? ZR060_VPR_PValPol : 0)
630 | (pol->vclk_pol ? ZR060_VPR_VCLKPol : 0);
631 zr36060_write(ptr, ZR060_VPR, reg);
634 switch (cap->decimation & 0xff) {
640 reg |= ZR060_SR_HScale2;
644 reg |= ZR060_SR_HScale4;
648 switch (cap->decimation >> 8) {
654 reg |= ZR060_SR_VScale;
657 zr36060_write(ptr, ZR060_SR, reg);
659 zr36060_write(ptr, ZR060_BCR_Y, 0x00);
660 zr36060_write(ptr, ZR060_BCR_U, 0x80);
661 zr36060_write(ptr, ZR060_BCR_V, 0x80);
665 reg = norm->Ht - 1; /* Vtotal */
666 zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
667 zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
669 reg = norm->Wt - 1; /* Htotal */
670 zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
671 zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
673 reg = 6 - 1; /* VsyncSize */
674 zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
676 //reg = 30 - 1; /* HsyncSize */
677 ///*CP*/ reg = (zr->params.norm == 1 ? 57 : 68);
679 zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
681 reg = norm->VStart - 1; /* BVstart */
682 zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
684 reg += norm->Ha / 2; /* BVend */
685 zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
686 zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
688 reg = norm->HStart - 1; /* BHstart */
689 zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
691 reg += norm->Wa; /* BHend */
692 zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
693 zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
696 reg = cap->y + norm->VStart; /* Vstart */
697 zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
698 zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
700 reg += cap->height; /* Vend */
701 zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
702 zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
704 reg = cap->x + norm->HStart; /* Hstart */
705 zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
706 zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
708 reg += cap->width; /* Hend */
709 zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
710 zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
713 reg = norm->VStart - 4; /* SVstart */
714 zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
715 zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
717 reg += norm->Ha / 2 + 8; /* SVend */
718 zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
719 zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
721 reg = norm->HStart /*+ 64 */ - 4; /* SHstart */
722 zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
723 zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
725 reg += norm->Wa + 8; /* SHend */
726 zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
727 zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
729 size = ptr->width * ptr->height;
730 /* Target compressed field size in bits: */
731 size = size * 16; /* uncompressed size in bits */
732 /* (Ronald) by default, quality = 100 is a compression
733 * ratio 1:2. Setting low_bitrate (insmod option) sets
734 * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
735 * buz can't handle more at decimation=1... Use low_bitrate if
736 * you have a Buz, unless you know what you're doing */
737 size = size * cap->quality / (low_bitrate ? 400 : 200);
738 /* Lower limit (arbitrary, 1 KB) */
741 /* Upper limit: 7/8 of the code buffers */
742 if (size > ptr->total_code_vol * 7)
743 size = ptr->total_code_vol * 7;
745 ptr->real_code_vol = size >> 3; /* in bytes */
747 /* the MBCVR is the *maximum* block volume, according to the
748 * JPEG ISO specs, this shouldn't be used, since that allows
749 * for the best encoding quality. So set it to it's max value */
750 reg = ptr->max_block_vol;
751 zr36060_write(ptr, ZR060_MBCVR, reg);
756 /* additional control functions */
758 zr36060_control (struct videocodec *codec,
763 struct zr36060 *ptr = (struct zr36060 *) codec->data;
764 int *ival = (int *) data;
766 dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
770 case CODEC_G_STATUS: /* get last status */
771 if (size != sizeof(int))
773 zr36060_read_status(ptr);
777 case CODEC_G_CODEC_MODE:
778 if (size != sizeof(int))
780 *ival = CODEC_MODE_BJPG;
783 case CODEC_S_CODEC_MODE:
784 if (size != sizeof(int))
786 if (*ival != CODEC_MODE_BJPG)
788 /* not needed, do nothing */
793 /* not needed, do nothing */
797 /* not available, give an error */
800 case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */
801 if (size != sizeof(int))
803 *ival = ptr->total_code_vol;
806 case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */
807 if (size != sizeof(int))
809 ptr->total_code_vol = *ival;
810 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
813 case CODEC_G_JPEG_SCALE: /* get scaling factor */
814 if (size != sizeof(int))
816 *ival = zr36060_read_scalefactor(ptr);
819 case CODEC_S_JPEG_SCALE: /* set scaling factor */
820 if (size != sizeof(int))
822 ptr->scalefact = *ival;
825 case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */
826 struct jpeg_app_marker *app = data;
828 if (size != sizeof(struct jpeg_app_marker))
835 case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */
836 struct jpeg_app_marker *app = data;
838 if (size != sizeof(struct jpeg_app_marker))
845 case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */
846 struct jpeg_com_marker *com = data;
848 if (size != sizeof(struct jpeg_com_marker))
855 case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */
856 struct jpeg_com_marker *com = data;
858 if (size != sizeof(struct jpeg_com_marker))
872 /* =========================================================================
873 Exit and unregister function:
875 Deinitializes Zoran's JPEG processor
876 ========================================================================= */
879 zr36060_unset (struct videocodec *codec)
881 struct zr36060 *ptr = codec->data;
884 /* do wee need some codec deinit here, too ???? */
886 dprintk(1, "%s: finished codec #%d\n", ptr->name,
898 /* =========================================================================
899 Setup and registry function:
901 Initializes Zoran's JPEG processor
903 Also sets pixel size, average code size, mode (compr./decompr.)
904 (the given size is determined by the processor with the video interface)
905 ========================================================================= */
908 zr36060_setup (struct videocodec *codec)
913 dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n",
916 if (zr36060_codecs == MAX_CODECS) {
918 KERN_ERR "zr36060: Can't attach more codecs!\n");
922 codec->data = ptr = kmalloc(sizeof(struct zr36060), GFP_KERNEL);
924 dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n");
927 memset(ptr, 0, sizeof(struct zr36060));
929 snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]",
931 ptr->num = zr36060_codecs++;
935 res = zr36060_basic_test(ptr);
937 zr36060_unset(codec);
941 memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
942 memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
944 ptr->bitrate_ctrl = 0; /* 0 or 1 - fixed file size flag
945 * (what is the difference?) */
946 ptr->mode = CODEC_DO_COMPRESSION;
949 ptr->total_code_vol = 16000; /* CHECKME */
950 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
951 ptr->max_block_vol = 240; /* CHECKME, was 120 is 240 */
952 ptr->scalefact = 0x100;
953 ptr->dri = 1; /* CHECKME, was 8 is 1 */
955 /* by default, no COM or APP markers - app should set those */
962 dprintk(1, KERN_INFO "%s: codec attached and running\n",
968 static const struct videocodec zr36060_codec = {
969 .owner = THIS_MODULE,
971 .magic = 0L, // magic not used
973 CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
974 CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
975 .type = CODEC_TYPE_ZR36060,
976 .setup = zr36060_setup, // functionality
977 .unset = zr36060_unset,
978 .set_mode = zr36060_set_mode,
979 .set_video = zr36060_set_video,
980 .control = zr36060_control,
981 // others are not used
984 /* =========================================================================
985 HOOK IN DRIVER AS KERNEL MODULE
986 ========================================================================= */
989 zr36060_init_module (void)
991 //dprintk(1, "zr36060 driver %s\n",ZR060_VERSION);
993 return videocodec_register(&zr36060_codec);
997 zr36060_cleanup_module (void)
999 if (zr36060_codecs) {
1001 "zr36060: something's wrong - %d codecs left somehow.\n",
1005 /* however, we can't just stay alive */
1006 videocodec_unregister(&zr36060_codec);
1009 module_init(zr36060_init_module);
1010 module_exit(zr36060_cleanup_module);
1012 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
1013 MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors "
1015 MODULE_LICENSE("GPL");