~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/media/video/adv7175.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  adv7175 - adv7175a video encoder driver version 0.0.3
 
3
 *
 
4
 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
 
5
 * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
 
6
 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
 
7
 *    - some corrections for Pinnacle Systems Inc. DC10plus card.
 
8
 *
 
9
 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
 
10
 *    - moved over to linux>=2.4.x i2c protocol (9/9/2002)
 
11
 *
 
12
 * This program is free software; you can redistribute it and/or modify
 
13
 * it under the terms of the GNU General Public License as published by
 
14
 * the Free Software Foundation; either version 2 of the License, or
 
15
 * (at your option) any later version.
 
16
 *
 
17
 * This program is distributed in the hope that it will be useful,
 
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
 * GNU General Public License for more details.
 
21
 *
 
22
 * You should have received a copy of the GNU General Public License
 
23
 * along with this program; if not, write to the Free Software
 
24
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
25
 */
 
26
 
 
27
#include <linux/module.h>
 
28
#include <linux/types.h>
 
29
#include <linux/slab.h>
 
30
#include <linux/ioctl.h>
 
31
#include <asm/uaccess.h>
 
32
#include <linux/i2c.h>
 
33
#include <linux/videodev2.h>
 
34
#include <media/v4l2-device.h>
 
35
#include <media/v4l2-chip-ident.h>
 
36
 
 
37
MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
 
38
MODULE_AUTHOR("Dave Perks");
 
39
MODULE_LICENSE("GPL");
 
40
 
 
41
#define   I2C_ADV7175        0xd4
 
42
#define   I2C_ADV7176        0x54
 
43
 
 
44
 
 
45
static int debug;
 
46
module_param(debug, int, 0);
 
47
MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
48
 
 
49
/* ----------------------------------------------------------------------- */
 
50
 
 
51
struct adv7175 {
 
52
        struct v4l2_subdev sd;
 
53
        v4l2_std_id norm;
 
54
        int input;
 
55
};
 
56
 
 
57
static inline struct adv7175 *to_adv7175(struct v4l2_subdev *sd)
 
58
{
 
59
        return container_of(sd, struct adv7175, sd);
 
60
}
 
61
 
 
62
static char *inputs[] = { "pass_through", "play_back", "color_bar" };
 
63
 
 
64
static enum v4l2_mbus_pixelcode adv7175_codes[] = {
 
65
        V4L2_MBUS_FMT_UYVY8_2X8,
 
66
        V4L2_MBUS_FMT_UYVY8_1X16,
 
67
};
 
68
 
 
69
/* ----------------------------------------------------------------------- */
 
70
 
 
71
static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value)
 
72
{
 
73
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
74
 
 
75
        return i2c_smbus_write_byte_data(client, reg, value);
 
76
}
 
77
 
 
78
static inline int adv7175_read(struct v4l2_subdev *sd, u8 reg)
 
79
{
 
80
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
81
 
 
82
        return i2c_smbus_read_byte_data(client, reg);
 
83
}
 
84
 
 
85
static int adv7175_write_block(struct v4l2_subdev *sd,
 
86
                     const u8 *data, unsigned int len)
 
87
{
 
88
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
89
        int ret = -1;
 
90
        u8 reg;
 
91
 
 
92
        /* the adv7175 has an autoincrement function, use it if
 
93
         * the adapter understands raw I2C */
 
94
        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 
95
                /* do raw I2C, not smbus compatible */
 
96
                u8 block_data[32];
 
97
                int block_len;
 
98
 
 
99
                while (len >= 2) {
 
100
                        block_len = 0;
 
101
                        block_data[block_len++] = reg = data[0];
 
102
                        do {
 
103
                                block_data[block_len++] = data[1];
 
104
                                reg++;
 
105
                                len -= 2;
 
106
                                data += 2;
 
107
                        } while (len >= 2 && data[0] == reg && block_len < 32);
 
108
                        ret = i2c_master_send(client, block_data, block_len);
 
109
                        if (ret < 0)
 
110
                                break;
 
111
                }
 
112
        } else {
 
113
                /* do some slow I2C emulation kind of thing */
 
114
                while (len >= 2) {
 
115
                        reg = *data++;
 
116
                        ret = adv7175_write(sd, reg, *data++);
 
117
                        if (ret < 0)
 
118
                                break;
 
119
                        len -= 2;
 
120
                }
 
121
        }
 
