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

Subversion Repositories test_project

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

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

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Driver for the SAA5246A or SAA5281 Teletext (=Videotext) decoder chips from
3
 * Philips.
4
 *
5
 * Only capturing of Teletext pages is tested. The videotext chips also have a
6
 * TV output but my hardware doesn't use it. For this reason this driver does
7
 * not support changing any TV display settings.
8
 *
9
 * Copyright (C) 2004 Michael Geng <linux@MichaelGeng.de>
10
 *
11
 * Derived from
12
 *
13
 * saa5249 driver
14
 * Copyright (C) 1998 Richard Guenther
15
 * <richard.guenther@student.uni-tuebingen.de>
16
 *
17
 * with changes by
18
 * Alan Cox <Alan.Cox@linux.org>
19
 *
20
 * and
21
 *
22
 * vtx.c
23
 * Copyright (C) 1994-97 Martin Buck  <martin-2.buck@student.uni-ulm.de>
24
 *
25
 * This program is free software; you can redistribute it and/or modify
26
 * it under the terms of the GNU General Public License as published by
27
 * the Free Software Foundation; either version 2 of the License, or
28
 * (at your option) any later version.
29
 *
30
 * This program is distributed in the hope that it will be useful,
31
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33
 * GNU General Public License for more details.
34
 *
35
 * You should have received a copy of the GNU General Public License
36
 * along with this program; if not, write to the Free Software
37
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
38
 * USA.
39
 */
40
 
41
#include <linux/module.h>
42
#include <linux/kernel.h>
43
#include <linux/mm.h>
44
#include <linux/init.h>
45
#include <linux/i2c.h>
46
#include <linux/videotext.h>
47
#include <linux/videodev.h>
48
#include <media/v4l2-common.h>
49
#include <linux/mutex.h>
50
 
51
#include "saa5246a.h"
52
 
53
MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>");
54
MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver");
55
MODULE_LICENSE("GPL");
56
 
57
struct saa5246a_device
58
{
59
        u8     pgbuf[NUM_DAUS][VTX_VIRTUALSIZE];
60
        int    is_searching[NUM_DAUS];
61
        struct i2c_client *client;
62
        struct mutex lock;
63
};
64
 
65
static struct video_device saa_template;        /* Declared near bottom */
66
 
67
/* Addresses to scan */
68
static unsigned short normal_i2c[]       = { I2C_ADDRESS, I2C_CLIENT_END };
69
I2C_CLIENT_INSMOD;
70
 
71
static struct i2c_client client_template;
72
 
73
static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind)
74
{
75
        int pgbuf;
76
        int err;
77
        struct i2c_client *client;
78
        struct video_device *vd;
79
        struct saa5246a_device *t;
80
 
81
        printk(KERN_INFO "saa5246a: teletext chip found.\n");
82
        client=kmalloc(sizeof(*client), GFP_KERNEL);
83
        if(client==NULL)
84
                return -ENOMEM;
85
        client_template.adapter = adap;
86
        client_template.addr = addr;
87
        memcpy(client, &client_template, sizeof(*client));
88
        t = kzalloc(sizeof(*t), GFP_KERNEL);
89
        if(t==NULL)
90
        {
91
                kfree(client);
92
                return -ENOMEM;
93
        }
94
        strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
95
        mutex_init(&t->lock);
96
 
97
        /*
98
         *      Now create a video4linux device
99
         */
100
 
101
        vd = video_device_alloc();
102
        if(vd==NULL)
103
        {
104
                kfree(t);
105
                kfree(client);
106
                return -ENOMEM;
107
        }
108
        i2c_set_clientdata(client, vd);
109
        memcpy(vd, &saa_template, sizeof(*vd));
110
 
111
        for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
112
        {
113
                memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0]));
114
                t->is_searching[pgbuf] = false;
115
        }
116
        vd->priv=t;
117
 
118
 
