1
2
3
4
5
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
19#include <linux/io.h>
20
21
22#include "zr36060.h"
23
24
25#include "videocodec.h"
26
27
28#define MAX_CODECS 20
29
30
31static int zr36060_codecs;
32
33static bool low_bitrate;
34module_param(low_bitrate, bool, 0);
35MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
36
37
38static int debug;
39module_param(debug, int, 0);
40MODULE_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
50
51
52
53
54static u8 zr36060_read(struct zr36060 *ptr, u16 reg)
55{
56 u8 value = 0;
57
58
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
67static void zr36060_write(struct zr36060 *ptr, u16 reg, u8 value)
68{
69 dprintk(4, "0x%02x @0x%04x\n", value, reg);
70
71
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
80
81
82
83
84
85static 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
94static 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
100 zr36060_read(ptr, 0);
101 return ptr->scalefact;
102}
103
104
105static 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) {
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
121static 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;
136}
137
138
139static 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
153
154
155
156
157
158
159
160
161static const char zr36060_dqt[0x86] = {
162 0xff, 0xdb,
163 0x00, 0x84,
164 0x00,
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,
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
184static const char zr36060_dht[0x1a4] = {
185 0xff, 0xc4,
186 0x01, 0xa2,
187 0x00,
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,
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,
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,
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
242#define NO_OF_COMPONENTS 0x3
243#define BASELINE_PRECISION 0x8
244static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
245static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
246static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
247
248
249static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
250static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
251
252
253static int zr36060_set_sof(struct zr36060 *ptr)
254{
255 char sof_data[34];
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;
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;
272 sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
273 (ptr->v_samp_ratio[i]);
274 sof_data[12 + (i * 3)] = zr36060_tq[i];
275 }
276 return zr36060_pushit(ptr, ZR060_SOF_IDX,
277 (3 * NO_OF_COMPONENTS) + 10, sof_data);
278}
279
280
281static int zr36060_set_sos(struct zr36060 *ptr)
282{
283 char sos_data[16];
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;
294 sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
295 zr36060_ta[i];
296 }
297 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;
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
306static int zr36060_set_dri(struct zr36060 *ptr)
307{
308 char dri_data[6];
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
321
322
323static 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
334 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
335
336
337
338 zr36060_write(ptr, ZR060_CMR, ZR060_CMR_COMP | ZR060_CMR_PASS2 | ZR060_CMR_BRB);
339
340
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
346 zr36060_write(ptr, ZR060_IMR, 0);
347
348
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
357 sum += zr36060_set_sof(ptr);
358 sum += zr36060_set_sos(ptr);
359 sum += zr36060_set_dri(ptr);
360
361
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
376
377
378 sum = ptr->real_code_vol - sum;
379 bitcnt = sum << 3;
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;
392 bitcnt -= ((bitcnt * 5) >> 6);
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
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
410
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
419 zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
420
421
422 zr36060_write(ptr, ZR060_CMR, 0);
423
424
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
430 zr36060_write(ptr, ZR060_IMR, 0);
431
432
433 zr36060_write(ptr, ZR060_MER, 0);
434
435
436 zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
437
438
439
440
441 zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
442 }
443
444
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;
452 }
453}
454
455
456
457
458
459
460
461
462
463
464static 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
480static 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
491
492
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
500
501
502
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
545
546 reg = norm->ht - 1;
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;
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;
555 zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
556
557
558
559 reg = 68;
560 zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
561
562 reg = norm->v_start - 1;
563 zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
564
565 reg += norm->ha / 2;
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;
570 zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
571
572 reg += norm->wa;
573 zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
574 zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
575
576
577 reg = cap->y + norm->v_start;
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;
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;
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;
590 zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
591 zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
592
593
594 reg = norm->v_start - 4;
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;
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 - 4;
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;
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
612 size = size * 16;
613
614
615
616
617
618
619 size = size * cap->quality / (low_bitrate ? 400 : 200);
620
621 if (size < 8192)
622 size = 8192;
623
624 if (size > ptr->total_code_vol * 7)
625 size = ptr->total_code_vol * 7;
626
627 ptr->real_code_vol = size >> 3;
628
629
630
631
632
633 reg = ptr->max_block_vol;
634 zr36060_write(ptr, ZR060_MBCVR, reg);
635
636 return 0;
637}
638
639
640static 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:
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
668 return 0;
669
670 case CODEC_G_VFE:
671 case CODEC_S_VFE:
672
673 return 0;
674
675 case CODEC_S_MMAP:
676
677 return -ENXIO;
678
679 case CODEC_G_JPEG_TDS_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:
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:
693 if (size != sizeof(int))
694 return -EFAULT;
695 *ival = zr36060_read_scalefactor(ptr);
696 break;
697
698 case CODEC_S_JPEG_SCALE:
699 if (size != sizeof(int))
700 return -EFAULT;
701 ptr->scalefact = *ival;
702 break;
703
704 case CODEC_G_JPEG_APP_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: {
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: {
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: {
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
753
754
755
756static int zr36060_unset(struct videocodec *codec)
757{
758 struct zr36060 *ptr = codec->data;
759
760 if (ptr) {
761
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
776
777
778
779
780
781static 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
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
803 res = zr36060_basic_test(ptr);
804 if (res < 0) {
805 zr36060_unset(codec);
806 return res;
807 }
808
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;
813 ptr->mode = CODEC_DO_COMPRESSION;
814 ptr->width = 384;
815 ptr->height = 288;
816 ptr->total_code_vol = 16000;
817 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
818 ptr->max_block_vol = 240;
819 ptr->scalefact = 0x100;
820 ptr->dri = 1;
821
822
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
834static const struct videocodec zr36060_codec = {
835 .owner = THIS_MODULE,
836 .name = "zr36060",
837 .magic = 0L,
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,
843 .unset = zr36060_unset,
844 .set_mode = zr36060_set_mode,
845 .set_video = zr36060_set_video,
846 .control = zr36060_control,
847
848};
849
850static int __init zr36060_init_module(void)
851{
852 zr36060_codecs = 0;
853 return videocodec_register(&zr36060_codec);
854}
855
856static 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
865 videocodec_unregister(&zr36060_codec);
866}
867
868module_init(zr36060_init_module);
869module_exit(zr36060_cleanup_module);
870
871MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
872MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors " ZR060_VERSION);
873MODULE_LICENSE("GPL");
874