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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [media/] [video/] [adv7170.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * adv7170 - adv7170, adv7171 video encoder driver version 0.0.1
3
 *
4
 * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
5
 *
6
 * Based on adv7176 driver by:
7
 *
8
 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
9
 * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
10
 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
11
 *    - some corrections for Pinnacle Systems Inc. DC10plus card.
12
 *
13
 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
14
 *    - moved over to linux>=2.4.x i2c protocol (1/1/2003)
15
 *
16
 * This program is free software; you can redistribute it and/or modify
17
 * it under the terms of the GNU General Public License as published by
18
 * the Free Software Foundation; either version 2 of the License, or
19
 * (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program; if not, write to the Free Software
28
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29
 */
30
 
31
#include <linux/module.h>
32
#include <linux/init.h>
33
#include <linux/delay.h>
34
#include <linux/errno.h>
35
#include <linux/fs.h>
36
#include <linux/kernel.h>
37
#include <linux/major.h>
38
#include <linux/slab.h>
39
#include <linux/mm.h>
40
#include <linux/signal.h>
41
#include <linux/types.h>
42
#include <linux/i2c.h>
43
#include <asm/io.h>
44
#include <asm/pgtable.h>
45
#include <asm/page.h>
46
#include <asm/uaccess.h>
47
 
48
#include <linux/videodev.h>
49
#include <linux/video_encoder.h>
50
 
51
MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver");
52
MODULE_AUTHOR("Maxim Yevtyushkin");
53
MODULE_LICENSE("GPL");
54
 
55
 
56
#define I2C_NAME(x) (x)->name
57
 
58
 
59
static int debug = 0;
60
module_param(debug, int, 0);
61
MODULE_PARM_DESC(debug, "Debug level (0-1)");
62
 
63
#define dprintk(num, format, args...) \
64
        do { \
65
                if (debug >= num) \
66
                        printk(format, ##args); \
67
        } while (0)
68
 
69
/* ----------------------------------------------------------------------- */
70
 
71
struct adv7170 {
72
        unsigned char reg[128];
73
 
74
        int norm;
75
        int input;
76
        int enable;
77
        int bright;
78
        int contrast;
79
        int hue;
80
        int sat;
81
};
82
 
83
#define   I2C_ADV7170        0xd4
84
#define   I2C_ADV7171        0x54
85
 
86
static char adv7170_name[] = "adv7170";
87
static char adv7171_name[] = "adv7171";
88
 
89
static char *inputs[] = { "pass_through", "play_back" };
90
static char *norms[] = { "PAL", "NTSC" };
91
 
92
/* ----------------------------------------------------------------------- */
93
 
94
static inline int
95
adv7170_write (struct i2c_client *client,
96
               u8                 reg,
97
               u8                 value)
98
{
99
        struct adv7170 *encoder = i2c_get_clientdata(client);
100
 
101
        encoder->reg[reg] = value;
102
        return i2c_smbus_write_byte_data(client, reg, value);
103
}
104
 
105
static inline int
106
adv7170_read (struct i2c_client *client,
107
              u8                 reg)
108
{
109
        return i2c_smbus_read_byte_data(client, reg);
110
}
111
 
112
static int
113
adv7170_write_block (struct i2c_client *client,
114
                     const u8          *data,
115
                     unsigned int       len)
116
{
117
        int ret = -1;
118
        u8 reg;
119
 
120
        /* the adv7170 has an autoincrement function, use it if
121
         * the adapter understands raw I2C */
122
        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
123
                /* do raw I2C, not smbus compatible */
124
                struct adv7170 *encoder = i2c_get_clientdata(client);
125
                u8 block_data[32];
126
                int block_len;
127
 
128
                while (len >= 2) {
129
                        block_len = 0;
130
                        block_data[block_len++] = reg = data[0];
131
                        do {
132
                                block_data[block_len++] =
133
                                    encoder->reg[reg++] = data[1];
134
                                len -= 2;
135
                                data += 2;
136
                        } while (len >= 2 && data[0] == reg &&
137
                                 block_len < 32);
138
                        if ((ret = i2c_master_send(client, block_data,
139
                                                   block_len)) < 0)
140
                                break;
141
                }
142
        } else {
143
                /* do some slow I2C emulation kind of thing */
144
                while (len >= 2) {
145
                        reg = *data++;
146
                        if ((ret = adv7170_write(client, reg,
147
                                                 *data++)) < 0)
148
                                break;
149
                        len -= 2;
150
                }
151
        }
152
 
153
        return ret;
154
}
155
 
156
/* ----------------------------------------------------------------------- */
157
// Output filter:  S-Video  Composite
158
 
159
#define MR050       0x11        //0x09
160
#define MR060       0x14        //0x0c
161
 
162
//---------------------------------------------------------------------------
163
 
164
#define TR0MODE     0x4c
165
#define TR0RST      0x80
166
 
167
#define TR1CAPT     0x00
168
#define TR1PLAY     0x00
169
 
170
 
171
static const unsigned char init_NTSC[] = {
172
        0x00, 0x10,             // MR0
173
        0x01, 0x20,             // MR1
174
        0x02, 0x0e,             // MR2 RTC control: bits 2 and 1
175
        0x03, 0x80,             // MR3
176
        0x04, 0x30,             // MR4
177
        0x05, 0x00,             // Reserved
178
        0x06, 0x00,             // Reserved
179
        0x07, TR0MODE,          // TM0
180
        0x08, TR1CAPT,          // TM1
181
        0x09, 0x16,             // Fsc0
182
        0x0a, 0x7c,             // Fsc1
183
        0x0b, 0xf0,             // Fsc2
184
        0x0c, 0x21,             // Fsc3
185
        0x0d, 0x00,             // Subcarrier Phase
186
        0x0e, 0x00,             // Closed Capt. Ext 0
187
        0x0f, 0x00,             // Closed Capt. Ext 1
188
        0x10, 0x00,             // Closed Capt. 0
189
        0x11, 0x00,             // Closed Capt. 1
190
        0x12, 0x00,             // Pedestal Ctl 0
191
        0x13, 0x00,             // Pedestal Ctl 1
192
        0x14, 0x00,             // Pedestal Ctl 2
193
        0x15, 0x00,             // Pedestal Ctl 3
194
        0x16, 0x00,             // CGMS_WSS_0
195
        0x17, 0x00,             // CGMS_WSS_1
196
        0x18, 0x00,             // CGMS_WSS_2
197
        0x19, 0x00,             // Teletext Ctl
198
};
199
 
200
static const unsigned char init_PAL[] = {
201
        0x00, 0x71,             // MR0
202
        0x01, 0x20,             // MR1
203
        0x02, 0x0e,             // MR2 RTC control: bits 2 and 1
204
        0x03, 0x80,             // MR3
205
        0x04, 0x30,             // MR4
206
        0x05, 0x00,             // Reserved
207
        0x06, 0x00,             // Reserved
208
        0x07, TR0MODE,          // TM0
209
        0x08, TR1CAPT,          // TM1
210
        0x09, 0xcb,             // Fsc0
211
        0x0a, 0x8a,             // Fsc1
212
        0x0b, 0x09,             // Fsc2
213
        0x0c, 0x2a,             // Fsc3
214
        0x0d, 0x00,             // Subcarrier Phase
215
        0x0e, 0x00,             // Closed Capt. Ext 0
216
        0x0f, 0x00,             // Closed Capt. Ext 1
217
        0x10, 0x00,             // Closed Capt. 0
218
        0x11, 0x00,             // Closed Capt. 1
219
        0x12, 0x00,             // Pedestal Ctl 0
220
        0x13, 0x00,             // Pedestal Ctl 1
221
        0x14, 0x00,             // Pedestal Ctl 2
222
        0x15, 0x00,             // Pedestal Ctl 3
223
        0x16, 0x00,             // CGMS_WSS_0
224
        0x17, 0x00,             // CGMS_WSS_1
225
        0x18, 0x00,             // CGMS_WSS_2
226
        0x19, 0x00,             // Teletext Ctl
227
};
228
 
229
 
230
static int
231
adv7170_command (struct i2c_client *client,
232
                 unsigned int       cmd,
233
                 void *             arg)
234
{
235
        struct adv7170 *encoder = i2c_get_clientdata(client);
236
 
237
        switch (cmd) {
238
 
239
        case 0:
240
#if 0
241
                /* This is just for testing!!! */
242
                adv7170_write_block(client, init_common,
243
                                    sizeof(init_common));
244
                adv7170_write(client, 0x07, TR0MODE | TR0RST);
245
                adv7170_write(client, 0x07, TR0MODE);
246
#endif
247
                break;
248
 
249
        case ENCODER_GET_CAPABILITIES:
250
        {
251
                struct video_encoder_capability *cap = arg;
252
 
253
                cap->flags = VIDEO_ENCODER_PAL |
254
                             VIDEO_ENCODER_NTSC;
255
                cap->inputs = 2;
256
                cap->outputs = 1;
257
        }
258
                break;
259
 
260
        case ENCODER_SET_NORM:
261
        {
262
                int iarg = *(int *) arg;
263
 
264
                dprintk(1, KERN_DEBUG "%s_command: set norm %d",
265
                        I2C_NAME(client), iarg);
266
 
267
                switch (iarg) {
268
 
269
                case VIDEO_MODE_NTSC:
270
                        adv7170_write_block(client, init_NTSC,
271
                                            sizeof(init_NTSC));
272
                        if (encoder->input == 0)
273
                                adv7170_write(client, 0x02, 0x0e);      // Enable genlock
274
                        adv7170_write(client, 0x07, TR0MODE | TR0RST);
275
                        adv7170_write(client, 0x07, TR0MODE);
276
                        break;
277
 
278
                case VIDEO_MODE_PAL:
279
                        adv7170_write_block(client, init_PAL,
280
                                            sizeof(init_PAL));
281
                        if (encoder->input == 0)
282
                                adv7170_write(client, 0x02, 0x0e);      // Enable genlock
283
                        adv7170_write(client, 0x07, TR0MODE | TR0RST);
284
                        adv7170_write(client, 0x07, TR0MODE);
285
                        break;
286
 
287
                default:
288
                        dprintk(1, KERN_ERR "%s: illegal norm: %d\n",
289
                               I2C_NAME(client), iarg);
290
                        return -EINVAL;
291
 
292
                }
293
                dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client),
294
                        norms[iarg]);
295
                encoder->norm = iarg;
296
        }
297
                break;
298
 
299
        case ENCODER_SET_INPUT:
300
        {
301
                int iarg = *(int *) arg;
302
 
303
                /* RJ: *iarg = 0: input is from decoder
304
                 *iarg = 1: input is from ZR36060
305
                 *iarg = 2: color bar */
306
 
307
                dprintk(1, KERN_DEBUG "%s_command: set input from %s\n",
308
                        I2C_NAME(client),
309
                        iarg == 0 ? "decoder" : "ZR36060");
310
 
311
                switch (iarg) {
312
 
313
                case 0:
314
                        adv7170_write(client, 0x01, 0x20);
315
                        adv7170_write(client, 0x08, TR1CAPT);   /* TR1 */
316
                        adv7170_write(client, 0x02, 0x0e);      // Enable genlock
317
                        adv7170_write(client, 0x07, TR0MODE | TR0RST);
318
                        adv7170_write(client, 0x07, TR0MODE);
319
                        //udelay(10);
320
                        break;
321
 
322
                case 1:
323
                        adv7170_write(client, 0x01, 0x00);
324
                        adv7170_write(client, 0x08, TR1PLAY);   /* TR1 */
325
                        adv7170_write(client, 0x02, 0x08);
326
                        adv7170_write(client, 0x07, TR0MODE | TR0RST);
327
                        adv7170_write(client, 0x07, TR0MODE);
328
                        //udelay(10);
329
                        break;
330
 
331
                default:
332
                        dprintk(1, KERN_ERR "%s: illegal input: %d\n",
333
                                I2C_NAME(client), iarg);
334
                        return -EINVAL;
335
 
336
                }
337
                dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client),
338
                        inputs[iarg]);
339
                encoder->input = iarg;
340
        }