119
        /*
120
         *      Register it
121
         */
122
 
123
        if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0)
124
        {
125
                kfree(t);
126
                kfree(client);
127
                video_device_release(vd);
128
                return err;
129
        }
130
        t->client = client;
131
        i2c_attach_client(client);
132
        return 0;
133
}
134
 
135
/*
136
 *      We do most of the hard work when we become a device on the i2c.
137
 */
138
static int saa5246a_probe(struct i2c_adapter *adap)
139
{
140
        if (adap->class & I2C_CLASS_TV_ANALOG)
141
                return i2c_probe(adap, &addr_data, saa5246a_attach);
142
        return 0;
143
}
144
 
145
static int saa5246a_detach(struct i2c_client *client)
146
{
147
        struct video_device *vd = i2c_get_clientdata(client);
148
        i2c_detach_client(client);
149
        video_unregister_device(vd);
150
        kfree(vd->priv);
151
        kfree(client);
152
        return 0;
153
}
154
 
155
/*
156
 *      I2C interfaces
157
 */
158
 
159
static struct i2c_driver i2c_driver_videotext =
160
{
161
        .driver = {
162
                .name   = IF_NAME,              /* name */
163
        },
164
        .id             = I2C_DRIVERID_SAA5249, /* in i2c.h */
165
        .attach_adapter = saa5246a_probe,
166
        .detach_client  = saa5246a_detach,
167
};
168
 
169
static struct i2c_client client_template = {
170
        .driver         = &i2c_driver_videotext,
171
        .name           = "(unset)",
172
};
173
 
174
static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data)
175
{
176
        char buf[64];
177
 
178
        buf[0] = reg;
179
        memcpy(buf+1, data, count);
180
 
181
        if(i2c_master_send(t->client, buf, count+1)==count+1)
182
                return 0;
183
        return -1;
184
}
185
 
186
static int i2c_senddata(struct saa5246a_device *t, ...)
187
{
188
        unsigned char buf[64];
189
        int v;
190
        int ct = 0;
191
        va_list argp;
192
        va_start(argp, t);
193
 
194
        while ((v = va_arg(argp, int)) != -1)
195
                buf[ct++] = v;
196
 
197
        va_end(argp);
198
        return i2c_sendbuf(t, buf[0], ct-1, buf+1);
199
}
200
 
201
/* Get count number of bytes from I²C-device at address adr, store them in buf.
202
 * Start & stop handshaking is done by this routine, ack will be sent after the
203
 * last byte to inhibit further sending of data. If uaccess is 'true', data is
204
 * written to user-space with put_user. Returns -1 if I²C-device didn't send
205
 * acknowledge, 0 otherwise
206
 */
207
static int i2c_getdata(struct saa5246a_device *t, int count, u8 *buf)
208
{
209
        if(i2c_master_recv(t->client, buf, count)!=count)
210
                return -1;
211
        return 0;
212
}
213
 
214
/* When a page is found then the not FOUND bit in one of the status registers
215
 * of the SAA5264A chip is cleared. Unfortunately this bit is not set
216
 * automatically when a new page is requested. Instead this function must be
217
 * called after a page has been requested.
218
 *
219
 * Return value: 0 if successful
220
 */
221
static int saa5246a_clear_found_bit(struct saa5246a_device *t,
222
        unsigned char dau_no)
223
{
224
        unsigned char row_25_column_8;
225
 
226
        if (i2c_senddata(t, SAA5246A_REGISTER_R8,
227
 
228
                dau_no |
229
                R8_DO_NOT_CLEAR_MEMORY,
230
 
231
                R9_CURSER_ROW_25,
232
 
233
                R10_CURSER_COLUMN_8,
234
 
235
                COMMAND_END) ||
236
                i2c_getdata(t, 1, &row_25_column_8))
237
        {
238
                return -EIO;
239
        }
240
        row_25_column_8 |= ROW25_COLUMN8_PAGE_NOT_FOUND;
241
        if (i2c_senddata(t, SAA5246A_REGISTER_R8,
242
 
243
                dau_no |
244
                R8_DO_NOT_CLEAR_MEMORY,
245
 
246
                R9_CURSER_ROW_25,
247
 
248
                R10_CURSER_COLUMN_8,
249
 
250
                row_25_column_8,
251
 
252
                COMMAND_END))
253
        {
254
                return -EIO;
255
        }
256
 
257
        return 0;
258
}
259
 
