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 #define ZR060_VERSION "v0.7"
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
13 #include <linux/delay.h>
15 #include <linux/types.h>
16 #include <linux/wait.h>
18 /* I/O commands, error codes */
21 /* headerfile of this module */
25 #include "videocodec.h"
27 /* it doesn't make sense to have more than 20 or so, just to prevent some unwanted loops */
30 /* amount of chips attached via this driver */
31 static int zr36060_codecs;
33 static bool low_bitrate;
34 module_param(low_bitrate, bool, 0);
35 MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
37 /* debugging is available via module parameter */
39 module_param(debug, int, 0);
40 MODULE_PARM_DESC(debug, "Debug level (0-4)");
42 #define dprintk(num, format, args...) \
45 printk(format, ##args); \
48 /* =========================================================================
49 * Local hardware I/O functions:
50 * read/write via codec layer (registers are located in the master device)
51 * =========================================================================
54 static u8 zr36060_read(struct zr36060 *ptr, u16 reg)
58 // just in case something is wrong...
59 if (ptr->codec->master_data->readreg)
60 value = (ptr->codec->master_data->readreg(ptr->codec, reg)) & 0xff;
62 pr_err("%s: invalid I/O setup, nothing read!\n", ptr->name);
67 static void zr36060_write(struct zr36060 *ptr, u16 reg, u8 value)
69 dprintk(4, "0x%02x @0x%04x\n", value, reg);
71 // just in case something is wrong...
72 if (ptr->codec->master_data->writereg)
73 ptr->codec->master_data->writereg(ptr->codec, reg, value);
75 pr_err("%s: invalid I/O setup, nothing written!\n", ptr->name);
78 /* =========================================================================
79 * Local helper function:
81 * =========================================================================
84 /* status is kept in datastructure */
85 static u8 zr36060_read_status(struct zr36060 *ptr)
87 ptr->status = zr36060_read(ptr, ZR060_CFSR);
93 /* scale factor is kept in datastructure */
94 static u16 zr36060_read_scalefactor(struct zr36060 *ptr)
96 ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
97 (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
99 /* leave 0 selected for an eventually GO from master */
100 zr36060_read(ptr, 0);
101 return ptr->scalefact;
104 /* wait if codec is ready to proceed (end of processing) or time is over */
105 static void zr36060_wait_end(struct zr36060 *ptr)
109 while (zr36060_read_status(ptr) & ZR060_CFSR_BUSY) {
111 if (i++ > 200000) { // 200ms, there is for sure something wrong!!!
113 "%s: timeout at wait_end (last status: 0x%02x)\n",
114 ptr->name, ptr->status);
120 /* Basic test of "connectivity", writes/reads to/from memory the SOF marker */
121 static int zr36060_basic_test(struct zr36060 *ptr)
123 if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
124 (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
125 pr_err("%s: attach failed, can't connect to jpeg processor!\n", ptr->name);
129 zr36060_wait_end(ptr);
130 if (ptr->status & ZR060_CFSR_BUSY) {
131 pr_err("%s: attach failed, jpeg processor failed (end flag)!\n", ptr->name);
135 return 0; /* looks good! */
138 /* simple loop for pushing the init datasets */
139 static int zr36060_pushit(struct zr36060 *ptr, u16 startreg, u16 len, const char *data)
143 dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
146 zr36060_write(ptr, startreg++, data[i++]);
151 /* =========================================================================
153 * jpeg baseline setup data (you find it on lots places in internet, or just
154 * extract it from any regular .jpg image...)
156 * Could be variable, but until it's not needed it they are just fixed to save
157 * memory. Otherwise expand zr36060 structure with arrays, push the values to
158 * it and initialize from there, as e.g. the linux zr36057/60 driver does it.
159 * =========================================================================
161 static const char zr36060_dqt[0x86] = {
162 0xff, 0xdb, //Marker: DQT
163 0x00, 0x84, //Length: 2*65+2
164 0x00, //Pq,Tq first table
165 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
166 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
167 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
168 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
169 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
170 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
171 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
172 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
173 0x01, //Pq,Tq second table
174 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
175 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 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,
179 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
180 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
181 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
184 static const char zr36060_dht[0x1a4] = {
185 0xff, 0xc4, //Marker: DHT
186 0x01, 0xa2, //Length: 2*AC, 2*DC
187 0x00, //DC first table
188 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
189 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
190 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
191 0x01, //DC second table
192 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
193 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
194 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
195 0x10, //AC first table
196 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
197 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
198 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
199 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
200 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
201 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
202 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
203 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
204 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
205 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
206 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
207 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
208 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
209 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
210 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
211 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
212 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
213 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
214 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
215 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
217 0x11, //AC second table
218 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
219 0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
220 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
221 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
222 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
223 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
224 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
225 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
226 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
227 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
228 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
229 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
230 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
231 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
232 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
233 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
234 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
235 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
236 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
237 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
241 /* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
242 #define NO_OF_COMPONENTS 0x3 //Y,U,V
243 #define BASELINE_PRECISION 0x8 //MCU size (?)
244 static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's QT
245 static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's DC
246 static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's AC
248 /* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
249 static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
250 static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
252 /* SOF (start of frame) segment depends on width, height and sampling ratio of each color component */
253 static int zr36060_set_sof(struct zr36060 *ptr)
255 char sof_data[34]; // max. size of register set
258 dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
259 ptr->width, ptr->height, NO_OF_COMPONENTS);
263 sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
264 sof_data[4] = BASELINE_PRECISION; // only '8' possible with zr36060
265 sof_data[5] = (ptr->height) >> 8;
266 sof_data[6] = (ptr->height) & 0xff;
267 sof_data[7] = (ptr->width) >> 8;
268 sof_data[8] = (ptr->width) & 0xff;
269 sof_data[9] = NO_OF_COMPONENTS;
270 for (i = 0; i < NO_OF_COMPONENTS; i++) {
271 sof_data[10 + (i * 3)] = i; // index identifier
272 sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
273 (ptr->v_samp_ratio[i]); // sampling ratios
274 sof_data[12 + (i * 3)] = zr36060_tq[i]; // Q table selection
276 return zr36060_pushit(ptr, ZR060_SOF_IDX,
277 (3 * NO_OF_COMPONENTS) + 10, sof_data);
280 /* SOS (start of scan) segment depends on the used scan components of each color component */
281 static int zr36060_set_sos(struct zr36060 *ptr)
283 char sos_data[16]; // max. size of register set
286 dprintk(3, "%s: write SOS\n", ptr->name);
290 sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
291 sos_data[4] = NO_OF_COMPONENTS;
292 for (i = 0; i < NO_OF_COMPONENTS; i++) {
293 sos_data[5 + (i * 2)] = i; // index
294 sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
295 zr36060_ta[i]; // AC/DC tbl.sel.
297 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start
298 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
299 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
300 return zr36060_pushit(ptr, ZR060_SOS_IDX,
301 4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
305 /* DRI (define restart interval) */
306 static int zr36060_set_dri(struct zr36060 *ptr)
308 char dri_data[6]; // max. size of register set
310 dprintk(3, "%s: write DRI\n", ptr->name);
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);
320 /* Setup compression/decompression of Zoran's JPEG processor ( see also zoran 36060 manual )
321 * ... sorry for the spaghetti code ...
323 static void zr36060_init(struct zr36060 *ptr)
328 if (ptr->mode == CODEC_DO_COMPRESSION) {
329 dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
331 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
333 /* 060 communicates with 067 in master mode */
334 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
336 /* Compression with or without variable scale factor */
337 /*FIXME: What about ptr->bitrate_ctrl? */
338 zr36060_write(ptr, ZR060_CMR, ZR060_CMR_COMP | ZR060_CMR_PASS2 | ZR060_CMR_BRB);
341 zr36060_write(ptr, ZR060_MBZ, 0x00);
342 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
343 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
345 /* Disable all IRQs - no DataErr means autoreset */
346 zr36060_write(ptr, ZR060_IMR, 0);
348 /* volume control settings */
349 zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
350 zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
352 zr36060_write(ptr, ZR060_AF_HI, 0xff);
353 zr36060_write(ptr, ZR060_AF_M, 0xff);
354 zr36060_write(ptr, ZR060_AF_LO, 0xff);
356 /* setup the variable jpeg tables */
357 sum += zr36060_set_sof(ptr);
358 sum += zr36060_set_sos(ptr);
359 sum += zr36060_set_dri(ptr);
361 /* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
362 sum += zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt), zr36060_dqt);
363 sum += zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
364 zr36060_write(ptr, ZR060_APP_IDX, 0xff);
365 zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
366 zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
367 zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
368 sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60, ptr->app.data) + 4;
369 zr36060_write(ptr, ZR060_COM_IDX, 0xff);
370 zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
371 zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
372 zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
373 sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60, ptr->com.data) + 4;
375 /* setup misc. data for compression (target code sizes) */
377 /* size of compressed code to reach without header data */
378 sum = ptr->real_code_vol - sum;
379 bitcnt = sum << 3; /* need the size in bits */
383 "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
384 ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
385 zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
386 zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
387 tmp = bitcnt & 0xffff;
388 zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
389 zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
391 bitcnt -= bitcnt >> 7; // bits without stuffing
392 bitcnt -= ((bitcnt * 5) >> 6); // bits without eob
395 dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
396 ptr->name, bitcnt, tmp);
397 zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
398 zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
399 tmp = bitcnt & 0xffff;
400 zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
401 zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
403 /* JPEG markers to be included in the compressed stream */
404 zr36060_write(ptr, ZR060_MER,
405 ZR060_MER_DQT | ZR060_MER_DHT |
406 ((ptr->com.len > 0) ? ZR060_MER_COM : 0) |
407 ((ptr->app.len > 0) ? ZR060_MER_APP : 0));
409 /* Setup the Video Frontend */
410 /* Limit pixel range to 16..235 as per CCIR-601 */
411 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
414 dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
416 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
418 /* 060 communicates with 067 in master mode */
419 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
422 zr36060_write(ptr, ZR060_CMR, 0);
425 zr36060_write(ptr, ZR060_MBZ, 0x00);
426 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
427 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
429 /* Disable all IRQs - no DataErr means autoreset */
430 zr36060_write(ptr, ZR060_IMR, 0);
432 /* setup misc. data for expansion */
433 zr36060_write(ptr, ZR060_MER, 0);
435 /* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
436 zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
438 /* Setup the Video Frontend */
439 //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FI_EXT);
440 //this doesn't seem right and doesn't work...
441 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
444 /* Load the tables */
445 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST | ZR060_LOAD_LOAD);
446 zr36060_wait_end(ptr);
447 dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name, ptr->status);
449 if (ptr->status & ZR060_CFSR_BUSY) {
450 pr_err("%s: init aborted!\n", ptr->name);
451 return; // something is wrong, its timed out!!!!
455 /* =========================================================================
456 * CODEC API FUNCTIONS
457 * this functions are accessed by the master via the API structure
458 * =========================================================================
461 /* set compressiion/expansion mode and launches codec -
462 * this should be the last call from the master before starting processing
464 static int zr36060_set_mode(struct videocodec *codec, int mode)
466 struct zr36060 *ptr = (struct zr36060 *)codec->data;
468 dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
470 if (mode != CODEC_DO_EXPANSION && mode != CODEC_DO_COMPRESSION)
479 /* set picture size (norm is ignored as the codec doesn't know about it) */
480 static int zr36060_set_video(struct videocodec *codec, const struct tvnorm *norm,
481 struct vfe_settings *cap, struct vfe_polarity *pol)
483 struct zr36060 *ptr = (struct zr36060 *)codec->data;
487 dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
488 cap->x, cap->y, cap->width, cap->height, cap->decimation);
490 /* if () return -EINVAL;
491 * trust the master driver that it knows what it does - so
492 * we allow invalid startx/y and norm for now ...
494 ptr->width = cap->width / (cap->decimation & 0xff);
495 ptr->height = cap->height / (cap->decimation >> 8);
497 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
499 /* Note that VSPol/HSPol bits in zr36060 have the opposite
500 * meaning of their zr360x7 counterparts with the same names
501 * N.b. for VSPol this is only true if FIVEdge = 0 (default,
502 * left unchanged here - in accordance with datasheet).
504 reg = (!pol->vsync_pol ? ZR060_VPR_VS_POL : 0)
505 | (!pol->hsync_pol ? ZR060_VPR_HS_POL : 0)
506 | (pol->field_pol ? ZR060_VPR_FI_POL : 0)
507 | (pol->blank_pol ? ZR060_VPR_BL_POL : 0)
508 | (pol->subimg_pol ? ZR060_VPR_S_IMG_POL : 0)
509 | (pol->poe_pol ? ZR060_VPR_POE_POL : 0)
510 | (pol->pvalid_pol ? ZR060_VPR_P_VAL_POL : 0)
511 | (pol->vclk_pol ? ZR060_VPR_VCLK_POL : 0);
512 zr36060_write(ptr, ZR060_VPR, reg);
515 switch (cap->decimation & 0xff) {
521 reg |= ZR060_SR_H_SCALE2;
525 reg |= ZR060_SR_H_SCALE4;
529 switch (cap->decimation >> 8) {
535 reg |= ZR060_SR_V_SCALE;
538 zr36060_write(ptr, ZR060_SR, reg);
540 zr36060_write(ptr, ZR060_BCR_Y, 0x00);
541 zr36060_write(ptr, ZR060_BCR_U, 0x80);
542 zr36060_write(ptr, ZR060_BCR_V, 0x80);
546 reg = norm->ht - 1; /* Vtotal */
547 zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
548 zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
550 reg = norm->wt - 1; /* Htotal */
551 zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
552 zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
554 reg = 6 - 1; /* VsyncSize */
555 zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
557 //reg = 30 - 1; /* HsyncSize */
558 ///*CP*/ reg = (zr->params.norm == 1 ? 57 : 68);
560 zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
562 reg = norm->v_start - 1; /* BVstart */
563 zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
565 reg += norm->ha / 2; /* BVend */
566 zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
567 zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
569 reg = norm->h_start - 1; /* BHstart */
570 zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
572 reg += norm->wa; /* BHend */
573 zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
574 zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
577 reg = cap->y + norm->v_start; /* Vstart */
578 zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
579 zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
581 reg += cap->height; /* Vend */
582 zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
583 zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
585 reg = cap->x + norm->h_start; /* Hstart */
586 zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
587 zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
589 reg += cap->width; /* Hend */
590 zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
591 zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
594 reg = norm->v_start - 4; /* SVstart */
595 zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
596 zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
598 reg += norm->ha / 2 + 8; /* SVend */
599 zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
600 zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
602 reg = norm->h_start /*+ 64 */ - 4; /* SHstart */
603 zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
604 zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
606 reg += norm->wa + 8; /* SHend */
607 zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
608 zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
610 size = ptr->width * ptr->height;
611 /* Target compressed field size in bits: */
612 size = size * 16; /* uncompressed size in bits */
613 /* (Ronald) by default, quality = 100 is a compression
614 * ratio 1:2. Setting low_bitrate (insmod option) sets
615 * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
616 * buz can't handle more at decimation=1... Use low_bitrate if
617 * you have a Buz, unless you know what you're doing
619 size = size * cap->quality / (low_bitrate ? 400 : 200);
620 /* Lower limit (arbitrary, 1 KB) */
623 /* Upper limit: 7/8 of the code buffers */
624 if (size > ptr->total_code_vol * 7)
625 size = ptr->total_code_vol * 7;
627 ptr->real_code_vol = size >> 3; /* in bytes */
629 /* the MBCVR is the *maximum* block volume, according to the
630 * JPEG ISO specs, this shouldn't be used, since that allows
631 * for the best encoding quality. So set it to it's max value
633 reg = ptr->max_block_vol;
634 zr36060_write(ptr, ZR060_MBCVR, reg);
639 /* additional control functions */
640 static int zr36060_control(struct videocodec *codec, int type, int size, void *data)
642 struct zr36060 *ptr = (struct zr36060 *)codec->data;
643 int *ival = (int *)data;
645 dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
649 case CODEC_G_STATUS: /* get last status */
650 if (size != sizeof(int))
652 zr36060_read_status(ptr);
656 case CODEC_G_CODEC_MODE:
657 if (size != sizeof(int))
659 *ival = CODEC_MODE_BJPG;
662 case CODEC_S_CODEC_MODE:
663 if (size != sizeof(int))
665 if (*ival != CODEC_MODE_BJPG)
667 /* not needed, do nothing */
672 /* not needed, do nothing */
676 /* not available, give an error */
679 case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */
680 if (size != sizeof(int))
682 *ival = ptr->total_code_vol;
685 case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */
686 if (size != sizeof(int))
688 ptr->total_code_vol = *ival;
689 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
692 case CODEC_G_JPEG_SCALE: /* get scaling factor */
693 if (size != sizeof(int))
695 *ival = zr36060_read_scalefactor(ptr);
698 case CODEC_S_JPEG_SCALE: /* set scaling factor */
699 if (size != sizeof(int))
701 ptr->scalefact = *ival;
704 case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */
705 struct jpeg_app_marker *app = data;
707 if (size != sizeof(struct jpeg_app_marker))
714 case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */
715 struct jpeg_app_marker *app = data;
717 if (size != sizeof(struct jpeg_app_marker))
724 case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */
725 struct jpeg_com_marker *com = data;
727 if (size != sizeof(struct jpeg_com_marker))
734 case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */
735 struct jpeg_com_marker *com = data;
737 if (size != sizeof(struct jpeg_com_marker))
751 /* =========================================================================
752 * Exit and unregister function:
753 * Deinitializes Zoran's JPEG processor
754 * =========================================================================
756 static int zr36060_unset(struct videocodec *codec)
758 struct zr36060 *ptr = codec->data;
761 /* do wee need some codec deinit here, too ???? */
763 dprintk(1, "%s: finished codec #%d\n", ptr->name, ptr->num);
774 /* =========================================================================
775 * Setup and registry function:
776 * Initializes Zoran's JPEG processor
777 * Also sets pixel size, average code size, mode (compr./decompr.)
778 * (the given size is determined by the processor with the video interface)
779 * =========================================================================
781 static int zr36060_setup(struct videocodec *codec)
786 dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n", zr36060_codecs);
788 if (zr36060_codecs == MAX_CODECS) {
789 pr_err("zr36060: Can't attach more codecs!\n");
793 codec->data = ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
797 snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]", zr36060_codecs);
798 ptr->num = zr36060_codecs++;
802 res = zr36060_basic_test(ptr);
804 zr36060_unset(codec);
808 memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
809 memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
811 ptr->bitrate_ctrl = 0; /* 0 or 1 - fixed file size flag (what is the difference?) */
812 ptr->mode = CODEC_DO_COMPRESSION;
815 ptr->total_code_vol = 16000; /* CHECKME */
816 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
817 ptr->max_block_vol = 240; /* CHECKME, was 120 is 240 */
818 ptr->scalefact = 0x100;
819 ptr->dri = 1; /* CHECKME, was 8 is 1 */
821 /* by default, no COM or APP markers - app should set those */
828 dprintk(1, KERN_INFO "%s: codec attached and running\n", ptr->name);
833 static const struct videocodec zr36060_codec = {
834 .owner = THIS_MODULE,
836 .magic = 0L, // magic not used
838 CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
839 CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
840 .type = CODEC_TYPE_ZR36060,
841 .setup = zr36060_setup, // functionality
842 .unset = zr36060_unset,
843 .set_mode = zr36060_set_mode,
844 .set_video = zr36060_set_video,
845 .control = zr36060_control,
846 // others are not used
849 static int __init zr36060_init_module(void)
852 return videocodec_register(&zr36060_codec);
855 static void __exit zr36060_cleanup_module(void)
857 if (zr36060_codecs) {
859 "zr36060: something's wrong - %d codecs left somehow.\n",
863 /* however, we can't just stay alive */
864 videocodec_unregister(&zr36060_codec);
867 module_init(zr36060_init_module);
868 module_exit(zr36060_cleanup_module);
870 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
871 MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors " ZR060_VERSION);
872 MODULE_LICENSE("GPL");