122
 
 
123
        return ret;
 
124
}
 
125
 
 
126
static void set_subcarrier_freq(struct v4l2_subdev *sd, int pass_through)
 
127
{
 
128
        /* for some reason pass_through NTSC needs
 
129
         * a different sub-carrier freq to remain stable. */
 
130
        if (pass_through)
 
131
                adv7175_write(sd, 0x02, 0x00);
 
132
        else
 
133
                adv7175_write(sd, 0x02, 0x55);
 
134
 
 
135
        adv7175_write(sd, 0x03, 0x55);
 
136
        adv7175_write(sd, 0x04, 0x55);
 
137
        adv7175_write(sd, 0x05, 0x25);
 
138
}
 
139
 
 
140
/* ----------------------------------------------------------------------- */
 
141
/* Output filter:  S-Video  Composite */
 
142
 
 
143
#define MR050       0x11        /* 0x09 */
 
144
#define MR060       0x14        /* 0x0c */
 
145
 
 
146
/* ----------------------------------------------------------------------- */
 
147
 
 
148
#define TR0MODE     0x46
 
149
#define TR0RST      0x80
 
150
 
 
151
#define TR1CAPT     0x80
 
152
#define TR1PLAY     0x00
 
153
 
 
154
static const unsigned char init_common[] = {
 
155
 
 
156
        0x00, MR050,            /* MR0, PAL enabled */
 
157
        0x01, 0x00,             /* MR1 */
 
158
        0x02, 0x0c,             /* subc. freq. */
 
159
        0x03, 0x8c,             /* subc. freq. */
 
160
        0x04, 0x79,             /* subc. freq. */
 
161
        0x05, 0x26,             /* subc. freq. */
 
162
        0x06, 0x40,             /* subc. phase */
 
163
 
 
164
        0x07, TR0MODE,          /* TR0, 16bit */
 
165
        0x08, 0x21,             /*  */
 
166
        0x09, 0x00,             /*  */
 
167
        0x0a, 0x00,             /*  */
 
168
        0x0b, 0x00,             /*  */
 
169
        0x0c, TR1CAPT,          /* TR1 */
 
170
        0x0d, 0x4f,             /* MR2 */
 
171
        0x0e, 0x00,             /*  */
 
172
        0x0f, 0x00,             /*  */
 
173
        0x10, 0x00,             /*  */
 
174
        0x11, 0x00,             /*  */
 
175
};
 
176
 
 
177
static const unsigned char init_pal[] = {
 
178
        0x00, MR050,            /* MR0, PAL enabled */
 
179
        0x01, 0x00,             /* MR1 */
 
180
        0x02, 0x0c,             /* subc. freq. */
 
181
        0x03, 0x8c,             /* subc. freq. */
 
182
        0x04, 0x79,             /* subc. freq. */
 
183
        0x05, 0x26,             /* subc. freq. */
 
184
        0x06, 0x40,             /* subc. phase */
 
185
};
 
186
 
 
187
static const unsigned char init_ntsc[] = {
 
188
        0x00, MR060,            /* MR0, NTSC enabled */
 
189
        0x01, 0x00,             /* MR1 */
 
190
        0x02, 0x55,             /* subc. freq. */
 
191
        0x03, 0x55,             /* subc. freq. */
 
192
        0x04, 0x55,             /* subc. freq. */
 
193
        0x05, 0x25,             /* subc. freq. */
 
194
        0x06, 0x1a,             /* subc. phase */
 
195
};
 
