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#include <asm/io.h>
39
40
41#include "zr36060.h"
42
43
44#include "videocodec.h"
45
46
47
48#define MAX_CODECS 20
49
50
51static int zr36060_codecs;
52
53static bool low_bitrate;
54module_param(low_bitrate, bool, 0);
55MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
56
57
58static int debug;
59module_param(debug, int, 0);
60MODULE_PARM_DESC(debug, "Debug level (0-4)");
61
62#define dprintk(num, format, args...) \
63 do { \
64 if (debug >= num) \
65 printk(format, ##args); \
66 } while (0)
67
68
69
70
71
72
73
74
75static u8
76zr36060_read (struct zr36060 *ptr,
77 u16 reg)
78{
79 u8 value = 0;
80
81
82 if (ptr->codec->master_data->readreg)
83 value = (ptr->codec->master_data->readreg(ptr->codec,
84 reg)) & 0xff;
85 else
86 dprintk(1,
87 KERN_ERR "%s: invalid I/O setup, nothing read!\n",
88 ptr->name);
89
90
91
92 return value;
93}
94
95static void
96zr36060_write(struct zr36060 *ptr,
97 u16 reg,
98 u8 value)
99{
100
101 dprintk(4, "0x%02x @0x%04x\n", value, reg);
102
103
104 if (ptr->codec->master_data->writereg)
105 ptr->codec->master_data->writereg(ptr->codec, reg, value);
106 else
107 dprintk(1,
108 KERN_ERR
109 "%s: invalid I/O setup, nothing written!\n",
110 ptr->name);
111}
112
113
114
115
116
117
118
119
120static u8
121zr36060_read_status (struct zr36060 *ptr)
122{
123 ptr->status = zr36060_read(ptr, ZR060_CFSR);
124
125 zr36060_read(ptr, 0);
126 return ptr->status;
127}
128
129
130
131
132
133
134
135
136static u16
137zr36060_read_scalefactor (struct zr36060 *ptr)
138{
139 ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
140 (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
141
142
143 zr36060_read(ptr, 0);
144 return ptr->scalefact;
145}
146
147
148
149
150
151
152
153static void
154zr36060_wait_end (struct zr36060 *ptr)
155{
156 int i = 0;
157
158 while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) {
159 udelay(1);
160 if (i++ > 200000) {
161 dprintk(1,
162 "%s: timeout at wait_end (last status: 0x%02x)\n",
163 ptr->name, ptr->status);
164 break;
165 }
166 }
167}
168
169
170
171
172
173
174
175static int
176zr36060_basic_test (struct zr36060 *ptr)
177{
178 if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
179 (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
180 dprintk(1,
181 KERN_ERR
182 "%s: attach failed, can't connect to jpeg processor!\n",
183 ptr->name);
184 return -ENXIO;
185 }
186
187 zr36060_wait_end(ptr);
188 if (ptr->status & ZR060_CFSR_Busy) {
189 dprintk(1,
190 KERN_ERR
191 "%s: attach failed, jpeg processor failed (end flag)!\n",
192 ptr->name);
193 return -EBUSY;
194 }
195
196 return 0;
197}
198
199
200
201
202
203
204
205static int
206zr36060_pushit (struct zr36060 *ptr,
207 u16 startreg,
208 u16 len,
209 const char *data)
210{
211 int i = 0;
212
213 dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
214 startreg, len);
215 while (i < len) {
216 zr36060_write(ptr, startreg++, data[i++]);
217 }
218
219 return i;
220}
221
222
223
224
225
226
227
228
229
230
231
232
233static const char zr36060_dqt[0x86] = {
234 0xff, 0xdb,
235 0x00, 0x84,
236 0x00,
237 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
238 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
239 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
240 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
241 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
242 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
243 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
244 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
245 0x01,
246 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
247 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
248 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
249 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
250 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
251 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
252 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
253 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
254};
255
256static const char zr36060_dht[0x1a4] = {
257 0xff, 0xc4,
258 0x01, 0xa2,
259 0x00,
260 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
261 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
262 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
263 0x01,
264 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
265 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
266 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
267 0x10,
268 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
269 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
270 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
271 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
272 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
273 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
274 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
275 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
276 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
277 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
278 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
279 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
280 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
281 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
282 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
283 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
284 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
285 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
286 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
287 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
288 0xF8, 0xF9, 0xFA,
289 0x11,
290 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
291 0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
292 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
293 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
294 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
295 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
296 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
297 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
298 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
299 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
300 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
301 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
302 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
303 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
304 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
305 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
306 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
307 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
308 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
309 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
310 0xF9, 0xFA
311};
312
313
314#define NO_OF_COMPONENTS 0x3
315#define BASELINE_PRECISION 0x8
316static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
317static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
318static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
319
320
321static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
322static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
323
324
325
326
327
328
329
330
331
332
333
334
335
336static int
337zr36060_set_sof (struct zr36060 *ptr)
338{
339 char sof_data[34];
340 int i;
341
342 dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
343 ptr->width, ptr->height, NO_OF_COMPONENTS);
344 sof_data[0] = 0xff;
345 sof_data[1] = 0xc0;
346 sof_data[2] = 0x00;
347 sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
348 sof_data[4] = BASELINE_PRECISION;
349 sof_data[5] = (ptr->height) >> 8;
350 sof_data[6] = (ptr->height) & 0xff;
351 sof_data[7] = (ptr->width) >> 8;
352 sof_data[8] = (ptr->width) & 0xff;
353 sof_data[9] = NO_OF_COMPONENTS;
354 for (i = 0; i < NO_OF_COMPONENTS; i++) {
355 sof_data[10 + (i * 3)] = i;
356 sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
357 (ptr->v_samp_ratio[i]);
358 sof_data[12 + (i * 3)] = zr36060_tq[i];
359 }
360 return zr36060_pushit(ptr, ZR060_SOF_IDX,
361 (3 * NO_OF_COMPONENTS) + 10, sof_data);
362}
363
364
365
366
367
368
369static int
370zr36060_set_sos (struct zr36060 *ptr)
371{
372 char sos_data[16];
373 int i;
374
375 dprintk(3, "%s: write SOS\n", ptr->name);
376 sos_data[0] = 0xff;
377 sos_data[1] = 0xda;
378 sos_data[2] = 0x00;
379 sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
380 sos_data[4] = NO_OF_COMPONENTS;
381 for (i = 0; i < NO_OF_COMPONENTS; i++) {
382 sos_data[5 + (i * 2)] = i;
383 sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
384 zr36060_ta[i];
385 }
386 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;
387 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
388 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
389 return zr36060_pushit(ptr, ZR060_SOS_IDX,
390 4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
391 sos_data);
392}
393
394
395
396
397
398static int
399zr36060_set_dri (struct zr36060 *ptr)
400{
401 char dri_data[6];
402
403 dprintk(3, "%s: write DRI\n", ptr->name);
404 dri_data[0] = 0xff;
405 dri_data[1] = 0xdd;
406 dri_data[2] = 0x00;
407 dri_data[3] = 0x04;
408 dri_data[4] = (ptr->dri) >> 8;
409 dri_data[5] = (ptr->dri) & 0xff;
410 return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
411}
412
413
414
415
416
417
418
419
420
421static void
422zr36060_init (struct zr36060 *ptr)
423{
424 int sum = 0;
425 long bitcnt, tmp;
426
427 if (ptr->mode == CODEC_DO_COMPRESSION) {
428 dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
429
430 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
431
432
433 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
434
435
436
437 zr36060_write(ptr, ZR060_CMR,
438 ZR060_CMR_Comp | ZR060_CMR_Pass2 |
439 ZR060_CMR_BRB);
440
441
442 zr36060_write(ptr, ZR060_MBZ, 0x00);
443 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
444 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
445
446
447 zr36060_write(ptr, ZR060_IMR, 0);
448
449
450 zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
451 zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
452
453 zr36060_write(ptr, ZR060_AF_HI, 0xff);
454 zr36060_write(ptr, ZR060_AF_M, 0xff);
455 zr36060_write(ptr, ZR060_AF_LO, 0xff);
456
457
458 sum += zr36060_set_sof(ptr);
459 sum += zr36060_set_sos(ptr);
460 sum += zr36060_set_dri(ptr);
461
462
463
464 sum +=
465 zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt),
466 zr36060_dqt);
467 sum +=
468 zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
469 zr36060_dht);
470 zr36060_write(ptr, ZR060_APP_IDX, 0xff);
471 zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
472 zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
473 zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
474 sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60,
475 ptr->app.data) + 4;
476 zr36060_write(ptr, ZR060_COM_IDX, 0xff);
477 zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
478 zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
479 zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
480 sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60,
481 ptr->com.data) + 4;
482
483
484
485
486 sum = ptr->real_code_vol - sum;
487 bitcnt = sum << 3;
488
489 tmp = bitcnt >> 16;
490 dprintk(3,
491 "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
492 ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
493 zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
494 zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
495 tmp = bitcnt & 0xffff;
496 zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
497 zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
498
499 bitcnt -= bitcnt >> 7;
500 bitcnt -= ((bitcnt * 5) >> 6);
501
502 tmp = bitcnt >> 16;
503 dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
504 ptr->name, bitcnt, tmp);
505 zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
506 zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
507 tmp = bitcnt & 0xffff;
508 zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
509 zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
510
511
512 zr36060_write(ptr, ZR060_MER,
513 ZR060_MER_DQT | ZR060_MER_DHT |
514 ((ptr->com.len > 0) ? ZR060_MER_Com : 0) |
515 ((ptr->app.len > 0) ? ZR060_MER_App : 0));
516
517
518
519 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
520
521 } else {
522 dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
523
524 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
525
526
527 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
528
529
530 zr36060_write(ptr, ZR060_CMR, 0);
531
532
533 zr36060_write(ptr, ZR060_MBZ, 0x00);
534 zr36060_write(ptr, ZR060_TCR_HI, 0x00);
535 zr36060_write(ptr, ZR060_TCR_LO, 0x00);
536
537
538 zr36060_write(ptr, ZR060_IMR, 0);
539
540
541 zr36060_write(ptr, ZR060_MER, 0);
542
543
544
545 zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
546 zr36060_dht);
547
548
549
550
551 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
552 }
553
554
555 zr36060_write(ptr, ZR060_LOAD,
556 ZR060_LOAD_SyncRst | ZR060_LOAD_Load);
557 zr36060_wait_end(ptr);
558 dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name,
559 ptr->status);
560
561 if (ptr->status & ZR060_CFSR_Busy) {
562 dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name);
563 return;
564 }
565}
566
567
568
569
570
571
572
573
574
575static int
576zr36060_set_mode (struct videocodec *codec,
577 int mode)
578{
579 struct zr36060 *ptr = (struct zr36060 *) codec->data;
580
581 dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
582
583 if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
584 return -EINVAL;
585
586 ptr->mode = mode;
587 zr36060_init(ptr);
588
589 return 0;
590}
591
592
593static int
594zr36060_set_video (struct videocodec *codec,
595 struct tvnorm *norm,
596 struct vfe_settings *cap,
597 struct vfe_polarity *pol)
598{
599 struct zr36060 *ptr = (struct zr36060 *) codec->data;
600 u32 reg;
601 int size;
602
603 dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
604 cap->x, cap->y, cap->width, cap->height, cap->decimation);
605
606
607
608
609 ptr->width = cap->width / (cap->decimation & 0xff);
610 ptr->height = cap->height / (cap->decimation >> 8);
611
612 zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
613
614
615
616
617
618
619 reg = (!pol->vsync_pol ? ZR060_VPR_VSPol : 0)
620 | (!pol->hsync_pol ? ZR060_VPR_HSPol : 0)
621 | (pol->field_pol ? ZR060_VPR_FIPol : 0)
622 | (pol->blank_pol ? ZR060_VPR_BLPol : 0)
623 | (pol->subimg_pol ? ZR060_VPR_SImgPol : 0)
624 | (pol->poe_pol ? ZR060_VPR_PoePol : 0)
625 | (pol->pvalid_pol ? ZR060_VPR_PValPol : 0)
626 | (pol->vclk_pol ? ZR060_VPR_VCLKPol : 0);
627 zr36060_write(ptr, ZR060_VPR, reg);
628
629 reg = 0;
630 switch (cap->decimation & 0xff) {
631 default:
632 case 1:
633 break;
634
635 case 2:
636 reg |= ZR060_SR_HScale2;
637 break;
638
639 case 4:
640 reg |= ZR060_SR_HScale4;
641 break;
642 }
643
644 switch (cap->decimation >> 8) {
645 default:
646 case 1:
647 break;
648
649 case 2:
650 reg |= ZR060_SR_VScale;
651 break;
652 }
653 zr36060_write(ptr, ZR060_SR, reg);
654
655 zr36060_write(ptr, ZR060_BCR_Y, 0x00);
656 zr36060_write(ptr, ZR060_BCR_U, 0x80);
657 zr36060_write(ptr, ZR060_BCR_V, 0x80);
658
659
660
661 reg = norm->Ht - 1;
662 zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
663 zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
664
665 reg = norm->Wt - 1;
666 zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
667 zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
668
669 reg = 6 - 1;
670 zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
671
672
673
674 reg = 68;
675 zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
676
677 reg = norm->VStart - 1;
678 zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
679
680 reg += norm->Ha / 2;
681 zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
682 zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
683
684 reg = norm->HStart - 1;
685 zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
686
687 reg += norm->Wa;
688 zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
689 zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
690
691
692 reg = cap->y + norm->VStart;
693 zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
694 zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
695
696 reg += cap->height;
697 zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
698 zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
699
700 reg = cap->x + norm->HStart;
701 zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
702 zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
703
704 reg += cap->width;
705 zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
706 zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
707
708
709 reg = norm->VStart - 4;
710 zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
711 zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
712
713 reg += norm->Ha / 2 + 8;
714 zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
715 zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
716
717 reg = norm->HStart - 4;
718 zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
719 zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
720
721 reg += norm->Wa + 8;
722 zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
723 zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
724
725 size = ptr->width * ptr->height;
726
727 size = size * 16;
728
729
730
731
732
733 size = size * cap->quality / (low_bitrate ? 400 : 200);
734
735 if (size < 8192)
736 size = 8192;
737
738 if (size > ptr->total_code_vol * 7)
739 size = ptr->total_code_vol * 7;
740
741 ptr->real_code_vol = size >> 3;
742
743
744
745
746 reg = ptr->max_block_vol;
747 zr36060_write(ptr, ZR060_MBCVR, reg);
748
749 return 0;
750}
751
752
753static int
754zr36060_control (struct videocodec *codec,
755 int type,
756 int size,
757 void *data)
758{
759 struct zr36060 *ptr = (struct zr36060 *) codec->data;
760 int *ival = (int *) data;
761
762 dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
763 size);
764
765 switch (type) {
766 case CODEC_G_STATUS:
767 if (size != sizeof(int))
768 return -EFAULT;
769 zr36060_read_status(ptr);
770 *ival = ptr->status;
771 break;
772
773 case CODEC_G_CODEC_MODE:
774 if (size != sizeof(int))
775 return -EFAULT;
776 *ival = CODEC_MODE_BJPG;
777 break;
778
779 case CODEC_S_CODEC_MODE:
780 if (size != sizeof(int))
781 return -EFAULT;
782 if (*ival != CODEC_MODE_BJPG)
783 return -EINVAL;
784
785 return 0;
786
787 case CODEC_G_VFE:
788 case CODEC_S_VFE:
789
790 return 0;
791
792 case CODEC_S_MMAP:
793
794 return -ENXIO;
795
796 case CODEC_G_JPEG_TDS_BYTE:
797 if (size != sizeof(int))
798 return -EFAULT;
799 *ival = ptr->total_code_vol;
800 break;
801
802 case CODEC_S_JPEG_TDS_BYTE:
803 if (size != sizeof(int))
804 return -EFAULT;
805 ptr->total_code_vol = *ival;
806 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
807 break;
808
809 case CODEC_G_JPEG_SCALE:
810 if (size != sizeof(int))
811 return -EFAULT;
812 *ival = zr36060_read_scalefactor(ptr);
813 break;
814
815 case CODEC_S_JPEG_SCALE:
816 if (size != sizeof(int))
817 return -EFAULT;
818 ptr->scalefact = *ival;
819 break;
820
821 case CODEC_G_JPEG_APP_DATA: {
822 struct jpeg_app_marker *app = data;
823
824 if (size != sizeof(struct jpeg_app_marker))
825 return -EFAULT;
826
827 *app = ptr->app;
828 break;
829 }
830
831 case CODEC_S_JPEG_APP_DATA: {
832 struct jpeg_app_marker *app = data;
833
834 if (size != sizeof(struct jpeg_app_marker))
835 return -EFAULT;
836
837 ptr->app = *app;
838 break;
839 }
840
841 case CODEC_G_JPEG_COM_DATA: {
842 struct jpeg_com_marker *com = data;
843
844 if (size != sizeof(struct jpeg_com_marker))
845 return -EFAULT;
846
847 *com = ptr->com;
848 break;
849 }
850
851 case CODEC_S_JPEG_COM_DATA: {
852 struct jpeg_com_marker *com = data;
853
854 if (size != sizeof(struct jpeg_com_marker))
855 return -EFAULT;
856
857 ptr->com = *com;
858 break;
859 }
860
861 default:
862 return -EINVAL;
863 }
864
865 return size;
866}
867
868
869
870
871
872
873
874static int
875zr36060_unset (struct videocodec *codec)
876{
877 struct zr36060 *ptr = codec->data;
878
879 if (ptr) {
880
881
882 dprintk(1, "%s: finished codec #%d\n", ptr->name,
883 ptr->num);
884 kfree(ptr);
885 codec->data = NULL;
886
887 zr36060_codecs--;
888 return 0;
889 }
890
891 return -EFAULT;
892}
893
894
895
896
897
898
899
900
901
902
903static int
904zr36060_setup (struct videocodec *codec)
905{
906 struct zr36060 *ptr;
907 int res;
908
909 dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n",
910 zr36060_codecs);
911
912 if (zr36060_codecs == MAX_CODECS) {
913 dprintk(1,
914 KERN_ERR "zr36060: Can't attach more codecs!\n");
915 return -ENOSPC;
916 }
917
918 codec->data = ptr = kzalloc(sizeof(struct zr36060), GFP_KERNEL);
919 if (NULL == ptr) {
920 dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n");
921 return -ENOMEM;
922 }
923
924 snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]",
925 zr36060_codecs);
926 ptr->num = zr36060_codecs++;
927 ptr->codec = codec;
928
929
930 res = zr36060_basic_test(ptr);
931 if (res < 0) {
932 zr36060_unset(codec);
933 return res;
934 }
935
936 memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
937 memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
938
939 ptr->bitrate_ctrl = 0;
940
941 ptr->mode = CODEC_DO_COMPRESSION;
942 ptr->width = 384;
943 ptr->height = 288;
944 ptr->total_code_vol = 16000;
945 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
946 ptr->max_block_vol = 240;
947 ptr->scalefact = 0x100;
948 ptr->dri = 1;
949
950
951 ptr->com.len = 0;
952 ptr->app.appn = 0;
953 ptr->app.len = 0;
954
955 zr36060_init(ptr);
956
957 dprintk(1, KERN_INFO "%s: codec attached and running\n",
958 ptr->name);
959
960 return 0;
961}
962
963static const struct videocodec zr36060_codec = {
964 .owner = THIS_MODULE,
965 .name = "zr36060",
966 .magic = 0L,
967 .flags =
968 CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
969 CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
970 .type = CODEC_TYPE_ZR36060,
971 .setup = zr36060_setup,
972 .unset = zr36060_unset,
973 .set_mode = zr36060_set_mode,
974 .set_video = zr36060_set_video,
975 .control = zr36060_control,
976
977};
978
979
980
981
982
983static int __init
984zr36060_init_module (void)
985{
986
987 zr36060_codecs = 0;
988 return videocodec_register(&zr36060_codec);
989}
990
991static void __exit
992zr36060_cleanup_module (void)
993{
994 if (zr36060_codecs) {
995 dprintk(1,
996 "zr36060: something's wrong - %d codecs left somehow.\n",
997 zr36060_codecs);
998 }
999
1000
1001 videocodec_unregister(&zr36060_codec);
1002}
1003
1004module_init(zr36060_init_module);
1005module_exit(zr36060_cleanup_module);
1006
1007MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
1008MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors "
1009 ZR060_VERSION);
1010MODULE_LICENSE("GPL");
1011