1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Zoran ZR36060 basic configuration functions
5 * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/slab.h>
11 #include <linux/delay.h>
13 #include <linux/types.h>
14 #include <linux/wait.h>
16 /* I/O commands, error codes */
19 /* headerfile of this module */
23 #include "videocodec.h"
25 /* it doesn't make sense to have more than 20 or so, just to prevent some unwanted loops */
28 /* amount of chips attached via this driver */
29 static int zr36060_codecs;
31 static bool low_bitrate;
32 module_param(low_bitrate, bool, 0);
33 MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
35 static int zr36060_debug;
36 module_param(zr36060_debug, int, 0);
37 MODULE_PARM_DESC(zr36060_debug, "Debug level (0-4)");
39 #define dprintk(num, format, args...) \
41 if (zr36060_debug >= num) \
42 printk(format, ##args); \
45 /* =========================================================================
46 * Local hardware I/O functions:
47 * read/write via codec layer (registers are located in the master device)
48 * =========================================================================
51 static u8 zr36060_read(struct zr36060 *ptr, u16 reg)
55 // just in case something is wrong...
56 if (ptr->codec->master_data->readreg)
57 value = (ptr->codec->master_data->readreg(ptr->codec, reg)) & 0xff;
59 pr_err("%s: invalid I/O setup, nothing read!\n", ptr->name);
64 static void zr36060_write(struct zr36060 *ptr, u16 reg, u8 value)
66 dprintk(4, "0x%02x @0x%04x\n", value, reg);
68 // just in case something is wrong...
69 if (ptr->codec->master_data->writereg)
70 ptr->codec->master_data->writereg(ptr->codec, reg, value);
72 pr_err("%s: invalid I/O setup, nothing written!\n", ptr->name);
75 /* =========================================================================
76 * Local helper function:
78 * =========================================================================
81 /* status is kept in datastructure */
82 static u8 zr36060_read_status(struct zr36060 *ptr)
84 ptr->status = zr36060_read(ptr, ZR060_CFSR);
90 /* scale factor is kept in datastructure */
91 static u16 zr36060_read_scalefactor(struct zr36060 *ptr)
93 ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
94 (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
96 /* leave 0 selected for an eventually GO from master */
98 return ptr->scalefact;
101 /* wait if codec is ready to proceed (end of processing) or time is over */
102 static void zr36060_wait_end(struct zr36060 *ptr)
106 while (zr36060_read_status(ptr) & ZR060_CFSR_BUSY) {
108 if (i++ > 200000) { // 200ms, there is for sure something wrong!!!
110 "%s: timeout at wait_end (last status: 0x%02x)\n",
111 ptr->name, ptr->status);
117 /* Basic test of "connectivity", writes/reads to/from memory the SOF marker */
118 static int zr36060_basic_test(struct zr36060 *ptr)
120 if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
121 (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
122 pr_err("%s: attach failed, can't connect to jpeg processor!\n", ptr->name);
126 zr36060_wait_end(ptr);
127 if (ptr->status & ZR060_CFSR_BUSY) {
128 pr_err("%s: attach failed, jpeg processor failed (end flag)!\n", ptr->name);
132 return 0; /* looks good! */
135 /* simple loop for pushing the init datasets */
136 static int zr36060_pushit(struct zr36060 *ptr, u16 startreg, u16 len, const char *data)
140 dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
143 zr36060_write(ptr, startreg++, data[i++]);
148 /* =========================================================================
150 * jpeg baseline setup data (you find it on lots places in internet, or just
151 * extract it from any regular .jpg image...)
153 * Could be variable, but until it's not needed it they are just fixed to save
154 * memory. Otherwise expand zr36060 structure with arrays, push the values to
155 * it and initialize from there, as e.g. the linux zr36057/60 driver does it.
156 * =========================================================================
158 static const char zr36060_dqt[0x86] = {
159 0xff, 0xdb, //Marker: DQT
160 0x00, 0x84, //Length: 2*65+2
161 0x00, //Pq,Tq first table
162 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
163 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
164 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
165 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
166 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
167 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
168 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
169 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
170 0x01, //Pq,Tq second table
171 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
172 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 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 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
177 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
178 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
181 static const char zr36060_dht[0x1a4] = {
182 0xff, 0xc4, //Marker: DHT
183 0x01, 0xa2, //Length: 2*AC, 2*DC
184 0x00, //DC first table
185 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
186 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
187 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
188 0x01, //DC second table
189 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
190 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
191 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
192 0x10, //AC first table
193 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
194 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
195 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
196 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
197 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
198 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
199 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
200 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
201 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
202 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
203 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
204 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
205 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
206 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
207 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
208 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
209 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
210 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
211 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
212 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
214 0x11, //AC second table
215 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
216 0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
217 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
218 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
219 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
220 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
221 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
222 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
223 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
224 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
225 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
226 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
227 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
228 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
229 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
230 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
231 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
232 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
233 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
234 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
238 /* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
239 #define NO_OF_COMPONENTS 0x3 //Y,U,V
240 #define BASELINE_PRECISION 0x8 //MCU size (?)
241 static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's QT
242 static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's DC
243 static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's AC
245 /* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
246 static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
247 static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
249 /* SOF (start of frame) segment depends on width, height and sampling ratio of each color component */
250 static int zr36060_set_sof(struct zr36060 *ptr)
252 char sof_data[34]; // max. size of register set
255 dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
256 ptr->width, ptr->height, NO_OF_COMPONENTS);
260 sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
261 sof_data[4] = BASELINE_PRECISION; // only '8' possible with zr36060
262 sof_data[5] = (ptr->height) >> 8;
263 sof_data[6] = (ptr->height) & 0xff;
264 sof_data[7] = (ptr->width) >> 8;
265 sof_data[8] = (ptr->width) & 0xff;
266 sof_data[9] = NO_OF_COMPONENTS;
267 for (i = 0; i < NO_OF_COMPONENTS; i++) {
268 sof_data[10 + (i * 3)] = i; // index identifier
269 sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
270 (ptr->v_samp_ratio[i]); // sampling ratios
271 sof_data[12 + (i * 3)] = zr36060_tq[i]; // Q table selection
273 return zr36060_pushit(ptr, ZR060_SOF_IDX,
274 (3 * NO_OF_COMPONENTS) + 10, sof_data);
277 /* SOS (start of scan) segment depends on the used scan components of each color component */
278 static int zr36060_set_sos(struct zr36060 *ptr)
280 char sos_data[16]; // max. size of register set
283 dprintk(3, "%s: write SOS\n", ptr->name);
287 sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
288 sos_data[4] = NO_OF_COMPONENTS;
289 for (i = 0; i < NO_OF_COMPONENTS; i++) {
290 sos_data[5 + (i * 2)] = i; // index
291 sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
292 zr36060_ta[i]; // AC/DC tbl.sel.
294 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start
295 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
296 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
297 return zr36060_pushit(ptr, ZR060_SOS_IDX,
298 4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
302 /* DRI (define restart interval) */
303 static int zr36060_set_dri(struct zr36060 *ptr)
305 char dri_data[6]; // max. size of register set
307 dprintk(3, "%s: write DRI\n", ptr->name);
312 dri_data[4] = (ptr->dri) >> 8;
313 dri_data[5] = (ptr->dri) & 0xff;
314 return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
317 /* Setup compression/decompression of Zoran's JPEG processor ( see also zoran 36060 manual )
318 * ... sorry for the spaghetti code ...
320 static void zr36060_init(struct zr36060 *ptr)
325 if (ptr->mode == CODEC_DO_COMPRESSION) {
326 dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
328 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
330 /* 060 communicates with 067 in master mode */
331 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
333 /* Compression with or without variable scale factor */
334 /*FIXME: What about ptr->bitrate_ctrl? */
335 zr36060_write(ptr, ZR060_CMR, ZR060_CMR_COMP | ZR060_CMR_PASS2 | ZR060_CMR_BRB);
338 zr36060_write(ptr, ZR060_MBZ, 0x00);
339 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
340 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
342 /* Disable all IRQs - no DataErr means autoreset */
343 zr36060_write(ptr, ZR060_IMR, 0);
345 /* volume control settings */
346 zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
347 zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
349 zr36060_write(ptr, ZR060_AF_HI, 0xff);
350 zr36060_write(ptr, ZR060_AF_M, 0xff);
351 zr36060_write(ptr, ZR060_AF_LO, 0xff);
353 /* setup the variable jpeg tables */
354 sum += zr36060_set_sof(ptr);
355 sum += zr36060_set_sos(ptr);
356 sum += zr36060_set_dri(ptr);
358 /* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
359 sum += zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt), zr36060_dqt);
360 sum += zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
361 zr36060_write(ptr, ZR060_APP_IDX, 0xff);
362 zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
363 zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
364 zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
365 sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60, ptr->app.data) + 4;
366 zr36060_write(ptr, ZR060_COM_IDX, 0xff);
367 zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
368 zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
369 zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
370 sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60, ptr->com.data) + 4;
372 /* setup misc. data for compression (target code sizes) */
374 /* size of compressed code to reach without header data */
375 sum = ptr->real_code_vol - sum;
376 bitcnt = sum << 3; /* need the size in bits */
380 "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
381 ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
382 zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
383 zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
384 tmp = bitcnt & 0xffff;
385 zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
386 zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
388 bitcnt -= bitcnt >> 7; // bits without stuffing
389 bitcnt -= ((bitcnt * 5) >> 6); // bits without eob
392 dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
393 ptr->name, bitcnt, tmp);
394 zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
395 zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
396 tmp = bitcnt & 0xffff;
397 zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
398 zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
400 /* JPEG markers to be included in the compressed stream */
401 zr36060_write(ptr, ZR060_MER,
402 ZR060_MER_DQT | ZR060_MER_DHT |
403 ((ptr->com.len > 0) ? ZR060_MER_COM : 0) |
404 ((ptr->app.len > 0) ? ZR060_MER_APP : 0));
406 /* Setup the Video Frontend */
407 /* Limit pixel range to 16..235 as per CCIR-601 */
408 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
411 dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
413 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
415 /* 060 communicates with 067 in master mode */
416 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
419 zr36060_write(ptr, ZR060_CMR, 0);
422 zr36060_write(ptr, ZR060_MBZ, 0x00);
423 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
424 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
426 /* Disable all IRQs - no DataErr means autoreset */
427 zr36060_write(ptr, ZR060_IMR, 0);
429 /* setup misc. data for expansion */
430 zr36060_write(ptr, ZR060_MER, 0);
432 /* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
433 zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
435 /* Setup the Video Frontend */
436 //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FI_EXT);
437 //this doesn't seem right and doesn't work...
438 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
441 /* Load the tables */
442 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST | ZR060_LOAD_LOAD);
443 zr36060_wait_end(ptr);
444 dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name, ptr->status);
446 if (ptr->status & ZR060_CFSR_BUSY) {
447 pr_err("%s: init aborted!\n", ptr->name);
448 return; // something is wrong, its timed out!!!!
452 /* =========================================================================
453 * CODEC API FUNCTIONS
454 * this functions are accessed by the master via the API structure
455 * =========================================================================
458 /* set compressiion/expansion mode and launches codec -
459 * this should be the last call from the master before starting processing
461 static int zr36060_set_mode(struct videocodec *codec, int mode)
463 struct zr36060 *ptr = (struct zr36060 *)codec->data;
465 dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
467 if (mode != CODEC_DO_EXPANSION && mode != CODEC_DO_COMPRESSION)
476 /* set picture size (norm is ignored as the codec doesn't know about it) */
477 static int zr36060_set_video(struct videocodec *codec, const struct tvnorm *norm,
478 struct vfe_settings *cap, struct vfe_polarity *pol)
480 struct zr36060 *ptr = (struct zr36060 *)codec->data;
484 dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
485 cap->x, cap->y, cap->width, cap->height, cap->decimation);
487 /* if () return -EINVAL;
488 * trust the master driver that it knows what it does - so
489 * we allow invalid startx/y and norm for now ...
491 ptr->width = cap->width / (cap->decimation & 0xff);
492 ptr->height = cap->height / (cap->decimation >> 8);
494 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
496 /* Note that VSPol/HSPol bits in zr36060 have the opposite
497 * meaning of their zr360x7 counterparts with the same names
498 * N.b. for VSPol this is only true if FIVEdge = 0 (default,
499 * left unchanged here - in accordance with datasheet).
501 reg = (!pol->vsync_pol ? ZR060_VPR_VS_POL : 0)
502 | (!pol->hsync_pol ? ZR060_VPR_HS_POL : 0)
503 | (pol->field_pol ? ZR060_VPR_FI_POL : 0)
504 | (pol->blank_pol ? ZR060_VPR_BL_POL : 0)
505 | (pol->subimg_pol ? ZR060_VPR_S_IMG_POL : 0)
506 | (pol->poe_pol ? ZR060_VPR_POE_POL : 0)
507 | (pol->pvalid_pol ? ZR060_VPR_P_VAL_POL : 0)
508 | (pol->vclk_pol ? ZR060_VPR_VCLK_POL : 0);
509 zr36060_write(ptr, ZR060_VPR, reg);
512 switch (cap->decimation & 0xff) {
518 reg |= ZR060_SR_H_SCALE2;
522 reg |= ZR060_SR_H_SCALE4;
526 switch (cap->decimation >> 8) {
532 reg |= ZR060_SR_V_SCALE;
535 zr36060_write(ptr, ZR060_SR, reg);
537 zr36060_write(ptr, ZR060_BCR_Y, 0x00);
538 zr36060_write(ptr, ZR060_BCR_U, 0x80);
539 zr36060_write(ptr, ZR060_BCR_V, 0x80);
543 reg = norm->ht - 1; /* Vtotal */
544 zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
545 zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
547 reg = norm->wt - 1; /* Htotal */
548 zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
549 zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
551 reg = 6 - 1; /* VsyncSize */
552 zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
554 //reg = 30 - 1; /* HsyncSize */
555 ///*CP*/ reg = (zr->params.norm == 1 ? 57 : 68);
557 zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
559 reg = norm->v_start - 1; /* BVstart */
560 zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
562 reg += norm->ha / 2; /* BVend */
563 zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
564 zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
566 reg = norm->h_start - 1; /* BHstart */
567 zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
569 reg += norm->wa; /* BHend */
570 zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
571 zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
574 reg = cap->y + norm->v_start; /* Vstart */
575 zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
576 zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
578 reg += cap->height; /* Vend */
579 zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
580 zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
582 reg = cap->x + norm->h_start; /* Hstart */
583 zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
584 zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
586 reg += cap->width; /* Hend */
587 zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
588 zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
591 reg = norm->v_start - 4; /* SVstart */
592 zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
593 zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
595 reg += norm->ha / 2 + 8; /* SVend */
596 zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
597 zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
599 reg = norm->h_start /*+ 64 */ - 4; /* SHstart */
600 zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
601 zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
603 reg += norm->wa + 8; /* SHend */
604 zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
605 zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
607 size = ptr->width * ptr->height;
608 /* Target compressed field size in bits: */
609 size = size * 16; /* uncompressed size in bits */
610 /* (Ronald) by default, quality = 100 is a compression
611 * ratio 1:2. Setting low_bitrate (insmod option) sets
612 * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
613 * buz can't handle more at decimation=1... Use low_bitrate if
614 * you have a Buz, unless you know what you're doing
616 size = size * cap->quality / (low_bitrate ? 400 : 200);
617 /* Lower limit (arbitrary, 1 KB) */
620 /* Upper limit: 7/8 of the code buffers */
621 if (size > ptr->total_code_vol * 7)
622 size = ptr->total_code_vol * 7;
624 ptr->real_code_vol = size >> 3; /* in bytes */
626 /* the MBCVR is the *maximum* block volume, according to the
627 * JPEG ISO specs, this shouldn't be used, since that allows
628 * for the best encoding quality. So set it to it's max value
630 reg = ptr->max_block_vol;
631 zr36060_write(ptr, ZR060_MBCVR, reg);
636 /* additional control functions */
637 static int zr36060_control(struct videocodec *codec, int type, int size, void *data)
639 struct zr36060 *ptr = (struct zr36060 *)codec->data;
640 int *ival = (int *)data;
642 dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
646 case CODEC_G_STATUS: /* get last status */
647 if (size != sizeof(int))
649 zr36060_read_status(ptr);
653 case CODEC_G_CODEC_MODE:
654 if (size != sizeof(int))
656 *ival = CODEC_MODE_BJPG;
659 case CODEC_S_CODEC_MODE:
660 if (size != sizeof(int))
662 if (*ival != CODEC_MODE_BJPG)
664 /* not needed, do nothing */
669 /* not needed, do nothing */
673 /* not available, give an error */
676 case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */
677 if (size != sizeof(int))
679 *ival = ptr->total_code_vol;
682 case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */
683 if (size != sizeof(int))
685 ptr->total_code_vol = *ival;
686 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
689 case CODEC_G_JPEG_SCALE: /* get scaling factor */
690 if (size != sizeof(int))
692 *ival = zr36060_read_scalefactor(ptr);
695 case CODEC_S_JPEG_SCALE: /* set scaling factor */
696 if (size != sizeof(int))
698 ptr->scalefact = *ival;
701 case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */
702 struct jpeg_app_marker *app = data;
704 if (size != sizeof(struct jpeg_app_marker))
711 case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */
712 struct jpeg_app_marker *app = data;
714 if (size != sizeof(struct jpeg_app_marker))
721 case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */
722 struct jpeg_com_marker *com = data;
724 if (size != sizeof(struct jpeg_com_marker))
731 case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */
732 struct jpeg_com_marker *com = data;
734 if (size != sizeof(struct jpeg_com_marker))
748 /* =========================================================================
749 * Exit and unregister function:
750 * Deinitializes Zoran's JPEG processor
751 * =========================================================================
753 static int zr36060_unset(struct videocodec *codec)
755 struct zr36060 *ptr = codec->data;
758 /* do wee need some codec deinit here, too ???? */
760 dprintk(1, "%s: finished codec #%d\n", ptr->name, ptr->num);
771 /* =========================================================================
772 * Setup and registry function:
773 * Initializes Zoran's JPEG processor
774 * Also sets pixel size, average code size, mode (compr./decompr.)
775 * (the given size is determined by the processor with the video interface)
776 * =========================================================================
778 static int zr36060_setup(struct videocodec *codec)
783 dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n", zr36060_codecs);
785 if (zr36060_codecs == MAX_CODECS) {
786 pr_err("zr36060: Can't attach more codecs!\n");
790 ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
795 snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]", zr36060_codecs);
796 ptr->num = zr36060_codecs++;
800 res = zr36060_basic_test(ptr);
802 zr36060_unset(codec);
806 memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
807 memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
809 ptr->bitrate_ctrl = 0; /* 0 or 1 - fixed file size flag (what is the difference?) */
810 ptr->mode = CODEC_DO_COMPRESSION;
813 ptr->total_code_vol = 16000; /* CHECKME */
814 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
815 ptr->max_block_vol = 240; /* CHECKME, was 120 is 240 */
816 ptr->scalefact = 0x100;
817 ptr->dri = 1; /* CHECKME, was 8 is 1 */
819 /* by default, no COM or APP markers - app should set those */
826 dprintk(1, KERN_INFO "%s: codec attached and running\n", ptr->name);
831 static const struct videocodec zr36060_codec = {
833 .magic = 0L, // magic not used
835 CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
836 CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
837 .type = CODEC_TYPE_ZR36060,
838 .setup = zr36060_setup, // functionality
839 .unset = zr36060_unset,
840 .set_mode = zr36060_set_mode,
841 .set_video = zr36060_set_video,
842 .control = zr36060_control,
843 // others are not used
846 int zr36060_init_module(void)
849 return videocodec_register(&zr36060_codec);
852 void zr36060_cleanup_module(void)
854 if (zr36060_codecs) {
856 "zr36060: something's wrong - %d codecs left somehow.\n",
860 /* however, we can't just stay alive */
861 videocodec_unregister(&zr36060_codec);