196
 
 
197
static int adv7175_init(struct v4l2_subdev *sd, u32 val)
 
198
{
 
199
        /* This is just for testing!!! */
 
200
        adv7175_write_block(sd, init_common, sizeof(init_common));
 
201
        adv7175_write(sd, 0x07, TR0MODE | TR0RST);
 
202
        adv7175_write(sd, 0x07, TR0MODE);
 
203
        return 0;
 
204
}
 
205
 
 
206
static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
 
207
{
 
208
        struct adv7175 *encoder = to_adv7175(sd);
 
209
 
 
210
        if (std & V4L2_STD_NTSC) {
 
211
                adv7175_write_block(sd, init_ntsc, sizeof(init_ntsc));
 
212
                if (encoder->input == 0)
 
213
                        adv7175_write(sd, 0x0d, 0x4f);  /* Enable genlock */
 
214
                adv7175_write(sd, 0x07, TR0MODE | TR0RST);
 
215
                adv7175_write(sd, 0x07, TR0MODE);
 
216
        } else if (std & V4L2_STD_PAL) {
 
217
                adv7175_write_block(sd, init_pal, sizeof(init_pal));
 
218
                if (encoder->input == 0)
 
219
                        adv7175_write(sd, 0x0d, 0x4f);  /* Enable genlock */
 
220
                adv7175_write(sd, 0x07, TR0MODE | TR0RST);
 
221
                adv7175_write(sd, 0x07, TR0MODE);
 
222
        } else if (std & V4L2_STD_SECAM) {
 
223
                /* This is an attempt to convert
 
224
                 * SECAM->PAL (typically it does not work
 
225
                 * due to genlock: when decoder is in SECAM
 
226
                 * and encoder in in PAL the subcarrier can
 
227
                 * not be syncronized with horizontal
 
228
                 * quency) */
 
229
                adv7175_write_block(sd, init_pal, sizeof(init_pal));
 
230
                if (encoder->input == 0)
 
231
                        adv7175_write(sd, 0x0d, 0x49);  /* Disable genlock */
 
232
                adv7175_write(sd, 0x07, TR0MODE | TR0RST);
 
233
                adv7175_write(sd, 0x07, TR0MODE);
 
234
        } else {
 
235
                v4l2_dbg(1, debug, sd, "illegal norm: %llx\n",
 
236
                                (unsigned long long)std);
 
237
                return -EINVAL;
 
238
        }
 
239
        v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std);
 
240
        encoder->norm = std;
 
241
        return 0;
 
242
}
 
243
 
 
244
static int adv7175_s_routing(struct v4l2_subdev *sd,
 
245
                             u32 input, u32 output, u32 config)
 
