OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [media/] [video/] [adv7175.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
#define DEBUGLEVEL 0
2
/*
3
    adv7175 - adv7175a video encoder driver version 0.0.3
4
 
5
    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
6
 
7
    Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
8
    Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
9
       - some corrections for Pinnacle Systems Inc. DC10plus card.
10
 
11
    This program is free software; you can redistribute it and/or modify
12
    it under the terms of the GNU General Public License as published by
13
    the Free Software Foundation; either version 2 of the License, or
14
    (at your option) any later version.
15
 
16
    This program is distributed in the hope that it will be useful,
17
    but WITHOUT ANY WARRANTY; without even the implied warranty of
18
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
    GNU General Public License for more details.
20
 
21
    You should have received a copy of the GNU General Public License
22
    along with this program; if not, write to the Free Software
23
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
*/
25
 
26
#include <linux/module.h>
27
#include <linux/init.h>
28
#include <linux/delay.h>
29
#include <linux/errno.h>
30
#include <linux/fs.h>
31
#include <linux/kernel.h>
32
#include <linux/major.h>
33
#include <linux/slab.h>
34
#include <linux/mm.h>
35
#include <linux/pci.h>
36
#include <linux/signal.h>
37
#include <asm/io.h>
38
#include <asm/pgtable.h>
39
#include <asm/page.h>
40
#include <linux/sched.h>
41
#include <asm/segment.h>
42
#include <linux/types.h>
43
#include <linux/wrapper.h>
44
 
45
#include <linux/videodev.h>
46
#include <linux/version.h>
47
#include <asm/uaccess.h>
48
 
49
#include <linux/i2c-old.h>
50
 
51
#include <linux/video_encoder.h>
52
 
53
#if (DEBUGLEVEL > 0)
54
#define DEBUG(x...)  x          /* Debug driver */
55
#else
56
#define DEBUG(x...)
57
#endif
58
 
59
/* ----------------------------------------------------------------------- */
60
 
61
struct adv7175 {
62
        struct i2c_bus *bus;
63
        int addr;
64
        unsigned char reg[128];
65
 
66
        int norm;
67
        int input;
68
        int enable;
69
        int bright;
70
        int contrast;
71
        int hue;
72
        int sat;
73
};
74
 
75
#define   I2C_ADV7175        0xd4
76
#define   I2C_ADV7176        0x54
77
 
78
static char adv7175_name[] = "adv7175";
79
static char adv7176_name[] = "adv7176";
80
static char unknown_name[] = "UNKNOWN";
81
 
82
#if (DEBUGLEVEL > 0)
83
static char *inputs[] = { "pass_through", "play_back", "color_bar" };
84
static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
85
#endif
86
 
87
#define I2C_DELAY   10
88
 
89
/* ----------------------------------------------------------------------- */
90
 
91
static int adv7175_write(struct adv7175 *dev, unsigned char subaddr, unsigned char data)
92
{
93
        int ack;
94
 
95
        LOCK_I2C_BUS(dev->bus);
96
 
97
        i2c_start(dev->bus);
98
        i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
99
        i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
100
        ack = i2c_sendbyte(dev->bus, data, I2C_DELAY);
101
        dev->reg[subaddr] = data;
102
        i2c_stop(dev->bus);
103
        UNLOCK_I2C_BUS(dev->bus);
104
        return ack;
105
}
106
 
107
static unsigned char adv7175_read(struct adv7175 *dev, unsigned char subaddr)
108
{
109
        unsigned char data;
110
 
111
        LOCK_I2C_BUS(dev->bus);
112
 
113
        i2c_start(dev->bus);
114
        i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
115
        i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
116
        i2c_sendbyte(dev->bus, dev->addr + 1, I2C_DELAY);
117
        data = i2c_readbyte(dev->bus, 1);
118
        dev->reg[subaddr] = data;
119
        i2c_stop(dev->bus);
120
        UNLOCK_I2C_BUS(dev->bus);
121
        return data;
122
}
123
 
124
static int adv7175_write_block(struct adv7175 *dev,
125
                               unsigned const char *data, unsigned int len)
126
{
127
        int ack = 0;
128
        unsigned subaddr;
129
 
130
        while (len > 1) {
131
                LOCK_I2C_BUS(dev->bus);
132
                i2c_start(dev->bus);
133
                i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
134
                ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY);
135
                ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
136
                len -= 2;
137
                while (len > 1 && *data == ++subaddr) {
138
                        data++;
139
                        ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
140
                        len -= 2;
141
                }
142
                i2c_stop(dev->bus);
143
                UNLOCK_I2C_BUS(dev->bus);
144
        }
145
        return ack;
146
}
147
 