260
/* Requests one videotext page as described in req. The fields of req are
261
 * checked and an error is returned if something is invalid.
262
 *
263
 * Return value: 0 if successful
264
 */
265
static int saa5246a_request_page(struct saa5246a_device *t,
266
    vtx_pagereq_t *req)
267
{
268
        if (req->pagemask < 0 || req->pagemask >= PGMASK_MAX)
269
                return -EINVAL;
270
        if (req->pagemask & PGMASK_PAGE)
271
                if (req->page < 0 || req->page > PAGE_MAX)
272
                        return -EINVAL;
273
        if (req->pagemask & PGMASK_HOUR)
274
                if (req->hour < 0 || req->hour > HOUR_MAX)
275
                        return -EINVAL;
276
        if (req->pagemask & PGMASK_MINUTE)
277
                if (req->minute < 0 || req->minute > MINUTE_MAX)
278
                        return -EINVAL;
279
        if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
280
                return -EINVAL;
281
 
282
        if (i2c_senddata(t, SAA5246A_REGISTER_R2,
283
 
284
                R2_IN_R3_SELECT_PAGE_HUNDREDS |
285
                req->pgbuf << 4 |
286
                R2_BANK_0 |
287
                R2_HAMMING_CHECK_OFF,
288
 
289
                HUNDREDS_OF_PAGE(req->page) |
290
                R3_HOLD_PAGE |
291
                (req->pagemask & PG_HUND ?
292
                        R3_PAGE_HUNDREDS_DO_CARE :
293
                        R3_PAGE_HUNDREDS_DO_NOT_CARE),
294
 
295
                TENS_OF_PAGE(req->page) |
296
                (req->pagemask & PG_TEN ?
297
                        R3_PAGE_TENS_DO_CARE :
298
                        R3_PAGE_TENS_DO_NOT_CARE),
299
 
300
                UNITS_OF_PAGE(req->page) |
301
                (req->pagemask & PG_UNIT ?
302
                        R3_PAGE_UNITS_DO_CARE :
303
                        R3_PAGE_UNITS_DO_NOT_CARE),
304
 
305
                TENS_OF_HOUR(req->hour) |
306
                (req->pagemask & HR_TEN ?
307
                        R3_HOURS_TENS_DO_CARE :
308
                        R3_HOURS_TENS_DO_NOT_CARE),
309
 
310
                UNITS_OF_HOUR(req->hour) |
311
                (req->pagemask & HR_UNIT ?
312
                        R3_HOURS_UNITS_DO_CARE :
313
                        R3_HOURS_UNITS_DO_NOT_CARE),
314
 
315
                TENS_OF_MINUTE(req->minute) |
316
                (req->pagemask & MIN_TEN ?
317
                        R3_MINUTES_TENS_DO_CARE :
318
                        R3_MINUTES_TENS_DO_NOT_CARE),
319
 
320
                UNITS_OF_MINUTE(req->minute) |
321
                (req->pagemask & MIN_UNIT ?
322
                        R3_MINUTES_UNITS_DO_CARE :
323
                        R3_MINUTES_UNITS_DO_NOT_CARE),
324
 
325
                COMMAND_END) || i2c_senddata(t, SAA5246A_REGISTER_R2,
326
 
327
                R2_IN_R3_SELECT_PAGE_HUNDREDS |
328
                req->pgbuf << 4 |
329
                R2_BANK_0 |
330
                R2_HAMMING_CHECK_OFF,
331
 
332
                HUNDREDS_OF_PAGE(req->page) |
333
                R3_UPDATE_PAGE |
334
                (req->pagemask & PG_HUND ?
335
                        R3_PAGE_HUNDREDS_DO_CARE :
336
                        R3_PAGE_HUNDREDS_DO_NOT_CARE),
337
 
338
                COMMAND_END))
339
        {
340
                return -EIO;
341
        }
342
 
343
        t->is_searching[req->pgbuf] = true;
344
        return 0;
345
}
346
 