246
{
 
247
        struct adv7175 *encoder = to_adv7175(sd);
 
248
 
 
249
        /* RJ: input = 0: input is from decoder
 
250
           input = 1: input is from ZR36060
 
251
           input = 2: color bar */
 
252
 
 
253
        switch (input) {
 
254
        case 0:
 
255
                adv7175_write(sd, 0x01, 0x00);
 
256
 
 
257
                if (encoder->norm & V4L2_STD_NTSC)
 
258
                        set_subcarrier_freq(sd, 1);
 
259
 
 
260
                adv7175_write(sd, 0x0c, TR1CAPT);       /* TR1 */
 
261
                if (encoder->norm & V4L2_STD_SECAM)
 
262
                        adv7175_write(sd, 0x0d, 0x49);  /* Disable genlock */
 
263
                else
 
264
                        adv7175_write(sd, 0x0d, 0x4f);  /* Enable genlock */
 
265
                adv7175_write(sd, 0x07, TR0MODE | TR0RST);
 
266
                adv7175_write(sd, 0x07, TR0MODE);
 
267
                /*udelay(10);*/
 
268
                break;
 
269
 
 
270
        case 1:
 
271
                adv7175_write(sd, 0x01, 0x00);
 
272
 
 
273
                if (encoder->norm & V4L2_STD_NTSC)
 
274
                        set_subcarrier_freq(sd, 0);
 
275
 
 
276
                adv7175_write(sd, 0x0c, TR1PLAY);       /* TR1 */
 
277
                adv7175_write(sd, 0x0d, 0x49);
 
278
                adv7175_write(sd, 0x07, TR0MODE | TR0RST);
 
279
                adv7175_write(sd, 0x07, TR0MODE);
 
280
                /* udelay(10); */
 
281
                break;
 
282
 
 
283
        case 2:
 
284
                adv7175_write(sd, 0x01, 0x80);
 
285
 
 
286
                if (encoder->norm & V4L2_STD_NTSC)
 
287
                        set_subcarrier_freq(sd, 0);
 
288
 
 
289
                adv7175_write(sd, 0x0d, 0x49);
 
290
                adv7175_write(sd, 0x07, TR0MODE | TR0RST);
 
291
                adv7175_write(sd, 0x07, TR0MODE);
 
292
                /* udelay(10); */
 
293
                break;
 
294
 
 
295
        default:
 
296
                v4l2_dbg(1, debug, sd, "illegal input: %d\n", input);
 
297
                return -EINVAL;
 
298
        }
 
299
        v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[input]);
 
300
        encoder->input = input;
 
301
        return 0;
 
302
}
 
303
 
 
304
static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
 
305
                                enum v4l2_mbus_pixelcode *code)
 
306
{
 
307
        if (index >= ARRAY_SIZE(adv7175_codes))
 
308
                return -EINVAL;
 
309
 
 
310
        *code = adv7175_codes[index];
 
311
        return 0;
 
312
}
 
313
 
 
314
static int adv7175_g_fmt(struct v4l2_subdev *sd,
 
315
                                struct v4l2_mbus_framefmt *mf)
 
316
{
 
317
        u8 val = adv7175_read(sd, 0x7);
 
318
 
 
319
        if ((val & 0x40) == (1 << 6))
 
320
                mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
 
321
        else
 
322
                mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
 
323
 
 
324
        mf->colorspace  = V4L2_COLORSPACE_SMPTE170M;
 
325
        mf->width       = 0;
 
326
        mf->height      = 0;
 
327
        mf->field       = V4L2_FIELD_ANY;
 
328
 
 
329
        return 0;
 
330
}
 
331
 
 
332
static int adv7175_s_fmt(struct v4l2_subdev *sd,
 
333
                                struct v4l2_mbus_framefmt *mf)
 
334
{
 
335
        u8 val = adv7175_read(sd, 0x7);
 
336
        int ret;
 
337
 
 
338
        switch (mf->code) {
 
339
        case V4L2_MBUS_FMT_UYVY8_2X8:
 
340
                val &= ~0x40;
 
341
                break;
 
342
 
 
343
        case V4L2_MBUS_FMT_UYVY8_1X16:
 
344
                val |= 0x40;
 
345
                break;
 
346
 
 
347
        default:
 
348
                v4l2_dbg(1, debug, sd,
 
349
                        "illegal v4l2_mbus_framefmt code: %d\n", mf->code);
 
350
                return -EINVAL;
 
351
        }
 
352
 
 
353
        ret = adv7175_write(sd, 0x7, val);
 
354
 
 
355
        return ret;
 
356
}
 
357
 
 
358
static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 
359
{
 
360
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
361
 
 
362
        return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0);
 
363
}
 
364
 
 
365
static int adv7175_s_power(struct v4l2_subdev *sd, int on)
 
366
{
 
367
        if (on)
 
368
                adv7175_write(sd, 0x01, 0x00);
 
369
        else
 
370
                adv7175_write(sd, 0x01, 0x78);
 
371
 
 
372
        return 0;
 
373
}
 
374
 
 
375
/* ----------------------------------------------------------------------- */
 