341
                break;
342
 
343
        case ENCODER_SET_OUTPUT:
344
        {
345
                int *iarg = arg;
346
 
347
                /* not much choice of outputs */
348
                if (*iarg != 0) {
349
                        return -EINVAL;
350
                }
351
        }
352
                break;
353
 
354
        case ENCODER_ENABLE_OUTPUT:
355
        {
356
                int *iarg = arg;
357
 
358
                encoder->enable = !!*iarg;
359
        }
360
                break;
361
 
362
        default:
363
                return -EINVAL;
364
        }
365
 
366
        return 0;
367
}
368
 
369
/* ----------------------------------------------------------------------- */
370
 
371
/*
372
 * Generic i2c probe
373
 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
374
 */
375
static unsigned short normal_i2c[] =
376
    { I2C_ADV7170 >> 1, (I2C_ADV7170 >> 1) + 1,
377
        I2C_ADV7171 >> 1, (I2C_ADV7171 >> 1) + 1,
378
        I2C_CLIENT_END
379
};
380
 
381
static unsigned short ignore = I2C_CLIENT_END;
382
 
383
static struct i2c_client_address_data addr_data = {
384
        .normal_i2c             = normal_i2c,
385
        .probe                  = &ignore,
386
        .ignore                 = &ignore,
387
};
388
 
