Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 60450 Details for
Bug 94814
Could we please add Gerd Knorr's kernel patches to sys-kernel/gentoo-sources?
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
All-2.6.11.diff
All-2.6.11.diff (text/plain), 431.60 KB, created by
Charlie Gehlin
on 2005-06-02 05:16:32 UTC
(
hide
)
Description:
All-2.6.11.diff
Filename:
MIME Type:
Creator:
Charlie Gehlin
Created:
2005-06-02 05:16:32 UTC
Size:
431.60 KB
patch
obsolete
>Index: linux-2.6.11/Documentation/scsi-changer.txt >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/Documentation/scsi-changer.txt 2005-03-07 18:13:01.000000000 +0100 >@@ -0,0 +1,180 @@ >+ >+README for the SCSI media changer driver >+======================================== >+ >+This is a driver for SCSI Medium Changer devices, which are listed >+with "Type: Medium Changer" in /proc/scsi/scsi. >+ >+This is for *real* Jukeboxes. It is *not* supported to work with >+common small CD-ROM changers, neither one-lun-per-slot SCSI changers >+nor IDE drives. >+ >+Userland tools available from here: >+ http://linux.bytesex.org/misc/changer.html >+ >+ >+General Information >+------------------- >+ >+First some words about how changers work: A changer has 2 (possibly >+more) SCSI ID's. One for the changer device which controls the robot, >+and one for the device which actually reads and writes the data. The >+later may be anything, a MOD, a CD-ROM, a tape or whatever. For the >+changer device this is a "don't care", he *only* shuffles around the >+media, nothing else. >+ >+ >+The SCSI changer model is complex, compared to - for example - IDE-CD >+changers. But it allows to handle nearly all possible cases. It knows >+4 different types of changer elements: >+ >+ media transport - this one shuffles around the media, i.e. the >+ transport arm. Also known as "picker". >+ storage - a slot which can hold a media. >+ import/export - the same as above, but is accessable from outside, >+ i.e. there the operator (you !) can use this to >+ fill in and remove media from the changer. >+ Sometimes named "mailslot". >+ data transfer - this is the device which reads/writes, i.e. the >+ CD-ROM / Tape / whatever drive. >+ >+None of these is limited to one: A huge Jukebox could have slots for >+123 CD-ROM's, 5 CD-ROM readers (and therefore 6 SCSI ID's: the changer >+and each CD-ROM) and 2 transport arms. No problem to handle. >+ >+ >+How it is implemented >+--------------------- >+ >+I implemented the driver as character device driver with a NetBSD-like >+ioctl interface. Just grabbed NetBSD's header file and one of the >+other linux SCSI device drivers as starting point. The interface >+should be source code compatible with NetBSD. So if there is any >+software (anybody knows ???) which supports a BSDish changer driver, >+it should work with this driver too. >+ >+Over time a few more ioctls where added, volume tag support for example >+wasn't covered by the NetBSD ioctl API. >+ >+ >+Current State >+------------- >+ >+Support for more than one transport arm is not implemented yet (and >+nobody asked for it so far...). >+ >+I test and use the driver myself with a 35 slot cdrom jukebox from >+Grundig. I got some reports telling it works ok with tape autoloaders >+(Exabyte, HP and DEC). Some People use this driver with amanda. It >+works fine with small (11 slots) and a huge (4 MOs, 88 slots) >+magneto-optical Jukebox. Probably with lots of other changers too, most >+(but not all :-) people mail me only if it does *not* work... >+ >+I don't have any device lists, neither black-list nor white-list. Thus >+it is quite useless to ask me whenever a specific device is supported or >+not. In theory every changer device which supports the SCSI-2 media >+changer command set should work out-of-the-box with this driver. If it >+doesn't, it is a bug. Either within the driver or within the firmware >+of the changer device. >+ >+ >+Using it >+-------- >+ >+This is a character device with major number is 86, so use >+"mknod /dev/sch0 c 86 0" to create the special file for the driver. >+ >+If the module finds the changer, it prints some messages about the >+device [ try "dmesg" if you don't see anything ] and should show up in >+/proc/devices. If not.... some changers use ID ? / LUN 0 for the >+device and ID ? / LUN 1 for the robot mechanism. But Linux does *not* >+look for LUN's other than 0 as default, becauce there are to many >+broken devices. So you can try: >+ >+ 1) echo "scsi add-single-device 0 0 ID 1" > /proc/scsi/scsi >+ (replace ID with the SCSI-ID of the device) >+ 2) boot the kernel with "max_scsi_luns=1" on the command line >+ (append="max_scsi_luns=1" in lilo.conf should do the trick) >+ >+ >+Trouble? >+-------- >+ >+If you insmod the driver with "insmod debug=1", it will be verbose and >+prints a lot of stuff to the syslog. Compiling the kernel with >+CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages alot >+because the kernel will translate the error codes into human-readable >+strings then. >+ >+You can display these messages with the dmesg command (or check the >+logfiles). If you email me some question becauce of a problem with the >+driver, please include these messages. >+ >+ >+Insmod options >+-------------- >+ >+debug=0/1 >+ Enable debug messages (see above, default: 0). >+ >+verbose=0/1 >+ Be verbose (default: 1). >+ >+init=0/1 >+ Send INITIALIZE ELEMENT STATUS command to the changer >+ at insmod time (default: 1). >+ >+timeout_init=<seconds> >+ timeout for the INITIALIZE ELEMENT STATUS command >+ (default: 3600). >+ >+timeout_move=<seconds> >+ timeout for all other commands (default: 120). >+ >+dt_id=<id1>,<id2>,... >+dt_lun=<lun1>,<lun2>,... >+ These two allow to specify the SCSI ID and LUN for the data >+ transfer elements. You likely don't need this as the jukebox >+ should provide this information. But some devices don't ... >+ >+vendor_firsts= >+vendor_counts= >+vendor_labels= >+ These insmod options can be used to tell the driver that there >+ are some vendor-specific element types. Grundig for example >+ does this. Some jukeboxes have a printer to label fresh burned >+ CDs, which is addressed as element 0xc000 (type 5). To tell the >+ driver about this vendor-specific element, use this: >+ $ insmod ch \ >+ vendor_firsts=0xc000 \ >+ vendor_counts=1 \ >+ vendor_labels=printer >+ All three insmod options accept up to four comma-separated >+ values, this way you can configure the element types 5-8. >+ You likely need the SCSI specs for the device in question to >+ find the correct values as they are not covered by the SCSI-2 >+ standard. >+ >+ >+Credits >+------- >+ >+I wrote this driver using the famous mailing-patches-around-the-world >+method. With (more or less) help from: >+ >+ Daniel Moehwald <moehwald@hdg.de> >+ Dane Jasper <dane@sonic.net> >+ R. Scott Bailey <sbailey@dsddi.eds.com> >+ Jonathan Corbet <corbet@lwn.net> >+ >+Special thanks go to >+ Martin Kuehne <martin.kuehne@bnbt.de> >+for a old, second-hand (but full functional) cdrom jukebox which I use >+to develop/test driver and tools now. >+ >+Have fun, >+ >+ Gerd >+ >+-- >+Gerd Knorr <kraxel@bytesex.org> >Index: linux-2.6.11/Documentation/video4linux/CARDLIST.saa7134 >=================================================================== >--- linux-2.6.11.orig/Documentation/video4linux/CARDLIST.saa7134 2005-03-07 10:12:23.000000000 +0100 >+++ linux-2.6.11/Documentation/video4linux/CARDLIST.saa7134 2005-03-08 10:33:01.000000000 +0100 >@@ -6,29 +6,30 @@ > 5 -> SKNet Monster TV [1131:4e85] > 6 -> Tevion MD 9717 > 7 -> KNC One TV-Station RDS / Typhoon TV Tuner RDS [1131:fe01,1894:fe01] >- 8 -> KNC One TV-Station DVR [1894:a006] >- 9 -> Terratec Cinergy 400 TV [153B:1142] >- 10 -> Medion 5044 >- 11 -> Kworld/KuroutoShikou SAA7130-TVPCI >- 12 -> Terratec Cinergy 600 TV [153B:1143] >- 13 -> Medion 7134 [16be:0003] >- 14 -> Typhoon TV+Radio 90031 >- 15 -> ELSA EX-VISION 300TV [1048:226b] >- 16 -> ELSA EX-VISION 500TV [1048:226b] >- 17 -> ASUS TV-FM 7134 [1043:4842,1043:4830,1043:4840] >- 18 -> AOPEN VA1000 POWER [1131:7133] >- 19 -> 10MOONS PCI TV CAPTURE CARD [1131:2001] >- 20 -> BMK MPEX No Tuner >- 21 -> Compro VideoMate TV [185b:c100] >- 22 -> Matrox CronosPlus [102B:48d0] >- 23 -> Medion 2819/ AverMedia M156 [1461:a70b,1461:2115] >- 24 -> BMK MPEX Tuner >+ 8 -> Terratec Cinergy 400 TV [153B:1142] >+ 9 -> Medion 5044 >+ 10 -> Kworld/KuroutoShikou SAA7130-TVPCI >+ 11 -> Terratec Cinergy 600 TV [153B:1143] >+ 12 -> Medion 7134 [16be:0003] >+ 13 -> Typhoon TV+Radio 90031 >+ 14 -> ELSA EX-VISION 300TV [1048:226b] >+ 15 -> ELSA EX-VISION 500TV [1048:226b] >+ 16 -> ASUS TV-FM 7134 [1043:4842,1043:4830,1043:4840] >+ 17 -> AOPEN VA1000 POWER [1131:7133] >+ 18 -> BMK MPEX No Tuner >+ 19 -> Compro VideoMate TV [185b:c100] >+ 20 -> Matrox CronosPlus [102B:48d0] >+ 21 -> 10MOONS PCI TV CAPTURE CARD [1131:2001] >+ 22 -> Medion 2819/ AverMedia M156 [1461:a70b,1461:2115] >+ 23 -> BMK MPEX Tuner >+ 24 -> KNC One TV-Station DVR [1894:a006] > 25 -> ASUS TV-FM 7133 [1043:4843] > 26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b] >- 27 -> Manli MuchTV M-TV002 >- 28 -> Manli MuchTV M-TV001 >+ 27 -> Manli MuchTV M-TV002 >+ 28 -> Manli MuchTV M-TV001 > 29 -> Nagase Sangyo TransGear 3000TV [1461:050c] > 30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) [1019:4cb4] > 31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5] >- 32 -> AVACS SmartTV >+ 32 -> AVACS SmartTV > 33 -> AVerMedia DVD EZMaker [1461:10ff] >+ 34 -> LifeView FlyTV Platinum33 mini [5168:0212] >Index: linux-2.6.11/Documentation/video4linux/README.cx88 >=================================================================== >--- linux-2.6.11.orig/Documentation/video4linux/README.cx88 2005-03-07 10:13:25.000000000 +0100 >+++ linux-2.6.11/Documentation/video4linux/README.cx88 2005-03-08 10:33:01.000000000 +0100 >@@ -11,9 +11,6 @@ current status > video > - Basically works. > - Some minor image quality glitches. >- - Red and blue are swapped sometimes for not-yet known >- reasons (seems to depend on the image size, try to resize >- your tv app window as workaround ...). > - For now only capture, overlay support isn't completed yet. > > audio >Index: linux-2.6.11/Documentation/video4linux/bttv/Cards >=================================================================== >--- linux-2.6.11.orig/Documentation/video4linux/bttv/Cards 2005-03-07 10:13:04.000000000 +0100 >+++ linux-2.6.11/Documentation/video4linux/bttv/Cards 2005-03-08 10:33:01.000000000 +0100 >@@ -1,9 +1,9 @@ > > Gunther Mayer's bttv card gallery (graphical version of this text file :-) >-is available at: http://mayerg.gmxhome.de/bttv/bttv-gallery.html >+is available at: http://www.bttv-gallery.de/ > > >-Suppported cards: >+Supported cards: > Bt848/Bt848a/Bt849/Bt878/Bt879 cards > ------------------------------------ > >@@ -166,6 +166,9 @@ Lifeview Flyvideo Series: > or Flyvideo 3000 (SAA7134) w/Stereo TV > These exist in variations w/FM and w/Remote sometimes denoted > by suffixes "FM" and "R". >+ 3) You have a laptop (miniPCI card): >+ Product = FlyTV Platinum Mini >+ Model/Chip = LR212/saa7135 > > Lifeview.com.tw states (Feb. 2002): > "The FlyVideo2000 and FlyVideo2000s product name have renamed to FlyVideo98." >Index: linux-2.6.11/Documentation/video4linux/bttv/README >=================================================================== >--- linux-2.6.11.orig/Documentation/video4linux/bttv/README 2005-03-07 10:12:37.000000000 +0100 >+++ linux-2.6.11/Documentation/video4linux/bttv/README 2005-03-08 10:33:01.000000000 +0100 >@@ -22,7 +22,7 @@ very likely specified the wrong (or no) > cards is in CARDLIST.bttv > > If bttv takes very long to load (happens sometimes with the cheap >-cards which have no tuner), try adding this to your modprobe.conf: >+cards which have no tuner), try adding this to your modules.conf: > options i2c-algo-bit bit_test=1 > > For the WinTV/PVR you need one firmware file from the driver CD: >Index: linux-2.6.11/MAINTAINERS >=================================================================== >--- linux-2.6.11.orig/MAINTAINERS 2005-03-07 10:14:21.000000000 +0100 >+++ linux-2.6.11/MAINTAINERS 2005-03-08 10:33:27.000000000 +0100 >@@ -501,7 +501,7 @@ P: Gerd Knorr > M: kraxel@bytesex.org > L: video4linux-list@redhat.com > W: http://bytesex.org/bttv/ >-S: Maintained >+S: Orphan > > BUSLOGIC SCSI DRIVER > P: Leonard N. Zubkoff >@@ -2534,7 +2534,8 @@ S: Maintained > VIDEO FOR LINUX > P: Gerd Knorr > M: kraxel@bytesex.org >-S: Maintained >+L: video4linux-list@redhat.com >+S: Orphan > > W1 DALLAS'S 1-WIRE BUS > P: Evgeniy Polyakov >Index: linux-2.6.11/arch/x86_64/ia32/ia32_ioctl.c >=================================================================== >--- linux-2.6.11.orig/arch/x86_64/ia32/ia32_ioctl.c 2005-03-07 10:14:05.000000000 +0100 >+++ linux-2.6.11/arch/x86_64/ia32/ia32_ioctl.c 2005-03-08 10:33:27.000000000 +0100 >@@ -18,25 +18,6 @@ > #define CODE > #include "compat_ioctl.c" > >-#ifndef TIOCGDEV >-#define TIOCGDEV _IOR('T',0x32, unsigned int) >-#endif >-static int tiocgdev(unsigned fd, unsigned cmd, unsigned int __user *ptr) >-{ >- >- struct file *file = fget(fd); >- struct tty_struct *real_tty; >- >- if (!file) >- return -EBADF; >- if (file->f_op->ioctl != tty_ioctl) >- return -EINVAL; >- real_tty = (struct tty_struct *)file->private_data; >- if (!real_tty) >- return -EINVAL; >- return put_user(new_encode_dev(tty_devnum(real_tty)), ptr); >-} >- > #define RTC_IRQP_READ32 _IOR('p', 0x0b, unsigned int) /* Read IRQ rate */ > #define RTC_IRQP_SET32 _IOW('p', 0x0c, unsigned int) /* Set IRQ rate */ > #define RTC_EPOCH_READ32 _IOR('p', 0x0d, unsigned) /* Read epoch */ >@@ -176,7 +157,6 @@ COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - > COMPATIBLE_IOCTL(FIOQSIZE) > > /* And these ioctls need translation */ >-HANDLE_IOCTL(TIOCGDEV, tiocgdev) > /* realtime device */ > HANDLE_IOCTL(RTC_IRQP_READ, rtc32_ioctl) > HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl) >Index: linux-2.6.11/drivers/char/tty_io.c >=================================================================== >--- linux-2.6.11.orig/drivers/char/tty_io.c 2005-03-07 10:14:19.000000000 +0100 >+++ linux-2.6.11/drivers/char/tty_io.c 2005-03-08 10:33:27.000000000 +0100 >@@ -2369,6 +2369,21 @@ int tty_ioctl(struct inode * inode, stru > case TIOCMBIC: > case TIOCMBIS: > return tty_tiocmset(tty, file, cmd, p); >+ /* >+ * Without the real device to which /dev/console is connected, >+ * blogd can not work. >+ * blogd spawns a pty/tty pair, >+ * set /dev/console to the tty of that pair (ioctl TIOCCONS), >+ * then reads in all input from the current /dev/console, >+ * buffer or write the readed data to /var/log/boot.msg >+ * _and_ to the original real device. >+ */ >+ case TIOCGDEV: >+ { >+ unsigned int ret = new_encode_dev(tty_devnum(real_tty)); >+ return put_user(ret, (unsigned int __user *)p); >+ } >+ > } > if (tty->driver->ioctl) { > retval = (tty->driver->ioctl)(tty, file, cmd, arg); >Index: linux-2.6.11/drivers/media/common/ir-common.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/common/ir-common.c 2005-03-07 10:14:43.000000000 +0100 >+++ linux-2.6.11/drivers/media/common/ir-common.c 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: ir-common.c,v 1.6 2004/12/10 12:33:39 kraxel Exp $ >+ * $Id: ir-common.c,v 1.8 2005/02/22 12:28:40 kraxel Exp $ > * > * some common structs and functions to handle infrared remotes via > * input layer ... >@@ -23,7 +23,6 @@ > > #include <linux/module.h> > #include <linux/moduleparam.h> >- > #include <media/ir-common.h> > > /* -------------------------------------------------------------------------- */ >@@ -45,6 +44,7 @@ module_param(debug, int, 0644); > > /* generic RC5 keytable */ > /* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ >+/* used by old (black) Hauppauge remotes */ > IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { > [ 0x00 ] = KEY_KP0, // 0 > [ 0x01 ] = KEY_KP1, // 1 >@@ -117,12 +117,102 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB > }; > EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); > >+/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ >+IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { >+ [ 5 ] = KEY_KP1, >+ [ 6 ] = KEY_KP2, >+ [ 7 ] = KEY_KP3, >+ [ 9 ] = KEY_KP4, >+ [ 10 ] = KEY_KP5, >+ [ 11 ] = KEY_KP6, >+ [ 13 ] = KEY_KP7, >+ [ 14 ] = KEY_KP8, >+ [ 15 ] = KEY_KP9, >+ [ 18 ] = KEY_KP0, >+ >+ [ 0 ] = KEY_POWER, >+// [ 27 ] = MTS button >+ [ 2 ] = KEY_TUNER, // TV/FM >+ [ 30 ] = KEY_VIDEO, >+// [ 22 ] = display button >+ [ 4 ] = KEY_VOLUMEUP, >+ [ 8 ] = KEY_VOLUMEDOWN, >+ [ 12 ] = KEY_CHANNELUP, >+ [ 16 ] = KEY_CHANNELDOWN, >+ [ 3 ] = KEY_ZOOM, // fullscreen >+ [ 31 ] = KEY_SUBTITLE, // closed caption/teletext >+ [ 32 ] = KEY_SLEEP, >+// [ 41 ] = boss key >+ [ 20 ] = KEY_MUTE, >+ [ 43 ] = KEY_RED, >+ [ 44 ] = KEY_GREEN, >+ [ 45 ] = KEY_YELLOW, >+ [ 46 ] = KEY_BLUE, >+ [ 24 ] = KEY_KPPLUS, //fine tune + >+ [ 25 ] = KEY_KPMINUS, //fine tune - >+// [ 42 ] = picture in picture >+ [ 33 ] = KEY_KPDOT, >+ [ 19 ] = KEY_KPENTER, >+// [ 17 ] = recall >+ [ 34 ] = KEY_BACK, >+ [ 35 ] = KEY_PLAYPAUSE, >+ [ 36 ] = KEY_NEXT, >+// [ 37 ] = time shifting >+ [ 38 ] = KEY_STOP, >+ [ 39 ] = KEY_RECORD >+// [ 40 ] = snapshot >+}; >+EXPORT_SYMBOL_GPL(ir_codes_winfast); >+ > /* empty keytable, can be used as placeholder for not-yet created keytables */ > IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { > [ 42 ] = KEY_COFFEE, > }; > EXPORT_SYMBOL_GPL(ir_codes_empty); > >+/* Hauppauge: the newer, gray remotes (seems there are multiple >+ * slightly different versions), shipped with cx88+ivtv cards. >+ * almost rc5 coding, but some non-standard keys */ >+IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { >+ [ 0x00 ] = KEY_KP0, // 0 >+ [ 0x01 ] = KEY_KP1, // 1 >+ [ 0x02 ] = KEY_KP2, // 2 >+ [ 0x03 ] = KEY_KP3, // 3 >+ [ 0x04 ] = KEY_KP4, // 4 >+ [ 0x05 ] = KEY_KP5, // 5 >+ [ 0x06 ] = KEY_KP6, // 6 >+ [ 0x07 ] = KEY_KP7, // 7 >+ [ 0x08 ] = KEY_KP8, // 8 >+ [ 0x09 ] = KEY_KP9, // 9 >+ [ 0x0b ] = KEY_RED, // red button >+ [ 0x0c ] = KEY_OPTION, // black key without text >+ [ 0x0d ] = KEY_MENU, // menu >+ [ 0x0f ] = KEY_MUTE, // mute >+ [ 0x10 ] = KEY_VOLUMEUP, // volume + >+ [ 0x11 ] = KEY_VOLUMEDOWN, // volume - >+ [ 0x1e ] = KEY_NEXT, // skip >| >+ [ 0x1f ] = KEY_EXIT, // back/exit >+ [ 0x20 ] = KEY_CHANNELUP, // channel / program + >+ [ 0x21 ] = KEY_CHANNELDOWN, // channel / program - >+ [ 0x22 ] = KEY_CHANNEL, // source (old black remote) >+ [ 0x24 ] = KEY_PREVIOUS, // replay |< >+ [ 0x25 ] = KEY_ENTER, // OK >+ [ 0x26 ] = KEY_SLEEP, // minimize (old black remote) >+ [ 0x29 ] = KEY_BLUE, // blue key >+ [ 0x2e ] = KEY_GREEN, // green button >+ [ 0x30 ] = KEY_PAUSE, // pause >+ [ 0x32 ] = KEY_REWIND, // backward << >+ [ 0x34 ] = KEY_FASTFORWARD, // forward >> >+ [ 0x35 ] = KEY_PLAY, // play >+ [ 0x36 ] = KEY_STOP, // stop >+ [ 0x37 ] = KEY_RECORD, // recording >+ [ 0x38 ] = KEY_YELLOW, // yellow key >+ [ 0x3b ] = KEY_SELECT, // top right button >+ [ 0x3c ] = KEY_ZOOM, // full >+ [ 0x3d ] = KEY_POWER, // system power (green button) >+}; >+EXPORT_SYMBOL(ir_codes_hauppauge_new); >+ > /* -------------------------------------------------------------------------- */ > > static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) >@@ -192,6 +282,8 @@ void ir_input_keydown(struct input_dev * > #endif > } > >+/* -------------------------------------------------------------------------- */ >+ > u32 ir_extract_bits(u32 data, u32 mask) > { > int mbit, vbit; >@@ -209,10 +301,78 @@ u32 ir_extract_bits(u32 data, u32 mask) > return value; > } > >+static int inline getbit(u32 *samples, int bit) >+{ >+ return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0; >+} >+ >+/* sump raw samples for visual debugging ;) */ >+int ir_dump_samples(u32 *samples, int count) >+{ >+ int i, bit, start; >+ >+ printk(KERN_DEBUG "ir samples: "); >+ start = 0; >+ for (i = 0; i < count * 32; i++) { >+ bit = getbit(samples,i); >+ if (bit) >+ start = 1; >+ if (0 == start) >+ continue; >+ printk("%s", bit ? "#" : "_"); >+ } >+ printk("\n"); >+ return 0; >+} >+ >+/* decode raw samples, biphase coding, used by rc5 for example */ >+int ir_decode_biphase(u32 *samples, int count, int low, int high) >+{ >+ int i,last,bit,len,flips; >+ u32 value; >+ >+ /* find start bit (1) */ >+ for (i = 0; i < 32; i++) { >+ bit = getbit(samples,i); >+ if (bit) >+ break; >+ } >+ >+ /* go decoding */ >+ len = 0; >+ flips = 0; >+ value = 1; >+ for (; i < count * 32; i++) { >+ if (len > high) >+ break; >+ if (flips > 1) >+ break; >+ last = bit; >+ bit = getbit(samples,i); >+ if (last == bit) { >+ len++; >+ continue; >+ } >+ if (len < low) { >+ len++; >+ flips++; >+ continue; >+ } >+ value <<= 1; >+ value |= bit; >+ flips = 0; >+ len = 1; >+ } >+ return value; >+} >+ > EXPORT_SYMBOL_GPL(ir_input_init); > EXPORT_SYMBOL_GPL(ir_input_nokey); > EXPORT_SYMBOL_GPL(ir_input_keydown); >+ > EXPORT_SYMBOL_GPL(ir_extract_bits); >+EXPORT_SYMBOL_GPL(ir_dump_samples); >+EXPORT_SYMBOL_GPL(ir_decode_biphase); > > /* > * Local variables: >Index: linux-2.6.11/drivers/media/dvb/dvb-core/dvb_frontend.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/dvb/dvb-core/dvb_frontend.c 2005-03-07 10:13:08.000000000 +0100 >+++ linux-2.6.11/drivers/media/dvb/dvb-core/dvb_frontend.c 2005-03-08 10:33:27.000000000 +0100 >@@ -919,3 +919,24 @@ int dvb_unregister_frontend(struct dvb_f > return 0; > } > EXPORT_SYMBOL(dvb_unregister_frontend); >+ >+void dvb_suspend_frontend(struct dvb_frontend* fe) >+{ >+ if (fe->ops->sleep) >+ fe->ops->sleep(fe); >+} >+EXPORT_SYMBOL(dvb_suspend_frontend); >+ >+void dvb_resume_frontend(struct dvb_frontend* fe) >+{ >+ struct dvb_frontend_private *fepriv = fe->frontend_priv; >+ >+ if (fe->ops->init) >+ fe->ops->init(fe); >+ fepriv->state = FESTATE_RETUNE; >+ dvb_frontend_wakeup(fe); >+ dvb_frontend_add_event (fe, 0); >+ fepriv->status = 0; >+} >+EXPORT_SYMBOL(dvb_resume_frontend); >+ >Index: linux-2.6.11/drivers/media/dvb/dvb-core/dvb_frontend.h >=================================================================== >--- linux-2.6.11.orig/drivers/media/dvb/dvb-core/dvb_frontend.h 2005-03-07 10:15:26.000000000 +0100 >+++ linux-2.6.11/drivers/media/dvb/dvb-core/dvb_frontend.h 2005-03-08 10:33:27.000000000 +0100 >@@ -122,5 +122,7 @@ extern int dvb_register_frontend(struct > struct dvb_frontend* fe); > > extern int dvb_unregister_frontend(struct dvb_frontend* fe); >+extern void dvb_suspend_frontend(struct dvb_frontend* fe); >+extern void dvb_resume_frontend(struct dvb_frontend* fe); > > #endif >Index: linux-2.6.11/drivers/media/dvb/frontends/Kconfig >=================================================================== >--- linux-2.6.11.orig/drivers/media/dvb/frontends/Kconfig 2005-03-07 10:12:55.000000000 +0100 >+++ linux-2.6.11/drivers/media/dvb/frontends/Kconfig 2005-03-08 10:33:27.000000000 +0100 >@@ -157,4 +157,8 @@ config DVB_NXT2002 > help > An ATSC 8VSB tuner module. Say Y when you want to support this frontend. > >+config DVB_OR51132 >+ tristate "OR51132 based (pcHDTV)" >+ depends on DVB_CORE >+ > endmenu >Index: linux-2.6.11/drivers/media/dvb/frontends/Makefile >=================================================================== >--- linux-2.6.11.orig/drivers/media/dvb/frontends/Makefile 2005-03-07 10:12:27.000000000 +0100 >+++ linux-2.6.11/drivers/media/dvb/frontends/Makefile 2005-03-08 10:33:27.000000000 +0100 >@@ -4,6 +4,7 @@ > > EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ > >+obj-$(CONFIG_DVB_CORE) += dvb-pll.o > obj-$(CONFIG_DVB_STV0299) += stv0299.o > obj-$(CONFIG_DVB_SP8870) += sp8870.o > obj-$(CONFIG_DVB_CX22700) += cx22700.o >@@ -25,4 +26,4 @@ obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o > obj-$(CONFIG_DVB_TDA10021) += tda10021.o > obj-$(CONFIG_DVB_STV0297) += stv0297.o > obj-$(CONFIG_DVB_NXT2002) += nxt2002.o >- >+obj-$(CONFIG_DVB_OR51132) += or51132.o >Index: linux-2.6.11/drivers/media/dvb/frontends/cx22702.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/dvb/frontends/cx22702.c 2005-03-07 10:14:54.000000000 +0100 >+++ linux-2.6.11/drivers/media/dvb/frontends/cx22702.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,8 +1,8 @@ > /* >- Conexant 22702 DVB OFDM demodulator driver >+ Conexant 22702 DVB OFDM frontend driver > > based on: >- Alps TDMB7 DVB OFDM demodulator driver >+ Alps TDMB7 DVB OFDM frontend driver > > Copyright (C) 2001-2002 Convergence Integrated Media GmbH > Holger Waechtler <holger@convergence.de> >@@ -31,30 +31,35 @@ > #include <linux/string.h> > #include <linux/slab.h> > #include <linux/delay.h> >+ > #include "dvb_frontend.h" >+#include "dvb-pll.h" > #include "cx22702.h" > >+#define FRONTEND_NAME "dvbfe_cx22702" > >-struct cx22702_state { >- >- struct i2c_adapter* i2c; >- >- struct dvb_frontend_ops ops; >+#define dprintk if (debug) printk > >- /* configuration settings */ >- const struct cx22702_config* config; >+static int debug = 0; >+module_param(debug, int, 0644); >+MODULE_PARM_DESC(debug, "Enable verbose debug messages"); > >- struct dvb_frontend frontend; >+/* ------------------------------------------------------------------ */ > >- /* previous uncorrected block counter */ >+struct cx22702_state { >+ const struct cx22702_config *config; >+ struct i2c_client demod; >+ struct i2c_client pll; >+ struct dvb_frontend fe; >+ struct dvb_frontend_ops ops; > u8 prevUCBlocks; > }; > >-static int debug = 0; >-#define dprintk if (debug) printk >+static struct i2c_client demod_template; >+static struct i2c_client pll_template; > > /* Register values to initialise the demod */ >-static u8 init_tab [] = { >+static u8 init_tab[] = { > 0x00, 0x00, /* Stop aquisition */ > 0x0B, 0x06, > 0x09, 0x01, >@@ -83,73 +88,105 @@ static u8 init_tab [] = { > 0xfd, 0x00, > }; > >-static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data) >+/* ------------------------------------------------------------------ */ >+ >+static int writereg(struct i2c_client *c, u8 reg, u8 data) > { >+ u8 buf[] = { reg, data }; > int ret; >- u8 buf [] = { reg, data }; >- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; > >- ret = i2c_transfer(state->i2c, &msg, 1); >- >- if (ret != 1) >+ ret = i2c_master_send(c, buf, 2); >+ if (ret != 2) { > printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n", >- __FUNCTION__, reg, data, ret); >+ __FUNCTION__, reg, data, ret); >+ return -1; >+ } >+ return 0; >+} > >- return (ret != 1) ? -1 : 0; >+static int readreg(struct i2c_client *c, u8 reg) >+{ >+ u8 wr [] = { reg }; >+ u8 rd [] = { 0 }; >+ struct i2c_msg msg [] = { >+ { .addr = c->addr, .flags = 0, .buf = wr, .len = 1 }, >+ { .addr = c->addr, .flags = I2C_M_RD, .buf = rd, .len = 1 }, >+ }; >+ int ret; >+ >+ ret = i2c_transfer(c->adapter, msg, 2); >+ if (ret != 2) { >+ printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); >+ return -1; >+ } >+ return rd[0]; > } > >-static u8 cx22702_readreg (struct cx22702_state* state, u8 reg) >+/* ------------------------------------------------------------------ */ >+ >+#define PLL_ENABLE(cx) writereg(&cx->demod, 0x0D, readreg(&cx->demod, 0x0D) & 0xfe) >+#define PLL_DISABLE(cx) writereg(&cx->demod, 0x0D, readreg(&cx->demod, 0x0D) | 0x01) >+ >+static int pll_write4(struct i2c_client *c, u8 *data) > { > int ret; >- u8 b0 [] = { reg }; >- u8 b1 [] = { 0 }; > >- struct i2c_msg msg [] = { >- { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, >- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; >+ ret = i2c_master_send(c, data, 4); >+ if (ret != 4) { >+ printk("%s: i/o error (addr == 0x%02x, ret == %i)\n", >+ __FUNCTION__, c->addr, ret); >+ return -EIO; >+ } >+ return 0; >+} > >- ret = i2c_transfer(state->i2c, msg, 2); >+/* ------------------------------------------------------------------ */ > >- if (ret != 2) >- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); >+static int cx22702_reset(struct cx22702_state *state) >+{ >+ int i; > >- return b1[0]; >+ dprintk("%s\n",__FUNCTION__); >+ writereg(&state->demod, 0x00, 0x02); >+ msleep(10); >+ >+ for (i=0; i<ARRAY_SIZE(init_tab); i+=2) >+ writereg(&state->demod, init_tab[i], init_tab[i+1]); >+ return 0; > } > >-static int cx22702_set_inversion (struct cx22702_state *state, int inversion) >+static int cx22702_set_inversion(struct cx22702_state *state, int inversion) > { > u8 val; > > switch (inversion) { >+ case INVERSION_AUTO: >+ return -EOPNOTSUPP; > >- case INVERSION_AUTO: >- return -EOPNOTSUPP; >- >- case INVERSION_ON: >- val = cx22702_readreg (state, 0x0C); >- return cx22702_writereg (state, 0x0C, val | 0x01); >- >- case INVERSION_OFF: >- val = cx22702_readreg (state, 0x0C); >- return cx22702_writereg (state, 0x0C, val & 0xfe); >+ case INVERSION_ON: >+ val = readreg(&state->demod, 0x0C); >+ return writereg(&state->demod, 0x0C, val | 0x01); > >- default: >- return -EINVAL; >+ case INVERSION_OFF: >+ val = readreg(&state->demod, 0x0C); >+ return writereg(&state->demod, 0x0C, val & 0xfe); > >+ default: >+ return -EINVAL; > } >- > } > > /* Retrieve the demod settings */ >-static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_parameters *p) >+static int cx22702_get_tps(struct cx22702_state *state, >+ struct dvb_ofdm_parameters *p) > { > u8 val; > > /* Make sure the TPS regs are valid */ >- if (!(cx22702_readreg(state, 0x0A) & 0x20)) >+ if (!(readreg(&state->demod, 0x0A) & 0x20)) > return -EAGAIN; > >- val = cx22702_readreg (state, 0x01); >+ val = readreg(&state->demod, 0x01); > switch( (val&0x18)>>3) { > case 0: p->constellation = QPSK; break; > case 1: p->constellation = QAM_16; break; >@@ -162,8 +199,7 @@ static int cx22702_get_tps (struct cx227 > case 3: p->hierarchy_information = HIERARCHY_4; break; > } > >- >- val = cx22702_readreg (state, 0x02); >+ val = readreg(&state->demod, 0x02); > switch( (val&0x38)>>3 ) { > case 0: p->code_rate_HP = FEC_1_2; break; > case 1: p->code_rate_HP = FEC_2_3; break; >@@ -179,14 +215,13 @@ static int cx22702_get_tps (struct cx227 > case 4: p->code_rate_LP = FEC_7_8; break; > } > >- >- val = cx22702_readreg (state, 0x03); >+ val = readreg(&state->demod, 0x03); > switch( (val&0x0c)>>2 ) { > case 0: p->guard_interval = GUARD_INTERVAL_1_32; break; > case 1: p->guard_interval = GUARD_INTERVAL_1_16; break; > case 2: p->guard_interval = GUARD_INTERVAL_1_8; break; > case 3: p->guard_interval = GUARD_INTERVAL_1_4; break; >-} >+ } > switch( val&0x03 ) { > case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break; > case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break; >@@ -195,42 +230,36 @@ static int cx22702_get_tps (struct cx227 > return 0; > } > >- >- >- >- >- >- >- >- >- >- >- >- > /* Talk to the demod, set the FEC, GUARD, QAM settings etc */ >-static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) >+static int cx22702_set_tps(struct cx22702_state *state, >+ struct dvb_frontend_parameters *p) > { > u8 val; >- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; >+ u8 pllbuf[4]; >+ >+ dprintk("%s\n",__FUNCTION__); > > /* set PLL */ >- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe); >- state->config->pll_set(fe, p); >- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1); >+ dvb_pll_configure(state->config->pll_desc, pllbuf, >+ p->frequency, >+ p->u.ofdm.bandwidth); >+ PLL_ENABLE(state); >+ pll_write4(&state->pll,pllbuf); >+ PLL_DISABLE(state); > > /* set inversion */ >- cx22702_set_inversion (state, p->inversion); >+ cx22702_set_inversion(state, p->inversion); > > /* set bandwidth */ > switch(p->u.ofdm.bandwidth) { > case BANDWIDTH_6_MHZ: >- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x20 ); >+ writereg(&state->demod, 0x0C, (readreg(&state->demod, 0x0C) & 0xcf) | 0x20 ); > break; > case BANDWIDTH_7_MHZ: >- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x10 ); >+ writereg(&state->demod, 0x0C, (readreg(&state->demod, 0x0C) & 0xcf) | 0x10 ); > break; > case BANDWIDTH_8_MHZ: >- cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf ); >+ writereg(&state->demod, 0x0C, readreg(&state->demod, 0x0C) &0xcf ); > break; > default: > dprintk ("%s: invalid bandwidth\n",__FUNCTION__); >@@ -249,13 +278,13 @@ static int cx22702_set_tps (struct dvb_f > (p->u.ofdm.transmission_mode==TRANSMISSION_MODE_AUTO) ) { > > /* TPS Source - use hardware driven values */ >- cx22702_writereg(state, 0x06, 0x10); >- cx22702_writereg(state, 0x07, 0x9); >- cx22702_writereg(state, 0x08, 0xC1); >- cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc ); >- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 ); >- cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */ >- printk("%s: Autodetecting\n",__FUNCTION__); >+ writereg(&state->demod, 0x06, 0x10); >+ writereg(&state->demod, 0x07, 0x9); >+ writereg(&state->demod, 0x08, 0xC1); >+ writereg(&state->demod, 0x0B, readreg(&state->demod, 0x0B) & 0xfc ); >+ writereg(&state->demod, 0x0C, (readreg(&state->demod, 0x0C) & 0xBF) | 0x40 ); >+ writereg(&state->demod, 0x00, 0x01); /* Begin aquisition */ >+ dprintk("%s: Autodetecting\n",__FUNCTION__); > return 0; > } > >@@ -278,7 +307,7 @@ static int cx22702_set_tps (struct dvb_f > dprintk ("%s: invalid hierarchy\n",__FUNCTION__); > return -EINVAL; > } >- cx22702_writereg (state, 0x06, val); >+ writereg(&state->demod, 0x06, val); > > val=0; > switch(p->u.ofdm.code_rate_HP) { >@@ -303,7 +332,7 @@ static int cx22702_set_tps (struct dvb_f > dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__); > return -EINVAL; > } >- cx22702_writereg (state, 0x07, val); >+ writereg(&state->demod, 0x07, val); > > val=0; > switch(p->u.ofdm.guard_interval) { >@@ -322,211 +351,300 @@ static int cx22702_set_tps (struct dvb_f > dprintk ("%s: invalid transmission_mode\n",__FUNCTION__); > return -EINVAL; > } >- cx22702_writereg(state, 0x08, val); >- cx22702_writereg(state, 0x0B, (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02 ); >- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 ); >+ writereg(&state->demod, 0x08, val); >+ writereg(&state->demod, 0x0B, (readreg(&state->demod, 0x0B) & 0xfc) | 0x02 ); >+ writereg(&state->demod, 0x0C, (readreg(&state->demod, 0x0C) & 0xBF) | 0x40 ); > > /* Begin channel aquisition */ >- cx22702_writereg(state, 0x00, 0x01); >+ writereg(&state->demod, 0x00, 0x01); > > return 0; > } > >+/* ------------------------------------------------------------------ */ > >-/* Reset the demod hardware and reset all of the configuration registers >- to a default state. */ >-static int cx22702_init (struct dvb_frontend* fe) >+static int cx22702_init(struct dvb_frontend* fe) > { >- int i; >- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; >- >- cx22702_writereg (state, 0x00, 0x02); >- >- msleep(10); >- >- for (i=0; i<sizeof(init_tab); i+=2) >- cx22702_writereg (state, init_tab[i], init_tab[i+1]); >- >- >- /* init PLL */ >- if (state->config->pll_init) { >- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe); >- state->config->pll_init(fe); >- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1); >- } >+ struct cx22702_state *state = fe->demodulator_priv; > >+ cx22702_reset(state); > return 0; > } > > static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status) > { >- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; >- u8 reg0A; >- u8 reg23; >- >- *status = 0; >- >- reg0A = cx22702_readreg (state, 0x0A); >- reg23 = cx22702_readreg (state, 0x23); >- >- dprintk ("%s: status demod=0x%02x agc=0x%02x\n" >- ,__FUNCTION__,reg0A,reg23); >- >- if(reg0A & 0x10) { >- *status |= FE_HAS_LOCK; >- *status |= FE_HAS_VITERBI; >- *status |= FE_HAS_SYNC; >- } >- >- if(reg0A & 0x20) >- *status |= FE_HAS_CARRIER; >+ struct cx22702_state *state = fe->demodulator_priv; >+ u8 reg0A = readreg(&state->demod, 0x0A); >+ u8 reg23 = readreg(&state->demod, 0x23); > >- if(reg23 < 0xf0) >- *status |= FE_HAS_SIGNAL; >+ *status = 0; >+ if (reg0A & 0x10) >+ *status |= FE_HAS_LOCK| FE_HAS_VITERBI | FE_HAS_SYNC; >+ if (reg0A & 0x20) >+ *status |= FE_HAS_CARRIER; >+ if (reg23 < 0xf0) >+ *status |= FE_HAS_SIGNAL; > >+ dprintk ("%s: status demod=0x%02x agc=0x%02x status=0x%x\n", >+ __FUNCTION__,reg0A,reg23,*status); > return 0; >- } >+} > > static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber) >- { >- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; >- >- if(cx22702_readreg (state, 0xE4) & 0x02) { >- /* Realtime statistics */ >- *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7 >- | (cx22702_readreg (state, 0xDF)&0x7F); >- } else { >- /* Averagtine statistics */ >- *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7 >- | cx22702_readreg (state, 0xDF); >- } >+{ >+ struct cx22702_state *state = fe->demodulator_priv; > >+ *ber = (readreg(&state->demod, 0xDE) & 0x7F) << 7; >+ *ber |= readreg(&state->demod, 0xDF) & 0x7F; > return 0; >- } >- >-static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) >- { >- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; >+} > >- *signal_strength = cx22702_readreg (state, 0x23); >+static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* strength) >+{ >+ struct cx22702_state *state = fe->demodulator_priv; >+ u8 signal; > >+ signal = readreg(&state->demod, 0x23); >+ *strength = ((signal<<8) | signal); > return 0; > } > > static int cx22702_read_snr(struct dvb_frontend* fe, u16* snr) > { >- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; >- >- u16 rs_ber=0; >- if(cx22702_readreg (state, 0xE4) & 0x02) { >- /* Realtime statistics */ >- rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7 >- | (cx22702_readreg (state, 0xDF)& 0x7F); >- } else { >- /* Averagine statistics */ >- rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 8 >- | cx22702_readreg (state, 0xDF); >- } >- *snr = ~rs_ber; >+ u32 ber; > >+ /* We don't have an register for this */ >+ /* We'll take the inverse of the BER register */ >+ cx22702_read_ber(fe, &ber); >+ *snr = ~ber; > return 0; > } > > static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) > { >- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; >- >- u8 _ucblocks; >+ struct cx22702_state *state = fe->demodulator_priv; >+ u8 ucb; > > /* RS Uncorrectable Packet Count then reset */ >- _ucblocks = cx22702_readreg (state, 0xE3); >- if (state->prevUCBlocks < _ucblocks) *ucblocks = (_ucblocks - state->prevUCBlocks); >- else *ucblocks = state->prevUCBlocks - _ucblocks; >- state->prevUCBlocks = _ucblocks; >- >+ ucb = readreg(&state->demod, 0xE3); >+ if (state->prevUCBlocks <= ucb) >+ *ucblocks = (ucb - state->prevUCBlocks); >+ else >+ *ucblocks = 256 + ucb - state->prevUCBlocks; >+ state->prevUCBlocks = ucb; > return 0; > } > >-static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) >+static int cx22702_get_frontend(struct dvb_frontend* fe, >+ struct dvb_frontend_parameters* params) > { >- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; >+ struct cx22702_state *state = fe->demodulator_priv; >+ u8 reg0C = readreg(&state->demod, 0x0C); >+ params->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF; >+ return cx22702_get_tps(state, ¶ms->u.ofdm); >+} > >- u8 reg0C = cx22702_readreg (state, 0x0C); >+static int cx22702_set_frontend(struct dvb_frontend* fe, >+ struct dvb_frontend_parameters* params) >+{ >+ struct cx22702_state *state = fe->demodulator_priv; >+ int ret; > >- p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF; >- return cx22702_get_tps (state, &p->u.ofdm); >+ ret=cx22702_set_tps(state, params); >+ if (debug && ret < 0) >+ printk("%s: set_tps failed ret=%d\n",__FUNCTION__,ret); >+ return ret; > } > > static void cx22702_release(struct dvb_frontend* fe) > { >- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv; >- kfree(state); >- } >+ struct cx22702_state *state = fe->demodulator_priv; > >-static struct dvb_frontend_ops cx22702_ops; >+ i2c_detach_client(&state->demod); >+ i2c_detach_client(&state->pll); >+ kfree(state); >+} > >-struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, >- struct i2c_adapter* i2c) >+static int cx22702_sleep(struct dvb_frontend* fe) > { >- struct cx22702_state* state = NULL; >- >- /* allocate memory for the internal state */ >- state = (struct cx22702_state*) kmalloc(sizeof(struct cx22702_state), GFP_KERNEL); >- if (state == NULL) goto error; >- >- /* setup the state */ >- state->config = config; >- state->i2c = i2c; >- memcpy(&state->ops, &cx22702_ops, sizeof(struct dvb_frontend_ops)); >- state->prevUCBlocks = 0; >- >- /* check if the demod is there */ >- if (cx22702_readreg(state, 0x1f) != 0x3) goto error; >+ struct cx22702_state *state = fe->demodulator_priv; >+ u8 pllbuf[4]; > >- /* create dvb_frontend */ >- state->frontend.ops = &state->ops; >- state->frontend.demodulator_priv = state; >- return &state->frontend; >+ dprintk("%s\n",__FUNCTION__); > >-error: >- if (state) kfree(state); >- return NULL; >+ dvb_pll_configure(state->config->pll_desc, pllbuf, 0, 0); >+ PLL_ENABLE(state); >+ pll_write4(&state->pll,pllbuf); >+ PLL_DISABLE(state); >+ return 0; > } > >-static struct dvb_frontend_ops cx22702_ops = { >- >+static struct dvb_frontend_ops cx22702_fe_ops = { > .info = { >- .name = "Conexant CX22702 DVB-T", >+ .name = "cx22702 demod", > .type = FE_OFDM, > .frequency_min = 177000000, > .frequency_max = 858000000, > .frequency_stepsize = 166666, >- .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | >- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | >- FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | >- FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | >- FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER >+ .caps = >+ FE_CAN_FEC_1_2 | >+ FE_CAN_FEC_2_3 | >+ FE_CAN_FEC_3_4 | >+ FE_CAN_FEC_5_6 | >+ FE_CAN_FEC_7_8 | >+ FE_CAN_FEC_AUTO | >+ FE_CAN_QPSK | >+ FE_CAN_QAM_16 | >+ FE_CAN_QAM_64 | >+ FE_CAN_QAM_AUTO | >+ FE_CAN_HIERARCHY_AUTO | >+ FE_CAN_GUARD_INTERVAL_AUTO | >+ FE_CAN_TRANSMISSION_MODE_AUTO | >+ FE_CAN_RECOVER, > }, >+ .init = cx22702_init, >+ .sleep = cx22702_sleep, >+ .set_frontend = cx22702_set_frontend, >+ .get_frontend = cx22702_get_frontend, >+ .read_status = cx22702_read_status, >+ .read_ber = cx22702_read_ber, >+ .read_signal_strength = cx22702_read_signal_strength, >+ .read_snr = cx22702_read_snr, >+ .read_ucblocks = cx22702_read_ucblocks, >+ .release = cx22702_release, >+}; > >- .release = cx22702_release, >+/* ------------------------------------------------------------------ */ > >- .init = cx22702_init, >+/* Validate the demod, make sure we understand the hardware */ >+static int cx22702_validate_demod(struct i2c_client *c) >+{ >+ int type = readreg(c, 0x1f); > >- .set_frontend = cx22702_set_tps, >- .get_frontend = cx22702_get_frontend, >+ if (0x03 != type) { >+ printk ("%s i2c demod type 0x%02x not known\n", >+ __FUNCTION__, type); >+ return -ENODEV; >+ } >+ return 0; >+} > >- .read_status = cx22702_read_status, >- .read_ber = cx22702_read_ber, >- .read_signal_strength = cx22702_read_signal_strength, >- .read_snr = cx22702_read_snr, >- .read_ucblocks = cx22702_read_ucblocks, >+/* Validate the tuner PLL, make sure we understand the hardware */ >+static int cx22702_validate_pll(struct cx22702_state *state) >+{ >+ int result=0; >+ >+ PLL_ENABLE(state); >+ result = readreg(&state->pll,0xc2); >+ PLL_DISABLE(state); >+ return result; >+} >+ >+struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, >+ struct i2c_adapter* i2c) >+{ >+ struct cx22702_state *state; >+ int ret; >+ >+ state = kmalloc(sizeof(*state), GFP_KERNEL); >+ if (NULL == state) >+ return NULL; >+ memset(state, 0, sizeof(*state)); >+ >+ state->config = config; >+ state->ops = cx22702_fe_ops; >+ state->fe.demodulator_priv = state; >+ state->fe.ops = &state->ops; >+ >+ state->demod = demod_template; >+ state->demod.adapter = i2c; >+ state->demod.addr = config->demod_address; >+ state->pll = pll_template; >+ strlcpy(state->pll.name, config->pll_desc->name, sizeof(state->pll.name)); >+ state->pll.adapter = i2c; >+ state->pll.addr = config->pll_address; >+ i2c_set_clientdata(&state->demod, state); >+ i2c_set_clientdata(&state->pll, state); >+ >+ /* verify devices */ >+ ret=cx22702_validate_demod(&state->demod); >+ if (ret < 0) >+ goto fail_free; >+ ret=cx22702_validate_pll(state); >+ if(ret < 0) >+ goto fail_free; >+ >+ /* register i2c */ >+ ret = i2c_attach_client(&state->demod); >+ if (0 != ret) { >+ printk("cx22702: i2c demod register failed (%d)\n", ret); >+ goto fail_free; >+ } >+ ret = i2c_attach_client(&state->pll); >+ if (0 != ret) { >+ printk("cx22702: i2c pll register failed (%d)\n", ret); >+ goto fail_unreg1; >+ } >+ >+ /* all fine ;) */ >+ return &state->fe; >+ >+fail_unreg1: >+ i2c_detach_client(&state->demod); >+fail_free: >+ kfree(state); >+ return NULL; >+} >+EXPORT_SYMBOL(cx22702_attach); >+ >+/* ------------------------------------------------------------------ */ >+ >+static struct i2c_driver demod_driver = { >+ .owner = THIS_MODULE, >+ .name = __stringify(KBUILD_MODNAME) " demod", >+ .id = I2C_DRIVERID_DVBFE_CX22702, >+}; >+static struct i2c_client demod_template = { >+ .name = "cx22702", >+ .flags = I2C_CLIENT_ALLOW_USE, >+ .driver = &demod_driver, > }; > >-module_param(debug, int, 0644); >-MODULE_PARM_DESC(debug, "Enable verbose debug messages"); >+static struct i2c_driver pll_driver = { >+ .owner = THIS_MODULE, >+ .name = __stringify(KBUILD_MODNAME) " pll", >+ .id = I2C_DRIVERID_DVBFE_CX22702, >+}; >+static struct i2c_client pll_template = { >+ .name = "unset", >+ .flags = I2C_CLIENT_ALLOW_USE, >+ .driver = &pll_driver, >+}; > >-MODULE_DESCRIPTION("Conexant CX22702 DVB-T Demodulator driver"); >+static int __init init_cx22702 (void) >+{ >+ i2c_add_driver(&demod_driver); >+ i2c_add_driver(&pll_driver); >+ return 0; >+} >+ >+static void __exit exit_cx22702 (void) >+{ >+ i2c_del_driver(&pll_driver); >+ i2c_del_driver(&demod_driver); >+} >+ >+module_init (init_cx22702); >+module_exit (exit_cx22702); >+ >+MODULE_DESCRIPTION("CX22702 DVB Frontend driver"); > MODULE_AUTHOR("Steven Toth"); >+MODULE_AUTHOR("Gerd Knorr"); > MODULE_LICENSE("GPL"); > >-EXPORT_SYMBOL(cx22702_attach); >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * compile-command: "make DVB=1" >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/dvb/frontends/cx22702.h >=================================================================== >--- linux-2.6.11.orig/drivers/media/dvb/frontends/cx22702.h 2005-03-07 10:14:50.000000000 +0100 >+++ linux-2.6.11/drivers/media/dvb/frontends/cx22702.h 2005-03-08 10:33:27.000000000 +0100 >@@ -36,8 +36,14 @@ struct cx22702_config > u8 demod_address; > > /* PLL maintenance */ >+ u8 pll_address; >+ struct dvb_pll_desc *pll_desc; >+ >+#if 0 /* disabled for now, but maybe we'll need it again for plls >+ * which don't fit into the dvb_pll_desc model ... */ > int (*pll_init)(struct dvb_frontend* fe); > int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); >+#endif > }; > > extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, >Index: linux-2.6.11/drivers/media/dvb/frontends/dvb-pll.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/media/dvb/frontends/dvb-pll.c 2005-03-08 10:33:15.000000000 +0100 >@@ -0,0 +1,168 @@ >+/* >+ * $Id: dvb-pll.c,v 1.7 2005/02/10 11:52:02 kraxel Exp $ >+ * >+ * descriptions + helper functions for simple dvb plls. >+ * >+ * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 2 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ */ >+ >+#include <linux/module.h> >+#include <linux/dvb/frontend.h> >+#include <asm/types.h> >+ >+#include "dvb-pll.h" >+ >+/* ----------------------------------------------------------- */ >+/* descriptions */ >+ >+struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { >+ .name = "Thomson dtt7579", >+ .min = 177000000, >+ .max = 858000000, >+ .count = 5, >+ .entries = { >+ { 0, 36166667, 166666, 0xb4, 0x03 }, /* go sleep */ >+ { 443250000, 36166667, 166666, 0xb4, 0x02 }, >+ { 542000000, 36166667, 166666, 0xb4, 0x08 }, >+ { 771000000, 36166667, 166666, 0xbc, 0x08 }, >+ { 999999999, 36166667, 166666, 0xf4, 0x08 }, >+ }, >+}; >+EXPORT_SYMBOL(dvb_pll_thomson_dtt7579); >+ >+struct dvb_pll_desc dvb_pll_thomson_dtt7610 = { >+ .name = "Thomson dtt7610", >+ .min = 44000000, >+ .max = 958000000, >+ .count = 3, >+ .entries = { >+ { 157250000, 44000000, 62500, 0x8e, 0x39 }, >+ { 454000000, 44000000, 62500, 0x8e, 0x3a }, >+ { 999999999, 44000000, 62500, 0x8e, 0x3c }, >+ }, >+}; >+EXPORT_SYMBOL(dvb_pll_thomson_dtt7610); >+ >+static void thomson_dtt759x_bw(u8 *buf, int bandwidth) >+{ >+ if (BANDWIDTH_7_MHZ == bandwidth) >+ buf[3] |= 0x10; >+} >+ >+struct dvb_pll_desc dvb_pll_thomson_dtt759x = { >+ .name = "Thomson dtt759x", >+ .min = 177000000, >+ .max = 896000000, >+ .setbw = thomson_dtt759x_bw, >+ .count = 6, >+ .entries = { >+ { 0, 36166667, 166666, 0x84, 0x03 }, >+ { 264000000, 36166667, 166666, 0xb4, 0x02 }, >+ { 470000000, 36166667, 166666, 0xbc, 0x02 }, >+ { 735000000, 36166667, 166666, 0xbc, 0x08 }, >+ { 835000000, 36166667, 166666, 0xf4, 0x08 }, >+ { 999999999, 36166667, 166666, 0xfc, 0x08 }, >+ }, >+}; >+EXPORT_SYMBOL(dvb_pll_thomson_dtt759x); >+ >+struct dvb_pll_desc dvb_pll_lg_z201 = { >+ .name = "LG z201", >+ .min = 174000000, >+ .max = 862000000, >+ .count = 5, >+ .entries = { >+ { 0, 36166667, 166666, 0xbc, 0x03 }, >+ { 443250000, 36166667, 166666, 0xbc, 0x01 }, >+ { 542000000, 36166667, 166666, 0xbc, 0x02 }, >+ { 830000000, 36166667, 166666, 0xf4, 0x02 }, >+ { 999999999, 36166667, 166666, 0xfc, 0x02 }, >+ }, >+}; >+EXPORT_SYMBOL(dvb_pll_lg_z201); >+ >+struct dvb_pll_desc dvb_pll_unknown_1 = { >+ .name = "unknown 1", /* used by dntv live dvb-t */ >+ .min = 174000000, >+ .max = 862000000, >+ .count = 9, >+ .entries = { >+ { 150000000, 36166667, 166666, 0xb4, 0x01 }, >+ { 173000000, 36166667, 166666, 0xbc, 0x01 }, >+ { 250000000, 36166667, 166666, 0xb4, 0x02 }, >+ { 400000000, 36166667, 166666, 0xbc, 0x02 }, >+ { 420000000, 36166667, 166666, 0xf4, 0x02 }, >+ { 470000000, 36166667, 166666, 0xfc, 0x02 }, >+ { 600000000, 36166667, 166666, 0xbc, 0x08 }, >+ { 730000000, 36166667, 166666, 0xf4, 0x08 }, >+ { 999999999, 36166667, 166666, 0xfc, 0x08 }, >+ }, >+}; >+EXPORT_SYMBOL(dvb_pll_unknown_1); >+ >+/* ----------------------------------------------------------- */ >+/* code */ >+ >+static int debug = 0; >+module_param(debug, int, 0644); >+MODULE_PARM_DESC(debug, "enable verbose debug messages"); >+ >+int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, >+ u32 freq, int bandwidth) >+{ >+ u32 div; >+ int i; >+ >+ if (freq != 0 && (freq < desc->min || freq > desc->max)) >+ return -EINVAL; >+ >+ for (i = 0; i < desc->count; i++) { >+ if (freq > desc->entries[i].limit) >+ continue; >+ break; >+ } >+ if (debug) >+ printk("pll: %s: freq=%d bw=%d | i=%d/%d\n", >+ desc->name, freq, bandwidth, i, desc->count); >+ BUG_ON(i == desc->count); >+ >+ div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize; >+ buf[0] = div >> 8; >+ buf[1] = div & 0xff; >+ buf[2] = desc->entries[i].cb1; >+ buf[3] = desc->entries[i].cb2; >+ >+ if (desc->setbw) >+ desc->setbw(buf, bandwidth); >+ >+ if (debug) >+ printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", >+ desc->name, div, buf[0], buf[1], buf[2], buf[3]); >+ >+ return 0; >+} >+EXPORT_SYMBOL(dvb_pll_configure); >+ >+MODULE_DESCRIPTION("dvb pll library"); >+MODULE_AUTHOR("Gerd Knorr"); >+MODULE_LICENSE("GPL"); >+ >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/dvb/frontends/dvb-pll.h >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/media/dvb/frontends/dvb-pll.h 2005-03-08 10:33:15.000000000 +0100 >@@ -0,0 +1,34 @@ >+/* >+ * $Id: dvb-pll.h,v 1.2 2005/02/10 11:43:41 kraxel Exp $ >+ */ >+ >+struct dvb_pll_desc { >+ char *name; >+ u32 min; >+ u32 max; >+ void (*setbw)(u8 *buf, int bandwidth); >+ int count; >+ struct { >+ u32 limit; >+ u32 offset; >+ u32 stepsize; >+ u8 cb1; >+ u8 cb2; >+ } entries[]; >+}; >+ >+extern struct dvb_pll_desc dvb_pll_thomson_dtt7579; >+extern struct dvb_pll_desc dvb_pll_thomson_dtt759x; >+extern struct dvb_pll_desc dvb_pll_thomson_dtt7610; >+extern struct dvb_pll_desc dvb_pll_lg_z201; >+extern struct dvb_pll_desc dvb_pll_unknown_1; >+ >+int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, >+ u32 freq, int bandwidth); >+ >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * compile-command: "make DVB=1" >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/dvb/frontends/mt352.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/dvb/frontends/mt352.c 2005-03-07 10:12:32.000000000 +0100 >+++ linux-2.6.11/drivers/media/dvb/frontends/mt352.c 2005-03-08 10:33:27.000000000 +0100 >@@ -41,13 +41,12 @@ > #include "mt352.h" > > struct mt352_state { >- > struct i2c_adapter* i2c; >- > struct dvb_frontend_ops ops; > > /* configuration settings */ > const struct mt352_config* config; >+ int s0,s1,s3; > > struct dvb_frontend frontend; > }; >@@ -66,23 +65,23 @@ static int mt352_single_write(struct dvb > .buf = buf, .len = 2 }; > int err = i2c_transfer(state->i2c, &msg, 1); > if (err != 1) { >- dprintk("mt352_write() to reg %x failed (err = %d)!\n", reg, err); >+ printk("mt352_write() to reg %x failed (err = %d)!\n", reg, err); > return err; >-} >- return 0; >+ } >+ return 0; > } > > int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen) > { > int err,i; > for (i=0; i < ilen-1; i++) >- if ((err = mt352_single_write(fe,ibuf[0]+i,ibuf[i+1]))) >+ if ((err = mt352_single_write(fe,ibuf[0]+i,ibuf[i+1]))) > return err; > > return 0; > } > >-static u8 mt352_read_register(struct mt352_state* state, u8 reg) >+static int mt352_read_register(struct mt352_state* state, u8 reg) > { > int ret; > u8 b0 [] = { reg }; >@@ -96,41 +95,87 @@ static u8 mt352_read_register(struct mt3 > > ret = i2c_transfer(state->i2c, msg, 2); > >- if (ret != 2) >- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); >+ if (ret != 2) { >+ printk("%s: readreg error (reg=%d, ret==%i)\n", >+ __FUNCTION__, reg, ret); >+ return ret; >+ } > > return b1[0]; > } > >-u8 mt352_read(struct dvb_frontend *fe, u8 reg) >+int mt352_read(struct dvb_frontend *fe, u8 reg) > { > return mt352_read_register(fe->demodulator_priv,reg); > } > >+static int mt352_sleep(struct dvb_frontend* fe) >+{ >+ static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 }; > >+ mt352_write(fe, mt352_softdown, sizeof(mt352_softdown)); >+ return 0; >+} > >+static void mt352_calc_nominal_rate(struct mt352_state* state, >+ enum fe_bandwidth bandwidth, >+ unsigned char *buf) >+{ >+ u32 adc_clock = 20480; /* 20.340 MHz */ >+ u32 bw,value; > >+ switch (bandwidth) { >+ case BANDWIDTH_6_MHZ: >+ bw = 6; >+ break; >+ case BANDWIDTH_7_MHZ: >+ bw = 7; >+ break; >+ case BANDWIDTH_8_MHZ: >+ default: >+ bw = 8; >+ break; >+ } >+ if (state->config->adc_clock) >+ adc_clock = state->config->adc_clock; > >+ value = 64 * bw * (1<<16) / (7 * 8); >+ value = value * 1000 / adc_clock; >+ dprintk("%s: bw %d, adc_clock %d => 0x%x\n", >+ __FUNCTION__, bw, adc_clock, value); >+ buf[0] = msb(value); >+ buf[1] = lsb(value); >+} > >- >- >-static int mt352_sleep(struct dvb_frontend* fe) >+static void mt352_calc_input_freq(struct mt352_state* state, >+ unsigned char *buf) > { >- static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 }; >+ int adc_clock = 20480; /* 20.480000 MHz */ >+ int if2 = 36167; /* 36.166667 MHz */ >+ int ife,value; > >- mt352_write(fe, mt352_softdown, sizeof(mt352_softdown)); >+ if (state->config->adc_clock) >+ adc_clock = state->config->adc_clock; >+ if (state->config->if2) >+ if2 = state->config->if2; > >- return 0; >+ ife = (2*adc_clock - if2); >+ value = -16374 * ife / adc_clock; >+ dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n", >+ __FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff); >+ buf[0] = msb(value); >+ buf[1] = lsb(value); > } > > static int mt352_set_parameters(struct dvb_frontend* fe, > struct dvb_frontend_parameters *param) > { > struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; >- unsigned char buf[14]; >+ unsigned char buf[13]; >+ static unsigned char tuner_go[] = { 0x5d, 0x01 }; >+ static unsigned char fsm_go[] = { 0x5e, 0x01 }; > unsigned int tps = 0; > struct dvb_ofdm_parameters *op = ¶m->u.ofdm; >- int i; > > switch (op->code_rate_HP) { > case FEC_2_3: >@@ -241,39 +286,33 @@ static int mt352_set_parameters(struct d > buf[1] = msb(tps); /* TPS_GIVEN_(1|0) */ > buf[2] = lsb(tps); > >- buf[3] = 0x50; >- >- /** >- * these settings assume 20.48MHz f_ADC, for other tuners you might >- * need other values. See p. 33 in the MT352 Design Manual. >- */ >- if (op->bandwidth == BANDWIDTH_8_MHZ) { >- buf[4] = 0x72; /* TRL_NOMINAL_RATE_(1|0) */ >- buf[5] = 0x49; >- } else if (op->bandwidth == BANDWIDTH_7_MHZ) { >- buf[4] = 0x64; >- buf[5] = 0x00; >- } else { /* 6MHz */ >- buf[4] = 0x55; >- buf[5] = 0xb7; >- } >- >- buf[6] = 0x31; /* INPUT_FREQ_(1|0), 20.48MHz clock, 36.166667MHz IF */ >- buf[7] = 0x05; /* see MT352 Design Manual page 32 for details */ >+ buf[3] = 0x50; // old >+// buf[3] = 0xf4; // pinnacle > >+ mt352_calc_nominal_rate(state, op->bandwidth, buf+4); >+ mt352_calc_input_freq(state, buf+6); > state->config->pll_set(fe, param, buf+8); > >- buf[13] = 0x01; /* TUNER_GO!! */ >- >+#if 0 /* FIXME: should be catched elsewhere ... */ > /* Only send the tuning request if the tuner doesn't have the requested > * parameters already set. Enhances tuning time and prevents stream > * breakup when retuning the same transponder. */ > for (i = 1; i < 13; i++) >- if (buf[i] != mt352_read_register(state, i + 0x50)) { >- mt352_write(fe, buf, sizeof(buf)); >+ if (buf[i] != mt352_read_register(state, i + 0x50)) > break; >- } >+ if (13 == i) >+ /* no changes */ >+ return 0; >+#endif > >+ mt352_write(fe, buf, sizeof(buf)); >+ if (state->config->no_tuner) { >+ /* start decoding */ >+ mt352_write(fe, fsm_go, 2); >+ } else { >+ /* start tuning */ >+ mt352_write(fe, tuner_go, 2); >+ } > return 0; > } > >@@ -395,24 +434,39 @@ static int mt352_get_parameters(struct d > static int mt352_read_status(struct dvb_frontend* fe, fe_status_t* status) > { > struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; >- u8 r; >- >- *status = 0; >- r = mt352_read_register (state, STATUS_0); >- if (r & (1 << 4)) >- *status = FE_HAS_CARRIER; >- if (r & (1 << 1)) >- *status |= FE_HAS_VITERBI; >- if (r & (1 << 5)) >- *status |= FE_HAS_LOCK; >+#if 1 >+ int val; > >- r = mt352_read_register (state, STATUS_1); >- if (r & (1 << 1)) >- *status |= FE_HAS_SYNC; >+ if (0 != mt352_read_register(state, INTERRUPT_0)) { >+ val = mt352_read_register(state, STATUS_0); >+ if (-1 != val) >+ state->s0 = val; >+ val = mt352_read_register(state, STATUS_1); >+ if (-1 != val) >+ state->s1 = val; >+ val = mt352_read_register(state, STATUS_3); >+ if (-1 != val) >+ state->s3 = val; >+ } >+#else >+ state->s0 = mt352_read_register(state, STATUS_0); >+ state->s1 = mt352_read_register(state, STATUS_1); >+ state->s3 = mt352_read_register(state, STATUS_3); >+ if (-1 == state->s0 || -1 == state->s1 || -1 == state->s3) >+ return -EIO; >+#endif > >- r = mt352_read_register (state, STATUS_3); >- if (r & (1 << 6)) >- *status |= FE_HAS_SIGNAL; >+ *status = 0; >+ if (state->s0 & (1 << 4)) >+ *status |= FE_HAS_CARRIER; >+ if (state->s0 & (1 << 1)) >+ *status |= FE_HAS_VITERBI; >+ if (state->s0 & (1 << 5)) >+ *status |= FE_HAS_LOCK; >+ if (state->s1 & (1 << 1)) >+ *status |= FE_HAS_SYNC; >+ if (state->s3 & (1 << 6)) >+ *status |= FE_HAS_SIGNAL; > > if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != > (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) >@@ -470,7 +524,7 @@ static int mt352_get_tune_settings(struc > fe_tune_settings->max_drift = 0; > > return 0; >- } >+} > > static int mt352_init(struct dvb_frontend* fe) > { >@@ -478,22 +532,24 @@ static int mt352_init(struct dvb_fronten > > static u8 mt352_reset_attach [] = { RESET, 0xC0 }; > >+ dprintk("%s: hello\n",__FUNCTION__); >+ > if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 || > (mt352_read_register(state, CONFIG) & 0x20) == 0) { > >- /* Do a "hard" reset */ >+ /* Do a "hard" reset */ > mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach)); > return state->config->demod_init(fe); > } > > return 0; >- } >+} > > static void mt352_release(struct dvb_frontend* fe) > { > struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; >- kfree(state); >- } >+ kfree(state); >+} > > static struct dvb_frontend_ops mt352_ops; > >@@ -505,6 +561,7 @@ struct dvb_frontend* mt352_attach(const > /* allocate memory for the internal state */ > state = (struct mt352_state*) kmalloc(sizeof(struct mt352_state), GFP_KERNEL); > if (state == NULL) goto error; >+ memset(state,0,sizeof(*state)); > > /* setup the state */ > state->config = config; >@@ -568,3 +625,9 @@ MODULE_LICENSE("GPL"); > EXPORT_SYMBOL(mt352_attach); > EXPORT_SYMBOL(mt352_write); > EXPORT_SYMBOL(mt352_read); >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * compile-command: "make DVB=1" >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/dvb/frontends/mt352.h >=================================================================== >--- linux-2.6.11.orig/drivers/media/dvb/frontends/mt352.h 2005-03-07 10:16:32.000000000 +0100 >+++ linux-2.6.11/drivers/media/dvb/frontends/mt352.h 2005-03-08 10:33:27.000000000 +0100 >@@ -40,6 +40,13 @@ struct mt352_config > /* the demodulator's i2c address */ > u8 demod_address; > >+ /* frequencies in kHz */ >+ int adc_clock; // default: 20480 >+ int if2; // default: 36166 >+ >+ /* set if no pll is connected to the secondary i2c bus */ >+ int no_tuner; >+ > /* Initialise the demodulator and PLL. Cannot be NULL */ > int (*demod_init)(struct dvb_frontend* fe); > >@@ -54,6 +61,12 @@ extern struct dvb_frontend* mt352_attach > struct i2c_adapter* i2c); > > extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen); >-extern u8 mt352_read(struct dvb_frontend *fe, u8 reg); >+extern int mt352_read(struct dvb_frontend *fe, u8 reg); > > #endif // MT352_H >+ >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/dvb/frontends/or51132.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/media/dvb/frontends/or51132.c 2005-03-08 10:33:27.000000000 +0100 >@@ -0,0 +1,628 @@ >+/* >+ * Support for OR51132 (pcHDTV HD-3000) - VSB/QAM >+ * >+ * Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com> >+ * >+ * Based on code from Jack Kelliher (kelliher@xmission.com) >+ * Copyright (C) 2002 & pcHDTV, inc. >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 2 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ * >+*/ >+ >+/* >+ * This driver needs two external firmware files. Please copy >+ * "dvb-fe-or51132-vsb.fw" and "dvb-fe-or51132-qam.fw" to >+ * /usr/lib/hotplug/firmware/ or /lib/firmware/ >+ * (depending on configuration of firmware hotplug). >+ */ >+#define OR51132_VSB_FIRMWARE "dvb-fe-or51132-vsb.fw" >+#define OR51132_QAM_FIRMWARE "dvb-fe-or51132-qam.fw" >+ >+#include <linux/kernel.h> >+#include <linux/module.h> >+#include <linux/moduleparam.h> >+#include <linux/init.h> >+#include <linux/delay.h> >+#include <asm/byteorder.h> >+ >+#include "dvb_frontend.h" >+#include "dvb-pll.h" >+#include "or51132.h" >+ >+static int debug; >+#define dprintk(args...) \ >+ do { \ >+ if (debug) printk(KERN_DEBUG "or51132: " args); \ >+ } while (0) >+ >+ >+struct or51132_state >+{ >+ struct i2c_adapter* i2c; >+ struct dvb_frontend_ops ops; >+ >+ /* Configuration settings */ >+ const struct or51132_config* config; >+ >+ struct dvb_frontend frontend; >+ >+ /* Demodulator private data */ >+ fe_modulation_t current_modulation; >+ >+ /* Tuner private data */ >+ u32 current_frequency; >+}; >+ >+static int i2c_writebytes (struct or51132_state* state, u8 reg, u8 *buf, int len) >+{ >+ int err; >+ struct i2c_msg msg; >+ msg.addr = reg; >+ msg.flags = 0; >+ msg.len = len; >+ msg.buf = buf; >+ >+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { >+ printk(KERN_WARNING "or51132: i2c_writebytes error (addr %02x, err == %i)\n", reg, err); >+ return -EREMOTEIO; >+ } >+ >+ return 0; >+} >+ >+static u8 i2c_readbytes (struct or51132_state* state, u8 reg, u8* buf, int len) >+{ >+ int err; >+ struct i2c_msg msg; >+ msg.addr = reg; >+ msg.flags = I2C_M_RD; >+ msg.len = len; >+ msg.buf = buf; >+ >+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { >+ printk(KERN_WARNING "or51132: i2c_readbytes error (addr %02x, err == %i)\n", reg, err); >+ return -EREMOTEIO; >+ } >+ >+ return 0; >+} >+ >+static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) >+{ >+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; >+ static u8 run_buf[] = {0x7F,0x01}; >+ static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00}; >+ u8 rec_buf[14]; >+ u8 cmd_buf[14]; >+ u32 firmwareAsize, firmwareBsize; >+ int i,ret; >+ >+ dprintk("Firmware is %ld bytes\n",fw->size); >+ >+ /* Get size of firmware A and B */ >+ firmwareAsize = le32_to_cpu(*((u32*)fw->data)); >+ dprintk("FirmwareA is %i bytes\n",firmwareAsize); >+ firmwareBsize = le32_to_cpu(*((u32*)(fw->data+4))); >+ dprintk("FirmwareB is %i bytes\n",firmwareBsize); >+ >+ /* Upload firmware */ >+ if ((ret = i2c_writebytes(state,state->config->demod_address, >+ &fw->data[8],firmwareAsize))) { >+ printk(KERN_WARNING "or51132: load_firmware error 1\n"); >+ return ret; >+ } >+ msleep(1); /* 1ms */ >+ if ((ret = i2c_writebytes(state,state->config->demod_address, >+ &fw->data[8+firmwareAsize],firmwareBsize))) { >+ printk(KERN_WARNING "or51132: load_firmware error 2\n"); >+ return ret; >+ } >+ msleep(1); /* 1ms */ >+ >+ if ((ret = i2c_writebytes(state,state->config->demod_address, >+ run_buf,2))) { >+ printk(KERN_WARNING "or51132: load_firmware error 3\n"); >+ return ret; >+ } >+ >+ /* Wait at least 5 msec */ >+ msleep(20); /* 10ms */ >+ >+ if ((ret = i2c_writebytes(state,state->config->demod_address, >+ run_buf,2))) { >+ printk(KERN_WARNING "or51132: load_firmware error 4\n"); >+ return ret; >+ } >+ >+ /* 50ms for operation to begin */ >+ msleep(50); >+ >+ /* Read back ucode version to besure we loaded correctly and are really up and running */ >+ /* Get uCode version */ >+ cmd_buf[0] = 0x10; >+ cmd_buf[1] = 0x10; >+ cmd_buf[2] = 0x00; >+ cmd_buf[3] = 0x00; >+ msleep(20); /* 20ms */ >+ if ((ret = i2c_writebytes(state,state->config->demod_address, >+ cmd_buf,3))) { >+ printk(KERN_WARNING "or51132: load_firmware error a\n"); >+ return ret; >+ } >+ >+ cmd_buf[0] = 0x04; >+ cmd_buf[1] = 0x17; >+ cmd_buf[2] = 0x00; >+ cmd_buf[3] = 0x00; >+ msleep(20); /* 20ms */ >+ if ((ret = i2c_writebytes(state,state->config->demod_address, >+ cmd_buf,2))) { >+ printk(KERN_WARNING "or51132: load_firmware error b\n"); >+ return ret; >+ } >+ >+ cmd_buf[0] = 0x00; >+ cmd_buf[1] = 0x00; >+ cmd_buf[2] = 0x00; >+ cmd_buf[3] = 0x00; >+ msleep(20); /* 20ms */ >+ if ((ret = i2c_writebytes(state,state->config->demod_address, >+ cmd_buf,2))) { >+ printk(KERN_WARNING "or51132: load_firmware error c\n"); >+ return ret; >+ } >+ >+ for(i=0;i<4;i++) { >+ msleep(20); /* 20ms */ >+ get_ver_buf[4] = i+1; >+ if ((ret = i2c_readbytes(state,state->config->demod_address, >+ &rec_buf[i*2],2))) { >+ printk(KERN_WARNING >+ "or51132: load_firmware error d - %d\n",i); >+ return ret; >+ } >+ } >+ >+ printk(KERN_WARNING >+ "or51132: Version: %02X%02X%02X%02X-%02X%02X%02X%02X (%02X%01X-%01X-%02X%01X-%01X)\n", >+ rec_buf[1],rec_buf[0],rec_buf[3],rec_buf[2], >+ rec_buf[5],rec_buf[4],rec_buf[7],rec_buf[6], >+ rec_buf[3],rec_buf[2]>>4,rec_buf[2]&0x0f, >+ rec_buf[5],rec_buf[4]>>4,rec_buf[4]&0x0f); >+ >+ cmd_buf[0] = 0x10; >+ cmd_buf[1] = 0x00; >+ cmd_buf[2] = 0x00; >+ cmd_buf[3] = 0x00; >+ msleep(20); /* 20ms */ >+ if ((ret = i2c_writebytes(state,state->config->demod_address, >+ cmd_buf,3))) { >+ printk(KERN_WARNING "or51132: load_firmware error e\n"); >+ return ret; >+ } >+ return 0; >+}; >+ >+static int or51132_init(struct dvb_frontend* fe) >+{ >+ return 0; >+} >+ >+static int or51132_read_ber(struct dvb_frontend* fe, u32* ber) >+{ >+ *ber = 0; >+ return 0; >+} >+ >+static int or51132_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) >+{ >+ *ucblocks = 0; >+ return 0; >+} >+ >+static int or51132_sleep(struct dvb_frontend* fe) >+{ >+ return 0; >+} >+ >+static int or51132_setmode(struct dvb_frontend* fe) >+{ >+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; >+ unsigned char cmd_buf[4]; >+ >+ dprintk("setmode %d\n",(int)state->current_modulation); >+ /* set operation mode in Receiver 1 register; */ >+ cmd_buf[0] = 0x04; >+ cmd_buf[1] = 0x01; >+ switch (state->current_modulation) { >+ case QAM_256: >+ case QAM_64: >+ case QAM_AUTO: >+ /* Auto-deinterleave; MPEG ser, MPEG2tr, phase noise-high*/ >+ cmd_buf[2] = 0x5F; >+ break; >+ case VSB_8: >+ /* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high*/ >+ cmd_buf[2] = 0x50; >+ break; >+ default: >+ printk("setmode:Modulation set to unsupported value\n"); >+ }; >+ cmd_buf[3] = 0x00; >+ if (i2c_writebytes(state,state->config->demod_address, >+ cmd_buf,3)) { >+ printk(KERN_WARNING "or51132: set_mode error 1\n"); >+ return -1; >+ } >+ dprintk("or51132: set #1 to %02x\n", cmd_buf[2]); >+ >+ /* Set operation mode in Receiver 6 register */ >+ cmd_buf[0] = 0x1C; >+ switch (state->current_modulation) { >+ case QAM_AUTO: >+ /* REC MODE Normal Carrier Lock */ >+ cmd_buf[1] = 0x00; >+ /* Channel MODE Auto QAM64/256 */ >+ cmd_buf[2] = 0x4f; >+ break; >+ case QAM_256: >+ /* REC MODE Normal Carrier Lock */ >+ cmd_buf[1] = 0x00; >+ /* Channel MODE QAM256 */ >+ cmd_buf[2] = 0x45; >+ break; >+ case QAM_64: >+ /* REC MODE Normal Carrier Lock */ >+ cmd_buf[1] = 0x00; >+ /* Channel MODE QAM64 */ >+ cmd_buf[2] = 0x43; >+ break; >+ case VSB_8: >+ /* REC MODE inv IF spectrum, Normal */ >+ cmd_buf[1] = 0x03; >+ /* Channel MODE ATSC/VSB8 */ >+ cmd_buf[2] = 0x06; >+ break; >+ default: >+ printk("setmode: Modulation set to unsupported value\n"); >+ }; >+ cmd_buf[3] = 0x00; >+ msleep(20); /* 20ms */ >+ if (i2c_writebytes(state,state->config->demod_address, >+ cmd_buf,3)) { >+ printk(KERN_WARNING "or51132: set_mode error 2\n"); >+ return -1; >+ } >+ dprintk("or51132: set #6 to 0x%02x%02x\n", cmd_buf[1], cmd_buf[2]); >+ >+ return 0; >+} >+ >+static int or51132_set_parameters(struct dvb_frontend* fe, >+ struct dvb_frontend_parameters *param) >+{ >+ int ret; >+ u8 buf[4]; >+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; >+ const struct firmware *fw; >+ >+ /* Change only if we are actually changing the modulation */ >+ if (state->current_modulation != param->u.vsb.modulation) { >+ switch(param->u.vsb.modulation) { >+ case VSB_8: >+ dprintk("set_parameters VSB MODE\n"); >+ printk("or51132: Waiting for firmware upload(%s)...\n", >+ OR51132_VSB_FIRMWARE); >+ ret = request_firmware(&fw, OR51132_VSB_FIRMWARE, >+ &state->i2c->dev); >+ if (ret){ >+ printk(KERN_WARNING "or51132: No firmware up" >+ "loaded(timeout or file not found?)\n"); >+ return ret; >+ } >+ /* Set non-punctured clock for VSB */ >+ state->config->set_ts_params(fe, 0); >+ break; >+ case QAM_AUTO: >+ case QAM_64: >+ case QAM_256: >+ dprintk("set_parameters QAM MODE\n"); >+ printk("or51132: Waiting for firmware upload(%s)...\n", >+ OR51132_QAM_FIRMWARE); >+ ret = request_firmware(&fw, OR51132_QAM_FIRMWARE, >+ &state->i2c->dev); >+ if (ret){ >+ printk(KERN_WARNING "or51132: No firmware up" >+ "loaded(timeout or file not found?)\n"); >+ return ret; >+ } >+ /* Set punctured clock for QAM */ >+ state->config->set_ts_params(fe, 1); >+ break; >+ default: >+ printk("or51132:Modulation type(%d) UNSUPPORTED\n", >+ param->u.vsb.modulation); >+ return -1; >+ }; >+ ret = or51132_load_firmware(fe, fw); >+ release_firmware(fw); >+ if (ret) { >+ printk(KERN_WARNING "or51132: Writing firmware to " >+ "device failed!\n"); >+ return ret; >+ } >+ printk("or51132: Firmware upload complete.\n"); >+ >+ state->current_modulation = param->u.vsb.modulation; >+ or51132_setmode(fe); >+ } >+ >+ /* Change only if we are actually changing the channel */ >+ if (state->current_frequency != param->frequency) { >+ dvb_pll_configure(state->config->pll_desc, buf, >+ param->frequency, 0); >+ dprintk("set_parameters tuner bytes: 0x%02x 0x%02x " >+ "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]); >+ if (i2c_writebytes(state, state->config->pll_address ,buf, 4)) >+ printk(KERN_WARNING "or51132: set_parameters error " >+ "writing to tuner\n"); >+ >+ /* Set to current mode */ >+ or51132_setmode(fe); >+ >+ /* Update current frequency */ >+ state->current_frequency = param->frequency; >+ } >+ return 0; >+} >+ >+static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) >+{ >+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; >+ unsigned char rec_buf[2]; >+ unsigned char snd_buf[2]; >+ *status = 0; >+ >+ /* Receiver Status */ >+ snd_buf[0]=0x04; >+ snd_buf[1]=0x00; >+ msleep(30); /* 30ms */ >+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { >+ printk(KERN_WARNING "or51132: read_status write error\n"); >+ return -1; >+ } >+ msleep(30); /* 30ms */ >+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { >+ printk(KERN_WARNING "or51132: read_status read error\n"); >+ return -1; >+ } >+ dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]); >+ >+ if (rec_buf[1] & 0x01) { /* Receiver Lock */ >+ *status |= FE_HAS_SIGNAL; >+ *status |= FE_HAS_CARRIER; >+ *status |= FE_HAS_VITERBI; >+ *status |= FE_HAS_SYNC; >+ *status |= FE_HAS_LOCK; >+ } >+ return 0; >+} >+ >+/* log10-1 table at .5 increments from 1 to 100.5 */ >+unsigned int i100x20log10[] = { >+ 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480, >+ 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042, >+ 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380, >+ 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623, >+ 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813, >+ 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968, >+ 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100, >+ 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214, >+ 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316, >+ 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406, >+ 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488, >+ 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563, >+ 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632, >+ 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696, >+ 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755, >+ 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811, >+ 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863, >+ 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913, >+ 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960, >+ 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004, >+}; >+ >+unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000}; >+ >+unsigned int i20Log10(unsigned short val) >+{ >+ unsigned int rntval = 100; >+ unsigned int tmp = val; >+ unsigned int exp = 1; >+ >+ while(tmp > 100) {tmp /= 100; exp++;} >+ >+ val = (2 * val)/denom[exp]; >+ if (exp > 1) rntval = 2000*exp; >+ >+ rntval += i100x20log10[val]; >+ return rntval; >+} >+ >+static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) >+{ >+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; >+ unsigned char rec_buf[2]; >+ unsigned char snd_buf[2]; >+ u8 rcvr_stat; >+ u16 snr_equ; >+ int usK; >+ >+ snd_buf[0]=0x04; >+ snd_buf[1]=0x02; /* SNR after Equalizer */ >+ msleep(30); /* 30ms */ >+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { >+ printk(KERN_WARNING "or51132: read_status write error\n"); >+ return -1; >+ } >+ msleep(30); /* 30ms */ >+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { >+ printk(KERN_WARNING "or51132: read_status read error\n"); >+ return -1; >+ } >+ snr_equ = rec_buf[0] | (rec_buf[1] << 8); >+ dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); >+ >+ /* Receiver Status */ >+ snd_buf[0]=0x04; >+ snd_buf[1]=0x00; >+ msleep(30); /* 30ms */ >+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { >+ printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n"); >+ return -1; >+ } >+ msleep(30); /* 30ms */ >+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { >+ printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n"); >+ return -1; >+ } >+ dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]); >+ rcvr_stat = rec_buf[1]; >+ usK = (rcvr_stat & 0x10) ? 3 : 0; >+ >+ /* The value reported back from the frontend will be FFFF=100% 0000=0% */ >+ *strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000; >+ dprintk("read_signal_strength %i\n",*strength); >+ >+ return 0; >+} >+ >+static int or51132_read_snr(struct dvb_frontend* fe, u16* snr) >+{ >+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; >+ unsigned char rec_buf[2]; >+ unsigned char snd_buf[2]; >+ u16 snr_equ; >+ >+ snd_buf[0]=0x04; >+ snd_buf[1]=0x02; /* SNR after Equalizer */ >+ msleep(30); /* 30ms */ >+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) { >+ printk(KERN_WARNING "or51132: read_snr write error\n"); >+ return -1; >+ } >+ msleep(30); /* 30ms */ >+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { >+ printk(KERN_WARNING "or51132: read_snr dvr read error\n"); >+ return -1; >+ } >+ snr_equ = rec_buf[0] | (rec_buf[1] << 8); >+ dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ); >+ >+ *snr = 0xFFFF - snr_equ; >+ dprintk("read_snr %i\n",*snr); >+ >+ return 0; >+} >+ >+static int or51132_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings) >+{ >+ fe_tune_settings->min_delay_ms = 500; >+ fe_tune_settings->step_size = 0; >+ fe_tune_settings->max_drift = 0; >+ >+ return 0; >+} >+ >+static void or51132_release(struct dvb_frontend* fe) >+{ >+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv; >+ kfree(state); >+} >+ >+static struct dvb_frontend_ops or51132_ops; >+ >+struct dvb_frontend* or51132_attach(const struct or51132_config* config, >+ struct i2c_adapter* i2c) >+{ >+ struct or51132_state* state = NULL; >+ >+ /* Allocate memory for the internal state */ >+ state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL); >+ if (state == NULL) >+ goto error; >+ >+ /* Setup the state */ >+ state->config = config; >+ state->i2c = i2c; >+ memcpy(&state->ops, &or51132_ops, sizeof(struct dvb_frontend_ops)); >+ state->current_frequency = -1; >+ state->current_modulation = -1; >+ >+ /* Create dvb_frontend */ >+ state->frontend.ops = &state->ops; >+ state->frontend.demodulator_priv = state; >+ return &state->frontend; >+ >+error: >+ if (state) >+ kfree(state); >+ return NULL; >+} >+ >+static struct dvb_frontend_ops or51132_ops = { >+ >+ .info = { >+ .name = "Oren OR51132 VSB/QAM Frontend", >+ .type = FE_ATSC, >+ .frequency_min = 44000000, >+ .frequency_max = 958000000, >+ .frequency_stepsize = 166666, >+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | >+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | >+ FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO | >+ FE_CAN_8VSB >+ }, >+ >+ .release = or51132_release, >+ >+ .init = or51132_init, >+ .sleep = or51132_sleep, >+ >+ .set_frontend = or51132_set_parameters, >+ .get_tune_settings = or51132_get_tune_settings, >+ >+ .read_status = or51132_read_status, >+ .read_ber = or51132_read_ber, >+ .read_signal_strength = or51132_read_signal_strength, >+ .read_snr = or51132_read_snr, >+ .read_ucblocks = or51132_read_ucblocks, >+}; >+ >+module_param(debug, int, 0644); >+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); >+ >+MODULE_DESCRIPTION("OR51132 ATSC [pcHDTV HD-3000] (8VSB & ITU J83 AnnexB FEC QAM64/256) Demodulator Driver"); >+MODULE_AUTHOR("Kirk Lapray"); >+MODULE_LICENSE("GPL"); >+ >+EXPORT_SYMBOL(or51132_attach); >+ >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/dvb/frontends/or51132.h >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/media/dvb/frontends/or51132.h 2005-03-08 10:33:27.000000000 +0100 >@@ -0,0 +1,48 @@ >+/* >+ * Support for OR51132 (pcHDTV HD-3000) - VSB/QAM >+ * >+ * Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com> >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 2 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ * >+*/ >+ >+#ifndef OR51132_H >+#define OR51132_H >+ >+#include <linux/firmware.h> >+#include <linux/dvb/frontend.h> >+ >+struct or51132_config >+{ >+ /* The demodulator's i2c address */ >+ u8 demod_address; >+ u8 pll_address; >+ struct dvb_pll_desc *pll_desc; >+ >+ /* Need to set device param for start_dma */ >+ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); >+}; >+ >+extern struct dvb_frontend* or51132_attach(const struct or51132_config* config, >+ struct i2c_adapter* i2c); >+ >+#endif // OR51132_H >+ >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/radio/miropcm20-radio.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/radio/miropcm20-radio.c 2005-03-07 10:13:11.000000000 +0100 >+++ linux-2.6.11/drivers/media/radio/miropcm20-radio.c 2005-03-08 10:33:15.000000000 +0100 >@@ -75,9 +75,7 @@ static int pcm20_getflags(struct pcm20_d > > if ((i=aci_rw_cmd(ACI_READ_TUNERSTATION, -1, -1))<0) > return i; >-#ifdef DEBUG >- printk("check_sig: 0x%x\n", i); >-#endif >+ pr_debug("check_sig: 0x%x\n", i); > if (i & 0x80) { > /* no signal from tuner */ > *flags=0; >@@ -107,9 +105,7 @@ static int pcm20_getflags(struct pcm20_d > > if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0) > return i; >-#ifdef DEBUG >- printk("rds-signal: %d\n", buf); >-#endif >+ pr_debug("rds-signal: %d\n", buf); > if (buf > 15) { > printk("miropcm20-radio: RX strengths unexpected high...\n"); > buf=15; >@@ -172,9 +168,7 @@ static int pcm20_do_ioctl(struct inode * > unsigned long *freq = arg; > pcm20->freq = *freq; > i=pcm20_setfreq(pcm20, pcm20->freq); >-#ifdef DEBUG >- printk("First view (setfreq): 0x%x\n", i); >-#endif >+ pr_debug("First view (setfreq): 0x%x\n", i); > return i; > } > case VIDIOCGAUDIO: >Index: linux-2.6.11/drivers/media/radio/radio-zoltrix.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/radio/radio-zoltrix.c 2005-03-07 10:15:52.000000000 +0100 >+++ linux-2.6.11/drivers/media/radio/radio-zoltrix.c 2005-03-08 10:33:15.000000000 +0100 >@@ -29,7 +29,7 @@ > #include <linux/module.h> /* Modules */ > #include <linux/init.h> /* Initdata */ > #include <linux/ioport.h> /* check_region, request_region */ >-#include <linux/delay.h> /* udelay */ >+#include <linux/delay.h> /* udelay, msleep */ > #include <asm/io.h> /* outb, outb_p */ > #include <asm/uaccess.h> /* copy to/from user */ > #include <linux/videodev.h> /* kernel radio structs */ >@@ -51,15 +51,6 @@ struct zol_device { > struct semaphore lock; > }; > >- >-/* local things */ >- >-static void sleep_delay(void) >-{ >- /* Sleep nicely for +/- 10 mS */ >- schedule(); >-} >- > static int zol_setvol(struct zol_device *dev, int vol) > { > dev->curvol = vol; >@@ -76,7 +67,7 @@ static int zol_setvol(struct zol_device > } > > outb(dev->curvol-1, io); >- sleep_delay(); >+ msleep(10); > inb(io + 2); > up(&dev->lock); > return 0; >@@ -176,11 +167,10 @@ static int zol_getsigstr(struct zol_devi > down(&dev->lock); > outb(0x00, io); /* This stuff I found to do nothing */ > outb(dev->curvol, io); >- sleep_delay(); >- sleep_delay(); >+ msleep(20); > > a = inb(io); >- sleep_delay(); >+ msleep(10); > b = inb(io); > > up(&dev->lock); >@@ -202,11 +192,10 @@ static int zol_is_stereo (struct zol_dev > > outb(0x00, io); > outb(dev->curvol, io); >- sleep_delay(); >- sleep_delay(); >+ msleep(20); > > x1 = inb(io); >- sleep_delay(); >+ msleep(10); > x2 = inb(io); > > up(&dev->lock); >@@ -368,8 +357,7 @@ static int __init zoltrix_init(void) > > outb(0, io); > outb(0, io); >- sleep_delay(); >- sleep_delay(); >+ msleep(20); > inb(io + 3); > > zoltrix_unit.curvol = 0; >Index: linux-2.6.11/drivers/media/video/Kconfig >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/Kconfig 2005-03-07 10:15:21.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/Kconfig 2005-03-08 10:33:27.000000000 +0100 >@@ -249,7 +249,9 @@ config VIDEO_SAA7134 > > config VIDEO_SAA7134_DVB > tristate "DVB Support for saa7134 based TV cards" >- depends on VIDEO_SAA7134 && DVB_CORE && BROKEN >+ depends on VIDEO_SAA7134 && DVB_CORE >+ select VIDEO_BUF_DVB >+ select DVB_MT352 > ---help--- > This adds support for DVB cards based on the > Philips saa7134 chip. >@@ -305,11 +307,14 @@ config VIDEO_HEXIUM_GEMINI > > config VIDEO_CX88 > tristate "Conexant 2388x (bt878 successor) support" >- depends on VIDEO_DEV && PCI && EXPERIMENTAL >+ depends on VIDEO_DEV && PCI && I2C && EXPERIMENTAL > select I2C_ALGOBIT >+ select FW_LOADER > select VIDEO_BTCX > select VIDEO_BUF > select VIDEO_TUNER >+ select VIDEO_TVEEPROM >+ select VIDEO_IR > ---help--- > This is a video4linux driver for Conexant 2388x based > TV cards. >@@ -319,10 +324,13 @@ config VIDEO_CX88 > > config VIDEO_CX88_DVB > tristate "DVB Support for cx2388x based TV cards" >- depends on VIDEO_CX88 && DVB_CORE && BROKEN >+ depends on VIDEO_CX88 && DVB_CORE > select VIDEO_BUF_DVB >+ select DVB_MT352 >+ select DVB_CX22702 >+ select DVB_OR51132 > ---help--- >- This adds support for DVB cards based on the >+ This adds support for DVB/ATSC cards based on the > Connexant 2388x chip. > > config VIDEO_OVCAMCHIP >Index: linux-2.6.11/drivers/media/video/Makefile >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/Makefile 2005-03-07 10:13:33.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/Makefile 2005-03-07 18:13:01.000000000 +0100 >@@ -7,6 +7,7 @@ bttv-objs := bttv-driver.o bttv-cards.o > zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o > zr36067-objs := zoran_procfs.o zoran_device.o \ > zoran_driver.o zoran_card.o >+tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o > > obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o > >Index: linux-2.6.11/drivers/media/video/bt832.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/bt832.c 2005-03-07 10:14:50.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/bt832.c 2005-03-08 10:33:27.000000000 +0100 >@@ -6,7 +6,7 @@ > It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly > connected to bt848/bt878 GPIO pins on this purpose. > (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets) >- >+ > Supported Cards: > - Pixelview Rev.4E: 0x8a > GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 ! >@@ -31,8 +31,8 @@ > #include <linux/errno.h> > #include <linux/slab.h> > >-#include "id.h" >-#include "audiochip.h" >+#include <media/audiochip.h> >+#include <media/id.h> > #include "bttv.h" > #include "bt832.h" > >@@ -95,7 +95,7 @@ int bt832_init(struct i2c_client *i2c_cl > > buf=kmalloc(65,GFP_KERNEL); > bt832_hexdump(i2c_client_s,buf); >- >+ > if(buf[0x40] != 0x31) { > printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); > kfree(buf); >@@ -135,7 +135,7 @@ int bt832_init(struct i2c_client *i2c_cl > buf[1]= 0x27 & (~0x01); // Default | !skip > if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) > printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); >- >+ > bt832_hexdump(i2c_client_s,buf); > > #if 0 >@@ -168,8 +168,7 @@ int bt832_init(struct i2c_client *i2c_cl > > > >-static int bt832_attach(struct i2c_adapter *adap, int addr, >- unsigned short flags, int kind) >+static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) > { > struct bt832 *t; > >@@ -184,27 +183,32 @@ static int bt832_attach(struct i2c_adapt > return -ENOMEM; > memset(t,0,sizeof(*t)); > t->client = client_template; >- t->client.data = t; >+ i2c_set_clientdata(&t->client, t); > i2c_attach_client(&t->client); > > if(! bt832_init(&t->client)) { > bt832_detach(&t->client); > return -1; > } >- >+ > return 0; > } > > static int bt832_probe(struct i2c_adapter *adap) > { >+#ifdef I2C_CLASS_TV_ANALOG > if (adap->class & I2C_CLASS_TV_ANALOG) > return i2c_probe(adap, &addr_data, bt832_attach); >+#else >+ if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) >+ return i2c_probe(adap, &addr_data, bt832_attach); >+#endif > return 0; > } > > static int bt832_detach(struct i2c_client *client) > { >- struct bt832 *t = (struct bt832*)client->data; >+ struct bt832 *t = i2c_get_clientdata(client); > > printk("bt832: detach.\n"); > i2c_detach_client(client); >@@ -215,7 +219,7 @@ static int bt832_detach(struct i2c_clien > static int > bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) > { >- struct bt832 *t = (struct bt832*)client->data; >+ struct bt832 *t = i2c_get_clientdata(client); > > printk("bt832: command %x\n",cmd); > >@@ -249,19 +253,18 @@ static struct i2c_driver driver = { > }; > static struct i2c_client client_template = > { >- .name = "bt832", >- .flags = I2C_CLIENT_ALLOW_USE, >- .driver = &driver, >+ I2C_DEVNAME("bt832"), >+ .flags = I2C_CLIENT_ALLOW_USE, >+ .driver = &driver, > }; > > >-int bt832_init_module(void) >+static int __init bt832_init_module(void) > { >- i2c_add_driver(&driver); >- return 0; >+ return i2c_add_driver(&driver); > } > >-static void bt832_cleanup_module(void) >+static void __exit bt832_cleanup_module(void) > { > i2c_del_driver(&driver); > } >@@ -269,3 +272,10 @@ static void bt832_cleanup_module(void) > module_init(bt832_init_module); > module_exit(bt832_cleanup_module); > >+/* >+ * Overrides for Emacs so that we follow Linus's tabbing style. >+ * --------------------------------------------------------------------------- >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/video/bt832.h >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/bt832.h 2005-03-07 10:14:39.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/bt832.h 2005-03-08 10:33:27.000000000 +0100 >@@ -1,6 +1,6 @@ > /* Bt832 CMOS Camera Video Processor (VP) > >- The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS >+ The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS > color digital camera directly to video capture devices via an 8-bit, > 4:2:2 YUV or YCrCb video interface. > >@@ -85,7 +85,7 @@ > #define BT832_DEVICE_ID 63 > # define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31 > >-/* STMicroelectronivcs VV5404 camera module >+/* STMicroelectronivcs VV5404 camera module > i2c: 0x20: sensor address > i2c: 0xa0: eeprom for ccd defect map > */ >@@ -256,26 +256,26 @@ For the CCIR-601 standards, the sampling > //=========================================================================== > // Timing generator SRAM table values for CCIR601 720x480 NTSC > //=========================================================================== >-// For NTSC CCIR656 >+// For NTSC CCIR656 > BYTE BtCard::SRAMTable_NTSC[] = > { > // SRAM Timing Table for NTSC >- 0x0c, 0xc0, 0x00, >- 0x00, 0x90, 0xc2, >- 0x03, 0x10, 0x03, >- 0x06, 0x10, 0x34, >- 0x12, 0x12, 0x65, >- 0x02, 0x13, 0x24, >- 0x19, 0x00, 0x24, >- 0x39, 0x00, 0x96, >- 0x59, 0x08, 0x93, >+ 0x0c, 0xc0, 0x00, >+ 0x00, 0x90, 0xc2, >+ 0x03, 0x10, 0x03, >+ 0x06, 0x10, 0x34, >+ 0x12, 0x12, 0x65, >+ 0x02, 0x13, 0x24, >+ 0x19, 0x00, 0x24, >+ 0x39, 0x00, 0x96, >+ 0x59, 0x08, 0x93, > 0x83, 0x08, 0x97, >- 0x03, 0x50, 0x30, >- 0xc0, 0x40, 0x30, >- 0x86, 0x01, 0x01, >- 0xa6, 0x0d, 0x62, >- 0x03, 0x11, 0x61, >- 0x05, 0x37, 0x30, >+ 0x03, 0x50, 0x30, >+ 0xc0, 0x40, 0x30, >+ 0x86, 0x01, 0x01, >+ 0xa6, 0x0d, 0x62, >+ 0x03, 0x11, 0x61, >+ 0x05, 0x37, 0x30, > 0xac, 0x21, 0x50 > }; > >Index: linux-2.6.11/drivers/media/video/btcx-risc.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/btcx-risc.c 2005-03-07 10:12:26.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/btcx-risc.c 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- $Id: btcx-risc.c,v 1.5 2004/12/10 12:33:39 kraxel Exp $ >+ $Id: btcx-risc.c,v 1.6 2005/02/21 13:57:59 kraxel Exp $ > > btcx-risc.c > >@@ -52,12 +52,13 @@ void btcx_riscmem_free(struct pci_dev *p > { > if (NULL == risc->cpu) > return; >- pci_free_consistent(pci, risc->size, risc->cpu, risc->dma); >- memset(risc,0,sizeof(*risc)); > if (debug) { > memcnt--; >- printk("btcx: riscmem free [%d]\n",memcnt); >+ printk("btcx: riscmem free [%d] dma=%lx\n", >+ memcnt, (unsigned long)risc->dma); > } >+ pci_free_consistent(pci, risc->size, risc->cpu, risc->dma); >+ memset(risc,0,sizeof(*risc)); > } > > int btcx_riscmem_alloc(struct pci_dev *pci, >@@ -78,7 +79,8 @@ int btcx_riscmem_alloc(struct pci_dev *p > risc->size = size; > if (debug) { > memcnt++; >- printk("btcx: riscmem alloc size=%d [%d]\n",size,memcnt); >+ printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n", >+ memcnt, (unsigned long)dma, cpu, size); > } > } > memset(risc->cpu,0,risc->size); >Index: linux-2.6.11/drivers/media/video/bttv-cards.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/bttv-cards.c 2005-03-07 10:13:52.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/bttv-cards.c 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- $Id: bttv-cards.c,v 1.42 2005/01/13 17:22:33 kraxel Exp $ >+ $Id: bttv-cards.c,v 1.47 2005/02/22 14:06:32 kraxel Exp $ > > bttv-cards.c > >@@ -80,6 +80,9 @@ static void picolo_tetra_init(struct btt > static void tibetCS16_muxsel(struct bttv *btv, unsigned int input); > static void tibetCS16_init(struct bttv *btv); > >+static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input); >+static void kodicom4400r_init(struct bttv *btv); >+ > static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input); > static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input); > >@@ -101,6 +104,7 @@ static unsigned int pll[BTTV_MAX] = { > static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; > static unsigned int svhs[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; > static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; >+static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL }; > #ifdef MODULE > static unsigned int autoload = 1; > #else >@@ -170,6 +174,8 @@ static struct CARD { > // some cards ship with byteswapped IDs ... > { 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" }, > { 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" }, >+ // this seems to happen as well ... >+ { 0xff1211bd, BTTV_PINNACLE, "Pinnacle PCTV" }, > > { 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, > { 0x263710b4, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, >@@ -291,7 +297,7 @@ static struct CARD { > { 0x07611461, BTTV_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, > { 0x001c11bd, BTTV_PINNACLESAT, "Pinnacle PCTV Sat" }, > { 0x002611bd, BTTV_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, >- { 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB-T" }, >+ { 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB" }, > { 0xfc00270f, BTTV_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, > { 0x07711461, BTTV_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, > { 0xdb1018ac, BTTV_DVICO_DVBT_LITE, "DVICO FusionHDTV DVB-T Lite" }, >@@ -1920,6 +1926,7 @@ struct tvcard bttv_tvcards[] = { > .svhs = 2, > .muxsel = { 2, 3, 1, 0}, > .tuner_type = TUNER_PHILIPS_ATSC, >+ .has_dvb = 1, > },{ > .name = "Twinhan DST + clones", > .no_msp34xx = 1, >@@ -2188,6 +2195,63 @@ struct tvcard bttv_tvcards[] = { > .no_tda7432 = 1, > .tuner_type = -1, > .muxsel_hook = tibetCS16_muxsel, >+}, >+{ >+ /* Bill Brack <wbrack@mmm.com.hk> */ >+ /* >+ * Note that, because of the card's wiring, the "master" >+ * BT878A chip (i.e. the one which controls the analog switch >+ * and must use this card type) is the 2nd one detected. The >+ * other 3 chips should use card type 0x85, whose description >+ * follows this one. There is a EEPROM on the card (which is >+ * connected to the I2C of one of those other chips), but is >+ * not currently handled. There is also a facility for a >+ * "monitor", which is also not currently implemented. >+ */ >+ .name = "Kodicom 4400R (master)", >+ .video_inputs = 16, >+ .audio_inputs = 0, >+ .tuner = -1, >+ .tuner_type = -1, >+ .svhs = -1, >+ /* GPIO bits 0-9 used for analog switch: >+ * 00 - 03: camera selector >+ * 04 - 06: channel (controller) selector >+ * 07: data (1->on, 0->off) >+ * 08: strobe >+ * 09: reset >+ * bit 16 is input from sync separator for the channel >+ */ >+ .gpiomask = 0x0003ff, >+ .no_gpioirq = 1, >+ .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, >+ .pll = PLL_28, >+ .no_msp34xx = 1, >+ .no_tda7432 = 1, >+ .no_tda9875 = 1, >+ .muxsel_hook = kodicom4400r_muxsel, >+}, >+{ >+ /* Bill Brack <wbrack@mmm.com.hk> */ >+ /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the >+ * one which controls the analog switch, and must use the card type) >+ * is the 2nd one detected. The other 3 chips should use this card >+ * type >+ */ >+ .name = "Kodicom 4400R (slave)", >+ .video_inputs = 16, >+ .audio_inputs = 0, >+ .tuner = -1, >+ .tuner_type = -1, >+ .svhs = -1, >+ .gpiomask = 0x010000, >+ .no_gpioirq = 1, >+ .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, >+ .pll = PLL_28, >+ .no_msp34xx = 1, >+ .no_tda7432 = 1, >+ .no_tda9875 = 1, >+ .muxsel_hook = kodicom4400r_muxsel, > }}; > > static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); >@@ -2682,6 +2746,9 @@ void __devinit bttv_init_card2(struct bt > case BTTV_TIBET_CS16: > tibetCS16_init(btv); > break; >+ case BTTV_KODICOM_4400R: >+ kodicom4400r_init(btv); >+ break; > } > > /* pll configuration */ >@@ -3894,6 +3961,112 @@ static void tibetCS16_init(struct bttv * > gpio_write(0x0f7fff); > } > >+/* >+ * The following routines for the Kodicom-4400r get a little mind-twisting. >+ * There is a "master" controller and three "slave" controllers, together >+ * an analog switch which connects any of 16 cameras to any of the BT87A's. >+ * The analog switch is controlled by the "master", but the detection order >+ * of the four BT878A chips is in an order which I just don't understand. >+ * The "master" is actually the second controller to be detected. The >+ * logic on the board uses logical numbers for the 4 controlers, but >+ * those numbers are different from the detection sequence. When working >+ * with the analog switch, we need to "map" from the detection sequence >+ * over to the board's logical controller number. This mapping sequence >+ * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical >+ * unit 3, the second (which is the master) is logical unit 0, etc. >+ * We need to maintain the status of the analog switch (which of the 16 >+ * cameras is connected to which of the 4 controllers). Rather than >+ * add to the bttv structure for this, we use the data reserved for >+ * the mbox (unused for this card type). >+ */ >+ >+/* >+ * First a routine to set the analog switch, which controls which camera >+ * is routed to which controller. The switch comprises an X-address >+ * (gpio bits 0-3, representing the camera, ranging from 0-15), and a >+ * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3). >+ * A data value (gpio bit 7) of '1' enables the switch, and '0' disables >+ * the switch. A STROBE bit (gpio bit 8) latches the data value into the >+ * specified address. The idea is to set the address and data, then bring >+ * STROBE high, and finally bring STROBE back to low. >+ */ >+static void kodicom4400r_write(struct bttv *btv, >+ unsigned char xaddr, >+ unsigned char yaddr, >+ unsigned char data) { >+ unsigned int udata; >+ >+ udata = (data << 7) | ((yaddr&3) << 4) | (xaddr&0xf); >+ gpio_bits(0x1ff, udata); /* write ADDR and DAT */ >+ gpio_bits(0x1ff, udata | (1 << 8)); /* strobe high */ >+ gpio_bits(0x1ff, udata); /* strobe low */ >+} >+ >+/* >+ * Next the mux select. Both the "master" and "slave" 'cards' (controllers) >+ * use this routine. The routine finds the "master" for the card, maps >+ * the controller number from the detected position over to the logical >+ * number, writes the appropriate data to the analog switch, and housekeeps >+ * the local copy of the switch information. The parameter 'input' is the >+ * requested camera number (0 - 15). >+ */ >+static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) >+{ >+ char *sw_status; >+ int xaddr, yaddr; >+ struct bttv *mctlr; >+ static unsigned char map[4] = {3, 0, 2, 1}; >+ >+ mctlr = master[btv->c.nr]; >+ if (mctlr == NULL) { /* ignore if master not yet detected */ >+ return; >+ } >+ yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */ >+ yaddr = map[yaddr]; >+ sw_status = (char *)(&mctlr->mbox_we); >+ xaddr = input & 0xf; >+ /* Check if the controller/camera pair has changed, else ignore */ >+ if (sw_status[yaddr] != xaddr) >+ { >+ /* "open" the old switch, "close" the new one, save the new */ >+ kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0); >+ sw_status[yaddr] = xaddr; >+ kodicom4400r_write(mctlr, xaddr, yaddr, 1); >+ } >+} >+ >+/* >+ * During initialisation, we need to reset the analog switch. We >+ * also preset the switch to map the 4 connectors on the card to the >+ * *user's* (see above description of kodicom4400r_muxsel) channels >+ * 0 through 3 >+ */ >+static void kodicom4400r_init(struct bttv *btv) >+{ >+ char *sw_status = (char *)(&btv->mbox_we); >+ int ix; >+ >+ gpio_inout(0x0003ff, 0x0003ff); >+ gpio_write(1 << 9); /* reset MUX */ >+ gpio_write(0); >+ /* Preset camera 0 to the 4 controllers */ >+ for (ix=0; ix<4; ix++) { >+ sw_status[ix] = ix; >+ kodicom4400r_write(btv, ix, ix, 1); >+ } >+ /* >+ * Since this is the "master", we need to set up the >+ * other three controller chips' pointers to this structure >+ * for later use in the muxsel routine. >+ */ >+ if ((btv->c.nr<1) || (btv->c.nr>BTTV_MAX-3)) >+ return; >+ master[btv->c.nr-1] = btv; >+ master[btv->c.nr] = btv; >+ master[btv->c.nr+1] = btv; >+ master[btv->c.nr+2] = btv; >+} >+ > // The Grandtec X-Guard framegrabber card uses two Dual 4-channel > // video multiplexers to provide up to 16 video inputs. These > // multiplexers are controlled by the lower 8 GPIO pins of the >Index: linux-2.6.11/drivers/media/video/bttv-driver.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/bttv-driver.c 2005-03-07 10:14:53.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/bttv-driver.c 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- $Id: bttv-driver.c,v 1.34 2005/01/07 13:11:19 kraxel Exp $ >+ $Id: bttv-driver.c,v 1.37 2005/02/21 13:57:59 kraxel Exp $ > > bttv - Bt848 frame grabber driver > >@@ -3167,6 +3167,82 @@ static struct video_device radio_templat > }; > > /* ----------------------------------------------------------------------- */ >+/* some debug code */ >+ >+int bttv_risc_decode(u32 risc) >+{ >+ static char *instr[16] = { >+ [ BT848_RISC_WRITE >> 28 ] = "write", >+ [ BT848_RISC_SKIP >> 28 ] = "skip", >+ [ BT848_RISC_WRITEC >> 28 ] = "writec", >+ [ BT848_RISC_JUMP >> 28 ] = "jump", >+ [ BT848_RISC_SYNC >> 28 ] = "sync", >+ [ BT848_RISC_WRITE123 >> 28 ] = "write123", >+ [ BT848_RISC_SKIP123 >> 28 ] = "skip123", >+ [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23", >+ }; >+ static int incr[16] = { >+ [ BT848_RISC_WRITE >> 28 ] = 2, >+ [ BT848_RISC_JUMP >> 28 ] = 2, >+ [ BT848_RISC_SYNC >> 28 ] = 2, >+ [ BT848_RISC_WRITE123 >> 28 ] = 5, >+ [ BT848_RISC_SKIP123 >> 28 ] = 2, >+ [ BT848_RISC_WRITE1S23 >> 28 ] = 3, >+ }; >+ static char *bits[] = { >+ "be0", "be1", "be2", "be3/resync", >+ "set0", "set1", "set2", "set3", >+ "clr0", "clr1", "clr2", "clr3", >+ "irq", "res", "eol", "sol", >+ }; >+ int i; >+ >+ printk("0x%08x [ %s", risc, >+ instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); >+ for (i = ARRAY_SIZE(bits)-1; i >= 0; i--) >+ if (risc & (1 << (i + 12))) >+ printk(" %s",bits[i]); >+ printk(" count=%d ]\n", risc & 0xfff); >+ return incr[risc >> 28] ? incr[risc >> 28] : 1; >+} >+ >+void bttv_risc_disasm(struct bttv *btv, >+ struct btcx_riscmem *risc) >+{ >+ unsigned int i,j,n; >+ >+ printk("%s: risc disasm: %p [dma=0x%08lx]\n", >+ btv->c.name, risc->cpu, (unsigned long)risc->dma); >+ for (i = 0; i < (risc->size >> 2); i += n) { >+ printk("%s: 0x%lx: ", btv->c.name, >+ (unsigned long)(risc->dma + (i<<2))); >+ n = bttv_risc_decode(risc->cpu[i]); >+ for (j = 1; j < n; j++) >+ printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n", >+ btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)), >+ risc->cpu[i+j], j); >+ if (0 == risc->cpu[i]) >+ break; >+ } >+} >+ >+static void bttv_print_riscaddr(struct bttv *btv) >+{ >+ printk(" main: %08Lx\n", >+ (unsigned long long)btv->main.dma); >+ printk(" vbi : o=%08Lx e=%08Lx\n", >+ btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0, >+ btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0); >+ printk(" cap : o=%08Lx e=%08Lx\n", >+ btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, >+ btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); >+ printk(" scr : o=%08Lx e=%08Lx\n", >+ btv->screen ? (unsigned long long)btv->screen->top.dma : 0, >+ btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0); >+ bttv_risc_disasm(btv, &btv->main); >+} >+ >+/* ----------------------------------------------------------------------- */ > /* irq handler */ > > static char *irq_name[] = { >@@ -3204,21 +3280,6 @@ static void bttv_print_irqbits(u32 print > } > } > >-static void bttv_print_riscaddr(struct bttv *btv) >-{ >- printk(" main: %08Lx\n", >- (unsigned long long)btv->main.dma); >- printk(" vbi : o=%08Lx e=%08Lx\n", >- btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0, >- btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0); >- printk(" cap : o=%08Lx e=%08Lx\n", >- btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, >- btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); >- printk(" scr : o=%08Lx e=%08Lx\n", >- btv->screen ? (unsigned long long)btv->screen->top.dma : 0, >- btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0); >-} >- > static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc) > { > printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n", >@@ -3921,7 +3982,7 @@ static void __devexit bttv_remove(struct > return; > } > >-static int bttv_suspend(struct pci_dev *pci_dev, u32 state) >+static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) > { > struct bttv *btv = pci_get_drvdata(pci_dev); > struct bttv_buffer_set idle; >Index: linux-2.6.11/drivers/media/video/bttv-gpio.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/bttv-gpio.c 2005-03-07 10:14:52.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/bttv-gpio.c 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- $Id: bttv-gpio.c,v 1.6 2004/11/03 09:04:50 kraxel Exp $ >+ $Id: bttv-gpio.c,v 1.7 2005/02/16 12:14:10 kraxel Exp $ > > bttv-gpio.c -- gpio sub drivers > >@@ -94,6 +94,7 @@ int bttv_sub_del_devices(struct bttv_cor > > list_for_each_safe(item,save,&core->subs) { > sub = list_entry(item,struct bttv_sub_device,list); >+ list_del(&sub->list); > device_unregister(&sub->dev); > } > return 0; >@@ -113,20 +114,6 @@ void bttv_gpio_irq(struct bttv_core *cor > } > } > >-void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach) >-{ >- struct bttv_sub_driver *drv; >- struct bttv_sub_device *dev; >- struct list_head *item; >- >- list_for_each(item,&core->subs) { >- dev = list_entry(item,struct bttv_sub_device,list); >- drv = to_bttv_sub_drv(dev->dev.driver); >- if (drv && drv->i2c_info) >- drv->i2c_info(dev,client,attach); >- } >-} >- > /* ----------------------------------------------------------------------- */ > /* external: sub-driver register/unregister */ > >Index: linux-2.6.11/drivers/media/video/bttv-i2c.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/bttv-i2c.c 2005-03-07 10:12:39.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/bttv-i2c.c 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- $Id: bttv-i2c.c,v 1.17 2004/12/14 15:33:30 kraxel Exp $ >+ $Id: bttv-i2c.c,v 1.18 2005/02/16 12:14:10 kraxel Exp $ > > bttv-i2c.c -- all the i2c code is here > >@@ -39,7 +39,6 @@ static struct i2c_adapter bttv_i2c_adap_ > static struct i2c_client bttv_i2c_client_template; > > static int attach_inform(struct i2c_client *client); >-static int detach_inform(struct i2c_client *client); > > static int i2c_debug = 0; > static int i2c_hw = 0; >@@ -112,7 +111,6 @@ static struct i2c_adapter bttv_i2c_adap_ > I2C_DEVNAME("bt848"), > .id = I2C_HW_B_BT848, > .client_register = attach_inform, >- .client_unregister = detach_inform, > }; > > /* ----------------------------------------------------------------------- */ >@@ -290,7 +288,6 @@ static struct i2c_adapter bttv_i2c_adap_ > .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */, > .algo = &bttv_algo, > .client_register = attach_inform, >- .client_unregister = detach_inform, > }; > > /* ----------------------------------------------------------------------- */ >@@ -305,22 +302,12 @@ static int attach_inform(struct i2c_clie > if (btv->pinnacle_id != UNSET) > bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE, > &btv->pinnacle_id); >- bttv_i2c_info(&btv->c, client, 1); >- > if (bttv_debug) > printk("bttv%d: i2c attach [client=%s]\n", > btv->c.nr, i2c_clientname(client)); > return 0; > } > >-static int detach_inform(struct i2c_client *client) >-{ >- struct bttv *btv = i2c_get_adapdata(client->adapter); >- >- bttv_i2c_info(&btv->c, client, 0); >- return 0; >-} >- > void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) > { > if (0 != btv->i2c_rc) >Index: linux-2.6.11/drivers/media/video/bttv.h >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/bttv.h 2005-03-07 10:12:47.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/bttv.h 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: bttv.h,v 1.14 2005/01/07 13:11:19 kraxel Exp $ >+ * $Id: bttv.h,v 1.17 2005/02/22 14:06:32 kraxel Exp $ > * > * bttv - Bt848 frame grabber driver > * >@@ -134,6 +134,7 @@ > #define BTTV_APAC_VIEWCOMP 0x7f > #define BTTV_DVICO_DVBT_LITE 0x80 > #define BTTV_TIBET_CS16 0x83 >+#define BTTV_KODICOM_4400R 0x84 > > /* i2c address list */ > #define I2C_TSA5522 0xc2 >@@ -302,8 +303,6 @@ struct bttv_sub_driver { > struct device_driver drv; > char wanted[BUS_ID_SIZE]; > void (*gpio_irq)(struct bttv_sub_device *sub); >- void (*i2c_info)(struct bttv_sub_device *sub, >- struct i2c_client *client, int attach); > }; > #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) > >Index: linux-2.6.11/drivers/media/video/bttvp.h >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/bttvp.h 2005-03-07 10:16:20.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/bttvp.h 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- $Id: bttvp.h,v 1.15 2004/12/14 15:33:30 kraxel Exp $ >+ $Id: bttvp.h,v 1.17 2005/02/16 12:14:10 kraxel Exp $ > > bttv - Bt848 frame grabber driver > >@@ -209,7 +209,6 @@ extern struct bus_type bttv_sub_bus_type > int bttv_sub_add_device(struct bttv_core *core, char *name); > int bttv_sub_del_devices(struct bttv_core *core); > void bttv_gpio_irq(struct bttv_core *core); >-void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach); > > > /* ---------------------------------------------------------- */ >Index: linux-2.6.11/drivers/media/video/cx88/Makefile >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/Makefile 2005-03-07 10:13:03.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/Makefile 2005-03-08 10:33:15.000000000 +0100 >@@ -1,4 +1,5 @@ >-cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o >+cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \ >+ cx88-input.o > cx8800-objs := cx88-video.o cx88-vbi.o > cx8802-objs := cx88-mpeg.o > >Index: linux-2.6.11/drivers/media/video/cx88/cx88-blackbird.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-blackbird.c 2005-03-07 10:15:01.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-blackbird.c 2005-03-08 10:33:20.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: cx88-blackbird.c,v 1.17 2004/11/07 13:17:15 kraxel Exp $ >+ * $Id: cx88-blackbird.c,v 1.26 2005/03/07 15:58:05 kraxel Exp $ > * > * Support for a cx23416 mpeg encoder via cx2388x host port. > * "blackbird" reference design. >@@ -25,6 +25,7 @@ > */ > > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/init.h> > #include <linux/fs.h> > #include <linux/delay.h> >@@ -207,10 +208,6 @@ static int register_write(struct cx88_co > cx_read(P1_RADDR0); > > return wait_ready_gpio0_bit1(core,1); >-#if 0 >- udelay(1000); /* without this, things don't go right (subsequent memory_write()'s don't get through */ >- /* ? would this be safe here? set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); */ >-#endif > } > > >@@ -283,7 +280,7 @@ static int blackbird_api_cmd(struct cx88 > timeout = jiffies + msecs_to_jiffies(10); > for (;;) { > memory_read(dev->core, dev->mailbox, &flag); >- if (0 == (flag & 4)) >+ if (0 != (flag & 4)) > break; > if (time_after(jiffies,timeout)) { > dprintk(0, "ERROR: API Mailbox timeout\n"); >@@ -324,7 +321,7 @@ static int blackbird_find_mailbox(struct > signaturecnt = 0; > if (4 == signaturecnt) { > dprintk(1, "Mailbox signature found\n"); >- return i; >+ return i+1; > } > } > dprintk(0, "Mailbox signature values not found!\n"); >@@ -427,7 +424,8 @@ static void blackbird_codec_settings(str > blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0); > > /* assign frame size */ >- blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0, 480, 720); >+ blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0, >+ dev->height, dev->width); > > /* assign aspect ratio */ > blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2); >@@ -629,8 +627,8 @@ static int mpeg_do_ioctl(struct inode *i > > memset(f,0,sizeof(*f)); > f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; >- f->fmt.pix.width = 720; >- f->fmt.pix.height = 576; >+ f->fmt.pix.width = dev->width; >+ f->fmt.pix.height = dev->height; > f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; > f->fmt.pix.sizeimage = 1024 * 512 /* FIXME: BUFFER_SIZE */; > } >@@ -694,6 +692,10 @@ static int mpeg_open(struct inode *inode > file->private_data = fh; > fh->dev = dev; > >+ /* FIXME: locking against other video device */ >+ cx88_set_scale(dev->core, dev->width, dev->height, >+ V4L2_FIELD_INTERLACED); >+ > videobuf_queue_init(&fh->mpegq, &blackbird_qops, > dev->pci, &dev->slock, > V4L2_BUF_TYPE_VIDEO_CAPTURE, >@@ -715,6 +717,7 @@ static int mpeg_release(struct inode *in > if (fh->mpegq.reading) > videobuf_read_stop(&fh->mpegq); > >+ videobuf_mmap_free(&fh->mpegq); > file->private_data = NULL; > kfree(fh); > return 0; >@@ -821,6 +824,8 @@ static int __devinit blackbird_probe(str > memset(dev,0,sizeof(*dev)); > dev->pci = pci_dev; > dev->core = core; >+ dev->width = 720; >+ dev->height = 480; > > err = cx8802_init_common(dev); > if (0 != err) >@@ -852,6 +857,8 @@ static void __devexit blackbird_remove(s > > /* common */ > cx8802_fini_common(dev); >+ cx88_core_put(dev->core,dev->pci); >+ kfree(dev); > } > > static struct pci_device_id cx8802_pci_tbl[] = { >@@ -885,7 +892,7 @@ static int blackbird_init(void) > printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", > SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); > #endif >- return pci_module_init(&blackbird_pci_driver); >+ return pci_register_driver(&blackbird_pci_driver); > } > > static void blackbird_fini(void) >Index: linux-2.6.11/drivers/media/video/cx88/cx88-cards.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-cards.c 2005-03-07 10:14:56.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-cards.c 2005-03-08 10:33:15.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: cx88-cards.c,v 1.47 2004/11/03 09:04:50 kraxel Exp $ >+ * $Id: cx88-cards.c,v 1.66 2005/03/04 09:12:23 kraxel Exp $ > * > * device driver for Conexant 2388x based TV cards > * card-specific stuff. >@@ -26,14 +26,7 @@ > #include <linux/pci.h> > #include <linux/delay.h> > >-#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) >-# define WITH_DVB 1 >-#endif >- > #include "cx88.h" >-#ifdef WITH_DVB >-#include "cx22702.h" >-#endif > > /* ------------------------------------------------------------------ */ > /* board config info */ >@@ -59,6 +52,7 @@ struct cx88_board cx88_boards[] = { > [CX88_BOARD_HAUPPAUGE] = { > .name = "Hauppauge WinTV 34xxx models", > .tuner_type = UNSET, >+ .tda9887_conf = TDA9887_PRESENT, > .input = {{ > .type = CX88_VMUX_TELEVISION, > .vmux = 0, >@@ -91,7 +85,7 @@ struct cx88_board cx88_boards[] = { > }, > [CX88_BOARD_PIXELVIEW] = { > .name = "PixelView", >- .tuner_type = UNSET, >+ .tuner_type = 5, > .input = {{ > .type = CX88_VMUX_TELEVISION, > .vmux = 0, >@@ -126,7 +120,7 @@ struct cx88_board cx88_boards[] = { > .gpio0 = 0x03fe, > }}, > }, >- [CX88_BOARD_WINFAST2000XP] = { >+ [CX88_BOARD_WINFAST2000XP_EXPERT] = { > .name = "Leadtek Winfast 2000XP Expert", > .tuner_type = 44, > .tda9887_conf = TDA9887_PRESENT, >@@ -217,26 +211,55 @@ struct cx88_board cx88_boards[] = { > .input = {{ > .type = CX88_VMUX_TELEVISION, > .vmux = 0, >- }}, >+ .gpio0 = 0x0035e700, >+ .gpio1 = 0x00003004, >+ .gpio2 = 0x0035e700, >+ .gpio3 = 0x02000000, >+ },{ >+ >+ .type = CX88_VMUX_COMPOSITE1, >+ .vmux = 1, >+ .gpio0 = 0x0035c700, >+ .gpio1 = 0x00003004, >+ .gpio2 = 0x0035c700, >+ .gpio3 = 0x02000000, >+ },{ >+ .type = CX88_VMUX_SVIDEO, >+ .vmux = 2, >+ .gpio0 = 0x0035c700, >+ .gpio1 = 0x0035c700, >+ .gpio2 = 0x02000000, >+ .gpio3 = 0x02000000, >+ }}, > .radio = { >- .type = CX88_RADIO, >- }, >+ .type = CX88_RADIO, >+ .gpio0 = 0x0035d700, >+ .gpio1 = 0x00007004, >+ .gpio2 = 0x0035d700, >+ .gpio3 = 0x02000000, >+ }, > }, > [CX88_BOARD_LEADTEK_PVR2000] = { >+ // gpio values for PAL version from regspy by DScaler > .name = "Leadtek PVR 2000", > .tuner_type = 38, >+ .tda9887_conf = TDA9887_PRESENT, > .input = {{ > .type = CX88_VMUX_TELEVISION, > .vmux = 0, >+ .gpio0 = 0x0000bde6, > },{ > .type = CX88_VMUX_COMPOSITE1, > .vmux = 1, >+ .gpio0 = 0x0000bde6, > },{ > .type = CX88_VMUX_SVIDEO, > .vmux = 2, >+ .gpio0 = 0x0000bde6, > }}, > .radio = { > .type = CX88_RADIO, >+ .gpio0 = 0x0000bd62, > }, > .blackbird = 1, > }, >@@ -320,14 +343,15 @@ struct cx88_board cx88_boards[] = { > .name = "KWorld/VStream XPert DVB-T", > .tuner_type = TUNER_ABSENT, > .input = {{ >- .type = CX88_VMUX_DVB, >- .vmux = 0, >- },{ > .type = CX88_VMUX_COMPOSITE1, > .vmux = 1, >+ .gpio0 = 0x0700, >+ .gpio2 = 0x0101, > },{ > .type = CX88_VMUX_SVIDEO, > .vmux = 2, >+ .gpio0 = 0x0700, >+ .gpio2 = 0x0101, > }}, > .dvb = 1, > }, >@@ -452,6 +476,131 @@ struct cx88_board cx88_boards[] = { > }}, > .dvb = 1, > }, >+ [CX88_BOARD_DNTV_LIVE_DVB_T] = { >+ .name = "digitalnow DNTV Live! DVB-T", >+ .tuner_type = TUNER_ABSENT, >+ .input = {{ >+ .type = CX88_VMUX_COMPOSITE1, >+ .vmux = 1, >+ .gpio0 = 0x00000700, >+ .gpio2 = 0x00000101, >+ },{ >+ .type = CX88_VMUX_SVIDEO, >+ .vmux = 2, >+ .gpio0 = 0x00000700, >+ .gpio2 = 0x00000101, >+ }}, >+ .dvb = 1, >+ }, >+ [CX88_BOARD_PCHDTV_HD3000] = { >+ .name = "pcHDTV HD3000 HDTV", >+ .tuner_type = TUNER_THOMSON_DTT7610, >+ .input = {{ >+ .type = CX88_VMUX_TELEVISION, >+ .vmux = 0, >+ .gpio0 = 0x00008484, >+ .gpio1 = 0x00000000, >+ .gpio2 = 0x00000000, >+ .gpio3 = 0x00000000, >+ },{ >+ .type = CX88_VMUX_COMPOSITE1, >+ .vmux = 1, >+ .gpio0 = 0x00008400, >+ .gpio1 = 0x00000000, >+ .gpio2 = 0x00000000, >+ .gpio3 = 0x00000000, >+ },{ >+ .type = CX88_VMUX_SVIDEO, >+ .vmux = 2, >+ .gpio0 = 0x00008400, >+ .gpio1 = 0x00000000, >+ .gpio2 = 0x00000000, >+ .gpio3 = 0x00000000, >+ }}, >+ .radio = { >+ .type = CX88_RADIO, >+ .vmux = 2, >+ .gpio0 = 0x00008400, >+ .gpio1 = 0x00000000, >+ .gpio2 = 0x00000000, >+ .gpio3 = 0x00000000, >+ }, >+ .dvb = 1, >+ }, >+ [CX88_BOARD_HAUPPAUGE_ROSLYN] = { >+ // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu> >+ // GPIO values obtained from regspy, courtesy Sean Covel >+ .name = "Hauppauge WinTV 28xxx (Roslyn) models", >+ .tuner_type = UNSET, >+ .input = {{ >+ .type = CX88_VMUX_TELEVISION, >+ .vmux = 0, >+ .gpio0 = 0xed12, // internal decoder >+ .gpio2 = 0x00ff, >+ },{ >+ .type = CX88_VMUX_DEBUG, >+ .vmux = 0, >+ .gpio0 = 0xff01, // mono from tuner chip >+ },{ >+ .type = CX88_VMUX_COMPOSITE1, >+ .vmux = 1, >+ .gpio0 = 0xff02, >+ },{ >+ .type = CX88_VMUX_SVIDEO, >+ .vmux = 2, >+ .gpio0 = 0xed92, >+ .gpio2 = 0x00ff, >+ }}, >+ .radio = { >+ .type = CX88_RADIO, >+ .gpio0 = 0xed96, >+ .gpio2 = 0x00ff, >+ }, >+ .blackbird = 1, >+ }, >+ [CX88_BOARD_DIGITALLOGIC_MEC] = { >+ /* params copied over from Leadtek PVR 2000 */ >+ .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)", >+ /* not sure yet about the tuner type */ >+ .tuner_type = 38, >+ .tda9887_conf = TDA9887_PRESENT, >+ .input = {{ >+ .type = CX88_VMUX_TELEVISION, >+ .vmux = 0, >+ .gpio0 = 0x0000bde6, >+ },{ >+ .type = CX88_VMUX_COMPOSITE1, >+ .vmux = 1, >+ .gpio0 = 0x0000bde6, >+ },{ >+ .type = CX88_VMUX_SVIDEO, >+ .vmux = 2, >+ .gpio0 = 0x0000bde6, >+ }}, >+ .radio = { >+ .type = CX88_RADIO, >+ .gpio0 = 0x0000bd62, >+ }, >+ .blackbird = 1, >+ }, >+ [CX88_BOARD_IODATA_GVBCTV7E] = { >+ .name = "IODATA GV/BCTV7E", >+ .tuner_type = TUNER_PHILIPS_FQ1286, >+ .tda9887_conf = TDA9887_PRESENT, >+ .input = {{ >+ .type = CX88_VMUX_TELEVISION, >+ .vmux = 1, >+ .gpio1 = 0x0000e03f, >+ },{ >+ .type = CX88_VMUX_COMPOSITE1, >+ .vmux = 2, >+ .gpio1 = 0x0000e07f, >+ },{ >+ .type = CX88_VMUX_SVIDEO, >+ .vmux = 3, >+ .gpio1 = 0x0000e07f, >+ }} >+ }, > }; > const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); > >@@ -482,11 +631,11 @@ struct cx88_subid cx88_subids[] = { > },{ > .subvendor = 0x107d, > .subdevice = 0x6611, >- .card = CX88_BOARD_WINFAST2000XP, >+ .card = CX88_BOARD_WINFAST2000XP_EXPERT, > },{ > .subvendor = 0x107d, > .subdevice = 0x6613, /* NTSC */ >- .card = CX88_BOARD_WINFAST2000XP, >+ .card = CX88_BOARD_WINFAST2000XP_EXPERT, > },{ > .subvendor = 0x107d, > .subdevice = 0x6620, >@@ -543,6 +692,30 @@ struct cx88_subid cx88_subids[] = { > .subvendor = 0x18AC, > .subdevice = 0xDB10, > .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, >+ },{ >+ .subvendor = 0x1554, >+ .subdevice = 0x4811, >+ .card = CX88_BOARD_PIXELVIEW, >+ },{ >+ .subvendor = 0x7063, >+ .subdevice = 0x3000, /* HD-3000 card */ >+ .card = CX88_BOARD_PCHDTV_HD3000, >+ },{ >+ .subvendor = 0x17DE, >+ .subdevice = 0xA8A6, >+ .card = CX88_BOARD_DNTV_LIVE_DVB_T, >+ },{ >+ .subvendor = 0x0070, >+ .subdevice = 0x2801, >+ .card = CX88_BOARD_HAUPPAUGE_ROSLYN, >+ },{ >+ .subvendor = 0x14F1, >+ .subdevice = 0x0342, >+ .card = CX88_BOARD_DIGITALLOGIC_MEC, >+ },{ >+ .subvendor = 0x10fc, >+ .subdevice = 0xd035, >+ .card = CX88_BOARD_IODATA_GVBCTV7E, > } > }; > const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); >@@ -552,7 +725,7 @@ const unsigned int cx88_idcount = ARRAY_ > > static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) > { >- /* This is just for the Winfast 2000 XP board ATM; I don't have data on >+ /* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on > * any others. > * > * Byte 0 is 1 on the NTSC board. >@@ -569,108 +742,27 @@ static void __devinit leadtek_eeprom(str > core->has_radio = 1; > core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38; > >- printk(KERN_INFO "%s: Leadtek Winfast 2000 XP config: " >+ printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: " > "tuner=%d, eeprom[0]=0x%02x\n", > core->name, core->tuner_type, eeprom_data[0]); > } > > > /* ----------------------------------------------------------------------- */ >-/* some hauppauge specific stuff */ >- >-static struct { >- int id; >- char *name; >-} hauppauge_tuner[] __devinitdata = { >- { TUNER_ABSENT, "" }, >- { TUNER_ABSENT, "External" }, >- { TUNER_ABSENT, "Unspecified" }, >- { TUNER_PHILIPS_PAL, "Philips FI1216" }, >- { TUNER_PHILIPS_SECAM, "Philips FI1216MF" }, >- { TUNER_PHILIPS_NTSC, "Philips FI1236" }, >- { TUNER_PHILIPS_PAL_I, "Philips FI1246" }, >- { TUNER_PHILIPS_PAL_DK,"Philips FI1256" }, >- { TUNER_PHILIPS_PAL, "Philips FI1216 MK2" }, >- { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" }, >- { TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" }, >- { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" }, >- { TUNER_PHILIPS_PAL_DK,"Philips FI1256 MK2" }, >- { TUNER_TEMIC_NTSC, "Temic 4032FY5" }, >- { TUNER_TEMIC_PAL, "Temic 4002FH5" }, >- { TUNER_TEMIC_PAL_I, "Temic 4062FY5" }, >- { TUNER_PHILIPS_PAL, "Philips FR1216 MK2" }, >- { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" }, >- { TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" }, >- { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" }, >- { TUNER_PHILIPS_PAL_DK,"Philips FR1256 MK2" }, >- { TUNER_PHILIPS_PAL, "Philips FM1216" }, >- { TUNER_PHILIPS_SECAM, "Philips FM1216MF" }, >- { TUNER_PHILIPS_NTSC, "Philips FM1236" }, >- { TUNER_PHILIPS_PAL_I, "Philips FM1246" }, >- { TUNER_PHILIPS_PAL_DK,"Philips FM1256" }, >- { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" }, >- { TUNER_ABSENT, "Samsung TCPN9082D" }, >- { TUNER_ABSENT, "Samsung TCPM9092P" }, >- { TUNER_TEMIC_4006FH5_PAL, "Temic 4006FH5" }, >- { TUNER_ABSENT, "Samsung TCPN9085D" }, >- { TUNER_ABSENT, "Samsung TCPB9085P" }, >- { TUNER_ABSENT, "Samsung TCPL9091P" }, >- { TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" }, >- { TUNER_PHILIPS_FQ1216ME, "Philips FQ1216 ME" }, >- { TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" }, >- { TUNER_PHILIPS_NTSC, "Philips TD1536" }, >- { TUNER_PHILIPS_NTSC, "Philips TD1536D" }, >- { TUNER_PHILIPS_NTSC, "Philips FMR1236" }, /* mono radio */ >- { TUNER_ABSENT, "Philips FI1256MP" }, >- { TUNER_ABSENT, "Samsung TCPQ9091P" }, >- { TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" }, >- { TUNER_TEMIC_4009FR5_PAL, "Temic 4009FR5" }, >- { TUNER_TEMIC_4046FM5, "Temic 4046FM5" }, >- { TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" }, >- { TUNER_ABSENT, "Philips TD1536D_FH_44"}, >- { TUNER_LG_NTSC_FM, "LG TPI8NSR01F"}, >- { TUNER_LG_PAL_FM, "LG TPI8PSB01D"}, >- { TUNER_LG_PAL, "LG TPI8PSB11D"}, >- { TUNER_LG_PAL_I_FM, "LG TAPC-I001D"}, >- { TUNER_LG_PAL_I, "LG TAPC-I701D"} >-}; > > static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) > { >- unsigned int blk2,tuner,radio,model; >- >- if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0) { >- printk(KERN_WARNING "%s: Hauppauge eeprom: invalid\n", >- core->name); >- return; >- } >- >- /* Block 2 starts after len+3 bytes header */ >- blk2 = eeprom_data[1] + 3; >- >- /* decode + use some config infos */ >- model = eeprom_data[12] << 8 | eeprom_data[11]; >- tuner = eeprom_data[9]; >- radio = eeprom_data[blk2-1] & 0x01; >- >- if (tuner < ARRAY_SIZE(hauppauge_tuner)) >- core->tuner_type = hauppauge_tuner[tuner].id; >- if (radio) >- core->has_radio = 1; >+ struct tveeprom tv; > >- printk(KERN_INFO "%s: hauppauge eeprom: model=%d, " >- "tuner=%s (%d), radio=%s\n", >- core->name, model, (tuner < ARRAY_SIZE(hauppauge_tuner) >- ? hauppauge_tuner[tuner].name : "?"), >- core->tuner_type, radio ? "yes" : "no"); >+ tveeprom_hauppauge_analog(&tv, eeprom_data); >+ core->tuner_type = tv.tuner_type; >+ core->has_radio = tv.has_radio; > } > >-#ifdef WITH_DVB > static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee) > { > int model; > int tuner; >- char *tname; > > /* Make sure we support the board model */ > model = ee[0x1f] << 24 | ee[0x1e] << 16 | ee[0x1d] << 8 | ee[0x1c]; >@@ -689,26 +781,18 @@ static int hauppauge_eeprom_dvb(struct c > /* Make sure we support the tuner */ > tuner = ee[0x2d]; > switch(tuner) { >- case 0x4B: >- tname = "Thomson DTT 7595"; >- core->pll_type = PLLTYPE_DTT7595; >- break; >- case 0x4C: >- tname = "Thomson DTT 7592"; >- core->pll_type = PLLTYPE_DTT7592; >+ case 0x4B: /* dtt 7595 */ >+ case 0x4C: /* dtt 7592 */ > break; > default: > printk("%s: error: unknown hauppauge tuner 0x%02x\n", > core->name, tuner); > return -ENODEV; > } >- printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%s (%d)\n", >- core->name, model, tname, tuner); >- >- core->pll_addr = 0x61; >- core->demod_addr = 0x43; >+ printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%d\n", >+ core->name, model, tuner); >+ return 0; > } >-#endif > > /* ----------------------------------------------------------------------- */ > /* some GDI (was: Modular Technology) specific stuff */ >@@ -763,36 +847,6 @@ static void gdi_eeprom(struct cx88_core > > /* ----------------------------------------------------------------------- */ > >-static int >-i2c_eeprom(struct i2c_client *c, unsigned char *eedata, int len) >-{ >- unsigned char buf; >- int err; >- >- c->addr = 0xa0 >> 1; >- buf = 0; >- if (1 != (err = i2c_master_send(c,&buf,1))) { >- printk(KERN_INFO "cx88: Huh, no eeprom present (err=%d)?\n", >- err); >- return -1; >- } >- if (len != (err = i2c_master_recv(c,eedata,len))) { >- printk(KERN_WARNING "cx88: i2c eeprom read error (err=%d)\n", >- err); >- return -1; >- } >-#if 0 >- for (i = 0; i < len; i++) { >- if (0 == (i % 16)) >- printk(KERN_INFO "cx88 ee: %02x:",i); >- printk(" %02x",eedata[i]); >- if (15 == (i % 16)) >- printk("\n"); >- } >-#endif >- return 0; >-} >- > void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) > { > int i; >@@ -823,41 +877,46 @@ void cx88_card_setup(struct cx88_core *c > { > static u8 eeprom[128]; > >+ if (0 == core->i2c_rc) { >+ core->i2c_client.addr = 0xa0 >> 1; >+ tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom)); >+ } >+ > switch (core->board) { > case CX88_BOARD_HAUPPAUGE: >+ case CX88_BOARD_HAUPPAUGE_ROSLYN: > if (0 == core->i2c_rc) >- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom)); >- hauppauge_eeprom(core,eeprom+8); >+ hauppauge_eeprom(core,eeprom+8); > break; > case CX88_BOARD_GDI: > if (0 == core->i2c_rc) >- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom)); >- gdi_eeprom(core,eeprom); >+ gdi_eeprom(core,eeprom); > break; >- case CX88_BOARD_WINFAST2000XP: >+ case CX88_BOARD_WINFAST2000XP_EXPERT: > if (0 == core->i2c_rc) >- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom)); >- leadtek_eeprom(core,eeprom); >+ leadtek_eeprom(core,eeprom); >+ break; >+ case CX88_BOARD_HAUPPAUGE_DVB_T1: >+ if (0 == core->i2c_rc) >+ hauppauge_eeprom_dvb(core,eeprom); > break; > case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: >- /* Tuner reset is hooked to the tuner out of reset */ >+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: >+ /* GPIO0:0 is hooked to mt352 reset pin */ > cx_set(MO_GP0_IO, 0x00000101); > cx_clear(MO_GP0_IO, 0x00000001); > msleep(1); > cx_set(MO_GP0_IO, 0x00000101); > break; >-#ifdef WITH_DVB >- case CX88_BOARD_HAUPPAUGE_DVB_T1: >- if (0 == core->i2c_rc) >- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom)); >- hauppauge_eeprom_dvb(core,eeprom); >- break; >- case CX88_BOARD_CONEXANT_DVB_T1: >- core->pll_type = PLLTYPE_DTT7579; >- core->pll_addr = 0x60; >- core->demod_addr = 0x43; >+ case CX88_BOARD_KWORLD_DVB_T: >+ case CX88_BOARD_DNTV_LIVE_DVB_T: >+ cx_set(MO_GP0_IO, 0x00000707); >+ cx_set(MO_GP2_IO, 0x00000101); >+ cx_clear(MO_GP2_IO, 0x00000001); >+ msleep(1); >+ cx_clear(MO_GP0_IO, 0x00000007); >+ cx_set(MO_GP2_IO, 0x00000101); > break; >-#endif > } > if (cx88_boards[core->board].radio.type == CX88_RADIO) > core->has_radio = 1; >Index: linux-2.6.11/drivers/media/video/cx88/cx88-core.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-core.c 2005-03-07 10:13:16.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-core.c 2005-03-08 10:33:15.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: cx88-core.c,v 1.15 2004/10/25 11:26:36 kraxel Exp $ >+ * $Id: cx88-core.c,v 1.24 2005/01/19 12:01:55 kraxel Exp $ > * > * device driver for Conexant 2388x based TV cards > * driver core >@@ -24,6 +24,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kernel.h> > #include <linux/slab.h> > #include <linux/kmod.h> >@@ -62,6 +63,10 @@ static unsigned int nicam = 0; > module_param(nicam,int,0644); > MODULE_PARM_DESC(nicam,"tv audio is nicam"); > >+static unsigned int nocomb = 0; >+module_param(nocomb,int,0644); >+MODULE_PARM_DESC(nocomb,"disable comb filter"); >+ > #define dprintk(level,fmt, arg...) if (core_debug >= level) \ > printk(KERN_DEBUG "%s: " fmt, core->name , ## arg) > >@@ -462,6 +467,7 @@ int cx88_risc_decode(u32 risc) > return incr[risc >> 28] ? incr[risc >> 28] : 1; > } > >+#if 0 /* currently unused, but useful for debugging */ > void cx88_risc_disasm(struct cx88_core *core, > struct btcx_riscmem *risc) > { >@@ -479,6 +485,7 @@ void cx88_risc_disasm(struct cx88_core * > break; > } > } >+#endif > > void cx88_sram_channel_dump(struct cx88_core *core, > struct sram_channel *ch) >@@ -579,10 +586,19 @@ void cx88_print_irqbits(char *name, char > > /* ------------------------------------------------------------------ */ > >-void cx88_irq(struct cx88_core *core, u32 status, u32 mask) >+int cx88_core_irq(struct cx88_core *core, u32 status) > { >- cx88_print_irqbits(core->name, "irq pci", >- cx88_pci_irqs, status, mask); >+ int handled = 0; >+ >+ if (status & (1<<18)) { >+ cx88_ir_irq(core); >+ handled++; >+ } >+ if (!handled) >+ cx88_print_irqbits(core->name, "irq pci", >+ cx88_pci_irqs, status, >+ core->pci_irqmask); >+ return handled; > } > > void cx88_wakeup(struct cx88_core *core, >@@ -800,6 +816,8 @@ int cx88_set_scale(struct cx88_core *cor > value |= (1 << 0); // 3-tap interpolation > if (width < 193) > value |= (1 << 1); // 5-tap interpolation >+ if (nocomb) >+ value |= (3 << 5); // disable comb filter > > cx_write(MO_FILTER_EVEN, value); > cx_write(MO_FILTER_ODD, value); >@@ -887,8 +905,8 @@ static int set_tvaudio(struct cx88_core > cx88_set_tvaudio(core); > // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); > >- cx_write(MO_AUDD_LNGTH, 128/8); /* fifo size */ >- cx_write(MO_AUDR_LNGTH, 128/8); /* fifo size */ >+ cx_write(MO_AUDD_LNGTH, 128); /* fifo size */ >+ cx_write(MO_AUDR_LNGTH, 128); /* fifo size */ > cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */ > return 0; > } >@@ -969,6 +987,9 @@ int cx88_set_tvnorm(struct cx88_core *co > cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */ > norm_vbipack(norm))); > >+ // this is needed as well to set all tvnorm parameter >+ cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED); >+ > // audio > set_tvaudio(core); > >@@ -1105,9 +1126,10 @@ struct cx88_core* cx88_core_get(struct p > goto fail_unlock; > > memset(core,0,sizeof(*core)); >+ atomic_inc(&core->refcount); > core->pci_bus = pci->bus->number; > core->pci_slot = PCI_SLOT(pci->devfn); >- atomic_inc(&core->refcount); >+ core->pci_irqmask = 0x00fc00; > > core->nr = cx88_devcount++; > sprintf(core->name,"cx88[%d]",core->nr); >@@ -1150,6 +1172,7 @@ struct cx88_core* cx88_core_get(struct p > cx88_reset(core); > cx88_i2c_init(core,pci); > cx88_card_setup(core); >+ cx88_ir_init(core,pci); > > up(&devlist); > return core; >@@ -1170,6 +1193,7 @@ void cx88_core_put(struct cx88_core *cor > return; > > down(&devlist); >+ cx88_ir_fini(core); > if (0 == core->i2c_rc) > i2c_bit_del_bus(&core->i2c_adap); > list_del(&core->devlist); >@@ -1187,7 +1211,7 @@ EXPORT_SYMBOL(cx88_vid_irqs); > EXPORT_SYMBOL(cx88_mpeg_irqs); > EXPORT_SYMBOL(cx88_print_irqbits); > >-EXPORT_SYMBOL(cx88_irq); >+EXPORT_SYMBOL(cx88_core_irq); > EXPORT_SYMBOL(cx88_wakeup); > EXPORT_SYMBOL(cx88_reset); > EXPORT_SYMBOL(cx88_shutdown); >@@ -1197,8 +1221,6 @@ EXPORT_SYMBOL(cx88_risc_databuffer); > EXPORT_SYMBOL(cx88_risc_stopper); > EXPORT_SYMBOL(cx88_free_buffer); > >-EXPORT_SYMBOL(cx88_risc_disasm); >- > EXPORT_SYMBOL(cx88_sram_channels); > EXPORT_SYMBOL(cx88_sram_channel_setup); > EXPORT_SYMBOL(cx88_sram_channel_dump); >Index: linux-2.6.11/drivers/media/video/cx88/cx88-dvb.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-dvb.c 2005-03-07 10:14:23.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-dvb.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: cx88-dvb.c,v 1.19 2004/11/07 14:44:59 kraxel Exp $ >+ * $Id: cx88-dvb.c,v 1.31 2005/03/07 15:58:05 kraxel Exp $ > * > * device driver for Conexant 2388x based TV cards > * MPEG Transport Stream (DVB) routines >@@ -30,10 +30,20 @@ > #include <linux/file.h> > #include <linux/suspend.h> > >+/* those two frontends need merging via linuxtv cvs ... */ >+#define HAVE_CX22702 1 >+#define HAVE_OR51132 1 >+ > #include "cx88.h" >-#include "cx22702.h" >+#include "dvb-pll.h" > #include "mt352.h" >-#include "mt352_priv.h" /* FIXME */ >+#include "mt352_priv.h" >+#if HAVE_CX22702 >+# include "cx22702.h" >+#endif >+#if HAVE_OR51132 >+# include "or51132.h" >+#endif > > MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); > MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); >@@ -110,111 +120,144 @@ static int dvico_fusionhdtv_demod_init(s > return 0; > } > >-#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ >- >-static int lg_z201_pll_set(struct dvb_frontend* fe, >- struct dvb_frontend_parameters* params, u8* pllbuf) >+static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) > { >- u32 div; >- unsigned char cp = 0; >- unsigned char bs = 0; >- >- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; >- >- if (params->frequency < 542000000) cp = 0xbc; >- else if (params->frequency < 830000000) cp = 0xf4; >- else cp = 0xfc; >+ static u8 clock_config [] = { 0x89, 0x38, 0x39 }; >+ static u8 reset [] = { 0x50, 0x80 }; >+ static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; >+ static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, >+ 0x00, 0xFF, 0x00, 0x40, 0x40 }; >+ static u8 dntv_extra[] = { 0xB5, 0x7A }; >+ static u8 capt_range_cfg[] = { 0x75, 0x32 }; > >- if (params->frequency == 0) bs = 0x03; >- else if (params->frequency < 157500000) bs = 0x01; >- else if (params->frequency < 443250000) bs = 0x02; >- else bs = 0x04; >+ mt352_write(fe, clock_config, sizeof(clock_config)); >+ udelay(2000); >+ mt352_write(fe, reset, sizeof(reset)); >+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); > >- pllbuf[0] = 0xC2; /* Note: non-linux standard PLL I2C address */ >- pllbuf[1] = div >> 8; >- pllbuf[2] = div & 0xff; >- pllbuf[3] = cp; >- pllbuf[4] = bs; >+ mt352_write(fe, agc_cfg, sizeof(agc_cfg)); >+ udelay(2000); >+ mt352_write(fe, dntv_extra, sizeof(dntv_extra)); >+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); > > return 0; > } > >-static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, >- struct dvb_frontend_parameters* params, >- u8* pllbuf) >+static int mt352_pll_set(struct dvb_frontend* fe, >+ struct dvb_frontend_parameters* params, >+ u8* pllbuf) > { >- u32 div; >- unsigned char cp = 0; >- unsigned char bs = 0; >- >- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; >- >- if (params->frequency < 542000000) cp = 0xb4; >- else if (params->frequency < 771000000) cp = 0xbc; >- else cp = 0xf4; >- >- if (params->frequency == 0) bs = 0x03; >- else if (params->frequency < 443250000) bs = 0x02; >- else bs = 0x08; >- >- pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address >- pllbuf[1] = div >> 8; >- pllbuf[2] = div & 0xff; >- pllbuf[3] = cp; >- pllbuf[4] = bs; >+ struct cx8802_dev *dev= fe->dvb->priv; > >+ pllbuf[0] = dev->core->pll_addr << 1; >+ dvb_pll_configure(dev->core->pll_desc, pllbuf+1, >+ params->frequency, >+ params->u.ofdm.bandwidth); > return 0; > } > >-struct mt352_config dvico_fusionhdtv_dvbt1 = { >+static struct mt352_config dvico_fusionhdtv = { > .demod_address = 0x0F, > .demod_init = dvico_fusionhdtv_demod_init, >- .pll_set = lg_z201_pll_set, >+ .pll_set = mt352_pll_set, > }; > >-struct mt352_config dvico_fusionhdtv_dvbt_plus = { >- .demod_address = 0x0F, >- .demod_init = dvico_fusionhdtv_demod_init, >- .pll_set = thomson_dtt7579_pll_set, >+static struct mt352_config dntv_live_dvbt_config = { >+ .demod_address = 0x0f, >+ .demod_init = dntv_live_dvbt_demod_init, >+ .pll_set = mt352_pll_set, >+}; >+ >+#if HAVE_CX22702 >+static struct cx22702_config connexant_refboard_config = { >+ .demod_address = 0x43, >+ .pll_address = 0x60, >+ .pll_desc = &dvb_pll_thomson_dtt7579, >+}; >+ >+static struct cx22702_config hauppauge_novat_config = { >+ .demod_address = 0x43, >+ .pll_address = 0x61, >+ .pll_desc = &dvb_pll_thomson_dtt759x, > }; >+#endif >+ >+#if HAVE_OR51132 >+static int or51132_set_ts_param(struct dvb_frontend* fe, >+ int is_punctured) >+{ >+ struct cx8802_dev *dev= fe->dvb->priv; >+ dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; >+ return 0; >+} >+ >+struct or51132_config pchdtv_hd3000 = { >+ .demod_address = 0x15, >+ .pll_address = 0x61, >+ .pll_desc = &dvb_pll_thomson_dtt7610, >+ .set_ts_params = or51132_set_ts_param, >+}; >+#endif > > static int dvb_register(struct cx8802_dev *dev) > { > /* init struct videobuf_dvb */ > dev->dvb.name = dev->core->name; >+ dev->ts_gen_cntrl = 0x0c; > > /* init frontend */ > switch (dev->core->board) { >+#if HAVE_CX22702 > case CX88_BOARD_HAUPPAUGE_DVB_T1: >+ dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config, >+ &dev->core->i2c_adap); >+ break; > case CX88_BOARD_CONEXANT_DVB_T1: >- dev->dvb.frontend = cx22702_create(&dev->core->i2c_adap, >- dev->core->pll_addr, >- dev->core->pll_type, >- dev->core->demod_addr); >+ dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, >+ &dev->core->i2c_adap); > break; >+#endif > case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: >- dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dvbt1, >+ dev->core->pll_addr = 0x61; >+ dev->core->pll_desc = &dvb_pll_lg_z201; >+ dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, > &dev->core->i2c_adap); >- if (dev->dvb.frontend) { >- dev->dvb.frontend->ops->info.frequency_min = 174000000; >- dev->dvb.frontend->ops->info.frequency_max = 862000000; >- } > break; > case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: >- dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dvbt_plus, >+ dev->core->pll_addr = 0x60; >+ dev->core->pll_desc = &dvb_pll_thomson_dtt7579; >+ dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, >+ &dev->core->i2c_adap); >+ break; >+ case CX88_BOARD_KWORLD_DVB_T: >+ case CX88_BOARD_DNTV_LIVE_DVB_T: >+ dev->core->pll_addr = 0x61; >+ dev->core->pll_desc = &dvb_pll_unknown_1; >+ dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, >+ &dev->core->i2c_adap); >+ break; >+#if HAVE_OR51132 >+ case CX88_BOARD_PCHDTV_HD3000: >+ dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, > &dev->core->i2c_adap); >- if (dev->dvb.frontend) { >- dev->dvb.frontend->ops->info.frequency_min = 174000000; >- dev->dvb.frontend->ops->info.frequency_max = 862000000; >- } > break; >+#endif > default: >- printk("%s: FIXME: frontend handling not here yet ...\n", >- dev->core->name); >+ printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n" >+ "%s: you might want to look out for patches here:\n" >+ "%s: http://dl.bytesex.org/patches/\n", >+ dev->core->name, dev->core->name, dev->core->name); > break; > } >- if (NULL == dev->dvb.frontend) >+ if (NULL == dev->dvb.frontend) { >+ printk("%s: frontend initialization failed\n",dev->core->name); > return -1; >+ } >+ >+ if (dev->core->pll_desc) { >+ dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min; >+ dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max; >+ } > > /* Copy the board name into the DVB structure */ > strlcpy(dev->dvb.frontend->ops->info.name, >@@ -222,7 +265,7 @@ static int dvb_register(struct cx8802_de > sizeof(dev->dvb.frontend->ops->info.name)); > > /* register everything */ >- return videobuf_dvb_register(&dev->dvb); >+ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); > } > > /* ----------------------------------------------------------- */ >@@ -319,7 +362,7 @@ static int dvb_init(void) > printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", > SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); > #endif >- return pci_module_init(&dvb_pci_driver); >+ return pci_register_driver(&dvb_pci_driver); > } > > static void dvb_fini(void) >Index: linux-2.6.11/drivers/media/video/cx88/cx88-i2c.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-i2c.c 2005-03-07 10:13:32.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-i2c.c 2005-03-08 10:33:15.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- $Id: cx88-i2c.c,v 1.18 2004/10/13 10:39:00 kraxel Exp $ >+ $Id: cx88-i2c.c,v 1.20 2005/02/15 15:59:35 kraxel Exp $ > > cx88-i2c.c -- all the i2c code is here > >@@ -25,6 +25,7 @@ > */ > > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/init.h> > > #include <asm/io.h> >Index: linux-2.6.11/drivers/media/video/cx88/cx88-input.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-input.c 2005-03-08 10:33:15.000000000 +0100 >@@ -0,0 +1,396 @@ >+/* >+ * $Id: cx88-input.c,v 1.9 2005/03/04 09:12:23 kraxel Exp $ >+ * >+ * Device driver for GPIO attached remote control interfaces >+ * on Conexant 2388x based TV/DVB cards. >+ * >+ * Copyright (c) 2003 Pavel Machek >+ * Copyright (c) 2004 Gerd Knorr >+ * Copyright (c) 2004 Chris Pascoe >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 2 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ */ >+ >+#include <linux/init.h> >+#include <linux/delay.h> >+#include <linux/input.h> >+#include <linux/pci.h> >+#include <linux/module.h> >+#include <linux/moduleparam.h> >+ >+#include <media/ir-common.h> >+ >+#include "cx88.h" >+ >+/* ---------------------------------------------------------------------- */ >+ >+/* DigitalNow DNTV Live DVB-T Remote */ >+static IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { >+ [ 0x00 ] = KEY_ESC, // 'go up a level?' >+ [ 0x01 ] = KEY_KP1, // '1' >+ [ 0x02 ] = KEY_KP2, // '2' >+ [ 0x03 ] = KEY_KP3, // '3' >+ [ 0x04 ] = KEY_KP4, // '4' >+ [ 0x05 ] = KEY_KP5, // '5' >+ [ 0x06 ] = KEY_KP6, // '6' >+ [ 0x07 ] = KEY_KP7, // '7' >+ [ 0x08 ] = KEY_KP8, // '8' >+ [ 0x09 ] = KEY_KP9, // '9' >+ [ 0x0a ] = KEY_KP0, // '0' >+ [ 0x0b ] = KEY_TUNER, // 'tv/fm' >+ [ 0x0c ] = KEY_SEARCH, // 'scan' >+ [ 0x0d ] = KEY_STOP, // 'stop' >+ [ 0x0e ] = KEY_PAUSE, // 'pause' >+ [ 0x0f ] = KEY_LIST, // 'source' >+ >+ [ 0x10 ] = KEY_MUTE, // 'mute' >+ [ 0x11 ] = KEY_REWIND, // 'backward <<' >+ [ 0x12 ] = KEY_POWER, // 'power' >+ [ 0x13 ] = KEY_S, // 'snap' >+ [ 0x14 ] = KEY_AUDIO, // 'stereo' >+ [ 0x15 ] = KEY_CLEAR, // 'reset' >+ [ 0x16 ] = KEY_PLAY, // 'play' >+ [ 0x17 ] = KEY_ENTER, // 'enter' >+ [ 0x18 ] = KEY_ZOOM, // 'full screen' >+ [ 0x19 ] = KEY_FASTFORWARD, // 'forward >>' >+ [ 0x1a ] = KEY_CHANNELUP, // 'channel +' >+ [ 0x1b ] = KEY_VOLUMEUP, // 'volume +' >+ [ 0x1c ] = KEY_INFO, // 'preview' >+ [ 0x1d ] = KEY_RECORD, // 'record' >+ [ 0x1e ] = KEY_CHANNELDOWN, // 'channel -' >+ [ 0x1f ] = KEY_VOLUMEDOWN, // 'volume -' >+}; >+ >+/* ---------------------------------------------------------------------- */ >+ >+/* IO-DATA BCTV7E Remote */ >+static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { >+ [ 0x40 ] = KEY_TV, // TV >+ [ 0x20 ] = KEY_RADIO, // FM >+ [ 0x60 ] = KEY_EPG, // EPG >+ [ 0x00 ] = KEY_POWER, // power >+ >+ [ 0x50 ] = KEY_KP1, // 1 >+ [ 0x30 ] = KEY_KP2, // 2 >+ [ 0x70 ] = KEY_KP3, // 3 >+ [ 0x10 ] = KEY_L, // Live >+ >+ [ 0x48 ] = KEY_KP4, // 4 >+ [ 0x28 ] = KEY_KP5, // 5 >+ [ 0x68 ] = KEY_KP6, // 6 >+ [ 0x08 ] = KEY_T, // Time Shift >+ >+ [ 0x58 ] = KEY_KP7, // 7 >+ [ 0x38 ] = KEY_KP8, // 8 >+ [ 0x78 ] = KEY_KP9, // 9 >+ [ 0x18 ] = KEY_PLAYPAUSE, // Play >+ >+ [ 0x44 ] = KEY_KP0, // 10 >+ [ 0x24 ] = KEY_ENTER, // 11 >+ [ 0x64 ] = KEY_ESC, // 12 >+ [ 0x04 ] = KEY_M, // Multi >+ >+ [ 0x54 ] = KEY_VIDEO, // VIDEO >+ [ 0x34 ] = KEY_CHANNELUP, // channel + >+ [ 0x74 ] = KEY_VOLUMEUP, // volume + >+ [ 0x14 ] = KEY_MUTE, // Mute >+ >+ [ 0x4c ] = KEY_S, // SVIDEO >+ [ 0x2c ] = KEY_CHANNELDOWN, // channel - >+ [ 0x6c ] = KEY_VOLUMEDOWN, // volume - >+ [ 0x0c ] = KEY_ZOOM, // Zoom >+ >+ [ 0x5c ] = KEY_PAUSE, // pause >+ [ 0x3c ] = KEY_C, // || (red) >+ [ 0x7c ] = KEY_RECORD, // recording >+ [ 0x1c ] = KEY_STOP, // stop >+ >+ [ 0x41 ] = KEY_REWIND, // backward << >+ [ 0x21 ] = KEY_PLAY, // play >+ [ 0x61 ] = KEY_FASTFORWARD, // forward >> >+ [ 0x01 ] = KEY_NEXT, // skip >| >+}; >+ >+/* ---------------------------------------------------------------------- */ >+ >+struct cx88_IR { >+ struct cx88_core *core; >+ struct input_dev input; >+ struct ir_input_state ir; >+ char name[32]; >+ char phys[32]; >+ >+ /* sample from gpio pin 16 */ >+ int sampling; >+ u32 samples[16]; >+ int scount; >+ unsigned long release; >+ >+ /* poll external decoder */ >+ int polling; >+ struct work_struct work; >+ struct timer_list timer; >+ u32 gpio_addr; >+ u32 last_gpio; >+ u32 mask_keycode; >+ u32 mask_keydown; >+ u32 mask_keyup; >+}; >+ >+static int ir_debug = 0; >+module_param(ir_debug, int, 0644); /* debug level [IR] */ >+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); >+ >+#define ir_dprintk(fmt, arg...) if (ir_debug) \ >+ printk(KERN_DEBUG "%s IR: " fmt , ir->core->name, ## arg) >+ >+/* ---------------------------------------------------------------------- */ >+ >+static void cx88_ir_handle_key(struct cx88_IR *ir) >+{ >+ struct cx88_core *core = ir->core; >+ u32 gpio, data; >+ >+ /* read gpio value */ >+ gpio = cx_read(ir->gpio_addr); >+ if (ir->polling) { >+ if (ir->last_gpio == gpio) >+ return; >+ ir->last_gpio = gpio; >+ } >+ >+ /* extract data */ >+ data = ir_extract_bits(gpio, ir->mask_keycode); >+ ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n", >+ gpio, data, >+ ir->polling ? "poll" : "irq", >+ (gpio & ir->mask_keydown) ? " down" : "", >+ (gpio & ir->mask_keyup) ? " up" : ""); >+ >+ if (ir->mask_keydown) { >+ /* bit set on keydown */ >+ if (gpio & ir->mask_keydown) { >+ ir_input_keydown(&ir->input,&ir->ir,data,data); >+ } else { >+ ir_input_nokey(&ir->input,&ir->ir); >+ } >+ >+ } else if (ir->mask_keyup) { >+ /* bit cleared on keydown */ >+ if (0 == (gpio & ir->mask_keyup)) { >+ ir_input_keydown(&ir->input,&ir->ir,data,data); >+ } else { >+ ir_input_nokey(&ir->input,&ir->ir); >+ } >+ >+ } else { >+ /* can't distinguish keydown/up :-/ */ >+ ir_input_keydown(&ir->input,&ir->ir,data,data); >+ ir_input_nokey(&ir->input,&ir->ir); >+ } >+} >+ >+static void ir_timer(unsigned long data) >+{ >+ struct cx88_IR *ir = (struct cx88_IR*)data; >+ >+ schedule_work(&ir->work); >+} >+ >+static void cx88_ir_work(void *data) >+{ >+ struct cx88_IR *ir = data; >+ unsigned long timeout; >+ >+ cx88_ir_handle_key(ir); >+ timeout = jiffies + (ir->polling * HZ / 1000); >+ mod_timer(&ir->timer, timeout); >+} >+ >+/* ---------------------------------------------------------------------- */ >+ >+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) >+{ >+ struct cx88_IR *ir; >+ IR_KEYTAB_TYPE *ir_codes = NULL; >+ int ir_type = IR_TYPE_OTHER; >+ >+ ir = kmalloc(sizeof(*ir),GFP_KERNEL); >+ if (NULL == ir) >+ return -ENOMEM; >+ memset(ir,0,sizeof(*ir)); >+ >+ /* detect & configure */ >+ switch (core->board) { >+ case CX88_BOARD_DNTV_LIVE_DVB_T: >+ ir_codes = ir_codes_dntv_live_dvb_t; >+ ir->gpio_addr = MO_GP1_IO; >+ ir->mask_keycode = 0x1f; >+ ir->mask_keyup = 0x60; >+ ir->polling = 50; // ms >+ break; >+ case CX88_BOARD_HAUPPAUGE: >+ case CX88_BOARD_HAUPPAUGE_DVB_T1: >+ ir_codes = ir_codes_hauppauge_new; >+ ir_type = IR_TYPE_RC5; >+ ir->sampling = 1; >+ break; >+ case CX88_BOARD_WINFAST2000XP_EXPERT: >+ ir_codes = ir_codes_winfast; >+ ir->gpio_addr = MO_GP0_IO; >+ ir->mask_keycode = 0x8f8; >+ ir->mask_keyup = 0x100; >+ ir->polling = 1; // ms >+ break; >+ case CX88_BOARD_IODATA_GVBCTV7E: >+ ir_codes = ir_codes_iodata_bctv7e; >+ ir->gpio_addr = MO_GP0_IO; >+ ir->mask_keycode = 0xfd; >+ ir->mask_keydown = 0x02; >+ ir->polling = 5; // ms >+ break; >+ } >+ if (NULL == ir_codes) { >+ kfree(ir); >+ return -ENODEV; >+ } >+ >+ /* init input device */ >+ snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", >+ cx88_boards[core->board].name); >+ snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", >+ pci_name(pci)); >+ >+ ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes); >+ ir->input.name = ir->name; >+ ir->input.phys = ir->phys; >+ ir->input.id.bustype = BUS_PCI; >+ ir->input.id.version = 1; >+ if (pci->subsystem_vendor) { >+ ir->input.id.vendor = pci->subsystem_vendor; >+ ir->input.id.product = pci->subsystem_device; >+ } else { >+ ir->input.id.vendor = pci->vendor; >+ ir->input.id.product = pci->device; >+ } >+ >+ /* record handles to ourself */ >+ ir->core = core; >+ core->ir = ir; >+ >+ if (ir->polling) { >+ INIT_WORK(&ir->work, cx88_ir_work, ir); >+ init_timer(&ir->timer); >+ ir->timer.function = ir_timer; >+ ir->timer.data = (unsigned long)ir; >+ schedule_work(&ir->work); >+ } >+ if (ir->sampling) { >+ core->pci_irqmask |= (1<<18); // IR_SMP_INT >+ cx_write(MO_DDS_IO, 0xa80a80); // 4 kHz sample rate >+ cx_write(MO_DDSCFG_IO, 0x5); // enable >+ } >+ >+ /* all done */ >+ input_register_device(&ir->input); >+ printk("%s: registered IR remote control\n", core->name); >+ >+ return 0; >+} >+ >+int cx88_ir_fini(struct cx88_core *core) >+{ >+ struct cx88_IR *ir = core->ir; >+ >+ /* skip detach on non attached boards */ >+ if (NULL == ir) >+ return 0; >+ >+ if (ir->polling) { >+ del_timer(&ir->timer); >+ flush_scheduled_work(); >+ } >+ >+ input_unregister_device(&ir->input); >+ kfree(ir); >+ >+ /* done */ >+ core->ir = NULL; >+ return 0; >+} >+ >+/* ---------------------------------------------------------------------- */ >+ >+void cx88_ir_irq(struct cx88_core *core) >+{ >+ struct cx88_IR *ir = core->ir; >+ u32 samples,rc5; >+ int i; >+ >+ if (NULL == ir) >+ return; >+ if (!ir->sampling) >+ return; >+ >+ samples = cx_read(MO_SAMPLE_IO); >+ if (0 != samples && 0xffffffff != samples) { >+ /* record sample data */ >+ if (ir->scount < ARRAY_SIZE(ir->samples)) >+ ir->samples[ir->scount++] = samples; >+ return; >+ } >+ if (!ir->scount) { >+ /* nothing to sample */ >+ if (ir->ir.keypressed && time_after(jiffies,ir->release)) >+ ir_input_nokey(&ir->input,&ir->ir); >+ return; >+ } >+ >+ /* have a complete sample */ >+ if (ir->scount < ARRAY_SIZE(ir->samples)) >+ ir->samples[ir->scount++] = samples; >+ for (i = 0; i < ir->scount; i++) >+ ir->samples[i] = ~ir->samples[i]; >+ if (ir_debug) >+ ir_dump_samples(ir->samples,ir->scount); >+ >+ /* decode it */ >+ switch (core->board) { >+ case CX88_BOARD_HAUPPAUGE: >+ case CX88_BOARD_HAUPPAUGE_DVB_T1: >+ rc5 = ir_decode_biphase(ir->samples,ir->scount,5,7); >+ ir_dprintk("biphase decoded: %x\n",rc5); >+ if ((rc5 & 0xfffff000) != 0x3000) >+ break; >+ ir_input_keydown(&ir->input, &ir->ir, rc5 & 0x3f, rc5); >+ ir->release = jiffies + msecs_to_jiffies(120); >+ break; >+ } >+ >+ ir->scount = 0; >+ return; >+} >+ >+/* ---------------------------------------------------------------------- */ >+ >+MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe"); >+MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls"); >+MODULE_LICENSE("GPL"); >+ >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/video/cx88/cx88-mpeg.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-mpeg.c 2005-03-07 10:16:04.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-mpeg.c 2005-03-08 10:33:15.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: cx88-mpeg.c,v 1.14 2004/10/25 11:26:36 kraxel Exp $ >+ * $Id: cx88-mpeg.c,v 1.25 2005/03/07 14:18:00 kraxel Exp $ > * > * Support for the mpeg transport stream transfers > * PCI function #2 of the cx2388x. >@@ -24,6 +24,7 @@ > */ > > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/init.h> > #include <linux/device.h> > #include <linux/interrupt.h> >@@ -68,8 +69,14 @@ static int cx8802_start_dma(struct cx880 > * also: move to cx88-blackbird + cx88-dvb source files? */ > > if (cx88_boards[core->board].dvb) { >- /* Setup TS portion of chip */ >- cx_write(TS_GEN_CNTRL, 0x0c); >+ /* negedge driven & software reset */ >+ cx_write(TS_GEN_CNTRL, 0x40); >+ udelay(100); >+ cx_write(MO_PINMUX_IO, 0x00); >+ cx_write(TS_HW_SOP_CNTRL,47<<16|188<<4|0x00); >+ cx_write(TS_SOP_STAT,0x00); >+ cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); >+ udelay(100); > } > > if (cx88_boards[core->board].blackbird) { >@@ -93,7 +100,7 @@ static int cx8802_start_dma(struct cx880 > q->count = 1; > > /* enable irqs */ >- cx_set(MO_PCI_INTMSK, 0x00fc04); >+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04); > cx_write(MO_TS_INTMSK, 0x1f0011); > > /* start dma */ >@@ -292,19 +299,18 @@ static irqreturn_t cx8802_irq(int irq, v > { > struct cx8802_dev *dev = dev_id; > struct cx88_core *core = dev->core; >- u32 status, mask; >+ u32 status; > int loop, handled = 0; > > for (loop = 0; loop < 10; loop++) { >- status = cx_read(MO_PCI_INTSTAT) & (~0x1f | 0x04); >- mask = cx_read(MO_PCI_INTMSK); >- if (0 == (status & mask)) >+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04); >+ if (0 == status) > goto out; > handled = 1; > cx_write(MO_PCI_INTSTAT, status); > >- if (status & mask & ~0x1f) >- cx88_irq(core,status,mask); >+ if (status & core->pci_irqmask) >+ cx88_core_irq(core,status); > if (status & 0x04) > cx8802_mpeg_irq(dev); > }; >@@ -323,6 +329,7 @@ static irqreturn_t cx8802_irq(int irq, v > > int cx8802_init_common(struct cx8802_dev *dev) > { >+ struct cx88_core *core = dev->core; > int err; > > /* pci init */ >@@ -354,11 +361,6 @@ int cx8802_init_common(struct cx8802_dev > cx88_risc_stopper(dev->pci,&dev->mpegq.stopper, > MO_TS_DMACNTRL,0x11,0x00); > >-#if 0 /* FIXME */ >- /* initialize hardware */ >- cx8802_reset(dev); >-#endif >- > /* get irq */ > err = request_irq(dev->pci->irq, cx8802_irq, > SA_SHIRQ | SA_INTERRUPT, dev->core->name, dev); >@@ -367,11 +369,7 @@ int cx8802_init_common(struct cx8802_dev > dev->core->name, dev->pci->irq); > return err; > } >- >-#if 0 /* FIXME */ >- /* register i2c bus + load i2c helpers */ >- cx88_card_setup(dev); >-#endif >+ cx_set(MO_PCI_INTMSK, core->pci_irqmask); > > /* everything worked */ > pci_set_drvdata(dev->pci,dev); >@@ -393,7 +391,7 @@ void cx8802_fini_common(struct cx8802_de > > /* ----------------------------------------------------------- */ > >-int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state) >+int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state) > { > struct cx8802_dev *dev = pci_get_drvdata(pci_dev); > struct cx88_core *core = dev->core; >@@ -413,7 +411,7 @@ int cx8802_suspend_common(struct pci_dev > #endif > > pci_save_state(pci_dev); >- if (0 != pci_set_power_state(pci_dev, state)) { >+ if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) { > pci_disable_device(pci_dev); > dev->state.disabled = 1; > } >@@ -429,7 +427,7 @@ int cx8802_resume_common(struct pci_dev > pci_enable_device(pci_dev); > dev->state.disabled = 0; > } >- pci_set_power_state(pci_dev, 0); >+ pci_set_power_state(pci_dev, PCI_D0); > pci_restore_state(pci_dev); > > #if 1 >Index: linux-2.6.11/drivers/media/video/cx88/cx88-tvaudio.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-tvaudio.c 2005-03-07 10:13:41.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-tvaudio.c 2005-03-08 10:33:20.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- $Id: cx88-tvaudio.c,v 1.24 2004/10/25 11:51:00 kraxel Exp $ >+ $Id: cx88-tvaudio.c,v 1.34 2005/03/07 16:10:51 kraxel Exp $ > > cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver > >@@ -37,6 +37,7 @@ > */ > > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/errno.h> > #include <linux/kernel.h> > #include <linux/slab.h> >@@ -56,7 +57,7 @@ > > #include "cx88.h" > >-static unsigned int audio_debug = 1; >+static unsigned int audio_debug = 0; > module_param(audio_debug,int,0644); > MODULE_PARM_DESC(audio_debug,"enable debug messages [audio]"); > >@@ -141,6 +142,13 @@ static void set_audio_finish(struct cx88 > { > u32 volume; > >+ if (cx88_boards[core->board].blackbird) { >+ // 'pass-thru mode': this enables the i2s output to the mpeg encoder >+ cx_set(AUD_CTL, 0x2000); >+ cx_write(AUD_I2SOUTPUTCNTL, 1); >+ //cx_write(AUD_APB_IN_RATE_ADJ, 0); >+ } >+ > // finish programming > cx_write(AUD_SOFT_RESET, 0x0000); > >@@ -263,6 +271,7 @@ static void set_audio_standard_BTSC(stru > set_audio_finish(core); > } > >+#if 0 > static void set_audio_standard_NICAM(struct cx88_core *core) > { > static const struct rlist nicam_common[] = { >@@ -335,128 +344,243 @@ static void set_audio_standard_NICAM(str > }; > set_audio_finish(core); > } >+#endif > >-static void set_audio_standard_NICAM_L(struct cx88_core *core) >+static void set_audio_standard_NICAM_L(struct cx88_core *core, int stereo) > { >- /* This is officially weird.. register dumps indicate windows >- * uses audio mode 4.. A2. Let's operate and find out. */ >+ /* This is probably weird.. >+ * Let's operate and find out. */ > >- static const struct rlist nicam_l[] = { >- // setup QAM registers >- { AUD_PDF_DDS_CNST_BYTE2, 0x48 }, >- { AUD_PDF_DDS_CNST_BYTE1, 0x3d }, >- { AUD_PDF_DDS_CNST_BYTE0, 0xf5 }, >- { AUD_QAM_MODE, 0x00 }, >- { AUD_PHACC_FREQ_8MSB, 0x3a }, >- { AUD_PHACC_FREQ_8LSB, 0x4a }, >+ static const struct rlist nicam_l_mono[] = { >+ { AUD_ERRLOGPERIOD_R, 0x00000064 }, >+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF }, >+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F }, >+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F }, > >- { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 }, >- { AUD_IIR1_0_SEL, 0x00000000 }, >- { AUD_IIR1_1_SEL, 0x00000002 }, >- { AUD_IIR1_2_SEL, 0x00000023 }, >- { AUD_IIR1_3_SEL, 0x00000004 }, >- { AUD_IIR1_4_SEL, 0x00000005 }, >- { AUD_IIR1_5_SEL, 0x00000007 }, >- { AUD_IIR1_0_SHIFT, 0x00000007 }, >- { AUD_IIR1_1_SHIFT, 0x00000000 }, >- { AUD_IIR1_2_SHIFT, 0x00000000 }, >- { AUD_IIR1_3_SHIFT, 0x00000007 }, >- { AUD_IIR1_4_SHIFT, 0x00000007 }, >- { AUD_IIR1_5_SHIFT, 0x00000007 }, >- { AUD_IIR2_0_SEL, 0x00000002 }, >- { AUD_IIR2_1_SEL, 0x00000003 }, >- { AUD_IIR2_2_SEL, 0x00000004 }, >- { AUD_IIR2_3_SEL, 0x00000005 }, >- { AUD_IIR3_0_SEL, 0x00000007 }, >- { AUD_IIR3_1_SEL, 0x00000023 }, >- { AUD_IIR3_2_SEL, 0x00000016 }, >- { AUD_IIR4_0_SHIFT, 0x00000000 }, >- { AUD_IIR4_1_SHIFT, 0x00000000 }, >- { AUD_IIR3_2_SHIFT, 0x00000002 }, >- { AUD_IIR4_0_SEL, 0x0000001d }, >- { AUD_IIR4_1_SEL, 0x00000019 }, >- { AUD_IIR4_2_SEL, 0x00000008 }, >- { AUD_IIR4_0_SHIFT, 0x00000000 }, >- { AUD_IIR4_1_SHIFT, 0x00000007 }, >- { AUD_IIR4_2_SHIFT, 0x00000007 }, >- { AUD_IIR4_0_CA0, 0x0003e57e }, >- { AUD_IIR4_0_CA1, 0x00005e11 }, >- { AUD_IIR4_0_CA2, 0x0003a7cf }, >- { AUD_IIR4_0_CB0, 0x00002368 }, >- { AUD_IIR4_0_CB1, 0x0003bf1b }, >- { AUD_IIR4_1_CA0, 0x00006349 }, >- { AUD_IIR4_1_CA1, 0x00006f27 }, >- { AUD_IIR4_1_CA2, 0x0000e7a3 }, >- { AUD_IIR4_1_CB0, 0x00005653 }, >- { AUD_IIR4_1_CB1, 0x0000cf97 }, >- { AUD_IIR4_2_CA0, 0x00006349 }, >- { AUD_IIR4_2_CA1, 0x00006f27 }, >- { AUD_IIR4_2_CA2, 0x0000e7a3 }, >- { AUD_IIR4_2_CB0, 0x00005653 }, >- { AUD_IIR4_2_CB1, 0x0000cf97 }, >- { AUD_HP_MD_IIR4_1, 0x00000001 }, >- { AUD_HP_PROG_IIR4_1, 0x0000001a }, >- { AUD_DN0_FREQ, 0x00000000 }, >- { AUD_DN1_FREQ, 0x00003318 }, >- { AUD_DN1_SRC_SEL, 0x00000017 }, >- { AUD_DN1_SHFT, 0x00000007 }, >- { AUD_DN1_AFC, 0x00000000 }, >- { AUD_DN1_FREQ_SHIFT, 0x00000000 }, >- { AUD_DN2_FREQ, 0x00003551 }, >- { AUD_DN2_SRC_SEL, 0x00000001 }, >- { AUD_DN2_SHFT, 0x00000000 }, >- { AUD_DN2_AFC, 0x00000002 }, >- { AUD_DN2_FREQ_SHIFT, 0x00000000 }, >- { AUD_PDET_SRC, 0x00000014 }, >- { AUD_PDET_SHIFT, 0x00000000 }, >- { AUD_DEEMPH0_SRC_SEL, 0x00000011 }, >- { AUD_DEEMPH1_SRC_SEL, 0x00000011 }, >- { AUD_DEEMPH0_SHIFT, 0x00000000 }, >- { AUD_DEEMPH1_SHIFT, 0x00000000 }, >- { AUD_DEEMPH0_G0, 0x00007000 }, >- { AUD_DEEMPH0_A0, 0x00000000 }, >- { AUD_DEEMPH0_B0, 0x00000000 }, >- { AUD_DEEMPH0_A1, 0x00000000 }, >- { AUD_DEEMPH0_B1, 0x00000000 }, >- { AUD_DEEMPH1_G0, 0x00007000 }, >- { AUD_DEEMPH1_A0, 0x00000000 }, >- { AUD_DEEMPH1_B0, 0x00000000 }, >- { AUD_DEEMPH1_A1, 0x00000000 }, >- { AUD_DEEMPH1_B1, 0x00000000 }, >- { AUD_DMD_RA_DDS, 0x00f5c285 }, >- { AUD_RATE_ADJ1, 0x00000100 }, >- { AUD_RATE_ADJ2, 0x00000200 }, >- { AUD_RATE_ADJ3, 0x00000300 }, >- { AUD_RATE_ADJ4, 0x00000400 }, >- { AUD_RATE_ADJ5, 0x00000500 }, >- { AUD_C2_UP_THR, 0x00005400 }, >- { AUD_C2_LO_THR, 0x00003000 }, >- { AUD_C1_UP_THR, 0x00007000 }, >- { AUD_C2_LO_THR, 0x00005400 }, >- { AUD_CTL, 0x0000100c }, >- { AUD_DCOC_0_SRC, 0x00000021 }, >- { AUD_DCOC_1_SRC, 0x00000003 }, >- { AUD_DCOC1_SHIFT, 0x00000000 }, >- { AUD_DCOC_1_SHIFT_IN0, 0x0000000a }, >- { AUD_DCOC_1_SHIFT_IN1, 0x00000008 }, >- { AUD_DCOC_PASS_IN, 0x00000000 }, >- { AUD_DCOC_2_SRC, 0x0000001b }, >- { AUD_IIR4_0_SEL, 0x0000001d }, >- { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 }, >- { AUD_PHASE_FIX_CTL, 0x00000000 }, >- { AUD_CORDIC_SHIFT_1, 0x00000007 }, >- { AUD_PLL_EN, 0x00000000 }, >- { AUD_PLL_PRESCALE, 0x00000002 }, >- { AUD_PLL_INT, 0x0000001e }, >- { AUD_OUT1_SHIFT, 0x00000000 }, >+ { AUD_PDF_DDS_CNST_BYTE2, 0x48 }, >+ { AUD_PDF_DDS_CNST_BYTE1, 0x3D }, >+ { AUD_QAM_MODE, 0x00 }, >+ { AUD_PDF_DDS_CNST_BYTE0, 0xf5 }, >+ { AUD_PHACC_FREQ_8MSB, 0x3a }, >+ { AUD_PHACC_FREQ_8LSB, 0x4a }, > >- { /* end of list */ }, >- }; >+ { AUD_DEEMPHGAIN_R, 0x6680 }, >+ { AUD_DEEMPHNUMER1_R, 0x353DE }, >+ { AUD_DEEMPHNUMER2_R, 0x1B1 }, >+ { AUD_DEEMPHDENOM1_R, 0x0F3D0 }, >+ { AUD_DEEMPHDENOM2_R, 0x0 }, >+ { AUD_FM_MODE_ENABLE, 0x7 }, >+ { AUD_POLYPH80SCALEFAC, 0x3 }, >+ { AUD_AFE_12DB_EN, 0x1 }, >+ { AAGC_GAIN, 0x0 }, >+ { AAGC_HYST, 0x18 }, >+ { AAGC_DEF, 0x20 }, >+ { AUD_DN0_FREQ, 0x0 }, >+ { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 }, >+ { AUD_DCOC_0_SRC, 0x21 }, >+ { AUD_IIR1_0_SEL, 0x0 }, >+ { AUD_IIR1_0_SHIFT, 0x7 }, >+ { AUD_IIR1_1_SEL, 0x2 }, >+ { AUD_IIR1_1_SHIFT, 0x0 }, >+ { AUD_DCOC_1_SRC, 0x3 }, >+ { AUD_DCOC1_SHIFT, 0x0 }, >+ { AUD_DCOC_PASS_IN, 0x0 }, >+ { AUD_IIR1_2_SEL, 0x23 }, >+ { AUD_IIR1_2_SHIFT, 0x0 }, >+ { AUD_IIR1_3_SEL, 0x4 }, >+ { AUD_IIR1_3_SHIFT, 0x7 }, >+ { AUD_IIR1_4_SEL, 0x5 }, >+ { AUD_IIR1_4_SHIFT, 0x7 }, >+ { AUD_IIR3_0_SEL, 0x7 }, >+ { AUD_IIR3_0_SHIFT, 0x0 }, >+ { AUD_DEEMPH0_SRC_SEL, 0x11 }, >+ { AUD_DEEMPH0_SHIFT, 0x0 }, >+ { AUD_DEEMPH0_G0, 0x7000 }, >+ { AUD_DEEMPH0_A0, 0x0 }, >+ { AUD_DEEMPH0_B0, 0x0 }, >+ { AUD_DEEMPH0_A1, 0x0 }, >+ { AUD_DEEMPH0_B1, 0x0 }, >+ { AUD_DEEMPH1_SRC_SEL, 0x11 }, >+ { AUD_DEEMPH1_SHIFT, 0x0 }, >+ { AUD_DEEMPH1_G0, 0x7000 }, >+ { AUD_DEEMPH1_A0, 0x0 }, >+ { AUD_DEEMPH1_B0, 0x0 }, >+ { AUD_DEEMPH1_A1, 0x0 }, >+ { AUD_DEEMPH1_B1, 0x0 }, >+ { AUD_OUT0_SEL, 0x3F }, >+ { AUD_OUT1_SEL, 0x3F }, >+ { AUD_DMD_RA_DDS, 0x0F5C285 }, >+ { AUD_PLL_INT, 0x1E }, >+ { AUD_PLL_DDS, 0x0 }, >+ { AUD_PLL_FRAC, 0x0E542 }, > >- dprintk("%s (status: unknown)\n",__FUNCTION__); >- set_audio_start(core, 0x0004, >- 0 /* FIXME */); >- set_audio_registers(core, nicam_l); >+ // setup QAM registers >+ { AUD_RATE_ADJ1, 0x00000100 }, >+ { AUD_RATE_ADJ2, 0x00000200 }, >+ { AUD_RATE_ADJ3, 0x00000300 }, >+ { AUD_RATE_ADJ4, 0x00000400 }, >+ { AUD_RATE_ADJ5, 0x00000500 }, >+ { AUD_RATE_THRES_DMD, 0x000000C0 }, >+ { /* end of list */ }, >+ }; >+ >+ static const struct rlist nicam_l[] = { >+ // setup QAM registers >+ { AUD_RATE_ADJ1, 0x00000060 }, >+ { AUD_RATE_ADJ2, 0x000000F9 }, >+ { AUD_RATE_ADJ3, 0x000001CC }, >+ { AUD_RATE_ADJ4, 0x000002B3 }, >+ { AUD_RATE_ADJ5, 0x00000726 }, >+ { AUD_DEEMPHDENOM1_R, 0x0000F3D0 }, >+ { AUD_DEEMPHDENOM2_R, 0x00000000 }, >+ { AUD_ERRLOGPERIOD_R, 0x00000064 }, >+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF }, >+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F }, >+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F }, >+ { AUD_POLYPH80SCALEFAC, 0x00000003 }, >+ { AUD_DMD_RA_DDS, 0x00C00000 }, >+ { AUD_PLL_INT, 0x0000001E }, >+ { AUD_PLL_DDS, 0x00000000 }, >+ { AUD_PLL_FRAC, 0x0000E542 }, >+ { AUD_START_TIMER, 0x00000000 }, >+ { AUD_DEEMPHNUMER1_R, 0x000353DE }, >+ { AUD_DEEMPHNUMER2_R, 0x000001B1 }, >+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 }, >+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 }, >+ { AUD_QAM_MODE, 0x05 }, >+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 }, >+ { AUD_PHACC_FREQ_8MSB, 0x34 }, >+ { AUD_PHACC_FREQ_8LSB, 0x4C }, >+ { AUD_DEEMPHGAIN_R, 0x00006680 }, >+ { AUD_RATE_THRES_DMD, 0x000000C0 }, >+ { /* end of list */ }, >+ } ; >+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo); >+ >+ if (!stereo) { >+ /* AM mono sound */ >+ set_audio_start(core, 0x0004, >+ 0x100c /* FIXME again */); >+ set_audio_registers(core, nicam_l_mono); >+ } else { >+ set_audio_start(core, 0x0010, >+ 0x1924 /* FIXME again */); >+ set_audio_registers(core, nicam_l); >+ } >+ set_audio_finish(core); >+ >+} >+ >+static void set_audio_standard_PAL_I(struct cx88_core *core, int stereo) >+{ >+ static const struct rlist pal_i_fm_mono[] = { >+ {AUD_ERRLOGPERIOD_R, 0x00000064}, >+ {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, >+ {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, >+ {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, >+ {AUD_PDF_DDS_CNST_BYTE2, 0x06}, >+ {AUD_PDF_DDS_CNST_BYTE1, 0x82}, >+ {AUD_PDF_DDS_CNST_BYTE0, 0x12}, >+ {AUD_QAM_MODE, 0x05}, >+ {AUD_PHACC_FREQ_8MSB, 0x3a}, >+ {AUD_PHACC_FREQ_8LSB, 0x93}, >+ {AUD_DMD_RA_DDS, 0x002a4f2f}, >+ {AUD_PLL_INT, 0x0000001e}, >+ {AUD_PLL_DDS, 0x00000004}, >+ {AUD_PLL_FRAC, 0x0000e542}, >+ {AUD_RATE_ADJ1, 0x00000100}, >+ {AUD_RATE_ADJ2, 0x00000200}, >+ {AUD_RATE_ADJ3, 0x00000300}, >+ {AUD_RATE_ADJ4, 0x00000400}, >+ {AUD_RATE_ADJ5, 0x00000500}, >+ {AUD_THR_FR, 0x00000000}, >+ {AUD_PILOT_BQD_1_K0, 0x0000755b}, >+ {AUD_PILOT_BQD_1_K1, 0x00551340}, >+ {AUD_PILOT_BQD_1_K2, 0x006d30be}, >+ {AUD_PILOT_BQD_1_K3, 0xffd394af}, >+ {AUD_PILOT_BQD_1_K4, 0x00400000}, >+ {AUD_PILOT_BQD_2_K0, 0x00040000}, >+ {AUD_PILOT_BQD_2_K1, 0x002a4841}, >+ {AUD_PILOT_BQD_2_K2, 0x00400000}, >+ {AUD_PILOT_BQD_2_K3, 0x00000000}, >+ {AUD_PILOT_BQD_2_K4, 0x00000000}, >+ {AUD_MODE_CHG_TIMER, 0x00000060}, >+ {AUD_AFE_12DB_EN, 0x00000001}, >+ {AAGC_HYST, 0x0000000a}, >+ {AUD_CORDIC_SHIFT_0, 0x00000007}, >+ {AUD_CORDIC_SHIFT_1, 0x00000007}, >+ {AUD_C1_UP_THR, 0x00007000}, >+ {AUD_C1_LO_THR, 0x00005400}, >+ {AUD_C2_UP_THR, 0x00005400}, >+ {AUD_C2_LO_THR, 0x00003000}, >+ {AUD_DCOC_0_SRC, 0x0000001a}, >+ {AUD_DCOC0_SHIFT, 0x00000000}, >+ {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, >+ {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, >+ {AUD_DCOC_PASS_IN, 0x00000003}, >+ {AUD_IIR3_0_SEL, 0x00000021}, >+ {AUD_DN2_AFC, 0x00000002}, >+ {AUD_DCOC_1_SRC, 0x0000001b}, >+ {AUD_DCOC1_SHIFT, 0x00000000}, >+ {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, >+ {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, >+ {AUD_IIR3_1_SEL, 0x00000023}, >+ {AUD_DN0_FREQ, 0x000035a3}, >+ {AUD_DN2_FREQ, 0x000029c7}, >+ {AUD_CRDC0_SRC_SEL, 0x00000511}, >+ {AUD_IIR1_0_SEL, 0x00000001}, >+ {AUD_IIR1_1_SEL, 0x00000000}, >+ {AUD_IIR3_2_SEL, 0x00000003}, >+ {AUD_IIR3_2_SHIFT, 0x00000000}, >+ {AUD_IIR3_0_SEL, 0x00000002}, >+ {AUD_IIR2_0_SEL, 0x00000021}, >+ {AUD_IIR2_0_SHIFT, 0x00000002}, >+ {AUD_DEEMPH0_SRC_SEL, 0x0000000b}, >+ {AUD_DEEMPH1_SRC_SEL, 0x0000000b}, >+ {AUD_POLYPH80SCALEFAC, 0x00000001}, >+ {AUD_START_TIMER, 0x00000000}, >+ { /* end of list */ }, >+ }; >+ >+ static const struct rlist pal_i_nicam[] = { >+ { AUD_RATE_ADJ1, 0x00000010 }, >+ { AUD_RATE_ADJ2, 0x00000040 }, >+ { AUD_RATE_ADJ3, 0x00000100 }, >+ { AUD_RATE_ADJ4, 0x00000400 }, >+ { AUD_RATE_ADJ5, 0x00001000 }, >+ // { AUD_DMD_RA_DDS, 0x00c0d5ce }, >+ { AUD_DEEMPHGAIN_R, 0x000023c2 }, >+ { AUD_DEEMPHNUMER1_R, 0x0002a7bc }, >+ { AUD_DEEMPHNUMER2_R, 0x0003023e }, >+ { AUD_DEEMPHDENOM1_R, 0x0000f3d0 }, >+ { AUD_DEEMPHDENOM2_R, 0x00000000 }, >+ { AUD_DEEMPHDENOM2_R, 0x00000000 }, >+ { AUD_ERRLOGPERIOD_R, 0x00000fff }, >+ { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff }, >+ { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff }, >+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f }, >+ { AUD_POLYPH80SCALEFAC, 0x00000003 }, >+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 }, >+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 }, >+ { AUD_PDF_DDS_CNST_BYTE0, 0x16 }, >+ { AUD_QAM_MODE, 0x05 }, >+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 }, >+ { AUD_PHACC_FREQ_8MSB, 0x3a }, >+ { AUD_PHACC_FREQ_8LSB, 0x93 }, >+ { /* end of list */ }, >+ }; >+ >+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo); >+ >+ if (!stereo) { >+ // FM mono >+ set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1); >+ set_audio_registers(core, pal_i_fm_mono); >+ } else { >+ // Nicam Stereo >+ set_audio_start(core, 0x0010, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO); >+ set_audio_registers(core, pal_i_nicam); >+ } > set_audio_finish(core); > } > >@@ -553,13 +677,6 @@ static void set_audio_standard_A2(struct > set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO); > set_audio_registers(core, a2_common); > switch (core->tvaudio) { >- case WW_NICAM_I: >- /* gives at least mono according to the dscaler guys */ >- /* so use use that while nicam is broken ... */ >- dprintk("%s PAL-I mono (status: unknown)\n",__FUNCTION__); >- set_audio_registers(core, a2_table1); >- cx_write(AUD_CTL, EN_A2_FORCE_MONO1); >- break; > case WW_A2_BG: > dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__); > set_audio_registers(core, a2_table1); >@@ -646,11 +763,12 @@ void cx88_set_tvaudio(struct cx88_core * > case WW_BTSC: > set_audio_standard_BTSC(core,0); > break; >- // case WW_NICAM_I: > case WW_NICAM_BGDKL: >- set_audio_standard_NICAM(core); >+ set_audio_standard_NICAM_L(core,0); > break; > case WW_NICAM_I: >+ set_audio_standard_PAL_I(core,0); >+ break; > case WW_A2_BG: > case WW_A2_DK: > case WW_A2_M: >@@ -663,7 +781,7 @@ void cx88_set_tvaudio(struct cx88_core * > set_audio_standard_FM(core); > break; > case WW_SYSTEM_L_AM: >- set_audio_standard_NICAM_L(core); >+ set_audio_standard_NICAM_L(core, 1); > break; > case WW_NONE: > default: >@@ -674,6 +792,19 @@ void cx88_set_tvaudio(struct cx88_core * > return; > } > >+void cx88_newstation(struct cx88_core *core) >+{ >+ core->audiomode_manual = UNSET; >+ >+ switch (core->tvaudio) { >+ case WW_SYSTEM_L_AM: >+ /* try nicam ... */ >+ core->audiomode_current = V4L2_TUNER_MODE_STEREO; >+ set_audio_standard_NICAM_L(core, 1); >+ break; >+ } >+} >+ > void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) > { > static char *m[] = {"stereo", "dual mono", "mono", "sap"}; >@@ -721,22 +852,37 @@ void cx88_get_stereo(struct cx88_core *c > } > break; > case WW_NICAM_BGDKL: >- if (0 == mode) >+ if (0 == mode) { > t->audmode = V4L2_TUNER_MODE_STEREO; >+ t->rxsubchans |= V4L2_TUNER_SUB_STEREO; >+ } > break; >+ case WW_SYSTEM_L_AM: >+ if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) { >+ t->audmode = V4L2_TUNER_MODE_STEREO; >+ t->rxsubchans |= V4L2_TUNER_SUB_STEREO; >+ } >+ break ; > default: >- t->rxsubchans = V4L2_TUNER_SUB_MONO; >- t->audmode = V4L2_TUNER_MODE_MONO; >+ /* nothing */ > break; > } > return; > } > >-void cx88_set_stereo(struct cx88_core *core, u32 mode) >+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) > { > u32 ctl = UNSET; > u32 mask = UNSET; > >+ if (manual) { >+ core->audiomode_manual = mode; >+ } else { >+ if (UNSET != core->audiomode_manual) >+ return; >+ } >+ core->audiomode_current = mode; >+ > switch (core->tvaudio) { > case WW_BTSC: > switch (mode) { >@@ -789,6 +935,28 @@ void cx88_set_stereo(struct cx88_core *c > break; > } > break; >+ case WW_SYSTEM_L_AM: >+ switch (mode) { >+ case V4L2_TUNER_MODE_MONO: >+ case V4L2_TUNER_MODE_LANG1: /* FIXME */ >+ set_audio_standard_NICAM_L(core, 0); >+ break; >+ case V4L2_TUNER_MODE_STEREO: >+ set_audio_standard_NICAM_L(core, 1); >+ break; >+ } >+ break; >+ case WW_NICAM_I: >+ switch (mode) { >+ case V4L2_TUNER_MODE_MONO: >+ case V4L2_TUNER_MODE_LANG1: >+ set_audio_standard_PAL_I(core, 0); >+ break; >+ case V4L2_TUNER_MODE_STEREO: >+ set_audio_standard_PAL_I(core, 1); >+ break; >+ } >+ break; > case WW_FM: > switch (mode) { > case V4L2_TUNER_MODE_MONO: >@@ -804,13 +972,11 @@ void cx88_set_stereo(struct cx88_core *c > } > > if (UNSET != ctl) { >- cx_write(AUD_SOFT_RESET, 0x0001); >- cx_andor(AUD_CTL, mask, ctl); >- cx_write(AUD_SOFT_RESET, 0x0000); > dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x " > "[status=0x%x,ctl=0x%x,vol=0x%x]\n", > mask, ctl, cx_read(AUD_STATUS), > cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL)); >+ cx_andor(AUD_CTL, mask, ctl); > } > return; > } >@@ -819,16 +985,32 @@ int cx88_audio_thread(void *data) > { > struct cx88_core *core = data; > struct v4l2_tuner t; >+ u32 mode = 0; > > dprintk("cx88: tvaudio thread started\n"); > for (;;) { >+ msleep_interruptible(1000); > if (kthread_should_stop()) > break; > > /* just monitor the audio status for now ... */ > memset(&t,0,sizeof(t)); > cx88_get_stereo(core,&t); >- msleep_interruptible(1000); >+ >+ if (UNSET != core->audiomode_manual) >+ /* manually set, don't do anything. */ >+ continue; >+ >+ /* monitor signal */ >+ if (t.rxsubchans & V4L2_TUNER_SUB_STEREO) >+ mode = V4L2_TUNER_MODE_STEREO; >+ else >+ mode = V4L2_TUNER_MODE_MONO; >+ if (mode == core->audiomode_current) >+ continue; >+ >+ /* automatically switch to best available mode */ >+ cx88_set_stereo(core, mode, 0); > } > > dprintk("cx88: tvaudio thread exiting\n"); >@@ -838,6 +1020,7 @@ int cx88_audio_thread(void *data) > /* ----------------------------------------------------------- */ > > EXPORT_SYMBOL(cx88_set_tvaudio); >+EXPORT_SYMBOL(cx88_newstation); > EXPORT_SYMBOL(cx88_set_stereo); > EXPORT_SYMBOL(cx88_get_stereo); > EXPORT_SYMBOL(cx88_audio_thread); >Index: linux-2.6.11/drivers/media/video/cx88/cx88-vbi.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-vbi.c 2005-03-07 10:13:49.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-vbi.c 2005-03-08 10:33:15.000000000 +0100 >@@ -1,8 +1,9 @@ > /* >- * $Id: cx88-vbi.c,v 1.14 2004/11/07 13:17:15 kraxel Exp $ >+ * $Id: cx88-vbi.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $ > */ > #include <linux/kernel.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/init.h> > #include <linux/slab.h> > >@@ -64,7 +65,7 @@ int cx8800_start_vbi_dma(struct cx8800_d > q->count = 1; > > /* enable irqs */ >- cx_set(MO_PCI_INTMSK, 0x00fc01); >+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01); > cx_set(MO_VID_INTMSK, 0x0f0088); > > /* enable capture */ >Index: linux-2.6.11/drivers/media/video/cx88/cx88-video.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-video.c 2005-03-07 10:14:10.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88-video.c 2005-03-08 10:33:20.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: cx88-video.c,v 1.46 2004/11/07 14:44:59 kraxel Exp $ >+ * $Id: cx88-video.c,v 1.58 2005/03/07 15:58:05 kraxel Exp $ > * > * device driver for Conexant 2388x based TV cards > * video4linux video interface >@@ -24,6 +24,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kmod.h> > #include <linux/kernel.h> > #include <linux/slab.h> >@@ -428,7 +429,7 @@ static int start_video_dma(struct cx8800 > q->count = 1; > > /* enable irqs */ >- cx_set(MO_PCI_INTMSK, 0x00fc01); >+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01); > cx_set(MO_VID_INTMSK, 0x0f0011); > > /* enable capture */ >@@ -994,7 +995,7 @@ static int video_open(struct inode *inod > cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); > dev->core->tvaudio = WW_FM; > cx88_set_tvaudio(core); >- cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO); >+ cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); > cx88_call_i2c_clients(dev->core,AUDC_SET_RADIO,NULL); > } > >@@ -1002,7 +1003,7 @@ static int video_open(struct inode *inod > } > > static ssize_t >-video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) >+video_read(struct file *file, char *data, size_t count, loff_t *ppos) > { > struct cx8800_fh *fh = file->private_data; > >@@ -1083,6 +1084,8 @@ static int video_release(struct inode *i > res_free(dev,fh,RESOURCE_VBI); > } > >+ videobuf_mmap_free(&fh->vidq); >+ videobuf_mmap_free(&fh->vbiq); > file->private_data = NULL; > kfree(fh); > return 0; >@@ -1338,7 +1341,6 @@ static int video_do_ioctl(struct inode * > 0; > if (UNSET != core->tuner_type) > cap->capabilities |= V4L2_CAP_TUNER; >- > return 0; > } > >@@ -1429,6 +1431,7 @@ static int video_do_ioctl(struct inode * > if (*i >= 4) > return -EINVAL; > down(&dev->lock); >+ cx88_newstation(core); > video_mux(dev,*i); > up(&dev->lock); > return 0; >@@ -1560,7 +1563,7 @@ static int video_do_ioctl(struct inode * > return -EINVAL; > if (0 != t->index) > return -EINVAL; >- cx88_set_stereo(core, t->audmode); >+ cx88_set_stereo(core, t->audmode, 1); > return 0; > } > case VIDIOC_G_FREQUENCY: >@@ -1590,6 +1593,7 @@ static int video_do_ioctl(struct inode * > return -EINVAL; > down(&dev->lock); > dev->freq = f->frequency; >+ cx88_newstation(core); > #ifdef V4L2_I2C_CLIENTS > cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f); > #else >@@ -1880,19 +1884,18 @@ static irqreturn_t cx8800_irq(int irq, v > { > struct cx8800_dev *dev = dev_id; > struct cx88_core *core = dev->core; >- u32 status, mask; >+ u32 status; > int loop, handled = 0; > > for (loop = 0; loop < 10; loop++) { >- status = cx_read(MO_PCI_INTSTAT) & (~0x1f | 0x01); >- mask = cx_read(MO_PCI_INTMSK); >- if (0 == (status & mask)) >+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x01); >+ if (0 == status) > goto out; > cx_write(MO_PCI_INTSTAT, status); > handled = 1; > >- if (status & mask & ~0x1f) >- cx88_irq(core,status,mask); >+ if (status & core->pci_irqmask) >+ cx88_core_irq(core,status); > if (status & 0x01) > cx8800_vid_irq(dev); > }; >@@ -2055,6 +2058,7 @@ static int __devinit cx8800_initdev(stru > core->name,pci_dev->irq); > goto fail_core; > } >+ cx_set(MO_PCI_INTMSK, core->pci_irqmask); > > /* load and configure helper modules */ > if (TUNER_ABSENT != core->tuner_type) >@@ -2156,7 +2160,7 @@ static void __devexit cx8800_finidev(str > kfree(dev); > } > >-static int cx8800_suspend(struct pci_dev *pci_dev, u32 state) >+static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) > { > struct cx8800_dev *dev = pci_get_drvdata(pci_dev); > struct cx88_core *core = dev->core; >@@ -2181,7 +2185,7 @@ static int cx8800_suspend(struct pci_dev > #endif > > pci_save_state(pci_dev); >- if (0 != pci_set_power_state(pci_dev, state)) { >+ if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) { > pci_disable_device(pci_dev); > dev->state.disabled = 1; > } >@@ -2197,7 +2201,7 @@ static int cx8800_resume(struct pci_dev > pci_enable_device(pci_dev); > dev->state.disabled = 0; > } >- pci_set_power_state(pci_dev, 0); >+ pci_set_power_state(pci_dev, PCI_D0); > pci_restore_state(pci_dev); > > #if 1 >@@ -2254,7 +2258,7 @@ static int cx8800_init(void) > printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", > SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); > #endif >- return pci_module_init(&cx8800_pci_driver); >+ return pci_register_driver(&cx8800_pci_driver); > } > > static void cx8800_fini(void) >Index: linux-2.6.11/drivers/media/video/cx88/cx88.h >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/cx88/cx88.h 2005-03-07 10:15:48.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/cx88/cx88.h 2005-03-08 10:33:15.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: cx88.h,v 1.40 2004/11/03 09:04:51 kraxel Exp $ >+ * $Id: cx88.h,v 1.56 2005/03/04 09:12:23 kraxel Exp $ > * > * v4l2 device driver for cx2388x based TV cards > * >@@ -27,6 +27,7 @@ > #include <linux/kdev_t.h> > > #include <media/tuner.h> >+#include <media/tveeprom.h> > #include <media/audiochip.h> > #include <media/video-buf.h> > #include <media/video-buf-dvb.h> >@@ -139,7 +140,7 @@ extern struct sram_channel cx88_sram_cha > #define CX88_BOARD_GDI 2 > #define CX88_BOARD_PIXELVIEW 3 > #define CX88_BOARD_ATI_WONDER_PRO 4 >-#define CX88_BOARD_WINFAST2000XP 5 >+#define CX88_BOARD_WINFAST2000XP_EXPERT 5 > #define CX88_BOARD_AVERTV_303 6 > #define CX88_BOARD_MSI_TVANYWHERE_MASTER 7 > #define CX88_BOARD_WINFAST_DV2000 8 >@@ -156,6 +157,11 @@ extern struct sram_channel cx88_sram_cha > #define CX88_BOARD_CONEXANT_DVB_T1 19 > #define CX88_BOARD_PROVIDEO_PV259 20 > #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21 >+#define CX88_BOARD_PCHDTV_HD3000 22 >+#define CX88_BOARD_DNTV_LIVE_DVB_T 23 >+#define CX88_BOARD_HAUPPAUGE_ROSLYN 24 >+#define CX88_BOARD_DIGITALLOGIC_MEC 25 >+#define CX88_BOARD_IODATA_GVBCTV7E 26 > > enum cx88_itype { > CX88_VMUX_COMPOSITE1 = 1, >@@ -238,6 +244,7 @@ struct cx88_core { > u32 __iomem *lmmio; > u8 __iomem *bmmio; > u32 shadow[SHADOW_MAX]; >+ int pci_irqmask; > > /* i2c i/o */ > struct i2c_adapter i2c_adap; >@@ -252,16 +259,20 @@ struct cx88_core { > unsigned int has_radio; > > /* config info -- dvb */ >- unsigned int pll_type; >+ struct dvb_pll_desc *pll_desc; > unsigned int pll_addr; >- unsigned int demod_addr; > > /* state info */ > struct task_struct *kthread; > struct cx88_tvnorm *tvnorm; > u32 tvaudio; >+ u32 audiomode_manual; >+ u32 audiomode_current; > u32 input; > u32 astat; >+ >+ /* IR remote control state */ >+ struct cx88_IR *ir; > }; > > struct cx8800_dev; >@@ -371,11 +382,16 @@ struct cx8802_dev { > struct list_head devlist; > struct video_device *mpeg_dev; > u32 mailbox; >+ int width; >+ int height; > > /* for dvb only */ > struct videobuf_dvb dvb; > void* fe_handle; > int (*fe_release)(void *handle); >+ >+ /* for switching modulation types */ >+ unsigned char ts_gen_cntrl; > }; > > /* ----------------------------------------------------------- */ >@@ -411,7 +427,7 @@ extern void cx88_print_irqbits(char *nam > u32 bits, u32 mask); > extern void cx88_print_ioctl(char *name, unsigned int cmd); > >-extern void cx88_irq(struct cx88_core *core, u32 status, u32 mask); >+extern int cx88_core_irq(struct cx88_core *core, u32 status); > extern void cx88_wakeup(struct cx88_core *core, > struct cx88_dmaqueue *q, u32 count); > extern void cx88_shutdown(struct cx88_core *core); >@@ -503,11 +519,19 @@ extern void cx88_card_setup(struct cx88_ > #define WW_FM 12 > > void cx88_set_tvaudio(struct cx88_core *core); >+void cx88_newstation(struct cx88_core *core); > void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); >-void cx88_set_stereo(struct cx88_core *core, u32 mode); >+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); > int cx88_audio_thread(void *data); > > /* ----------------------------------------------------------- */ >+/* cx88-input.c */ >+ >+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci); >+int cx88_ir_fini(struct cx88_core *core); >+void cx88_ir_irq(struct cx88_core *core); >+ >+/* ----------------------------------------------------------- */ > /* cx88-mpeg.c */ > > int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf); >@@ -517,7 +541,7 @@ void cx8802_cancel_buffers(struct cx8802 > int cx8802_init_common(struct cx8802_dev *dev); > void cx8802_fini_common(struct cx8802_dev *dev); > >-int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state); >+int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state); > int cx8802_resume_common(struct pci_dev *pci_dev); > > /* >Index: linux-2.6.11/drivers/media/video/ir-kbd-gpio.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/ir-kbd-gpio.c 2005-03-07 10:14:58.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/ir-kbd-gpio.c 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: ir-kbd-gpio.c,v 1.11 2004/10/25 11:26:36 kraxel Exp $ >+ * $Id: ir-kbd-gpio.c,v 1.12 2005/02/22 12:28:40 kraxel Exp $ > * > * Copyright (c) 2003 Gerd Knorr > * Copyright (c) 2003 Pavel Machek >@@ -114,51 +114,6 @@ static IR_KEYTAB_TYPE ir_codes_avermedia > [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' > }; > >-static IR_KEYTAB_TYPE winfast_codes[IR_KEYTAB_SIZE] = { >- [ 5 ] = KEY_KP1, >- [ 6 ] = KEY_KP2, >- [ 7 ] = KEY_KP3, >- [ 9 ] = KEY_KP4, >- [ 10 ] = KEY_KP5, >- [ 11 ] = KEY_KP6, >- [ 13 ] = KEY_KP7, >- [ 14 ] = KEY_KP8, >- [ 15 ] = KEY_KP9, >- [ 18 ] = KEY_KP0, >- >- [ 0 ] = KEY_POWER, >-// [ 27 ] = MTS button >- [ 2 ] = KEY_TUNER, // TV/FM >- [ 30 ] = KEY_VIDEO, >-// [ 22 ] = display button >- [ 4 ] = KEY_VOLUMEUP, >- [ 8 ] = KEY_VOLUMEDOWN, >- [ 12 ] = KEY_CHANNELUP, >- [ 16 ] = KEY_CHANNELDOWN, >- [ 3 ] = KEY_ZOOM, // fullscreen >- [ 31 ] = KEY_SUBTITLE, // closed caption/teletext >- [ 32 ] = KEY_SLEEP, >-// [ 41 ] = boss key >- [ 20 ] = KEY_MUTE, >- [ 43 ] = KEY_RED, >- [ 44 ] = KEY_GREEN, >- [ 45 ] = KEY_YELLOW, >- [ 46 ] = KEY_BLUE, >- [ 24 ] = KEY_KPPLUS, //fine tune + >- [ 25 ] = KEY_KPMINUS, //fine tune - >-// [ 42 ] = picture in picture >- [ 33 ] = KEY_KPDOT, >- [ 19 ] = KEY_KPENTER, >-// [ 17 ] = recall >- [ 34 ] = KEY_BACK, >- [ 35 ] = KEY_PLAYPAUSE, >- [ 36 ] = KEY_NEXT, >-// [ 37 ] = time shifting >- [ 38 ] = KEY_STOP, >- [ 39 ] = KEY_RECORD >-// [ 40 ] = snapshot >-}; >- > static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { > [ 2 ] = KEY_KP0, > [ 1 ] = KEY_KP1, >@@ -388,12 +343,12 @@ static int ir_probe(struct device *dev) > break; > > case BTTV_WINFAST2000: >- ir_codes = winfast_codes; >+ ir_codes = ir_codes_winfast; > ir->mask_keycode = 0x1f8; > break; > case BTTV_MAGICTVIEW061: > case BTTV_MAGICTVIEW063: >- ir_codes = winfast_codes; >+ ir_codes = ir_codes_winfast; > ir->mask_keycode = 0x0008e000; > ir->mask_keydown = 0x00200000; > break; >Index: linux-2.6.11/drivers/media/video/msp3400.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/msp3400.c 2005-03-07 10:14:23.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/msp3400.c 2005-03-07 18:13:02.000000000 +0100 >@@ -380,7 +380,9 @@ static void msp3400c_setvolume(struct i2 > int val = 0, bal = 0; > > if (!muted) { >- val = (volume * 0x7F / 65535) << 8; >+ /* 0x7f instead if 0x73 here has sound quality issues, >+ * probably due to overmodulation + clipping ... */ >+ val = (volume * 0x73 / 65535) << 8; > } > if (val) { > bal = (balance / 256) - 128; >@@ -993,7 +995,13 @@ static int msp34xx_modus(int norm) > { > switch (norm) { > case VIDEO_MODE_PAL: >+#if 1 >+ /* experimental: not sure this works with all chip versions */ >+ return 0x7003; >+#else >+ /* previous value, try this if it breaks ... */ > return 0x1003; >+#endif > case VIDEO_MODE_NTSC: /* BTSC */ > return 0x2003; > case VIDEO_MODE_SECAM: >@@ -1260,6 +1268,7 @@ static int msp34xxg_thread(void *data) > int val, std, i; > > printk("msp34xxg: daemon started\n"); >+ msp->source = 1; /* default */ > for (;;) { > d2printk(KERN_DEBUG "msp34xxg: thread: sleep\n"); > msp34xx_sleep(msp,-1); >@@ -1330,8 +1339,9 @@ static void msp34xxg_set_source(struct i > > /* fix matrix mode to stereo and let the msp choose what > * to output according to 'source', as recommended >+ * for MONO (source==0) downmixing set bit[7:0] to 0x30 > */ >- int value = (source&0x07)<<8|(source==0 ? 0x00:0x20); >+ int value = (source&0x07)<<8|(source==0 ? 0x30:0x20); > dprintk("msp34xxg: set source to %d (0x%x)\n", source, value); > msp3400c_write(client, > I2C_MSP3400C_DFP, >@@ -1355,7 +1365,7 @@ static void msp34xxg_set_source(struct i > msp3400c_write(client, > I2C_MSP3400C_DEM, > 0x22, /* a2 threshold for stereo/bilingual */ >- source==0 ? 0x7f0:stereo_threshold); >+ stereo_threshold); > msp->source=source; > } > >@@ -1390,7 +1400,7 @@ static void msp34xxg_detect_stereo(struc > static void msp34xxg_set_audmode(struct i2c_client *client, int audmode) > { > struct msp3400c *msp = i2c_get_clientdata(client); >- int source = 0; >+ int source; > > switch (audmode) { > case V4L2_TUNER_MODE_MONO: >@@ -1406,9 +1416,10 @@ static void msp34xxg_set_audmode(struct > case V4L2_TUNER_MODE_LANG2: > source=4; /* stereo or B */ > break; >- default: /* doing nothing: a safe, sane default */ >+ default: > audmode = 0; >- return; >+ source = 1; >+ break; > } > msp->audmode = audmode; > msp34xxg_set_source(client, source); >@@ -1510,12 +1521,9 @@ static int msp_attach(struct i2c_adapter > > msp->opmode = opmode; > if (OPMODE_AUTO == msp->opmode) { >-#if 0 /* seems to work for ivtv only, disable by default for now ... */ > if (HAVE_SIMPLER(msp)) > msp->opmode = OPMODE_SIMPLER; >- else >-#endif >- if (HAVE_SIMPLE(msp)) >+ else if (HAVE_SIMPLE(msp)) > msp->opmode = OPMODE_SIMPLE; > else > msp->opmode = OPMODE_MANUAL; >Index: linux-2.6.11/drivers/media/video/mt20xx.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/media/video/mt20xx.c 2005-03-07 18:13:02.000000000 +0100 >@@ -0,0 +1,558 @@ >+/* >+ * $Id: mt20xx.c,v 1.4 2005/03/04 09:24:56 kraxel Exp $ >+ * >+ * i2c tv tuner chip device driver >+ * controls microtune tuners, mt2032 + mt2050 at the moment. >+ */ >+#include <linux/delay.h> >+#include <linux/i2c.h> >+#include <linux/videodev.h> >+#include <linux/moduleparam.h> >+#include <media/tuner.h> >+ >+/* ---------------------------------------------------------------------- */ >+ >+static unsigned int optimize_vco = 1; >+module_param(optimize_vco, int, 0644); >+ >+static unsigned int tv_antenna = 1; >+module_param(tv_antenna, int, 0644); >+ >+static unsigned int radio_antenna = 0; >+module_param(radio_antenna, int, 0644); >+ >+/* ---------------------------------------------------------------------- */ >+ >+#define MT2032 0x04 >+#define MT2030 0x06 >+#define MT2040 0x07 >+#define MT2050 0x42 >+ >+static char *microtune_part[] = { >+ [ MT2030 ] = "MT2030", >+ [ MT2032 ] = "MT2032", >+ [ MT2040 ] = "MT2040", >+ [ MT2050 ] = "MT2050", >+}; >+ >+// IsSpurInBand()? >+static int mt2032_spurcheck(struct i2c_client *c, >+ int f1, int f2, int spectrum_from,int spectrum_to) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ int n1=1,n2,f; >+ >+ f1=f1/1000; //scale to kHz to avoid 32bit overflows >+ f2=f2/1000; >+ spectrum_from/=1000; >+ spectrum_to/=1000; >+ >+ tuner_dbg("spurcheck f1=%d f2=%d from=%d to=%d\n", >+ f1,f2,spectrum_from,spectrum_to); >+ >+ do { >+ n2=-n1; >+ f=n1*(f1-f2); >+ do { >+ n2--; >+ f=f-f2; >+ tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f); >+ >+ if( (f>spectrum_from) && (f<spectrum_to)) >+ tuner_dbg("mt2032 spurcheck triggered: %d\n",n1); >+ } while ( (f>(f2-spectrum_to)) || (n2>-5)); >+ n1++; >+ } while (n1<5); >+ >+ return 1; >+} >+ >+static int mt2032_compute_freq(struct i2c_client *c, >+ unsigned int rfin, >+ unsigned int if1, unsigned int if2, >+ unsigned int spectrum_from, >+ unsigned int spectrum_to, >+ unsigned char *buf, >+ int *ret_sel, >+ unsigned int xogc) //all in Hz >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, >+ desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; >+ >+ fref= 5250 *1000; //5.25MHz >+ desired_lo1=rfin+if1; >+ >+ lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000); >+ lo1n=lo1/8; >+ lo1a=lo1-(lo1n*8); >+ >+ s=rfin/1000/1000+1090; >+ >+ if(optimize_vco) { >+ if(s>1890) sel=0; >+ else if(s>1720) sel=1; >+ else if(s>1530) sel=2; >+ else if(s>1370) sel=3; >+ else sel=4; // >1090 >+ } >+ else { >+ if(s>1790) sel=0; // <1958 >+ else if(s>1617) sel=1; >+ else if(s>1449) sel=2; >+ else if(s>1291) sel=3; >+ else sel=4; // >1090 >+ } >+ *ret_sel=sel; >+ >+ lo1freq=(lo1a+8*lo1n)*fref; >+ >+ tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n", >+ rfin,lo1,lo1n,lo1a,sel,lo1freq); >+ >+ desired_lo2=lo1freq-rfin-if2; >+ lo2=(desired_lo2)/fref; >+ lo2n=lo2/8; >+ lo2a=lo2-(lo2n*8); >+ lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith >+ lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; >+ >+ tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n", >+ rfin,lo2,lo2n,lo2a,lo2num,lo2freq); >+ >+ if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { >+ tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n", >+ lo1a, lo1n, lo2a,lo2n); >+ return(-1); >+ } >+ >+ mt2032_spurcheck(c, lo1freq, desired_lo2, spectrum_from, spectrum_to); >+ // should recalculate lo1 (one step up/down) >+ >+ // set up MT2032 register map for transfer over i2c >+ buf[0]=lo1n-1; >+ buf[1]=lo1a | (sel<<4); >+ buf[2]=0x86; // LOGC >+ buf[3]=0x0f; //reserved >+ buf[4]=0x1f; >+ buf[5]=(lo2n-1) | (lo2a<<5); >+ if(rfin >400*1000*1000) >+ buf[6]=0xe4; >+ else >+ buf[6]=0xf4; // set PKEN per rev 1.2 >+ buf[7]=8+xogc; >+ buf[8]=0xc3; //reserved >+ buf[9]=0x4e; //reserved >+ buf[10]=0xec; //reserved >+ buf[11]=(lo2num&0xff); >+ buf[12]=(lo2num>>8) |0x80; // Lo2RST >+ >+ return 0; >+} >+ >+static int mt2032_check_lo_lock(struct i2c_client *c) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ int try,lock=0; >+ unsigned char buf[2]; >+ >+ for(try=0;try<10;try++) { >+ buf[0]=0x0e; >+ i2c_master_send(c,buf,1); >+ i2c_master_recv(c,buf,1); >+ tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]); >+ lock=buf[0] &0x06; >+ >+ if (lock==6) >+ break; >+ >+ tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); >+ udelay(1000); >+ } >+ return lock; >+} >+ >+static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ unsigned char buf[2]; >+ int tad1; >+ >+ buf[0]=0x0f; >+ i2c_master_send(c,buf,1); >+ i2c_master_recv(c,buf,1); >+ tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]); >+ tad1=buf[0]&0x07; >+ >+ if(tad1 ==0) return lock; >+ if(tad1 ==1) return lock; >+ >+ if(tad1==2) { >+ if(sel==0) >+ return lock; >+ else sel--; >+ } >+ else { >+ if(sel<4) >+ sel++; >+ else >+ return lock; >+ } >+ >+ tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel); >+ >+ buf[0]=0x0f; >+ buf[1]=sel; >+ i2c_master_send(c,buf,2); >+ lock=mt2032_check_lo_lock(c); >+ return lock; >+} >+ >+ >+static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, >+ unsigned int if1, unsigned int if2, >+ unsigned int from, unsigned int to) >+{ >+ unsigned char buf[21]; >+ int lint_try,ret,sel,lock=0; >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", >+ rfin,if1,if2,from,to); >+ >+ buf[0]=0; >+ ret=i2c_master_send(c,buf,1); >+ i2c_master_recv(c,buf,21); >+ >+ buf[0]=0; >+ ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc); >+ if (ret<0) >+ return; >+ >+ // send only the relevant registers per Rev. 1.2 >+ buf[0]=0; >+ ret=i2c_master_send(c,buf,4); >+ buf[5]=5; >+ ret=i2c_master_send(c,buf+5,4); >+ buf[11]=11; >+ ret=i2c_master_send(c,buf+11,3); >+ if(ret!=3) >+ tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); >+ >+ // wait for PLLs to lock (per manual), retry LINT if not. >+ for(lint_try=0; lint_try<2; lint_try++) { >+ lock=mt2032_check_lo_lock(c); >+ >+ if(optimize_vco) >+ lock=mt2032_optimize_vco(c,sel,lock); >+ if(lock==6) break; >+ >+ tuner_dbg("mt2032: re-init PLLs by LINT\n"); >+ buf[0]=7; >+ buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs >+ i2c_master_send(c,buf,2); >+ mdelay(10); >+ buf[1]=8+t->xogc; >+ i2c_master_send(c,buf,2); >+ } >+ >+ if (lock!=6) >+ tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n"); >+ >+ buf[0]=2; >+ buf[1]=0x20; // LOGC for optimal phase noise >+ ret=i2c_master_send(c,buf,2); >+ if (ret!=2) >+ tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); >+} >+ >+ >+static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ int if2,from,to; >+ >+ // signal bandwidth and picture carrier >+ if (t->std & V4L2_STD_525_60) { >+ // NTSC >+ from = 40750*1000; >+ to = 46750*1000; >+ if2 = 45750*1000; >+ } else { >+ // PAL >+ from = 32900*1000; >+ to = 39900*1000; >+ if2 = 38900*1000; >+ } >+ >+ mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, >+ 1090*1000*1000, if2, from, to); >+} >+ >+static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ int if2 = t->radio_if2; >+ >+ // per Manual for FM tuning: first if center freq. 1085 MHz >+ mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, >+ 1085*1000*1000,if2,if2,if2); >+} >+ >+// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001 >+static int mt2032_init(struct i2c_client *c) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ unsigned char buf[21]; >+ int ret,xogc,xok=0; >+ >+ // Initialize Registers per spec. >+ buf[1]=2; // Index to register 2 >+ buf[2]=0xff; >+ buf[3]=0x0f; >+ buf[4]=0x1f; >+ ret=i2c_master_send(c,buf+1,4); >+ >+ buf[5]=6; // Index register 6 >+ buf[6]=0xe4; >+ buf[7]=0x8f; >+ buf[8]=0xc3; >+ buf[9]=0x4e; >+ buf[10]=0xec; >+ ret=i2c_master_send(c,buf+5,6); >+ >+ buf[12]=13; // Index register 13 >+ buf[13]=0x32; >+ ret=i2c_master_send(c,buf+12,2); >+ >+ // Adjust XOGC (register 7), wait for XOK >+ xogc=7; >+ do { >+ tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); >+ mdelay(10); >+ buf[0]=0x0e; >+ i2c_master_send(c,buf,1); >+ i2c_master_recv(c,buf,1); >+ xok=buf[0]&0x01; >+ tuner_dbg("mt2032: xok = 0x%02x\n",xok); >+ if (xok == 1) break; >+ >+ xogc--; >+ tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); >+ if (xogc == 3) { >+ xogc=4; // min. 4 per spec >+ break; >+ } >+ buf[0]=0x07; >+ buf[1]=0x88 + xogc; >+ ret=i2c_master_send(c,buf,2); >+ if (ret!=2) >+ tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); >+ } while (xok != 1 ); >+ t->xogc=xogc; >+ >+ t->tv_freq = mt2032_set_tv_freq; >+ t->radio_freq = mt2032_set_radio_freq; >+ return(1); >+} >+ >+static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ unsigned char buf[2]; >+ int ret; >+ >+ buf[0] = 6; >+ buf[1] = antenna ? 0x11 : 0x10; >+ ret=i2c_master_send(c,buf,2); >+ tuner_dbg("mt2050: enabled antenna connector %d\n", antenna); >+} >+ >+static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ unsigned int if1=1218*1000*1000; >+ unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b; >+ int ret; >+ unsigned char buf[6]; >+ >+ tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n", >+ freq,if1,if2); >+ >+ f_lo1=freq+if1; >+ f_lo1=(f_lo1/1000000)*1000000; >+ >+ f_lo2=f_lo1-freq-if2; >+ f_lo2=(f_lo2/50000)*50000; >+ >+ lo1=f_lo1/4000000; >+ lo2=f_lo2/4000000; >+ >+ f_lo1_modulo= f_lo1-(lo1*4000000); >+ f_lo2_modulo= f_lo2-(lo2*4000000); >+ >+ num1=4*f_lo1_modulo/4000000; >+ num2=4096*(f_lo2_modulo/1000)/4000; >+ >+ // todo spurchecks >+ >+ div1a=(lo1/12)-1; >+ div1b=lo1-(div1a+1)*12; >+ >+ div2a=(lo2/8)-1; >+ div2b=lo2-(div2a+1)*8; >+ >+ if (tuner_debug > 1) { >+ tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2); >+ tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n", >+ num1,num2,div1a,div1b,div2a,div2b); >+ } >+ >+ buf[0]=1; >+ buf[1]= 4*div1b + num1; >+ if(freq<275*1000*1000) buf[1] = buf[1]|0x80; >+ >+ buf[2]=div1a; >+ buf[3]=32*div2b + num2/256; >+ buf[4]=num2-(num2/256)*256; >+ buf[5]=div2a; >+ if(num2!=0) buf[5]=buf[5]|0x40; >+ >+ if (tuner_debug > 1) { >+ int i; >+ tuner_dbg("bufs is: "); >+ for(i=0;i<6;i++) >+ printk("%x ",buf[i]); >+ printk("\n"); >+ } >+ >+ ret=i2c_master_send(c,buf,6); >+ if (ret!=6) >+ tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret); >+} >+ >+static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ unsigned int if2; >+ >+ if (t->std & V4L2_STD_525_60) { >+ // NTSC >+ if2 = 45750*1000; >+ } else { >+ // PAL >+ if2 = 38900*1000; >+ } >+ if (V4L2_TUNER_DIGITAL_TV == t->mode) { >+ // DVB (pinnacle 300i) >+ if2 = 36150*1000; >+ } >+ mt2050_set_if_freq(c, freq*62500, if2); >+ mt2050_set_antenna(c, tv_antenna); >+} >+ >+static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ int if2 = t->radio_if2; >+ >+ mt2050_set_if_freq(c, freq*62500, if2); >+ mt2050_set_antenna(c, radio_antenna); >+} >+ >+static int mt2050_init(struct i2c_client *c) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ unsigned char buf[2]; >+ int ret; >+ >+ buf[0]=6; >+ buf[1]=0x10; >+ ret=i2c_master_send(c,buf,2); // power >+ >+ buf[0]=0x0f; >+ buf[1]=0x0f; >+ ret=i2c_master_send(c,buf,2); // m1lo >+ >+ buf[0]=0x0d; >+ ret=i2c_master_send(c,buf,1); >+ i2c_master_recv(c,buf,1); >+ >+ tuner_dbg("mt2050: sro is %x\n",buf[0]); >+ t->tv_freq = mt2050_set_tv_freq; >+ t->radio_freq = mt2050_set_radio_freq; >+ return 0; >+} >+ >+int microtune_init(struct i2c_client *c) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ char *name; >+ unsigned char buf[21]; >+ int company_code; >+ >+ memset(buf,0,sizeof(buf)); >+ t->tv_freq = NULL; >+ t->radio_freq = NULL; >+ name = "unknown"; >+ >+ i2c_master_send(c,buf,1); >+ i2c_master_recv(c,buf,21); >+ if (tuner_debug) { >+ int i; >+ tuner_dbg("MT20xx hexdump:"); >+ for(i=0;i<21;i++) { >+ printk(" %02x",buf[i]); >+ if(((i+1)%8)==0) printk(" "); >+ } >+ printk("\n"); >+ } >+ company_code = buf[0x11] << 8 | buf[0x12]; >+ tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n", >+ company_code,buf[0x13],buf[0x14]); >+ >+#if 0 >+ /* seems to cause more problems than it solves ... */ >+ switch (company_code) { >+ case 0x30bf: >+ case 0x3cbf: >+ case 0x3dbf: >+ case 0x4d54: >+ case 0x8e81: >+ case 0x8e91: >+ /* ok (?) */ >+ break; >+ default: >+ tuner_warn("tuner: microtune: unknown companycode\n"); >+ return 0; >+ } >+#endif >+ >+ if (buf[0x13] < ARRAY_SIZE(microtune_part) && >+ NULL != microtune_part[buf[0x13]]) >+ name = microtune_part[buf[0x13]]; >+ switch (buf[0x13]) { >+ case MT2032: >+ mt2032_init(c); >+ break; >+ case MT2050: >+ mt2050_init(c); >+ break; >+ default: >+ tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", >+ name); >+ return 0; >+ } >+ >+ strlcpy(c->name, name, sizeof(c->name)); >+ tuner_info("microtune %s found, OK\n",name); >+ return 0; >+} >+ >+/* >+ * Overrides for Emacs so that we follow Linus's tabbing style. >+ * --------------------------------------------------------------------------- >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/video/planb.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/planb.c 2005-03-07 10:14:57.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/planb.c 2005-03-08 10:33:15.000000000 +0100 >@@ -40,6 +40,7 @@ > #include <linux/mm.h> > #include <linux/sched.h> > #include <linux/videodev.h> >+#include <linux/wait.h> > #include <asm/uaccess.h> > #include <asm/io.h> > #include <asm/prom.h> >@@ -1609,8 +1610,7 @@ static int planb_ioctl(struct video_devi > } > planb_lock(pb); > /* empty the grabbing queue */ >- while(pb->grabbing) >- interruptible_sleep_on(&pb->capq); >+ wait_event(pb->capq, !pb->grabbing); > pb->maxlines = maxlines; > pb->win.norm = v.norm; > /* Stop overlay if running */ >Index: linux-2.6.11/drivers/media/video/saa5246a.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa5246a.c 2005-03-07 10:13:46.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa5246a.c 2005-03-08 10:33:15.000000000 +0100 >@@ -65,18 +65,7 @@ static struct video_device saa_template; > /* Addresses to scan */ > static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END }; > static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; >-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >-static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >- >-static struct i2c_client_address_data addr_data = { >- normal_i2c, normal_i2c_range, >- probe, probe_range, >- ignore, ignore_range, >- force >-}; >+I2C_CLIENT_INSMOD; > > static struct i2c_client client_template; > >Index: linux-2.6.11/drivers/media/video/saa5249.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa5249.c 2005-03-07 10:14:50.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa5249.c 2005-03-08 10:33:15.000000000 +0100 >@@ -133,18 +133,7 @@ static struct video_device saa_template; > /* Addresses to scan */ > static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END}; > static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; >-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >-static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; >- >-static struct i2c_client_address_data addr_data = { >- normal_i2c, normal_i2c_range, >- probe, probe_range, >- ignore, ignore_range, >- force >-}; >+I2C_CLIENT_INSMOD; > > static struct i2c_client client_template; > >Index: linux-2.6.11/drivers/media/video/saa7110.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7110.c 2005-03-07 10:12:20.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7110.c 2005-03-08 10:33:15.000000000 +0100 >@@ -30,6 +30,7 @@ > #include <linux/types.h> > #include <linux/delay.h> > #include <linux/slab.h> >+#include <linux/wait.h> > #include <asm/io.h> > #include <asm/uaccess.h> > >@@ -205,13 +206,16 @@ static const unsigned char initseq[] = { > static int > determine_norm (struct i2c_client *client) > { >+ DEFINE_WAIT(wait); > struct saa7110 *decoder = i2c_get_clientdata(client); > int status; > > /* mode changed, start automatic detection */ > saa7110_write_block(client, initseq, sizeof(initseq)); > saa7110_selmux(client, decoder->input); >- sleep_on_timeout(&decoder->wq, HZ / 4); >+ prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); >+ schedule_timeout(HZ/4); >+ finish_wait(&decoder->wq, &wait); > status = saa7110_read(client); > if (status & 0x40) { > dprintk(1, KERN_INFO "%s: status=0x%02x (no signal)\n", >@@ -250,7 +254,9 @@ determine_norm (struct i2c_client *clien > saa7110_write(client, 0x11, 0x59); > //saa7110_write(client,0x2E,0x9A); > >- sleep_on_timeout(&decoder->wq, HZ / 4); >+ prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); >+ schedule_timeout(HZ/4); >+ finish_wait(&decoder->wq, &wait); > > status = saa7110_read(client); > if ((status & 0x03) == 0x01) { >Index: linux-2.6.11/drivers/media/video/saa7134/Makefile >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/Makefile 2005-03-07 10:16:02.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/Makefile 2005-03-08 10:33:27.000000000 +0100 >@@ -8,3 +8,4 @@ obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa71 > > EXTRA_CFLAGS += -I$(src)/.. > EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core >+EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends >Index: linux-2.6.11/drivers/media/video/saa7134/saa6752hs.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa6752hs.c 2005-03-07 10:15:39.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa6752hs.c 2005-03-08 10:33:27.000000000 +0100 >@@ -11,9 +11,14 @@ > #include <linux/types.h> > #include <linux/videodev.h> > #include <linux/init.h> >+#include <linux/crc32.h> > > #include <media/id.h> >-#include <media/saa6752hs.h> >+ >+#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000 >+#define MPEG_VIDEO_MAX_BITRATE_MAX 27000 >+#define MPEG_TOTAL_TARGET_BITRATE_MAX 27000 >+#define MPEG_PID_MAX ((1 << 14) - 1) > > /* Addresses to scan */ > static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END}; >@@ -27,6 +32,10 @@ MODULE_LICENSE("GPL"); > static struct i2c_driver driver; > static struct i2c_client client_template; > >+struct saa6752hs_state { >+ struct i2c_client client; >+ struct v4l2_mpeg_compression params; >+}; > > enum saa6752hs_command { > SAA6752HS_COMMAND_RESET = 0, >@@ -40,7 +49,6 @@ enum saa6752hs_command { > SAA6752HS_COMMAND_MAX > }; > >- > /* ---------------------------------------------------------------------- */ > > static u8 PAT[] = { >@@ -64,9 +72,9 @@ static u8 PAT[] = { > > 0x00, 0x01, // program_number(1) > >- 0xe0, 0x10, // PMT PID(0x10) >+ 0xe0, 0x00, // PMT PID > >- 0x76, 0xf1, 0x44, 0xd1 // CRC32 >+ 0x00, 0x00, 0x00, 0x00 // CRC32 > }; > > static u8 PMT[] = { >@@ -74,7 +82,7 @@ static u8 PMT[] = { > 0x01, // table number for encoder > > 0x47, // sync >- 0x40, 0x10, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0x10) >+ 0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid > 0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) > > 0x00, // PSI pointer to start of table >@@ -88,27 +96,50 @@ static u8 PMT[] = { > > 0x00, 0x00, // section_number(0), last_section_number(0) > >- 0xe1, 0x04, // PCR_PID (0x104) >+ 0xe0, 0x00, // PCR_PID > > 0xf0, 0x00, // program_info_length(0) > >- 0x02, 0xe1, 0x00, 0xf0, 0x00, // video stream type(2), pid(0x100) >- 0x04, 0xe1, 0x03, 0xf0, 0x00, // audio stream type(4), pid(0x103) >+ 0x02, 0xe0, 0x00, 0xf0, 0x00, // video stream type(2), pid >+ 0x04, 0xe0, 0x00, 0xf0, 0x00, // audio stream type(4), pid > >- 0xa1, 0xca, 0x0f, 0x82 // CRC32 >+ 0x00, 0x00, 0x00, 0x00 // CRC32 > }; > >-static struct mpeg_params mpeg_params_template = >+static struct v4l2_mpeg_compression param_defaults = > { >- .bitrate_mode = MPEG_BITRATE_MODE_CBR, >- .video_target_bitrate = 5000, >- .audio_bitrate = MPEG_AUDIO_BITRATE_256, >- .total_bitrate = 6000, >-}; >+ .st_type = V4L2_MPEG_TS_2, >+ .st_bitrate = { >+ .mode = V4L2_BITRATE_CBR, >+ .target = 7000, >+ }, > >+ .ts_pid_pmt = 16, >+ .ts_pid_video = 260, >+ .ts_pid_audio = 256, >+ .ts_pid_pcr = 259, > >-/* ---------------------------------------------------------------------- */ >+ .vi_type = V4L2_MPEG_VI_2, >+ .vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3, >+ .vi_bitrate = { >+ .mode = V4L2_BITRATE_VBR, >+ .target = 4000, >+ .max = 6000, >+ }, > >+ .au_type = V4L2_MPEG_AU_2_II, >+ .au_bitrate = { >+ .mode = V4L2_BITRATE_CBR, >+ .target = 256, >+ }, >+ >+#if 0 >+ /* FIXME: size? via S_FMT? */ >+ .video_format = MPEG_VIDEO_FORMAT_D1, >+#endif >+}; >+ >+/* ---------------------------------------------------------------------- */ > > static int saa6752hs_chip_command(struct i2c_client* client, > enum saa6752hs_command command) >@@ -124,7 +155,7 @@ static int saa6752hs_chip_command(struct > break; > > case SAA6752HS_COMMAND_STOP: >- buf[0] = 0x03; >+ buf[0] = 0x03; > break; > > case SAA6752HS_COMMAND_START: >@@ -180,74 +211,117 @@ static int saa6752hs_chip_command(struct > > > static int saa6752hs_set_bitrate(struct i2c_client* client, >- struct mpeg_params* params) >+ struct v4l2_mpeg_compression* params) > { > u8 buf[3]; > > // set the bitrate mode > buf[0] = 0x71; >- buf[1] = params->bitrate_mode; >+ buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1; > i2c_master_send(client, buf, 2); > > // set the video bitrate >- if (params->bitrate_mode == MPEG_BITRATE_MODE_VBR) { >+ if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) { > // set the target bitrate > buf[0] = 0x80; >- buf[1] = params->video_target_bitrate >> 8; >- buf[2] = params->video_target_bitrate & 0xff; >+ buf[1] = params->vi_bitrate.target >> 8; >+ buf[2] = params->vi_bitrate.target & 0xff; > i2c_master_send(client, buf, 3); > > // set the max bitrate > buf[0] = 0x81; >- buf[1] = params->video_max_bitrate >> 8; >- buf[2] = params->video_max_bitrate & 0xff; >+ buf[1] = params->vi_bitrate.max >> 8; >+ buf[2] = params->vi_bitrate.max & 0xff; > i2c_master_send(client, buf, 3); > } else { > // set the target bitrate (no max bitrate for CBR) > buf[0] = 0x81; >- buf[1] = params->video_target_bitrate >> 8; >- buf[2] = params->video_target_bitrate & 0xff; >+ buf[1] = params->vi_bitrate.target >> 8; >+ buf[2] = params->vi_bitrate.target & 0xff; > i2c_master_send(client, buf, 3); > } > > // set the audio bitrate > buf[0] = 0x94; >- buf[1] = params->audio_bitrate; >+ buf[1] = (256 == params->au_bitrate.target) ? 0 : 1; > i2c_master_send(client, buf, 2); > > // set the total bitrate > buf[0] = 0xb1; >- buf[1] = params->total_bitrate >> 8; >- buf[2] = params->total_bitrate & 0xff; >+ buf[1] = params->st_bitrate.target >> 8; >+ buf[2] = params->st_bitrate.target & 0xff; > i2c_master_send(client, buf, 3); > >+ // return success > return 0; > } > > >-static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params) >+static void saa6752hs_set_params(struct i2c_client* client, >+ struct v4l2_mpeg_compression* params) > { >- unsigned char buf[3]; >- void *data; >+ struct saa6752hs_state *h = i2c_get_clientdata(client); > >- // check the bitrate parameters first >- if (params != NULL) { >- if (params->bitrate_mode >= MPEG_BITRATE_MODE_MAX) >- return -EINVAL; >- if (params->video_target_bitrate >= MPEG_VIDEO_TARGET_BITRATE_MAX) >- return -EINVAL; >- if (params->video_max_bitrate >= MPEG_VIDEO_MAX_BITRATE_MAX) >- return -EINVAL; >- if (params->audio_bitrate >= MPEG_AUDIO_BITRATE_MAX) >- return -EINVAL; >- if (params->total_bitrate >= MPEG_TOTAL_BITRATE_MAX) >- return -EINVAL; >- if (params->bitrate_mode == MPEG_BITRATE_MODE_MAX && >- params->video_target_bitrate <= params->video_max_bitrate) >- return -EINVAL; >- } >+ /* check PIDs */ >+ if (params->ts_pid_pmt <= MPEG_PID_MAX) >+ h->params.ts_pid_pmt = params->ts_pid_pmt; >+ if (params->ts_pid_pcr <= MPEG_PID_MAX) >+ h->params.ts_pid_pcr = params->ts_pid_pcr; >+ if (params->ts_pid_video <= MPEG_PID_MAX) >+ h->params.ts_pid_video = params->ts_pid_video; >+ if (params->ts_pid_audio <= MPEG_PID_MAX) >+ h->params.ts_pid_audio = params->ts_pid_audio; > >- // Set GOP structure {3, 13} >+ /* check bitrate parameters */ >+ if ((params->vi_bitrate.mode == V4L2_BITRATE_CBR) || >+ (params->vi_bitrate.mode == V4L2_BITRATE_VBR)) >+ h->params.vi_bitrate.mode = params->vi_bitrate.mode; >+ if (params->vi_bitrate.mode != V4L2_BITRATE_NONE) >+ h->params.st_bitrate.target = params->st_bitrate.target; >+ if (params->vi_bitrate.mode != V4L2_BITRATE_NONE) >+ h->params.vi_bitrate.target = params->vi_bitrate.target; >+ if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) >+ h->params.vi_bitrate.max = params->vi_bitrate.max; >+ if (params->au_bitrate.mode != V4L2_BITRATE_NONE) >+ h->params.au_bitrate.target = params->au_bitrate.target; >+ >+ /* aspect ratio */ >+ if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3 || >+ params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9) >+ h->params.vi_aspect_ratio = params->vi_aspect_ratio; >+ >+ /* range checks */ >+ if (h->params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX) >+ h->params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX; >+ if (h->params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX) >+ h->params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX; >+ if (h->params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX) >+ h->params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX; >+ if (h->params.au_bitrate.target <= 256) >+ h->params.au_bitrate.target = 256; >+ else >+ h->params.au_bitrate.target = 384; >+} >+ >+static int saa6752hs_init(struct i2c_client* client) >+{ >+ unsigned char buf[9], buf2[4]; >+ struct saa6752hs_state *h; >+ u32 crc; >+ unsigned char localPAT[256]; >+ unsigned char localPMT[256]; >+ >+ h = i2c_get_clientdata(client); >+ >+ // Set video format - must be done first as it resets other settings >+ buf[0] = 0x41; >+ buf[1] = 0 /* MPEG_VIDEO_FORMAT_D1 */; >+ i2c_master_send(client, buf, 2); >+ >+ // set bitrate >+ saa6752hs_set_bitrate(client, &h->params); >+ >+ // Set GOP structure {3, 13} > buf[0] = 0x72; > buf[1] = 0x03; > buf[2] = 0x0D; >@@ -265,7 +339,7 @@ static int saa6752hs_init(struct i2c_cli > > // Set Output Protocol > buf[0] = 0xD0; >- buf[1] = 0x01; >+ buf[1] = 0x81; > i2c_master_send(client,buf,2); > > // Set video output stream format {TS} >@@ -273,25 +347,53 @@ static int saa6752hs_init(struct i2c_cli > buf[1] = 0x05; > i2c_master_send(client,buf,2); > >- // Set Audio PID {0x103} >+ /* compute PAT */ >+ memcpy(localPAT, PAT, sizeof(PAT)); >+ localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f); >+ localPAT[18] = h->params.ts_pid_pmt & 0xff; >+ crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4); >+ localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF; >+ localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF; >+ localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF; >+ localPAT[sizeof(PAT) - 1] = crc & 0xFF; >+ >+ /* compute PMT */ >+ memcpy(localPMT, PMT, sizeof(PMT)); >+ localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); >+ localPMT[4] = h->params.ts_pid_pmt & 0xff; >+ localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); >+ localPMT[16] = h->params.ts_pid_pcr & 0xFF; >+ localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F); >+ localPMT[21] = h->params.ts_pid_video & 0xFF; >+ localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F); >+ localPMT[26] = h->params.ts_pid_audio & 0xFF; >+ crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4); >+ localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF; >+ localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF; >+ localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF; >+ localPMT[sizeof(PMT) - 1] = crc & 0xFF; >+ >+ // Set Audio PID > buf[0] = 0xC1; >- buf[1] = 0x01; >- buf[2] = 0x03; >+ buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF; >+ buf[2] = h->params.ts_pid_audio & 0xFF; > i2c_master_send(client,buf,3); > >- // setup bitrate settings >- data = i2c_get_clientdata(client); >- if (params) { >- saa6752hs_set_bitrate(client, params); >- memcpy(data, params, sizeof(struct mpeg_params)); >- } else { >- // parameters were not supplied. use the previous set >- saa6752hs_set_bitrate(client, (struct mpeg_params*) data); >- } >+ // Set Video PID >+ buf[0] = 0xC0; >+ buf[1] = (h->params.ts_pid_video >> 8) & 0xFF; >+ buf[2] = h->params.ts_pid_video & 0xFF; >+ i2c_master_send(client,buf,3); >+ >+ // Set PCR PID >+ buf[0] = 0xC4; >+ buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF; >+ buf[2] = h->params.ts_pid_pcr & 0xFF; >+ i2c_master_send(client,buf,3); > > // Send SI tables >- i2c_master_send(client,PAT,sizeof(PAT)); >- i2c_master_send(client,PMT,sizeof(PMT)); >+ i2c_master_send(client,localPAT,sizeof(PAT)); >+ i2c_master_send(client,localPMT,sizeof(PMT)); > > // mute then unmute audio. This removes buzzing artefacts > buf[0] = 0xa4; >@@ -303,31 +405,56 @@ static int saa6752hs_init(struct i2c_cli > // start it going > saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); > >+ // readout current state >+ buf[0] = 0xE1; >+ buf[1] = 0xA7; >+ buf[2] = 0xFE; >+ buf[3] = 0x82; >+ buf[4] = 0xB0; >+ i2c_master_send(client, buf, 5); >+ i2c_master_recv(client, buf2, 4); >+ >+ // change aspect ratio >+ buf[0] = 0xE0; >+ buf[1] = 0xA7; >+ buf[2] = 0xFE; >+ buf[3] = 0x82; >+ buf[4] = 0xB0; >+ buf[5] = buf2[0]; >+ switch(h->params.vi_aspect_ratio) { >+ case V4L2_MPEG_ASPECT_16_9: >+ buf[6] = buf2[1] | 0x40; >+ break; >+ case V4L2_MPEG_ASPECT_4_3: >+ default: >+ buf[6] = buf2[1] & 0xBF; >+ break; >+ break; >+ } >+ buf[7] = buf2[2]; >+ buf[8] = buf2[3]; >+ i2c_master_send(client, buf, 9); >+ >+ // return success > return 0; > } > > static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) > { >- struct i2c_client *client; >- struct mpeg_params* params; >- >- client_template.adapter = adap; >- client_template.addr = addr; >+ struct saa6752hs_state *h; > > printk("saa6752hs: chip found @ 0x%x\n", addr<<1); > >- if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) >+ if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL))) > return -ENOMEM; >- memcpy(client,&client_template,sizeof(struct i2c_client)); >- strlcpy(client->name, "saa6752hs", sizeof(client->name)); >- >- if (NULL == (params = kmalloc(sizeof(struct mpeg_params), GFP_KERNEL))) >- return -ENOMEM; >- memcpy(params,&mpeg_params_template,sizeof(struct mpeg_params)); >- i2c_set_clientdata(client, params); >- >- i2c_attach_client(client); >+ memset(h,0,sizeof(*h)); >+ h->client = client_template; >+ h->params = param_defaults; >+ h->client.adapter = adap; >+ h->client.addr = addr; > >+ i2c_set_clientdata(&h->client, h); >+ i2c_attach_client(&h->client); > return 0; > } > >@@ -340,30 +467,39 @@ static int saa6752hs_probe(struct i2c_ad > > static int saa6752hs_detach(struct i2c_client *client) > { >- void *data; >+ struct saa6752hs_state *h; > >- data = i2c_get_clientdata(client); >+ h = i2c_get_clientdata(client); > i2c_detach_client(client); >- kfree(data); >- kfree(client); >+ kfree(h); > return 0; > } > > static int > saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) > { >- struct mpeg_params* init_arg = arg; >+ struct saa6752hs_state *h = i2c_get_clientdata(client); >+ struct v4l2_mpeg_compression *params = arg; >+ int err = 0; > > switch (cmd) { >- case MPEG_SETPARAMS: >- return saa6752hs_init(client, init_arg); >- >+ case VIDIOC_S_MPEGCOMP: >+ if (NULL == params) { >+ /* apply settings and start encoder */ >+ saa6752hs_init(client); >+ break; >+ } >+ saa6752hs_set_params(client, params); >+ /* fall through */ >+ case VIDIOC_G_MPEGCOMP: >+ *params = h->params; >+ break; > default: > /* nothing */ > break; > } > >- return 0; >+ return err; > } > > /* ----------------------------------------------------------------------- */ >@@ -380,7 +516,7 @@ static struct i2c_driver driver = { > > static struct i2c_client client_template = > { >- I2C_DEVNAME("(saa6752hs unset)"), >+ I2C_DEVNAME("saa6752hs"), > .flags = I2C_CLIENT_ALLOW_USE, > .driver = &driver, > }; >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-cards.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-cards.c 2005-03-07 10:15:07.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-cards.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,6 @@ >+ > /* >- * $Id: saa7134-cards.c,v 1.35 2004/11/07 14:44:59 kraxel Exp $ >+ * $Id: saa7134-cards.c,v 1.54 2005/03/07 12:01:51 kraxel Exp $ > * > * device driver for philips saa7134 based TV cards > * card-specific stuff. >@@ -156,11 +157,11 @@ struct saa7134_board saa7134_boards[] = > .gpio = 0x8000, > }, > }, >- [SAA7134_BOARD_FLYTVPLATINUM] = { >+ [SAA7134_BOARD_FLYTVPLATINUM_MINI] = { > /* "Arnaud Quette" <aquette@free.fr> */ >- .name = "LifeView FlyTV Platinum", >+ .name = "LifeView FlyTV Platinum Mini", > .audio_clock = 0x00200000, >- .tuner_type = TUNER_PHILIPS_SECAM, >+ .tuner_type = TUNER_PHILIPS_TDA8290, > .inputs = {{ > .name = name_tv, > .vmux = 1, >@@ -176,6 +177,47 @@ struct saa7134_board saa7134_boards[] = > .amux = LINE2, > }}, > }, >+ [SAA7134_BOARD_FLYTVPLATINUM_FM] = { >+ /* LifeView FlyTV Platinum FM (LR214WF) */ >+ /* "Peter Missel <peter.missel@onlinehome.de> */ >+ .name = "LifeView FlyTV Platinum FM", >+ .audio_clock = 0x00200000, >+ .tuner_type = TUNER_PHILIPS_TDA8290, >+// .gpiomask = 0xe000, >+ .inputs = {{ >+ .name = name_tv, >+ .vmux = 1, >+ .amux = TV, >+// .gpio = 0x0000, >+ .tv = 1, >+ },{ >+/* .name = name_tv_mono, >+ .vmux = 1, >+ .amux = LINE2, >+ .gpio = 0x0000, >+ .tv = 1, >+ },{ >+*/ .name = name_comp1, /* Composite signal on S-Video input */ >+ .vmux = 0, >+ .amux = LINE2, >+// .gpio = 0x4000, >+ },{ >+ .name = name_comp2, /* Composite input */ >+ .vmux = 3, >+ .amux = LINE2, >+// .gpio = 0x4000, >+ },{ >+ .name = name_svideo, /* S-Video signal on S-Video input */ >+ .vmux = 8, >+ .amux = LINE2, >+// .gpio = 0x4000, >+ }}, >+/* .radio = { >+ .name = name_radio, >+ .amux = LINE2, >+ .gpio = 0x2000, >+ }, >+*/ }, > [SAA7134_BOARD_EMPRESS] = { > /* "Gert Vervoort" <gert.vervoort@philips.com> */ > .name = "EMPRESS", >@@ -436,6 +478,7 @@ struct saa7134_board saa7134_boards[] = > .audio_clock = 0x00187de7, > .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, > .tda9887_conf = TDA9887_PRESENT, >+ .mpeg = SAA7134_MPEG_DVB, > .inputs = {{ > .name = name_tv, > .vmux = 1, >@@ -444,11 +487,11 @@ struct saa7134_board saa7134_boards[] = > },{ > .name = name_comp1, > .vmux = 0, >- .amux = LINE2, >+ .amux = LINE1, > },{ > .name = name_svideo, > .vmux = 8, >- .amux = LINE2, >+ .amux = LINE1, > }}, > .radio = { > .name = name_radio, >@@ -544,6 +587,34 @@ struct saa7134_board saa7134_boards[] = > .amux = LINE1, > }, > }, >+ [SAA7135_BOARD_ASUSTeK_TVFM7135] = { >+ .name = "ASUS TV-FM 7135", >+ .audio_clock = 0x00187de7, >+ .tuner_type = TUNER_PHILIPS_TDA8290, >+ .gpiomask = 0x200000, >+ .inputs = {{ >+ .name = name_tv, >+ .vmux = 1, >+ .amux = TV, >+ .gpio = 0x0000, >+ .tv = 1, >+ },{ >+ .name = name_comp1, >+ .vmux = 4, >+ .amux = LINE2, >+ .gpio = 0x0000, >+ },{ >+ .name = name_svideo, >+ .vmux = 6, >+ .amux = LINE2, >+ .gpio = 0x0000, >+ }}, >+ .radio = { >+ .name = name_radio, >+ .amux = TV, >+ .gpio = 0x200000, >+ }, >+ }, > [SAA7134_BOARD_VA1000POWER] = { > .name = "AOPEN VA1000 POWER", > .audio_clock = 0x00187de7, >@@ -749,7 +820,7 @@ struct saa7134_board saa7134_boards[] = > },{ > .name = name_tv, > .vmux = 3, >- .amux = LINE2, >+ .amux = TV, > .tv = 1, > }}, > .mpeg = SAA7134_MPEG_EMPRESS, >@@ -828,6 +899,10 @@ struct saa7134_board saa7134_boards[] = > .name = name_radio, > .amux = LINE2, > }, >+ .mute = { >+ .name = name_mute, >+ .amux = LINE1, >+ }, > }, > [SAA7134_BOARD_MANLI_MTV001] = { > /* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */ >@@ -975,6 +1050,9 @@ struct saa7134_board saa7134_boards[] = > .inputs = {{ > .name = name_comp1, > .vmux = 3, >+ },{ >+ .name = name_svideo, >+ .vmux = 8, > }}, > }, > [SAA7134_BOARD_NOVAC_PRIMETV7133] = { >@@ -995,11 +1073,12 @@ struct saa7134_board saa7134_boards[] = > .vmux = 8, > }}, > }, >- [SAA7134_BOARD_AVERMEDIA_305] = { >- .name = "AverMedia 305", >+ [SAA7134_BOARD_AVERMEDIA_STUDIO_305] = { >+ .name = "AverMedia AverTV Studio 305", > .audio_clock = 0x00187de7, >- .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, >+ .tuner_type = TUNER_PHILIPS_FM1256_IH3, > .tda9887_conf = TDA9887_PRESENT, >+ .gpiomask = 0x3, > .inputs = {{ > .name = name_tv, > .vmux = 1, >@@ -1104,23 +1183,23 @@ struct saa7134_board saa7134_boards[] = > .name = name_svideo, > .vmux = 8, > .amux = LINE1, >- .gpio = 0x00080 >+ .gpio = 0x00080, > },{ > .name = name_comp1, > .vmux = 3, > .amux = LINE1, >- .gpio = 0x00080 >+ .gpio = 0x00080, > },{ > .name = name_tv, > .vmux = 1, >- .amux = LINE2, >+ .amux = LINE2_LEFT, > .tv = 1, >- .gpio = 0x00080 >+ .gpio = 0x00080, > }}, > .radio = { >- .name = name_radio, >- .amux = LINE2, >- .gpio = 0x80000 >+ .name = name_radio, >+ .amux = LINE2, >+ .gpio = 0x80000, > }, > .mute = { > .name = name_mute, >@@ -1129,21 +1208,20 @@ struct saa7134_board saa7134_boards[] = > }, > }, > [SAA7134_BOARD_SABRENT_SBTTVFM] = { >- /* Michael Rodriguez-Torrent */ >+ /* Michael Rodriguez-Torrent <mrtorrent@asu.edu> */ > .name = "Sabrent SBT-TVFM (saa7130)", > .audio_clock = 0x00187de7, > .tuner_type = TUNER_PHILIPS_NTSC_M, >- .tda9887_conf = TDA9887_PRESENT, > .inputs = {{ >+ .name = name_comp1, >+ .vmux = 1, >+ .amux = LINE2, >+ },{ > .name = name_tv, > .vmux = 3, > .amux = LINE2, > .tv = 1, > },{ >- .name = name_comp1, >- .vmux = 1, >- .amux = LINE2, >- },{ > .name = name_svideo, > .vmux = 8, > .amux = LINE2, >@@ -1208,32 +1286,41 @@ struct saa7134_board saa7134_boards[] = > } > }, > [SAA7134_BOARD_AVERMEDIA_307] = { >- /* Nickolay V. Shmyrev <nshmyrev@yandex.ru> */ >+ /* >+ Nickolay V. Shmyrev <nshmyrev@yandex.ru> >+ Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru> >+ */ > .name = "Avermedia AVerTV Studio 307", > .audio_clock = 0x00187de7, >- .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, >+ .tuner_type = TUNER_PHILIPS_FM1256_IH3, > .tda9887_conf = TDA9887_PRESENT, >+ .gpiomask = 0x03, > .inputs = {{ > .name = name_tv, > .vmux = 1, > .amux = TV, > .tv = 1, >+ .gpio = 0x00, > },{ > .name = name_comp1, > .vmux = 0, > .amux = LINE2, >+ .gpio = 0x00, > },{ > .name = name_comp2, > .vmux = 3, > .amux = LINE2, >+ .gpio = 0x00, > },{ > .name = name_svideo, > .vmux = 8, > .amux = LINE2, >+ .gpio = 0x00, > }}, > .radio = { > .name = name_radio, >- .amux = TV, >+ .amux = LINE1, >+ .gpio = 0x01, > }, > }, > [SAA7134_BOARD_AVERMEDIA_CARDBUS] = { >@@ -1263,10 +1350,17 @@ struct saa7134_board saa7134_boards[] = > [SAA7134_BOARD_CINERGY400_CARDBUS] = { > .name = "Terratec Cinergy 400 mobile", > .audio_clock = 0x187de7, >- .tuner_type = UNSET /* not supported yet :/ */, >+ .tuner_type = TUNER_ALPS_TSBE5_PAL, >+ .tda9887_conf = TDA9887_PRESENT, > .inputs = {{ > .name = name_tv, >- .vmux = 5, >+ .vmux = 1, >+ .amux = TV, >+ .tv = 1, >+ },{ >+ .name = name_tv_mono, >+ .vmux = 1, >+ .amux = LINE2, > .tv = 1, > },{ > .name = name_comp1, >@@ -1274,8 +1368,182 @@ struct saa7134_board saa7134_boards[] = > .amux = LINE1, > },{ > .name = name_svideo, >+ .vmux = 8, >+ .amux = LINE1, >+ }}, >+ }, >+ [SAA7134_BOARD_CINERGY600_MK3] = { >+ .name = "Terratec Cinergy 600 TV MK3", >+ .audio_clock = 0x00200000, >+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, >+ .tda9887_conf = TDA9887_PRESENT, >+ .inputs = {{ >+ .name = name_tv, >+ .vmux = 1, >+ .amux = TV, >+ .tv = 1, >+ },{ >+ .name = name_comp1, > .vmux = 4, > .amux = LINE1, >+ },{ >+ .name = name_svideo, >+ .vmux = 8, >+ .amux = LINE1, >+ },{ >+ .name = name_comp2, // CVideo over SVideo Connector >+ .vmux = 0, >+ .amux = LINE1, >+ }}, >+ .radio = { >+ .name = name_radio, >+ .amux = LINE2, >+ }, >+ }, >+ [SAA7134_BOARD_VIDEOMATE_GOLD_PLUS] = { >+ /* Dylan Walkden <dylan_walkden@hotmail.com> */ >+ .name = "Compro VideoMate Gold+ Pal", >+ .audio_clock = 0x00187de7, >+ .tuner_type = TUNER_PHILIPS_PAL, >+ .gpiomask = 0x1ce780, >+ .inputs = {{ >+ .name = name_svideo, >+ .vmux = 0, // CVideo over SVideo Connector - ok? >+ .amux = LINE1, >+ .gpio = 0x008080, >+ },{ >+ .name = name_comp1, >+ .vmux = 3, >+ .amux = LINE1, >+ .gpio = 0x008080, >+ },{ >+ .name = name_tv, >+ .vmux = 1, >+ .amux = TV, >+ .tv = 1, >+ .gpio = 0x008080, >+ }}, >+ .radio = { >+ .name = name_radio, >+ .amux = LINE2, >+ .gpio = 0x80000, >+ }, >+ .mute = { >+ .name = name_mute, >+ .amux = LINE2, >+ .gpio = 0x0c8000, >+ }, >+ }, >+ [SAA7134_BOARD_PINNACLE_300I_DVBT_PAL] = { >+ .name = "Pinnacle PCTV 300i DVB-T + PAL", >+ .audio_clock = 0x00187de7, >+ .tuner_type = TUNER_MT2032, >+ .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER, >+ .mpeg = SAA7134_MPEG_DVB, >+ .inputs = {{ >+ .name = name_tv, >+ .vmux = 3, >+ .amux = TV, >+ .tv = 1, >+ },{ >+ .name = name_comp1, >+ .vmux = 0, >+ .amux = LINE2, >+ },{ >+ .name = name_comp2, >+ .vmux = 1, >+ .amux = LINE2, >+ },{ >+ .name = name_svideo, >+ .vmux = 8, >+ .amux = LINE2, >+ }}, >+ }, >+ [SAA7134_BOARD_PROVIDEO_PV952] = { >+ /* andreas.kretschmer@web.de */ >+ .name = "ProVideo PV952", >+ .audio_clock = 0x00187de7, >+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, >+ .tda9887_conf = TDA9887_PRESENT, >+ .inputs = {{ >+ .name = name_comp1, >+ .vmux = 0, >+ .amux = LINE1, >+ },{ >+ .name = name_tv, >+ .vmux = 1, >+ .amux = TV, >+ .tv = 1, >+ },{ >+ .name = name_tv_mono, >+ .vmux = 1, >+ .amux = LINE2, >+ .tv = 1, >+ }}, >+ .radio = { >+ .name = name_radio, >+ .amux = LINE2, >+ }, >+ }, >+ [SAA7134_BOARD_AVERMEDIA_305] = { >+ /* much like the "studio" version but without radio >+ * and another tuner (sirspiritus@yandex.ru) */ >+ .name = "AverMedia AverTV/305", >+ .audio_clock = 0x00187de7, >+ .tuner_type = TUNER_PHILIPS_FQ1216ME, >+ .tda9887_conf = TDA9887_PRESENT, >+ .gpiomask = 0x3, >+ .inputs = {{ >+ .name = name_tv, >+ .vmux = 1, >+ .amux = LINE2, >+ .tv = 1, >+ },{ >+ .name = name_comp1, >+ .vmux = 0, >+ .amux = LINE2, >+ },{ >+ .name = name_comp2, >+ .vmux = 3, >+ .amux = LINE2, >+ },{ >+ .name = name_svideo, >+ .vmux = 8, >+ .amux = LINE2, >+ }}, >+ .mute = { >+ .name = name_mute, >+ .amux = LINE1, >+ }, >+ }, >+ [SAA7134_BOARD_FLYDVBTDUO] = { >+ /* LifeView FlyDVB-T DUO */ >+ /* "Nico Sabbi <nsabbi@tiscali.it> */ >+ .name = "LifeView FlyDVB-T DUO", >+ .audio_clock = 0x00200000, >+ .tuner_type = TUNER_PHILIPS_TDA8290, >+// .gpiomask = 0xe000, >+ .inputs = {{ >+ .name = name_tv, >+ .vmux = 1, >+ .amux = TV, >+// .gpio = 0x0000, >+ .tv = 1, >+ },{ >+ .name = name_comp1, /* Composite signal on S-Video input */ >+ .vmux = 0, >+ .amux = LINE2, >+// .gpio = 0x4000, >+ },{ >+ .name = name_comp2, /* Composite input */ >+ .vmux = 3, >+ .amux = LINE2, >+// .gpio = 0x4000, >+ },{ >+ .name = name_svideo, /* S-Video signal on S-Video input */ >+ .vmux = 8, >+ .amux = LINE2, >+// .gpio = 0x4000, > }}, > }, > }; >@@ -1322,6 +1590,12 @@ struct pci_device_id saa7134_pci_tbl[] = > .subdevice = 0x1143, > .driver_data = SAA7134_BOARD_CINERGY600, > },{ >+ .vendor = PCI_VENDOR_ID_PHILIPS, >+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134, >+ .subvendor = 0x153B, >+ .subdevice = 0x1158, >+ .driver_data = SAA7134_BOARD_CINERGY600_MK3, >+ },{ > .vendor = PCI_VENDOR_ID_PHILIPS, > .device = PCI_DEVICE_ID_PHILIPS_SAA7133, > .subvendor = 0x153b, >@@ -1349,8 +1623,14 @@ struct pci_device_id saa7134_pci_tbl[] = > .vendor = PCI_VENDOR_ID_PHILIPS, > .device = PCI_DEVICE_ID_PHILIPS_SAA7135, > .subvendor = 0x5168, >- .subdevice = 0x0212, >- .driver_data = SAA7134_BOARD_FLYTVPLATINUM, >+ .subdevice = 0x0212, /* minipci, LR212 */ >+ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, >+ },{ >+ .vendor = PCI_VENDOR_ID_PHILIPS, >+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, >+ .subvendor = 0x5168, >+ .subdevice = 0x0214, /* Standard PCI, LR214WF */ >+ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, > },{ > .vendor = PCI_VENDOR_ID_PHILIPS, > .device = PCI_DEVICE_ID_PHILIPS_SAA7134, >@@ -1377,6 +1657,12 @@ struct pci_device_id saa7134_pci_tbl[] = > .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, > },{ > .vendor = PCI_VENDOR_ID_PHILIPS, >+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, >+ .subvendor = PCI_VENDOR_ID_ASUSTEK, >+ .subdevice = 0x4845, >+ .driver_data = SAA7135_BOARD_ASUSTeK_TVFM7135, >+ },{ >+ .vendor = PCI_VENDOR_ID_PHILIPS, > .device = PCI_DEVICE_ID_PHILIPS_SAA7134, > .subvendor = PCI_VENDOR_ID_ASUSTEK, > .subdevice = 0x4830, >@@ -1452,6 +1738,12 @@ struct pci_device_id saa7134_pci_tbl[] = > .device = PCI_DEVICE_ID_PHILIPS_SAA7130, > .subvendor = 0x1461, /* Avermedia Technologies Inc */ > .subdevice = 0x2115, >+ .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_305, >+ },{ >+ .vendor = PCI_VENDOR_ID_PHILIPS, >+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130, >+ .subvendor = 0x1461, /* Avermedia Technologies Inc */ >+ .subdevice = 0x2108, > .driver_data = SAA7134_BOARD_AVERMEDIA_305, > },{ > .vendor = PCI_VENDOR_ID_PHILIPS, >@@ -1483,8 +1775,8 @@ struct pci_device_id saa7134_pci_tbl[] = > .vendor = PCI_VENDOR_ID_PHILIPS, > .device = PCI_DEVICE_ID_PHILIPS_SAA7134, > .subvendor = 0x11bd, >- .subdevice = 0x002d, /* 300i DVB-T + PAL */ >- .driver_data = SAA7134_BOARD_PINNACLE_PCTV_STEREO, >+ .subdevice = 0x002d, >+ .driver_data = SAA7134_BOARD_PINNACLE_300I_DVBT_PAL, > },{ > .vendor = PCI_VENDOR_ID_PHILIPS, > .device = PCI_DEVICE_ID_PHILIPS_SAA7134, >@@ -1509,20 +1801,43 @@ struct pci_device_id saa7134_pci_tbl[] = > .subvendor = 0x153B, > .subdevice = 0x1152, > .driver_data = SAA7134_BOARD_CINERGY200, >- > },{ > .vendor = PCI_VENDOR_ID_PHILIPS, > .device = PCI_DEVICE_ID_PHILIPS_SAA7130, > .subvendor = 0x185b, > .subdevice = 0xc100, > .driver_data = SAA7134_BOARD_VIDEOMATE_TV_PVR, >- > },{ > .vendor = PCI_VENDOR_ID_PHILIPS, >+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130, >+ .subvendor = 0x1131, >+ .subdevice = 0, >+ .driver_data = SAA7134_BOARD_SABRENT_SBTTVFM, >+ },{ >+ .vendor = PCI_VENDOR_ID_PHILIPS, > .device = PCI_DEVICE_ID_PHILIPS_SAA7134, >- .subvendor = 0x1461, /* Avermedia Technologies Inc */ >- .subdevice = 0x9715, >+ .subvendor = 0x1461, /* Avermedia Technologies Inc */ >+ .subdevice = 0x9715, > .driver_data = SAA7134_BOARD_AVERMEDIA_307, >+ },{ >+ .vendor = PCI_VENDOR_ID_PHILIPS, >+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134, >+ .subvendor = 0x185b, >+ .subdevice = 0xc200, >+ .driver_data = SAA7134_BOARD_VIDEOMATE_GOLD_PLUS, >+ },{ >+ .vendor = PCI_VENDOR_ID_PHILIPS, >+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134, >+ .subvendor = 0x1540, >+ .subdevice = 0x9524, >+ .driver_data = SAA7134_BOARD_PROVIDEO_PV952, >+ >+ },{ >+ .vendor = PCI_VENDOR_ID_PHILIPS, >+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, >+ .subvendor = 0x5168, >+ .subdevice = 0x0306, >+ .driver_data = SAA7134_BOARD_FLYDVBTDUO, > > },{ > /* --- boards without eeprom + subsystem ID --- */ >@@ -1631,16 +1946,19 @@ int saa7134_board_init1(struct saa7134_d > case SAA7134_BOARD_FLYVIDEO2000: > case SAA7134_BOARD_FLYVIDEO3000: > dev->has_remote = 1; >- /* fall throuth */ >- case SAA7134_BOARD_FLYTVPLATINUM: > board_flyvideo(dev); > break; > case SAA7134_BOARD_CINERGY400: > case SAA7134_BOARD_CINERGY600: >+ case SAA7134_BOARD_CINERGY600_MK3: > case SAA7134_BOARD_ECS_TVP3XP: > case SAA7134_BOARD_ECS_TVP3XP_4CB5: > case SAA7134_BOARD_MD2819: >+ case SAA7134_BOARD_AVERMEDIA_STUDIO_305: >+ case SAA7134_BOARD_AVERMEDIA_305: > case SAA7134_BOARD_AVERMEDIA_307: >+// case SAA7134_BOARD_SABRENT_SBTTVFM: /* not finished yet */ >+ case SAA7134_BOARD_VIDEOMATE_TV_PVR: > dev->has_remote = 1; > break; > case SAA7134_BOARD_AVACSSMARTTV: >@@ -1656,8 +1974,13 @@ int saa7134_board_init1(struct saa7134_d > /* power-up tuner chip */ > saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); > saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000); >+ msleep(1); > break; > } >+ if (dev->has_remote) >+ dev->irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | >+ SAA7134_IRQ2_INTE_GPIO18A | >+ SAA7134_IRQ2_INTE_GPIO16 ); > return 0; > } > >@@ -1676,6 +1999,7 @@ int saa7134_board_init2(struct saa7134_d > : SAA7134_BOARD_BMK_MPEX_TUNER; > if (board == dev->board) > break; >+ dev->board = board; > printk("%s: board type fixup: %s\n", dev->name, > saa7134_boards[dev->board].name); > dev->tuner_type = saa7134_boards[dev->board].tuner_type; >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-core.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-core.c 2005-03-07 10:13:26.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-core.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-core.c,v 1.15 2004/11/07 14:44:59 kraxel Exp $ >+ * $Id: saa7134-core.c,v 1.28 2005/02/22 09:56:29 kraxel Exp $ > * > * device driver for philips saa7134 based TV cards > * driver core >@@ -25,6 +25,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kernel.h> > #include <linux/slab.h> > #include <linux/kmod.h> >@@ -88,7 +89,7 @@ MODULE_PARM_DESC(card, "card type"); > static DECLARE_MUTEX(devlist_lock); > LIST_HEAD(saa7134_devlist); > static LIST_HEAD(mops_list); >-unsigned int saa7134_devcount; >+static unsigned int saa7134_devcount; > > #define dprintk(fmt, arg...) if (core_debug) \ > printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) >@@ -620,7 +621,7 @@ static irqreturn_t saa7134_irq(int irq, > dump_statusregs(dev); > #endif > >- if (report & SAA7134_IRQ_REPORT_INTL) >+ if (report & SAA7134_IRQ_REPORT_RDCAP /* _INTL */) > saa7134_irq_video_intl(dev); > > if ((report & SAA7134_IRQ_REPORT_DONE_RA0) && >@@ -642,8 +643,8 @@ static irqreturn_t saa7134_irq(int irq, > SAA7134_IRQ_REPORT_GPIO18)) && > dev->remote) > saa7134_input_irq(dev); >+ } > >- }; > if (10 == loop) { > print_irqstatus(dev,loop,report,status); > if (report & SAA7134_IRQ_REPORT_PE) { >@@ -651,6 +652,13 @@ static irqreturn_t saa7134_irq(int irq, > printk(KERN_WARNING "%s/irq: looping -- " > "clearing PE (parity error!) enable bit\n",dev->name); > saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE); >+ } else if (report & (SAA7134_IRQ_REPORT_GPIO16 | >+ SAA7134_IRQ_REPORT_GPIO18)) { >+ /* disable gpio IRQs */ >+ printk(KERN_WARNING "%s/irq: looping -- " >+ "clearing GPIO enable bits\n",dev->name); >+ saa_clearl(SAA7134_IRQ2, (SAA7134_IRQ2_INTE_GPIO16 | >+ SAA7134_IRQ2_INTE_GPIO18)); > } else { > /* disable all irqs */ > printk(KERN_WARNING "%s/irq: looping -- " >@@ -725,20 +733,7 @@ static int saa7134_hwinit2(struct saa713 > > /* enable IRQ's */ > saa_writel(SAA7134_IRQ1, 0); >- saa_writel(SAA7134_IRQ2, >- SAA7134_IRQ2_INTE_GPIO18 | >- SAA7134_IRQ2_INTE_GPIO18A | >- SAA7134_IRQ2_INTE_GPIO16 | >- SAA7134_IRQ2_INTE_SC2 | >- SAA7134_IRQ2_INTE_SC1 | >- SAA7134_IRQ2_INTE_SC0 | >- /* SAA7134_IRQ2_INTE_DEC5 | FIXME: TRIG_ERR ??? */ >- SAA7134_IRQ2_INTE_DEC3 | >- SAA7134_IRQ2_INTE_DEC2 | >- /* SAA7134_IRQ2_INTE_DEC1 | */ >- SAA7134_IRQ2_INTE_DEC0 | >- SAA7134_IRQ2_INTE_PE | >- SAA7134_IRQ2_INTE_AR); >+ saa_writel(SAA7134_IRQ2, dev->irq2_mask); > > return 0; > } >@@ -959,6 +954,13 @@ static int __devinit saa7134_initdev(str > } > > /* initialize hardware #1 */ >+ dev->irq2_mask = >+ SAA7134_IRQ2_INTE_DEC3 | >+ SAA7134_IRQ2_INTE_DEC2 | >+ SAA7134_IRQ2_INTE_DEC1 | >+ SAA7134_IRQ2_INTE_DEC0 | >+ SAA7134_IRQ2_INTE_PE | >+ SAA7134_IRQ2_INTE_AR; > saa7134_board_init1(dev); > saa7134_hwinit1(dev); > >@@ -1060,6 +1062,9 @@ static int __devinit saa7134_initdev(str > } > list_add_tail(&dev->devlist,&saa7134_devlist); > up(&devlist_lock); >+ >+ /* check for signal */ >+ saa7134_irq_video_intl(dev); > return 0; > > fail5: >@@ -1207,6 +1212,8 @@ static int saa7134_init(void) > > static void saa7134_fini(void) > { >+ if (pending_registered) >+ unregister_module_notifier(&pending_notifier); > pci_unregister_driver(&saa7134_pci_driver); > } > >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-dvb.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-dvb.c 2005-03-07 10:14:28.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-dvb.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-dvb.c,v 1.4 2004/11/07 14:44:59 kraxel Exp $ >+ * $Id: saa7134-dvb.c,v 1.12 2005/02/18 12:28:29 kraxel Exp $ > * > * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] > * >@@ -30,35 +30,211 @@ > #include "saa7134-reg.h" > #include "saa7134.h" > >+#include "dvb-pll.h" >+#include "mt352.h" >+#include "mt352_priv.h" /* FIXME */ >+#include "tda1004x.h" >+ > MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); > MODULE_LICENSE("GPL"); > >+static unsigned int antenna_pwr = 0; >+module_param(antenna_pwr, int, 0444); >+MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); >+ > /* ------------------------------------------------------------------ */ > >-static int dvb_init(struct saa7134_dev *dev) >+static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on) > { >- printk("%s: %s\n",dev->name,__FUNCTION__); >+ u32 ok; >+ >+ if (!on) { >+ saa_setl(SAA7134_GPIO_GPMODE0 >> 2, (1 << 26)); >+ saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26)); >+ return 0; >+ } >+ >+ saa_setl(SAA7134_GPIO_GPMODE0 >> 2, (1 << 26)); >+ saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26)); >+ udelay(10); >+ >+ saa_setl(SAA7134_GPIO_GPMODE0 >> 2, (1 << 28)); >+ saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 28)); >+ udelay(10); >+ saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 28)); >+ udelay(10); >+ ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27); >+ printk("%s: %s %s\n", dev->name, __FUNCTION__, >+ ok ? "on" : "off"); >+ >+ if (!ok) >+ saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26)); >+ return ok; >+} >+ >+static int mt352_pinnacle_init(struct dvb_frontend* fe) >+{ >+ static u8 clock_config [] = { CLOCK_CTL, 0x3d, 0x28 }; >+ static u8 reset [] = { RESET, 0x80 }; >+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; >+ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0xa0 }; >+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x31 }; >+ static u8 fsm_ctl_cfg[] = { 0x7b, 0x04 }; >+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x0f }; >+ static u8 scan_ctl_cfg [] = { SCAN_CTL, 0x0d }; >+ static u8 irq_cfg [] = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 }; >+ struct saa7134_dev *dev= fe->dvb->priv; >+ >+ printk("%s: %s called\n",dev->name,__FUNCTION__); >+ >+ mt352_write(fe, clock_config, sizeof(clock_config)); >+ udelay(200); >+ mt352_write(fe, reset, sizeof(reset)); >+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); >+ mt352_write(fe, agc_cfg, sizeof(agc_cfg)); >+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); >+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); >+ >+ mt352_write(fe, fsm_ctl_cfg, sizeof(fsm_ctl_cfg)); >+ mt352_write(fe, scan_ctl_cfg, sizeof(scan_ctl_cfg)); >+ mt352_write(fe, irq_cfg, sizeof(irq_cfg)); >+ return 0; >+} >+ >+static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, >+ struct dvb_frontend_parameters* params, >+ u8* pllbuf) >+{ >+ static int on = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE; >+ static int off = TDA9887_PRESENT | TDA9887_PORT2_ACTIVE; >+ struct saa7134_dev *dev = fe->dvb->priv; >+ struct v4l2_frequency f; >+ >+ /* set frequency (mt2050) */ >+ f.tuner = 0; >+ f.type = V4L2_TUNER_DIGITAL_TV; >+ f.frequency = params->frequency / 1000 * 16 / 1000; >+ saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&on); >+ saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f); >+ saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&off); >+ >+ pinnacle_antenna_pwr(dev, antenna_pwr); > >+ /* mt352 setup */ >+ mt352_pinnacle_init(fe); >+ pllbuf[0] = 0xc2; >+ pllbuf[1] = 0x00; >+ pllbuf[2] = 0x00; >+ pllbuf[3] = 0x80; >+ pllbuf[4] = 0x00; >+ return 0; >+} >+ >+static struct mt352_config pinnacle_300i = { >+ .demod_address = 0x3c >> 1, >+ .adc_clock = 20333, >+ .if2 = 36150, >+ .no_tuner = 1, >+ .demod_init = mt352_pinnacle_init, >+ .pll_set = mt352_pinnacle_pll_set, >+}; >+ >+/* ------------------------------------------------------------------ */ >+ >+static int medion_cardbus_init(struct dvb_frontend* fe) >+{ >+ /* anything to do here ??? */ >+ return 0; >+} >+ >+static int medion_cardbus_pll_set(struct dvb_frontend* fe, >+ struct dvb_frontend_parameters* params) >+{ >+ struct saa7134_dev *dev = fe->dvb->priv; >+ struct v4l2_frequency f; >+ >+ /* >+ * this instructs tuner.o to set the frequency, the call will >+ * end up in tuner_command(), VIDIOC_S_FREQUENCY switch. >+ * tda9887.o will see that as well. >+ */ >+ f.tuner = 0; >+ f.type = V4L2_TUNER_DIGITAL_TV; >+ f.frequency = params->frequency / 1000 * 16 / 1000; >+ saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f); >+ return 0; >+} >+ >+static int fe_request_firmware(struct dvb_frontend* fe, >+ const struct firmware **fw, char* name) >+{ >+ struct saa7134_dev *dev = fe->dvb->priv; >+ return request_firmware(fw, name, &dev->pci->dev); >+} >+ >+struct tda1004x_config medion_cardbus = { >+ .demod_address = 0x08, /* not sure this is correct */ >+ .invert = 0, >+ .invert_oclk = 0, >+ .pll_init = medion_cardbus_init, >+ .pll_set = medion_cardbus_pll_set, >+ .request_firmware = fe_request_firmware, >+}; >+ >+/* ------------------------------------------------------------------ */ >+ >+static int dvb_init(struct saa7134_dev *dev) >+{ > /* init struct videobuf_dvb */ >+ dev->ts.nr_bufs = 32; >+ dev->ts.nr_packets = 32*4; > dev->dvb.name = dev->name; > videobuf_queue_init(&dev->dvb.dvbq, &saa7134_ts_qops, > dev->pci, &dev->slock, > V4L2_BUF_TYPE_VIDEO_CAPTURE, >- V4L2_FIELD_TOP, >+ V4L2_FIELD_ALTERNATE, > sizeof(struct saa7134_buf), > dev); > >- /* TODO: init frontend */ >- if (NULL == dev->dvb.frontend) >+ switch (dev->board) { >+ case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: >+ printk("%s: pinnacle 300i dvb setup\n",dev->name); >+ dev->dvb.frontend = mt352_attach(&pinnacle_300i, >+ &dev->i2c_adap); >+ break; >+ case SAA7134_BOARD_MD7134: >+ dev->dvb.frontend = tda10046_attach(&medion_cardbus, >+ &dev->i2c_adap); >+ if (NULL == dev->dvb.frontend) >+ printk("%s: Hmm, looks like this is the old MD7134 " >+ "version without DVB-T support\n",dev->name); >+ break; >+ default: >+ printk("%s: Huh? unknown DVB card?\n",dev->name); >+ break; >+ } >+ >+ if (NULL == dev->dvb.frontend) { >+ printk("%s: frontend initialization failed\n",dev->name); > return -1; >+ } > > /* register everything else */ >- return videobuf_dvb_register(&dev->dvb); >+ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); > } > > static int dvb_fini(struct saa7134_dev *dev) > { >+ static int on = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE; >+ > printk("%s: %s\n",dev->name,__FUNCTION__); >+ >+ switch (dev->board) { >+ case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: >+ /* otherwise we don't detect the tuner on next insmod */ >+ saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&on); >+ break; >+ }; > videobuf_dvb_unregister(&dev->dvb); > return 0; > } >@@ -86,6 +262,5 @@ module_exit(dvb_unregister); > /* > * Local variables: > * c-basic-offset: 8 >- * compile-command: "make DVB=1" > * End: > */ >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-empress.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-empress.c 2005-03-07 10:15:53.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-empress.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-empress.c,v 1.3 2004/11/07 13:17:15 kraxel Exp $ >+ * $Id: saa7134-empress.c,v 1.10 2005/02/03 10:24:33 kraxel Exp $ > * > * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] > * >@@ -21,6 +21,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kernel.h> > #include <linux/slab.h> > #include <linux/delay.h> >@@ -50,16 +51,21 @@ MODULE_PARM_DESC(debug,"enable debug mes > > static void ts_reset_encoder(struct saa7134_dev* dev) > { >+ if (!dev->empress_started) >+ return; >+ > saa_writeb(SAA7134_SPECIAL_MODE, 0x00); > msleep(10); > saa_writeb(SAA7134_SPECIAL_MODE, 0x01); > msleep(100); >+ dev->empress_started = 0; > } > >-static int ts_init_encoder(struct saa7134_dev* dev, void* arg) >+static int ts_init_encoder(struct saa7134_dev* dev) > { > ts_reset_encoder(dev); >- saa7134_i2c_call_clients(dev, MPEG_SETPARAMS, arg); >+ saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL); >+ dev->empress_started = 1; > return 0; > } > >@@ -81,18 +87,19 @@ static int ts_open(struct inode *inode, > return -ENODEV; > > dprintk("open minor=%d\n",minor); >- down(&dev->empress_tsq.lock); > err = -EBUSY; >- if (dev->empress_users) >+ if (down_trylock(&dev->empress_tsq.lock)) > goto done; >+ if (dev->empress_users) >+ goto done_up; > > dev->empress_users++; > file->private_data = dev; >- ts_init_encoder(dev, NULL); > err = 0; > >- done: >+done_up: > up(&dev->empress_tsq.lock); >+done: > return err; > } > >@@ -105,6 +112,7 @@ static int ts_release(struct inode *inod > down(&dev->empress_tsq.lock); > if (dev->empress_tsq.reading) > videobuf_read_stop(&dev->empress_tsq); >+ videobuf_mmap_free(&dev->empress_tsq); > dev->empress_users--; > > /* stop the encoder */ >@@ -119,6 +127,9 @@ ts_read(struct file *file, char __user * > { > struct saa7134_dev *dev = file->private_data; > >+ if (!dev->empress_started) >+ ts_init_encoder(dev); >+ > return videobuf_read_stream(&dev->empress_tsq, > data, count, ppos, 0, > file->f_flags & O_NONBLOCK); >@@ -281,8 +292,13 @@ static int ts_do_ioctl(struct inode *ino > case VIDIOC_S_CTRL: > return saa7134_common_ioctl(dev, cmd, arg); > >- case MPEG_SETPARAMS: >- return ts_init_encoder(dev, arg); >+ case VIDIOC_S_MPEGCOMP: >+ saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg); >+ ts_init_encoder(dev); >+ return 0; >+ case VIDIOC_G_MPEGCOMP: >+ saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg); >+ return 0; > > default: > return -ENOIOCTLCMD; >@@ -320,6 +336,26 @@ static struct video_device saa7134_empre > .minor = -1, > }; > >+static void empress_signal_update(void* data) >+{ >+ struct saa7134_dev* dev = (struct saa7134_dev*) data; >+ >+ if (dev->nosignal) { >+ dprintk("no video signal\n"); >+ ts_reset_encoder(dev); >+ } else { >+ dprintk("video signal acquired\n"); >+ if (dev->empress_users) >+ ts_init_encoder(dev); >+ } >+} >+ >+static void empress_signal_change(struct saa7134_dev *dev) >+{ >+ schedule_work(&dev->empress_workqueue); >+} >+ >+ > static int empress_init(struct saa7134_dev *dev) > { > int err; >@@ -335,6 +371,8 @@ static int empress_init(struct saa7134_d > "%s empress (%s)", dev->name, > saa7134_boards[dev->board].name); > >+ INIT_WORK(&dev->empress_workqueue, empress_signal_update, (void*) dev); >+ > err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, > empress_nr[dev->nr]); > if (err < 0) { >@@ -353,6 +391,8 @@ static int empress_init(struct saa7134_d > V4L2_FIELD_ALTERNATE, > sizeof(struct saa7134_buf), > dev); >+ >+ empress_signal_update(dev); > return 0; > } > >@@ -362,6 +402,7 @@ static int empress_fini(struct saa7134_d > > if (NULL == dev->empress_dev) > return 0; >+ flush_scheduled_work(); > video_unregister_device(dev->empress_dev); > dev->empress_dev = NULL; > return 0; >@@ -371,6 +412,7 @@ static struct saa7134_mpeg_ops empress_o > .type = SAA7134_MPEG_EMPRESS, > .init = empress_init, > .fini = empress_fini, >+ .signal_change = empress_signal_change, > }; > > static int __init empress_register(void) >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-i2c.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-i2c.c 2005-03-07 10:12:56.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-i2c.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-i2c.c,v 1.7 2004/11/07 13:17:15 kraxel Exp $ >+ * $Id: saa7134-i2c.c,v 1.10 2005/01/24 17:37:23 kraxel Exp $ > * > * device driver for philips saa7134 based TV cards > * i2c interface support >@@ -24,6 +24,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kernel.h> > #include <linux/slab.h> > #include <linux/delay.h> >@@ -205,7 +206,8 @@ static inline int i2c_send_byte(struct s > dword &= 0x0f; > dword |= (attr << 6); > dword |= ((__u32)data << 8); >- dword |= 0x00 << 16; >+ dword |= 0x00 << 16; /* 100 kHz */ >+// dword |= 0x40 << 16; /* 400 kHz */ > dword |= 0xf0 << 24; > saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword); > #endif >@@ -248,13 +250,24 @@ static int saa7134_i2c_xfer(struct i2c_a > if (!i2c_reset(dev)) > return -EIO; > >+ d2printk("start xfer\n"); > d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name); > for (i = 0; i < num; i++) { > if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) { > /* send address */ >+ d2printk("send address\n"); > addr = msgs[i].addr << 1; > if (msgs[i].flags & I2C_M_RD) > addr |= 1; >+ if (i > 0 && msgs[i].flags & I2C_M_RD) { >+ /* workaround for a saa7134 i2c bug >+ * needed to talk to the mt352 demux >+ * thanks to pinnacle for the hint */ >+ int quirk = 0xfd; >+ d1printk(" [%02x quirk]",quirk); >+ i2c_send_byte(dev,START,quirk); >+ i2c_recv_byte(dev); >+ } > d1printk(" < %02x", addr); > rc = i2c_send_byte(dev,START,addr); > if (rc < 0) >@@ -262,6 +275,7 @@ static int saa7134_i2c_xfer(struct i2c_a > } > if (msgs[i].flags & I2C_M_RD) { > /* read bytes */ >+ d2printk("read bytes\n"); > for (byte = 0; byte < msgs[i].len; byte++) { > d1printk(" ="); > rc = i2c_recv_byte(dev); >@@ -272,6 +286,7 @@ static int saa7134_i2c_xfer(struct i2c_a > } > } else { > /* write bytes */ >+ d2printk("write bytes\n"); > for (byte = 0; byte < msgs[i].len; byte++) { > data = msgs[i].buf[byte]; > d1printk(" %02x", data); >@@ -281,6 +296,7 @@ static int saa7134_i2c_xfer(struct i2c_a > } > } > } >+ d2printk("xfer done\n"); > d1printk(" >"); > i2c_set_attr(dev,STOP); > rc = -EIO; >@@ -313,18 +329,6 @@ static u32 functionality(struct i2c_adap > return I2C_FUNC_SMBUS_EMUL; > } > >-#ifndef I2C_PEC >-static void inc_use(struct i2c_adapter *adap) >-{ >- MOD_INC_USE_COUNT; >-} >- >-static void dec_use(struct i2c_adapter *adap) >-{ >- MOD_DEC_USE_COUNT; >-} >-#endif >- > static int attach_inform(struct i2c_client *client) > { > struct saa7134_dev *dev = client->adapter->algo_data; >@@ -345,12 +349,7 @@ static struct i2c_algorithm saa7134_algo > }; > > static struct i2c_adapter saa7134_adap_template = { >-#ifdef I2C_PEC > .owner = THIS_MODULE, >-#else >- .inc_use = inc_use, >- .dec_use = dec_use, >-#endif > #ifdef I2C_CLASS_TV_ANALOG > .class = I2C_CLASS_TV_ANALOG, > #endif >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-input.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-input.c 2005-03-07 10:16:31.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-input.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-input.c,v 1.12 2004/11/07 13:17:15 kraxel Exp $ >+ * $Id: saa7134-input.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $ > * > * handle saa7134 IR remotes via linux kernel input layer. > * >@@ -20,6 +20,7 @@ > */ > > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/init.h> > #include <linux/delay.h> > #include <linux/sched.h> >@@ -258,6 +259,55 @@ static IR_KEYTAB_TYPE md2819_codes[IR_KE > [ 17 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE- > [ 49 ] = KEY_CHANNELUP // CHANNEL/PAGE+ > }; >+ >+static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = { >+ [ 20 ] = KEY_MUTE, >+ [ 36 ] = KEY_ZOOM, >+ >+ [ 1 ] = KEY_DVD, >+ [ 35 ] = KEY_RADIO, >+ [ 0 ] = KEY_TV, >+ >+ [ 10 ] = KEY_REWIND, >+ [ 8 ] = KEY_PLAYPAUSE, >+ [ 15 ] = KEY_FORWARD, >+ >+ [ 2 ] = KEY_PREVIOUS, >+ [ 7 ] = KEY_STOP, >+ [ 6 ] = KEY_NEXT, >+ >+ [ 12 ] = KEY_UP, >+ [ 14 ] = KEY_DOWN, >+ [ 11 ] = KEY_LEFT, >+ [ 13 ] = KEY_RIGHT, >+ [ 17 ] = KEY_OK, >+ >+ [ 3 ] = KEY_MENU, >+ [ 9 ] = KEY_SETUP, >+ [ 5 ] = KEY_VIDEO, >+ [ 34 ] = KEY_CHANNEL, >+ >+ [ 18 ] = KEY_VOLUMEUP, >+ [ 21 ] = KEY_VOLUMEDOWN, >+ [ 16 ] = KEY_CHANNELUP, >+ [ 19 ] = KEY_CHANNELDOWN, >+ >+ [ 4 ] = KEY_RECORD, >+ >+ [ 22 ] = KEY_KP1, >+ [ 23 ] = KEY_KP2, >+ [ 24 ] = KEY_KP3, >+ [ 25 ] = KEY_KP4, >+ [ 26 ] = KEY_KP5, >+ [ 27 ] = KEY_KP6, >+ [ 28 ] = KEY_KP7, >+ [ 29 ] = KEY_KP8, >+ [ 30 ] = KEY_KP9, >+ [ 31 ] = KEY_KP0, >+ >+ [ 32 ] = KEY_LANGUAGE, >+ [ 33 ] = KEY_SLEEP, >+}; > /* ---------------------------------------------------------------------- */ > > static int build_key(struct saa7134_dev *dev) >@@ -335,6 +385,7 @@ int saa7134_input_init1(struct saa7134_d > break; > case SAA7134_BOARD_CINERGY400: > case SAA7134_BOARD_CINERGY600: >+ case SAA7134_BOARD_CINERGY600_MK3: > ir_codes = cinergy_codes; > mask_keycode = 0x00003f; > mask_keyup = 0x040000; >@@ -353,6 +404,7 @@ int saa7134_input_init1(struct saa7134_d > polling = 50; // ms > break; > case SAA7134_BOARD_MD2819: >+ case SAA7134_BOARD_AVERMEDIA_305: > case SAA7134_BOARD_AVERMEDIA_307: > ir_codes = md2819_codes; > mask_keycode = 0x0007C8; >@@ -362,6 +414,12 @@ int saa7134_input_init1(struct saa7134_d > saa_setb(SAA7134_GPIO_GPMODE0, 0x4); > saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); > break; >+ case SAA7134_BOARD_VIDEOMATE_TV_PVR: >+ ir_codes = videomate_tv_pvr_codes; >+ mask_keycode = 0x00003F; >+ mask_keyup = 0x400000; >+ polling = 50; // ms >+ break; > } > if (NULL == ir_codes) { > printk("%s: Oops: IR config error [card=%d]\n", >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-oss.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-oss.c 2005-03-07 10:16:26.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-oss.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-oss.c,v 1.11 2004/11/07 13:17:15 kraxel Exp $ >+ * $Id: saa7134-oss.c,v 1.13 2004/12/10 12:33:39 kraxel Exp $ > * > * device driver for philips saa7134 based TV cards > * oss dsp interface >@@ -24,6 +24,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kernel.h> > #include <linux/slab.h> > #include <linux/soundcard.h> >@@ -543,6 +544,7 @@ mixer_recsrc_7134(struct saa7134_dev *de > break; > case LINE1: > case LINE2: >+ case LINE2_LEFT: > analog_io = (LINE1 == dev->oss.input) ? 0x00 : 0x08; > rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; > saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); >@@ -566,6 +568,7 @@ mixer_recsrc_7133(struct saa7134_dev *de > value = 0xbbbb32; /* AUX1 */ > break; > case LINE2: >+ case LINE2_LEFT: > value = 0xbbbb54; /* AUX2 */ > break; > } >@@ -608,6 +611,7 @@ mixer_level(struct saa7134_dev *dev, enu > (100 == level) ? 0x00 : 0x10); > break; > case LINE2: >+ case LINE2_LEFT: > saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20, > (100 == level) ? 0x00 : 0x20); > break; >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-ts.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-ts.c 2005-03-07 10:12:29.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-ts.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-ts.c,v 1.12 2004/11/07 13:17:15 kraxel Exp $ >+ * $Id: saa7134-ts.c,v 1.14 2005/02/03 10:24:33 kraxel Exp $ > * > * device driver for philips saa7134 based TV cards > * video4linux video interface >@@ -24,6 +24,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kernel.h> > #include <linux/slab.h> > #include <linux/delay.h> >@@ -220,10 +221,10 @@ void saa7134_irq_ts_done(struct saa7134_ > if (dev->ts_q.curr) { > field = dev->ts_q.curr->vb.field; > if (field == V4L2_FIELD_TOP) { >- if ((status & 0x100000) != 0x100000) >+ if ((status & 0x100000) != 0x000000) > goto done; > } else { >- if ((status & 0x100000) != 0x000000) >+ if ((status & 0x100000) != 0x100000) > goto done; > } > saa7134_buffer_finish(dev,&dev->ts_q,STATE_DONE); >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-tvaudio.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-tvaudio.c 2005-03-07 10:12:25.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-tvaudio.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-tvaudio.c,v 1.17 2004/11/07 13:17:15 kraxel Exp $ >+ * $Id: saa7134-tvaudio.c,v 1.22 2005/01/07 13:11:19 kraxel Exp $ > * > * device driver for philips saa7134 based TV cards > * tv audio decoder (fm stereo, nicam, ...) >@@ -24,6 +24,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kernel.h> > #include <linux/slab.h> > #include <linux/delay.h> >@@ -237,13 +238,14 @@ static void mute_input_7134(struct saa71 > > if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device) > /* 7134 mute */ >- saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xff : 0xbb); >+ saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xbf : 0xbb); > > /* switch internal audio mux */ > switch (in->amux) { >- case TV: ausel=0xc0; ics=0x00; ocs=0x02; break; >- case LINE1: ausel=0x80; ics=0x00; ocs=0x00; break; >- case LINE2: ausel=0x80; ics=0x08; ocs=0x01; break; >+ case TV: ausel=0xc0; ics=0x00; ocs=0x02; break; >+ case LINE1: ausel=0x80; ics=0x00; ocs=0x00; break; >+ case LINE2: ausel=0x80; ics=0x08; ocs=0x01; break; >+ case LINE2_LEFT: ausel=0x80; ics=0x08; ocs=0x05; break; > } > saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel); > saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics); >@@ -437,15 +439,16 @@ static int tvaudio_getstereo(struct saa7 > nicam = saa_readb(SAA7134_NICAM_STATUS); > dprintk("getstereo: nicam=0x%x\n",nicam); > switch (nicam & 0x0b) { >- case 0x08: >- retval = V4L2_TUNER_SUB_MONO; >- break; > case 0x09: > retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; > break; > case 0x0a: > retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; > break; >+ case 0x08: >+ default: >+ retval = V4L2_TUNER_SUB_MONO; >+ break; > } > break; > } >@@ -748,9 +751,16 @@ static int mute_input_7133(struct saa713 > int mask; > > switch (dev->input->amux) { >- case TV: reg = 0x02; break; >- case LINE1: reg = 0x00; break; >- case LINE2: reg = 0x01; break; >+ case TV: >+ reg = 0x02; >+ break; >+ case LINE1: >+ reg = 0x00; >+ break; >+ case LINE2: >+ case LINE2_LEFT: >+ reg = 0x01; >+ break; > } > if (dev->ctl_mute) > reg = 0x07; >@@ -869,6 +879,21 @@ static int tvaudio_thread_ddep(void *dat > /* ------------------------------------------------------------------ */ > /* common stuff + external entry points */ > >+static void saa7134_enable_i2s(struct saa7134_dev *dev) >+{ >+ int i2s_format; >+ >+ if (!card_is_empress(dev)) >+ return; >+ i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01; >+ >+ /* enable I2S audio output for the mpeg encoder */ >+ saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80); >+ saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format); >+ saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F); >+ saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01); >+} >+ > int saa7134_tvaudio_rx2mode(u32 rx) > { > u32 mode; >@@ -911,6 +936,7 @@ void saa7134_tvaudio_setinput(struct saa > mute_input_7133(dev); > break; > } >+ saa7134_enable_i2s(dev); > } > > void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level) >@@ -946,18 +972,6 @@ int saa7134_tvaudio_init2(struct saa7134 > DECLARE_MUTEX_LOCKED(sem); > int (*my_thread)(void *data) = NULL; > >- /* enable I2S audio output */ >- if (card_is_empress(dev)) { >- int i2sform = (48000 == dev->oss.rate) >- ? 0x01 : 0x00; >- >- /* enable I2S output */ >- saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80); >- saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2sform); >- saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F); >- saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01); >- } >- > switch (dev->pci->device) { > case PCI_DEVICE_ID_PHILIPS_SAA7134: > my_thread = tvaudio_thread; >@@ -977,9 +991,10 @@ int saa7134_tvaudio_init2(struct saa7134 > if (dev->thread.pid < 0) > printk(KERN_WARNING "%s: kernel_thread() failed\n", > dev->name); >- wake_up_interruptible(&dev->thread.wq); >+ saa7134_tvaudio_do_scan(dev); > } > >+ saa7134_enable_i2s(dev); > return 0; > } > >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-vbi.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-vbi.c 2005-03-07 10:15:23.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-vbi.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-vbi.c,v 1.5 2004/11/07 13:17:15 kraxel Exp $ >+ * $Id: saa7134-vbi.c,v 1.6 2004/12/10 12:33:39 kraxel Exp $ > * > * device driver for philips saa7134 based TV cards > * video4linux video interface >@@ -24,6 +24,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kernel.h> > #include <linux/slab.h> > >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134-video.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134-video.c 2005-03-07 10:12:58.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134-video.c 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134-video.c,v 1.19 2004/11/07 14:44:59 kraxel Exp $ >+ * $Id: saa7134-video.c,v 1.28 2005/02/15 15:59:35 kraxel Exp $ > * > * device driver for philips saa7134 based TV cards > * video4linux video interface >@@ -24,6 +24,7 @@ > #include <linux/init.h> > #include <linux/list.h> > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/kernel.h> > #include <linux/slab.h> > >@@ -267,6 +268,24 @@ static struct saa7134_tvnorm tvnorms[] = > .chroma_ctrl2 = 0x06, > .vgate_misc = 0x1c, > >+ },{ >+ .name = "PAL-60", >+ .id = V4L2_STD_PAL_60, >+ >+ .h_start = 0, >+ .h_stop = 719, >+ .video_v_start = 22, >+ .video_v_stop = 22+239, >+ .vbi_v_start = 10, /* FIXME */ >+ .vbi_v_stop = 21, /* FIXME */ >+ .src_timing = 1, >+ >+ .sync_control = 0x18, >+ .luma_control = 0x40, >+ .chroma_ctrl1 = 0x81, >+ .chroma_gain = 0x2a, >+ .chroma_ctrl2 = 0x06, >+ .vgate_misc = 0x1c, > } > }; > #define TVNORMS ARRAY_SIZE(tvnorms) >@@ -443,11 +462,10 @@ void res_free(struct saa7134_dev *dev, s > > static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) > { >- int luma_control,sync_control,mux,nosignal; >+ int luma_control,sync_control,mux; > > dprintk("set tv norm = %s\n",norm->name); > dev->tvnorm = norm; >- nosignal = (0 == (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03)); > > mux = card_in(dev,dev->ctl_input).vmux; > luma_control = norm->luma_control; >@@ -455,7 +473,7 @@ static void set_tvnorm(struct saa7134_de > > if (mux > 5) > luma_control |= 0x80; /* svideo */ >- if (noninterlaced || nosignal) >+ if (noninterlaced || dev->nosignal) > sync_control |= 0x20; > > /* setup cropping */ >@@ -1359,6 +1377,9 @@ static int video_release(struct inode *i > res_free(dev,fh,RESOURCE_VBI); > } > >+ /* free stuff */ >+ videobuf_mmap_free(&fh->cap); >+ videobuf_mmap_free(&fh->vbi); > saa7134_pgtable_free(dev->pci,&fh->pt_cap); > saa7134_pgtable_free(dev->pci,&fh->pt_vbi); > >@@ -1472,6 +1493,7 @@ static int saa7134_try_fmt(struct saa713 > f->fmt.pix.width = maxw; > if (f->fmt.pix.height > maxh) > f->fmt.pix.height = maxh; >+ f->fmt.pix.width &= ~0x03; > f->fmt.pix.bytesperline = > (f->fmt.pix.width * fmt->depth) >> 3; > f->fmt.pix.sizeimage = >@@ -2267,7 +2289,7 @@ int saa7134_video_init1(struct saa7134_d > dev->ctl_hue = ctrl_by_id(V4L2_CID_HUE)->default_value; > dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value; > dev->ctl_volume = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value; >- dev->ctl_mute = ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value; >+ dev->ctl_mute = 1; // ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value; > dev->ctl_invert = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value; > dev->ctl_automute = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value; > >@@ -2317,24 +2339,31 @@ int saa7134_video_fini(struct saa7134_de > void saa7134_irq_video_intl(struct saa7134_dev *dev) > { > static const char *st[] = { >- "no signal", "found NTSC", "found PAL", "found SECAM" }; >- int norm; >+ "(no signal)", "NTSC", "PAL", "SECAM" }; >+ u32 st1,st2; > >- norm = saa_readb(SAA7134_STATUS_VIDEO1) & 0x03; >- dprintk("DCSDT: %s\n",st[norm]); >+ st1 = saa_readb(SAA7134_STATUS_VIDEO1); >+ st2 = saa_readb(SAA7134_STATUS_VIDEO2); >+ dprintk("DCSDT: pll: %s, sync: %s, norm: %s\n", >+ (st1 & 0x40) ? "not locked" : "locked", >+ (st2 & 0x40) ? "no" : "yes", >+ st[st1 & 0x03]); >+ dev->nosignal = (st1 & 0x40) || (st2 & 0x40); > >- if (0 != norm) { >- /* wake up tvaudio audio carrier scan thread */ >- saa7134_tvaudio_do_scan(dev); >- if (!noninterlaced) >- saa_clearb(SAA7134_SYNC_CTRL, 0x20); >- } else { >+ if (dev->nosignal) { > /* no video signal -> mute audio */ > if (dev->ctl_automute) > dev->automute = 1; > saa7134_tvaudio_setmute(dev); > saa_setb(SAA7134_SYNC_CTRL, 0x20); >+ } else { >+ /* wake up tvaudio audio carrier scan thread */ >+ saa7134_tvaudio_do_scan(dev); >+ if (!noninterlaced) >+ saa_clearb(SAA7134_SYNC_CTRL, 0x20); > } >+ if (dev->mops && dev->mops->signal_change) >+ dev->mops->signal_change(dev); > } > > void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status) >Index: linux-2.6.11/drivers/media/video/saa7134/saa7134.h >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/saa7134/saa7134.h 2005-03-07 10:14:47.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/saa7134/saa7134.h 2005-03-08 10:33:27.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: saa7134.h,v 1.27 2004/11/04 11:03:52 kraxel Exp $ >+ * $Id: saa7134.h,v 1.38 2005/03/07 12:01:51 kraxel Exp $ > * > * v4l2 device driver for philips saa7134 based TV cards > * >@@ -64,6 +64,7 @@ enum saa7134_audio_in { > TV = 1, > LINE1 = 2, > LINE2 = 3, >+ LINE2_LEFT, > }; > > enum saa7134_video_out { >@@ -156,11 +157,11 @@ struct saa7134_format { > #define SAA7134_BOARD_AVACSSMARTTV 32 > #define SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER 33 > #define SAA7134_BOARD_NOVAC_PRIMETV7133 34 >-#define SAA7134_BOARD_AVERMEDIA_305 35 >+#define SAA7134_BOARD_AVERMEDIA_STUDIO_305 35 > #define SAA7133_BOARD_UPMOST_PURPLE_TV 36 > #define SAA7134_BOARD_ITEMS_MTV005 37 > #define SAA7134_BOARD_CINERGY200 38 >-#define SAA7134_BOARD_FLYTVPLATINUM 39 >+#define SAA7134_BOARD_FLYTVPLATINUM_MINI 39 > #define SAA7134_BOARD_VIDEOMATE_TV_PVR 40 > #define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS 41 > #define SAA7134_BOARD_SABRENT_SBTTVFM 42 >@@ -169,6 +170,14 @@ struct saa7134_format { > #define SAA7134_BOARD_AVERMEDIA_307 45 > #define SAA7134_BOARD_AVERMEDIA_CARDBUS 46 > #define SAA7134_BOARD_CINERGY400_CARDBUS 47 >+#define SAA7134_BOARD_CINERGY600_MK3 48 >+#define SAA7134_BOARD_VIDEOMATE_GOLD_PLUS 49 >+#define SAA7134_BOARD_PINNACLE_300I_DVBT_PAL 50 >+#define SAA7134_BOARD_PROVIDEO_PV952 51 >+#define SAA7134_BOARD_AVERMEDIA_305 52 >+#define SAA7135_BOARD_ASUSTeK_TVFM7135 53 >+#define SAA7134_BOARD_FLYTVPLATINUM_FM 54 >+#define SAA7134_BOARD_FLYDVBTDUO 55 > > #define SAA7134_MAXBOARDS 8 > #define SAA7134_INPUT_MAX 8 >@@ -355,6 +364,7 @@ struct saa7134_mpeg_ops { > struct list_head next; > int (*init)(struct saa7134_dev *dev); > int (*fini)(struct saa7134_dev *dev); >+ void (*signal_change)(struct saa7134_dev *dev); > }; > > /* global device status */ >@@ -390,6 +400,7 @@ struct saa7134_dev { > unsigned int tuner_type; > unsigned int tda9887_conf; > unsigned int gpio_value; >+ unsigned int irq2_mask; > > /* i2c i/o */ > struct i2c_adapter i2c_adap; >@@ -437,6 +448,7 @@ struct saa7134_dev { > struct saa7134_input *hw_input; > unsigned int hw_mute; > int last_carrier; >+ int nosignal; > > /* SAA7134_MPEG_* */ > struct saa7134_ts ts; >@@ -447,6 +459,8 @@ struct saa7134_dev { > struct video_device *empress_dev; > struct videobuf_queue empress_tsq; > unsigned int empress_users; >+ struct work_struct empress_workqueue; >+ int empress_started; > > /* SAA7134_MPEG_DVB only */ > struct videobuf_dvb dvb; >@@ -476,7 +490,6 @@ struct saa7134_dev { > /* saa7134-core.c */ > > extern struct list_head saa7134_devlist; >-extern unsigned int saa7134_devcount; > > void saa7134_print_ioctl(char *name, unsigned int cmd); > void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); >Index: linux-2.6.11/drivers/media/video/stradis.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/stradis.c 2005-03-07 10:15:16.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/stradis.c 2005-03-08 10:33:15.000000000 +0100 >@@ -2181,12 +2181,9 @@ static void release_saa(void) > /* unmap and free memory */ > saa->audhead = saa->audtail = saa->osdhead = 0; > saa->vidhead = saa->vidtail = saa->osdtail = 0; >- if (saa->vidbuf) >- vfree(saa->vidbuf); >- if (saa->audbuf) >- vfree(saa->audbuf); >- if (saa->osdbuf) >- vfree(saa->osdbuf); >+ vfree(saa->vidbuf); >+ vfree(saa->audbuf); >+ vfree(saa->osdbuf); > if (saa->dmavid2) > kfree((void *) saa->dmavid2); > saa->audbuf = saa->vidbuf = saa->osdbuf = NULL; >Index: linux-2.6.11/drivers/media/video/tda8290.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/media/video/tda8290.c 2005-03-07 18:13:02.000000000 +0100 >@@ -0,0 +1,224 @@ >+/* >+ * $Id: tda8290.c,v 1.7 2005/03/07 12:01:51 kraxel Exp $ >+ * >+ * i2c tv tuner chip device driver >+ * controls the philips tda8290+75 tuner chip combo. >+ */ >+#include <linux/i2c.h> >+#include <linux/videodev.h> >+#include <linux/delay.h> >+#include <media/tuner.h> >+ >+/* ---------------------------------------------------------------------- */ >+ >+struct freq_entry { >+ u16 freq; >+ u8 value; >+}; >+ >+static struct freq_entry band_table[] = { >+ { 0x2DF4, 0x1C }, >+ { 0x2574, 0x14 }, >+ { 0x22B4, 0x0C }, >+ { 0x20D4, 0x0B }, >+ { 0x1E74, 0x3B }, >+ { 0x1C34, 0x33 }, >+ { 0x16F4, 0x5B }, >+ { 0x1454, 0x53 }, >+ { 0x12D4, 0x52 }, >+ { 0x1034, 0x4A }, >+ { 0x0EE4, 0x7A }, >+ { 0x0D34, 0x72 }, >+ { 0x0B54, 0x9A }, >+ { 0x0914, 0x91 }, >+ { 0x07F4, 0x89 }, >+ { 0x0774, 0xB9 }, >+ { 0x067B, 0xB1 }, >+ { 0x0634, 0xD9 }, >+ { 0x05A4, 0xD8 }, // FM radio >+ { 0x0494, 0xD0 }, >+ { 0x03BC, 0xC8 }, >+ { 0x0394, 0xF8 }, // 57250000 Hz >+ { 0x0000, 0xF0 }, // 0 >+}; >+ >+static struct freq_entry div_table[] = { >+ { 0x1C34, 3 }, >+ { 0x0D34, 2 }, >+ { 0x067B, 1 }, >+ { 0x0000, 0 }, >+}; >+ >+static struct freq_entry agc_table[] = { >+ { 0x22B4, 0x8F }, >+ { 0x0B54, 0x9F }, >+ { 0x09A4, 0x8F }, >+ { 0x0554, 0x9F }, >+ { 0x0000, 0xBF }, >+}; >+ >+static __u8 get_freq_entry( struct freq_entry* table, __u16 freq) >+{ >+ while(table->freq && table->freq > freq) >+ table++; >+ return table->value; >+} >+ >+/* ---------------------------------------------------------------------- */ >+ >+static unsigned char i2c_enable_bridge[2] = { 0x21, 0xC0 }; >+static unsigned char i2c_disable_bridge[2] = { 0x21, 0x80 }; >+static unsigned char i2c_init_tda8275[14] = { 0x00, 0x00, 0x00, 0x00, >+ 0x7C, 0x04, 0xA3, 0x3F, >+ 0x2A, 0x04, 0xFF, 0x00, >+ 0x00, 0x40 }; >+static unsigned char i2c_set_VS[2] = { 0x30, 0x6F }; >+static unsigned char i2c_set_GP01_CF[2] = { 0x20, 0x0B }; >+static unsigned char i2c_tda8290_reset[2] = { 0x00, 0x00 }; >+static unsigned char i2c_gainset_off[2] = { 0x28, 0x14 }; >+static unsigned char i2c_gainset_on[2] = { 0x28, 0x54 }; >+static unsigned char i2c_agc3_00[2] = { 0x80, 0x00 }; >+static unsigned char i2c_agc2_BF[2] = { 0x60, 0xBF }; >+static unsigned char i2c_cb1_D2[2] = { 0x30, 0xD2 }; >+static unsigned char i2c_cb1_56[2] = { 0x30, 0x56 }; >+static unsigned char i2c_cb1_52[2] = { 0x30, 0x52 }; >+static unsigned char i2c_cb1_50[2] = { 0x30, 0x50 }; >+static unsigned char i2c_agc2_7F[2] = { 0x60, 0x7F }; >+static unsigned char i2c_agc3_08[2] = { 0x80, 0x08 }; >+ >+static struct i2c_msg i2c_msg_init[] = { >+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_init_tda8275), i2c_init_tda8275 }, >+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge }, >+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_VS), i2c_set_VS }, >+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_GP01_CF), i2c_set_GP01_CF }, >+}; >+ >+static struct i2c_msg i2c_msg_prolog[] = { >+// { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_easy_mode), i2c_easy_mode }, >+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_off), i2c_gainset_off }, >+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_reset), i2c_tda8290_reset }, >+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge }, >+}; >+ >+static struct i2c_msg i2c_msg_config[] = { >+// { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_set_freq), i2c_set_freq }, >+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_00), i2c_agc3_00 }, >+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_BF), i2c_agc2_BF }, >+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D2), i2c_cb1_D2 }, >+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_56), i2c_cb1_56 }, >+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_52), i2c_cb1_52 }, >+}; >+ >+static struct i2c_msg i2c_msg_epilog[] = { >+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_50), i2c_cb1_50 }, >+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_7F), i2c_agc2_7F }, >+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_08), i2c_agc3_08 }, >+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge }, >+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_on), i2c_gainset_on }, >+}; >+ >+static int tda8290_tune(struct i2c_client *c) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ struct i2c_msg easy_mode = >+ { I2C_ADDR_TDA8290, 0, 2, t->i2c_easy_mode }; >+ struct i2c_msg set_freq = >+ { I2C_ADDR_TDA8275, 0, 8, t->i2c_set_freq }; >+ >+ i2c_transfer(c->adapter, &easy_mode, 1); >+ i2c_transfer(c->adapter, i2c_msg_prolog, ARRAY_SIZE(i2c_msg_prolog)); >+ >+ i2c_transfer(c->adapter, &set_freq, 1); >+ i2c_transfer(c->adapter, i2c_msg_config, ARRAY_SIZE(i2c_msg_config)); >+ >+ msleep(550); >+ i2c_transfer(c->adapter, i2c_msg_epilog, ARRAY_SIZE(i2c_msg_epilog)); >+ return 0; >+} >+ >+static void set_frequency(struct tuner *t, u16 ifc) >+{ >+ u32 N = (((t->freq<<3)+ifc)&0x3fffc); >+ >+ N = N >> get_freq_entry(div_table, t->freq); >+ t->i2c_set_freq[0] = 0; >+ t->i2c_set_freq[1] = (unsigned char)(N>>8); >+ t->i2c_set_freq[2] = (unsigned char) N; >+ t->i2c_set_freq[3] = 0x40; >+ t->i2c_set_freq[4] = 0x52; >+ t->i2c_set_freq[5] = get_freq_entry(band_table, t->freq); >+ t->i2c_set_freq[6] = get_freq_entry(agc_table, t->freq); >+ t->i2c_set_freq[7] = 0x8f; >+} >+ >+#define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC) >+#define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B) >+#define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H) >+#define V4L2_STD_DK (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK) >+ >+static void set_audio(struct tuner *t) >+{ >+ t->i2c_easy_mode[0] = 0x01; >+ >+ if (t->std & V4L2_STD_MN) >+ t->i2c_easy_mode[1] = 0x01; >+ else if (t->std & V4L2_STD_B) >+ t->i2c_easy_mode[1] = 0x02; >+ else if (t->std & V4L2_STD_GH) >+ t->i2c_easy_mode[1] = 0x04; >+ else if (t->std & V4L2_STD_PAL_I) >+ t->i2c_easy_mode[1] = 0x08; >+ else if (t->std & V4L2_STD_DK) >+ t->i2c_easy_mode[1] = 0x10; >+ else if (t->std & V4L2_STD_SECAM_L) >+ t->i2c_easy_mode[1] = 0x20; >+} >+ >+static void set_tv_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ set_audio(t); >+ set_frequency(t, 864); >+ tda8290_tune(c); >+} >+ >+static void set_radio_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ set_frequency(t, 704); >+ tda8290_tune(c); >+} >+ >+static int has_signal(struct i2c_client *c) >+{ >+ unsigned char i2c_get_afc[1] = { 0x1B }; >+ unsigned char afc = 0; >+ >+ i2c_master_send(c, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); >+ i2c_master_recv(c, &afc, 1); >+ return (afc & 0x80)? 65535:0; >+} >+ >+int tda8290_init(struct i2c_client *c) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ strlcpy(c->name, "tda8290+75", sizeof(c->name)); >+ tuner_info("tuner: type set to %s\n", c->name); >+ t->tv_freq = set_tv_freq; >+ t->radio_freq = set_radio_freq; >+ t->has_signal = has_signal; >+ >+ i2c_master_send(c, i2c_enable_bridge, ARRAY_SIZE(i2c_enable_bridge)); >+ i2c_transfer(c->adapter, i2c_msg_init, ARRAY_SIZE(i2c_msg_init)); >+ return 0; >+} >+ >+/* >+ * Overrides for Emacs so that we follow Linus's tabbing style. >+ * --------------------------------------------------------------------------- >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/video/tda9887.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/tda9887.c 2005-03-07 10:16:07.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/tda9887.c 2005-03-07 18:13:01.000000000 +0100 >@@ -557,7 +557,7 @@ static int tda9887_configure(struct tda9 > #if 0 > /* This as-is breaks some cards, must be fixed in a > * card-specific way, probably using TDA9887_SET_CONFIG to >- * turn on/off port2 */ >+ * turn on/off port2 */ > if (t->std & V4L2_STD_SECAM_L) { > /* secam fixup (FIXME: move this to tvnorms array?) */ > buf[1] &= ~cOutputPort2Inactive; >Index: linux-2.6.11/drivers/media/video/tuner-core.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/media/video/tuner-core.c 2005-03-07 18:13:01.000000000 +0100 >@@ -0,0 +1,443 @@ >+/* >+ * $Id: tuner-core.c,v 1.5 2005/02/15 15:59:35 kraxel Exp $ >+ * >+ * i2c tv tuner chip device driver >+ * core core, i.e. kernel interfaces, registering and so on >+ */ >+ >+#include <linux/module.h> >+#include <linux/moduleparam.h> >+#include <linux/kernel.h> >+#include <linux/sched.h> >+#include <linux/string.h> >+#include <linux/timer.h> >+#include <linux/delay.h> >+#include <linux/errno.h> >+#include <linux/slab.h> >+#include <linux/poll.h> >+#include <linux/i2c.h> >+#include <linux/types.h> >+#include <linux/videodev.h> >+#include <linux/init.h> >+ >+#include <media/tuner.h> >+#include <media/audiochip.h> >+ >+#define UNSET (-1U) >+ >+/* standard i2c insmod options */ >+static unsigned short normal_i2c[] = { >+ 0x4b, /* tda8290 */ >+ I2C_CLIENT_END >+}; >+static unsigned short normal_i2c_range[] = { >+ 0x60, 0x6f, >+ I2C_CLIENT_END >+}; >+I2C_CLIENT_INSMOD; >+ >+/* insmod options used at init time => read/only */ >+static unsigned int addr = 0; >+module_param(addr, int, 0444); >+ >+/* insmod options used at runtime => read/write */ >+unsigned int tuner_debug = 0; >+module_param(tuner_debug, int, 0644); >+ >+static unsigned int tv_range[2] = { 44, 958 }; >+static unsigned int radio_range[2] = { 65, 108 }; >+ >+module_param_array(tv_range, int, NULL, 0644); >+module_param_array(radio_range, int, NULL, 0644); >+ >+MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); >+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); >+MODULE_LICENSE("GPL"); >+ >+static int this_adap; >+ >+static struct i2c_driver driver; >+static struct i2c_client client_template; >+ >+/* ---------------------------------------------------------------------- */ >+ >+// Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz >+static void set_tv_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ if (t->type == UNSET) { >+ tuner_info("tuner type not set\n"); >+ return; >+ } >+ if (NULL == t->tv_freq) { >+ tuner_info("Huh? tv_set is NULL?\n"); >+ return; >+ } >+ if (freq < tv_range[0]*16 || freq > tv_range[1]*16) { >+ /* FIXME: better do that chip-specific, but >+ right now we don't have that in the config >+ struct and this way is still better than no >+ check at all */ >+ tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n", >+ freq/16,freq%16*100/16,tv_range[0],tv_range[1]); >+ return; >+ } >+ t->tv_freq(c,freq); >+} >+ >+static void set_radio_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ if (t->type == UNSET) { >+ tuner_info("tuner type not set\n"); >+ return; >+ } >+ if (NULL == t->radio_freq) { >+ tuner_info("no radio tuning for this one, sorry.\n"); >+ return; >+ } >+ if (freq < radio_range[0]*16 || freq > radio_range[1]*16) { >+ tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n", >+ freq/16,freq%16*100/16, >+ radio_range[0],radio_range[1]); >+ return; >+ } >+ t->radio_freq(c,freq); >+} >+ >+static void set_freq(struct i2c_client *c, unsigned long freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ switch (t->mode) { >+ case V4L2_TUNER_RADIO: >+ tuner_dbg("radio freq set to %lu.%02lu\n", >+ freq/16,freq%16*100/16); >+ set_radio_freq(c,freq); >+ break; >+ case V4L2_TUNER_ANALOG_TV: >+ case V4L2_TUNER_DIGITAL_TV: >+ tuner_dbg("tv freq set to %lu.%02lu\n", >+ freq/16,freq%16*100/16); >+ set_tv_freq(c, freq); >+ break; >+ } >+ t->freq = freq; >+} >+ >+static void set_type(struct i2c_client *c, unsigned int type) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ /* sanity check */ >+ if (type == UNSET || type == TUNER_ABSENT) >+ return; >+ if (type >= tuner_count) >+ return; >+ >+ if (NULL == t->i2c.dev.driver) { >+ /* not registered yet */ >+ t->type = type; >+ return; >+ } >+ if (t->initialized) >+ /* run only once */ >+ return; >+ >+ t->initialized = 1; >+ t->type = type; >+ switch (t->type) { >+ case TUNER_MT2032: >+ microtune_init(c); >+ break; >+ case TUNER_PHILIPS_TDA8290: >+ tda8290_init(c); >+ break; >+ default: >+ default_tuner_init(c); >+ break; >+ } >+} >+ >+static char pal[] = "-"; >+module_param_string(pal, pal, 0644, sizeof(pal)); >+ >+static int tuner_fixup_std(struct tuner *t) >+{ >+ if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { >+ /* get more precise norm info from insmod option */ >+ switch (pal[0]) { >+ case 'b': >+ case 'B': >+ case 'g': >+ case 'G': >+ tuner_dbg("insmod fixup: PAL => PAL-BG\n"); >+ t->std = V4L2_STD_PAL_BG; >+ break; >+ case 'i': >+ case 'I': >+ tuner_dbg("insmod fixup: PAL => PAL-I\n"); >+ t->std = V4L2_STD_PAL_I; >+ break; >+ case 'd': >+ case 'D': >+ case 'k': >+ case 'K': >+ tuner_dbg("insmod fixup: PAL => PAL-DK\n"); >+ t->std = V4L2_STD_PAL_DK; >+ break; >+ } >+ } >+ return 0; >+} >+ >+/* ---------------------------------------------------------------------- */ >+ >+static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) >+{ >+ struct tuner *t; >+ >+ if (this_adap > 0) >+ return -1; >+ this_adap++; >+ >+ client_template.adapter = adap; >+ client_template.addr = addr; >+ >+ t = kmalloc(sizeof(struct tuner),GFP_KERNEL); >+ if (NULL == t) >+ return -ENOMEM; >+ memset(t,0,sizeof(struct tuner)); >+ memcpy(&t->i2c,&client_template,sizeof(struct i2c_client)); >+ i2c_set_clientdata(&t->i2c, t); >+ t->type = UNSET; >+ t->radio_if2 = 10700*1000; // 10.7MHz - FM radio >+ >+ i2c_attach_client(&t->i2c); >+ tuner_info("chip found @ 0x%x (%s)\n", >+ addr << 1, adap->name); >+ set_type(&t->i2c, t->type); >+ return 0; >+} >+ >+static int tuner_probe(struct i2c_adapter *adap) >+{ >+ if (0 != addr) { >+ normal_i2c[0] = addr; >+ normal_i2c_range[0] = addr; >+ normal_i2c_range[1] = addr; >+ } >+ this_adap = 0; >+ >+ if (adap->class & I2C_CLASS_TV_ANALOG) >+ return i2c_probe(adap, &addr_data, tuner_attach); >+ return 0; >+} >+ >+static int tuner_detach(struct i2c_client *client) >+{ >+ struct tuner *t = i2c_get_clientdata(client); >+ >+ i2c_detach_client(&t->i2c); >+ kfree(t); >+ return 0; >+} >+ >+#define SWITCH_V4L2 if (!t->using_v4l2 && tuner_debug) \ >+ tuner_info("switching to v4l2\n"); \ >+ t->using_v4l2 = 1; >+#define CHECK_V4L2 if (t->using_v4l2) { if (tuner_debug) \ >+ tuner_info("ignore v4l1 call\n"); \ >+ return 0; } >+ >+static int >+tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) >+{ >+ struct tuner *t = i2c_get_clientdata(client); >+ unsigned int *iarg = (int*)arg; >+ >+ switch (cmd) { >+ >+ /* --- configuration --- */ >+ case TUNER_SET_TYPE: >+ set_type(client,*iarg); >+ break; >+ case AUDC_SET_RADIO: >+ if (V4L2_TUNER_RADIO != t->mode) { >+ set_tv_freq(client,400 * 16); >+ t->mode = V4L2_TUNER_RADIO; >+ } >+ break; >+ case AUDC_CONFIG_PINNACLE: >+ switch (*iarg) { >+ case 2: >+ tuner_dbg("pinnacle pal\n"); >+ t->radio_if2 = 33300 * 1000; >+ break; >+ case 3: >+ tuner_dbg("pinnacle ntsc\n"); >+ t->radio_if2 = 41300 * 1000; >+ break; >+ } >+ break; >+ >+ /* --- v4l ioctls --- */ >+ /* take care: bttv does userspace copying, we'll get a >+ kernel pointer here... */ >+ case VIDIOCSCHAN: >+ { >+ static const v4l2_std_id map[] = { >+ [ VIDEO_MODE_PAL ] = V4L2_STD_PAL, >+ [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M, >+ [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM, >+ [ 4 /* bttv */ ] = V4L2_STD_PAL_M, >+ [ 5 /* bttv */ ] = V4L2_STD_PAL_N, >+ [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, >+ }; >+ struct video_channel *vc = arg; >+ >+ CHECK_V4L2; >+ t->mode = V4L2_TUNER_ANALOG_TV; >+ if (vc->norm < ARRAY_SIZE(map)) >+ t->std = map[vc->norm]; >+ tuner_fixup_std(t); >+ if (t->freq) >+ set_tv_freq(client,t->freq); >+ return 0; >+ } >+ case VIDIOCSFREQ: >+ { >+ unsigned long *v = arg; >+ >+ CHECK_V4L2; >+ set_freq(client,*v); >+ return 0; >+ } >+ case VIDIOCGTUNER: >+ { >+ struct video_tuner *vt = arg; >+ >+ CHECK_V4L2; >+ if (V4L2_TUNER_RADIO == t->mode && t->has_signal) >+ vt->signal = t->has_signal(client); >+ return 0; >+ } >+ case VIDIOCGAUDIO: >+ { >+ struct video_audio *va = arg; >+ >+ CHECK_V4L2; >+ if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) >+ va->mode = t->is_stereo(client) >+ ? VIDEO_SOUND_STEREO >+ : VIDEO_SOUND_MONO; >+ return 0; >+ } >+ >+ case VIDIOC_S_STD: >+ { >+ v4l2_std_id *id = arg; >+ >+ SWITCH_V4L2; >+ t->mode = V4L2_TUNER_ANALOG_TV; >+ t->std = *id; >+ tuner_fixup_std(t); >+ if (t->freq) >+ set_freq(client,t->freq); >+ break; >+ } >+ case VIDIOC_S_FREQUENCY: >+ { >+ struct v4l2_frequency *f = arg; >+ >+ SWITCH_V4L2; >+ if (V4L2_TUNER_RADIO == f->type && >+ V4L2_TUNER_RADIO != t->mode) >+ set_tv_freq(client,400*16); >+ t->mode = f->type; >+ t->freq = f->frequency; >+ set_freq(client,t->freq); >+ break; >+ } >+ case VIDIOC_G_TUNER: >+ { >+ struct v4l2_tuner *tuner = arg; >+ >+ SWITCH_V4L2; >+ if (V4L2_TUNER_RADIO == t->mode && t->has_signal) >+ tuner->signal = t->has_signal(client); >+ break; >+ } >+ default: >+ /* nothing */ >+ break; >+ } >+ >+ return 0; >+} >+ >+static int tuner_suspend(struct device * dev, u32 state, u32 level) >+{ >+ struct i2c_client *c = container_of(dev, struct i2c_client, dev); >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ tuner_dbg("suspend\n"); >+ /* FIXME: power down ??? */ >+ return 0; >+} >+ >+static int tuner_resume(struct device * dev, u32 level) >+{ >+ struct i2c_client *c = container_of(dev, struct i2c_client, dev); >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ tuner_dbg("resume\n"); >+ if (t->freq) >+ set_freq(c,t->freq); >+ return 0; >+} >+ >+/* ----------------------------------------------------------------------- */ >+ >+static struct i2c_driver driver = { >+ .owner = THIS_MODULE, >+ .name = "tuner", >+ .id = I2C_DRIVERID_TUNER, >+ .flags = I2C_DF_NOTIFY, >+ .attach_adapter = tuner_probe, >+ .detach_client = tuner_detach, >+ .command = tuner_command, >+ .driver = { >+ .suspend = tuner_suspend, >+ .resume = tuner_resume, >+ }, >+}; >+static struct i2c_client client_template = >+{ >+ I2C_DEVNAME("(tuner unset)"), >+ .flags = I2C_CLIENT_ALLOW_USE, >+ .driver = &driver, >+}; >+ >+static int __init tuner_init_module(void) >+{ >+ return i2c_add_driver(&driver); >+} >+ >+static void __exit tuner_cleanup_module(void) >+{ >+ i2c_del_driver(&driver); >+} >+ >+module_init(tuner_init_module); >+module_exit(tuner_cleanup_module); >+ >+/* >+ * Overrides for Emacs so that we follow Linus's tabbing style. >+ * --------------------------------------------------------------------------- >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/video/tuner-simple.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/media/video/tuner-simple.c 2005-03-08 10:32:50.000000000 +0100 >@@ -0,0 +1,474 @@ >+/* >+ * $Id: tuner-simple.c,v 1.10 2005/03/08 08:38:00 kraxel Exp $ >+ * >+ * i2c tv tuner chip device driver >+ * controls all those simple 4-control-bytes style tuners. >+ */ >+#include <linux/delay.h> >+#include <linux/i2c.h> >+#include <linux/videodev.h> >+#include <media/tuner.h> >+ >+/* ---------------------------------------------------------------------- */ >+ >+/* tv standard selection for Temic 4046 FM5 >+ this value takes the low bits of control byte 2 >+ from datasheet Rev.01, Feb.00 >+ standard BG I L L2 D >+ picture IF 38.9 38.9 38.9 33.95 38.9 >+ sound 1 33.4 32.9 32.4 40.45 32.4 >+ sound 2 33.16 >+ NICAM 33.05 32.348 33.05 33.05 >+ */ >+#define TEMIC_SET_PAL_I 0x05 >+#define TEMIC_SET_PAL_DK 0x09 >+#define TEMIC_SET_PAL_L 0x0a // SECAM ? >+#define TEMIC_SET_PAL_L2 0x0b // change IF ! >+#define TEMIC_SET_PAL_BG 0x0c >+ >+/* tv tuner system standard selection for Philips FQ1216ME >+ this value takes the low bits of control byte 2 >+ from datasheet "1999 Nov 16" (supersedes "1999 Mar 23") >+ standard BG DK I L L` >+ picture carrier 38.90 38.90 38.90 38.90 33.95 >+ colour 34.47 34.47 34.47 34.47 38.38 >+ sound 1 33.40 32.40 32.90 32.40 40.45 >+ sound 2 33.16 - - - - >+ NICAM 33.05 33.05 32.35 33.05 39.80 >+ */ >+#define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/ >+#define PHILIPS_SET_PAL_BGDK 0x09 >+#define PHILIPS_SET_PAL_L2 0x0a >+#define PHILIPS_SET_PAL_L 0x0b >+ >+/* system switching for Philips FI1216MF MK2 >+ from datasheet "1996 Jul 09", >+ standard BG L L' >+ picture carrier 38.90 38.90 33.95 >+ colour 34.47 34.37 38.38 >+ sound 1 33.40 32.40 40.45 >+ sound 2 33.16 - - >+ NICAM 33.05 33.05 39.80 >+ */ >+#define PHILIPS_MF_SET_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */ >+#define PHILIPS_MF_SET_PAL_L 0x03 // France >+#define PHILIPS_MF_SET_PAL_L2 0x02 // L' >+ >+ >+/* ---------------------------------------------------------------------- */ >+ >+struct tunertype >+{ >+ char *name; >+ unsigned char Vendor; >+ unsigned char Type; >+ >+ unsigned short thresh1; /* band switch VHF_LO <=> VHF_HI */ >+ unsigned short thresh2; /* band switch VHF_HI <=> UHF */ >+ unsigned char VHF_L; >+ unsigned char VHF_H; >+ unsigned char UHF; >+ unsigned char config; >+ unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL, >+ 732 =16*45.75 NTSCi, >+ 940 =16*58.75 NTSC-Japan >+ 704 =16*44 ATSC */ >+}; >+ >+/* >+ * The floats in the tuner struct are computed at compile time >+ * by gcc and cast back to integers. Thus we don't violate the >+ * "no float in kernel" rule. >+ */ >+static struct tunertype tuners[] = { >+ { "Temic PAL (4002 FH5)", TEMIC, PAL, >+ 16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623}, >+ { "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I, >+ 16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, >+ { "Philips NTSC (FI1236,FM1236 and compatibles)", Philips, NTSC, >+ 16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732}, >+ { "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", Philips, SECAM, >+ 16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623}, >+ >+ { "NoTuner", NoTuner, NOTUNER, >+ 0,0,0x00,0x00,0x00,0x00,0x00}, >+ { "Philips PAL_BG (FI1216 and compatibles)", Philips, PAL, >+ 16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623}, >+ { "Temic NTSC (4032 FY5)", TEMIC, NTSC, >+ 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732}, >+ { "Temic PAL_I (4062 FY5)", TEMIC, PAL_I, >+ 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623}, >+ >+ { "Temic NTSC (4036 FY5)", TEMIC, NTSC, >+ 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732}, >+ { "Alps HSBH1", TEMIC, NTSC, >+ 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, >+ { "Alps TSBE1",TEMIC,PAL, >+ 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, >+ { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */ >+ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632}, >+ >+ { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ >+ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622}, >+ { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ >+ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608}, >+ { "Temic PAL_BG (4006FH5)", TEMIC, PAL, >+ 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >+ { "Alps TSCH6",Alps,NTSC, >+ 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, >+ >+ { "Temic PAL_DK (4016 FY5)",TEMIC,PAL, >+ 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623}, >+ { "Philips NTSC_M (MK2)",Philips,NTSC, >+ 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, >+ { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I, >+ 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, >+ { "Temic PAL* auto (4006 FN5)", TEMIC, PAL, >+ 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, >+ >+ { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL, >+ 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, >+ { "Temic NTSC (4039 FR5)", TEMIC, NTSC, >+ 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, >+ { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL, >+ 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, >+ { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL, >+ 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >+ >+ { "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL, >+ 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >+ { "LG PAL_I+FM (TAPC-I001D)", LGINNOTEK, PAL_I, >+ 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >+ { "LG PAL_I (TAPC-I701D)", LGINNOTEK, PAL_I, >+ 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >+ { "LG NTSC+FM (TPI8NSR01F)", LGINNOTEK, NTSC, >+ 16*210.00,16*497.00,0xa0,0x90,0x30,0x8e,732}, >+ >+ { "LG PAL_BG+FM (TPI8PSB01D)", LGINNOTEK, PAL, >+ 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >+ { "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL, >+ 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >+ { "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL, >+ 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, >+ { "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */ >+ 16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 }, >+ >+ { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */ >+ 16*169,16*464,0xA0,0x90,0x30,0x8e,623}, >+ { "MT20xx universal", Microtune,PAL|NTSC, >+ /* see mt20xx.c for details */ }, >+ { "Temic PAL_BG (4106 FH5)", TEMIC, PAL, >+ 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, >+ { "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL, >+ 16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623}, >+ >+ { "Temic NTSC (4136 FY5)", TEMIC, NTSC, >+ 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, >+ { "LG PAL (newer TAPC series)", LGINNOTEK, PAL, >+ 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623}, >+ { "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL, >+ 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, >+ { "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC, >+ 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, >+ >+ { "HITACHI V7-J180AT", HITACHI, NTSC, >+ 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 }, >+ { "Philips PAL_MK (FI1216 MK)", Philips, PAL, >+ 16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623}, >+ { "Philips 1236D ATSC/NTSC daul in",Philips,ATSC, >+ 16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732}, >+ { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC, >+ 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, >+ >+ { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC, >+ 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, >+ { "Microtune 4049 FM5",Microtune,PAL, >+ 16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623}, >+ { "Panasonic VP27s/ENGE4324D", Panasonic, NTSC, >+ 16*160.00,16*454.00,0x01,0x02,0x08,0xce,940}, >+ { "LG NTSC (TAPE series)", LGINNOTEK, NTSC, >+ 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, >+ >+ { "Tenna TNF 8831 BGFF)", Philips, PAL, >+ 16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, >+ { "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC, >+ 16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732}, >+ { "TCL 2002N", TCL, NTSC, >+ 16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732}, >+ { "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL, >+ 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, >+ >+ { "Thomson DDT 7610 (ATSC/NTSC)", THOMSON, ATSC, >+ 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, >+ { "Philips FQ1286", Philips, NTSC, >+ 16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, // UHF band untested >+ { "tda8290+75", Philips,PAL|NTSC, >+ /* see tda8290.c for details */ }, >+ { "LG PAL (TAPE series)", LGINNOTEK, PAL, >+ 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623}, >+ >+ { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL, >+ 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 }, >+ { "Philips FQ1236A MK4", Philips, NTSC, >+ 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, >+ >+}; >+unsigned const int tuner_count = ARRAY_SIZE(tuners); >+ >+/* ---------------------------------------------------------------------- */ >+ >+static int tuner_getstatus(struct i2c_client *c) >+{ >+ unsigned char byte; >+ >+ if (1 != i2c_master_recv(c,&byte,1)) >+ return 0; >+ return byte; >+} >+ >+#define TUNER_POR 0x80 >+#define TUNER_FL 0x40 >+#define TUNER_MODE 0x38 >+#define TUNER_AFC 0x07 >+ >+#define TUNER_STEREO 0x10 /* radio mode */ >+#define TUNER_SIGNAL 0x07 /* radio mode */ >+ >+static int tuner_signal(struct i2c_client *c) >+{ >+ return (tuner_getstatus(c) & TUNER_SIGNAL)<<13; >+} >+ >+static int tuner_stereo(struct i2c_client *c) >+{ >+ return (tuner_getstatus (c) & TUNER_STEREO); >+} >+ >+#if 0 /* unused */ >+static int tuner_islocked (struct i2c_client *c) >+{ >+ return (tuner_getstatus (c) & TUNER_FL); >+} >+ >+static int tuner_afcstatus (struct i2c_client *c) >+{ >+ return (tuner_getstatus (c) & TUNER_AFC) - 2; >+} >+ >+static int tuner_mode (struct i2c_client *c) >+{ >+ return (tuner_getstatus (c) & TUNER_MODE) >> 3; >+} >+#endif >+ >+/* ---------------------------------------------------------------------- */ >+ >+static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ u8 config; >+ u16 div; >+ struct tunertype *tun; >+ unsigned char buffer[4]; >+ int rc; >+ >+ tun = &tuners[t->type]; >+ if (freq < tun->thresh1) { >+ config = tun->VHF_L; >+ tuner_dbg("tv: VHF lowrange\n"); >+ } else if (freq < tun->thresh2) { >+ config = tun->VHF_H; >+ tuner_dbg("tv: VHF high range\n"); >+ } else { >+ config = tun->UHF; >+ tuner_dbg("tv: UHF range\n"); >+ } >+ >+ >+ /* tv norm specific stuff for multi-norm tuners */ >+ switch (t->type) { >+ case TUNER_PHILIPS_SECAM: // FI1216MF >+ /* 0x01 -> ??? no change ??? */ >+ /* 0x02 -> PAL BDGHI / SECAM L */ >+ /* 0x04 -> ??? PAL others / SECAM others ??? */ >+ config &= ~0x02; >+ if (t->std & V4L2_STD_SECAM) >+ config |= 0x02; >+ break; >+ >+ case TUNER_TEMIC_4046FM5: >+ config &= ~0x0f; >+ >+ if (t->std & V4L2_STD_PAL_BG) { >+ config |= TEMIC_SET_PAL_BG; >+ >+ } else if (t->std & V4L2_STD_PAL_I) { >+ config |= TEMIC_SET_PAL_I; >+ >+ } else if (t->std & V4L2_STD_PAL_DK) { >+ config |= TEMIC_SET_PAL_DK; >+ >+ } else if (t->std & V4L2_STD_SECAM_L) { >+ config |= TEMIC_SET_PAL_L; >+ >+ } >+ break; >+ >+ case TUNER_PHILIPS_FQ1216ME: >+ config &= ~0x0f; >+ >+ if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { >+ config |= PHILIPS_SET_PAL_BGDK; >+ >+ } else if (t->std & V4L2_STD_PAL_I) { >+ config |= PHILIPS_SET_PAL_I; >+ >+ } else if (t->std & V4L2_STD_SECAM_L) { >+ config |= PHILIPS_SET_PAL_L; >+ >+ } >+ break; >+ >+ case TUNER_PHILIPS_ATSC: >+ /* 0x00 -> ATSC antenna input 1 */ >+ /* 0x01 -> ATSC antenna input 2 */ >+ /* 0x02 -> NTSC antenna input 1 */ >+ /* 0x03 -> NTSC antenna input 2 */ >+ config &= ~0x03; >+ if (!(t->std & V4L2_STD_ATSC)) >+ config |= 2; >+ /* FIXME: input */ >+ break; >+ >+ case TUNER_MICROTUNE_4042FI5: >+ /* Set the charge pump for fast tuning */ >+ tun->config |= 0x40; >+ break; >+ } >+ >+ /* >+ * Philips FI1216MK2 remark from specification : >+ * for channel selection involving band switching, and to ensure >+ * smooth tuning to the desired channel without causing >+ * unnecessary charge pump action, it is recommended to consider >+ * the difference between wanted channel frequency and the >+ * current channel frequency. Unnecessary charge pump action >+ * will result in very low tuning voltage which may drive the >+ * oscillator to extreme conditions. >+ * >+ * Progfou: specification says to send config data before >+ * frequency in case (wanted frequency < current frequency). >+ */ >+ >+ div=freq + tun->IFPCoff; >+ if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) { >+ buffer[0] = tun->config; >+ buffer[1] = config; >+ buffer[2] = (div>>8) & 0x7f; >+ buffer[3] = div & 0xff; >+ } else { >+ buffer[0] = (div>>8) & 0x7f; >+ buffer[1] = div & 0xff; >+ buffer[2] = tun->config; >+ buffer[3] = config; >+ } >+ tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", >+ buffer[0],buffer[1],buffer[2],buffer[3]); >+ >+ if (4 != (rc = i2c_master_send(c,buffer,4))) >+ tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); >+ >+ if (t->type == TUNER_MICROTUNE_4042FI5) { >+ // FIXME - this may also work for other tuners >+ unsigned long timeout = jiffies + msecs_to_jiffies(1); >+ u8 status_byte = 0; >+ >+ /* Wait until the PLL locks */ >+ for (;;) { >+ if (time_after(jiffies,timeout)) >+ return; >+ if (1 != (rc = i2c_master_recv(c,&status_byte,1))) { >+ tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc); >+ break; >+ } >+ /* bit 6 is PLL locked indicator */ >+ if (status_byte & 0x40) >+ break; >+ udelay(10); >+ } >+ >+ /* Set the charge pump for optimized phase noise figure */ >+ tun->config &= ~0x40; >+ buffer[0] = (div>>8) & 0x7f; >+ buffer[1] = div & 0xff; >+ buffer[2] = tun->config; >+ buffer[3] = config; >+ tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", >+ buffer[0],buffer[1],buffer[2],buffer[3]); >+ >+ if (4 != (rc = i2c_master_send(c,buffer,4))) >+ tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); >+ } >+} >+ >+static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) >+{ >+ struct tunertype *tun; >+ struct tuner *t = i2c_get_clientdata(c); >+ unsigned char buffer[4]; >+ unsigned div; >+ int rc; >+ >+ tun=&tuners[t->type]; >+ div = freq + (int)(16*10.7); >+ buffer[2] = tun->config; >+ >+ switch (t->type) { >+ case TUNER_PHILIPS_FM1216ME_MK3: >+ case TUNER_PHILIPS_FM1236_MK3: >+ buffer[3] = 0x19; >+ break; >+ case TUNER_PHILIPS_FM1256_IH3: >+ div = (20 * freq)/16 + 333 * 2; >+ buffer[2] = 0x80; >+ buffer[3] = 0x19; >+ break; >+ case TUNER_LG_PAL_FM: >+ buffer[3] = 0xa5; >+ break; >+ default: >+ buffer[3] = 0xa4; >+ break; >+ } >+ buffer[0] = (div>>8) & 0x7f; >+ buffer[1] = div & 0xff; >+ >+ tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", >+ buffer[0],buffer[1],buffer[2],buffer[3]); >+ >+ if (4 != (rc = i2c_master_send(c,buffer,4))) >+ tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); >+} >+ >+int default_tuner_init(struct i2c_client *c) >+{ >+ struct tuner *t = i2c_get_clientdata(c); >+ >+ tuner_info("type set to %d (%s)\n", >+ t->type, tuners[t->type].name); >+ strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); >+ >+ t->tv_freq = default_set_tv_freq; >+ t->radio_freq = default_set_radio_freq; >+ t->has_signal = tuner_signal; >+ t->is_stereo = tuner_stereo; >+ return 0; >+} >+ >+/* >+ * Overrides for Emacs so that we follow Linus's tabbing style. >+ * --------------------------------------------------------------------------- >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/drivers/media/video/tuner.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/tuner.c 2005-03-07 10:16:33.000000000 +0100 >+++ /dev/null 1970-01-01 00:00:00.000000000 +0000 >@@ -1,1425 +0,0 @@ >-/* >- * $Id: tuner.c,v 1.36 2005/01/14 13:29:40 kraxel Exp $ >- */ >- >-#include <linux/module.h> >-#include <linux/moduleparam.h> >-#include <linux/kernel.h> >-#include <linux/sched.h> >-#include <linux/string.h> >-#include <linux/timer.h> >-#include <linux/delay.h> >-#include <linux/errno.h> >-#include <linux/slab.h> >-#include <linux/poll.h> >-#include <linux/i2c.h> >-#include <linux/types.h> >-#include <linux/videodev.h> >-#include <linux/init.h> >- >-#include <media/tuner.h> >-#include <media/audiochip.h> >- >-#define UNSET (-1U) >- >-/* standard i2c insmod options */ >-static unsigned short normal_i2c[] = {I2C_CLIENT_END}; >-static unsigned short normal_i2c_range[] = {0x60,0x6f,I2C_CLIENT_END}; >-I2C_CLIENT_INSMOD; >- >-/* insmod options used at init time => read/only */ >-static unsigned int type = UNSET; >-static unsigned int addr = 0; >-module_param(type, int, 0444); >-module_param(addr, int, 0444); >- >-/* insmod options used at runtime => read/write */ >-static unsigned int debug = 0; >-static unsigned int tv_antenna = 1; >-static unsigned int radio_antenna = 0; >-static unsigned int optimize_vco = 1; >-module_param(debug, int, 0644); >-module_param(tv_antenna, int, 0644); >-module_param(radio_antenna, int, 0644); >-module_param(optimize_vco, int, 0644); >- >-static unsigned int tv_range[2] = { 44, 958 }; >-static unsigned int radio_range[2] = { 65, 108 }; >- >-module_param_array(tv_range, int, NULL, 0644); >-module_param_array(radio_range, int, NULL, 0644); >- >-MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); >-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); >-MODULE_LICENSE("GPL"); >- >-static int this_adap; >-#define dprintk if (debug) printk >- >-struct tuner { >- unsigned int type; /* chip type */ >- unsigned int freq; /* keep track of the current settings */ >- v4l2_std_id std; >- int using_v4l2; >- >- enum v4l2_tuner_type mode; >- unsigned int input; >- >- // only for MT2032 >- unsigned int xogc; >- unsigned int radio_if2; >- >- void (*tv_freq)(struct i2c_client *c, unsigned int freq); >- void (*radio_freq)(struct i2c_client *c, unsigned int freq); >-}; >- >-static struct i2c_driver driver; >-static struct i2c_client client_template; >- >-/* ---------------------------------------------------------------------- */ >- >-/* tv standard selection for Temic 4046 FM5 >- this value takes the low bits of control byte 2 >- from datasheet Rev.01, Feb.00 >- standard BG I L L2 D >- picture IF 38.9 38.9 38.9 33.95 38.9 >- sound 1 33.4 32.9 32.4 40.45 32.4 >- sound 2 33.16 >- NICAM 33.05 32.348 33.05 33.05 >- */ >-#define TEMIC_SET_PAL_I 0x05 >-#define TEMIC_SET_PAL_DK 0x09 >-#define TEMIC_SET_PAL_L 0x0a // SECAM ? >-#define TEMIC_SET_PAL_L2 0x0b // change IF ! >-#define TEMIC_SET_PAL_BG 0x0c >- >-/* tv tuner system standard selection for Philips FQ1216ME >- this value takes the low bits of control byte 2 >- from datasheet "1999 Nov 16" (supersedes "1999 Mar 23") >- standard BG DK I L L` >- picture carrier 38.90 38.90 38.90 38.90 33.95 >- colour 34.47 34.47 34.47 34.47 38.38 >- sound 1 33.40 32.40 32.90 32.40 40.45 >- sound 2 33.16 - - - - >- NICAM 33.05 33.05 32.35 33.05 39.80 >- */ >-#define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/ >-#define PHILIPS_SET_PAL_BGDK 0x09 >-#define PHILIPS_SET_PAL_L2 0x0a >-#define PHILIPS_SET_PAL_L 0x0b >- >-/* system switching for Philips FI1216MF MK2 >- from datasheet "1996 Jul 09", >- standard BG L L' >- picture carrier 38.90 38.90 33.95 >- colour 34.47 34.37 38.38 >- sound 1 33.40 32.40 40.45 >- sound 2 33.16 - - >- NICAM 33.05 33.05 39.80 >- */ >-#define PHILIPS_MF_SET_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */ >-#define PHILIPS_MF_SET_PAL_L 0x03 // France >-#define PHILIPS_MF_SET_PAL_L2 0x02 // L' >- >- >-/* ---------------------------------------------------------------------- */ >- >-struct tunertype >-{ >- char *name; >- unsigned char Vendor; >- unsigned char Type; >- >- unsigned short thresh1; /* band switch VHF_LO <=> VHF_HI */ >- unsigned short thresh2; /* band switch VHF_HI <=> UHF */ >- unsigned char VHF_L; >- unsigned char VHF_H; >- unsigned char UHF; >- unsigned char config; >- unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL, >- 732 =16*45.75 NTSCi, >- 940 =16*58.75 NTSC-Japan >- 704 =16*44 ATSC */ >-}; >- >-/* >- * The floats in the tuner struct are computed at compile time >- * by gcc and cast back to integers. Thus we don't violate the >- * "no float in kernel" rule. >- */ >-static struct tunertype tuners[] = { >- { "Temic PAL (4002 FH5)", TEMIC, PAL, >- 16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623}, >- { "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I, >- 16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, >- { "Philips NTSC (FI1236,FM1236 and compatibles)", Philips, NTSC, >- 16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732}, >- { "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", Philips, SECAM, >- 16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623}, >- >- { "NoTuner", NoTuner, NOTUNER, >- 0,0,0x00,0x00,0x00,0x00,0x00}, >- { "Philips PAL_BG (FI1216 and compatibles)", Philips, PAL, >- 16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623}, >- { "Temic NTSC (4032 FY5)", TEMIC, NTSC, >- 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732}, >- { "Temic PAL_I (4062 FY5)", TEMIC, PAL_I, >- 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623}, >- >- { "Temic NTSC (4036 FY5)", TEMIC, NTSC, >- 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732}, >- { "Alps HSBH1", TEMIC, NTSC, >- 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, >- { "Alps TSBE1",TEMIC,PAL, >- 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, >- { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */ >- 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632}, >- >- { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ >- 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622}, >- { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ >- 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608}, >- { "Temic PAL_BG (4006FH5)", TEMIC, PAL, >- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >- { "Alps TSCH6",Alps,NTSC, >- 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, >- >- { "Temic PAL_DK (4016 FY5)",TEMIC,PAL, >- 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623}, >- { "Philips NTSC_M (MK2)",Philips,NTSC, >- 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, >- { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I, >- 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, >- { "Temic PAL* auto (4006 FN5)", TEMIC, PAL, >- 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, >- >- { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL, >- 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, >- { "Temic NTSC (4039 FR5)", TEMIC, NTSC, >- 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, >- { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL, >- 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, >- { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL, >- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >- >- { "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL, >- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >- { "LG PAL_I+FM (TAPC-I001D)", LGINNOTEK, PAL_I, >- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >- { "LG PAL_I (TAPC-I701D)", LGINNOTEK, PAL_I, >- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >- { "LG NTSC+FM (TPI8NSR01F)", LGINNOTEK, NTSC, >- 16*210.00,16*497.00,0xa0,0x90,0x30,0x8e,732}, >- >- { "LG PAL_BG+FM (TPI8PSB01D)", LGINNOTEK, PAL, >- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >- { "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL, >- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, >- { "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL, >- 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, >- { "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */ >- 16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 }, >- >- { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */ >- 16*169,16*464,0xA0,0x90,0x30,0x8e,623}, >- { "MT20xx universal", Microtune,PAL|NTSC, >- 0,0,0,0,0,0,0}, >- { "Temic PAL_BG (4106 FH5)", TEMIC, PAL, >- 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, >- { "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL, >- 16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623}, >- >- { "Temic NTSC (4136 FY5)", TEMIC, NTSC, >- 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, >- { "LG PAL (newer TAPC series)", LGINNOTEK, PAL, >- 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623}, >- { "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL, >- 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, >- { "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC, >- 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, >- >- { "HITACHI V7-J180AT", HITACHI, NTSC, >- 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 }, >- { "Philips PAL_MK (FI1216 MK)", Philips, PAL, >- 16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623}, >- { "Philips 1236D ATSC/NTSC daul in",Philips,ATSC, >- 16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732}, >- { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC, >- 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, >- >- { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC, >- 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, >- { "Microtune 4049 FM5",Microtune,PAL, >- 16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623}, >- { "Panasonic VP27s/ENGE4324D", Panasonic, NTSC, >- 16*160.00,16*454.00,0x01,0x02,0x08,0xce,940}, >- { "LG NTSC (TAPE series)", LGINNOTEK, NTSC, >- 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, >- >- { "Tenna TNF 8831 BGFF)", Philips, PAL, >- 16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, >- { "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC, >- 16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732}, >- { "TCL 2002N", TCL, NTSC, >- 16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732}, >- { "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL, >- 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, >- >- { "Thomson DDT 7610 ATSC/NTSC)", THOMSON, ATSC, >- 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, >- { "Philips FQ1286", Philips, NTSC, >- 16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, // UHF band untested >- >-}; >-#define TUNERS ARRAY_SIZE(tuners) >- >-/* ---------------------------------------------------------------------- */ >- >-static int tuner_getstatus(struct i2c_client *c) >-{ >- unsigned char byte; >- >- struct tuner *t = i2c_get_clientdata(c); >- >- if (t->type == TUNER_MT2032) >- return 0; >- >- if (1 != i2c_master_recv(c,&byte,1)) >- return 0; >- return byte; >-} >- >-#define TUNER_POR 0x80 >-#define TUNER_FL 0x40 >-#define TUNER_MODE 0x38 >-#define TUNER_AFC 0x07 >- >-#define TUNER_STEREO 0x10 /* radio mode */ >-#define TUNER_SIGNAL 0x07 /* radio mode */ >- >-static int tuner_signal(struct i2c_client *c) >-{ >- return (tuner_getstatus(c) & TUNER_SIGNAL)<<13; >-} >- >-static int tuner_stereo(struct i2c_client *c) >-{ >- return (tuner_getstatus (c) & TUNER_STEREO); >-} >- >-#if 0 /* unused */ >-static int tuner_islocked (struct i2c_client *c) >-{ >- return (tuner_getstatus (c) & TUNER_FL); >-} >- >-static int tuner_afcstatus (struct i2c_client *c) >-{ >- return (tuner_getstatus (c) & TUNER_AFC) - 2; >-} >- >-static int tuner_mode (struct i2c_client *c) >-{ >- return (tuner_getstatus (c) & TUNER_MODE) >> 3; >-} >-#endif >- >-/* ---------------------------------------------------------------------- */ >- >-#define MT2032 0x04 >-#define MT2030 0x06 >-#define MT2040 0x07 >-#define MT2050 0x42 >- >-static char *microtune_part[] = { >- [ MT2030 ] = "MT2030", >- [ MT2032 ] = "MT2032", >- [ MT2040 ] = "MT2040", >- [ MT2050 ] = "MT2050", >-}; >- >-// IsSpurInBand()? >-static int mt2032_spurcheck(int f1, int f2, int spectrum_from,int spectrum_to) >-{ >- int n1=1,n2,f; >- >- f1=f1/1000; //scale to kHz to avoid 32bit overflows >- f2=f2/1000; >- spectrum_from/=1000; >- spectrum_to/=1000; >- >- dprintk("spurcheck f1=%d f2=%d from=%d to=%d\n",f1,f2,spectrum_from,spectrum_to); >- >- do { >- n2=-n1; >- f=n1*(f1-f2); >- do { >- n2--; >- f=f-f2; >- dprintk(" spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f); >- >- if( (f>spectrum_from) && (f<spectrum_to)) >- printk("mt2032 spurcheck triggered: %d\n",n1); >- } while ( (f>(f2-spectrum_to)) || (n2>-5)); >- n1++; >- } while (n1<5); >- >- return 1; >-} >- >-static int mt2032_compute_freq(unsigned int rfin, >- unsigned int if1, unsigned int if2, >- unsigned int spectrum_from, >- unsigned int spectrum_to, >- unsigned char *buf, >- int *ret_sel, >- unsigned int xogc) //all in Hz >-{ >- unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, >- desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; >- >- fref= 5250 *1000; //5.25MHz >- desired_lo1=rfin+if1; >- >- lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000); >- lo1n=lo1/8; >- lo1a=lo1-(lo1n*8); >- >- s=rfin/1000/1000+1090; >- >- if(optimize_vco) { >- if(s>1890) sel=0; >- else if(s>1720) sel=1; >- else if(s>1530) sel=2; >- else if(s>1370) sel=3; >- else sel=4; // >1090 >- } >- else { >- if(s>1790) sel=0; // <1958 >- else if(s>1617) sel=1; >- else if(s>1449) sel=2; >- else if(s>1291) sel=3; >- else sel=4; // >1090 >- } >- *ret_sel=sel; >- >- lo1freq=(lo1a+8*lo1n)*fref; >- >- dprintk("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n", >- rfin,lo1,lo1n,lo1a,sel,lo1freq); >- >- desired_lo2=lo1freq-rfin-if2; >- lo2=(desired_lo2)/fref; >- lo2n=lo2/8; >- lo2a=lo2-(lo2n*8); >- lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith >- lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; >- >- dprintk("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n", >- rfin,lo2,lo2n,lo2a,lo2num,lo2freq); >- >- if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { >- printk("mt2032: frequency parameters out of range: %d %d %d %d\n", >- lo1a, lo1n, lo2a,lo2n); >- return(-1); >- } >- >- mt2032_spurcheck(lo1freq, desired_lo2, spectrum_from, spectrum_to); >- // should recalculate lo1 (one step up/down) >- >- // set up MT2032 register map for transfer over i2c >- buf[0]=lo1n-1; >- buf[1]=lo1a | (sel<<4); >- buf[2]=0x86; // LOGC >- buf[3]=0x0f; //reserved >- buf[4]=0x1f; >- buf[5]=(lo2n-1) | (lo2a<<5); >- if(rfin >400*1000*1000) >- buf[6]=0xe4; >- else >- buf[6]=0xf4; // set PKEN per rev 1.2 >- buf[7]=8+xogc; >- buf[8]=0xc3; //reserved >- buf[9]=0x4e; //reserved >- buf[10]=0xec; //reserved >- buf[11]=(lo2num&0xff); >- buf[12]=(lo2num>>8) |0x80; // Lo2RST >- >- return 0; >-} >- >-static int mt2032_check_lo_lock(struct i2c_client *c) >-{ >- int try,lock=0; >- unsigned char buf[2]; >- for(try=0;try<10;try++) { >- buf[0]=0x0e; >- i2c_master_send(c,buf,1); >- i2c_master_recv(c,buf,1); >- dprintk("mt2032 Reg.E=0x%02x\n",buf[0]); >- lock=buf[0] &0x06; >- >- if (lock==6) >- break; >- >- dprintk("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); >- udelay(1000); >- } >- return lock; >-} >- >-static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) >-{ >- unsigned char buf[2]; >- int tad1; >- >- buf[0]=0x0f; >- i2c_master_send(c,buf,1); >- i2c_master_recv(c,buf,1); >- dprintk("mt2032 Reg.F=0x%02x\n",buf[0]); >- tad1=buf[0]&0x07; >- >- if(tad1 ==0) return lock; >- if(tad1 ==1) return lock; >- >- if(tad1==2) { >- if(sel==0) >- return lock; >- else sel--; >- } >- else { >- if(sel<4) >- sel++; >- else >- return lock; >- } >- >- dprintk("mt2032 optimize_vco: sel=%d\n",sel); >- >- buf[0]=0x0f; >- buf[1]=sel; >- i2c_master_send(c,buf,2); >- lock=mt2032_check_lo_lock(c); >- return lock; >-} >- >- >-static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, >- unsigned int if1, unsigned int if2, >- unsigned int from, unsigned int to) >-{ >- unsigned char buf[21]; >- int lint_try,ret,sel,lock=0; >- struct tuner *t = i2c_get_clientdata(c); >- >- dprintk("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",rfin,if1,if2,from,to); >- >- buf[0]=0; >- ret=i2c_master_send(c,buf,1); >- i2c_master_recv(c,buf,21); >- >- buf[0]=0; >- ret=mt2032_compute_freq(rfin,if1,if2,from,to,&buf[1],&sel,t->xogc); >- if (ret<0) >- return; >- >- // send only the relevant registers per Rev. 1.2 >- buf[0]=0; >- ret=i2c_master_send(c,buf,4); >- buf[5]=5; >- ret=i2c_master_send(c,buf+5,4); >- buf[11]=11; >- ret=i2c_master_send(c,buf+11,3); >- if(ret!=3) >- printk("mt2032_set_if_freq failed with %d\n",ret); >- >- // wait for PLLs to lock (per manual), retry LINT if not. >- for(lint_try=0; lint_try<2; lint_try++) { >- lock=mt2032_check_lo_lock(c); >- >- if(optimize_vco) >- lock=mt2032_optimize_vco(c,sel,lock); >- if(lock==6) break; >- >- printk("mt2032: re-init PLLs by LINT\n"); >- buf[0]=7; >- buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs >- i2c_master_send(c,buf,2); >- mdelay(10); >- buf[1]=8+t->xogc; >- i2c_master_send(c,buf,2); >- } >- >- if (lock!=6) >- printk("MT2032 Fatal Error: PLLs didn't lock.\n"); >- >- buf[0]=2; >- buf[1]=0x20; // LOGC for optimal phase noise >- ret=i2c_master_send(c,buf,2); >- if (ret!=2) >- printk("mt2032_set_if_freq2 failed with %d\n",ret); >-} >- >- >-static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- int if2,from,to; >- >- // signal bandwidth and picture carrier >- if (t->std & V4L2_STD_525_60) { >- // NTSC >- from = 40750*1000; >- to = 46750*1000; >- if2 = 45750*1000; >- } else { >- // PAL >- from = 32900*1000; >- to = 39900*1000; >- if2 = 38900*1000; >- } >- >- mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, >- 1090*1000*1000, if2, from, to); >-} >- >-static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- int if2 = t->radio_if2; >- >- // per Manual for FM tuning: first if center freq. 1085 MHz >- mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, >- 1085*1000*1000,if2,if2,if2); >-} >- >-// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001 >-static int mt2032_init(struct i2c_client *c) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- unsigned char buf[21]; >- int ret,xogc,xok=0; >- >- // Initialize Registers per spec. >- buf[1]=2; // Index to register 2 >- buf[2]=0xff; >- buf[3]=0x0f; >- buf[4]=0x1f; >- ret=i2c_master_send(c,buf+1,4); >- >- buf[5]=6; // Index register 6 >- buf[6]=0xe4; >- buf[7]=0x8f; >- buf[8]=0xc3; >- buf[9]=0x4e; >- buf[10]=0xec; >- ret=i2c_master_send(c,buf+5,6); >- >- buf[12]=13; // Index register 13 >- buf[13]=0x32; >- ret=i2c_master_send(c,buf+12,2); >- >- // Adjust XOGC (register 7), wait for XOK >- xogc=7; >- do { >- dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07); >- mdelay(10); >- buf[0]=0x0e; >- i2c_master_send(c,buf,1); >- i2c_master_recv(c,buf,1); >- xok=buf[0]&0x01; >- dprintk("mt2032: xok = 0x%02x\n",xok); >- if (xok == 1) break; >- >- xogc--; >- dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07); >- if (xogc == 3) { >- xogc=4; // min. 4 per spec >- break; >- } >- buf[0]=0x07; >- buf[1]=0x88 + xogc; >- ret=i2c_master_send(c,buf,2); >- if (ret!=2) >- printk("mt2032_init failed with %d\n",ret); >- } while (xok != 1 ); >- t->xogc=xogc; >- >- t->tv_freq = mt2032_set_tv_freq; >- t->radio_freq = mt2032_set_radio_freq; >- return(1); >-} >- >-static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna) >-{ >- unsigned char buf[2]; >- int ret; >- >- buf[0] = 6; >- buf[1] = antenna ? 0x11 : 0x10; >- ret=i2c_master_send(c,buf,2); >- dprintk("mt2050: enabled antenna connector %d\n", antenna); >-} >- >-static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2) >-{ >- unsigned int if1=1218*1000*1000; >- unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b; >- int ret; >- unsigned char buf[6]; >- >- dprintk("mt2050_set_if_freq freq=%d if1=%d if2=%d\n", >- freq,if1,if2); >- >- f_lo1=freq+if1; >- f_lo1=(f_lo1/1000000)*1000000; >- >- f_lo2=f_lo1-freq-if2; >- f_lo2=(f_lo2/50000)*50000; >- >- lo1=f_lo1/4000000; >- lo2=f_lo2/4000000; >- >- f_lo1_modulo= f_lo1-(lo1*4000000); >- f_lo2_modulo= f_lo2-(lo2*4000000); >- >- num1=4*f_lo1_modulo/4000000; >- num2=4096*(f_lo2_modulo/1000)/4000; >- >- // todo spurchecks >- >- div1a=(lo1/12)-1; >- div1b=lo1-(div1a+1)*12; >- >- div2a=(lo2/8)-1; >- div2b=lo2-(div2a+1)*8; >- >- if (debug > 1) { >- printk("lo1 lo2 = %d %d\n", lo1, lo2); >- printk("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",num1,num2,div1a,div1b,div2a,div2b); >- } >- >- buf[0]=1; >- buf[1]= 4*div1b + num1; >- if(freq<275*1000*1000) buf[1] = buf[1]|0x80; >- >- buf[2]=div1a; >- buf[3]=32*div2b + num2/256; >- buf[4]=num2-(num2/256)*256; >- buf[5]=div2a; >- if(num2!=0) buf[5]=buf[5]|0x40; >- >- if (debug > 1) { >- int i; >- printk("bufs is: "); >- for(i=0;i<6;i++) >- printk("%x ",buf[i]); >- printk("\n"); >- } >- >- ret=i2c_master_send(c,buf,6); >- if (ret!=6) >- printk("mt2050_set_if_freq failed with %d\n",ret); >-} >- >-static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- unsigned int if2; >- >- if (t->std & V4L2_STD_525_60) { >- // NTSC >- if2 = 45750*1000; >- } else { >- // PAL >- if2 = 38900*1000; >- } >- if (V4L2_TUNER_DIGITAL_TV == t->mode) { >- // testing for DVB ... >- if2 = 36150*1000; >- } >- mt2050_set_if_freq(c, freq*62500, if2); >- mt2050_set_antenna(c, tv_antenna); >-} >- >-static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- int if2 = t->radio_if2; >- >- mt2050_set_if_freq(c, freq*62500, if2); >- mt2050_set_antenna(c, radio_antenna); >-} >- >-static int mt2050_init(struct i2c_client *c) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- unsigned char buf[2]; >- int ret; >- >- buf[0]=6; >- buf[1]=0x10; >- ret=i2c_master_send(c,buf,2); // power >- >- buf[0]=0x0f; >- buf[1]=0x0f; >- ret=i2c_master_send(c,buf,2); // m1lo >- >- buf[0]=0x0d; >- ret=i2c_master_send(c,buf,1); >- i2c_master_recv(c,buf,1); >- >- dprintk("mt2050: sro is %x\n",buf[0]); >- t->tv_freq = mt2050_set_tv_freq; >- t->radio_freq = mt2050_set_radio_freq; >- return 0; >-} >- >-static int microtune_init(struct i2c_client *c) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- char *name; >- unsigned char buf[21]; >- int company_code; >- >- memset(buf,0,sizeof(buf)); >- t->tv_freq = NULL; >- t->radio_freq = NULL; >- name = "unknown"; >- >- i2c_master_send(c,buf,1); >- i2c_master_recv(c,buf,21); >- if(debug) { >- int i; >- printk(KERN_DEBUG "tuner: MT2032 hexdump:\n"); >- for(i=0;i<21;i++) { >- printk(" %02x",buf[i]); >- if(((i+1)%8)==0) printk(" "); >- if(((i+1)%16)==0) printk("\n "); >- } >- printk("\n "); >- } >- company_code = buf[0x11] << 8 | buf[0x12]; >- printk("tuner: microtune: companycode=%04x part=%02x rev=%02x\n", >- company_code,buf[0x13],buf[0x14]); >- >-#if 0 >- /* seems to cause more problems than it solves ... */ >- switch (company_code) { >- case 0x30bf: >- case 0x3cbf: >- case 0x3dbf: >- case 0x4d54: >- case 0x8e81: >- case 0x8e91: >- /* ok (?) */ >- break; >- default: >- printk("tuner: microtune: unknown companycode\n"); >- return 0; >- } >-#endif >- >- if (buf[0x13] < ARRAY_SIZE(microtune_part) && >- NULL != microtune_part[buf[0x13]]) >- name = microtune_part[buf[0x13]]; >- switch (buf[0x13]) { >- case MT2032: >- mt2032_init(c); >- break; >- case MT2050: >- mt2050_init(c); >- break; >- default: >- printk("tuner: microtune %s found, not (yet?) supported, sorry :-/\n", >- name); >- return 0; >- } >- printk("tuner: microtune %s found, OK\n",name); >- return 0; >-} >- >-/* ---------------------------------------------------------------------- */ >- >-static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- u8 config; >- u16 div; >- struct tunertype *tun; >- unsigned char buffer[4]; >- int rc; >- >- tun = &tuners[t->type]; >- if (freq < tun->thresh1) { >- config = tun->VHF_L; >- dprintk("tv: VHF lowrange\n"); >- } else if (freq < tun->thresh2) { >- config = tun->VHF_H; >- dprintk("tv: VHF high range\n"); >- } else { >- config = tun->UHF; >- dprintk("tv: UHF range\n"); >- } >- >- >- /* tv norm specific stuff for multi-norm tuners */ >- switch (t->type) { >- case TUNER_PHILIPS_SECAM: // FI1216MF >- /* 0x01 -> ??? no change ??? */ >- /* 0x02 -> PAL BDGHI / SECAM L */ >- /* 0x04 -> ??? PAL others / SECAM others ??? */ >- config &= ~0x02; >- if (t->std & V4L2_STD_SECAM) >- config |= 0x02; >- break; >- >- case TUNER_TEMIC_4046FM5: >- config &= ~0x0f; >- >- if (t->std & V4L2_STD_PAL_BG) { >- config |= TEMIC_SET_PAL_BG; >- >- } else if (t->std & V4L2_STD_PAL_I) { >- config |= TEMIC_SET_PAL_I; >- >- } else if (t->std & V4L2_STD_PAL_DK) { >- config |= TEMIC_SET_PAL_DK; >- >- } else if (t->std & V4L2_STD_SECAM_L) { >- config |= TEMIC_SET_PAL_L; >- >- } >- break; >- >- case TUNER_PHILIPS_FQ1216ME: >- config &= ~0x0f; >- >- if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { >- config |= PHILIPS_SET_PAL_BGDK; >- >- } else if (t->std & V4L2_STD_PAL_I) { >- config |= PHILIPS_SET_PAL_I; >- >- } else if (t->std & V4L2_STD_SECAM_L) { >- config |= PHILIPS_SET_PAL_L; >- >- } >- break; >- >- case TUNER_PHILIPS_ATSC: >- /* 0x00 -> ATSC antenna input 1 */ >- /* 0x01 -> ATSC antenna input 2 */ >- /* 0x02 -> NTSC antenna input 1 */ >- /* 0x03 -> NTSC antenna input 2 */ >- config &= ~0x03; >- if (!(t->std & V4L2_STD_ATSC)) >- config |= 2; >- /* FIXME: input */ >- break; >- >- case TUNER_MICROTUNE_4042FI5: >- /* Set the charge pump for fast tuning */ >- tun->config |= 0x40; >- break; >- } >- >- /* >- * Philips FI1216MK2 remark from specification : >- * for channel selection involving band switching, and to ensure >- * smooth tuning to the desired channel without causing >- * unnecessary charge pump action, it is recommended to consider >- * the difference between wanted channel frequency and the >- * current channel frequency. Unnecessary charge pump action >- * will result in very low tuning voltage which may drive the >- * oscillator to extreme conditions. >- * >- * Progfou: specification says to send config data before >- * frequency in case (wanted frequency < current frequency). >- */ >- >- div=freq + tun->IFPCoff; >- if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) { >- buffer[0] = tun->config; >- buffer[1] = config; >- buffer[2] = (div>>8) & 0x7f; >- buffer[3] = div & 0xff; >- } else { >- buffer[0] = (div>>8) & 0x7f; >- buffer[1] = div & 0xff; >- buffer[2] = tun->config; >- buffer[3] = config; >- } >- dprintk("tuner: tv 0x%02x 0x%02x 0x%02x 0x%02x\n", >- buffer[0],buffer[1],buffer[2],buffer[3]); >- >- if (4 != (rc = i2c_master_send(c,buffer,4))) >- printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc); >- >- if (t->type == TUNER_MICROTUNE_4042FI5) { >- // FIXME - this may also work for other tuners >- unsigned long timeout = jiffies + msecs_to_jiffies(1); >- u8 status_byte = 0; >- >- /* Wait until the PLL locks */ >- for (;;) { >- if (time_after(jiffies,timeout)) >- return; >- if (1 != (rc = i2c_master_recv(c,&status_byte,1))) { >- dprintk("tuner: i2c i/o read error: rc == %d (should be 1)\n",rc); >- break; >- } >- /* bit 6 is PLL locked indicator */ >- if (status_byte & 0x40) >- break; >- udelay(10); >- } >- >- /* Set the charge pump for optimized phase noise figure */ >- tun->config &= ~0x40; >- buffer[0] = (div>>8) & 0x7f; >- buffer[1] = div & 0xff; >- buffer[2] = tun->config; >- buffer[3] = config; >- dprintk("tuner: tv 0x%02x 0x%02x 0x%02x 0x%02x\n", >- buffer[0],buffer[1],buffer[2],buffer[3]); >- >- if (4 != (rc = i2c_master_send(c,buffer,4))) >- dprintk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc); >- } >-} >- >-static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) >-{ >- struct tunertype *tun; >- struct tuner *t = i2c_get_clientdata(c); >- unsigned char buffer[4]; >- unsigned div; >- int rc; >- >- tun=&tuners[t->type]; >- div = freq + (int)(16*10.7); >- buffer[2] = tun->config; >- >- switch (t->type) { >- case TUNER_PHILIPS_FM1216ME_MK3: >- case TUNER_PHILIPS_FM1236_MK3: >- buffer[3] = 0x19; >- break; >- case TUNER_PHILIPS_FM1256_IH3: >- div = (20 * freq)/16 + 333 * 2; >- buffer[2] = 0x80; >- buffer[3] = 0x19; >- break; >- case TUNER_LG_PAL_FM: >- buffer[3] = 0xa5; >- break; >- default: >- buffer[3] = 0xa4; >- break; >- } >- buffer[0] = (div>>8) & 0x7f; >- buffer[1] = div & 0xff; >- >- dprintk("tuner: radio 0x%02x 0x%02x 0x%02x 0x%02x\n", >- buffer[0],buffer[1],buffer[2],buffer[3]); >- >- if (4 != (rc = i2c_master_send(c,buffer,4))) >- printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc); >-} >- >-/* ---------------------------------------------------------------------- */ >- >-// Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz >-static void set_tv_freq(struct i2c_client *c, unsigned int freq) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- >- if (t->type == UNSET) { >- printk("tuner: tuner type not set\n"); >- return; >- } >- if (NULL == t->tv_freq) { >- printk("tuner: Huh? tv_set is NULL?\n"); >- return; >- } >- if (freq < tv_range[0]*16 || freq > tv_range[1]*16) { >- /* FIXME: better do that chip-specific, but >- right now we don't have that in the config >- struct and this way is still better than no >- check at all */ >- printk("tuner: TV freq (%d.%02d) out of range (%d-%d)\n", >- freq/16,freq%16*100/16,tv_range[0],tv_range[1]); >- return; >- } >- t->tv_freq(c,freq); >-} >- >-static void set_radio_freq(struct i2c_client *c, unsigned int freq) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- >- if (t->type == UNSET) { >- printk("tuner: tuner type not set\n"); >- return; >- } >- if (NULL == t->radio_freq) { >- printk("tuner: no radio tuning for this one, sorry.\n"); >- return; >- } >- if (freq < radio_range[0]*16 || freq > radio_range[1]*16) { >- printk("tuner: radio freq (%d.%02d) out of range (%d-%d)\n", >- freq/16,freq%16*100/16, >- radio_range[0],radio_range[1]); >- return; >- } >- t->radio_freq(c,freq); >-} >- >-static void set_freq(struct i2c_client *c, unsigned long freq) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- >- switch (t->mode) { >- case V4L2_TUNER_RADIO: >- dprintk("tuner: radio freq set to %lu.%02lu\n", >- freq/16,freq%16*100/16); >- set_radio_freq(c,freq); >- break; >- case V4L2_TUNER_ANALOG_TV: >- case V4L2_TUNER_DIGITAL_TV: >- dprintk("tuner: tv freq set to %lu.%02lu\n", >- freq/16,freq%16*100/16); >- set_tv_freq(c, freq); >- break; >- } >- t->freq = freq; >-} >- >-static void set_type(struct i2c_client *c, unsigned int type, char *source) >-{ >- struct tuner *t = i2c_get_clientdata(c); >- >- if (t->type != UNSET && t->type != TUNER_ABSENT) { >- if (t->type != type) >- printk("tuner: type already set to %d, " >- "ignoring request for %d\n", t->type, type); >- return; >- } >- if (type >= TUNERS) >- return; >- >- t->type = type; >- printk("tuner: type set to %d (%s) by %s\n", >- t->type,tuners[t->type].name, source); >- strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); >- >- switch (t->type) { >- case TUNER_MT2032: >- microtune_init(c); >- break; >- default: >- t->tv_freq = default_set_tv_freq; >- t->radio_freq = default_set_radio_freq; >- break; >- } >-} >- >-static char pal[] = "-"; >-module_param_string(pal, pal, 0644, sizeof(pal)); >- >-static int tuner_fixup_std(struct tuner *t) >-{ >- if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { >- /* get more precise norm info from insmod option */ >- switch (pal[0]) { >- case 'b': >- case 'B': >- case 'g': >- case 'G': >- dprintk("insmod fixup: PAL => PAL-BG\n"); >- t->std = V4L2_STD_PAL_BG; >- break; >- case 'i': >- case 'I': >- dprintk("insmod fixup: PAL => PAL-I\n"); >- t->std = V4L2_STD_PAL_I; >- break; >- case 'd': >- case 'D': >- case 'k': >- case 'K': >- dprintk("insmod fixup: PAL => PAL-DK\n"); >- t->std = V4L2_STD_PAL_DK; >- break; >- } >- } >- return 0; >-} >- >-/* ---------------------------------------------------------------------- */ >- >-static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) >-{ >- struct tuner *t; >- struct i2c_client *client; >- >- if (this_adap > 0) >- return -1; >- this_adap++; >- >- client_template.adapter = adap; >- client_template.addr = addr; >- >- printk("tuner: chip found at addr 0x%x i2c-bus %s\n", >- addr<<1, adap->name); >- >- if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) >- return -ENOMEM; >- memcpy(client,&client_template,sizeof(struct i2c_client)); >- t = kmalloc(sizeof(struct tuner),GFP_KERNEL); >- if (NULL == t) { >- kfree(client); >- return -ENOMEM; >- } >- memset(t,0,sizeof(struct tuner)); >- i2c_set_clientdata(client, t); >- t->type = UNSET; >- t->radio_if2 = 10700*1000; // 10.7MHz - FM radio >- >- i2c_attach_client(client); >- if (type < TUNERS) { >- set_type(client, type, "insmod option"); >- printk("tuner: The type=<n> insmod option will go away soon.\n"); >- printk("tuner: Please use the tuner=<n> option provided by\n"); >- printk("tuner: tv aard core driver (bttv, saa7134, ...) instead.\n"); >- } >- return 0; >-} >- >-static int tuner_probe(struct i2c_adapter *adap) >-{ >- if (0 != addr) { >- normal_i2c_range[0] = addr; >- normal_i2c_range[1] = addr; >- } >- this_adap = 0; >- >-#ifdef I2C_CLASS_TV_ANALOG >- if (adap->class & I2C_CLASS_TV_ANALOG) >- return i2c_probe(adap, &addr_data, tuner_attach); >-#else >- switch (adap->id) { >- case I2C_ALGO_BIT | I2C_HW_SMBUS_VOODOO3: >- case I2C_ALGO_BIT | I2C_HW_B_BT848: >- case I2C_ALGO_BIT | I2C_HW_B_RIVA: >- case I2C_ALGO_SAA7134: >- case I2C_ALGO_SAA7146: >- return i2c_probe(adap, &addr_data, tuner_attach); >- break; >- } >-#endif >- return 0; >-} >- >-static int tuner_detach(struct i2c_client *client) >-{ >- struct tuner *t = i2c_get_clientdata(client); >- >- i2c_detach_client(client); >- kfree(t); >- kfree(client); >- return 0; >-} >- >-#define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ >- printk("tuner: switching to v4l2\n"); \ >- t->using_v4l2 = 1; >-#define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ >- printk("tuner: ignore v4l1 call\n"); \ >- return 0; } >- >-static int >-tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) >-{ >- struct tuner *t = i2c_get_clientdata(client); >- unsigned int *iarg = (int*)arg; >- >- switch (cmd) { >- >- /* --- configuration --- */ >- case TUNER_SET_TYPE: >- set_type(client,*iarg,client->adapter->name); >- break; >- case AUDC_SET_RADIO: >- if (V4L2_TUNER_RADIO != t->mode) { >- set_tv_freq(client,400 * 16); >- t->mode = V4L2_TUNER_RADIO; >- } >- break; >- case AUDC_CONFIG_PINNACLE: >- switch (*iarg) { >- case 2: >- dprintk("tuner: pinnacle pal\n"); >- t->radio_if2 = 33300 * 1000; >- break; >- case 3: >- dprintk("tuner: pinnacle ntsc\n"); >- t->radio_if2 = 41300 * 1000; >- break; >- } >- break; >- >- /* --- v4l ioctls --- */ >- /* take care: bttv does userspace copying, we'll get a >- kernel pointer here... */ >- case VIDIOCSCHAN: >- { >- static const v4l2_std_id map[] = { >- [ VIDEO_MODE_PAL ] = V4L2_STD_PAL, >- [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M, >- [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM, >- [ 4 /* bttv */ ] = V4L2_STD_PAL_M, >- [ 5 /* bttv */ ] = V4L2_STD_PAL_N, >- [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, >- }; >- struct video_channel *vc = arg; >- >- CHECK_V4L2; >- t->mode = V4L2_TUNER_ANALOG_TV; >- if (vc->norm < ARRAY_SIZE(map)) >- t->std = map[vc->norm]; >- tuner_fixup_std(t); >- if (t->freq) >- set_tv_freq(client,t->freq); >- return 0; >- } >- case VIDIOCSFREQ: >- { >- unsigned long *v = arg; >- >- CHECK_V4L2; >- set_freq(client,*v); >- return 0; >- } >- case VIDIOCGTUNER: >- { >- struct video_tuner *vt = arg; >- >- CHECK_V4L2; >- if (V4L2_TUNER_RADIO == t->mode) >- vt->signal = tuner_signal(client); >- return 0; >- } >- case VIDIOCGAUDIO: >- { >- struct video_audio *va = arg; >- >- CHECK_V4L2; >- if (V4L2_TUNER_RADIO == t->mode) >- va->mode = (tuner_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO); >- return 0; >- } >- >- case VIDIOC_S_STD: >- { >- v4l2_std_id *id = arg; >- >- SWITCH_V4L2; >- t->mode = V4L2_TUNER_ANALOG_TV; >- t->std = *id; >- tuner_fixup_std(t); >- if (t->freq) >- set_freq(client,t->freq); >- break; >- } >- case VIDIOC_S_FREQUENCY: >- { >- struct v4l2_frequency *f = arg; >- >- SWITCH_V4L2; >- if (V4L2_TUNER_RADIO == f->type && >- V4L2_TUNER_RADIO != t->mode) >- set_tv_freq(client,400*16); >- t->mode = f->type; >- t->freq = f->frequency; >- set_freq(client,t->freq); >- break; >- } >- case VIDIOC_G_TUNER: >- { >- struct v4l2_tuner *tuner = arg; >- >- SWITCH_V4L2; >- if (V4L2_TUNER_RADIO == t->mode) >- tuner->signal = tuner_signal(client); >- break; >- } >- default: >- /* nothing */ >- break; >- } >- >- return 0; >-} >- >-static int tuner_suspend(struct device * dev, u32 state, u32 level) >-{ >- dprintk("tuner: suspend\n"); >- /* FIXME: power down ??? */ >- return 0; >-} >- >-static int tuner_resume(struct device * dev, u32 level) >-{ >- struct i2c_client *c = container_of(dev, struct i2c_client, dev); >- struct tuner *t = i2c_get_clientdata(c); >- >- dprintk("tuner: resume\n"); >- if (t->freq) >- set_freq(c,t->freq); >- return 0; >-} >- >-/* ----------------------------------------------------------------------- */ >- >-static struct i2c_driver driver = { >- .owner = THIS_MODULE, >- .name = "i2c TV tuner driver", >- .id = I2C_DRIVERID_TUNER, >- .flags = I2C_DF_NOTIFY, >- .attach_adapter = tuner_probe, >- .detach_client = tuner_detach, >- .command = tuner_command, >- .driver = { >- .suspend = tuner_suspend, >- .resume = tuner_resume, >- }, >-}; >-static struct i2c_client client_template = >-{ >- I2C_DEVNAME("(tuner unset)"), >- .flags = I2C_CLIENT_ALLOW_USE, >- .driver = &driver, >-}; >- >-static int __init tuner_init_module(void) >-{ >- return i2c_add_driver(&driver); >-} >- >-static void __exit tuner_cleanup_module(void) >-{ >- i2c_del_driver(&driver); >-} >- >-module_init(tuner_init_module); >-module_exit(tuner_cleanup_module); >- >-/* >- * Overrides for Emacs so that we follow Linus's tabbing style. >- * --------------------------------------------------------------------------- >- * Local variables: >- * c-basic-offset: 8 >- * End: >- */ >Index: linux-2.6.11/drivers/media/video/tvaudio.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/tvaudio.c 2005-03-07 10:13:26.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/tvaudio.c 2005-03-07 18:13:02.000000000 +0100 >@@ -990,7 +990,7 @@ static int tda9874a_initialize(struct CH > { > if (tda9874a_SIF > 2) > tda9874a_SIF = 1; >- if (tda9874a_STD >= 8) >+ if (tda9874a_STD > 8) > tda9874a_STD = 0; > if(tda9874a_AMSEL > 1) > tda9874a_AMSEL = 0; >Index: linux-2.6.11/drivers/media/video/tveeprom.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/tveeprom.c 2005-03-07 10:15:43.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/tveeprom.c 2005-03-08 10:33:08.000000000 +0100 >@@ -30,10 +30,12 @@ > > > #include <linux/module.h> >+#include <linux/moduleparam.h> > #include <linux/errno.h> > #include <linux/kernel.h> > #include <linux/init.h> > #include <linux/types.h> >+#include <linux/videodev.h> > #include <linux/i2c.h> > > #include <media/tuner.h> >@@ -73,7 +75,7 @@ hauppauge_tuner_fmt[] = > { 0x00000007, "PAL(B/G)" }, > { 0x00001000, "NTSC(M)" }, > { 0x00000010, "PAL(I)" }, >- { 0x00400000, "SECAM(L/L�)" }, >+ { 0x00400000, "SECAM(L/L´)" }, > { 0x00000e00, "PAL(D/K)" }, > { 0x03000000, "ATSC Digital" }, > }; >@@ -190,11 +192,13 @@ hauppauge_tuner[] = > { TUNER_ABSENT, "TCL MFPE05 2"}, > /* 90-99 */ > { TUNER_ABSENT, "LG TALN H202T"}, >- { TUNER_ABSENT, "Philips FQ1216AME MK4"}, >- { TUNER_ABSENT, "Philips FQ1236A MK4"}, >+ { TUNER_PHILIPS_FQ1216AME_MK4, "Philips FQ1216AME MK4"}, >+ { TUNER_PHILIPS_FQ1236A_MK4, "Philips FQ1236A MK4"}, > { TUNER_ABSENT, "Philips FQ1286A MK4"}, > { TUNER_ABSENT, "Philips FQ1216ME MK5"}, > { TUNER_ABSENT, "Philips FQ1236 MK5"}, >+ { TUNER_ABSENT, "Unspecified"}, >+ { TUNER_LG_PAL_TAPE, "LG PAL (TAPE Series)"}, > }; > > static char *sndtype[] = { >@@ -240,6 +244,7 @@ static int hasRadioTuner(int tunerType) > case 61: //PNPEnv_TUNER_TAPE_M001D_MK3: > case 78: //PNPEnv_TUNER_TDA8275C1_8290_FM: > case 89: //PNPEnv_TUNER_TCL_MFPE05_2: >+ case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4: > return 1; > } > return 0; >@@ -255,8 +260,8 @@ void tveeprom_hauppauge_analog(struct tv > ** if packet[0] & f8 == f8, then EOD and packet[1] == checksum > ** > ** In our (ivtv) case we're interested in the following: >- ** tuner type: tag [00].05 or [0a].01 (index into hauppauge_tuners) >- ** tuner fmts: tag [00].04 or [0a].00 (bitmask index into hauppauge_fmts) >+ ** tuner type: tag [00].05 or [0a].01 (index into hauppauge_tuner) >+ ** tuner fmts: tag [00].04 or [0a].00 (bitmask index into hauppauge_tuner_fmt) > ** radio: tag [00].{last} or [0e].00 (bitmask. bit2=FM) > ** audio proc: tag [02].01 or [05].00 (lower nibble indexes lut?) > >@@ -268,11 +273,11 @@ void tveeprom_hauppauge_analog(struct tv > ** # of inputs/outputs ??? > */ > >- int i, j, len, done, tag, tuner = 0, t_format = 0; >+ int i, j, len, done, beenhere, tag, tuner = 0, t_format = 0; > char *t_name = NULL, *t_fmt_name = NULL; > > dprintk(1, "%s\n",__FUNCTION__); >- tvee->revision = done = len = 0; >+ tvee->revision = done = len = beenhere = 0; > for (i = 0; !done && i < 256; i += len) { > dprintk(2, "processing pos = %02x (%02x, %02x)\n", > i, eeprom_data[i], eeprom_data[i + 1]); >@@ -341,9 +346,14 @@ void tveeprom_hauppauge_analog(struct tv > (eeprom_data[i+7] << 16); > break; > case 0x0a: >- tuner = eeprom_data[i+2]; >- t_format = eeprom_data[i+1]; >- break; >+ if(beenhere == 0) { >+ tuner = eeprom_data[i+2]; >+ t_format = eeprom_data[i+1]; >+ beenhere = 1; >+ break; >+ } else { >+ break; >+ } > case 0x0e: > tvee->has_radio = eeprom_data[i+1]; > break; >Index: linux-2.6.11/drivers/media/video/video-buf.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/video-buf.c 2005-03-07 10:13:55.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/video-buf.c 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: video-buf.c,v 1.17 2004/12/10 12:33:40 kraxel Exp $ >+ * $Id: video-buf.c,v 1.18 2005/02/24 13:32:30 kraxel Exp $ > * > * generic helper functions for video4linux capture buffers, to handle > * memory management and PCI DMA. Right now bttv + saa7134 use it. >@@ -217,9 +217,18 @@ int videobuf_dma_pci_map(struct pci_dev > return -ENOMEM; > } > >- if (!dma->bus_addr) >+ if (!dma->bus_addr) { > dma->sglen = pci_map_sg(dev,dma->sglist,dma->nr_pages, > dma->direction); >+ if (0 == dma->sglen) { >+ printk(KERN_WARNING >+ "%s: pci_map_sg failed\n",__FUNCTION__); >+ kfree(dma->sglist); >+ dma->sglist = NULL; >+ dma->sglen = 0; >+ return -EIO; >+ } >+ } > return 0; > } > >Index: linux-2.6.11/drivers/media/video/zoran_card.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/zoran_card.c 2005-03-07 10:14:15.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/zoran_card.c 2005-03-08 10:33:15.000000000 +0100 >@@ -41,6 +41,7 @@ > #include <linux/spinlock.h> > #include <linux/sem.h> > #include <linux/kmod.h> >+#include <linux/wait.h> > > #include <linux/pci.h> > #include <linux/interrupt.h> >@@ -968,6 +969,7 @@ zoran_open_init_params (struct zoran *zr > static void __devinit > test_interrupts (struct zoran *zr) > { >+ DEFINE_WAIT(wait); > int timeout, icr; > > clear_interrupt_counters(zr); >@@ -975,7 +977,9 @@ test_interrupts (struct zoran *zr) > zr->testing = 1; > icr = btread(ZR36057_ICR); > btwrite(0x78000000 | ZR36057_ICR_IntPinEn, ZR36057_ICR); >- timeout = interruptible_sleep_on_timeout(&zr->test_q, 1 * HZ); >+ prepare_to_wait(&zr->test_q, &wait, TASK_INTERRUPTIBLE); >+ timeout = schedule_timeout(HZ); >+ finish_wait(&zr->test_q, &wait); > btwrite(0, ZR36057_ICR); > btwrite(0x78000000, ZR36057_ISR); > zr->testing = 0; >Index: linux-2.6.11/drivers/media/video/zoran_device.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/zoran_device.c 2005-03-07 10:14:13.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/zoran_device.c 2005-03-08 10:33:15.000000000 +0100 >@@ -46,6 +46,7 @@ > #include <linux/video_decoder.h> > #include <linux/video_encoder.h> > #include <linux/delay.h> >+#include <linux/wait.h> > > #include <asm/io.h> > >@@ -696,11 +697,10 @@ wait_grab_pending (struct zoran *zr) > if (!zr->v4l_memgrab_active) > return 0; > >- while (zr->v4l_pend_tail != zr->v4l_pend_head) { >- interruptible_sleep_on(&zr->v4l_capq); >- if (signal_pending(current)) >- return -ERESTARTSYS; >- } >+ wait_event_interruptible(zr->v4l_capq, >+ (zr->v4l_pend_tail == zr->v4l_pend_head)); >+ if (signal_pending(current)) >+ return -ERESTARTSYS; > > spin_lock_irqsave(&zr->spinlock, flags); > zr36057_set_memgrab(zr, 0); >Index: linux-2.6.11/drivers/media/video/zoran_driver.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/zoran_driver.c 2005-03-07 10:14:50.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/zoran_driver.c 2005-03-08 10:33:15.000000000 +0100 >@@ -52,6 +52,7 @@ > #include <linux/slab.h> > #include <linux/pci.h> > #include <linux/vmalloc.h> >+#include <linux/wait.h> > #include <linux/byteorder/generic.h> > > #include <linux/interrupt.h> >@@ -918,12 +919,12 @@ v4l_sync (struct file *file, > } > > /* wait on this buffer to get ready */ >- while (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_PEND) { >- if (!interruptible_sleep_on_timeout(&zr->v4l_capq, 10 * HZ)) >- return -ETIME; >- else if (signal_pending(current)) >- return -ERESTARTSYS; >- } >+ if (!wait_event_interruptible_timeout(zr->v4l_capq, >+ (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), >+ 10*HZ)) >+ return -ETIME; >+ if (signal_pending(current)) >+ return -ERESTARTSYS; > > /* buffer should now be in BUZ_STATE_DONE */ > if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE) >@@ -1107,7 +1108,7 @@ jpg_sync (struct file *file, > struct zoran_fh *fh = file->private_data; > struct zoran *zr = fh->zr; > unsigned long flags; >- int frame, timeout; >+ int frame; > > if (fh->jpg_buffers.active == ZORAN_FREE) { > dprintk(1, >@@ -1124,29 +1125,26 @@ jpg_sync (struct file *file, > ZR_DEVNAME(zr)); > return -EINVAL; > } >- while (zr->jpg_que_tail == zr->jpg_dma_tail) { >- if (zr->jpg_dma_tail == zr->jpg_dma_head) >- break; >- >- timeout = >- interruptible_sleep_on_timeout(&zr->jpg_capq, 10 * HZ); >- if (!timeout) { >- int isr; >+ if (!wait_event_interruptible_timeout(zr->jpg_capq, >+ (zr->jpg_que_tail != zr->jpg_dma_tail || >+ zr->jpg_dma_tail == zr->jpg_dma_head), >+ 10*HZ)) { >+ int isr; > >- btand(~ZR36057_JMC_Go_en, ZR36057_JMC); >- udelay(1); >- zr->codec->control(zr->codec, CODEC_G_STATUS, >+ btand(~ZR36057_JMC_Go_en, ZR36057_JMC); >+ udelay(1); >+ zr->codec->control(zr->codec, CODEC_G_STATUS, > sizeof(isr), &isr); >- dprintk(1, >- KERN_ERR >- "%s: jpg_sync() - timeout: codec isr=0x%02x\n", >- ZR_DEVNAME(zr), isr); >+ dprintk(1, >+ KERN_ERR >+ "%s: jpg_sync() - timeout: codec isr=0x%02x\n", >+ ZR_DEVNAME(zr), isr); > >- return -ETIME; >+ return -ETIME; > >- } else if (signal_pending(current)) >- return -ERESTARTSYS; > } >+ if (signal_pending(current)) >+ return -ERESTARTSYS; > > spin_lock_irqsave(&zr->spinlock, flags); > >Index: linux-2.6.11/drivers/media/video/zr36120.c >=================================================================== >--- linux-2.6.11.orig/drivers/media/video/zr36120.c 2005-03-07 10:13:55.000000000 +0100 >+++ linux-2.6.11/drivers/media/video/zr36120.c 2005-03-08 10:33:15.000000000 +0100 >@@ -30,6 +30,7 @@ > #include <linux/mm.h> > #include <linux/pci.h> > #include <linux/signal.h> >+#include <linux/wait.h> > #include <asm/io.h> > #include <asm/pgtable.h> > #include <asm/page.h> >@@ -899,12 +900,11 @@ long zoran_read(struct video_device* dev > zoran_cap(ztv, 1); > > /* wait till this buffer gets grabbed */ >- while (unused->status == FBUFFER_BUSY) { >- interruptible_sleep_on(&ztv->grabq); >- /* see if a signal did it */ >- if (signal_pending(current)) >- return -EINTR; >- } >+ wait_event_interruptible(ztv->grabq, >+ (unused->status != FBUFFER_BUSY)); >+ /* see if a signal did it */ >+ if (signal_pending(current)) >+ return -EINTR; > done = unused; > } > else >@@ -1326,12 +1326,11 @@ int zoran_ioctl(struct video_device* dev > return -EINVAL; > case FBUFFER_BUSY: > /* wait till this buffer gets grabbed */ >- while (ztv->grabinfo[i].status == FBUFFER_BUSY) { >- interruptible_sleep_on(&ztv->grabq); >- /* see if a signal did it */ >- if (signal_pending(current)) >- return -EINTR; >- } >+ wait_event_interruptible(ztv->grabq, >+ (ztv->grabinfo[i].status != FBUFFER_BUSY)); >+ /* see if a signal did it */ >+ if (signal_pending(current)) >+ return -EINTR; > /* don't fall through; a DONE buffer is not UNUSED */ > break; > case FBUFFER_DONE: >@@ -1640,12 +1639,11 @@ long vbi_read(struct video_device* dev, > zoran_cap(ztv, 1); > > /* wait till this buffer gets grabbed */ >- while (unused->status == FBUFFER_BUSY) { >- interruptible_sleep_on(&ztv->vbiq); >- /* see if a signal did it */ >- if (signal_pending(current)) >- return -EINTR; >- } >+ wait_event_interruptible(ztv->vbiq, >+ (unused->status != FBUFFER_BUSY)); >+ /* see if a signal did it */ >+ if (signal_pending(current)) >+ return -EINTR; > done = unused; > } > else >Index: linux-2.6.11/drivers/scsi/Kconfig >=================================================================== >--- linux-2.6.11.orig/drivers/scsi/Kconfig 2005-03-07 10:15:16.000000000 +0100 >+++ linux-2.6.11/drivers/scsi/Kconfig 2005-03-07 18:13:01.000000000 +0100 >@@ -137,6 +137,24 @@ config CHR_DEV_SG > > If unsure, say N. > >+config CHR_DEV_SCH >+ tristate "SCSI media changer support" >+ depends on SCSI >+ ---help--- >+ This is a driver for SCSI media changers. Most common devices are >+ tape libraries and MOD/CDROM jukeboxes. *Real* jukeboxes, you >+ don't need this for those tiny 6-slot cdrom changers. Media >+ changers are listed as "Type: Medium Changer" in /proc/scsi/scsi. >+ If you have such hardware and want to use it with linux, say Y >+ here. Check <file:Documentation/scsi-changer.txt> for details. >+ >+ If you want to compile this as a module ( = code which can be >+ inserted in and removed from the running kernel whenever you want), >+ say M here and read <file:Documentation/modules.txt> and >+ <file:Documentation/scsi.txt>. The module will be called ch.o. >+ If unsure, say N. >+ >+ > comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs" > depends on SCSI > >Index: linux-2.6.11/drivers/scsi/Makefile >=================================================================== >--- linux-2.6.11.orig/drivers/scsi/Makefile 2005-03-07 10:14:58.000000000 +0100 >+++ linux-2.6.11/drivers/scsi/Makefile 2005-03-07 18:13:01.000000000 +0100 >@@ -141,6 +141,7 @@ obj-$(CONFIG_CHR_DEV_OSST) += osst.o > obj-$(CONFIG_BLK_DEV_SD) += sd_mod.o > obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o > obj-$(CONFIG_CHR_DEV_SG) += sg.o >+obj-$(CONFIG_CHR_DEV_SCH) += ch.o > > scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ > scsicam.o scsi_error.o scsi_lib.o \ >Index: linux-2.6.11/drivers/scsi/ch.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/drivers/scsi/ch.c 2005-03-07 18:13:01.000000000 +0100 >@@ -0,0 +1,1020 @@ >+/* >+ * SCSI Media Changer device driver for Linux 2.6 >+ * >+ * (c) 1996-2003 Gerd Knorr <kraxel@bytesex.org> >+ * >+ */ >+ >+#define VERSION "0.24" >+ >+#include <linux/config.h> >+#include <linux/module.h> >+#include <linux/init.h> >+#include <linux/fs.h> >+#include <linux/kernel.h> >+#include <linux/sched.h> >+#include <linux/mm.h> >+#include <linux/major.h> >+#include <linux/string.h> >+#include <linux/errno.h> >+#include <linux/interrupt.h> >+#include <linux/blkdev.h> >+#include <linux/completion.h> >+#include <linux/devfs_fs_kernel.h> >+#include <linux/ioctl32.h> >+#include <linux/compat.h> >+#include <linux/chio.h> /* here are all the ioctls */ >+ >+#include <scsi/scsi.h> >+#include <scsi/scsi_cmnd.h> >+#include <scsi/scsi_driver.h> >+#include <scsi/scsi_ioctl.h> >+#include <scsi/scsi_host.h> >+#include <scsi/scsi_device.h> >+#include <scsi/scsi_request.h> >+#include <scsi/scsi_dbg.h> >+ >+#define CH_DT_MAX 16 >+#define CH_TYPES 8 >+ >+MODULE_DESCRIPTION("device driver for scsi media changer devices"); >+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org>"); >+MODULE_LICENSE("GPL"); >+ >+static int init = 1; >+module_param(init, int, 0444); >+MODULE_PARM_DESC(init, \ >+ "initialize element status on driver load (default: on)"); >+ >+static int timeout_move = 300; >+module_param(timeout_move, int, 0644); >+MODULE_PARM_DESC(timeout_move,"timeout for move commands " >+ "(default: 300 seconds)"); >+ >+static int timeout_init = 3600; >+module_param(timeout_init, int, 0644); >+MODULE_PARM_DESC(timeout_init,"timeout for INITIALIZE ELEMENT STATUS " >+ "(default: 3600 seconds)"); >+ >+static int verbose = 1; >+module_param(verbose, int, 0644); >+MODULE_PARM_DESC(verbose,"be verbose (default: on)"); >+ >+static int debug = 0; >+module_param(debug, int, 0644); >+MODULE_PARM_DESC(debug,"enable/disable debug messages, also prints more " >+ "detailed sense codes on scsi errors (default: off)"); >+ >+static int dt_id[CH_DT_MAX] = { [ 0 ... (CH_DT_MAX-1) ] = -1 }; >+static int dt_lun[CH_DT_MAX]; >+module_param_array(dt_id, int, NULL, 0444); >+module_param_array(dt_lun, int, NULL, 0444); >+ >+/* tell the driver about vendor-specific slots */ >+static int vendor_firsts[CH_TYPES-4]; >+static int vendor_counts[CH_TYPES-4]; >+module_param_array(vendor_firsts, int, NULL, 0444); >+module_param_array(vendor_counts, int, NULL, 0444); >+ >+static char *vendor_labels[CH_TYPES-4] = { >+ "v0", "v1", "v2", "v3" >+}; >+// module_param_string_array(vendor_labels, NULL, 0444); >+ >+#define dprintk(fmt, arg...) if (debug) \ >+ printk(KERN_DEBUG "%s: " fmt, ch->name, ##arg) >+#define vprintk(fmt, arg...) if (verbose) \ >+ printk(KERN_INFO "%s: " fmt, ch->name, ##arg) >+ >+/* ------------------------------------------------------------------- */ >+ >+#define MAX_RETRIES 1 >+ >+static int ch_probe(struct device *); >+static int ch_remove(struct device *); >+static int ch_open(struct inode * inode, struct file * filp); >+static int ch_release(struct inode * inode, struct file * filp); >+static int ch_ioctl(struct inode * inode, struct file * filp, >+ unsigned int cmd, unsigned long arg); >+static long ch_ioctl_compat(struct file * filp, >+ unsigned int cmd, unsigned long arg); >+ >+typedef struct { >+ struct list_head list; >+ int minor; >+ char name[8]; >+ struct scsi_device *device; >+ struct scsi_device **dt; /* ptrs to data transfer elements */ >+ u_int firsts[CH_TYPES]; >+ u_int counts[CH_TYPES]; >+ u_int unit_attention; >+ u_int voltags; >+ struct semaphore lock; >+} scsi_changer; >+ >+static LIST_HEAD(ch_devlist); >+static spinlock_t ch_devlist_lock = SPIN_LOCK_UNLOCKED; >+static int ch_devcount; >+ >+struct scsi_driver ch_template = >+{ >+ .owner = THIS_MODULE, >+ .gendrv = { >+ .name = "ch", >+ .probe = ch_probe, >+ .remove = ch_remove, >+ }, >+}; >+ >+static struct file_operations changer_fops = >+{ >+ .owner = THIS_MODULE, >+ .open = ch_open, >+ .release = ch_release, >+ .ioctl = ch_ioctl, >+#ifdef CONFIG_COMPAT >+ .compat_ioctl = ch_ioctl_compat, >+#endif >+}; >+ >+static struct { >+ unsigned char sense; >+ unsigned char asc; >+ unsigned char ascq; >+ int errno; >+} err[] = { >+/* Just filled in what looks right. Hav'nt checked any standard paper for >+ these errno assignments, so they may be wrong... */ >+ { >+ .sense = ILLEGAL_REQUEST, >+ .asc = 0x21, >+ .ascq = 0x01, >+ .errno = EBADSLT, /* Invalid element address */ >+ },{ >+ .sense = ILLEGAL_REQUEST, >+ .asc = 0x28, >+ .ascq = 0x01, >+ .errno = EBADE, /* Import or export element accessed */ >+ },{ >+ .sense = ILLEGAL_REQUEST, >+ .asc = 0x3B, >+ .ascq = 0x0D, >+ .errno = EXFULL, /* Medium destination element full */ >+ },{ >+ .sense = ILLEGAL_REQUEST, >+ .asc = 0x3B, >+ .ascq = 0x0E, >+ .errno = EBADE, /* Medium source element empty */ >+ },{ >+ .sense = ILLEGAL_REQUEST, >+ .asc = 0x20, >+ .ascq = 0x00, >+ .errno = EBADRQC, /* Invalid command operation code */ >+ },{ >+ /* end of list */ >+ } >+}; >+ >+/* ------------------------------------------------------------------- */ >+ >+static int ch_find_errno(unsigned char *sense_buffer) >+{ >+ int i,errno = 0; >+ >+ /* Check to see if additional sense information is available */ >+ if (sense_buffer[7] > 5 && >+ sense_buffer[12] != 0) { >+ for (i = 0; err[i].errno != 0; i++) { >+ if (err[i].sense == sense_buffer[ 2] && >+ err[i].asc == sense_buffer[12] && >+ err[i].ascq == sense_buffer[13]) { >+ errno = -err[i].errno; >+ break; >+ } >+ } >+ } >+ if (errno == 0) >+ errno = -EIO; >+ return errno; >+} >+ >+static void >+ch_request_done(struct scsi_cmnd *sc) >+{ >+ sc->request->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ >+ if (sc->request->waiting != NULL) >+ complete(sc->request->waiting); >+} >+ >+static int >+ch_do_scsi(scsi_changer *ch, unsigned char *cmd, >+ void *buffer, unsigned buflength) >+{ >+ int errno, retries = 0, timeout; >+ DECLARE_COMPLETION(wait); >+ struct scsi_request *sr; >+ >+ sr = scsi_allocate_request(ch->device, GFP_KERNEL); >+ if (NULL == sr) >+ return -ENOMEM; >+ >+ retry: >+ errno = 0; >+ if (debug) { >+ dprintk("command: "); >+ __scsi_print_command(cmd); >+ } >+ >+ sr->sr_request->waiting = &wait; >+ timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS) >+ ? timeout_init : timeout_move; >+ scsi_do_req(sr, cmd, buffer, buflength, ch_request_done, >+ timeout * HZ, MAX_RETRIES); >+ wait_for_completion(&wait); >+ sr->sr_request->waiting = NULL; >+ >+ dprintk("result: 0x%x\n",sr->sr_result); >+ if (driver_byte(sr->sr_result) != 0) { >+ if (debug) >+ scsi_print_req_sense(ch->name, sr); >+ errno = ch_find_errno(sr->sr_sense_buffer); >+ >+ switch(sr->sr_sense_buffer[2] & 0xf) { >+ case UNIT_ATTENTION: >+ ch->unit_attention = 1; >+ if (retries++ < 3) >+ goto retry; >+ break; >+ } >+ } >+ scsi_release_request(sr); >+ return errno; >+} >+ >+/* ------------------------------------------------------------------------ */ >+ >+static int >+ch_elem_to_typecode(scsi_changer *ch, u_int elem) >+{ >+ int i; >+ >+ for (i = 0; i < CH_TYPES; i++) { >+ if (elem >= ch->firsts[i] && >+ elem < ch->firsts[i] + >+ ch->counts[i]) >+ return i+1; >+ } >+ return 0; >+} >+ >+static int >+ch_read_element_status(scsi_changer *ch, u_int elem, char *data) >+{ >+ u_char cmd[12]; >+ u_char *buffer; >+ int result; >+ >+ buffer = kmalloc(512, GFP_KERNEL); >+ if(!buffer) >+ return -ENOMEM; >+ >+ retry: >+ memset(cmd,0,sizeof(cmd)); >+ cmd[0] = READ_ELEMENT_STATUS; >+ cmd[1] = (ch->device->lun << 5) | >+ (ch->voltags ? 0x10 : 0) | >+ ch_elem_to_typecode(ch,elem); >+ cmd[2] = (elem >> 8) & 0xff; >+ cmd[3] = elem & 0xff; >+ cmd[5] = 1; >+ cmd[9] = 255; >+ if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256))) { >+ if (((buffer[16] << 8) | buffer[17]) != elem) { >+ dprintk("asked for element 0x%02x, got 0x%02x\n", >+ elem,(buffer[16] << 8) | buffer[17]); >+ kfree(buffer); >+ return -EIO; >+ } >+ memcpy(data,buffer+16,16); >+ } else { >+ if (ch->voltags) { >+ ch->voltags = 0; >+ vprintk("device has no volume tag support%s\n",""); >+ goto retry; >+ } >+ dprintk("READ ELEMENT STATUS for element 0x%x failed\n",elem); >+ } >+ kfree(buffer); >+ return result; >+} >+ >+static int >+ch_init_elem(scsi_changer *ch) >+{ >+ int err; >+ u_char cmd[6]; >+ >+ vprintk("INITIALIZE ELEMENT STATUS, may take some time ...%s\n",""); >+ memset(cmd,0,sizeof(cmd)); >+ cmd[0] = INITIALIZE_ELEMENT_STATUS; >+ cmd[1] = ch->device->lun << 5; >+ err = ch_do_scsi(ch, cmd, NULL, 0); >+ vprintk("... finished%s\n",""); >+ return err; >+} >+ >+static int >+ch_readconfig(scsi_changer *ch) >+{ >+ u_char cmd[10], data[16]; >+ u_char *buffer; >+ int result,id,lun,i; >+ u_int elem; >+ >+ buffer = kmalloc(512, GFP_KERNEL); >+ if (!buffer) >+ return -ENOMEM; >+ memset(buffer,0,512); >+ >+ memset(cmd,0,sizeof(cmd)); >+ cmd[0] = MODE_SENSE; >+ cmd[1] = ch->device->lun << 5; >+ cmd[2] = 0x1d; >+ cmd[4] = 255; >+ result = ch_do_scsi(ch, cmd, buffer, 255); >+ if (0 != result) { >+ cmd[1] |= (1<<3); >+ result = ch_do_scsi(ch, cmd, buffer, 255); >+ } >+ if (0 == result) { >+ ch->firsts[CHET_MT] = >+ (buffer[buffer[3]+ 6] << 8) | buffer[buffer[3]+ 7]; >+ ch->counts[CHET_MT] = >+ (buffer[buffer[3]+ 8] << 8) | buffer[buffer[3]+ 9]; >+ ch->firsts[CHET_ST] = >+ (buffer[buffer[3]+10] << 8) | buffer[buffer[3]+11]; >+ ch->counts[CHET_ST] = >+ (buffer[buffer[3]+12] << 8) | buffer[buffer[3]+13]; >+ ch->firsts[CHET_IE] = >+ (buffer[buffer[3]+14] << 8) | buffer[buffer[3]+15]; >+ ch->counts[CHET_IE] = >+ (buffer[buffer[3]+16] << 8) | buffer[buffer[3]+17]; >+ ch->firsts[CHET_DT] = >+ (buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19]; >+ ch->counts[CHET_DT] = >+ (buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21]; >+ vprintk("type #1 (mt): 0x%x+%d [medium transport]\n", >+ ch->firsts[CHET_MT], >+ ch->counts[CHET_MT]); >+ vprintk("type #2 (st): 0x%x+%d [storage]\n", >+ ch->firsts[CHET_ST], >+ ch->counts[CHET_ST]); >+ vprintk("type #3 (ie): 0x%x+%d [import/export]\n", >+ ch->firsts[CHET_IE], >+ ch->counts[CHET_IE]); >+ vprintk("type #4 (dt): 0x%x+%d [data transfer]\n", >+ ch->firsts[CHET_DT], >+ ch->counts[CHET_DT]); >+ } else { >+ vprintk("reading element address assigment page failed!%s\n", >+ ""); >+ } >+ >+ /* vendor specific element types */ >+ for (i = 0; i < 4; i++) { >+ if (0 == vendor_counts[i]) >+ continue; >+ if (NULL == vendor_labels[i]) >+ continue; >+ ch->firsts[CHET_V1+i] = vendor_firsts[i]; >+ ch->counts[CHET_V1+i] = vendor_counts[i]; >+ vprintk("type #%d (v%d): 0x%x+%d [%s, vendor specific]\n", >+ i+5,i+1,vendor_firsts[i],vendor_counts[i], >+ vendor_labels[i]); >+ } >+ >+ /* look up the devices of the data transfer elements */ >+ ch->dt = kmalloc(ch->counts[CHET_DT]*sizeof(struct scsi_device), >+ GFP_KERNEL); >+ for (elem = 0; elem < ch->counts[CHET_DT]; elem++) { >+ id = -1; >+ lun = 0; >+ if (-1 != dt_id[elem]) { >+ id = dt_id[elem]; >+ lun = dt_lun[elem]; >+ vprintk("dt 0x%x: [insmod option] ", >+ elem+ch->firsts[CHET_DT]); >+ } else if (0 != ch_read_element_status >+ (ch,elem+ch->firsts[CHET_DT],data)) { >+ vprintk("dt 0x%x: READ ELEMENT STATUS failed\n", >+ elem+ch->firsts[CHET_DT]); >+ } else { >+ vprintk("dt 0x%x: ",elem+ch->firsts[CHET_DT]); >+ if (data[6] & 0x80) { >+ if (verbose) >+ printk("not this SCSI bus\n"); >+ ch->dt[elem] = NULL; >+ } else if (0 == (data[6] & 0x30)) { >+ if (verbose) >+ printk("ID/LUN unknown\n"); >+ ch->dt[elem] = NULL; >+ } else { >+ id = ch->device->id; >+ lun = 0; >+ if (data[6] & 0x20) id = data[7]; >+ if (data[6] & 0x10) lun = data[6] & 7; >+ } >+ } >+ if (-1 != id) { >+ if (verbose) >+ printk("ID %i, LUN %i, ",id,lun); >+ ch->dt[elem] = >+ scsi_device_lookup(ch->device->host, >+ ch->device->channel, >+ id,lun); >+ if (!ch->dt[elem]) { >+ /* should not happen */ >+ if (verbose) >+ printk("Huh? device not found!\n"); >+ } else { >+ if (verbose) >+ printk("name: %8.8s %16.16s %4.4s\n", >+ ch->dt[elem]->vendor, >+ ch->dt[elem]->model, >+ ch->dt[elem]->rev); >+ } >+ } >+ } >+ ch->voltags = 1; >+ kfree(buffer); >+ >+ return 0; >+} >+ >+/* ------------------------------------------------------------------------ */ >+ >+static int >+ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate) >+{ >+ u_char cmd[10]; >+ >+ dprintk("position: 0x%x\n",elem); >+ if (0 == trans) >+ trans = ch->firsts[CHET_MT]; >+ memset(cmd,0,sizeof(cmd)); >+ cmd[0] = POSITION_TO_ELEMENT; >+ cmd[1] = ch->device->lun << 5; >+ cmd[2] = (trans >> 8) & 0xff; >+ cmd[3] = trans & 0xff; >+ cmd[4] = (elem >> 8) & 0xff; >+ cmd[5] = elem & 0xff; >+ cmd[8] = rotate ? 1 : 0; >+ return ch_do_scsi(ch, cmd, NULL,0); >+} >+ >+static int >+ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate) >+{ >+ u_char cmd[12]; >+ >+ dprintk("move: 0x%x => 0x%x\n",src,dest); >+ if (0 == trans) >+ trans = ch->firsts[CHET_MT]; >+ memset(cmd,0,sizeof(cmd)); >+ cmd[0] = MOVE_MEDIUM; >+ cmd[1] = ch->device->lun << 5; >+ cmd[2] = (trans >> 8) & 0xff; >+ cmd[3] = trans & 0xff; >+ cmd[4] = (src >> 8) & 0xff; >+ cmd[5] = src & 0xff; >+ cmd[6] = (dest >> 8) & 0xff; >+ cmd[7] = dest & 0xff; >+ cmd[10] = rotate ? 1 : 0; >+ return ch_do_scsi(ch, cmd, NULL,0); >+} >+ >+static int >+ch_exchange(scsi_changer *ch, u_int trans, u_int src, >+ u_int dest1, u_int dest2, int rotate1, int rotate2) >+{ >+ u_char cmd[12]; >+ >+ dprintk("exchange: 0x%x => 0x%x => 0x%x\n", >+ src,dest1,dest2); >+ if (0 == trans) >+ trans = ch->firsts[CHET_MT]; >+ memset(cmd,0,sizeof(cmd)); >+ cmd[0] = EXCHANGE_MEDIUM; >+ cmd[1] = ch->device->lun << 5; >+ cmd[2] = (trans >> 8) & 0xff; >+ cmd[3] = trans & 0xff; >+ cmd[4] = (src >> 8) & 0xff; >+ cmd[5] = src & 0xff; >+ cmd[6] = (dest1 >> 8) & 0xff; >+ cmd[7] = dest1 & 0xff; >+ cmd[8] = (dest2 >> 8) & 0xff; >+ cmd[9] = dest2 & 0xff; >+ cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0); >+ >+ return ch_do_scsi(ch, cmd, NULL,0); >+} >+ >+static void >+ch_check_voltag(char *tag) >+{ >+ int i; >+ >+ for (i = 0; i < 32; i++) { >+ /* restrict to ascii */ >+ if (tag[i] >= 0x7f || tag[i] < 0x20) >+ tag[i] = ' '; >+ /* don't allow search wildcards */ >+ if (tag[i] == '?' || >+ tag[i] == '*') >+ tag[i] = ' '; >+ } >+} >+ >+static int >+ch_set_voltag(scsi_changer *ch, u_int elem, >+ int alternate, int clear, u_char *tag) >+{ >+ u_char cmd[12]; >+ u_char *buffer; >+ int result; >+ >+ buffer = kmalloc(512, GFP_KERNEL); >+ if (!buffer) >+ return -ENOMEM; >+ memset(buffer,0,512); >+ >+ dprintk("%s %s voltag: 0x%x => \"%s\"\n", >+ clear ? "clear" : "set", >+ alternate ? "alternate" : "primary", >+ elem, tag); >+ memset(cmd,0,sizeof(cmd)); >+ cmd[0] = SEND_VOLUME_TAG; >+ cmd[1] = (ch->device->lun << 5) | >+ ch_elem_to_typecode(ch,elem); >+ cmd[2] = (elem >> 8) & 0xff; >+ cmd[3] = elem & 0xff; >+ cmd[5] = clear >+ ? (alternate ? 0x0d : 0x0c) >+ : (alternate ? 0x0b : 0x0a); >+ >+ cmd[9] = 255; >+ >+ memcpy(buffer,tag,32); >+ ch_check_voltag(buffer); >+ >+ result = ch_do_scsi(ch, cmd, buffer, 256); >+ kfree(buffer); >+ return result; >+} >+ >+static int ch_gstatus(scsi_changer *ch, int type, unsigned char *dest) >+{ >+ int retval = 0; >+ u_char data[16]; >+ unsigned int i; >+ >+ down(&ch->lock); >+ for (i = 0; i < ch->counts[type]; i++) { >+ if (0 != ch_read_element_status >+ (ch, ch->firsts[type]+i,data)) { >+ retval = -EIO; >+ break; >+ } >+ put_user(data[2], dest+i); >+ if (data[2] & CESTATUS_EXCEPT) >+ vprintk("element 0x%x: asc=0x%x, ascq=0x%x\n", >+ ch->firsts[type]+i, >+ (int)data[4],(int)data[5]); >+ retval = ch_read_element_status >+ (ch, ch->firsts[type]+i,data); >+ if (0 != retval) >+ break; >+ } >+ up(&ch->lock); >+ return retval; >+} >+ >+/* ------------------------------------------------------------------------ */ >+ >+static int >+ch_release(struct inode *inode, struct file *file) >+{ >+ scsi_changer *ch = file->private_data; >+ >+ scsi_device_put(ch->device); >+ file->private_data = NULL; >+ return 0; >+} >+ >+static int >+ch_open(struct inode *inode, struct file *file) >+{ >+ scsi_changer *tmp, *ch; >+ int minor = iminor(inode); >+ >+ spin_lock(&ch_devlist_lock); >+ ch = NULL; >+ list_for_each_entry(tmp,&ch_devlist,list) { >+ if (tmp->minor == minor) >+ ch = tmp; >+ } >+ if (NULL == ch || scsi_device_get(ch->device)) { >+ spin_unlock(&ch_devlist_lock); >+ return -ENXIO; >+ } >+ spin_unlock(&ch_devlist_lock); >+ >+ file->private_data = ch; >+ return 0; >+} >+ >+static int >+ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit) >+{ >+ if (type >= CH_TYPES || unit >= ch->counts[type]) >+ return -1; >+ return 0; >+} >+ >+static int ch_ioctl(struct inode * inode, struct file * file, >+ unsigned int cmd, unsigned long arg) >+{ >+ scsi_changer *ch = file->private_data; >+ int retval; >+ >+ switch (cmd) { >+ case CHIOGPARAMS: >+ { >+ struct changer_params params; >+ >+ params.cp_curpicker = 0; >+ params.cp_npickers = ch->counts[CHET_MT]; >+ params.cp_nslots = ch->counts[CHET_ST]; >+ params.cp_nportals = ch->counts[CHET_IE]; >+ params.cp_ndrives = ch->counts[CHET_DT]; >+ >+ if (copy_to_user((void *) arg, ¶ms, sizeof(params))) >+ return -EFAULT; >+ return 0; >+ } >+ case CHIOGVPARAMS: >+ { >+ struct changer_vendor_params vparams; >+ >+ memset(&vparams,0,sizeof(vparams)); >+ if (ch->counts[CHET_V1]) { >+ vparams.cvp_n1 = ch->counts[CHET_V1]; >+ strncpy(vparams.cvp_label1,vendor_labels[0],16); >+ } >+ if (ch->counts[CHET_V2]) { >+ vparams.cvp_n2 = ch->counts[CHET_V2]; >+ strncpy(vparams.cvp_label2,vendor_labels[1],16); >+ } >+ if (ch->counts[CHET_V3]) { >+ vparams.cvp_n3 = ch->counts[CHET_V3]; >+ strncpy(vparams.cvp_label3,vendor_labels[2],16); >+ } >+ if (ch->counts[CHET_V4]) { >+ vparams.cvp_n4 = ch->counts[CHET_V4]; >+ strncpy(vparams.cvp_label4,vendor_labels[3],16); >+ } >+ if (copy_to_user((void *) arg, &vparams, sizeof(vparams))) >+ return -EFAULT; >+ return 0; >+ } >+ >+ case CHIOPOSITION: >+ { >+ struct changer_position pos; >+ >+ if (copy_from_user(&pos, (void*)arg, sizeof (pos))) >+ return -EFAULT; >+ >+ if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) { >+ dprintk("CHIOPOSITION: invalid parameter%s\n",""); >+ return -EBADSLT; >+ } >+ down(&ch->lock); >+ retval = ch_position(ch,0, >+ ch->firsts[pos.cp_type] + pos.cp_unit, >+ pos.cp_flags & CP_INVERT); >+ up(&ch->lock); >+ return retval; >+ } >+ >+ case CHIOMOVE: >+ { >+ struct changer_move mv; >+ >+ if (copy_from_user(&mv, (void*)arg, sizeof (mv))) >+ return -EFAULT; >+ >+ if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) || >+ 0 != ch_checkrange(ch, mv.cm_totype, mv.cm_tounit )) { >+ dprintk("CHIOMOVE: invalid parameter%s\n",""); >+ return -EBADSLT; >+ } >+ >+ down(&ch->lock); >+ retval = ch_move(ch,0, >+ ch->firsts[mv.cm_fromtype] + mv.cm_fromunit, >+ ch->firsts[mv.cm_totype] + mv.cm_tounit, >+ mv.cm_flags & CM_INVERT); >+ up(&ch->lock); >+ return retval; >+ } >+ >+ case CHIOEXCHANGE: >+ { >+ struct changer_exchange mv; >+ >+ if (copy_from_user(&mv, (void*)arg, sizeof (mv))) >+ return -EFAULT; >+ >+ if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) || >+ 0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) || >+ 0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) { >+ dprintk("CHIOEXCHANGE: invalid parameter%s\n",""); >+ return -EBADSLT; >+ } >+ >+ down(&ch->lock); >+ retval = ch_exchange >+ (ch,0, >+ ch->firsts[mv.ce_srctype] + mv.ce_srcunit, >+ ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit, >+ ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit, >+ mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2); >+ up(&ch->lock); >+ return retval; >+ } >+ >+ case CHIOGSTATUS: >+ { >+ struct changer_element_status ces; >+ >+ if (copy_from_user(&ces, (void*)arg, sizeof (ces))) >+ return -EFAULT; >+ if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES) >+ return -EINVAL; >+ >+ return ch_gstatus(ch, ces.ces_type, ces.ces_data); >+ } >+ >+ case CHIOGELEM: >+ { >+ struct changer_get_element cge; >+ u_char cmd[12]; >+ u_char *buffer; >+ unsigned int elem; >+ int result,i; >+ >+ if (copy_from_user(&cge, (void*)arg, sizeof (cge))) >+ return -EFAULT; >+ >+ if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit)) >+ return -EINVAL; >+ elem = ch->firsts[cge.cge_type] + cge.cge_unit; >+ >+ buffer = kmalloc(512, GFP_KERNEL); >+ if (!buffer) >+ return -ENOMEM; >+ down(&ch->lock); >+ >+ voltag_retry: >+ memset(cmd,0,sizeof(cmd)); >+ cmd[0] = READ_ELEMENT_STATUS; >+ cmd[1] = (ch->device->lun << 5) | >+ (ch->voltags ? 0x10 : 0) | >+ ch_elem_to_typecode(ch,elem); >+ cmd[2] = (elem >> 8) & 0xff; >+ cmd[3] = elem & 0xff; >+ cmd[5] = 1; >+ cmd[9] = 255; >+ >+ if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256))) { >+ cge.cge_status = buffer[18]; >+ cge.cge_flags = 0; >+ if (buffer[18] & CESTATUS_EXCEPT) { >+ /* FIXME: fill cge_errno */ >+ } >+ if (buffer[25] & 0x80) { >+ cge.cge_flags |= CGE_SRC; >+ if (buffer[25] & 0x40) >+ cge.cge_flags |= CGE_INVERT; >+ elem = (buffer[26]<<8) | buffer[27]; >+ for (i = 0; i < 4; i++) { >+ if (elem >= ch->firsts[i] && >+ elem < ch->firsts[i] + ch->counts[i]) { >+ cge.cge_srctype = i; >+ cge.cge_srcunit = elem-ch->firsts[i]; >+ } >+ } >+ } >+ if ((buffer[22] & 0x30) == 0x30) { >+ cge.cge_flags |= CGE_IDLUN; >+ cge.cge_id = buffer[23]; >+ cge.cge_lun = buffer[22] & 7; >+ } >+ if (buffer[9] & 0x80) { >+ cge.cge_flags |= CGE_PVOLTAG; >+ memcpy(cge.cge_pvoltag,buffer+28,36); >+ } >+ if (buffer[9] & 0x40) { >+ cge.cge_flags |= CGE_AVOLTAG; >+ memcpy(cge.cge_avoltag,buffer+64,36); >+ } >+ } else if (ch->voltags) { >+ ch->voltags = 0; >+ vprintk("device has no volume tag support%s\n",""); >+ goto voltag_retry; >+ } >+ kfree(buffer); >+ up(&ch->lock); >+ >+ if (copy_to_user((void*)arg, &cge, sizeof (cge))) >+ return -EFAULT; >+ return result; >+ } >+ >+ case CHIOINITELEM: >+ { >+ down(&ch->lock); >+ retval = ch_init_elem(ch); >+ up(&ch->lock); >+ return retval; >+ } >+ >+ case CHIOSVOLTAG: >+ { >+ struct changer_set_voltag csv; >+ int elem; >+ >+ if (copy_from_user(&csv, (void*)arg, sizeof(csv))) >+ return -EFAULT; >+ >+ if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) { >+ dprintk("CHIOSVOLTAG: invalid parameter%s\n",""); >+ return -EBADSLT; >+ } >+ elem = ch->firsts[csv.csv_type] + csv.csv_unit; >+ down(&ch->lock); >+ retval = ch_set_voltag(ch, elem, >+ csv.csv_flags & CSV_AVOLTAG, >+ csv.csv_flags & CSV_CLEARTAG, >+ csv.csv_voltag); >+ up(&ch->lock); >+ return retval; >+ } >+ >+ default: >+ return scsi_ioctl(ch->device, cmd, (void*)arg); >+ >+ } >+} >+ >+#ifdef CONFIG_COMPAT >+ >+struct changer_element_status32 { >+ int ces_type; >+ compat_uptr_t ces_data; >+}; >+#define CHIOGSTATUS32 _IOW('c', 8,struct changer_element_status32) >+ >+static long ch_ioctl_compat(struct file * file, >+ unsigned int cmd, unsigned long arg) >+{ >+ scsi_changer *ch = file->private_data; >+ >+ switch (cmd) { >+ case CHIOGPARAMS: >+ case CHIOGVPARAMS: >+ case CHIOPOSITION: >+ case CHIOMOVE: >+ case CHIOEXCHANGE: >+ case CHIOGELEM: >+ case CHIOINITELEM: >+ case CHIOSVOLTAG: >+ /* compatible */ >+ return ch_ioctl(NULL /* inode, unused */, >+ file, cmd, arg); >+ case CHIOGSTATUS32: >+ { >+ struct changer_element_status32 ces32; >+ unsigned char *data; >+ >+ if (copy_from_user(&ces32, (void*)arg, sizeof (ces32))) >+ return -EFAULT; >+ if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES) >+ return -EINVAL; >+ >+ data = compat_ptr(ces32.ces_data); >+ return ch_gstatus(ch, ces32.ces_type, data); >+ } >+ default: >+ // return scsi_ioctl_compat(ch->device, cmd, (void*)arg); >+ return -ENOIOCTLCMD; >+ >+ } >+} >+#endif >+ >+/* ------------------------------------------------------------------------ */ >+ >+static int ch_probe(struct device *dev) >+{ >+ struct scsi_device *sd = to_scsi_device(dev); >+ scsi_changer *ch; >+ >+ if (sd->type != TYPE_MEDIUM_CHANGER) >+ return -ENODEV; >+ >+ ch = kmalloc(sizeof(*ch), GFP_KERNEL); >+ if (NULL == ch) >+ return -ENOMEM; >+ >+ memset(ch,0,sizeof(*ch)); >+ ch->minor = ch_devcount; >+ sprintf(ch->name,"ch%d",ch->minor); >+ init_MUTEX(&ch->lock); >+ ch->device = sd; >+ ch_readconfig(ch); >+ if (init) >+ ch_init_elem(ch); >+ >+ devfs_mk_cdev(MKDEV(SCSI_CHANGER_MAJOR,ch->minor), >+ S_IFCHR | S_IRUGO | S_IWUGO, ch->name); >+ >+ printk(KERN_INFO "Attached scsi changer %s " >+ "at scsi%d, channel %d, id %d, lun %d\n", >+ ch->name, sd->host->host_no, sd->channel, sd->id, sd->lun); >+ >+ spin_lock(&ch_devlist_lock); >+ list_add_tail(&ch->list,&ch_devlist); >+ ch_devcount++; >+ spin_unlock(&ch_devlist_lock); >+ return 0; >+} >+ >+static int ch_remove(struct device *dev) >+{ >+ struct scsi_device *sd = to_scsi_device(dev); >+ scsi_changer *tmp, *ch; >+ >+ spin_lock(&ch_devlist_lock); >+ ch = NULL; >+ list_for_each_entry(tmp,&ch_devlist,list) { >+ if (tmp->device == sd) >+ ch = tmp; >+ } >+ BUG_ON(NULL == ch); >+ list_del(&ch->list); >+ spin_unlock(&ch_devlist_lock); >+ >+ devfs_remove(ch->name); >+ kfree(ch->dt); >+ kfree(ch); >+ ch_devcount--; >+ return 0; >+} >+ >+static int __init init_ch_module(void) >+{ >+ int rc; >+ >+ printk(KERN_INFO "SCSI Media Changer driver v" VERSION " \n"); >+ rc = register_chrdev(SCSI_CHANGER_MAJOR,"ch",&changer_fops); >+ if (rc < 0) { >+ printk("Unable to get major %d for SCSI-Changer\n", >+ SCSI_CHANGER_MAJOR); >+ return rc; >+ } >+ rc = scsi_register_driver(&ch_template.gendrv); >+ if (rc < 0) >+ goto fail1; >+ return 0; >+ >+ fail1: >+ unregister_chrdev(SCSI_CHANGER_MAJOR, "ch"); >+ return rc; >+} >+ >+static void __exit exit_ch_module(void) >+{ >+ scsi_unregister_driver(&ch_template.gendrv); >+ unregister_chrdev(SCSI_CHANGER_MAJOR, "ch"); >+} >+ >+module_init(init_ch_module); >+module_exit(exit_ch_module); >+ >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/include/asm-alpha/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-alpha/ioctls.h 2005-03-07 10:14:47.000000000 +0100 >+++ linux-2.6.11/include/asm-alpha/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -91,6 +91,7 @@ > #define TIOCGSID 0x5429 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define TIOCSERCONFIG 0x5453 > #define TIOCSERGWILD 0x5454 >Index: linux-2.6.11/include/asm-arm/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-arm/ioctls.h 2005-03-07 10:13:49.000000000 +0100 >+++ linux-2.6.11/include/asm-arm/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -48,6 +48,7 @@ > #define TIOCGSID 0x5429 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ > #define FIOCLEX 0x5451 >Index: linux-2.6.11/include/asm-i386/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-i386/ioctls.h 2005-03-07 10:12:46.000000000 +0100 >+++ linux-2.6.11/include/asm-i386/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -49,6 +49,7 @@ > #define TIOCGSID 0x5429 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define FIONCLEX 0x5450 > #define FIOCLEX 0x5451 >Index: linux-2.6.11/include/asm-ia64/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-ia64/ioctls.h 2005-03-07 10:12:52.000000000 +0100 >+++ linux-2.6.11/include/asm-ia64/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -55,6 +55,7 @@ > #define TIOCGSID 0x5429 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ > #define FIOCLEX 0x5451 >Index: linux-2.6.11/include/asm-m68k/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-m68k/ioctls.h 2005-03-07 10:14:32.000000000 +0100 >+++ linux-2.6.11/include/asm-m68k/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -48,6 +48,7 @@ > #define TIOCGSID 0x5429 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ > #define FIOCLEX 0x5451 >Index: linux-2.6.11/include/asm-mips/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-mips/ioctls.h 2005-03-07 10:15:10.000000000 +0100 >+++ linux-2.6.11/include/asm-mips/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -79,6 +79,7 @@ > #define TIOCGSID 0x7416 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > /* I hope the range from 0x5480 on is free ... */ > #define TIOCSCTTY 0x5480 /* become controlling tty */ >Index: linux-2.6.11/include/asm-ppc/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-ppc/ioctls.h 2005-03-07 10:14:59.000000000 +0100 >+++ linux-2.6.11/include/asm-ppc/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -88,6 +88,7 @@ > #define TIOCGSID 0x5429 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define TIOCSERCONFIG 0x5453 > #define TIOCSERGWILD 0x5454 >Index: linux-2.6.11/include/asm-ppc64/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-ppc64/ioctls.h 2005-03-07 10:12:24.000000000 +0100 >+++ linux-2.6.11/include/asm-ppc64/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -95,6 +95,7 @@ > #define TIOCGSID 0x5429 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define TIOCSERCONFIG 0x5453 > #define TIOCSERGWILD 0x5454 >Index: linux-2.6.11/include/asm-s390/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-s390/ioctls.h 2005-03-07 10:14:12.000000000 +0100 >+++ linux-2.6.11/include/asm-s390/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -56,6 +56,7 @@ > #define TIOCGSID 0x5429 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ > #define FIOCLEX 0x5451 >Index: linux-2.6.11/include/asm-sh/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-sh/ioctls.h 2005-03-07 10:14:29.000000000 +0100 >+++ linux-2.6.11/include/asm-sh/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -80,6 +80,7 @@ > #define TIOCGSID _IOR('T', 41, pid_t) /* 0x5429 */ /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */ > #define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */ >Index: linux-2.6.11/include/asm-sparc/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-sparc/ioctls.h 2005-03-07 10:13:48.000000000 +0100 >+++ linux-2.6.11/include/asm-sparc/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -15,6 +15,7 @@ > #define TCSETS _IOW('T', 9, struct termios) > #define TCSETSW _IOW('T', 10, struct termios) > #define TCSETSF _IOW('T', 11, struct termios) >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > /* Note that all the ioctls that are not available in Linux have a > * double underscore on the front to: a) avoid some programs to >Index: linux-2.6.11/include/asm-sparc64/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-sparc64/ioctls.h 2005-03-07 10:14:05.000000000 +0100 >+++ linux-2.6.11/include/asm-sparc64/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -16,6 +16,7 @@ > #define TCSETS _IOW('T', 9, struct termios) > #define TCSETSW _IOW('T', 10, struct termios) > #define TCSETSF _IOW('T', 11, struct termios) >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > /* Note that all the ioctls that are not available in Linux have a > * double underscore on the front to: a) avoid some programs to >Index: linux-2.6.11/include/asm-x86_64/ioctls.h >=================================================================== >--- linux-2.6.11.orig/include/asm-x86_64/ioctls.h 2005-03-07 10:15:44.000000000 +0100 >+++ linux-2.6.11/include/asm-x86_64/ioctls.h 2005-03-08 10:33:27.000000000 +0100 >@@ -48,6 +48,7 @@ > #define TIOCGSID 0x5429 /* Return the session ID of FD */ > #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ > #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ >+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ > > #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ > #define FIOCLEX 0x5451 >Index: linux-2.6.11/include/linux/chio.h >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/include/linux/chio.h 2005-03-07 18:13:01.000000000 +0100 >@@ -0,0 +1,168 @@ >+/* >+ * ioctl interface for the scsi media changer driver >+ */ >+ >+/* changer element types */ >+#define CHET_MT 0 /* media transport element (robot) */ >+#define CHET_ST 1 /* storage element (media slots) */ >+#define CHET_IE 2 /* import/export element */ >+#define CHET_DT 3 /* data transfer element (tape/cdrom/whatever) */ >+#define CHET_V1 4 /* vendor specific #1 */ >+#define CHET_V2 5 /* vendor specific #2 */ >+#define CHET_V3 6 /* vendor specific #3 */ >+#define CHET_V4 7 /* vendor specific #4 */ >+ >+ >+/* >+ * CHIOGPARAMS >+ * query changer properties >+ * >+ * CHIOVGPARAMS >+ * query vendor-specific element types >+ * >+ * accessing elements works by specifing type and unit of the element. >+ * for eample, storage elements are addressed with type = CHET_ST and >+ * unit = 0 .. cp_nslots-1 >+ * >+ */ >+struct changer_params { >+ int cp_curpicker; /* current transport element */ >+ int cp_npickers; /* number of transport elements (CHET_MT) */ >+ int cp_nslots; /* number of storage elements (CHET_ST) */ >+ int cp_nportals; /* number of import/export elements (CHET_IE) */ >+ int cp_ndrives; /* number of data transfer elements (CHET_DT) */ >+}; >+struct changer_vendor_params { >+ int cvp_n1; /* number of vendor specific elems (CHET_V1) */ >+ char cvp_label1[16]; >+ int cvp_n2; /* number of vendor specific elems (CHET_V2) */ >+ char cvp_label2[16]; >+ int cvp_n3; /* number of vendor specific elems (CHET_V3) */ >+ char cvp_label3[16]; >+ int cvp_n4; /* number of vendor specific elems (CHET_V4) */ >+ char cvp_label4[16]; >+ int reserved[8]; >+}; >+ >+ >+/* >+ * CHIOMOVE >+ * move a medium from one element to another >+ */ >+struct changer_move { >+ int cm_fromtype; /* type/unit of source element */ >+ int cm_fromunit; >+ int cm_totype; /* type/unit of destination element */ >+ int cm_tounit; >+ int cm_flags; >+}; >+#define CM_INVERT 1 /* flag: rotate media (for double-sided like MOD) */ >+ >+ >+/* >+ * CHIOEXCHANGE >+ * move one medium from element #1 to element #2, >+ * and another one from element #2 to element #3. >+ * element #1 and #3 are allowed to be identical. >+ */ >+struct changer_exchange { >+ int ce_srctype; /* type/unit of element #1 */ >+ int ce_srcunit; >+ int ce_fdsttype; /* type/unit of element #2 */ >+ int ce_fdstunit; >+ int ce_sdsttype; /* type/unit of element #3 */ >+ int ce_sdstunit; >+ int ce_flags; >+}; >+#define CE_INVERT1 1 >+#define CE_INVERT2 2 >+ >+ >+/* >+ * CHIOPOSITION >+ * move the transport element (robot arm) to a specific element. >+ */ >+struct changer_position { >+ int cp_type; >+ int cp_unit; >+ int cp_flags; >+}; >+#define CP_INVERT 1 >+ >+ >+/* >+ * CHIOGSTATUS >+ * get element status for all elements of a specific type >+ */ >+struct changer_element_status { >+ int ces_type; >+ unsigned char *ces_data; >+}; >+#define CESTATUS_FULL 0x01 /* full */ >+#define CESTATUS_IMPEXP 0x02 /* media was imported (inserted by sysop) */ >+#define CESTATUS_EXCEPT 0x04 /* error condition */ >+#define CESTATUS_ACCESS 0x08 /* access allowed */ >+#define CESTATUS_EXENAB 0x10 /* element can export media */ >+#define CESTATUS_INENAB 0x20 /* element can import media */ >+ >+ >+/* >+ * CHIOGELEM >+ * get more detailed status informtion for a single element >+ */ >+struct changer_get_element { >+ int cge_type; /* type/unit */ >+ int cge_unit; >+ int cge_status; /* status */ >+ int cge_errno; /* errno */ >+ int cge_srctype; /* source element of the last move/exchange */ >+ int cge_srcunit; >+ int cge_id; /* scsi id (for data transfer elements) */ >+ int cge_lun; /* scsi lun (for data transfer elements) */ >+ char cge_pvoltag[36]; /* primary volume tag */ >+ char cge_avoltag[36]; /* alternate volume tag */ >+ int cge_flags; >+}; >+/* flags */ >+#define CGE_ERRNO 0x01 /* errno available */ >+#define CGE_INVERT 0x02 /* media inverted */ >+#define CGE_SRC 0x04 /* media src available */ >+#define CGE_IDLUN 0x08 /* ID+LUN available */ >+#define CGE_PVOLTAG 0x10 /* primary volume tag available */ >+#define CGE_AVOLTAG 0x20 /* alternate volume tag available */ >+ >+ >+/* >+ * CHIOSVOLTAG >+ * set volume tag >+ */ >+struct changer_set_voltag { >+ int csv_type; /* type/unit */ >+ int csv_unit; >+ char csv_voltag[36]; /* volume tag */ >+ int csv_flags; >+}; >+#define CSV_PVOLTAG 0x01 /* primary volume tag */ >+#define CSV_AVOLTAG 0x02 /* alternate volume tag */ >+#define CSV_CLEARTAG 0x04 /* clear volume tag */ >+ >+/* ioctls */ >+#define CHIOMOVE _IOW('c', 1,struct changer_move) >+#define CHIOEXCHANGE _IOW('c', 2,struct changer_exchange) >+#define CHIOPOSITION _IOW('c', 3,struct changer_position) >+#define CHIOGPICKER _IOR('c', 4,int) /* not impl. */ >+#define CHIOSPICKER _IOW('c', 5,int) /* not impl. */ >+#define CHIOGPARAMS _IOR('c', 6,struct changer_params) >+#define CHIOGSTATUS _IOW('c', 8,struct changer_element_status) >+#define CHIOGELEM _IOW('c',16,struct changer_get_element) >+#define CHIOINITELEM _IO('c',17) >+#define CHIOSVOLTAG _IOW('c',18,struct changer_set_voltag) >+#define CHIOGVPARAMS _IOR('c',19,struct changer_vendor_params) >+ >+/* ---------------------------------------------------------------------- */ >+ >+/* >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/include/linux/compat_ioctl.h >=================================================================== >--- linux-2.6.11.orig/include/linux/compat_ioctl.h 2005-03-07 10:15:29.000000000 +0100 >+++ linux-2.6.11/include/linux/compat_ioctl.h 2005-03-08 10:33:27.000000000 +0100 >@@ -27,6 +27,7 @@ COMPATIBLE_IOCTL(TIOCSBRK) > COMPATIBLE_IOCTL(TIOCCBRK) > ULONG_IOCTL(TIOCMIWAIT) > COMPATIBLE_IOCTL(TIOCGICOUNT) >+COMPATIBLE_IOCTL(TIOCGDEV) > /* Little t */ > COMPATIBLE_IOCTL(TIOCGETD) > COMPATIBLE_IOCTL(TIOCSETD) >Index: linux-2.6.11/include/linux/major.h >=================================================================== >--- linux-2.6.11.orig/include/linux/major.h 2005-03-07 10:13:10.000000000 +0100 >+++ linux-2.6.11/include/linux/major.h 2005-03-07 18:13:01.000000000 +0100 >@@ -101,6 +101,7 @@ > #define I2O_MAJOR 80 /* 80->87 */ > > #define SHMIQ_MAJOR 85 /* Linux/mips, SGI /dev/shmiq */ >+#define SCSI_CHANGER_MAJOR 86 > > #define IDE6_MAJOR 88 > #define IDE7_MAJOR 89 >Index: linux-2.6.11/include/linux/videodev2.h >=================================================================== >--- linux-2.6.11.orig/include/linux/videodev2.h 2005-03-07 10:14:30.000000000 +0100 >+++ linux-2.6.11/include/linux/videodev2.h 2005-03-08 10:33:27.000000000 +0100 >@@ -268,64 +268,92 @@ struct v4l2_timecode > /* The above is based on SMPTE timecodes */ > > >+#if 1 > /* >- * C O M P R E S S I O N P A R A M E T E R S >+ * M P E G C O M P R E S S I O N P A R A M E T E R S >+ * >+ * ### WARNING: this is still work-in-progress right now, most likely >+ * ### there will be some incompatible changes. >+ * > */ >-#if 0 >-/* ### generic compression settings don't work, there is too much >- * ### codec-specific stuff. Maybe reuse that for MPEG codec settings >- * ### later ... */ >-struct v4l2_compression >-{ >- __u32 quality; >- __u32 keyframerate; >- __u32 pframerate; >- __u32 reserved[5]; > >-/* what we'll need for MPEG, extracted from some postings on >- the v4l list (Gert Vervoort, PlasmaJohn). > >-system stream: >- - type: elementary stream(ES), packatised elementary stream(s) (PES) >- program stream(PS), transport stream(TS) >- - system bitrate >- - PS packet size (DVD: 2048 bytes, VCD: 2324 bytes) >- - TS video PID >- - TS audio PID >- - TS PCR PID >- - TS system information tables (PAT, PMT, CAT, NIT and SIT) >- - (MPEG-1 systems stream vs. MPEG-2 program stream (TS not supported >- by MPEG-1 systems) >+enum v4l2_bitrate_mode { >+ V4L2_BITRATE_NONE = 0, /* not specified */ >+ V4L2_BITRATE_CBR, /* constant bitrate */ >+ V4L2_BITRATE_VBR, /* variable bitrate */ >+}; >+struct v4l2_bitrate { >+ /* rates are specified in kbit/sec */ >+ enum v4l2_bitrate_mode mode; >+ __u32 min; >+ __u32 target; /* use this one for CBR */ >+ __u32 max; >+}; > >-audio: >- - type: MPEG (+Layer I,II,III), AC-3, LPCM >- - bitrate >- - sampling frequency (DVD: 48 Khz, VCD: 44.1 KHz, 32 kHz) >- - Trick Modes? (ff, rew) >- - Copyright >- - Inverse Telecine >+enum v4l2_mpeg_streamtype { >+ V4L2_MPEG_SS_1, /* MPEG-1 system stream */ >+ V4L2_MPEG_PS_2, /* MPEG-2 program stream */ >+ V4L2_MPEG_TS_2, /* MPEG-2 transport stream */ >+ V4L2_MPEG_PS_DVD, /* MPEG-2 program stream with DVD header fixups */ >+}; >+enum v4l2_mpeg_audiotype { >+ V4L2_MPEG_AU_2_I, /* MPEG-2 layer 1 */ >+ V4L2_MPEG_AU_2_II, /* MPEG-2 layer 2 */ >+ V4L2_MPEG_AU_2_III, /* MPEG-2 layer 3 */ >+ V4L2_MPEG_AC3, /* AC3 */ >+ V4L2_MPEG_LPCM, /* LPCM */ >+}; >+enum v4l2_mpeg_videotype { >+ V4L2_MPEG_VI_1, /* MPEG-1 */ >+ V4L2_MPEG_VI_2, /* MPEG-2 */ >+}; >+enum v4l2_mpeg_aspectratio { >+ V4L2_MPEG_ASPECT_SQUARE = 1, /* square pixel */ >+ V4L2_MPEG_ASPECT_4_3 = 2, /* 4 : 3 */ >+ V4L2_MPEG_ASPECT_16_9 = 3, /* 16 : 9 */ >+ V4L2_MPEG_ASPECT_1_221 = 4, /* 1 : 2,21 */ >+}; > >-video: >- - picturesize (SIF, 1/2 D1, 2/3 D1, D1) and PAL/NTSC norm can be set >- through excisting V4L2 controls >- - noise reduction, parameters encoder specific? >- - MPEG video version: MPEG-1, MPEG-2 >- - GOP (Group Of Pictures) definition: >- - N: number of frames per GOP >- - M: distance between reference (I,P) frames >- - open/closed GOP >- - quantiser matrix: inter Q matrix (64 bytes) and intra Q matrix (64 bytes) >- - quantiser scale: linear or logarithmic >- - scanning: alternate or zigzag >- - bitrate mode: CBR (constant bitrate) or VBR (variable bitrate). >- - target video bitrate for CBR >- - target video bitrate for VBR >- - maximum video bitrate for VBR - min. quantiser value for VBR >- - max. quantiser value for VBR >- - adaptive quantisation value >- - return the number of bytes per GOP or bitrate for bitrate monitoring >+struct v4l2_mpeg_compression { >+ /* general */ >+ enum v4l2_mpeg_streamtype st_type; >+ struct v4l2_bitrate st_bitrate; > >-*/ >+ /* transport streams */ >+ __u16 ts_pid_pmt; >+ __u16 ts_pid_audio; >+ __u16 ts_pid_video; >+ __u16 ts_pid_pcr; >+ >+ /* program stream */ >+ __u16 ps_size; >+ __u16 reserved_1; /* align */ >+ >+ /* audio */ >+ enum v4l2_mpeg_audiotype au_type; >+ struct v4l2_bitrate au_bitrate; >+ __u32 au_sample_rate; >+ __u8 au_pesid; >+ __u8 reserved_2[3]; /* align */ >+ >+ /* video */ >+ enum v4l2_mpeg_videotype vi_type; >+ enum v4l2_mpeg_aspectratio vi_aspect_ratio; >+ struct v4l2_bitrate vi_bitrate; >+ __u32 vi_frame_rate; >+ __u16 vi_frames_per_gop; >+ __u16 vi_bframes_count; >+ __u8 vi_pesid; >+ __u8 reserved_3[3]; /* align */ >+ >+ /* misc flags */ >+ __u32 closed_gops:1; >+ __u32 pulldown:1; >+ __u32 reserved_4:30; /* align */ >+ >+ /* I don't expect the above being perfect yet ;) */ >+ __u32 reserved_5[8]; > }; > #endif > >@@ -841,9 +869,9 @@ struct v4l2_streamparm > #define VIDIOC_ENUM_FMT _IOWR ('V', 2, struct v4l2_fmtdesc) > #define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format) > #define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format) >-#if 0 >-#define VIDIOC_G_COMP _IOR ('V', 6, struct v4l2_compression) >-#define VIDIOC_S_COMP _IOW ('V', 7, struct v4l2_compression) >+#if 1 /* experimental */ >+#define VIDIOC_G_MPEGCOMP _IOR ('V', 6, struct v4l2_mpeg_compression) >+#define VIDIOC_S_MPEGCOMP _IOW ('V', 7, struct v4l2_mpeg_compression) > #endif > #define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers) > #define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer) >Index: linux-2.6.11/include/media/ir-common.h >=================================================================== >--- linux-2.6.11.orig/include/media/ir-common.h 2005-03-07 10:15:15.000000000 +0100 >+++ linux-2.6.11/include/media/ir-common.h 2005-03-07 18:13:02.000000000 +0100 >@@ -1,5 +1,5 @@ > /* >- * $Id: ir-common.h,v 1.6 2004/09/15 16:15:24 kraxel Exp $ >+ * $Id: ir-common.h,v 1.8 2005/02/22 12:28:40 kraxel Exp $ > * > * some common structs and functions to handle infrared remotes via > * input layer ... >@@ -47,7 +47,9 @@ struct ir_input_state { > }; > > extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; >+extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; > extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; >+extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; > > void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, > int ir_type, IR_KEYTAB_TYPE *ir_codes); >@@ -55,6 +57,8 @@ void ir_input_nokey(struct input_dev *de > void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, > u32 ir_key, u32 ir_raw); > u32 ir_extract_bits(u32 data, u32 mask); >+int ir_dump_samples(u32 *samples, int count); >+int ir_decode_biphase(u32 *samples, int count, int low, int high); > > /* > * Local variables: >Index: linux-2.6.11/include/media/saa6752hs.h >=================================================================== >--- linux-2.6.11.orig/include/media/saa6752hs.h 2005-03-07 10:16:30.000000000 +0100 >+++ linux-2.6.11/include/media/saa6752hs.h 2005-03-08 10:33:27.000000000 +0100 >@@ -18,14 +18,14 @@ > Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > */ > >-#ifndef _SAA6752HS_H >+#if 0 /* ndef _SAA6752HS_H */ > #define _SAA6752HS_H > >-enum mpeg_bitrate_mode { >- MPEG_BITRATE_MODE_VBR = 0, /* Variable bitrate */ >- MPEG_BITRATE_MODE_CBR = 1, /* Constant bitrate */ >+enum mpeg_video_bitrate_mode { >+ MPEG_VIDEO_BITRATE_MODE_VBR = 0, /* Variable bitrate */ >+ MPEG_VIDEO_BITRATE_MODE_CBR = 1, /* Constant bitrate */ > >- MPEG_BITRATE_MODE_MAX >+ MPEG_VIDEO_BITRATE_MODE_MAX > }; > > enum mpeg_audio_bitrate { >@@ -35,16 +35,33 @@ enum mpeg_audio_bitrate { > MPEG_AUDIO_BITRATE_MAX > }; > >+enum mpeg_video_format { >+ MPEG_VIDEO_FORMAT_D1 = 0, >+ MPEG_VIDEO_FORMAT_2_3_D1 = 1, >+ MPEG_VIDEO_FORMAT_1_2_D1 = 2, >+ MPEG_VIDEO_FORMAT_SIF = 3, >+ >+ MPEG_VIDEO_FORMAT_MAX >+}; >+ > #define MPEG_VIDEO_TARGET_BITRATE_MAX 27000 > #define MPEG_VIDEO_MAX_BITRATE_MAX 27000 > #define MPEG_TOTAL_BITRATE_MAX 27000 >+#define MPEG_PID_MAX ((1 << 14) - 1) > > struct mpeg_params { >- enum mpeg_bitrate_mode bitrate_mode; >+ enum mpeg_video_bitrate_mode video_bitrate_mode; > unsigned int video_target_bitrate; > unsigned int video_max_bitrate; // only used for VBR > enum mpeg_audio_bitrate audio_bitrate; > unsigned int total_bitrate; >+ >+ unsigned int pmt_pid; >+ unsigned int video_pid; >+ unsigned int audio_pid; >+ unsigned int pcr_pid; >+ >+ enum mpeg_video_format video_format; > }; > > #define MPEG_SETPARAMS _IOW('6',100,struct mpeg_params) >Index: linux-2.6.11/include/media/tuner.h >=================================================================== >--- linux-2.6.11.orig/include/media/tuner.h 2005-03-07 10:14:42.000000000 +0100 >+++ linux-2.6.11/include/media/tuner.h 2005-03-08 10:32:50.000000000 +0100 >@@ -29,55 +29,74 @@ > #define TUNER_PHILIPS_PAL_I 1 > #define TUNER_PHILIPS_NTSC 2 > #define TUNER_PHILIPS_SECAM 3 /* you must actively select B/G, L, L` */ >+ > #define TUNER_ABSENT 4 > #define TUNER_PHILIPS_PAL 5 > #define TUNER_TEMIC_NTSC 6 /* 4032 FY5 (3X 7004, 9498, 9789) */ > #define TUNER_TEMIC_PAL_I 7 /* 4062 FY5 (3X 8501, 9957) */ >+ > #define TUNER_TEMIC_4036FY5_NTSC 8 /* 4036 FY5 (3X 1223, 1981, 7686) */ > #define TUNER_ALPS_TSBH1_NTSC 9 > #define TUNER_ALPS_TSBE1_PAL 10 > #define TUNER_ALPS_TSBB5_PAL_I 11 >+ > #define TUNER_ALPS_TSBE5_PAL 12 > #define TUNER_ALPS_TSBC5_PAL 13 > #define TUNER_TEMIC_4006FH5_PAL 14 /* 4006 FH5 (3X 9500, 9501, 7291) */ > #define TUNER_ALPS_TSHC6_NTSC 15 >+ > #define TUNER_TEMIC_PAL_DK 16 /* 4016 FY5 (3X 1392, 1393) */ > #define TUNER_PHILIPS_NTSC_M 17 > #define TUNER_TEMIC_4066FY5_PAL_I 18 /* 4066 FY5 (3X 7032, 7035) */ > #define TUNER_TEMIC_4006FN5_MULTI_PAL 19 /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/ >+ > #define TUNER_TEMIC_4009FR5_PAL 20 /* incl. FM radio (3X 7607, 7488, 7711)*/ > #define TUNER_TEMIC_4039FR5_NTSC 21 /* incl. FM radio (3X 7246, 7578, 7732)*/ > #define TUNER_TEMIC_4046FM5 22 /* you must actively select B/G, D/K, I, L, L` ! (3X 7804, 7806, 8103, 8104)*/ > #define TUNER_PHILIPS_PAL_DK 23 >+ > #define TUNER_PHILIPS_FQ1216ME 24 /* you must actively select B/G/D/K, I, L, L` */ > #define TUNER_LG_PAL_I_FM 25 > #define TUNER_LG_PAL_I 26 > #define TUNER_LG_NTSC_FM 27 >+ > #define TUNER_LG_PAL_FM 28 > #define TUNER_LG_PAL 29 > #define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30 /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/ > #define TUNER_SHARP_2U5JF5540_NTSC 31 >+ > #define TUNER_Samsung_PAL_TCPM9091PD27 32 > #define TUNER_MT2032 33 > #define TUNER_TEMIC_4106FH5 34 /* 4106 FH5 (3X 7808, 7865)*/ > #define TUNER_TEMIC_4012FY5 35 /* 4012 FY5 (3X 0971, 1099)*/ >+ > #define TUNER_TEMIC_4136FY5 36 /* 4136 FY5 (3X 7708, 7746)*/ > #define TUNER_LG_PAL_NEW_TAPC 37 > #define TUNER_PHILIPS_FM1216ME_MK3 38 > #define TUNER_LG_NTSC_NEW_TAPC 39 >+ > #define TUNER_HITACHI_NTSC 40 > #define TUNER_PHILIPS_PAL_MK 41 > #define TUNER_PHILIPS_ATSC 42 > #define TUNER_PHILIPS_FM1236_MK3 43 >+ > #define TUNER_PHILIPS_4IN1 44 /* ATI TV Wonder Pro - Conexant */ > /* Microtune mergeged with Temic 12/31/1999 partially financed by Alps - these may be similar to Temic */ > #define TUNER_MICROTUNE_4049FM5 45 > #define TUNER_LG_NTSC_TAPE 47 >+ > #define TUNER_TNF_8831BGFF 48 > #define TUNER_MICROTUNE_4042FI5 49 /* FusionHDTV 3 Gold - 4042 FI5 (3X 8147) */ > #define TUNER_TCL_2002N 50 > #define TUNER_PHILIPS_FM1256_IH3 51 >+ > #define TUNER_THOMSON_DTT7610 52 >+#define TUNER_PHILIPS_FQ1286 53 >+#define TUNER_PHILIPS_TDA8290 54 >+#define TUNER_LG_PAL_TAPE 55 /* Hauppauge PVR-150 PAL */ >+ >+#define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */ >+#define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */ > > #define NOTUNER 0 > #define PAL 1 /* PAL_BG */ >@@ -102,10 +121,6 @@ > > #define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */ > #define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */ >-#if 0 /* obsolete */ >-# define TUNER_SET_RADIOFREQ _IOW('t',3,int) /* set radio freq */ >-# define TUNER_SET_MODE _IOW('t',4,int) /* set tuner mode */ >-#endif > > #define TDA9887_SET_CONFIG _IOW('t',5,int) > /* tv card specific */ >@@ -123,4 +138,62 @@ > # define TDA9887_DEEMPHASIS_75 (3<<16) > # define TDA9887_AUTOMUTE (1<<18) > >+#ifdef __KERNEL__ >+ >+#define I2C_ADDR_TDA8290 0x4b >+#define I2C_ADDR_TDA8275 0x61 >+ >+struct tuner { >+ /* device */ >+ struct i2c_client i2c; >+ >+ /* state + config */ >+ unsigned int initialized; >+ unsigned int type; /* chip type */ >+ unsigned int freq; /* keep track of the current settings */ >+ v4l2_std_id std; >+ int using_v4l2; >+ >+ enum v4l2_tuner_type mode; >+ unsigned int input; >+ >+ /* used by MT2032 */ >+ unsigned int xogc; >+ unsigned int radio_if2; >+ >+ /* used by tda8290 */ >+ unsigned char i2c_easy_mode[2]; >+ unsigned char i2c_set_freq[8]; >+ >+ /* function ptrs */ >+ void (*tv_freq)(struct i2c_client *c, unsigned int freq); >+ void (*radio_freq)(struct i2c_client *c, unsigned int freq); >+ int (*has_signal)(struct i2c_client *c); >+ int (*is_stereo)(struct i2c_client *c); >+}; >+ >+extern unsigned int tuner_debug; >+extern unsigned const int tuner_count; >+ >+extern int microtune_init(struct i2c_client *c); >+extern int tda8290_init(struct i2c_client *c); >+extern int default_tuner_init(struct i2c_client *c); >+ >+#define tuner_warn(fmt, arg...) \ >+ dev_printk(KERN_WARNING , &t->i2c.dev , fmt , ## arg) >+#define tuner_info(fmt, arg...) \ >+ dev_printk(KERN_INFO , &t->i2c.dev , fmt , ## arg) >+#define tuner_dbg(fmt, arg...) \ >+ if (tuner_debug) dev_printk(KERN_DEBUG , &t->i2c.dev , fmt , ## arg) >+ >+#endif /* __KERNEL__ */ >+ > #endif >+ >+/* >+ * Overrides for Emacs so that we follow Linus's tabbing style. >+ * --------------------------------------------------------------------------- >+ * Local variables: >+ * c-basic-offset: 8 >+ * End: >+ */ >Index: linux-2.6.11/include/scsi/scsi.h >=================================================================== >--- linux-2.6.11.orig/include/scsi/scsi.h 2005-03-07 10:15:45.000000000 +0100 >+++ linux-2.6.11/include/scsi/scsi.h 2005-03-07 18:13:01.000000000 +0100 >@@ -41,6 +41,7 @@ extern const char *const scsi_device_typ > #define FORMAT_UNIT 0x04 > #define READ_BLOCK_LIMITS 0x05 > #define REASSIGN_BLOCKS 0x07 >+#define INITIALIZE_ELEMENT_STATUS 0x07 > #define READ_6 0x08 > #define WRITE_6 0x0a > #define SEEK_6 0x0b >@@ -65,6 +66,7 @@ extern const char *const scsi_device_typ > #define READ_10 0x28 > #define WRITE_10 0x2a > #define SEEK_10 0x2b >+#define POSITION_TO_ELEMENT 0x2b > #define WRITE_VERIFY 0x2e > #define VERIFY 0x2f > #define SEARCH_HIGH 0x30 >@@ -97,6 +99,7 @@ extern const char *const scsi_device_typ > #define PERSISTENT_RESERVE_OUT 0x5f > #define REPORT_LUNS 0xa0 > #define MOVE_MEDIUM 0xa5 >+#define EXCHANGE_MEDIUM 0xa6 > #define READ_12 0xa8 > #define WRITE_12 0xaa > #define WRITE_VERIFY_12 0xae >Index: linux-2.6.11/localversion-kraxel >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ linux-2.6.11/localversion-kraxel 2005-03-07 18:13:01.000000000 +0100 >@@ -0,0 +1 @@ >+-kraxel1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 94814
: 60450