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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1275 phoenix
/*
2
    saa7110 - Philips SAA7110(A) video decoder driver
3
 
4
    Copyright (C) 1998 Pauline Middelink <middelin@polyware.nl>
5
 
6
    This program is free software; you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation; either version 2 of the License, or
9
    (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public License
17
    along with this program; if not, write to the Free Software
18
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
*/
20
 
21
#include <linux/module.h>
22
#include <linux/init.h>
23
#include <linux/types.h>
24
#include <linux/delay.h>
25
#include <linux/slab.h>
26
#include <asm/io.h>
27
#include <asm/uaccess.h>
28
 
29
#include <linux/i2c-old.h>
30
#include <linux/videodev.h>
31
#include "linux/video_decoder.h"
32
 
33
#define DEBUG(x...)                     /* remove when no long debugging */
34
 
35
#define SAA7110_MAX_INPUT       9       /* 6 CVBS, 3 SVHS */
36
#define SAA7110_MAX_OUTPUT      0        /* its a decoder only */
37
 
38
#define I2C_SAA7110             0x9C    /* or 0x9E */
39
 
40
#define I2C_DELAY               10      /* 10 us or 100khz */
41
 
42
struct saa7110 {
43
        struct  i2c_bus *bus;
44
        int             addr;
45
        unsigned char   reg[36];
46
 
47
        int             norm;
48
        int             input;
49
        int             enable;
50
        int             bright;
51
        int             contrast;
52
        int             hue;
53
        int             sat;
54
};
55
 
56
/* ----------------------------------------------------------------------- */
57
/* I2C support functions                                                   */
58
/* ----------------------------------------------------------------------- */
59
static
60
int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data)
61
{
62
        int ack;
63
 
64
        LOCK_I2C_BUS(decoder->bus);
65
        i2c_start(decoder->bus);
66
        i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
67
        i2c_sendbyte(decoder->bus, subaddr, I2C_DELAY);
68
        ack = i2c_sendbyte(decoder->bus, data, I2C_DELAY);
69
        i2c_stop(decoder->bus);
70
        decoder->reg[subaddr] = data;
71
        UNLOCK_I2C_BUS(decoder->bus);
72
        return ack;
73
}
74
 
75
static
76
int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)
77
{
78
        unsigned subaddr = *data;
79
 
80
        LOCK_I2C_BUS(decoder->bus);
81
        i2c_start(decoder->bus);
82
        i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY);
83
        while (len-- > 0) {
84
                if (i2c_sendbyte(decoder->bus,*data,0)) {
85
                        i2c_stop(decoder->bus);
86
                        UNLOCK_I2C_BUS(decoder->bus);
87
                        return -EAGAIN;
88
                }
89
                decoder->reg[subaddr++] = *data++;
90
        }
91
        i2c_stop(decoder->bus);
92
        UNLOCK_I2C_BUS(decoder->bus);
93
 
94
        return 0;
95
}
96
 
97
static
98
int saa7110_read(struct saa7110* decoder)
99
{
100
        int data;
101
 
102
        LOCK_I2C_BUS(decoder->bus);
103
        i2c_start(decoder->bus);
104
        i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
105
        i2c_start(decoder->bus);
106
        i2c_sendbyte(decoder->bus, decoder->addr | 1, I2C_DELAY);
107
        data = i2c_readbyte(decoder->bus, 1);
108
        i2c_stop(decoder->bus);
109
        UNLOCK_I2C_BUS(decoder->bus);
110
        return data;
111
}
112
 
