2 * Cleaned up to use existing videodev interface and allow the idea
3 * of multiple teletext decoders on the video4linux iface. Changed i2c
4 * to cover addressing clashes on device busses. It's also rebuilt so
5 * you can add arbitary multiple teletext devices to Linux video4linux
6 * now (well 32 anyway).
8 * Alan Cox <Alan.Cox@linux.org>
10 * The original driver was heavily modified to match the i2c interface
11 * It was truncated to use the WinTV boards, too.
13 * Copyright (c) 1998 Richard Guenther <richard.guenther@student.uni-tuebingen.de>
15 * $Id: saa5249.c,v 1.1 1998/03/30 22:23:23 alan Exp $
20 * This is a loadable character-device-driver for videotext-interfaces
21 * (aka teletext). Please check the Makefile/README for a list of supported
24 * Copyright (c) 1994-97 Martin Buck <martin-2.buck@student.uni-ulm.de>
27 * This program is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License as published by
29 * the Free Software Foundation; either version 2 of the License, or
30 * (at your option) any later version.
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write to the Free Software
39 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
43 #include <linux/module.h>
45 #include <linux/kernel.h>
46 #include <linux/sched.h>
48 #include <linux/errno.h>
49 #include <linux/delay.h>
50 #include <linux/ioport.h>
51 #include <linux/malloc.h>
53 #include <asm/uaccess.h>
55 #include <linux/i2c.h>
56 #include <linux/videotext.h>
57 #include <linux/videodev.h>
66 #define IF_NAME "SAA5249"
68 static const int disp_modes
[8][3] =
70 { 0x46, 0x03, 0x03 }, /* DISPOFF */
71 { 0x46, 0xcc, 0xcc }, /* DISPNORM */
72 { 0x44, 0x0f, 0x0f }, /* DISPTRANS */
73 { 0x46, 0xcc, 0x46 }, /* DISPINS */
74 { 0x44, 0x03, 0x03 }, /* DISPOFF, interlaced */
75 { 0x44, 0xcc, 0xcc }, /* DISPNORM, interlaced */
76 { 0x44, 0x0f, 0x0f }, /* DISPTRANS, interlaced */
77 { 0x44, 0xcc, 0x46 } /* DISPINS, interlaced */
82 #define PAGE_WAIT 30 /* Time in jiffies between requesting page and */
83 /* checking status bits */
84 #define PGBUF_EXPIRE 1500 /* Time in jiffies to wait before retransmitting */
85 /* page regardless of infobits */
87 u8 pgbuf
[VTX_VIRTUALSIZE
]; /* Page-buffer */
88 u8 laststat
[10]; /* Last value of infobits for DAU */
89 u8 sregs
[7]; /* Page-request registers */
90 unsigned long expire
; /* Time when page will be expired */
91 unsigned clrfound
: 1; /* VTXIOCCLRFOUND has been called */
92 unsigned stopped
: 1; /* VTXIOCSTOPDAU has been called */
97 vdau_t vdau
[NUM_DAUS
]; /* Data for virtual DAUs (the 5249 only has one */
98 /* real DAU, so we have to simulate some more) */
100 int is_searching
[NUM_DAUS
];
107 #define CCTWR 34 /* I²C write/read-address of vtx-chip */
109 #define NOACK_REPEAT 10 /* Retry access this many times on failure */
110 #define CLEAR_DELAY 5 /* Time in jiffies required to clear a page */
111 #define I2C_TIMEOUT 300 /* open/close/SDA-check timeout in jiffies */
112 #define READY_TIMEOUT 3 /* Time in jiffies to wait for ready signal of I²C-bus interface */
113 #define INIT_DELAY 500 /* Time in usec to wait at initialization of CEA interface */
114 #define START_DELAY 10 /* Time in usec to wait before starting write-cycle (CEA) */
116 #define VTX_DEV_MINOR 0
118 /* General defines and debugging support */
125 #define MIN(a, b) ((a) < (b) ? (a) : (b))
126 #define MAX(a, b) ((a) > (b) ? (a) : (b))
131 if (current->need_resched) \
135 static struct video_device saa_template
; /* Declared near bottom */
138 * We do most of the hard work when we become a device on the i2c.
141 static int saa5249_attach(struct i2c_device
*device
)
145 struct video_device
*vd
;
146 struct saa5249_device
*t
;
147 /* Only attach these chips to the BT848 bus for now */
149 if(device
->bus
->id
!=I2C_BUSID_BT848
)
152 strcpy(device
->name
, IF_NAME
);
155 * Now create a video4linux device
158 vd
=(struct video_device
*)kmalloc(sizeof(struct video_device
), GFP_KERNEL
);
162 memcpy(vd
, &saa_template
, sizeof(*vd
));
165 * Attach an saa5249 device
168 t
=(struct saa5249_device
*)kmalloc(sizeof(struct saa5249_device
), GFP_KERNEL
);
175 memset(t
, 0, sizeof(*t
));
177 for (pgbuf
= 0; pgbuf
< NUM_DAUS
; pgbuf
++)
179 memset(t
->vdau
[pgbuf
].pgbuf
, ' ', sizeof(t
->vdau
[0].pgbuf
));
180 memset(t
->vdau
[pgbuf
].sregs
, 0, sizeof(t
->vdau
[0].sregs
));
181 memset(t
->vdau
[pgbuf
].laststat
, 0, sizeof(t
->vdau
[0].laststat
));
182 t
->vdau
[pgbuf
].expire
= 0;
183 t
->vdau
[pgbuf
].clrfound
= TRUE
;
184 t
->vdau
[pgbuf
].stopped
= TRUE
;
185 t
->is_searching
[pgbuf
] = FALSE
;
194 if((err
=video_register_device(vd
, VFL_TYPE_VTX
))<0)
200 t
->bus
= device
->bus
;
204 static int saa5249_detach(struct i2c_device
*device
)
206 struct video_device
*vd
=device
->data
;
207 video_unregister_device(vd
);
213 static int saa5249_command(struct i2c_device
*device
,
214 unsigned int cmd
, void *arg
)
219 /* new I2C driver support */
221 static struct i2c_driver i2c_driver_videotext
=
224 I2C_DRIVERID_VIDEOTEXT
, /* in i2c.h */
225 34, 35, /* Addr range */
232 * Wait the given number of jiffies (10ms). This calls the scheduler, so the actual
233 * delay may be longer.
236 static void jdelay(unsigned long delay
)
238 sigset_t oldblocked
= current
->blocked
;
240 spin_lock_irq(¤t
->sigmask_lock
);
241 sigfillset(¤t
->blocked
);
242 recalc_sigpending(current
);
243 spin_unlock_irq(¤t
->sigmask_lock
);
244 current
->state
= TASK_INTERRUPTIBLE
;
245 schedule_timeout(delay
);
247 spin_lock_irq(¤t
->sigmask_lock
);
248 current
->blocked
= oldblocked
;
249 recalc_sigpending(current
);
250 spin_unlock_irq(¤t
->sigmask_lock
);
254 /* Send arbitrary number of bytes to I²C-bus. Start & stop handshaking is done by this routine.
255 * adr should be address of I²C-device, varargs-list of values to send must be terminated by -1
256 * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise
259 static int i2c_senddata(struct saa5249_device
*t
, int adr
, ...)
264 for (loop
= 0; loop
<= NOACK_REPEAT
; loop
++)
267 if (i2c_sendbyte(t
->bus
, adr
, 0) != 0)
271 while ((val
= va_arg(argp
, int)) != -1)
273 if (val
< 0 || val
> 255)
275 printk(KERN_ERR
"vtx: internal error in i2c_senddata\n");
278 if (i2c_sendbyte(t
->bus
, val
, 0) != 0)
292 /* Send count number of bytes from buffer buf to I²C-device adr. Start & stop handshaking is
293 * done by this routine. If uaccess is TRUE, data is read from user-space with get_user.
294 * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise
297 static int i2c_sendbuf(struct saa5249_device
*t
, int adr
, int reg
, int count
, u8
*buf
, int uaccess
)
302 for (loop
= 0; loop
<= NOACK_REPEAT
; loop
++)
305 if (i2c_sendbyte(t
->bus
, adr
, 0) != 0 || i2c_sendbyte(t
->bus
, reg
, 0) != 0)
307 for (pos
= 0; pos
< count
; pos
++)
309 /* FIXME: FAULT WITH CLI/SPINLOCK ?? */
311 get_user(val
, buf
+ pos
);
314 if (i2c_sendbyte(t
->bus
, val
, 0) != 0)
327 /* Get count number of bytes from I²C-device at address adr, store them in buf. Start & stop
328 * handshaking is done by this routine, ack will be sent after the last byte to inhibit further
329 * sending of data. If uaccess is TRUE, data is written to user-space with put_user.
330 * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise
333 static int i2c_getdata(struct saa5249_device
*t
, int adr
, int count
, u8
*buf
, int uaccess
)
337 for (loop
= 0; loop
<= NOACK_REPEAT
; loop
++)
340 if (i2c_sendbyte(t
->bus
, adr
, 1) != 0)
342 for (pos
= 0; pos
< count
; pos
++)
344 val
= i2c_readbyte(t
->bus
, (pos
==count
-1) ? 1 : 0);
346 put_user(val
, buf
+ pos
);
361 * Standard character-device-driver functions
364 static int saa5249_ioctl(struct video_device
*vd
, unsigned int cmd
, void *arg
)
366 struct saa5249_device
*t
=vd
->priv
;
367 static int virtual_mode
= FALSE
;
374 info
.version_major
= VTX_VER_MAJ
;
375 info
.version_minor
= VTX_VER_MIN
;
376 info
.numpages
= NUM_DAUS
;
377 /*info.cct_type = CCT_TYPE;*/
378 if(copy_to_user((void*)arg
, &info
, sizeof(vtx_info_t
)))
387 if(copy_from_user(&req
, (void*)arg
, sizeof(vtx_pagereq_t
)))
389 if (req
.pgbuf
< 0 || req
.pgbuf
>= NUM_DAUS
)
391 memset(t
->vdau
[req
.pgbuf
].pgbuf
, ' ', sizeof(t
->vdau
[0].pgbuf
));
392 t
->vdau
[req
.pgbuf
].clrfound
= TRUE
;
400 if(copy_from_user(&req
, (void*)arg
, sizeof(vtx_pagereq_t
)))
402 if (req
.pgbuf
< 0 || req
.pgbuf
>= NUM_DAUS
)
404 t
->vdau
[req
.pgbuf
].clrfound
= TRUE
;
411 if(copy_from_user(&req
, (void*)arg
, sizeof(vtx_pagereq_t
)))
413 if (!(req
.pagemask
& PGMASK_PAGE
))
415 if (!(req
.pagemask
& PGMASK_HOUR
))
417 if (!(req
.pagemask
& PGMASK_MINUTE
))
419 if (req
.page
< 0 || req
.page
> 0x8ff) /* 7FF ?? */
422 if (req
.hour
< 0 || req
.hour
> 0x3f || req
.minute
< 0 || req
.minute
> 0x7f ||
423 req
.pagemask
< 0 || req
.pagemask
>= PGMASK_MAX
|| req
.pgbuf
< 0 || req
.pgbuf
>= NUM_DAUS
)
425 t
->vdau
[req
.pgbuf
].sregs
[0] = (req
.pagemask
& PG_HUND
? 0x10 : 0) | (req
.page
/ 0x100);
426 t
->vdau
[req
.pgbuf
].sregs
[1] = (req
.pagemask
& PG_TEN
? 0x10 : 0) | ((req
.page
/ 0x10) & 0xf);
427 t
->vdau
[req
.pgbuf
].sregs
[2] = (req
.pagemask
& PG_UNIT
? 0x10 : 0) | (req
.page
& 0xf);
428 t
->vdau
[req
.pgbuf
].sregs
[3] = (req
.pagemask
& HR_TEN
? 0x10 : 0) | (req
.hour
/ 0x10);
429 t
->vdau
[req
.pgbuf
].sregs
[4] = (req
.pagemask
& HR_UNIT
? 0x10 : 0) | (req
.hour
& 0xf);
430 t
->vdau
[req
.pgbuf
].sregs
[5] = (req
.pagemask
& MIN_TEN
? 0x10 : 0) | (req
.minute
/ 0x10);
431 t
->vdau
[req
.pgbuf
].sregs
[6] = (req
.pagemask
& MIN_UNIT
? 0x10 : 0) | (req
.minute
& 0xf);
432 t
->vdau
[req
.pgbuf
].stopped
= FALSE
;
433 t
->vdau
[req
.pgbuf
].clrfound
= TRUE
;
434 t
->is_searching
[req
.pgbuf
] = TRUE
;
445 if(copy_from_user(&req
, (void*)arg
, sizeof(vtx_pagereq_t
)))
447 if (req
.pgbuf
< 0 || req
.pgbuf
>= NUM_DAUS
)
449 if (!t
->vdau
[req
.pgbuf
].stopped
)
451 if (i2c_senddata(t
, CCTWR
, 2, 0, -1) ||
452 i2c_sendbuf(t
, CCTWR
, 3, sizeof(t
->vdau
[0].sregs
), t
->vdau
[req
.pgbuf
].sregs
, FALSE
) ||
453 i2c_senddata(t
, CCTWR
, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) ||
454 i2c_senddata(t
, CCTWR
, 2, 0, t
->vdau
[req
.pgbuf
].sregs
[0] | 8, -1) ||
455 i2c_senddata(t
, CCTWR
, 8, 0, 25, 0, -1))
458 if (i2c_getdata(t
, CCTRD
, 10, infobits
, FALSE
))
461 if (!(infobits
[8] & 0x10) && !(infobits
[7] & 0xf0) && /* check FOUND-bit */
462 (memcmp(infobits
, t
->vdau
[req
.pgbuf
].laststat
, sizeof(infobits
)) ||
463 time_after_eq(jiffies
, t
->vdau
[req
.pgbuf
].expire
)))
464 { /* check if new page arrived */
465 if (i2c_senddata(t
, CCTWR
, 8, 0, 0, 0, -1) ||
466 i2c_getdata(t
, CCTRD
, VTX_PAGESIZE
, t
->vdau
[req
.pgbuf
].pgbuf
, FALSE
))
468 t
->vdau
[req
.pgbuf
].expire
= jiffies
+ PGBUF_EXPIRE
;
469 memset(t
->vdau
[req
.pgbuf
].pgbuf
+ VTX_PAGESIZE
, ' ', VTX_VIRTUALSIZE
- VTX_PAGESIZE
);
473 if (i2c_senddata(t
, CCTWR
, 8, 0, 0x20, 0, -1) ||
474 i2c_getdata(t
, CCTRD
, 40, t
->vdau
[req
.pgbuf
].pgbuf
+ VTX_PAGESIZE
+ 20 * 40, FALSE
))
477 if (i2c_senddata(t
, CCTWR
, 8, 0, 0x21, 0, -1) ||
478 i2c_getdata(t
, CCTRD
, 40, t
->vdau
[req
.pgbuf
].pgbuf
+ VTX_PAGESIZE
+ 16 * 40, FALSE
))
480 /* Packet 8/30/0...8/30/15
481 * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30,
482 * so we should undo this here.
484 if (i2c_senddata(t
, CCTWR
, 8, 0, 0x22, 0, -1) ||
485 i2c_getdata(t
, CCTRD
, 40, t
->vdau
[req
.pgbuf
].pgbuf
+ VTX_PAGESIZE
+ 23 * 40, FALSE
))
488 t
->vdau
[req
.pgbuf
].clrfound
= FALSE
;
489 memcpy(t
->vdau
[req
.pgbuf
].laststat
, infobits
, sizeof(infobits
));
493 memcpy(infobits
, t
->vdau
[req
.pgbuf
].laststat
, sizeof(infobits
));
498 memcpy(infobits
, t
->vdau
[req
.pgbuf
].laststat
, sizeof(infobits
));
501 info
.pagenum
= ((infobits
[8] << 8) & 0x700) | ((infobits
[1] << 4) & 0xf0) | (infobits
[0] & 0x0f);
502 if (info
.pagenum
< 0x100)
503 info
.pagenum
+= 0x800;
504 info
.hour
= ((infobits
[5] << 4) & 0x30) | (infobits
[4] & 0x0f);
505 info
.minute
= ((infobits
[3] << 4) & 0x70) | (infobits
[2] & 0x0f);
506 info
.charset
= ((infobits
[7] >> 1) & 7);
507 info
.delete = !!(infobits
[3] & 8);
508 info
.headline
= !!(infobits
[5] & 4);
509 info
.subtitle
= !!(infobits
[5] & 8);
510 info
.supp_header
= !!(infobits
[6] & 1);
511 info
.update
= !!(infobits
[6] & 2);
512 info
.inter_seq
= !!(infobits
[6] & 4);
513 info
.dis_disp
= !!(infobits
[6] & 8);
514 info
.serial
= !!(infobits
[7] & 1);
515 info
.notfound
= !!(infobits
[8] & 0x10);
516 info
.pblf
= !!(infobits
[9] & 0x20);
518 for (a
= 0; a
<= 7; a
++)
520 if (infobits
[a
] & 0xf0)
526 if (t
->vdau
[req
.pgbuf
].clrfound
)
528 if(copy_to_user(req
.buffer
, &info
, sizeof(vtx_pageinfo_t
)))
530 if (!info
.hamming
&& !info
.notfound
)
532 t
->is_searching
[req
.pgbuf
] = FALSE
;
542 if(copy_from_user(&req
, (void*)arg
, sizeof(vtx_pagereq_t
)))
544 if (req
.pgbuf
< 0 || req
.pgbuf
>= NUM_DAUS
|| req
.start
< 0 ||
545 req
.start
> req
.end
|| req
.end
>= (virtual_mode
? VTX_VIRTUALSIZE
: VTX_PAGESIZE
))
547 if(copy_to_user(req
.buffer
, &t
->vdau
[req
.pgbuf
].pgbuf
[req
.start
], req
.end
- req
.start
+ 1))
551 * Always read the time directly from SAA5249
554 if (req
.start
<= 39 && req
.end
>= 32)
556 start
= MAX(req
.start
, 32);
557 end
= MIN(req
.end
, 39);
558 if (i2c_senddata(t
, CCTWR
, 8, 0, 0, start
, -1) ||
559 i2c_getdata(t
, CCTRD
, end
- start
+ 1, req
.buffer
+ start
- req
.start
, TRUE
))
562 /* Insert the current header if DAU is still searching for a page */
563 if (req
.start
<= 31 && req
.end
>= 7 && t
->is_searching
[req
.pgbuf
])
565 start
= MAX(req
.start
, 7);
566 end
= MIN(req
.end
, 31);
567 if (i2c_senddata(t
, CCTWR
, 8, 0, 0, start
, -1) ||
568 i2c_getdata(t
, CCTRD
, end
- start
+ 1, req
.buffer
+ start
- req
.start
, TRUE
))
578 if(copy_from_user(&req
, (void*)arg
, sizeof(vtx_pagereq_t
)))
580 if (req
.pgbuf
< 0 || req
.pgbuf
>= NUM_DAUS
)
582 t
->vdau
[req
.pgbuf
].stopped
= TRUE
;
583 t
->is_searching
[req
.pgbuf
] = FALSE
;
594 if (i2c_senddata(t
,CCTWR
, 0, NUM_DAUS
, 0, 8, -1) || i2c_senddata(t
, CCTWR
, 11,
595 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
596 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', -1))
598 if (i2c_senddata(t
, CCTWR
, 3, 0x20, -1))
600 jdelay(10 * CLEAR_DELAY
); /* I have no idea how long we have to wait here */
606 /* The SAA5249 has virtual-row reception turned on always */
607 t
->virtual_mode
= (int)arg
;
615 static int saa5249_open(struct video_device
*vd
, int nb
)
617 struct saa5249_device
*t
=vd
->priv
;
623 if (i2c_senddata(t
, CCTWR
, 0, 0, -1) || /* Select R11 */
624 /* Turn off parity checks (we do this ourselves) */
625 i2c_senddata(t
, CCTWR
, 1, disp_modes
[t
->disp_mode
][0], 0, -1) ||
626 /* Display TV-picture, no virtual rows */
627 i2c_senddata(t
, CCTWR
, 4, NUM_DAUS
, disp_modes
[t
->disp_mode
][1], disp_modes
[t
->disp_mode
][2], 7, -1)) /* Set display to page 4 */
633 for (pgbuf
= 0; pgbuf
< NUM_DAUS
; pgbuf
++)
635 memset(t
->vdau
[pgbuf
].pgbuf
, ' ', sizeof(t
->vdau
[0].pgbuf
));
636 memset(t
->vdau
[pgbuf
].sregs
, 0, sizeof(t
->vdau
[0].sregs
));
637 memset(t
->vdau
[pgbuf
].laststat
, 0, sizeof(t
->vdau
[0].laststat
));
638 t
->vdau
[pgbuf
].expire
= 0;
639 t
->vdau
[pgbuf
].clrfound
= TRUE
;
640 t
->vdau
[pgbuf
].stopped
= TRUE
;
641 t
->is_searching
[pgbuf
] = FALSE
;
643 t
->virtual_mode
=FALSE
;
650 static void saa5249_release(struct video_device
*vd
)
652 struct saa5249_device
*t
=vd
->priv
;
653 i2c_senddata(t
, CCTWR
, 1, 0x20, -1); /* Turn off CCT */
654 i2c_senddata(t
, CCTWR
, 5, 3, 3, -1); /* Turn off TV-display */
659 static long saa5249_write(struct video_device
*v
, const char *buf
, unsigned long l
, int nb
)
664 static long saa5249_read(struct video_device
*v
, char *buf
, unsigned long l
, int nb
)
669 int init_saa_5249(struct video_init
*v
)
671 printk(KERN_INFO
"SAA5249 driver (" IF_NAME
" interface) for VideoText version %d.%d\n",
672 VTX_VER_MAJ
, VTX_VER_MIN
);
673 i2c_register_driver(&i2c_driver_videotext
);
678 static struct video_device saa_template
=
681 VID_TYPE_TELETEXT
, /*| VID_TYPE_TUNER ?? */
682 VID_HARDWARE_SAA5249
,
699 * Routines for loadable modules
702 int init_module(void)
709 void cleanup_module(void)
711 i2c_unregister_driver(&i2c_driver_videotext
);