347
/* This routine decodes the page number from the infobits contained in line 25.
348
 *
349
 * Parameters:
350
 * infobits: must be bits 0 to 9 of column 25
351
 *
352
 * Return value: page number coded in hexadecimal, i. e. page 123 is coded 0x123
353
 */
354
static inline int saa5246a_extract_pagenum_from_infobits(
355
    unsigned char infobits[10])
356
{
357
        int page_hundreds, page_tens, page_units;
358
 
359
        page_units    = infobits[0] & ROW25_COLUMN0_PAGE_UNITS;
360
        page_tens     = infobits[1] & ROW25_COLUMN1_PAGE_TENS;
361
        page_hundreds = infobits[8] & ROW25_COLUMN8_PAGE_HUNDREDS;
362
 
363
        /* page 0x.. means page 8.. */
364
        if (page_hundreds == 0)
365
                page_hundreds = 8;
366
 
367
        return((page_hundreds << 8) | (page_tens << 4) | page_units);
368
}
369
 
370
/* Decodes the hour from the infobits contained in line 25.
371
 *
372
 * Parameters:
373
 * infobits: must be bits 0 to 9 of column 25
374
 *
375
 * Return: hour coded in hexadecimal, i. e. 12h is coded 0x12
376
 */
377
static inline int saa5246a_extract_hour_from_infobits(
378
    unsigned char infobits[10])
379
{
380
        int hour_tens, hour_units;
381
 
382
        hour_units = infobits[4] & ROW25_COLUMN4_HOUR_UNITS;
383
        hour_tens  = infobits[5] & ROW25_COLUMN5_HOUR_TENS;
384
 
385
        return((hour_tens << 4) | hour_units);
386
}
387
 
388
/* Decodes the minutes from the infobits contained in line 25.
389
 *
390
 * Parameters:
391
 * infobits: must be bits 0 to 9 of column 25
392
 *
393
 * Return: minutes coded in hexadecimal, i. e. 10min is coded 0x10
394
 */
395
static inline int saa5246a_extract_minutes_from_infobits(
396
    unsigned char infobits[10])
397
{
398
        int minutes_tens, minutes_units;
399
 
400
        minutes_units = infobits[2] & ROW25_COLUMN2_MINUTES_UNITS;
401
        minutes_tens  = infobits[3] & ROW25_COLUMN3_MINUTES_TENS;
402
 
403
        return((minutes_tens << 4) | minutes_units);
404
}
405
 
406
/* Reads the status bits contained in the first 10 columns of the first line
407
 * and extracts the information into info.
408
 *
409
 * Return value: 0 if successful
410
 */
411
static inline int saa5246a_get_status(struct saa5246a_device *t,
412
    vtx_pageinfo_t *info, unsigned char dau_no)