148
/* ----------------------------------------------------------------------- */
149
// Output filter:  S-Video  Composite
150
 
151
#define MR050       0x11        //0x09
152
#define MR060       0x14        //0x0c
153
 
154
//---------------------------------------------------------------------------
155
 
156
#define TR0MODE     0x46
157
#define TR0RST      0x80
158
 
159
#define TR1CAPT     0x80
160
#define TR1PLAY     0x00
161
 
162
static const unsigned char init_common[] = {
163
 
164
        0x00, MR050,            /* MR0, PAL enabled */
165
        0x01, 0x00,             /* MR1 */
166
        0x02, 0x0c,             /* subc. freq. */
167
        0x03, 0x8c,             /* subc. freq. */
168
        0x04, 0x79,             /* subc. freq. */
169
        0x05, 0x26,             /* subc. freq. */
170
        0x06, 0x40,             /* subc. phase */
171
 
172
        0x07, TR0MODE,          /* TR0, 16bit */
173
        0x08, 0x21,             /*  */
174
        0x09, 0x00,             /*  */
175
        0x0a, 0x00,             /*  */
176
        0x0b, 0x00,             /*  */
177
        0x0c, TR1CAPT,          /* TR1 */
178
        0x0d, 0x4f,             /* MR2 */
179
        0x0e, 0x00,             /*  */
180
        0x0f, 0x00,             /*  */
181
        0x10, 0x00,             /*  */
182
        0x11, 0x00,             /*  */
183
        0x12, 0x00,             /* MR3 */
184
        0x24, 0x00,             /*  */
185
};
186
 
187
static const unsigned char init_pal[] = {
188
        0x00, MR050,            /* MR0, PAL enabled */
189
        0x01, 0x00,             /* MR1 */
190
        0x02, 0x0c,             /* subc. freq. */
191
        0x03, 0x8c,             /* subc. freq. */
192
        0x04, 0x79,             /* subc. freq. */
193
        0x05, 0x26,             /* subc. freq. */
194
        0x06, 0x40,             /* subc. phase */
195
};
196
 
197
static const unsigned char init_ntsc[] = {
198
        0x00, MR060,            /* MR0, NTSC enabled */
199
        0x01, 0x00,             /* MR1 */
200
        0x02, 0x55,             /* subc. freq. */
201
        0x03, 0x55,             /* subc. freq. */
202
        0x04, 0x55,             /* subc. freq. */
203
        0x05, 0x25,             /* subc. freq. */
204
        0x06, 0x1a,             /* subc. phase */
205
};
206
 
207
static int adv7175_attach(struct i2c_device *device)
208
{
209
        int i;
210
        struct adv7175 *encoder;
211
        char *dname;
212
 
213
        MOD_INC_USE_COUNT;
214
 
215
        device->data = encoder = kmalloc(sizeof(struct adv7175), GFP_KERNEL);
216
        if (encoder == NULL) {
217
                MOD_DEC_USE_COUNT;
218
                return -ENOMEM;
219
        }
220
 
221
 
222
        memset(encoder, 0, sizeof(struct adv7175));
223
        if ((device->addr == I2C_ADV7175) || (device->addr == (I2C_ADV7175 + 2))) {
224
                dname = adv7175_name;
225
        } else if ((device->addr == I2C_ADV7176) || (device->addr == (I2C_ADV7176 + 2))) {
226
                dname = adv7176_name;
227
        } else {
228
                // We should never get here!!!
229
                dname = unknown_name;
230
        }
231
        strcpy(device->name, dname);
232
        encoder->bus = device->bus;
233
        encoder->addr = device->addr;
234
        encoder->norm = VIDEO_MODE_PAL;
235
        encoder->input = 0;
236
        encoder->enable = 1;
237
 
238
        i = adv7175_write_block(encoder, init_common, sizeof(init_common));
239
        if (i >= 0) {
240
                i = adv7175_write(encoder, 0x07, TR0MODE | TR0RST);
241
                i = adv7175_write(encoder, 0x07, TR0MODE);
242
                i = adv7175_read(encoder, 0x12);
243
                printk(KERN_INFO "%s_attach: %s rev. %d at 0x%02x\n",
244
                       device->name, dname, i & 1, device->addr);
245
        }
246
        if (i < 0) {
247
                printk(KERN_ERR "%s_attach: init error %d\n", device->name,
248
                       i);
249
        }
250
 
251
        return 0;
252
}
253
 
