Subversion Repositories shark

Rev

Rev 425 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
425 giacomo 1
/*
2
    saa7111 - Philips SAA7111A video decoder 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/sched.h>
34
 
35
#include <linux/videodev.h>
36
#include <linux/version.h>
37
#include <linux/i2c.h>
38
 
39
#include <linux/video_decoder.h>
40
 
41
#define DEBUG(x)                /* Debug driver */
42
 
43
/* ----------------------------------------------------------------------- */
44
 
45
struct saa7111 {
46
        struct i2c_client *client;
47
        int addr;
48
        struct semaphore lock;
49
        unsigned char reg[32];
50
 
51
        int norm;
52
        int input;
53
        int enable;
54
        int bright;
55
        int contrast;
56
        int hue;
57
        int sat;
58
};
59
 
60
static unsigned short normal_i2c[] = { 0x24, 0x25, I2C_CLIENT_END };   
61
static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; 
62
 
63
I2C_CLIENT_INSMOD;
64
 
65
static struct i2c_client client_template;
66
/* ----------------------------------------------------------------------- */
67
static int saa7111_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)
68
{
69
        int i;
70
        struct saa7111 *decoder;
71
        struct i2c_client *client;
72
 
73
        /* who wrote this? init[] is used for i2c_master_send() which expects an array that
74
           will be used for the 'buf' part of an i2c message unchanged. so, the first byte
75
           needs to be the subaddress to start with, then follow the data bytes... */
76
        static const unsigned char init[] = {
77
                0x00,     /* start address */
78
 
79
                0x00,     /* 00 - ID byte */
80
                0x00,     /* 01 - reserved */
81
 
82
                /*front end */
83
                0xd0,     /* 02 - FUSE=3, GUDL=2, MODE=0 */
84
                0x23,     /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
85
                0x00,     /* 04 - GAI1=256 */
86
                0x00,     /* 05 - GAI2=256 */
87
 
88
                /* decoder */
89
                0xf3,     /* 06 - HSB at  13(50Hz) /  17(60Hz) pixels after end of last line */
90
                0x13,     /* 07 - HSS at 113(50Hz) / 117(60Hz) pixels after end of last line */
91
                0xc8,     /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1, HPLL=0, VNOI=0 */
92
                0x01,     /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0, UPTCV=0, APER=1 */
93
                0x80,     /* 0a - BRIG=128 */
94
                0x47,     /* 0b - CONT=1.109 */
95
                0x40,     /* 0c - SATN=1.0 */
96
                0x00,     /* 0d - HUE=0 */
97
                0x01,     /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
98
                0x00,     /* 0f - reserved */
99
                0x48,     /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
100
                0x1c,     /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
101
                0x00,     /* 12 - output control 2 */
102
                0x00,     /* 13 - output control 3 */
103
                0x00,     /* 14 - reserved */
104
                0x00,     /* 15 - VBI */
105
                0x00,     /* 16 - VBI */
106
                0x00,     /* 17 - VBI */
107
        };
108
        client = kmalloc(sizeof(*client), GFP_KERNEL);
109
        if(client == NULL)
110
                return -ENOMEM;
111
        client_template.adapter = adap;
112
        client_template.addr = addr;
113
        memcpy(client, &client_template, sizeof(*client));
114
 
115
        decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
116
        if (decoder == NULL)
117
        {
118
                kfree(client);
119
                return -ENOMEM;
120
        }
121
 
122
        memset(decoder, 0, sizeof(*decoder));
123
        decoder->client = client;
124
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
125
        client->data = decoder;        
126
#else
127
        i2c_set_clientdata(client, decoder);
128
#endif
129
        decoder->addr = addr;
130
        decoder->norm = VIDEO_MODE_NTSC;
131
        decoder->input = 0;
132
        decoder->enable = 1;
133
        decoder->bright = 32768;
134
        decoder->contrast = 32768;
135
        decoder->hue = 32768;
136
        decoder->sat = 32768;
137
 
138
        i = i2c_master_send(client, init, sizeof(init));
139
        if (i < 0) {
140
                printk(KERN_ERR "%s_attach: init status %d\n",
141
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
142
                       client->name, i);
143
#else
144
                       client->dev.name, i);
145
#endif
146
        } else {
147
                printk(KERN_INFO "%s_attach: chip version %x @ 0x%08x\n",
148
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
149
                       client->name, i2c_smbus_read_byte_data(client, 0x00) >> 4,addr);
150
#else
151
                       client->dev.name, i2c_smbus_read_byte_data(client, 0x00) >> 4,addr);
152
#endif
153
        }
154
 
155
        init_MUTEX(&decoder->lock);
156
        i2c_attach_client(client);
157
        MOD_INC_USE_COUNT;
158
        return 0;