413
{
414
        unsigned char infobits[10];
415
        int column;
416
 
417
        if (dau_no >= NUM_DAUS)
418
                return -EINVAL;
419
 
420
        if (i2c_senddata(t, SAA5246A_REGISTER_R8,
421
 
422
                dau_no |
423
                R8_DO_NOT_CLEAR_MEMORY,
424
 
425
                R9_CURSER_ROW_25,
426
 
427
                R10_CURSER_COLUMN_0,
428
 
429
                COMMAND_END) ||
430
                i2c_getdata(t, 10, infobits))
431
        {
432
                return -EIO;
433
        }
434
 
435
        info->pagenum = saa5246a_extract_pagenum_from_infobits(infobits);
436
        info->hour    = saa5246a_extract_hour_from_infobits(infobits);
437
        info->minute  = saa5246a_extract_minutes_from_infobits(infobits);
438
        info->charset = ((infobits[7] & ROW25_COLUMN7_CHARACTER_SET) >> 1);
439
        info->delete = !!(infobits[3] & ROW25_COLUMN3_DELETE_PAGE);
440
        info->headline = !!(infobits[5] & ROW25_COLUMN5_INSERT_HEADLINE);
441
        info->subtitle = !!(infobits[5] & ROW25_COLUMN5_INSERT_SUBTITLE);
442
        info->supp_header = !!(infobits[6] & ROW25_COLUMN6_SUPPRESS_HEADER);
443
        info->update = !!(infobits[6] & ROW25_COLUMN6_UPDATE_PAGE);
444
        info->inter_seq = !!(infobits[6] & ROW25_COLUMN6_INTERRUPTED_SEQUENCE);
445
        info->dis_disp = !!(infobits[6] & ROW25_COLUMN6_SUPPRESS_DISPLAY);
446
        info->serial = !!(infobits[7] & ROW25_COLUMN7_SERIAL_MODE);
447
        info->notfound = !!(infobits[8] & ROW25_COLUMN8_PAGE_NOT_FOUND);
448
        info->pblf = !!(infobits[9] & ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR);
449
        info->hamming = 0;
450
        for (column = 0; column <= 7; column++) {
451
                if (infobits[column] & ROW25_COLUMN0_TO_7_HAMMING_ERROR) {
452
                        info->hamming = 1;
453
                        break;
454
                }
455
        }
456
        if (!info->hamming && !info->notfound)
457
                t->is_searching[dau_no] = false;
458
        return 0;
459
}
460
 
461
/* Reads 1 videotext page buffer of the SAA5246A.
462
 *
463
 * req is used both as input and as output. It contains information which part
464
 * must be read. The videotext page is copied into req->buffer.
465
 *
466
 * Return value: 0 if successful
467
 */
468
static inline int saa5246a_get_page(struct saa5246a_device *t,
469
        vtx_pagereq_t *req)
470
{
471
        int start, end, size;
472
        char *buf;
473
        int err;
474
 
475
        if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS ||
476
            req->start < 0 || req->start > req->end || req->end >= VTX_PAGESIZE)
477
                return -EINVAL;
478
 
479
        buf = kmalloc(VTX_PAGESIZE, GFP_KERNEL);
480
        if (!buf)
481
                return -ENOMEM;
482
 
483
        /* Read "normal" part of page */
484
        err = -EIO;
485
 
486
        end = min(req->end, VTX_PAGESIZE - 1);
487
        if (i2c_senddata(t, SAA5246A_REGISTER_R8,
488
                        req->pgbuf | R8_DO_NOT_CLEAR_MEMORY,
489
                        ROW(req->start), COLUMN(req->start), COMMAND_END))
490
                goto out;
491
        if (i2c_getdata(t, end - req->start + 1, buf))
492
                goto out;
493
        err = -EFAULT;
494
        if (copy_to_user(req->buffer, buf, end - req->start + 1))
495
                goto out;
496
 
497
        /* Always get the time from buffer 4, since this stupid SAA5246A only
498
         * updates the currently displayed buffer...
499
         */
500
        if (REQ_CONTAINS_TIME(req)) {
501
                start = max(req->start, POS_TIME_START);
502
                end   = min(req->end,   POS_TIME_END);
503
                size = end - start + 1;
504
                err = -EINVAL;
505
                if (size < 0)
506
                        goto out;
507
                err = -EIO;
508
                if (i2c_senddata(t, SAA5246A_REGISTER_R8,
509
                                R8_ACTIVE_CHAPTER_4 | R8_DO_NOT_CLEAR_MEMORY,
510
                                R9_CURSER_ROW_0, start, COMMAND_END))
511
                        goto out;
512
                if (i2c_getdata(t, size, buf))
513
                        goto out;
514
                err = -EFAULT;
515
                if (copy_to_user(req->buffer + start - req->start, buf, size))
516
                        goto out;
517
        }