254
 
255
static int adv7175_detach(struct i2c_device *device)
256
{
257
        kfree(device->data);
258
        MOD_DEC_USE_COUNT;
259
        return 0;
260
}
261
 
262
static int adv7175_command(struct i2c_device *device, unsigned int cmd,
263
                           void *arg)
264
{
265
        struct adv7175 *encoder = device->data;
266
 
267
        switch (cmd) {
268
 
269
        case ENCODER_GET_CAPABILITIES:
270
                {
271
                        struct video_encoder_capability *cap = arg;
272
 
273
                        cap->flags = VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC
274
                            // | VIDEO_ENCODER_SECAM
275
                            // | VIDEO_ENCODER_CCIR
276
                            ;
277
                        cap->inputs = 2;
278
                        cap->outputs = 1;
279
                }
280
                break;
281
 
282
        case ENCODER_SET_NORM:
283
                {
284
                        int iarg = *(int *) arg;
285
 
286
                        if (encoder->norm != iarg) {
287
                                switch (iarg) {
288
 
289
                                case VIDEO_MODE_NTSC:
290
                                        adv7175_write_block(encoder,
291
                                                            init_ntsc,
292
                                                            sizeof
293
                                                            (init_ntsc));
294
                                        if (encoder->input == 0)
295
                                                adv7175_write(encoder, 0x0d, 0x4f);     // Enable genlock
296
                                        adv7175_write(encoder, 0x07,
297
                                                      TR0MODE | TR0RST);
298
                                        adv7175_write(encoder, 0x07,
299
                                                      TR0MODE);
300
                                        break;
301
 
302
                                case VIDEO_MODE_PAL:
303
                                        adv7175_write_block(encoder,
304
                                                            init_pal,
305
                                                            sizeof
306
                                                            (init_pal));
307
                                        if (encoder->input == 0)
308
                                                adv7175_write(encoder, 0x0d, 0x4f);     // Enable genlock
309
                                        adv7175_write(encoder, 0x07,
310
                                                      TR0MODE | TR0RST);
311
                                        adv7175_write(encoder, 0x07,
312
                                                      TR0MODE);
313
                                        break;
314
 
315
                                case VIDEO_MODE_SECAM:  // WARNING! ADV7176 does not support SECAM.
316
                                        // This is an attempt to convert SECAM->PAL (typically
317
                                        // it does not work due to genlock: when decoder
318
                                        // is in SECAM and encoder in in PAL the subcarrier
319
                                        // can not be syncronized with horizontal frequency)
320
                                        adv7175_write_block(encoder,
321
                                                            init_pal,
322
                                                            sizeof
323
                                                            (init_pal));
324
                                        if (encoder->input == 0)
325
                                                adv7175_write(encoder, 0x0d, 0x49);     // Disable genlock
326
                                        adv7175_write(encoder, 0x07,
327
                                                      TR0MODE | TR0RST);
328
                                        adv7175_write(encoder, 0x07,
329
                                                      TR0MODE);
330
                                        break;
331
                                default:
332
                                        printk(KERN_ERR
333
                                               "%s: illegal norm: %d\n",
334
                                               device->name, iarg);
335
                                        return -EINVAL;
336
 
337
                                }
338
                                DEBUG(printk
339
                                      (KERN_INFO "%s: switched to %s\n",
340
                                       device->name, norms[iarg]));
341
                                encoder->norm = iarg;
342
                        }
343
                }
344
                break;
345
 
346
        case ENCODER_SET_INPUT:
347
                {
348
                        int iarg = *(int *) arg;
349
 
350
                        /* RJ: *iarg = 0: input is from SAA7110
351
                           *iarg = 1: input is from ZR36060
352
                           *iarg = 2: color bar */
353
 
354
                        if (encoder->input != iarg) {
355
                                switch (iarg) {
356
 
357
                                case 0:
358
                                        adv7175_write(encoder, 0x01, 0x00);
359
                                        adv7175_write(encoder, 0x0c, TR1CAPT);  /* TR1 */
360
                                        if (encoder->norm ==
361
                                            VIDEO_MODE_SECAM)
362
                                                adv7175_write(encoder, 0x0d, 0x49);     // Disable genlock
363
                                        else
364
                                                adv7175_write(encoder, 0x0d, 0x4f);     // Enable genlock
365
                                        adv7175_write(encoder, 0x07,
366
                                                      TR0MODE | TR0RST);
367
                                        adv7175_write(encoder, 0x07,
368
                                                      TR0MODE);
369
                                        //udelay(10);
370
                                        break;
371
 
372
                                case 1:
373
                                        adv7175_write(encoder, 0x01, 0x00);
374
                                        adv7175_write(encoder, 0x0c, TR1PLAY);  /* TR1 */
375
                                        adv7175_write(encoder, 0x0d, 0x49);
376
                                        adv7175_write(encoder, 0x07,
377
                                                      TR0MODE | TR0RST);
378
                                        adv7175_write(encoder, 0x07,
379
                                                      TR0MODE);
380
                                        //udelay(10);
381
                                        break;
382
 
383
                                case 2:
384
                                        adv7175_write(encoder, 0x01, 0x80);
385
                                        adv7175_write(encoder, 0x0d, 0x49);
386
                                        adv7175_write(encoder, 0x07,
387
                                                      TR0MODE | TR0RST);
388
                                        adv7175_write(encoder, 0x07,
389
                                                      TR0MODE);
390
                                        //udelay(10);
391
                                        break;
392
 
393
                                default:
394
                                        printk(KERN_ERR
395
                                               "%s: illegal input: %d\n",
396
                                               device->name, iarg);
397
                                        return -EINVAL;
398
 
399
                                }
400
                                DEBUG(printk
401
                                      (KERN_INFO "%s: switched to %s\n",
402
                                       device->name, inputs[iarg]));
403
                                encoder->input = iarg;
404
                        }
405
                }
406
                break;
407
 
408
        case ENCODER_SET_OUTPUT:
409
                {
410
                        int *iarg = arg;
411
 
412
                        /* not much choice of outputs */
413
                        if (*iarg != 0) {
414
                                return -EINVAL;
415
                        }
416
                }
417
                break;
418
 
419
        case ENCODER_ENABLE_OUTPUT:
420
                {
421
                        int *iarg = arg;
422
 
423
                        encoder->enable = !!*iarg;
424
                        adv7175_write(encoder, 0x61,
425
                                      (encoder->
426
                                       reg[0x61] & 0xbf) | (encoder->
427
                                                            enable ? 0x00 :
428
                                                            0x40));
429
                }
430
                break;
431
 
432
        default:
433
                return -EINVAL;
434
        }
435
 
436
        return 0;
437
}
438
 