159
}
160
static int saa7111_probe(struct i2c_adapter *adap)
161
{
162
        /* probing unknown devices on any Matrox i2c-bus takes ages due to the
163
           slow bit banging algorithm used. because of the fact a saa7111(a)
164
           is *never* present on a Matrox gfx card, we can skip such adapters
165
           here */
166
        if( 0 != (adap->id & I2C_HW_B_G400)) {
167
                return -ENODEV;
168
        }
169
 
170
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
171
        printk("saa7111: probing %s i2c adapter [id=0x%x]\n",
172
                       adap->name,adap->id);
173
#else
174
        printk("saa7111: probing %s i2c adapter [id=0x%x]\n",
175
                       adap->dev.name,adap->id);
176
#endif
177
        return i2c_probe(adap, &addr_data, saa7111_attach);
178
}
179
 
180
static int saa7111_detach(struct i2c_client *client)
181
{
182
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
183
        struct saa7111 *decoder = client->data;
184
#else
185
        struct saa7111 *decoder = i2c_get_clientdata(client);
186
#endif
187
        i2c_detach_client(client);
188
        kfree(decoder);
189
        kfree(client);
190
        MOD_DEC_USE_COUNT;
191
        return 0;
192
}
193
 
194
static int saa7111_command(struct i2c_client *client, unsigned int cmd,
195
                           void *arg)