518
        /* Insert the header from buffer 4 only, if acquisition circuit is still searching for a page */
519
        if (REQ_CONTAINS_HEADER(req) && t->is_searching[req->pgbuf]) {
520
                start = max(req->start, POS_HEADER_START);
521
                end   = min(req->end,   POS_HEADER_END);
522
                size = end - start + 1;
523
                err = -EINVAL;
524
                if (size < 0)
525
                        goto out;
526
                err = -EIO;
527
                if (i2c_senddata(t, SAA5246A_REGISTER_R8,
528
                                R8_ACTIVE_CHAPTER_4 | R8_DO_NOT_CLEAR_MEMORY,
529
                                R9_CURSER_ROW_0, start, COMMAND_END))
530
                        goto out;
531
                if (i2c_getdata(t, end - start + 1, buf))
532
                        goto out;
533
                err = -EFAULT;
534
                if (copy_to_user(req->buffer + start - req->start, buf, size))
535
                        goto out;
536
        }
537
        err = 0;
538
out:
539
        kfree(buf);
540
        return err;
541
}
542
 
543
/* Stops the acquisition circuit given in dau_no. The page buffer associated
544
 * with this acquisition circuit will no more be updated. The other daus are
545
 * not affected.
546
 *
547
 * Return value: 0 if successful
548
 */
549
static inline int saa5246a_stop_dau(struct saa5246a_device *t,
550
    unsigned char dau_no)
551
{
552
        if (dau_no >= NUM_DAUS)
553
                return -EINVAL;
554
        if (i2c_senddata(t, SAA5246A_REGISTER_R2,
555
 
556
                R2_IN_R3_SELECT_PAGE_HUNDREDS |
557
                dau_no << 4 |
558
                R2_BANK_0 |
559
                R2_HAMMING_CHECK_OFF,
560
 
561
                R3_PAGE_HUNDREDS_0 |
562
                R3_HOLD_PAGE |
563
                R3_PAGE_HUNDREDS_DO_NOT_CARE,
564
 
565
                COMMAND_END))
566
        {
567
                return -EIO;
568
        }
569
        t->is_searching[dau_no] = false;
570
        return 0;
571
}
572
 
573
/*  Handles ioctls defined in videotext.h
574
 *
575
 *  Returns 0 if successful
576
 */
577
static int do_saa5246a_ioctl(struct inode *inode, struct file *file,
578
                            unsigned int cmd, void *arg)
