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 #define ZR060_VERSION "v0.7"
9
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
13 #include <linux/delay.h>
14
15 #include <linux/types.h>
16 #include <linux/wait.h>
17
18 /* I/O commands, error codes */
19 #include <linux/io.h>
20
21 /* headerfile of this module */
22 #include "zr36060.h"
23
24 /* codec io API */
25 #include "videocodec.h"
26
27 /* it doesn't make sense to have more than 20 or so, just to prevent some unwanted loops */
28 #define MAX_CODECS 20
29
30 /* amount of chips attached via this driver */
31 static int zr36060_codecs;
32
33 static bool low_bitrate;
34 module_param(low_bitrate, bool, 0);
35 MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
36
37 /* debugging is available via module parameter */
38 static int debug;
39 module_param(debug, int, 0);
40 MODULE_PARM_DESC(debug, "Debug level (0-4)");
41
42 #define dprintk(num, format, args...) \
43 do { \
44 if (debug >= num) \
45 printk(format, ##args); \
46 } while (0)
47
48 /* =========================================================================
49 * Local hardware I/O functions:
50 * read/write via codec layer (registers are located in the master device)
51 * =========================================================================
52 */
53
zr36060_read(struct zr36060 * ptr,u16 reg)54 static u8 zr36060_read(struct zr36060 *ptr, u16 reg)
55 {
56 u8 value = 0;
57
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;
61 else
62 pr_err("%s: invalid I/O setup, nothing read!\n", ptr->name);
63
64 return value;
65 }
66
zr36060_write(struct zr36060 * ptr,u16 reg,u8 value)67 static void zr36060_write(struct zr36060 *ptr, u16 reg, u8 value)
68 {
69 dprintk(4, "0x%02x @0x%04x\n", value, reg);
70
71 // just in case something is wrong...
72 if (ptr->codec->master_data->writereg)
73 ptr->codec->master_data->writereg(ptr->codec, reg, value);
74 else
75 pr_err("%s: invalid I/O setup, nothing written!\n", ptr->name);
76 }
77
78 /* =========================================================================
79 * Local helper function:
80 * status read
81 * =========================================================================
82 */
83
84 /* status is kept in datastructure */
zr36060_read_status(struct zr36060 * ptr)85 static u8 zr36060_read_status(struct zr36060 *ptr)
86 {
87 ptr->status = zr36060_read(ptr, ZR060_CFSR);
88
89 zr36060_read(ptr, 0);
90 return ptr->status;
91 }
92
93 /* scale factor is kept in datastructure */
zr36060_read_scalefactor(struct zr36060 * ptr)94 static u16 zr36060_read_scalefactor(struct zr36060 *ptr)
95 {
96 ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
97 (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
98
99 /* leave 0 selected for an eventually GO from master */
100 zr36060_read(ptr, 0);
101 return ptr->scalefact;
102 }
103
104 /* wait if codec is ready to proceed (end of processing) or time is over */
zr36060_wait_end(struct zr36060 * ptr)105 static void zr36060_wait_end(struct zr36060 *ptr)
106 {
107 int i = 0;
108
109 while (zr36060_read_status(ptr) & ZR060_CFSR_BUSY) {
110 udelay(1);
111 if (i++ > 200000) { // 200ms, there is for sure something wrong!!!
112 dprintk(1,
113 "%s: timeout at wait_end (last status: 0x%02x)\n",
114 ptr->name, ptr->status);
115 break;
116 }
117 }
118 }
119
120 /* Basic test of "connectivity", writes/reads to/from memory the SOF marker */
zr36060_basic_test(struct zr36060 * ptr)121 static int zr36060_basic_test(struct zr36060 *ptr)
122 {
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);
126 return -ENXIO;
127 }
128
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);
132 return -EBUSY;
133 }
134
135 return 0; /* looks good! */
136 }
137
138 /* simple loop for pushing the init datasets */
zr36060_pushit(struct zr36060 * ptr,u16 startreg,u16 len,const char * data)139 static int zr36060_pushit(struct zr36060 *ptr, u16 startreg, u16 len, const char *data)
140 {
141 int i = 0;
142
143 dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
144 startreg, len);
145 while (i < len)
146 zr36060_write(ptr, startreg++, data[i++]);
147
148 return i;
149 }
150
151 /* =========================================================================
152 * Basic datasets:
153 * jpeg baseline setup data (you find it on lots places in internet, or just
154 * extract it from any regular .jpg image...)
155 *
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 * =========================================================================
160 */
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
182 };
183
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,
216 0xF8, 0xF9, 0xFA,
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,
238 0xF9, 0xFA
239 };
240
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
247
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 };
251
252 /* SOF (start of frame) segment depends on width, height and sampling ratio of each color component */
zr36060_set_sof(struct zr36060 * ptr)253 static int zr36060_set_sof(struct zr36060 *ptr)
254 {
255 char sof_data[34]; // max. size of register set
256 int i;
257
258 dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
259 ptr->width, ptr->height, NO_OF_COMPONENTS);
260 sof_data[0] = 0xff;
261 sof_data[1] = 0xc0;
262 sof_data[2] = 0x00;
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
275 }
276 return zr36060_pushit(ptr, ZR060_SOF_IDX,
277 (3 * NO_OF_COMPONENTS) + 10, sof_data);
278 }
279
280 /* SOS (start of scan) segment depends on the used scan components of each color component */
zr36060_set_sos(struct zr36060 * ptr)281 static int zr36060_set_sos(struct zr36060 *ptr)
282 {
283 char sos_data[16]; // max. size of register set
284 int i;
285
286 dprintk(3, "%s: write SOS\n", ptr->name);
287 sos_data[0] = 0xff;
288 sos_data[1] = 0xda;
289 sos_data[2] = 0x00;
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.
296 }
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,
302 sos_data);
303 }
304
305 /* DRI (define restart interval) */
zr36060_set_dri(struct zr36060 * ptr)306 static int zr36060_set_dri(struct zr36060 *ptr)
307 {
308 char dri_data[6]; // max. size of register set
309
310 dprintk(3, "%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 */
zr36060_init(struct zr36060 * ptr)323 static void zr36060_init(struct zr36060 *ptr)
324 {
325 int sum = 0;
326 long bitcnt, tmp;
327
328 if (ptr->mode == CODEC_DO_COMPRESSION) {
329 dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
330
331 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
332
333 /* 060 communicates with 067 in master mode */
334 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
335
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);
339
340 /* Must be zero */
341 zr36060_write(ptr, ZR060_MBZ, 0x00);
342 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
343 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
344
345 /* Disable all IRQs - no DataErr means autoreset */
346 zr36060_write(ptr, ZR060_IMR, 0);
347
348 /* volume control settings */
349 zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
350 zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
351
352 zr36060_write(ptr, ZR060_AF_HI, 0xff);
353 zr36060_write(ptr, ZR060_AF_M, 0xff);
354 zr36060_write(ptr, ZR060_AF_LO, 0xff);
355
356 /* setup the variable jpeg tables */
357 sum += zr36060_set_sof(ptr);
358 sum += zr36060_set_sos(ptr);
359 sum += zr36060_set_dri(ptr);
360
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;
374
375 /* setup misc. data for compression (target code sizes) */
376
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 */
380
381 tmp = bitcnt >> 16;
382 dprintk(3,
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);
390
391 bitcnt -= bitcnt >> 7; // bits without stuffing
392 bitcnt -= ((bitcnt * 5) >> 6); // bits without eob
393
394 tmp = bitcnt >> 16;
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);
402
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));
408
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);
412
413 } else {
414 dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
415
416 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
417
418 /* 060 communicates with 067 in master mode */
419 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
420
421 /* Decompression */
422 zr36060_write(ptr, ZR060_CMR, 0);
423
424 /* Must be zero */
425 zr36060_write(ptr, ZR060_MBZ, 0x00);
426 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
427 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
428
429 /* Disable all IRQs - no DataErr means autoreset */
430 zr36060_write(ptr, ZR060_IMR, 0);
431
432 /* setup misc. data for expansion */
433 zr36060_write(ptr, ZR060_MER, 0);
434
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);
437
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);
442 }
443
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);
448
449 if (ptr->status & ZR060_CFSR_BUSY) {
450 pr_err("%s: init aborted!\n", ptr->name);
451 return; // something is wrong, its timed out!!!!
452 }
453 }
454
455 /* =========================================================================
456 * CODEC API FUNCTIONS
457 * this functions are accessed by the master via the API structure
458 * =========================================================================
459 */
460
461 /* set compressiion/expansion mode and launches codec -
462 * this should be the last call from the master before starting processing
463 */
zr36060_set_mode(struct videocodec * codec,int mode)464 static int zr36060_set_mode(struct videocodec *codec, int mode)
465 {
466 struct zr36060 *ptr = (struct zr36060 *)codec->data;
467
468 dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
469
470 if (mode != CODEC_DO_EXPANSION && mode != CODEC_DO_COMPRESSION)
471 return -EINVAL;
472
473 ptr->mode = mode;
474 zr36060_init(ptr);
475
476 return 0;
477 }
478
479 /* set picture size (norm is ignored as the codec doesn't know about it) */
zr36060_set_video(struct videocodec * codec,const struct tvnorm * norm,struct vfe_settings * cap,struct vfe_polarity * pol)480 static int zr36060_set_video(struct videocodec *codec, const struct tvnorm *norm,
481 struct vfe_settings *cap, struct vfe_polarity *pol)
482 {
483 struct zr36060 *ptr = (struct zr36060 *)codec->data;
484 u32 reg;
485 int size;
486
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);
489
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 ...
493 */
494 ptr->width = cap->width / (cap->decimation & 0xff);
495 ptr->height = cap->height / (cap->decimation >> 8);
496
497 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
498
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).
503 */
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);
513
514 reg = 0;
515 switch (cap->decimation & 0xff) {
516 default:
517 case 1:
518 break;
519
520 case 2:
521 reg |= ZR060_SR_H_SCALE2;
522 break;
523
524 case 4:
525 reg |= ZR060_SR_H_SCALE4;
526 break;
527 }
528
529 switch (cap->decimation >> 8) {
530 default:
531 case 1:
532 break;
533
534 case 2:
535 reg |= ZR060_SR_V_SCALE;
536 break;
537 }
538 zr36060_write(ptr, ZR060_SR, reg);
539
540 zr36060_write(ptr, ZR060_BCR_Y, 0x00);
541 zr36060_write(ptr, ZR060_BCR_U, 0x80);
542 zr36060_write(ptr, ZR060_BCR_V, 0x80);
543
544 /* sync generator */
545
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);
549
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);
553
554 reg = 6 - 1; /* VsyncSize */
555 zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
556
557 //reg = 30 - 1; /* HsyncSize */
558 ///*CP*/ reg = (zr->params.norm == 1 ? 57 : 68);
559 reg = 68;
560 zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
561
562 reg = norm->v_start - 1; /* BVstart */
563 zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
564
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);
568
569 reg = norm->h_start - 1; /* BHstart */
570 zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
571
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);
575
576 /* active area */
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);
580
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);
584
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);
588
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);
592
593 /* subimage area */
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);
597
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);
601
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);
605
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);
609
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
618 */
619 size = size * cap->quality / (low_bitrate ? 400 : 200);
620 /* Lower limit (arbitrary, 1 KB) */
621 if (size < 8192)
622 size = 8192;
623 /* Upper limit: 7/8 of the code buffers */
624 if (size > ptr->total_code_vol * 7)
625 size = ptr->total_code_vol * 7;
626
627 ptr->real_code_vol = size >> 3; /* in bytes */
628
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
632 */
633 reg = ptr->max_block_vol;
634 zr36060_write(ptr, ZR060_MBCVR, reg);
635
636 return 0;
637 }
638
639 /* additional control functions */
zr36060_control(struct videocodec * codec,int type,int size,void * data)640 static int zr36060_control(struct videocodec *codec, int type, int size, void *data)
641 {
642 struct zr36060 *ptr = (struct zr36060 *)codec->data;
643 int *ival = (int *)data;
644
645 dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
646 size);
647
648 switch (type) {
649 case CODEC_G_STATUS: /* get last status */
650 if (size != sizeof(int))
651 return -EFAULT;
652 zr36060_read_status(ptr);
653 *ival = ptr->status;
654 break;
655
656 case CODEC_G_CODEC_MODE:
657 if (size != sizeof(int))
658 return -EFAULT;
659 *ival = CODEC_MODE_BJPG;
660 break;
661
662 case CODEC_S_CODEC_MODE:
663 if (size != sizeof(int))
664 return -EFAULT;
665 if (*ival != CODEC_MODE_BJPG)
666 return -EINVAL;
667 /* not needed, do nothing */
668 return 0;
669
670 case CODEC_G_VFE:
671 case CODEC_S_VFE:
672 /* not needed, do nothing */
673 return 0;
674
675 case CODEC_S_MMAP:
676 /* not available, give an error */
677 return -ENXIO;
678
679 case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */
680 if (size != sizeof(int))
681 return -EFAULT;
682 *ival = ptr->total_code_vol;
683 break;
684
685 case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */
686 if (size != sizeof(int))
687 return -EFAULT;
688 ptr->total_code_vol = *ival;
689 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
690 break;
691
692 case CODEC_G_JPEG_SCALE: /* get scaling factor */
693 if (size != sizeof(int))
694 return -EFAULT;
695 *ival = zr36060_read_scalefactor(ptr);
696 break;
697
698 case CODEC_S_JPEG_SCALE: /* set scaling factor */
699 if (size != sizeof(int))
700 return -EFAULT;
701 ptr->scalefact = *ival;
702 break;
703
704 case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */
705 struct jpeg_app_marker *app = data;
706
707 if (size != sizeof(struct jpeg_app_marker))
708 return -EFAULT;
709
710 *app = ptr->app;
711 break;
712 }
713
714 case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */
715 struct jpeg_app_marker *app = data;
716
717 if (size != sizeof(struct jpeg_app_marker))
718 return -EFAULT;
719
720 ptr->app = *app;
721 break;
722 }
723
724 case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */
725 struct jpeg_com_marker *com = data;
726
727 if (size != sizeof(struct jpeg_com_marker))
728 return -EFAULT;
729
730 *com = ptr->com;
731 break;
732 }
733
734 case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */
735 struct jpeg_com_marker *com = data;
736
737 if (size != sizeof(struct jpeg_com_marker))
738 return -EFAULT;
739
740 ptr->com = *com;
741 break;
742 }
743
744 default:
745 return -EINVAL;
746 }
747
748 return size;
749 }
750
751 /* =========================================================================
752 * Exit and unregister function:
753 * Deinitializes Zoran's JPEG processor
754 * =========================================================================
755 */
zr36060_unset(struct videocodec * codec)756 static int zr36060_unset(struct videocodec *codec)
757 {
758 struct zr36060 *ptr = codec->data;
759
760 if (ptr) {
761 /* do wee need some codec deinit here, too ???? */
762
763 dprintk(1, "%s: finished codec #%d\n", ptr->name, ptr->num);
764 kfree(ptr);
765 codec->data = NULL;
766
767 zr36060_codecs--;
768 return 0;
769 }
770
771 return -EFAULT;
772 }
773
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 * =========================================================================
780 */
zr36060_setup(struct videocodec * codec)781 static int zr36060_setup(struct videocodec *codec)
782 {
783 struct zr36060 *ptr;
784 int res;
785
786 dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n", zr36060_codecs);
787
788 if (zr36060_codecs == MAX_CODECS) {
789 pr_err("zr36060: Can't attach more codecs!\n");
790 return -ENOSPC;
791 }
792 //mem structure init
793 ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
794 codec->data = ptr;
795 if (!ptr)
796 return -ENOMEM;
797
798 snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]", zr36060_codecs);
799 ptr->num = zr36060_codecs++;
800 ptr->codec = codec;
801
802 //testing
803 res = zr36060_basic_test(ptr);
804 if (res < 0) {
805 zr36060_unset(codec);
806 return res;
807 }
808 //final setup
809 memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
810 memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
811
812 ptr->bitrate_ctrl = 0; /* 0 or 1 - fixed file size flag (what is the difference?) */
813 ptr->mode = CODEC_DO_COMPRESSION;
814 ptr->width = 384;
815 ptr->height = 288;
816 ptr->total_code_vol = 16000; /* CHECKME */
817 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
818 ptr->max_block_vol = 240; /* CHECKME, was 120 is 240 */
819 ptr->scalefact = 0x100;
820 ptr->dri = 1; /* CHECKME, was 8 is 1 */
821
822 /* by default, no COM or APP markers - app should set those */
823 ptr->com.len = 0;
824 ptr->app.appn = 0;
825 ptr->app.len = 0;
826
827 zr36060_init(ptr);
828
829 dprintk(1, KERN_INFO "%s: codec attached and running\n", ptr->name);
830
831 return 0;
832 }
833
834 static const struct videocodec zr36060_codec = {
835 .owner = THIS_MODULE,
836 .name = "zr36060",
837 .magic = 0L, // magic not used
838 .flags =
839 CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
840 CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
841 .type = CODEC_TYPE_ZR36060,
842 .setup = zr36060_setup, // functionality
843 .unset = zr36060_unset,
844 .set_mode = zr36060_set_mode,
845 .set_video = zr36060_set_video,
846 .control = zr36060_control,
847 // others are not used
848 };
849
zr36060_init_module(void)850 static int __init zr36060_init_module(void)
851 {
852 zr36060_codecs = 0;
853 return videocodec_register(&zr36060_codec);
854 }
855
zr36060_cleanup_module(void)856 static void __exit zr36060_cleanup_module(void)
857 {
858 if (zr36060_codecs) {
859 dprintk(1,
860 "zr36060: something's wrong - %d codecs left somehow.\n",
861 zr36060_codecs);
862 }
863
864 /* however, we can't just stay alive */
865 videocodec_unregister(&zr36060_codec);
866 }
867
868 module_init(zr36060_init_module);
869 module_exit(zr36060_cleanup_module);
870
871 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
872 MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors " ZR060_VERSION);
873 MODULE_LICENSE("GPL");
874