389
static struct i2c_driver i2c_driver_adv7170;
390
 
391
static int
392
adv7170_detect_client (struct i2c_adapter *adapter,
393
                       int                 address,
394
                       int                 kind)
395
{
396
        int i;
397
        struct i2c_client *client;
398
        struct adv7170 *encoder;
399
        char *dname;
400
 
401
        dprintk(1,
402
                KERN_INFO
403
                "adv7170.c: detecting adv7170 client on address 0x%x\n",
404
                address << 1);
405
 
406
        /* Check if the adapter supports the needed features */
407
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
408
                return 0;
409
 
410
        client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
411
        if (client == 0)
412
                return -ENOMEM;
413
        client->addr = address;
414
        client->adapter = adapter;
415
        client->driver = &i2c_driver_adv7170;
416
        if ((client->addr == I2C_ADV7170 >> 1) ||
417
            (client->addr == (I2C_ADV7170 >> 1) + 1)) {
418
                dname = adv7170_name;
419
        } else if ((client->addr == I2C_ADV7171 >> 1) ||
420
                   (client->addr == (I2C_ADV7171 >> 1) + 1)) {
421
                dname = adv7171_name;
422
        } else {
423
                /* We should never get here!!! */
424
                kfree(client);
425
                return 0;
426
        }
427
        strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
428
 
429
        encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL);