196
{
197
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
198
        struct saa7111 *decoder = client->data;
199
#else
200
        struct saa7111 *decoder = i2c_get_clientdata(client);
201
#endif
202
        switch (cmd) {
203
 
204
#if defined(DECODER_DUMP)
205
        case DECODER_DUMP:
206
                {
207
                        int i;
208
 
209
                        for (i = 0; i < 32; i += 16) {
210
                                int j;
211
 
212
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
213
                                printk("KERN_DEBUG %s: %03x", client->name,
214
#else
215
                                printk("KERN_DEBUG %s: %03x", client->dev.name,
216
#endif
217
                                       i);
218
                                for (j = 0; j < 16; ++j) {
219
                                        printk(" %02x",
220
                                               i2c_smbus_read_byte_data(client,
221
                                                            i + j));
222
                                }
223
                                printk("\n");
224
                        }
225
                }
226
                break;
227
#endif                          /* defined(DECODER_DUMP) */
228
        case DECODER_GET_CAPABILITIES:
229
                {
230
                        struct video_decoder_capability *cap = arg;
231
 
232
                        cap->flags
233
                            = VIDEO_DECODER_PAL
234
                            | VIDEO_DECODER_NTSC
235
                            | VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR;
236
                        cap->inputs = 8;
237
                        cap->outputs = 1;
238
                }
239
                break;
240
        case DECODER_GET_STATUS:
241
                {
242
                        int *iarg = arg;
243
                        int status;
244
                        int res;
245
 
246
                        status = i2c_smbus_read_byte_data(client, 0x1f);
247
                        res = 0;
248
                        if ((status & (1 << 6)) == 0) {
249
                                res |= DECODER_STATUS_GOOD;
250
                        }
251
                        switch (decoder->norm) {
252
                        case VIDEO_MODE_NTSC:
253
                                res |= DECODER_STATUS_NTSC;
254
                                break;
255
                        case VIDEO_MODE_PAL:
256
                                res |= DECODER_STATUS_PAL;
257
                                break;
258
                        default:
259
                        case VIDEO_MODE_AUTO:
260
                                if ((status & (1 << 5)) != 0) {
261
                                        res |= DECODER_STATUS_NTSC;
262
                                } else {
263
                                        res |= DECODER_STATUS_PAL;
264
                                }
265
                                break;
266
                        }
267
                        if ((status & (1 << 0)) != 0) {
268
                                res |= DECODER_STATUS_COLOR;
269
                        }
270
                        *iarg = res;
271
                }
272
                break;
273
 
274
        case DECODER_SET_NORM:
275
                {
276
                        int *iarg = arg;
277
 
278
                        switch (*iarg) {
279
 
280
                        case VIDEO_MODE_NTSC:
281
                                i2c_smbus_write_byte_data(client, 0x08,
282
                                              (decoder->
283
                                               reg[0x08] & 0x3f) | 0x40);
284
                                break;
285
 
286
                        case VIDEO_MODE_PAL:
287
                                i2c_smbus_write_byte_data(client, 0x08,
288
                                              (decoder->
289
                                               reg[0x08] & 0x3f) | 0x00);
290
                                break;
291
 
292
                        case VIDEO_MODE_AUTO:
293
                                i2c_smbus_write_byte_data(client, 0x08,
294
                                              (decoder->
295
                                               reg[0x08] & 0x3f) | 0x80);
296
                                break;
297
 
298
                        default:
299
                                return -EINVAL;
300
 
301
                        }
302
                        decoder->norm = *iarg;
303
                }
304
                break;
305
 
306
        case DECODER_SET_INPUT:
307
                {
308
                        int *iarg = arg;
309
 
310
                        if (*iarg < 0 || *iarg > 7) {
311
                                return -EINVAL;
312
                        }
313
 
314
                        if (decoder->input != *iarg) {
315
                                decoder->input = *iarg;
316
                                /* select mode */
317
                                i2c_smbus_write_byte_data(client, 0x02,
318
                                              (decoder->
319
                                               reg[0x02] & 0xf8) |
320
                                              decoder->input);
321
                                /* bypass chrominance trap for modes 4..7 */
322
                                i2c_smbus_write_byte_data(client, 0x09,
323
                                              (decoder->
324
                                               reg[0x09] & 0x7f) |
325
                                              ((decoder->input >
326
                                                3) ? 0x80 : 0));
327
                        }
328
                }
329
                break;
330
 
331
        case DECODER_SET_OUTPUT:
332
                {
333
                        int *iarg = arg;
334
 
335
                        /* not much choice of outputs */
336
                        if (*iarg != 0) {
337
                                return -EINVAL;
338
                        }
339
                }
340
                break;
341
 
342
        case DECODER_ENABLE_OUTPUT:
343
                {
344
                        int *iarg = arg;
345
                        int enable = (*iarg != 0);
346
 
347
                        if (decoder->enable != enable) {
348
                                decoder->enable = enable;
349
 
350
// RJ: If output should be disabled (for playing videos), we also need a open PLL.
351
//     The input is set to 0 (where no input source is connected), although this
352
//     is not necessary.
353
//
354
//     If output should be enabled, we have to reverse the above.
355
 
356
                                if (decoder->enable) {
357
                                        i2c_smbus_write_byte_data(client, 0x02,
358
                                                      (decoder->
359
                                                       reg[0x02] & 0xf8) |
360
                                                      decoder->input);
361
                                        i2c_smbus_write_byte_data(client, 0x08,
362
                                                      (decoder->
363
                                                       reg[0x08] & 0xfb));
364
                                        i2c_smbus_write_byte_data(client, 0x11,
365
                                                      (decoder->
366
                                                       reg[0x11] & 0xf3) |
367
                                                      0x0c);
368
                                } else {
369
                                        i2c_smbus_write_byte_data(client, 0x02,
370
                                                      (decoder->
371
                                                       reg[0x02] & 0xf8));
372
                                        i2c_smbus_write_byte_data(client, 0x08,
373
                                                      (decoder->
374
                                                       reg[0x08] & 0xfb) |
375
                                                      0x04);
376
                                        i2c_smbus_write_byte_data(client, 0x11,
377
                                                      (decoder->
378
                                                       reg[0x11] & 0xf3));
379
                                }
380
                        }
381
                }
382
                break;
383
 
384
        case DECODER_SET_PICTURE:
385
                {
386
                        struct video_picture *pic = arg;
387
 
388
                        if (decoder->bright != pic->brightness) {
389
                                /* We want 0 to 255 we get 0-65535 */
390
                                decoder->bright = pic->brightness;
391
                                i2c_smbus_write_byte_data(client, 0x0a,
392
                                              decoder->bright >> 8);
393
                        }
394
                        if (decoder->contrast != pic->contrast) {
395
                                /* We want 0 to 127 we get 0-65535 */
396
                                decoder->contrast = pic->contrast;
397
                                i2c_smbus_write_byte_data(client, 0x0b,
398
                                              decoder->contrast >> 9);
399
                        }
400
                        if (decoder->sat != pic->colour) {
401
                                /* We want 0 to 127 we get 0-65535 */
402
                                decoder->sat = pic->colour;
403
                                i2c_smbus_write_byte_data(client, 0x0c,
404
                                              decoder->sat >> 9);
405
                        }
406
                        if (decoder->hue != pic->hue) {
407
                                /* We want -128 to 127 we get 0-65535 */
408
                                decoder->hue = pic->hue;
409
                                i2c_smbus_write_byte_data(client, 0x0d,
410
                                              (decoder->hue - 32768) >> 8);
411
                        }
412
                }
413
                break;
414
 
415
        default:
416
                return -EINVAL;
417
        }
418
 
419
        return 0;
420
}
421
 
422
/* ----------------------------------------------------------------------- */
423
 
424
static struct i2c_driver i2c_driver_saa7111 = {
425
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,54)
426
        .owner          = THIS_MODULE,
427
#endif
428
        .name           = "saa7111",             /* name */
429
        .id             = I2C_DRIVERID_SAA7111A, /* ID */
430
        .flags          = I2C_DF_NOTIFY,
431
        .attach_adapter = saa7111_probe,
432
        .detach_client  = saa7111_detach,
433
        .command        = saa7111_command
434
};
435
 
436
static struct i2c_client client_template = {
437
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
438
        .name   = "saa7111_client",
439
#else
440
        .dev    = {
441
                .name   = "saa7111_client",
442
        },
443
#endif
444
        .id     = -1,
445
        .driver = &i2c_driver_saa7111
446
};
447
 
448
static int saa7111_init(void)
449
{
450
        return i2c_add_driver(&i2c_driver_saa7111);
451
}
452
 
453
static void saa7111_exit(void)
454
{
455
        i2c_del_driver(&i2c_driver_saa7111);
456
}
457
 
458
module_init(saa7111_init);
459
module_exit(saa7111_exit);
460
MODULE_LICENSE("GPL");