439
/* ----------------------------------------------------------------------- */
440
 
441
static struct i2c_driver i2c_driver_adv7175 = {
442
        "adv7175",              /* name */
443
        I2C_DRIVERID_VIDEOENCODER,      /* ID */
444
        I2C_ADV7175, I2C_ADV7175 + 3,
445
 
446
        adv7175_attach,
447
        adv7175_detach,
448
        adv7175_command
449
};
450
 
451
static struct i2c_driver i2c_driver_adv7176 = {
452
        "adv7175",              /* name */
453
        I2C_DRIVERID_VIDEOENCODER,      /* ID */
454
        I2C_ADV7176, I2C_ADV7176 + 3,
455
 
456
        adv7175_attach,
457
        adv7175_detach,
458
        adv7175_command
459
};
460
 
461
EXPORT_NO_SYMBOLS;
462
 
463
static int adv7175_init(void)
464
{
465
        int res_adv7175 = 0, res_adv7176 = 0;
466
        res_adv7175 = i2c_register_driver(&i2c_driver_adv7175);
467
        res_adv7176 = i2c_register_driver(&i2c_driver_adv7176);
468
        return (res_adv7175 | res_adv7176);     // Any idea how to make it better?
469
}
470
 
471
static void adv7175_exit(void)
472
{
473
        i2c_unregister_driver(&i2c_driver_adv7176);
474
        i2c_unregister_driver(&i2c_driver_adv7175);
475
}
476
 
477
module_init(adv7175_init);
478
module_exit(adv7175_exit);
479
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.