579
{
580
        struct video_device *vd = video_devdata(file);
581
        struct saa5246a_device *t=vd->priv;
582
        switch(cmd)
583
        {
584
                case VTXIOCGETINFO:
585
                {
586
                        vtx_info_t *info = arg;
587
 
588
                        info->version_major = MAJOR_VERSION;
589
                        info->version_minor = MINOR_VERSION;
590
                        info->numpages = NUM_DAUS;
591
                        return 0;
592
                }
593
 
594
                case VTXIOCCLRPAGE:
595
                {
596
                        vtx_pagereq_t *req = arg;
597
 
598
                        if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
599
                                return -EINVAL;
600
                        memset(t->pgbuf[req->pgbuf], ' ', sizeof(t->pgbuf[0]));
601
                        return 0;
602
                }
603
 
604
                case VTXIOCCLRFOUND:
605
                {
606
                        vtx_pagereq_t *req = arg;
607
 
608
                        if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
609
                                return -EINVAL;
610
                        return(saa5246a_clear_found_bit(t, req->pgbuf));
611
                }
612
 
613
                case VTXIOCPAGEREQ:
614
                {
615
                        vtx_pagereq_t *req = arg;
616
 
617
                        return(saa5246a_request_page(t, req));
618
                }
619
 
620
                case VTXIOCGETSTAT:
621
                {
622
                        vtx_pagereq_t *req = arg;
623
                        vtx_pageinfo_t info;
624
                        int rval;
625
 
626
                        if ((rval = saa5246a_get_status(t, &info, req->pgbuf)))
627
                                return rval;
628
                        if(copy_to_user(req->buffer, &info,
629
                                sizeof(vtx_pageinfo_t)))
630
                                return -EFAULT;
631
                        return 0;
632
                }
633
 
634
                case VTXIOCGETPAGE:
635
                {
636
                        vtx_pagereq_t *req = arg;
637
 
638
                        return(saa5246a_get_page(t, req));
639
                }
640
 
641
                case VTXIOCSTOPDAU:
642
                {
643
                        vtx_pagereq_t *req = arg;
644
 
645
                        return(saa5246a_stop_dau(t, req->pgbuf));
646
                }
647
 
648
                case VTXIOCPUTPAGE:
649
                case VTXIOCSETDISP:
650
                case VTXIOCPUTSTAT:
651
                        return 0;
652
 
653
                case VTXIOCCLRCACHE:
654
                {
655
                        return 0;
656
                }
657
 
658
                case VTXIOCSETVIRT:
659
                {
660
                        /* I do not know what "virtual mode" means */
661
                        return 0;
662
                }
663
        }
664
        return -EINVAL;
665
}
666
 
667
/*
668
 * Translates old vtx IOCTLs to new ones
669
 *
670
 * This keeps new kernel versions compatible with old userspace programs.
671
 */
672
static inline unsigned int vtx_fix_command(unsigned int cmd)
673
{
674
        switch (cmd) {
675
        case VTXIOCGETINFO_OLD:
676
                cmd = VTXIOCGETINFO;
677
                break;
678
        case VTXIOCCLRPAGE_OLD:
679
                cmd = VTXIOCCLRPAGE;
680
                break;
681
        case VTXIOCCLRFOUND_OLD:
682
                cmd = VTXIOCCLRFOUND;
683
                break;
684
        case VTXIOCPAGEREQ_OLD:
685
                cmd = VTXIOCPAGEREQ;
686
                break;
687
        case VTXIOCGETSTAT_OLD:
688
                cmd = VTXIOCGETSTAT;
689
                break;
690
        case VTXIOCGETPAGE_OLD:
691
                cmd = VTXIOCGETPAGE;
692
                break;
693
        case VTXIOCSTOPDAU_OLD:
694
                cmd = VTXIOCSTOPDAU;
695
                break;
696
        case VTXIOCPUTPAGE_OLD:
697
                cmd = VTXIOCPUTPAGE;
698
                break;
699
        case VTXIOCSETDISP_OLD:
700
                cmd = VTXIOCSETDISP;
701
                break;
702
        case VTXIOCPUTSTAT_OLD:
703
                cmd = VTXIOCPUTSTAT;
704
                break;
705
        case VTXIOCCLRCACHE_OLD:
706
                cmd = VTXIOCCLRCACHE;
707
                break;
708
        case VTXIOCSETVIRT_OLD:
709
                cmd = VTXIOCSETVIRT;
710
                break;
711
        }
712
        return cmd;
713
}
714
 
715
/*
716
 *      Handle the locking
717
 */
718
static int saa5246a_ioctl(struct inode *inode, struct file *file,
719
                         unsigned int cmd, unsigned long arg)
720
{
721
        struct video_device *vd = video_devdata(file);
722
        struct saa5246a_device *t = vd->priv;
723
        int err;
724
 
725
        cmd = vtx_fix_command(cmd);
726
        mutex_lock(&t->lock);
727
        err = video_usercopy(inode, file, cmd, arg, do_saa5246a_ioctl);
728
        mutex_unlock(&t->lock);
729
        return err;
730
}
731
 
