Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[linux-2.6] / drivers / media / video / zr36016.c
1 /*
2  * Zoran ZR36016 basic configuration functions
3  *
4  * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
5  *
6  * $Id: zr36016.c,v 1.1.2.14 2003/08/20 19:46:55 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 ZR016_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 /* includes for structures and defines regarding video 
38    #include<linux/videodev.h> */
39
40 /* I/O commands, error codes */
41 #include<asm/io.h>
42 //#include<errno.h>
43
44 /* v4l  API */
45 #include<linux/videodev.h>
46
47 /* headerfile of this module */
48 #include"zr36016.h"
49
50 /* codec io API */
51 #include"videocodec.h"
52
53 /* it doesn't make sense to have more than 20 or so,
54   just to prevent some unwanted loops */
55 #define MAX_CODECS 20
56
57 /* amount of chips attached via this driver */
58 static int zr36016_codecs = 0;
59
60 /* debugging is available via module parameter */
61
62 static int debug = 0;
63 module_param(debug, int, 0);
64 MODULE_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    Local hardware I/O functions:
74
75    read/write via codec layer (registers are located in the master device)
76    ========================================================================= */
77
78 /* read and write functions */
79 static u8
80 zr36016_read (struct zr36016 *ptr,
81               u16             reg)
82 {
83         u8 value = 0;
84
85         // just in case something is wrong...
86         if (ptr->codec->master_data->readreg)
87                 value =
88                     (ptr->codec->master_data->
89                      readreg(ptr->codec, reg)) & 0xFF;
90         else
91                 dprintk(1,
92                         KERN_ERR "%s: invalid I/O setup, nothing read!\n",
93                         ptr->name);
94
95         dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
96                 value);
97
98         return value;
99 }
100
101 static void
102 zr36016_write (struct zr36016 *ptr,
103                u16             reg,
104                u8              value)
105 {
106         dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
107                 reg);
108
109         // just in case something is wrong...
110         if (ptr->codec->master_data->writereg) {
111                 ptr->codec->master_data->writereg(ptr->codec, reg, value);
112         } else
113                 dprintk(1,
114                         KERN_ERR
115                         "%s: invalid I/O setup, nothing written!\n",
116                         ptr->name);
117 }
118
119 /* indirect read and write functions */
120 /* the 016 supports auto-addr-increment, but
121  * writing it all time cost not much and is safer... */
122 static u8
123 zr36016_readi (struct zr36016 *ptr,
124                u16             reg)
125 {
126         u8 value = 0;
127
128         // just in case something is wrong...
129         if ((ptr->codec->master_data->writereg) &&
130             (ptr->codec->master_data->readreg)) {
131                 ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
132                 value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF;     // DATA
133         } else
134                 dprintk(1,
135                         KERN_ERR
136                         "%s: invalid I/O setup, nothing read (i)!\n",
137                         ptr->name);
138
139         dprintk(4, "%s: reading indirect from 0x%04x: %02x\n", ptr->name,
140                 reg, value);
141         return value;
142 }
143
144 static void
145 zr36016_writei (struct zr36016 *ptr,
146                 u16             reg,
147                 u8              value)
148 {
149         dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name,
150                 value, reg);
151
152         // just in case something is wrong...
153         if (ptr->codec->master_data->writereg) {
154                 ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
155                 ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF);      // DATA
156         } else
157                 dprintk(1,
158                         KERN_ERR
159                         "%s: invalid I/O setup, nothing written (i)!\n",
160                         ptr->name);
161 }
162
163 /* =========================================================================
164    Local helper function:
165
166    version read
167    ========================================================================= */
168
169 /* version kept in datastructure */
170 static u8
171 zr36016_read_version (struct zr36016 *ptr)
172 {
173         ptr->version = zr36016_read(ptr, 0) >> 4;
174         return ptr->version;
175 }
176
177 /* =========================================================================
178    Local helper function:
179
180    basic test of "connectivity", writes/reads to/from PAX-Lo register
181    ========================================================================= */
182
183 static int
184 zr36016_basic_test (struct zr36016 *ptr)
185 {
186         if (debug) {
187                 int i;
188                 zr36016_writei(ptr, ZR016I_PAX_LO, 0x55);
189                 dprintk(1, KERN_INFO "%s: registers: ", ptr->name);
190                 for (i = 0; i <= 0x0b; i++)
191                         dprintk(1, "%02x ", zr36016_readi(ptr, i));
192                 dprintk(1, "\n");
193         }
194         // for testing just write 0, then the default value to a register and read
195         // it back in both cases 
196         zr36016_writei(ptr, ZR016I_PAX_LO, 0x00);
197         if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) {
198                 dprintk(1,
199                         KERN_ERR
200                         "%s: attach failed, can't connect to vfe processor!\n",
201                         ptr->name);
202                 return -ENXIO;
203         }
204         zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0);
205         if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) {
206                 dprintk(1,
207                         KERN_ERR
208                         "%s: attach failed, can't connect to vfe processor!\n",
209                         ptr->name);
210                 return -ENXIO;
211         }
212         // we allow version numbers from 0-3, should be enough, though
213         zr36016_read_version(ptr);
214         if (ptr->version & 0x0c) {
215                 dprintk(1,
216                         KERN_ERR
217                         "%s: attach failed, suspicious version %d found...\n",
218                         ptr->name, ptr->version);
219                 return -ENXIO;
220         }
221
222         return 0;               /* looks good! */
223 }
224
225 /* =========================================================================
226    Local helper function:
227
228    simple loop for pushing the init datasets - NO USE --
229    ========================================================================= */
230
231 #if 0
232 static int zr36016_pushit (struct zr36016 *ptr,
233                            u16             startreg,
234                            u16             len,
235                            const char     *data)
236 {
237         int i=0;
238
239         dprintk(4, "%s: write data block to 0x%04x (len=%d)\n",
240                 ptr->name, startreg,len);
241         while (i<len) {
242                 zr36016_writei(ptr, startreg++,  data[i++]);
243         }
244
245         return i;
246 }
247 #endif
248
249 /* =========================================================================
250    Basic datasets & init:
251
252    //TODO//
253    ========================================================================= */
254
255 // needed offset values          PAL NTSC SECAM
256 static const int zr016_xoff[] = { 20, 20, 20 };
257 static const int zr016_yoff[] = { 8, 9, 7 };
258
259 static void
260 zr36016_init (struct zr36016 *ptr)
261 {
262         // stop any processing
263         zr36016_write(ptr, ZR016_GOSTOP, 0);
264
265         // mode setup (yuv422 in and out, compression/expansuon due to mode)
266         zr36016_write(ptr, ZR016_MODE,
267                       ZR016_YUV422 | ZR016_YUV422_YUV422 |
268                       (ptr->mode == CODEC_DO_COMPRESSION ?
269                        ZR016_COMPRESSION : ZR016_EXPANSION));
270
271         // misc setup
272         zr36016_writei(ptr, ZR016I_SETUP1,
273                        (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) |
274                        (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI);
275         zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR);
276
277         // Window setup
278         // (no extra offset for now, norm defines offset, default width height)
279         zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8);
280         zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF);
281         zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8);
282         zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF);
283         zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8);
284         zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF);
285         zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8);
286         zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF);
287
288         /* shall we continue now, please? */
289         zr36016_write(ptr, ZR016_GOSTOP, 1);
290 }
291
292 /* =========================================================================
293    CODEC API FUNCTIONS
294
295    this functions are accessed by the master via the API structure
296    ========================================================================= */
297
298 /* set compression/expansion mode and launches codec -
299    this should be the last call from the master before starting processing */
300 static int
301 zr36016_set_mode (struct videocodec *codec,
302                   int                mode)
303 {
304         struct zr36016 *ptr = (struct zr36016 *) codec->data;
305
306         dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
307
308         if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
309                 return -EINVAL;
310
311         ptr->mode = mode;
312         zr36016_init(ptr);
313
314         return 0;
315 }
316
317 /* set picture size */
318 static int
319 zr36016_set_video (struct videocodec   *codec,
320                    struct tvnorm       *norm,
321                    struct vfe_settings *cap,
322                    struct vfe_polarity *pol)
323 {
324         struct zr36016 *ptr = (struct zr36016 *) codec->data;
325
326         dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n",
327                 ptr->name, norm->HStart, norm->VStart,
328                 cap->x, cap->y, cap->width, cap->height,
329                 cap->decimation);
330
331         /* if () return -EINVAL;
332          * trust the master driver that it knows what it does - so
333          * we allow invalid startx/y for now ... */
334         ptr->width = cap->width;
335         ptr->height = cap->height;
336         /* (Ronald) This is ugly. zoran_device.c, line 387
337          * already mentions what happens if HStart is even
338          * (blue faces, etc., cr/cb inversed). There's probably
339          * some good reason why HStart is 0 instead of 1, so I'm
340          * leaving it to this for now, but really... This can be
341          * done a lot simpler */
342         ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x;
343         /* Something to note here (I don't understand it), setting
344          * VStart too high will cause the codec to 'not work'. I
345          * really don't get it. values of 16 (VStart) already break
346          * it here. Just '0' seems to work. More testing needed! */
347         ptr->yoff = norm->VStart + cap->y;
348         /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */
349         ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1;
350         ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1;
351
352         return 0;
353 }
354
355 /* additional control functions */
356 static int
357 zr36016_control (struct videocodec *codec,
358                  int                type,
359                  int                size,
360                  void              *data)
361 {
362         struct zr36016 *ptr = (struct zr36016 *) codec->data;
363         int *ival = (int *) data;
364
365         dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
366                 size);
367
368         switch (type) {
369         case CODEC_G_STATUS:    /* get last status - we don't know it ... */
370                 if (size != sizeof(int))
371                         return -EFAULT;
372                 *ival = 0;
373                 break;
374
375         case CODEC_G_CODEC_MODE:
376                 if (size != sizeof(int))
377                         return -EFAULT;
378                 *ival = 0;
379                 break;
380
381         case CODEC_S_CODEC_MODE:
382                 if (size != sizeof(int))
383                         return -EFAULT;
384                 if (*ival != 0)
385                         return -EINVAL;
386                 /* not needed, do nothing */
387                 return 0;
388
389         case CODEC_G_VFE:
390         case CODEC_S_VFE:
391                 return 0;
392
393         case CODEC_S_MMAP:
394                 /* not available, give an error */
395                 return -ENXIO;
396
397         default:
398                 return -EINVAL;
399         }
400
401         return size;
402 }
403
404 /* =========================================================================
405    Exit and unregister function:
406
407    Deinitializes Zoran's JPEG processor
408    ========================================================================= */
409
410 static int
411 zr36016_unset (struct videocodec *codec)
412 {
413         struct zr36016 *ptr = codec->data;
414
415         if (ptr) {
416                 /* do wee need some codec deinit here, too ???? */
417
418                 dprintk(1, "%s: finished codec #%d\n", ptr->name,
419                         ptr->num);
420                 kfree(ptr);
421                 codec->data = NULL;
422
423                 zr36016_codecs--;
424                 return 0;
425         }
426
427         return -EFAULT;
428 }
429
430 /* =========================================================================
431    Setup and registry function:
432
433    Initializes Zoran's JPEG processor
434
435    Also sets pixel size, average code size, mode (compr./decompr.)
436    (the given size is determined by the processor with the video interface)
437    ========================================================================= */
438
439 static int
440 zr36016_setup (struct videocodec *codec)
441 {
442         struct zr36016 *ptr;
443         int res;
444
445         dprintk(2, "zr36016: initializing VFE subsystem #%d.\n",
446                 zr36016_codecs);
447
448         if (zr36016_codecs == MAX_CODECS) {
449                 dprintk(1,
450                         KERN_ERR "zr36016: Can't attach more codecs!\n");
451                 return -ENOSPC;
452         }
453         //mem structure init
454         codec->data = ptr = kmalloc(sizeof(struct zr36016), GFP_KERNEL);
455         if (NULL == ptr) {
456                 dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n");
457                 return -ENOMEM;
458         }
459         memset(ptr, 0, sizeof(struct zr36016));
460
461         snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]",
462                  zr36016_codecs);
463         ptr->num = zr36016_codecs++;
464         ptr->codec = codec;
465
466         //testing
467         res = zr36016_basic_test(ptr);
468         if (res < 0) {
469                 zr36016_unset(codec);
470                 return res;
471         }
472         //final setup
473         ptr->mode = CODEC_DO_COMPRESSION;
474         ptr->width = 768;
475         ptr->height = 288;
476         ptr->xdec = 1;
477         ptr->ydec = 0;
478         zr36016_init(ptr);
479
480         dprintk(1, KERN_INFO "%s: codec v%d attached and running\n",
481                 ptr->name, ptr->version);
482
483         return 0;
484 }
485
486 static const struct videocodec zr36016_codec = {
487         .owner = THIS_MODULE,
488         .name = "zr36016",
489         .magic = 0L,            // magic not used
490         .flags =
491             CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER |
492             CODEC_FLAG_DECODER,
493         .type = CODEC_TYPE_ZR36016,
494         .setup = zr36016_setup, // functionality
495         .unset = zr36016_unset,
496         .set_mode = zr36016_set_mode,
497         .set_video = zr36016_set_video,
498         .control = zr36016_control,
499         // others are not used
500 };
501
502 /* =========================================================================
503    HOOK IN DRIVER AS KERNEL MODULE
504    ========================================================================= */
505
506 static int __init
507 zr36016_init_module (void)
508 {
509         //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION);
510         zr36016_codecs = 0;
511         return videocodec_register(&zr36016_codec);
512 }
513
514 static void __exit
515 zr36016_cleanup_module (void)
516 {
517         if (zr36016_codecs) {
518                 dprintk(1,
519                         "zr36016: something's wrong - %d codecs left somehow.\n",
520                         zr36016_codecs);
521         }
522         videocodec_unregister(&zr36016_codec);
523 }
524
525 module_init(zr36016_init_module);
526 module_exit(zr36016_cleanup_module);
527
528 MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
529 MODULE_DESCRIPTION("Driver module for ZR36016 video frontends "
530                    ZR016_VERSION);
531 MODULE_LICENSE("GPL");