113
/* ----------------------------------------------------------------------- */
114
/* SAA7110 functions                                                       */
115
/* ----------------------------------------------------------------------- */
116
static
117
int saa7110_selmux(struct i2c_device *device, int chan)
118
{
119
static  const unsigned char modes[9][8] = {
120
/* mode 0 */    { 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },
121
/* mode 1 */    { 0x00, 0xD8, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },
122
/* mode 2 */    { 0x00, 0xBA, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 },
123
/* mode 3 */    { 0x00, 0xB8, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 },
124
/* mode 4 */    { 0x00, 0x7C, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 },
125
/* mode 5 */    { 0x00, 0x78, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 },
126
/* mode 6 */    { 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 },
127
/* mode 7 */    { 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 },
128
/* mode 8 */    { 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } };
129
        struct saa7110* decoder = device->data;
130
        const unsigned char* ptr = modes[chan];
131
 
132
        saa7110_write(decoder,0x06,ptr[0]);      /* Luminance control    */
133
        saa7110_write(decoder,0x20,ptr[1]);     /* Analog Control #1    */
134
        saa7110_write(decoder,0x21,ptr[2]);     /* Analog Control #2    */
135
        saa7110_write(decoder,0x22,ptr[3]);     /* Mixer Control #1     */
136
        saa7110_write(decoder,0x2C,ptr[4]);     /* Mixer Control #2     */
137
        saa7110_write(decoder,0x30,ptr[5]);     /* ADCs gain control    */
138
        saa7110_write(decoder,0x31,ptr[6]);     /* Mixer Control #3     */
139
        saa7110_write(decoder,0x21,ptr[7]);     /* Analog Control #2    */
140
 
141
        return 0;
142
}
143
 
144
static
145
int determine_norm(struct i2c_device* dev)
146
{
147
        struct  saa7110* decoder = dev->data;
148
        int     status;
149
 
150
        /* mode changed, start automatic detection */
151
        status = saa7110_read(decoder);
152
        if ((status & 3) == 0) {
153
                saa7110_write(decoder,0x06,0x80);
154
                if (status & 0x20) {
155
                        DEBUG(printk(KERN_INFO "%s: norm=bw60\n",dev->name));
156
                        saa7110_write(decoder,0x2E,0x81);
157
                        return VIDEO_MODE_NTSC;
158
                }
159
                DEBUG(printk(KERN_INFO "%s: norm=bw50\n",dev->name));
160
                saa7110_write(decoder,0x2E,0x9A);
161
                return VIDEO_MODE_PAL;
162
        }
163
 
164
        saa7110_write(decoder,0x06,0x00);
165
        if (status & 0x20) {    /* 60Hz */
166
                DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",dev->name));
167
                saa7110_write(decoder,0x0D,0x06);
168
                saa7110_write(decoder,0x11,0x2C);
169
                saa7110_write(decoder,0x2E,0x81);
170
                return VIDEO_MODE_NTSC;
171
        }
172
 
173
        /* 50Hz -> PAL/SECAM */
174
        saa7110_write(decoder,0x0D,0x06);
175
        saa7110_write(decoder,0x11,0x59);
176
        saa7110_write(decoder,0x2E,0x9A);
177
 
178
        mdelay(150);    /* pause 150 ms */
179
 
180
        status = saa7110_read(decoder);
181
        if ((status & 0x03) == 0x01) {
182
                DEBUG(printk(KERN_INFO "%s: norm=secam\n",dev->name));
183
                saa7110_write(decoder,0x0D,0x07);
184
                return VIDEO_MODE_SECAM;
185
        }
186
        DEBUG(printk(KERN_INFO "%s: norm=pal\n",dev->name));
187
        return VIDEO_MODE_PAL;
188
}
189
 
190
static
191
int saa7110_attach(struct i2c_device *device)
192
{
193
static  const unsigned char initseq[] = {
194
             0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF0, 0x00, 0x00,
195
                0xF8, 0xF8, 0x60, 0x60, 0x00, 0x06, 0x18, 0x90,
196
                0x00, 0x2C, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,
197
                0xF0, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198
                0xD9, 0x17, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
199
                0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x81, 0x03,
200
                0x40, 0x75, 0x01, 0x8C, 0x03};
201
        struct  saa7110*        decoder;
202
        int                     rv;
203
 
204
        device->data = decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
205
        if (device->data == 0)
206
                return -ENOMEM;
207
 
208
        MOD_INC_USE_COUNT;
209
 
210
        /* clear our private data */
211
        memset(decoder, 0, sizeof(struct saa7110));
212
        strcpy(device->name, "saa7110");
213
        decoder->bus = device->bus;
214
        decoder->addr = device->addr;
215
        decoder->norm = VIDEO_MODE_PAL;
216
        decoder->input = 0;
217
        decoder->enable = 1;
218
        decoder->bright = 32768;
219
        decoder->contrast = 32768;
220
        decoder->hue = 32768;
221
        decoder->sat = 32768;
222
 
223
        rv = saa7110_write_block(decoder, initseq, sizeof(initseq));
224
        if (rv < 0)
225
                printk(KERN_ERR "%s_attach: init status %d\n", device->name, rv);
226
        else {
227
                saa7110_write(decoder,0x21,0x16);
228
                saa7110_write(decoder,0x0D,0x04);
229
                DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7110_read(decoder)));
