blob: faae4ec3ea0bf5288f12a1c52a78ce75e12bd7c2 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Zoran ZR36050 basic configuration functions
3 *
4 * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
5 *
6 * $Id: zr36050.c,v 1.1.2.11 2003/08/03 14:54:53 rbultje Exp $
7 *
8 * ------------------------------------------------------------------------
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * ------------------------------------------------------------------------
25 */
26
27#define ZR050_VERSION "v0.7.1"
28
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#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
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030037/* includes for structures and defines regarding video
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 #include<linux/videodev.h> */
39
40/* I/O commands, error codes */
Michal Piotrowskib9758df2007-08-21 12:34:48 -030041#include <asm/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042//#include<errno.h>
43
44/* headerfile of this module */
Michal Piotrowskib9758df2007-08-21 12:34:48 -030045#include "zr36050.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47/* codec io API */
Michal Piotrowskib9758df2007-08-21 12:34:48 -030048#include "videocodec.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50/* it doesn't make sense to have more than 20 or so,
51 just to prevent some unwanted loops */
52#define MAX_CODECS 20
53
54/* amount of chips attached via this driver */
55static int zr36050_codecs = 0;
56
57/* debugging is available via module parameter */
58
59static int debug = 0;
60module_param(debug, int, 0);
61MODULE_PARM_DESC(debug, "Debug level (0-4)");
62
63#define dprintk(num, format, args...) \
64 do { \
65 if (debug >= num) \
66 printk(format, ##args); \
67 } while (0)
68
69/* =========================================================================
70 Local hardware I/O functions:
71
72 read/write via codec layer (registers are located in the master device)
73 ========================================================================= */
74
75/* read and write functions */
76static u8
77zr36050_read (struct zr36050 *ptr,
78 u16 reg)
79{
80 u8 value = 0;
81
82 // just in case something is wrong...
83 if (ptr->codec->master_data->readreg)
84 value = (ptr->codec->master_data->readreg(ptr->codec,
85 reg)) & 0xFF;
86 else
87 dprintk(1,
88 KERN_ERR "%s: invalid I/O setup, nothing read!\n",
89 ptr->name);
90
91 dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
92 value);
93
94 return value;
95}
96
97static void
98zr36050_write (struct zr36050 *ptr,
99 u16 reg,
100 u8 value)
101{
102 dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
103 reg);
104
105 // just in case something is wrong...
106 if (ptr->codec->master_data->writereg)
107 ptr->codec->master_data->writereg(ptr->codec, reg, value);
108 else
109 dprintk(1,
110 KERN_ERR
111 "%s: invalid I/O setup, nothing written!\n",
112 ptr->name);
113}
114
115/* =========================================================================
116 Local helper function:
117
118 status read
119 ========================================================================= */
120
121/* status is kept in datastructure */
122static u8
123zr36050_read_status1 (struct zr36050 *ptr)
124{
125 ptr->status1 = zr36050_read(ptr, ZR050_STATUS_1);
126
127 zr36050_read(ptr, 0);
128 return ptr->status1;
129}
130
131/* =========================================================================
132 Local helper function:
133
134 scale factor read
135 ========================================================================= */
136
137/* scale factor is kept in datastructure */
138static u16
139zr36050_read_scalefactor (struct zr36050 *ptr)
140{
141 ptr->scalefact = (zr36050_read(ptr, ZR050_SF_HI) << 8) |
142 (zr36050_read(ptr, ZR050_SF_LO) & 0xFF);
143
144 /* leave 0 selected for an eventually GO from master */
145 zr36050_read(ptr, 0);
146 return ptr->scalefact;
147}
148
149/* =========================================================================
150 Local helper function:
151
152 wait if codec is ready to proceed (end of processing) or time is over
153 ========================================================================= */
154
155static void
156zr36050_wait_end (struct zr36050 *ptr)
157{
158 int i = 0;
159
160 while (!(zr36050_read_status1(ptr) & 0x4)) {
161 udelay(1);
Alexey Dobriyan8a598222006-03-07 22:20:23 -0300162 if (i++ > 200000) { // 200ms, there is for sure something wrong!!!
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 dprintk(1,
Joe Perchesc84e6032008-02-03 17:18:59 +0200164 "%s: timeout at wait_end (last status: 0x%02x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 ptr->name, ptr->status1);
166 break;
167 }
168 }
169}
170
171/* =========================================================================
172 Local helper function:
173
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300174 basic test of "connectivity", writes/reads to/from memory the SOF marker
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 ========================================================================= */
176
177static int
178zr36050_basic_test (struct zr36050 *ptr)
179{
180 zr36050_write(ptr, ZR050_SOF_IDX, 0x00);
181 zr36050_write(ptr, ZR050_SOF_IDX + 1, 0x00);
182 if ((zr36050_read(ptr, ZR050_SOF_IDX) |
183 zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0x0000) {
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 zr36050_write(ptr, ZR050_SOF_IDX, 0xff);
191 zr36050_write(ptr, ZR050_SOF_IDX + 1, 0xc0);
192 if (((zr36050_read(ptr, ZR050_SOF_IDX) << 8) |
193 zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0xffc0) {
194 dprintk(1,
195 KERN_ERR
196 "%s: attach failed, can't connect to jpeg processor!\n",
197 ptr->name);
198 return -ENXIO;
199 }
200
201 zr36050_wait_end(ptr);
202 if ((ptr->status1 & 0x4) == 0) {
203 dprintk(1,
204 KERN_ERR
205 "%s: attach failed, jpeg processor failed (end flag)!\n",
206 ptr->name);
207 return -EBUSY;
208 }
209
210 return 0; /* looks good! */
211}
212
213/* =========================================================================
214 Local helper function:
215
216 simple loop for pushing the init datasets
217 ========================================================================= */
218
219static int
220zr36050_pushit (struct zr36050 *ptr,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300221 u16 startreg,
222 u16 len,
223 const char *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224{
225 int i = 0;
226
227 dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
228 startreg, len);
229 while (i < len) {
230 zr36050_write(ptr, startreg++, data[i++]);
231 }
232
233 return i;
234}
235
236/* =========================================================================
237 Basic datasets:
238
239 jpeg baseline setup data (you find it on lots places in internet, or just
240 extract it from any regular .jpg image...)
241
242 Could be variable, but until it's not needed it they are just fixed to save
243 memory. Otherwise expand zr36050 structure with arrays, push the values to
244 it and initalize from there, as e.g. the linux zr36057/60 driver does it.
245 ========================================================================= */
246
247static const char zr36050_dqt[0x86] = {
248 0xff, 0xdb, //Marker: DQT
249 0x00, 0x84, //Length: 2*65+2
250 0x00, //Pq,Tq first table
251 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
252 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
253 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
254 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
255 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
256 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
257 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
258 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
259 0x01, //Pq,Tq second table
260 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
261 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
262 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
263 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
264 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
265 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
266 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
267 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
268};
269
270static const char zr36050_dht[0x1a4] = {
271 0xff, 0xc4, //Marker: DHT
272 0x01, 0xa2, //Length: 2*AC, 2*DC
273 0x00, //DC first table
274 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
275 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
276 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
277 0x01, //DC second table
278 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
279 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
280 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
281 0x10, //AC first table
282 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
283 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
284 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
285 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
286 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
287 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
288 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
289 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
290 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
291 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
292 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
293 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
294 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
295 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
296 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
297 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
298 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
299 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
300 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
301 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
302 0xF8, 0xF9, 0xFA,
303 0x11, //AC second table
304 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
305 0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
306 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
307 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
308 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
309 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
310 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
311 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
312 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
313 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
314 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
315 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
316 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
317 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
318 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
319 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
320 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
321 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
322 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
323 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
324 0xF9, 0xFA
325};
326
327/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
328#define NO_OF_COMPONENTS 0x3 //Y,U,V
329#define BASELINE_PRECISION 0x8 //MCU size (?)
330static const char zr36050_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's QT
331static const char zr36050_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's DC
332static const char zr36050_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's AC
333
334/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
335static const char zr36050_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
336static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
337
338/* =========================================================================
339 Local helper functions:
340
341 calculation and setup of parameter-dependent JPEG baseline segments
342 (needed for compression only)
343 ========================================================================= */
344
345/* ------------------------------------------------------------------------- */
346
347/* SOF (start of frame) segment depends on width, height and sampling ratio
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300348 of each color component */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350static int
351zr36050_set_sof (struct zr36050 *ptr)
352{
353 char sof_data[34]; // max. size of register set
354 int i;
355
356 dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
357 ptr->width, ptr->height, NO_OF_COMPONENTS);
358 sof_data[0] = 0xff;
359 sof_data[1] = 0xc0;
360 sof_data[2] = 0x00;
361 sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
362 sof_data[4] = BASELINE_PRECISION; // only '8' possible with zr36050
363 sof_data[5] = (ptr->height) >> 8;
364 sof_data[6] = (ptr->height) & 0xff;
365 sof_data[7] = (ptr->width) >> 8;
366 sof_data[8] = (ptr->width) & 0xff;
367 sof_data[9] = NO_OF_COMPONENTS;
368 for (i = 0; i < NO_OF_COMPONENTS; i++) {
369 sof_data[10 + (i * 3)] = i; // index identifier
370 sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) | (ptr->v_samp_ratio[i]); // sampling ratios
371 sof_data[12 + (i * 3)] = zr36050_tq[i]; // Q table selection
372 }
373 return zr36050_pushit(ptr, ZR050_SOF_IDX,
374 (3 * NO_OF_COMPONENTS) + 10, sof_data);
375}
376
377/* ------------------------------------------------------------------------- */
378
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300379/* SOS (start of scan) segment depends on the used scan components
380 of each color component */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382static int
383zr36050_set_sos (struct zr36050 *ptr)
384{
385 char sos_data[16]; // max. size of register set
386 int i;
387
388 dprintk(3, "%s: write SOS\n", ptr->name);
389 sos_data[0] = 0xff;
390 sos_data[1] = 0xda;
391 sos_data[2] = 0x00;
392 sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
393 sos_data[4] = NO_OF_COMPONENTS;
394 for (i = 0; i < NO_OF_COMPONENTS; i++) {
395 sos_data[5 + (i * 2)] = i; // index
396 sos_data[6 + (i * 2)] = (zr36050_td[i] << 4) | zr36050_ta[i]; // AC/DC tbl.sel.
397 }
398 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start
399 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3F;
400 sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
401 return zr36050_pushit(ptr, ZR050_SOS1_IDX,
402 4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
403 sos_data);
404}
405
406/* ------------------------------------------------------------------------- */
407
408/* DRI (define restart interval) */
409
410static int
411zr36050_set_dri (struct zr36050 *ptr)
412{
413 char dri_data[6]; // max. size of register set
414
415 dprintk(3, "%s: write DRI\n", ptr->name);
416 dri_data[0] = 0xff;
417 dri_data[1] = 0xdd;
418 dri_data[2] = 0x00;
419 dri_data[3] = 0x04;
420 dri_data[4] = ptr->dri >> 8;
421 dri_data[5] = ptr->dri & 0xff;
422 return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data);
423}
424
425/* =========================================================================
426 Setup function:
427
428 Setup compression/decompression of Zoran's JPEG processor
429 ( see also zoran 36050 manual )
430
431 ... sorry for the spaghetti code ...
432 ========================================================================= */
433static void
434zr36050_init (struct zr36050 *ptr)
435{
436 int sum = 0;
437 long bitcnt, tmp;
438
439 if (ptr->mode == CODEC_DO_COMPRESSION) {
440 dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
441
442 /* 050 communicates with 057 in master mode */
443 zr36050_write(ptr, ZR050_HARDWARE, ZR050_HW_MSTR);
444
445 /* encoding table preload for compression */
446 zr36050_write(ptr, ZR050_MODE,
447 ZR050_MO_COMP | ZR050_MO_TLM);
448 zr36050_write(ptr, ZR050_OPTIONS, 0);
449
450 /* disable all IRQs */
451 zr36050_write(ptr, ZR050_INT_REQ_0, 0);
452 zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
453
454 /* volume control settings */
455 /*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/
456 zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8);
457 zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff);
458
459 zr36050_write(ptr, ZR050_AF_HI, 0xff);
460 zr36050_write(ptr, ZR050_AF_M, 0xff);
461 zr36050_write(ptr, ZR050_AF_LO, 0xff);
462
463 /* setup the variable jpeg tables */
464 sum += zr36050_set_sof(ptr);
465 sum += zr36050_set_sos(ptr);
466 sum += zr36050_set_dri(ptr);
467
468 /* setup the fixed jpeg tables - maybe variable, though -
469 * (see table init section above) */
470 dprintk(3, "%s: write DQT, DHT, APP\n", ptr->name);
471 sum += zr36050_pushit(ptr, ZR050_DQT_IDX,
472 sizeof(zr36050_dqt), zr36050_dqt);
473 sum += zr36050_pushit(ptr, ZR050_DHT_IDX,
474 sizeof(zr36050_dht), zr36050_dht);
475 zr36050_write(ptr, ZR050_APP_IDX, 0xff);
476 zr36050_write(ptr, ZR050_APP_IDX + 1, 0xe0 + ptr->app.appn);
477 zr36050_write(ptr, ZR050_APP_IDX + 2, 0x00);
478 zr36050_write(ptr, ZR050_APP_IDX + 3, ptr->app.len + 2);
479 sum += zr36050_pushit(ptr, ZR050_APP_IDX + 4, 60,
480 ptr->app.data) + 4;
481 zr36050_write(ptr, ZR050_COM_IDX, 0xff);
482 zr36050_write(ptr, ZR050_COM_IDX + 1, 0xfe);
483 zr36050_write(ptr, ZR050_COM_IDX + 2, 0x00);
484 zr36050_write(ptr, ZR050_COM_IDX + 3, ptr->com.len + 2);
485 sum += zr36050_pushit(ptr, ZR050_COM_IDX + 4, 60,
486 ptr->com.data) + 4;
487
488 /* do the internal huffman table preload */
489 zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
490
491 zr36050_write(ptr, ZR050_GO, 1); // launch codec
492 zr36050_wait_end(ptr);
493 dprintk(2, "%s: Status after table preload: 0x%02x\n",
494 ptr->name, ptr->status1);
495
496 if ((ptr->status1 & 0x4) == 0) {
497 dprintk(1, KERN_ERR "%s: init aborted!\n",
498 ptr->name);
499 return; // something is wrong, its timed out!!!!
500 }
501
502 /* setup misc. data for compression (target code sizes) */
503
504 /* size of compressed code to reach without header data */
505 sum = ptr->real_code_vol - sum;
506 bitcnt = sum << 3; /* need the size in bits */
507
508 tmp = bitcnt >> 16;
509 dprintk(3,
510 "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
511 ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
512 zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8);
513 zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff);
514 tmp = bitcnt & 0xffff;
515 zr36050_write(ptr, ZR050_TCV_NET_ML, tmp >> 8);
516 zr36050_write(ptr, ZR050_TCV_NET_LO, tmp & 0xff);
517
518 bitcnt -= bitcnt >> 7; // bits without stuffing
519 bitcnt -= ((bitcnt * 5) >> 6); // bits without eob
520
521 tmp = bitcnt >> 16;
522 dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
523 ptr->name, bitcnt, tmp);
524 zr36050_write(ptr, ZR050_TCV_DATA_HI, tmp >> 8);
525 zr36050_write(ptr, ZR050_TCV_DATA_MH, tmp & 0xff);
526 tmp = bitcnt & 0xffff;
527 zr36050_write(ptr, ZR050_TCV_DATA_ML, tmp >> 8);
528 zr36050_write(ptr, ZR050_TCV_DATA_LO, tmp & 0xff);
529
530 /* compression setup with or without bitrate control */
531 zr36050_write(ptr, ZR050_MODE,
532 ZR050_MO_COMP | ZR050_MO_PASS2 |
533 (ptr->bitrate_ctrl ? ZR050_MO_BRC : 0));
534
535 /* this headers seem to deliver "valid AVI" jpeg frames */
536 zr36050_write(ptr, ZR050_MARKERS_EN,
537 ZR050_ME_DQT | ZR050_ME_DHT |
538 ((ptr->app.len > 0) ? ZR050_ME_APP : 0) |
539 ((ptr->com.len > 0) ? ZR050_ME_COM : 0));
540 } else {
541 dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
542
543 /* 050 communicates with 055 in master mode */
544 zr36050_write(ptr, ZR050_HARDWARE,
545 ZR050_HW_MSTR | ZR050_HW_CFIS_2_CLK);
546
547 /* encoding table preload */
548 zr36050_write(ptr, ZR050_MODE, ZR050_MO_TLM);
549
550 /* disable all IRQs */
551 zr36050_write(ptr, ZR050_INT_REQ_0, 0);
552 zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
553
554 dprintk(3, "%s: write DHT\n", ptr->name);
555 zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht),
556 zr36050_dht);
557
558 /* do the internal huffman table preload */
559 zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
560
561 zr36050_write(ptr, ZR050_GO, 1); // launch codec
562 zr36050_wait_end(ptr);
563 dprintk(2, "%s: Status after table preload: 0x%02x\n",
564 ptr->name, ptr->status1);
565
566 if ((ptr->status1 & 0x4) == 0) {
567 dprintk(1, KERN_ERR "%s: init aborted!\n",
568 ptr->name);
569 return; // something is wrong, its timed out!!!!
570 }
571
572 /* setup misc. data for expansion */
573 zr36050_write(ptr, ZR050_MODE, 0);
574 zr36050_write(ptr, ZR050_MARKERS_EN, 0);
575 }
576
577 /* adr on selected, to allow GO from master */
578 zr36050_read(ptr, 0);
579}
580
581/* =========================================================================
582 CODEC API FUNCTIONS
583
584 this functions are accessed by the master via the API structure
585 ========================================================================= */
586
587/* set compression/expansion mode and launches codec -
588 this should be the last call from the master before starting processing */
589static int
590zr36050_set_mode (struct videocodec *codec,
591 int mode)
592{
593 struct zr36050 *ptr = (struct zr36050 *) codec->data;
594
595 dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
596
597 if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
598 return -EINVAL;
599
600 ptr->mode = mode;
601 zr36050_init(ptr);
602
603 return 0;
604}
605
606/* set picture size (norm is ignored as the codec doesn't know about it) */
607static int
608zr36050_set_video (struct videocodec *codec,
609 struct tvnorm *norm,
610 struct vfe_settings *cap,
611 struct vfe_polarity *pol)
612{
613 struct zr36050 *ptr = (struct zr36050 *) codec->data;
614 int size;
615
616 dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n",
617 ptr->name, norm->HStart, norm->VStart,
618 cap->x, cap->y, cap->width, cap->height,
619 cap->decimation, cap->quality);
620 /* if () return -EINVAL;
621 * trust the master driver that it knows what it does - so
622 * we allow invalid startx/y and norm for now ... */
623 ptr->width = cap->width / (cap->decimation & 0xff);
624 ptr->height = cap->height / ((cap->decimation >> 8) & 0xff);
625
626 /* (KM) JPEG quality */
627 size = ptr->width * ptr->height;
628 size *= 16; /* size in bits */
629 /* apply quality setting */
630 size = size * cap->quality / 200;
631
632 /* Minimum: 1kb */
633 if (size < 8192)
634 size = 8192;
635 /* Maximum: 7/8 of code buffer */
636 if (size > ptr->total_code_vol * 7)
637 size = ptr->total_code_vol * 7;
638
639 ptr->real_code_vol = size >> 3; /* in bytes */
640
641 /* Set max_block_vol here (previously in zr36050_init, moved
642 * here for consistency with zr36060 code */
643 zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);
644
645 return 0;
646}
647
648/* additional control functions */
649static int
650zr36050_control (struct videocodec *codec,
651 int type,
652 int size,
653 void *data)
654{
655 struct zr36050 *ptr = (struct zr36050 *) codec->data;
656 int *ival = (int *) data;
657
658 dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
659 size);
660
661 switch (type) {
662 case CODEC_G_STATUS: /* get last status */
663 if (size != sizeof(int))
664 return -EFAULT;
665 zr36050_read_status1(ptr);
666 *ival = ptr->status1;
667 break;
668
669 case CODEC_G_CODEC_MODE:
670 if (size != sizeof(int))
671 return -EFAULT;
672 *ival = CODEC_MODE_BJPG;
673 break;
674
675 case CODEC_S_CODEC_MODE:
676 if (size != sizeof(int))
677 return -EFAULT;
678 if (*ival != CODEC_MODE_BJPG)
679 return -EINVAL;
680 /* not needed, do nothing */
681 return 0;
682
683 case CODEC_G_VFE:
684 case CODEC_S_VFE:
685 /* not needed, do nothing */
686 return 0;
687
688 case CODEC_S_MMAP:
689 /* not available, give an error */
690 return -ENXIO;
691
692 case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */
693 if (size != sizeof(int))
694 return -EFAULT;
695 *ival = ptr->total_code_vol;
696 break;
697
698 case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */
699 if (size != sizeof(int))
700 return -EFAULT;
701 ptr->total_code_vol = *ival;
702 /* (Kieran Morrissey)
703 * code copied from zr36060.c to ensure proper bitrate */
704 ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
705 break;
706
707 case CODEC_G_JPEG_SCALE: /* get scaling factor */
708 if (size != sizeof(int))
709 return -EFAULT;
710 *ival = zr36050_read_scalefactor(ptr);
711 break;
712
713 case CODEC_S_JPEG_SCALE: /* set scaling factor */
714 if (size != sizeof(int))
715 return -EFAULT;
716 ptr->scalefact = *ival;
717 break;
718
719 case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */
720 struct jpeg_app_marker *app = data;
721
722 if (size != sizeof(struct jpeg_app_marker))
723 return -EFAULT;
724
725 *app = ptr->app;
726 break;
727 }
728
729 case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */
730 struct jpeg_app_marker *app = data;
731
732 if (size != sizeof(struct jpeg_app_marker))
733 return -EFAULT;
734
735 ptr->app = *app;
736 break;
737 }
738
739 case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */
740 struct jpeg_com_marker *com = data;
741
742 if (size != sizeof(struct jpeg_com_marker))
743 return -EFAULT;
744
745 *com = ptr->com;
746 break;
747 }
748
749 case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */
750 struct jpeg_com_marker *com = data;
751
752 if (size != sizeof(struct jpeg_com_marker))
753 return -EFAULT;
754
755 ptr->com = *com;
756 break;
757 }
758
759 default:
760 return -EINVAL;
761 }
762
763 return size;
764}
765
766/* =========================================================================
767 Exit and unregister function:
768
769 Deinitializes Zoran's JPEG processor
770 ========================================================================= */
771
772static int
773zr36050_unset (struct videocodec *codec)
774{
775 struct zr36050 *ptr = codec->data;
776
777 if (ptr) {
778 /* do wee need some codec deinit here, too ???? */
779
780 dprintk(1, "%s: finished codec #%d\n", ptr->name,
781 ptr->num);
782 kfree(ptr);
783 codec->data = NULL;
784
785 zr36050_codecs--;
786 return 0;
787 }
788
789 return -EFAULT;
790}
791
792/* =========================================================================
793 Setup and registry function:
794
795 Initializes Zoran's JPEG processor
796
797 Also sets pixel size, average code size, mode (compr./decompr.)
798 (the given size is determined by the processor with the video interface)
799 ========================================================================= */
800
801static int
802zr36050_setup (struct videocodec *codec)
803{
804 struct zr36050 *ptr;
805 int res;
806
807 dprintk(2, "zr36050: initializing MJPEG subsystem #%d.\n",
808 zr36050_codecs);
809
810 if (zr36050_codecs == MAX_CODECS) {
811 dprintk(1,
812 KERN_ERR "zr36050: Can't attach more codecs!\n");
813 return -ENOSPC;
814 }
815 //mem structure init
Panagiotis Issaris74081872006-01-11 19:40:56 -0200816 codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 if (NULL == ptr) {
818 dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n");
819 return -ENOMEM;
820 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822 snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]",
823 zr36050_codecs);
824 ptr->num = zr36050_codecs++;
825 ptr->codec = codec;
826
827 //testing
828 res = zr36050_basic_test(ptr);
829 if (res < 0) {
830 zr36050_unset(codec);
831 return res;
832 }
833 //final setup
834 memcpy(ptr->h_samp_ratio, zr36050_decimation_h, 8);
835 memcpy(ptr->v_samp_ratio, zr36050_decimation_v, 8);
836
837 ptr->bitrate_ctrl = 0; /* 0 or 1 - fixed file size flag
838 * (what is the difference?) */
839 ptr->mode = CODEC_DO_COMPRESSION;
840 ptr->width = 384;
841 ptr->height = 288;
842 ptr->total_code_vol = 16000;
843 ptr->max_block_vol = 240;
844 ptr->scalefact = 0x100;
845 ptr->dri = 1;
846
847 /* no app/com marker by default */
848 ptr->app.appn = 0;
849 ptr->app.len = 0;
850 ptr->com.len = 0;
851
852 zr36050_init(ptr);
853
854 dprintk(1, KERN_INFO "%s: codec attached and running\n",
855 ptr->name);
856
857 return 0;
858}
859
860static const struct videocodec zr36050_codec = {
861 .owner = THIS_MODULE,
862 .name = "zr36050",
863 .magic = 0L, // magic not used
864 .flags =
865 CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
866 CODEC_FLAG_DECODER,
867 .type = CODEC_TYPE_ZR36050,
868 .setup = zr36050_setup, // functionality
869 .unset = zr36050_unset,
870 .set_mode = zr36050_set_mode,
871 .set_video = zr36050_set_video,
872 .control = zr36050_control,
873 // others are not used
874};
875
876/* =========================================================================
877 HOOK IN DRIVER AS KERNEL MODULE
878 ========================================================================= */
879
880static int __init
881zr36050_init_module (void)
882{
883 //dprintk(1, "ZR36050 driver %s\n",ZR050_VERSION);
884 zr36050_codecs = 0;
885 return videocodec_register(&zr36050_codec);
886}
887
888static void __exit
889zr36050_cleanup_module (void)
890{
891 if (zr36050_codecs) {
892 dprintk(1,
893 "zr36050: something's wrong - %d codecs left somehow.\n",
894 zr36050_codecs);
895 }
896 videocodec_unregister(&zr36050_codec);
897}
898
899module_init(zr36050_init_module);
900module_exit(zr36050_cleanup_module);
901
902MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
903MODULE_DESCRIPTION("Driver module for ZR36050 jpeg processors "
904 ZR050_VERSION);
905MODULE_LICENSE("GPL");