376
 
 
377
static const struct v4l2_subdev_core_ops adv7175_core_ops = {
 
378
        .g_chip_ident = adv7175_g_chip_ident,
 
379
        .init = adv7175_init,
 
380
        .s_power = adv7175_s_power,
 
381
};
 
382
 
 
383
static const struct v4l2_subdev_video_ops adv7175_video_ops = {
 
384
        .s_std_output = adv7175_s_std_output,
 
385
        .s_routing = adv7175_s_routing,
 
386
        .s_mbus_fmt = adv7175_s_fmt,
 
387
        .g_mbus_fmt = adv7175_g_fmt,
 
388
        .enum_mbus_fmt  = adv7175_enum_fmt,
 
389
};
 
390
 
 
391
static const struct v4l2_subdev_ops adv7175_ops = {
 
392
        .core = &adv7175_core_ops,
 
393
        .video = &adv7175_video_ops,
 
394
};
 
395
 
 
396
/* ----------------------------------------------------------------------- */
 
397
 
 
398
static int adv7175_probe(struct i2c_client *client,
 
399
                        const struct i2c_device_id *id)
 
400
{
 
401
        int i;
 
402
        struct adv7175 *encoder;
 
403
        struct v4l2_subdev *sd;
 
404
 
 
405
        /* Check if the adapter supports the needed features */
 
406
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 
407
                return -ENODEV;
 
408
 
 
409
        v4l_info(client, "chip found @ 0x%x (%s)\n",
 
410
                        client->addr << 1, client->adapter->name);
 
411
 
 
412
        encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
 
413
        if (encoder == NULL)
 
414
                return -ENOMEM;
 
415
        sd = &encoder->sd;
 
416
        v4l2_i2c_subdev_init(sd, client, &adv7175_ops);
 
417
        encoder->norm = V4L2_STD_NTSC;
 
418
        encoder->input = 0;
 
419
 
 
420
        i = adv7175_write_block(sd, init_common, sizeof(init_common));
 
421
        if (i >= 0) {
 
422
                i = adv7175_write(sd, 0x07, TR0MODE | TR0RST);
 
423
                i = adv7175_write(sd, 0x07, TR0MODE);
 
424
                i = adv7175_read(sd, 0x12);
 
425
                v4l2_dbg(1, debug, sd, "revision %d\n", i & 1);
 
426
        }
 
427
        if (i < 0)
 
428
                v4l2_dbg(1, debug, sd, "init error 0x%x\n", i);
 
429
        return 0;
 
430
}
 
431
 
 
432
static int adv7175_remove(struct i2c_client *client)
 
433
{
 
434
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 
435
 
 
436
        v4l2_device_unregister_subdev(sd);
 
437
        kfree(to_adv7175(sd));
 
438
        return 0;
 
439
}
 
440
 
 
441
/* ----------------------------------------------------------------------- */
 
442
 
 
443
static const struct i2c_device_id adv7175_id[] = {
 
444
        { "adv7175", 0 },
 
445
        { "adv7176", 0 },
 
446
        { }
 
447
};
 
448
MODULE_DEVICE_TABLE(i2c, adv7175_id);
 
449
 
 
450
static struct i2c_driver adv7175_driver = {
 
451
        .driver = {
 
452
                .owner  = THIS_MODULE,
 
453
                .name   = "adv7175",
 
454
        },
 
455
        .probe          = adv7175_probe,
 
456
        .remove         = adv7175_remove,
 
457
        .id_table       = adv7175_id,
 
458
};
 
459
 
 
460
static __init int init_adv7175(void)
 
461
{
 
462
        return i2c_add_driver(&adv7175_driver);
 
463
}
 
464
 
 
465
static __exit void exit_adv7175(void)
 
466
{
 
467
        i2c_del_driver(&adv7175_driver);
 
468
}
 
469
 
 
470
module_init(init_adv7175);
 
471
module_exit(exit_adv7175);