732
static int saa5246a_open(struct inode *inode, struct file *file)
733
{
734
        struct video_device *vd = video_devdata(file);
735
        struct saa5246a_device *t = vd->priv;
736
        int err;
737
 
738
        err = video_exclusive_open(inode,file);
739
        if (err < 0)
740
                return err;
741
 
742
        if (t->client==NULL) {
743
                err = -ENODEV;
744
                goto fail;
745
        }
746
 
747
        if (i2c_senddata(t, SAA5246A_REGISTER_R0,
748
 
749
                R0_SELECT_R11 |
750
                R0_PLL_TIME_CONSTANT_LONG |
751
                R0_ENABLE_nODD_EVEN_OUTPUT |
752
                R0_ENABLE_HDR_POLL |
753
                R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED |
754
                R0_NO_FREE_RUN_PLL |
755
                R0_NO_AUTOMATIC_FASTEXT_PROMPT,
756
 
757
                R1_NON_INTERLACED_312_312_LINES |
758
                R1_DEW |
759
                R1_EXTENDED_PACKET_DISABLE |
760
                R1_DAUS_ALL_ON |
761
                R1_8_BITS_NO_PARITY |
762
                R1_VCS_TO_SCS,
763
 
764
                COMMAND_END) ||
765
                i2c_senddata(t, SAA5246A_REGISTER_R4,
766
 
767
                /* We do not care much for the TV display but nevertheless we
768
                 * need the currently displayed page later because only on that
769
                 * page the time is updated. */
770
                R4_DISPLAY_PAGE_4,
771
 
772
                COMMAND_END))
773
        {
774
                err = -EIO;
775
                goto fail;
776
        }
777
 
778
        return 0;
779
 
780
fail:
781
        video_exclusive_release(inode,file);
782
        return err;
783
}
784
 
785
static int saa5246a_release(struct inode *inode, struct file *file)
786
{
787
        struct video_device *vd = video_devdata(file);
788
        struct saa5246a_device *t = vd->priv;
789
 
790
        /* Stop all acquisition circuits. */
791
        i2c_senddata(t, SAA5246A_REGISTER_R1,
792
 
793
                R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES |
794
                R1_DEW |
795
                R1_EXTENDED_PACKET_DISABLE |
796
                R1_DAUS_ALL_OFF |
797
                R1_8_BITS_NO_PARITY |
798
                R1_VCS_TO_SCS,
799
 
800
                COMMAND_END);
801
        video_exclusive_release(inode,file);
802
        return 0;
803
}
804
 
805
static int __init init_saa_5246a (void)
806
{
807
        printk(KERN_INFO
808
                "SAA5246A (or compatible) Teletext decoder driver version %d.%d\n",
809
                MAJOR_VERSION, MINOR_VERSION);
810
        return i2c_add_driver(&i2c_driver_videotext);
811
}
812
 
813
static void __exit cleanup_saa_5246a (void)
814
{
815
        i2c_del_driver(&i2c_driver_videotext);
816
}
817
 
818
module_init(init_saa_5246a);
819
module_exit(cleanup_saa_5246a);
820
 
821
static const struct file_operations saa_fops = {
822
        .owner   = THIS_MODULE,
823
        .open    = saa5246a_open,
824
        .release = saa5246a_release,
825
        .ioctl   = saa5246a_ioctl,
826
        .llseek  = no_llseek,
827
};
828
 
829
static struct video_device saa_template =
830
{
831
        .owner    = THIS_MODULE,
832
        .name     = IF_NAME,
833
        .type     = VID_TYPE_TELETEXT,
834
        .fops     = &saa_fops,
835
        .release  = video_device_release,
836
        .minor    = -1,
837
};

powered by: WebSVN 2.1.0

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