430
        if (encoder == NULL) {
431
                kfree(client);
432
                return -ENOMEM;
433
        }
434
        encoder->norm = VIDEO_MODE_NTSC;
435
        encoder->input = 0;
436
        encoder->enable = 1;
437
        i2c_set_clientdata(client, encoder);
438
 
439
        i = i2c_attach_client(client);
440
        if (i) {
441
                kfree(client);
442
                kfree(encoder);
443
                return i;
444
        }
445
 
446
        i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC));
447
        if (i >= 0) {
448
                i = adv7170_write(client, 0x07, TR0MODE | TR0RST);
449
                i = adv7170_write(client, 0x07, TR0MODE);
450
                i = adv7170_read(client, 0x12);
451
                dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%02x\n",
452
                        I2C_NAME(client), i & 1, client->addr << 1);
453
        }
454
        if (i < 0) {
455
                dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n",
456
                       I2C_NAME(client), i);
457
        }
458
 
459
        return 0;
460
}
461
 
462
static int
463
adv7170_attach_adapter (struct i2c_adapter *adapter)
464
{
465
        dprintk(1,
466
                KERN_INFO
467
                "adv7170.c: starting probe for adapter %s (0x%x)\n",
468
                I2C_NAME(adapter), adapter->id);
469
        return i2c_probe(adapter, &addr_data, &adv7170_detect_client);
470
}
471
 
472
static int
473
adv7170_detach_client (struct i2c_client *client)
474
{
475
        struct adv7170 *encoder = i2c_get_clientdata(client);
476
        int err;
477
 
478
        err = i2c_detach_client(client);
479
        if (err) {
480
                return err;
481
        }
482
 
483
        kfree(encoder);
484
        kfree(client);
485
 
486
        return 0;
487
}
488
 
489
/* ----------------------------------------------------------------------- */
490
 
491
static struct i2c_driver i2c_driver_adv7170 = {
492
        .driver = {
493
                .name = "adv7170",      /* name */
494
        },
495
 
496
        .id = I2C_DRIVERID_ADV7170,
497
 
498
        .attach_adapter = adv7170_attach_adapter,
499
        .detach_client = adv7170_detach_client,
500
        .command = adv7170_command,
501
};
502
 
503
static int __init
504
adv7170_init (void)
505
{
506
        return i2c_add_driver(&i2c_driver_adv7170);
507
}
508
 
509
static void __exit
510
adv7170_exit (void)
511
{
512
        i2c_del_driver(&i2c_driver_adv7170);
513
}
514
 
515
module_init(adv7170_init);
516
module_exit(adv7170_exit);

powered by: WebSVN 2.1.0

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