230
                saa7110_write(decoder,0x0D,0x06);
231
        }
232
 
233
        /* setup and implicit mode 0 select has been performed */
234
        return 0;
235
}
236
 
237
static
238
int saa7110_detach(struct i2c_device *device)
239
{
240
        struct saa7110* decoder = device->data;
241
 
242
        DEBUG(printk(KERN_INFO "%s_detach\n",device->name));
243
 
244
        /* stop further output */
245
        saa7110_write(decoder,0x0E,0x00);
246
 
247
        kfree(device->data);
248
 
249
        MOD_DEC_USE_COUNT;
250
        return 0;
251
}
252
 
253
static
254
int saa7110_command(struct i2c_device *device, unsigned int cmd, void *arg)
255
{
256
        struct saa7110* decoder = device->data;
257
        int     v;
258
 
259
        switch (cmd) {
260
         case DECODER_GET_CAPABILITIES:
261
                {
262
                        struct video_decoder_capability *dc = arg;
263
                        dc->flags = VIDEO_DECODER_PAL
264
                                  | VIDEO_DECODER_NTSC
265
                                  | VIDEO_DECODER_SECAM
266
                                  | VIDEO_DECODER_AUTO
267
                                  | VIDEO_DECODER_CCIR;
268
                        dc->inputs = SAA7110_MAX_INPUT;
269
                        dc->outputs = SAA7110_MAX_OUTPUT;
270
                }
271
                break;
272
 
273
         case DECODER_GET_STATUS:
274
                {
275
                        struct saa7110* decoder = device->data;
276
                        int status;
277
                        int res = 0;
278
 
279
                        status = i2c_read(device->bus,device->addr|1);
280
                        if (status & 0x40)
281
                                res |= DECODER_STATUS_GOOD;
282
                        if (status & 0x03)
283
                                res |= DECODER_STATUS_COLOR;
284
 
285
                        switch (decoder->norm) {
286
                         case VIDEO_MODE_NTSC:
287
                                res |= DECODER_STATUS_NTSC;
288
                                break;
289
                         case VIDEO_MODE_PAL:
290
                                res |= DECODER_STATUS_PAL;
291
                                break;
292
                         case VIDEO_MODE_SECAM:
293
                                res |= DECODER_STATUS_SECAM;
294
                                break;
295
                        }
296
                        *(int*)arg = res;
297
                }
298
                break;
299
 
300
         case DECODER_SET_NORM:
301
                v = *(int*)arg;
302
                if (decoder->norm != v) {
303
                        decoder->norm = v;
304
                        saa7110_write(decoder, 0x06, 0x00);
305
                        switch (v) {
306
                         case VIDEO_MODE_NTSC:
307
                                saa7110_write(decoder, 0x0D, 0x06);
308
                                saa7110_write(decoder, 0x11, 0x2C);
309
                                saa7110_write(decoder, 0x30, 0x81);
310
                                saa7110_write(decoder, 0x2A, 0xDF);
311
                                break;
312
                         case VIDEO_MODE_PAL:
313
                                saa7110_write(decoder, 0x0D, 0x06);
314
                                saa7110_write(decoder, 0x11, 0x59);
315
                                saa7110_write(decoder, 0x2E, 0x9A);
316
                                break;
317
                         case VIDEO_MODE_SECAM:
318
                                saa7110_write(decoder, 0x0D, 0x07);
319
                                saa7110_write(decoder, 0x11, 0x59);
320
                                saa7110_write(decoder, 0x2E, 0x9A);
321
                                break;
322
                         case VIDEO_MODE_AUTO:
323
                                *(int*)arg = determine_norm(device);
324
                                break;
325
                         default:
326
                                return -EPERM;
327
                        }
328
                }
329
                break;
330
 
331
         case DECODER_SET_INPUT:
332
                v = *(int*)arg;
333
                if (v<0 || v>SAA7110_MAX_INPUT)
334
                        return -EINVAL;
335
                if (decoder->input != v) {
336
                        decoder->input = v;
337
                        saa7110_selmux(device, v);
338
                }
339
                break;
340
 
341
         case DECODER_SET_OUTPUT:
342
                v = *(int*)arg;
343
                /* not much choice of outputs */
344
                if (v != 0)
345
                        return -EINVAL;
346
                break;
347
 
348
         case DECODER_ENABLE_OUTPUT:
349
                v = *(int*)arg;
350
                if (decoder->enable != v) {
351
                        decoder->enable = v;
352
                        saa7110_write(decoder,0x0E, v ? 0x18 : 0x00);
353
                }
354
                break;
355
 
356
         case DECODER_SET_PICTURE:
357
                {
358
                        struct video_picture *pic = arg;
359
 
360
                        if (decoder->bright != pic->brightness) {
361
                                /* We want 0 to 255 we get 0-65535 */
362
                                decoder->bright = pic->brightness;
363
                                saa7110_write(decoder, 0x19, decoder->bright >> 8);
364
                        }
365
                        if (decoder->contrast != pic->contrast) {
366
                                /* We want 0 to 127 we get 0-65535 */
367
                                decoder->contrast = pic->contrast;
368
                                saa7110_write(decoder, 0x13, decoder->contrast >> 9);
369
                        }
370
                        if (decoder->sat != pic->colour) {
371
                                /* We want 0 to 127 we get 0-65535 */
372
                                decoder->sat = pic->colour;
373
                                saa7110_write(decoder, 0x12, decoder->sat >> 9);
374
                        }
375
                        if (decoder->hue != pic->hue) {
376
                                /* We want -128 to 127 we get 0-65535 */
377
                                decoder->hue = pic->hue;
378
                                saa7110_write(decoder, 0x07, (decoder->hue>>8)-128);
379
                        }
380
                }
381
                break;
382
 
383
         case DECODER_DUMP:
384
                for (v=0; v<34; v+=16) {
385
                        int j;
386
                        DEBUG(printk(KERN_INFO "%s: %03x\n",device->name,v));
387
                        for (j=0; j<16; j++) {
388
                                DEBUG(printk(KERN_INFO " %02x",decoder->reg[v+j]));
389
                        }
390
                        DEBUG(printk(KERN_INFO "\n"));
391
                }
392
                break;
393
 
394
         default:
395
                DEBUG(printk(KERN_INFO "unknown saa7110_command?(%d)\n",cmd));
396
                return -EINVAL;
397
        }
398
        return 0;
399
}
400
 
401
/* ----------------------------------------------------------------------- */
402
 
403
static struct i2c_driver i2c_driver_saa7110 =
404
{
405
        "saa7110",                      /* name */
406
 
407
        I2C_DRIVERID_VIDEODECODER,      /* in i2c-old.h */
408
        I2C_SAA7110, I2C_SAA7110+1,     /* Addr range */
409
 
410
        saa7110_attach,
411
        saa7110_detach,
412
        saa7110_command
413
};
414
 
415
EXPORT_NO_SYMBOLS;
416
 
417
static int saa7110_init(void)
418
{
419
        return i2c_register_driver(&i2c_driver_saa7110);
420
}
421
 
422
static void saa7110_exit(void)
423
{
424
        i2c_unregister_driver(&i2c_driver_saa7110);
425
}
426
 
427
 
428
module_init(saa7110_init);
429
module_exit(saa7110_exit);
430
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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