import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / media / video / saa7185.c
1 /* 
2     saa7185 - Philips SAA7185B video encoder driver version 0.0.3
3
4     Copyright (C) 1998 Dave Perks <dperks@ibm.net>
5
6     Slight changes for video timing and attachment output by
7     Wolfgang Scherr <scherr@net4you.net>
8     
9     This program is free software; you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation; either version 2 of the License, or
12     (at your option) any later version.
13
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18
19     You should have received a copy of the GNU General Public License
20     along with this program; if not, write to the Free Software
21     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/delay.h>
27 #include <linux/errno.h>
28 #include <linux/fs.h>
29 #include <linux/kernel.h>
30 #include <linux/major.h>
31 #include <linux/slab.h>
32 #include <linux/mm.h>
33 #include <linux/pci.h>
34 #include <linux/signal.h>
35 #include <asm/io.h>
36 #include <asm/pgtable.h>
37 #include <asm/page.h>
38 #include <linux/sched.h>
39 #include <asm/segment.h>
40 #include <linux/types.h>
41 #include <linux/wrapper.h>
42
43 #include <linux/videodev.h>
44 #include <linux/version.h>
45 #include <asm/uaccess.h>
46
47 #include <linux/i2c-old.h>
48
49 #include <linux/video_encoder.h>
50
51 #define DEBUG(x)                /* Debug driver */
52
53 /* ----------------------------------------------------------------------- */
54
55 struct saa7185 {
56         struct i2c_bus *bus;
57         int addr;
58         unsigned char reg[128];
59
60         int norm;
61         int enable;
62         int bright;
63         int contrast;
64         int hue;
65         int sat;
66 };
67
68 #define   I2C_SAA7185        0x88
69
70 #define I2C_DELAY   10
71
72 /* ----------------------------------------------------------------------- */
73
74 static int saa7185_read(struct saa7185 *dev)
75 {
76         int ack;
77
78         LOCK_I2C_BUS(dev->bus);
79
80         i2c_start(dev->bus);
81         i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY);
82         ack = i2c_readbyte(dev->bus, 1);
83         i2c_stop(dev->bus);
84         UNLOCK_I2C_BUS(dev->bus);
85         return ack;
86 }
87
88 static int saa7185_write(struct saa7185 *dev, unsigned char subaddr,
89                          unsigned char data)
90 {
91         int ack;
92
93         DEBUG(printk
94               (KERN_DEBUG "SAA7185: %02x set to %02x\n", subaddr, data);
95             )
96             LOCK_I2C_BUS(dev->bus);
97
98         i2c_start(dev->bus);
99         i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
100         i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
101         ack = i2c_sendbyte(dev->bus, data, I2C_DELAY);
102         dev->reg[subaddr] = data;
103         i2c_stop(dev->bus);
104         UNLOCK_I2C_BUS(dev->bus);
105         return ack;
106 }
107
108 static int saa7185_write_block(struct saa7185 *dev,
109                                unsigned const char *data, unsigned int len)
110 {
111         int ack = -1;
112         unsigned subaddr;
113
114         while (len > 1) {
115                 LOCK_I2C_BUS(dev->bus);
116                 i2c_start(dev->bus);
117                 i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
118                 ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY);
119                 ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
120                 len -= 2;
121                 while (len > 1 && *data == ++subaddr) {
122                         data++;
123                         ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
124                         len -= 2;
125                 }
126                 i2c_stop(dev->bus);
127                 UNLOCK_I2C_BUS(dev->bus);
128         }
129         return ack;
130 }
131
132 /* ----------------------------------------------------------------------- */
133
134 static const unsigned char init_common[] = {
135         0x3a, 0x0f,             /* CBENB=0, V656=0, VY2C=1, YUV2C=1, MY2C=1, MUV2C=1 */
136
137         0x42, 0x6b,             /* OVLY0=107 */
138         0x43, 0x00,             /* OVLU0=0     white */
139         0x44, 0x00,             /* OVLV0=0   */
140         0x45, 0x22,             /* OVLY1=34  */
141         0x46, 0xac,             /* OVLU1=172   yellow */
142         0x47, 0x0e,             /* OVLV1=14  */
143         0x48, 0x03,             /* OVLY2=3   */
144         0x49, 0x1d,             /* OVLU2=29    cyan */
145         0x4a, 0xac,             /* OVLV2=172 */
146         0x4b, 0xf0,             /* OVLY3=240 */
147         0x4c, 0xc8,             /* OVLU3=200   green */
148         0x4d, 0xb9,             /* OVLV3=185 */
149         0x4e, 0xd4,             /* OVLY4=212 */
150         0x4f, 0x38,             /* OVLU4=56    magenta */
151         0x50, 0x47,             /* OVLV4=71  */
152         0x51, 0xc1,             /* OVLY5=193 */
153         0x52, 0xe3,             /* OVLU5=227   red */
154         0x53, 0x54,             /* OVLV5=84  */
155         0x54, 0xa3,             /* OVLY6=163 */
156         0x55, 0x54,             /* OVLU6=84    blue */
157         0x56, 0xf2,             /* OVLV6=242 */
158         0x57, 0x90,             /* OVLY7=144 */
159         0x58, 0x00,             /* OVLU7=0     black */
160         0x59, 0x00,             /* OVLV7=0   */
161
162         0x5a, 0x00,             /* CHPS=0    */
163         0x5b, 0x76,             /* GAINU=118 */
164         0x5c, 0xa5,             /* GAINV=165 */
165         0x5d, 0x3c,             /* BLCKL=60  */
166         0x5e, 0x3a,             /* BLNNL=58  */
167         0x5f, 0x3a,             /* CCRS=0, BLNVB=58 */
168         0x60, 0x00,             /* NULL      */
169
170 /* 0x61 - 0x66 set according to norm */
171
172         0x67, 0x00,             /* 0 : caption 1st byte odd  field */
173         0x68, 0x00,             /* 0 : caption 2nd byte odd  field */
174         0x69, 0x00,             /* 0 : caption 1st byte even field */
175         0x6a, 0x00,             /* 0 : caption 2nd byte even field */
176
177         0x6b, 0x91,             /* MODIN=2, PCREF=0, SCCLN=17 */
178         0x6c, 0x20,             /* SRCV1=0, TRCV2=1, ORCV1=0, PRCV1=0, CBLF=0, ORCV2=0, PRCV2=0 */
179         0x6d, 0x00,             /* SRCM1=0, CCEN=0 */
180
181         0x6e, 0x0e,             /* HTRIG=0x005, approx. centered, at least for PAL */
182         0x6f, 0x00,             /* HTRIG upper bits */
183         0x70, 0x20,             /* PHRES=0, SBLN=1, VTRIG=0 */
184
185 /* The following should not be needed */
186
187         0x71, 0x15,             /* BMRQ=0x115 */
188         0x72, 0x90,             /* EMRQ=0x690 */
189         0x73, 0x61,             /* EMRQ=0x690, BMRQ=0x115 */
190         0x74, 0x00,             /* NULL       */
191         0x75, 0x00,             /* NULL       */
192         0x76, 0x00,             /* NULL       */
193         0x77, 0x15,             /* BRCV=0x115 */
194         0x78, 0x90,             /* ERCV=0x690 */
195         0x79, 0x61,             /* ERCV=0x690, BRCV=0x115 */
196
197 /* Field length controls */
198
199         0x7a, 0x70,             /* FLC=0 */
200
201 /* The following should not be needed if SBLN = 1 */
202
203         0x7b, 0x16,             /* FAL=22 */
204         0x7c, 0x35,             /* LAL=244 */
205         0x7d, 0x20,             /* LAL=244, FAL=22 */
206 };
207
208 static const unsigned char init_pal[] = {
209         0x61, 0x1e,             /* FISE=0, PAL=1, SCBW=1, RTCE=1, YGS=1, INPI=0, DOWN=0 */
210         0x62, 0xc8,             /* DECTYP=1, BSTA=72 */
211         0x63, 0xcb,             /* FSC0 */
212         0x64, 0x8a,             /* FSC1 */
213         0x65, 0x09,             /* FSC2 */
214         0x66, 0x2a,             /* FSC3 */
215 };
216
217 static const unsigned char init_ntsc[] = {
218         0x61, 0x1d,             /* FISE=1, PAL=0, SCBW=1, RTCE=1, YGS=1, INPI=0, DOWN=0 */
219         0x62, 0xe6,             /* DECTYP=1, BSTA=102 */
220         0x63, 0x1f,             /* FSC0 */
221         0x64, 0x7c,             /* FSC1 */
222         0x65, 0xf0,             /* FSC2 */
223         0x66, 0x21,             /* FSC3 */
224 };
225
226 static int saa7185_attach(struct i2c_device *device)
227 {
228         int i;
229         struct saa7185 *encoder;
230
231         MOD_INC_USE_COUNT;
232         
233         device->data = encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL);
234         if (encoder == NULL) {
235                 MOD_DEC_USE_COUNT;
236                 return -ENOMEM;
237         }
238
239
240         memset(encoder, 0, sizeof(struct saa7185));
241         strcpy(device->name, "saa7185");
242         encoder->bus = device->bus;
243         encoder->addr = device->addr;
244         encoder->norm = VIDEO_MODE_NTSC;
245         encoder->enable = 1;
246
247         i = saa7185_write_block(encoder, init_common, sizeof(init_common));
248         if (i >= 0) {
249                 i = saa7185_write_block(encoder, init_ntsc,
250                                         sizeof(init_ntsc));
251         }
252         if (i < 0) {
253                 printk(KERN_ERR "%s_attach: init error %d\n", device->name,
254                        i);
255         } else {
256                 printk(KERN_INFO "%s_attach: chip version %d\n",
257                        device->name, saa7185_read(encoder) >> 5);
258         }
259
260         return 0;
261 }
262
263
264 static int saa7185_detach(struct i2c_device *device)
265 {
266         struct saa7185 *encoder = device->data;
267         saa7185_write(encoder, 0x61, (encoder->reg[0x61]) | 0x40);      /* SW: output off is active */
268         //saa7185_write(encoder, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */
269         kfree(encoder);
270         MOD_DEC_USE_COUNT;
271         return 0;
272 }
273
274 static int saa7185_command(struct i2c_device *device, unsigned int cmd,
275                            void *arg)
276 {
277         struct saa7185 *encoder = device->data;
278
279         switch (cmd) {
280
281         case ENCODER_GET_CAPABILITIES:
282                 {
283                         struct video_encoder_capability *cap = arg;
284
285                         cap->flags
286                             = VIDEO_ENCODER_PAL
287                             | VIDEO_ENCODER_NTSC
288                             | VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR;
289                         cap->inputs = 1;
290                         cap->outputs = 1;
291                 }
292                 break;
293
294         case ENCODER_SET_NORM:
295                 {
296                         int *iarg = arg;
297
298                         switch (*iarg) {
299
300                         case VIDEO_MODE_NTSC:
301                                 saa7185_write_block(encoder, init_ntsc,
302                                                     sizeof(init_ntsc));
303                                 break;
304
305                         case VIDEO_MODE_PAL:
306                                 saa7185_write_block(encoder, init_pal,
307                                                     sizeof(init_pal));
308                                 break;
309
310                         case VIDEO_MODE_SECAM:
311                         default:
312                                 return -EINVAL;
313
314                         }
315                         encoder->norm = *iarg;
316                 }
317                 break;
318
319         case ENCODER_SET_INPUT:
320                 {
321                         int *iarg = arg;
322
323                         /* RJ: *iarg = 0: input is from SA7111
324                            *iarg = 1: input is from ZR36060 */
325
326                         switch (*iarg) {
327
328                         case 0:
329                                 /* Switch RTCE to 1 */
330                                 saa7185_write(encoder, 0x61,
331                                               (encoder->
332                                                reg[0x61] & 0xf7) | 0x08);
333                                 saa7185_write(encoder, 0x6e, 0x01);
334                                 break;
335
336                         case 1:
337                                 /* Switch RTCE to 0 */
338                                 saa7185_write(encoder, 0x61,
339                                               (encoder->
340                                                reg[0x61] & 0xf7) | 0x00);
341                                 /* SW: a slight sync problem... */
342                                 saa7185_write(encoder, 0x6e, 0x00);
343                                 break;
344
345                         default:
346                                 return -EINVAL;
347
348                         }
349                 }
350                 break;
351
352         case ENCODER_SET_OUTPUT:
353                 {
354                         int *iarg = arg;
355
356                         /* not much choice of outputs */
357                         if (*iarg != 0) {
358                                 return -EINVAL;
359                         }
360                 }
361                 break;
362
363         case ENCODER_ENABLE_OUTPUT:
364                 {
365                         int *iarg = arg;
366
367                         encoder->enable = !!*iarg;
368                         saa7185_write(encoder, 0x61,
369                                       (encoder->
370                                        reg[0x61] & 0xbf) | (encoder->
371                                                             enable ? 0x00 :
372                                                             0x40));
373                 }
374                 break;
375
376         default:
377                 return -EINVAL;
378         }
379
380         return 0;
381 }
382
383 /* ----------------------------------------------------------------------- */
384
385 static struct i2c_driver i2c_driver_saa7185 = {
386         "saa7185",              /* name */
387         I2C_DRIVERID_VIDEOENCODER,      /* ID */
388         I2C_SAA7185, I2C_SAA7185 + 1,
389
390         saa7185_attach,
391         saa7185_detach,
392         saa7185_command
393 };
394
395 EXPORT_NO_SYMBOLS;
396
397 static int saa7185_init(void)
398 {
399         return i2c_register_driver(&i2c_driver_saa7185);
400 }
401
402 static void saa7185_exit(void)
403 {
404         i2c_unregister_driver(&i2c_driver_saa7185);
405 }
406
407 module_init(saa7185_init);
408 module_exit(saa7185_exit);
409 MODULE_LICENSE("GPL");