1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#define ZR060_VERSION "v0.7"
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/delay.h>
33
34#include <linux/types.h>
35#include <linux/wait.h>
36
37
38
39
40
41#include <asm/io.h>
42
43
44
45#include "zr36060.h"
46
47
48#include "videocodec.h"
49
50
51
52#define MAX_CODECS 20
53
54
55static int zr36060_codecs = 0;
56
57static int low_bitrate = 0;
58module_param(low_bitrate, bool, 0);
59MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
60
61
62static int debug = 0;
63module_param(debug, int, 0);
64MODULE_PARM_DESC(debug, "Debug level (0-4)");
65
66#define dprintk(num, format, args...) \
67 do { \
68 if (debug >= num) \
69 printk(format, ##args); \
70 } while (0)
71
72
73
74
75
76
77
78
79static u8
80zr36060_read (struct zr36060 *ptr,
81 u16 reg)
82{
83 u8 value = 0;
84
85
86 if (ptr->codec->master_data->readreg)
87 value = (ptr->codec->master_data->readreg(ptr->codec,
88 reg)) & 0xff;
89 else
90 dprintk(1,
91 KERN_ERR "%s: invalid I/O setup, nothing read!\n",
92 ptr->name);
93
94
95
96 return value;
97}
98
99static void
100zr36060_write(struct zr36060 *ptr,
101 u16 reg,
102 u8 value)
103{
104
105 dprintk(4, "0x%02x @0x%04x\n", value, reg);
106
107
108 if (ptr->codec->master_data->writereg)
109 ptr->codec->master_data->writereg(ptr->codec, reg, value);
110 else
111 dprintk(1,
112 KERN_ERR
113 "%s: invalid I/O setup, nothing written!\n",
114 ptr->name);
115}
116
117
118
119
120
121
122
123
124static u8
125zr36060_read_status (struct zr36060 *ptr)
126{
127 ptr->status = zr36060_read(ptr, ZR060_CFSR);
128
129 zr36060_read(ptr, 0);
130 return ptr->status;
131}
132
133
134
135
136
137
138
139
140static u16
141zr36060_read_scalefactor (struct zr36060 *ptr)
142{
143 ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
144 (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
145
146
147 zr36060_read(ptr, 0);
148 return ptr->scalefact;
149}
150
151
152
153
154
155
156
157static void
158zr36060_wait_end (struct zr36060 *ptr)
159{
160 int i = 0;
161
162 while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) {
163 udelay(1);
164 if (i++ > 200000) {
165 dprintk(1,
166 "%s: timout at wait_end (last status: 0x%02x)\n",
167 ptr->name, ptr->status);
168 break;
169 }
170 }
171}
172
173
174
175
176
177
178
179static int
180zr36060_basic_test (struct zr36060 *ptr)
181{
182 if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
183 (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
184 dprintk(1,
185 KERN_ERR
186 "%s: attach failed, can't connect to jpeg processor!\n",
187 ptr->name);
188 return -ENXIO;
189 }
190
191 zr36060_wait_end(ptr);
192 if (ptr->status & ZR060_CFSR_Busy) {
193 dprintk(1,
194 KERN_ERR
195 "%s: attach failed, jpeg processor failed (end flag)!\n",
196 ptr->name);
197 return -EBUSY;
198 }
199
200 return 0;
201}
202
203
204
205
206
207
208
209static int
210zr36060_pushit (struct zr36060 *ptr,
211 u16 startreg,
212 u16 len,
213 const char *data)
214{
215 int i = 0;
216
217 dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
218 startreg, len);
219 while (i < len) {
220 zr36060_write(ptr, startreg++, data[i++]);
221 }
222
223 return i;
224}
225
226
227
228
229
230
231
232
233
234
235
236
237static const char zr36060_dqt[0x86] = {
238 0xff, 0xdb,
239 0x00, 0x84,
240 0x00,
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,
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
258};
259
260static const char zr36060_dht[0x1a4] = {
261 0xff, 0xc4,
262 0x01, 0xa2,
263 0x00,
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,
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,
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,
292 0xF8, 0xF9, 0xFA,
293 0x11,
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,
314 0xF9, 0xFA
315};
316
317
318#define NO_OF_COMPONENTS 0x3
319#define BASELINE_PRECISION 0x8
320static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
321static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
322static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
323
324
325static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
326static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
327
328
329
330
331
332
333
334
335
336
337
338
339
340static int
341zr36060_set_sof (struct zr36060 *ptr)
342{
343 char sof_data[34];
344 int i;
345
346 dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
347 ptr->width, ptr->height, NO_OF_COMPONENTS);
348 sof_data[0] = 0xff;
349 sof_data[1] = 0xc0;
350 sof_data[2] = 0x00;
351 sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
352 sof_data[4] = BASELINE_PRECISION;
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;
360 sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
361 (ptr->v_samp_ratio[i]);
362 sof_data[12 + (i * 3)] = zr36060_tq[i];
363 }
364 return zr36060_pushit(ptr, ZR060_SOF_IDX,
365 (3 * NO_OF_COMPONENTS) + 10, sof_data);
366}
367
368
369
370
371
372
373static int
374zr36060_set_sos (struct zr36060 *ptr)
375{
376 char sos_data[16];
377 int i;
378
379 dprintk(3, "%s: write SOS\n", ptr->name);
380 sos_data[0] = 0xff;
381 sos_data[1] = 0xda;
382 sos_data[2] = 0x00;
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;
387 sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
388 zr36060_ta[i];
389 }
390 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;
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,
395 sos_data);
396}
397
398
399
400
401
402static int
403zr36060_set_dri (struct zr36060 *ptr)
404{
405 char dri_data[6];
406
407 dprintk(3, "%s: write DRI\n", ptr->name);
408 dri_data[0] = 0xff;
409 dri_data[1] = 0xdd;
410 dri_data[2] = 0x00;
411 dri_data[3] = 0x04;
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);
415}
416
417
418
419
420
421
422
423
424
425static void
426zr36060_init (struct zr36060 *ptr)
427{
428 int sum = 0;
429 long bitcnt, tmp;
430
431 if (ptr->mode == CODEC_DO_COMPRESSION) {
432 dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
433
434 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
435
436
437 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
438
439
440
441 zr36060_write(ptr, ZR060_CMR,
442 ZR060_CMR_Comp | ZR060_CMR_Pass2 |
443 ZR060_CMR_BRB);
444
445
446 zr36060_write(ptr, ZR060_MBZ, 0x00);
447 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
448 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
449
450
451 zr36060_write(ptr, ZR060_IMR, 0);
452
453
454 zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
455 zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
456
457 zr36060_write(ptr, ZR060_AF_HI, 0xff);
458 zr36060_write(ptr, ZR060_AF_M, 0xff);
459 zr36060_write(ptr, ZR060_AF_LO, 0xff);
460
461
462 sum += zr36060_set_sof(ptr);
463 sum += zr36060_set_sos(ptr);
464 sum += zr36060_set_dri(ptr);
465
466
467
468 sum +=
469 zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt),
470 zr36060_dqt);
471 sum +=
472 zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
473 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,
479 ptr->app.data) + 4;
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,
485 ptr->com.data) + 4;
486
487
488
489
490 sum = ptr->real_code_vol - sum;
491 bitcnt = sum << 3;
492
493 tmp = bitcnt >> 16;
494 dprintk(3,
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);
502
503 bitcnt -= bitcnt >> 7;
504 bitcnt -= ((bitcnt * 5) >> 6);
505
506 tmp = bitcnt >> 16;
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);
514
515
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));
520
521
522
523 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
524
525 } else {
526 dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
527
528 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
529
530
531 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
532
533
534 zr36060_write(ptr, ZR060_CMR, 0);
535
536
537 zr36060_write(ptr, ZR060_MBZ, 0x00);
538 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
539 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
540
541
542 zr36060_write(ptr, ZR060_IMR, 0);
543
544
545 zr36060_write(ptr, ZR060_MER, 0);
546
547
548
549 zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
550 zr36060_dht);
551
552
553
554
555 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
556 }
557
558
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,
563 ptr->status);
564
565 if (ptr->status & ZR060_CFSR_Busy) {
566 dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name);
567 return;
568 }
569}
570
571
572
573
574
575
576
577
578
579static int
580zr36060_set_mode (struct videocodec *codec,
581 int mode)
582{
583 struct zr36060 *ptr = (struct zr36060 *) codec->data;
584
585 dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
586
587 if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
588 return -EINVAL;
589
590 ptr->mode = mode;
591 zr36060_init(ptr);
592
593 return 0;
594}
595
596
597static int
598zr36060_set_video (struct videocodec *codec,
599 struct tvnorm *norm,
600 struct vfe_settings *cap,
601 struct vfe_polarity *pol)
602{
603 struct zr36060 *ptr = (struct zr36060 *) codec->data;
604 u32 reg;
605 int size;
606
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);
609
610
611
612
613 ptr->width = cap->width / (cap->decimation & 0xff);
614 ptr->height = cap->height / (cap->decimation >> 8);
615
616 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
617
618
619
620
621
622
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);
632
633 reg = 0;
634 switch (cap->decimation & 0xff) {
635 default:
636 case 1:
637 break;
638
639 case 2:
640 reg |= ZR060_SR_HScale2;
641 break;
642
643 case 4:
644 reg |= ZR060_SR_HScale4;
645 break;
646 }
647
648 switch (cap->decimation >> 8) {
649 default:
650 case 1:
651 break;
652
653 case 2:
654 reg |= ZR060_SR_VScale;
655 break;
656 }
657 zr36060_write(ptr, ZR060_SR, reg);
658
659 zr36060_write(ptr, ZR060_BCR_Y, 0x00);
660 zr36060_write(ptr, ZR060_BCR_U, 0x80);
661 zr36060_write(ptr, ZR060_BCR_V, 0x80);
662
663
664
665 reg = norm->Ht - 1;
666 zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
667 zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
668
669 reg = norm->Wt - 1;
670 zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
671 zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
672
673 reg = 6 - 1;
674 zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
675
676
677
678 reg = 68;
679 zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
680
681 reg = norm->VStart - 1;
682 zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
683
684 reg += norm->Ha / 2;
685 zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
686 zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
687
688 reg = norm->HStart - 1;
689 zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
690
691 reg += norm->Wa;
692 zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
693 zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
694
695
696 reg = cap->y + norm->VStart;
697 zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
698 zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
699
700 reg += cap->height;
701 zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
702 zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
703
704 reg = cap->x + norm->HStart;
705 zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
706 zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
707
708 reg += cap->width;
709 zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
710 zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
711
712
713 reg = norm->VStart - 4;
714 zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
715 zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
716
717 reg += norm->Ha / 2 + 8;
718 zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
719 zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
720
721 reg = norm->HStart - 4;
722 zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
723 zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
724
725 reg += norm->Wa + 8;
726 zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
727 zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
728
729 size = ptr->width * ptr->height;
730
731 size = size * 16;
732
733
734
735
736
737 size = size * cap->quality / (low_bitrate ? 400 : 200);
738
739 if (size < 8192)
740 size = 8192;
741
742 if (size > ptr->total_code_vol * 7)
743 size = ptr->total_code_vol * 7;
744
745 ptr->real_code_vol = size >> 3;
746
747
748
749
750 reg = ptr->max_block_vol;
751 zr36060_write(ptr, ZR060_MBCVR, reg);
752
753 return 0;
754}
755
756
757static int
758zr36060_control (struct videocodec *codec,
759 int type,
760 int size,
761 void *data)
762{
763 struct zr36060 *ptr = (struct zr36060 *) codec->data;
764 int *ival = (int *) data;
765
766 dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
767 size);
768
769 switch (type) {
770 case CODEC_G_STATUS:
771 if (size != sizeof(int))
772 return -EFAULT;
773 zr36060_read_status(ptr);
774 *ival = ptr->status;
775 break;
776
777 case CODEC_G_CODEC_MODE:
778 if (size != sizeof(int))
779 return -EFAULT;
780 *ival = CODEC_MODE_BJPG;
781 break;
782
783 case CODEC_S_CODEC_MODE:
784 if (size != sizeof(int))
785 return -EFAULT;
786 if (*ival != CODEC_MODE_BJPG)
787 return -EINVAL;
788
789 return 0;
790
791 case CODEC_G_VFE:
792 case CODEC_S_VFE:
793
794 return 0;
795
796 case CODEC_S_MMAP:
797
798 return -ENXIO;
799
800 case CODEC_G_JPEG_TDS_BYTE:
801 if (size != sizeof(int))
802 return -EFAULT;
803 *ival = ptr->total_code_vol;
804 break;
805
806 case CODEC_S_JPEG_TDS_BYTE:
807 if (size != sizeof(int))
808 return -EFAULT;
809 ptr->total_code_vol = *ival;
810 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
811 break;
812
813 case CODEC_G_JPEG_SCALE:
814 if (size != sizeof(int))
815 return -EFAULT;
816 *ival = zr36060_read_scalefactor(ptr);
817 break;
818
819 case CODEC_S_JPEG_SCALE:
820 if (size != sizeof(int))
821 return -EFAULT;
822 ptr->scalefact = *ival;
823 break;
824
825 case CODEC_G_JPEG_APP_DATA: {
826 struct jpeg_app_marker *app = data;
827
828 if (size != sizeof(struct jpeg_app_marker))
829 return -EFAULT;
830
831 *app = ptr->app;
832 break;
833 }
834
835 case CODEC_S_JPEG_APP_DATA: {
836 struct jpeg_app_marker *app = data;
837
838 if (size != sizeof(struct jpeg_app_marker))
839 return -EFAULT;
840
841 ptr->app = *app;
842 break;
843 }
844
845 case CODEC_G_JPEG_COM_DATA: {
846 struct jpeg_com_marker *com = data;
847
848 if (size != sizeof(struct jpeg_com_marker))
849 return -EFAULT;
850
851 *com = ptr->com;
852 break;
853 }
854
855 case CODEC_S_JPEG_COM_DATA: {
856 struct jpeg_com_marker *com = data;
857
858 if (size != sizeof(struct jpeg_com_marker))
859 return -EFAULT;
860
861 ptr->com = *com;
862 break;
863 }
864
865 default:
866 return -EINVAL;
867 }
868
869 return size;
870}
871
872
873
874
875
876
877
878static int
879zr36060_unset (struct videocodec *codec)
880{
881 struct zr36060 *ptr = codec->data;
882
883 if (ptr) {
884
885
886 dprintk(1, "%s: finished codec #%d\n", ptr->name,
887 ptr->num);
888 kfree(ptr);
889 codec->data = NULL;
890
891 zr36060_codecs--;
892 return 0;
893 }
894
895 return -EFAULT;
896}
897
898
899
900
901
902
903
904
905
906
907static int
908zr36060_setup (struct videocodec *codec)
909{
910 struct zr36060 *ptr;
911 int res;
912
913 dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n",
914 zr36060_codecs);
915
916 if (zr36060_codecs == MAX_CODECS) {
917 dprintk(1,
918 KERN_ERR "zr36060: Can't attach more codecs!\n");
919 return -ENOSPC;
920 }
921
922 codec->data = ptr = kzalloc(sizeof(struct zr36060), GFP_KERNEL);
923 if (NULL == ptr) {
924 dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n");
925 return -ENOMEM;
926 }
927
928 snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]",
929 zr36060_codecs);
930 ptr->num = zr36060_codecs++;
931 ptr->codec = codec;
932
933
934 res = zr36060_basic_test(ptr);
935 if (res < 0) {
936 zr36060_unset(codec);
937 return res;
938 }
939
940 memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
941 memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
942
943 ptr->bitrate_ctrl = 0;
944
945 ptr->mode = CODEC_DO_COMPRESSION;
946 ptr->width = 384;
947 ptr->height = 288;
948 ptr->total_code_vol = 16000;
949 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
950 ptr->max_block_vol = 240;
951 ptr->scalefact = 0x100;
952 ptr->dri = 1;
953
954
955 ptr->com.len = 0;
956 ptr->app.appn = 0;
957 ptr->app.len = 0;
958
959 zr36060_init(ptr);
960
961 dprintk(1, KERN_INFO "%s: codec attached and running\n",
962 ptr->name);
963
964 return 0;
965}
966
967static const struct videocodec zr36060_codec = {
968 .owner = THIS_MODULE,
969 .name = "zr36060",
970 .magic = 0L,
971 .flags =
972 CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
973 CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
974 .type = CODEC_TYPE_ZR36060,
975 .setup = zr36060_setup,
976 .unset = zr36060_unset,
977 .set_mode = zr36060_set_mode,
978 .set_video = zr36060_set_video,
979 .control = zr36060_control,
980
981};
982
983
984
985
986
987static int __init
988zr36060_init_module (void)
989{
990
991 zr36060_codecs = 0;
992 return videocodec_register(&zr36060_codec);
993}
994
995static void __exit
996zr36060_cleanup_module (void)
997{
998 if (zr36060_codecs) {
999 dprintk(1,
1000 "zr36060: something's wrong - %d codecs left somehow.\n",
1001 zr36060_codecs);
1002 }
1003
1004
1005 videocodec_unregister(&zr36060_codec);
1006}
1007
1008module_init(zr36060_init_module);
1009module_exit(zr36060_cleanup_module);
1010
1011MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
1012MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors "
1013 ZR060_VERSION);
1014MODULE_LICENSE("GPL");
1015