diff options
657 files changed, 18911 insertions, 13548 deletions
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl index 90dc2de8e0af..158ffe9bfade 100644 --- a/Documentation/DocBook/kernel-locking.tmpl +++ b/Documentation/DocBook/kernel-locking.tmpl @@ -222,7 +222,7 @@ <title>Two Main Types of Kernel Locks: Spinlocks and Semaphores</title> <para> - There are two main types of kernel locks. The fundamental type + There are three main types of kernel locks. The fundamental type is the spinlock (<filename class="headerfile">include/asm/spinlock.h</filename>), which is a very simple single-holder lock: if you can't get the @@ -230,16 +230,22 @@ very small and fast, and can be used anywhere. </para> <para> - The second type is a semaphore + The second type is a mutex + (<filename class="headerfile">include/linux/mutex.h</filename>): it + is like a spinlock, but you may block holding a mutex. + If you can't lock a mutex, your task will suspend itself, and be woken + up when the mutex is released. This means the CPU can do something + else while you are waiting. There are many cases when you simply + can't sleep (see <xref linkend="sleeping-things"/>), and so have to + use a spinlock instead. + </para> + <para> + The third type is a semaphore (<filename class="headerfile">include/asm/semaphore.h</filename>): it can have more than one holder at any time (the number decided at initialization time), although it is most commonly used as a - single-holder lock (a mutex). If you can't get a semaphore, - your task will put itself on the queue, and be woken up when the - semaphore is released. This means the CPU will do something - else while you are waiting, but there are many cases when you - simply can't sleep (see <xref linkend="sleeping-things"/>), and so - have to use a spinlock instead. + single-holder lock (a mutex). If you can't get a semaphore, your + task will be suspended and later on woken up - just like for mutexes. </para> <para> Neither type of lock is recursive: see diff --git a/Documentation/dvb/avermedia.txt b/Documentation/dvb/avermedia.txt index 2dc260b2b0a4..068070ff13cd 100644 --- a/Documentation/dvb/avermedia.txt +++ b/Documentation/dvb/avermedia.txt @@ -150,7 +150,8 @@ Getting the card going The frontend module sp887x.o, requires an external firmware. Please use the command "get_dvb_firmware sp887x" to download - it. Then copy it to /usr/lib/hotplug/firmware. + it. Then copy it to /usr/lib/hotplug/firmware or /lib/firmware/ + (depending on configuration of firmware hotplug). Receiving DVB-T in Australia diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index be6eb4c75991..75c28a174092 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -23,7 +23,7 @@ use IO::Handle; @components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t", "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004", - "or51211", "or51132_qam", "or51132_vsb"); + "or51211", "or51132_qam", "or51132_vsb", "bluebird"); # Check args syntax() if (scalar(@ARGV) != 1); @@ -34,7 +34,11 @@ for ($i=0; $i < scalar(@components); $i++) { if ($cid eq $components[$i]) { $outfile = eval($cid); die $@ if $@; - print STDERR "Firmware $outfile extracted successfully. Now copy it to either /lib/firmware or /usr/lib/hotplug/firmware/ (depending on your hotplug version).\n"; + print STDERR <<EOF; +Firmware $outfile extracted successfully. +Now copy it to either /usr/lib/hotplug/firmware or /lib/firmware +(depending on configuration of firmware hotplug). +EOF exit(0); } } @@ -243,7 +247,7 @@ sub nxt2002 { my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); checkstandard(); - + wgetfile($sourcefile, $url); unzip($sourcefile, $tmpdir); verify("$tmpdir/SkyNETU.sys", $hash); @@ -308,6 +312,19 @@ sub or51132_vsb { $fwfile; } +sub bluebird { + my $url = "http://www.linuxtv.org/download/dvb/firmware/dvb-usb-bluebird-01.fw"; + my $outfile = "dvb-usb-bluebird-01.fw"; + my $hash = "658397cb9eba9101af9031302671f49d"; + + checkstandard(); + + wgetfile($outfile, $url); + verify($outfile,$hash); + + $outfile; +} + # --------------------------------------------------------------- # Utilities diff --git a/Documentation/dvb/ttusb-dec.txt b/Documentation/dvb/ttusb-dec.txt index 5c1e984c26a7..b2f271cd784b 100644 --- a/Documentation/dvb/ttusb-dec.txt +++ b/Documentation/dvb/ttusb-dec.txt @@ -41,4 +41,5 @@ Hotplug Firmware Loading for 2.6 kernels For 2.6 kernels the firmware is loaded at the point that the driver module is loaded. See linux/Documentation/dvb/firmware.txt for more information. -Copy the three files downloaded above into the /usr/lib/hotplug/firmware directory. +Copy the three files downloaded above into the /usr/lib/hotplug/firmware or +/lib/firmware directory (depending on configuration of firmware hotplug). diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index a4dcf42c2fd9..944cf109a6f5 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -418,7 +418,7 @@ VmallocChunk: 111088 kB Dirty: Memory which is waiting to get written back to the disk Writeback: Memory which is actively being written back to the disk Mapped: files which have been mmaped, such as libraries - Slab: in-kernel data structures cache + Slab: in-kernel data structures cache CommitLimit: Based on the overcommit ratio ('vm.overcommit_ratio'), this is the total amount of memory currently available to be allocated on the system. This limit is only adhered to diff --git a/Documentation/i2o/ioctl b/Documentation/i2o/ioctl index 3e174978997d..1e77fac4e120 100644 --- a/Documentation/i2o/ioctl +++ b/Documentation/i2o/ioctl @@ -185,7 +185,7 @@ VII. Getting Parameters ENOMEM Kernel memory allocation error A return value of 0 does not mean that the value was actually - properly retreived. The user should check the result list + properly retrieved. The user should check the result list to determine the specific status of the transaction. VIII. Downloading Software diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index acb010bb087b..0dc848bf0b56 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -998,6 +998,8 @@ running once the system is up. nowb [ARM] + nr_uarts= [SERIAL] maximum number of UARTs to be registered. + opl3= [HW,OSS] Format: <io> diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index 0541fe1de704..0ea5a0c6e827 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt @@ -411,7 +411,8 @@ int init_module(void) printk("Couldn't find %s to plant kprobe\n", "do_fork"); return -1; } - if ((ret = register_kprobe(&kp) < 0)) { + ret = register_kprobe(&kp); + if (ret < 0) { printk("register_kprobe failed, returned %d\n", ret); return -1; } diff --git a/Documentation/mutex-design.txt b/Documentation/mutex-design.txt new file mode 100644 index 000000000000..cbf79881a41c --- /dev/null +++ b/Documentation/mutex-design.txt @@ -0,0 +1,135 @@ +Generic Mutex Subsystem + +started by Ingo Molnar <mingo@redhat.com> + + "Why on earth do we need a new mutex subsystem, and what's wrong + with semaphores?" + +firstly, there's nothing wrong with semaphores. But if the simpler +mutex semantics are sufficient for your code, then there are a couple +of advantages of mutexes: + + - 'struct mutex' is smaller on most architectures: .e.g on x86, + 'struct semaphore' is 20 bytes, 'struct mutex' is 16 bytes. + A smaller structure size means less RAM footprint, and better + CPU-cache utilization. + + - tighter code. On x86 i get the following .text sizes when + switching all mutex-alike semaphores in the kernel to the mutex + subsystem: + + text data bss dec hex filename + 3280380 868188 396860 4545428 455b94 vmlinux-semaphore + 3255329 865296 396732 4517357 44eded vmlinux-mutex + + that's 25051 bytes of code saved, or a 0.76% win - off the hottest + codepaths of the kernel. (The .data savings are 2892 bytes, or 0.33%) + Smaller code means better icache footprint, which is one of the + major optimization goals in the Linux kernel currently. + + - the mutex subsystem is slightly faster and has better scalability for + contended workloads. On an 8-way x86 system, running a mutex-based + kernel and testing creat+unlink+close (of separate, per-task files) + in /tmp with 16 parallel tasks, the average number of ops/sec is: + + Semaphores: Mutexes: + + $ ./test-mutex V 16 10 $ ./test-mutex V 16 10 + 8 CPUs, running 16 tasks. 8 CPUs, running 16 tasks. + checking VFS performance. checking VFS performance. + avg loops/sec: 34713 avg loops/sec: 84153 + CPU utilization: 63% CPU utilization: 22% + + i.e. in this workload, the mutex based kernel was 2.4 times faster + than the semaphore based kernel, _and_ it also had 2.8 times less CPU + utilization. (In terms of 'ops per CPU cycle', the semaphore kernel + performed 551 ops/sec per 1% of CPU time used, while the mutex kernel + performed 3825 ops/sec per 1% of CPU time used - it was 6.9 times + more efficient.) + + the scalability difference is visible even on a 2-way P4 HT box: + + Semaphores: Mutexes: + + $ ./test-mutex V 16 10 $ ./test-mutex V 16 10 + 4 CPUs, running 16 tasks. 8 CPUs, running 16 tasks. + checking VFS performance. checking VFS performance. + avg loops/sec: 127659 avg loops/sec: 181082 + CPU utilization: 100% CPU utilization: 34% + + (the straight performance advantage of mutexes is 41%, the per-cycle + efficiency of mutexes is 4.1 times better.) + + - there are no fastpath tradeoffs, the mutex fastpath is just as tight + as the semaphore fastpath. On x86, the locking fastpath is 2 + instructions: + + c0377ccb <mutex_lock>: + c0377ccb: f0 ff 08 lock decl (%eax) + c0377cce: 78 0e js c0377cde <.text.lock.mutex> + c0377cd0: c3 ret + + the unlocking fastpath is equally tight: + + c0377cd1 <mutex_unlock>: + c0377cd1: f0 ff 00 lock incl (%eax) + c0377cd4: 7e 0f jle c0377ce5 <.text.lock.mutex+0x7> + c0377cd6: c3 ret + + - 'struct mutex' semantics are well-defined and are enforced if + CONFIG_DEBUG_MUTEXES is turned on. Semaphores on the other hand have + virtually no debugging code or instrumentation. The mutex subsystem + checks and enforces the following rules: + + * - only one task can hold the mutex at a time + * - only the owner can unlock the mutex + * - multiple unlocks are not permitted + * - recursive locking is not permitted + * - a mutex object must be initialized via the API + * - a mutex object must not be initialized via memset or copying + * - task may not exit with mutex held + * - memory areas where held locks reside must not be freed + * - held mutexes must not be reinitialized + * - mutexes may not be used in irq contexts + + furthermore, there are also convenience features in the debugging + code: + + * - uses symbolic names of mutexes, whenever they are printed in debug output + * - point-of-acquire tracking, symbolic lookup of function names + * - list of all locks held in the system, printout of them + * - owner tracking + * - detects self-recursing locks and prints out all relevant info + * - detects multi-task circular deadlocks and prints out all affected + * locks and tasks (and only those tasks) + +Disadvantages +------------- + +The stricter mutex API means you cannot use mutexes the same way you +can use semaphores: e.g. they cannot be used from an interrupt context, +nor can they be unlocked from a different context that which acquired +it. [ I'm not aware of any other (e.g. performance) disadvantages from +using mutexes at the moment, please let me know if you find any. ] + +Implementation of mutexes +------------------------- + +'struct mutex' is the new mutex type, defined in include/linux/mutex.h +and implemented in kernel/mutex.c. It is a counter-based mutex with a +spinlock and a wait-list. The counter has 3 states: 1 for "unlocked", +0 for "locked" and negative numbers (usually -1) for "locked, potential +waiters queued". + +the APIs of 'struct mutex' have been streamlined: + + DEFINE_MUTEX(name); + + mutex_init(mutex); + + void mutex_lock(struct mutex *lock); + int mutex_lock_interruptible(struct mutex *lock); + int mutex_trylock(struct mutex *lock); + void mutex_unlock(struct mutex *lock); + int mutex_is_locked(struct mutex *lock); + diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt index 851fc97bb22f..f9d979ee9526 100644 --- a/Documentation/networking/sk98lin.txt +++ b/Documentation/networking/sk98lin.txt @@ -245,7 +245,7 @@ Default: Both This parameters is only relevant if auto-negotiation for this port is not set to "Sense". If auto-negotiation is set to "On", all three values are possible. If it is set to "Off", only "Full" and "Half" are allowed. -This parameter is usefull if your link partner does not support all +This parameter is useful if your link partner does not support all possible combinations. Flow Control diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index cd0fcd89a6f0..08c79d4dc540 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -212,7 +212,7 @@ A: Try running cat `cat /proc/[0-9]*/maps | grep / | sed 's:.* /:/:' | sort -u` > /dev/null -after resume. swapoff -a; swapon -a may also be usefull. +after resume. swapoff -a; swapon -a may also be useful. Q: What happens to devices during swsusp? They seem to be resumed during system suspend? @@ -323,7 +323,7 @@ to be useless to try to suspend to disk while that app is running? A: No, it should work okay, as long as your app does not mlock() it. Just prepare big enough swap partition. -Q: What information is usefull for debugging suspend-to-disk problems? +Q: What information is useful for debugging suspend-to-disk problems? A: Well, last messages on the screen are always useful. If something is broken, it is usually some kernel driver, therefore trying with as diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 330246ac80f8..74fb085e178b 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -141,3 +141,4 @@ 140 -> Osprey 440 [0070:ff07] 141 -> Asound Skyeye PCTV 142 -> Sabrent TV-FM (bttv version) +143 -> Hauppauge ImpactVCB (bt878) [0070:13eb] diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index a1017d1a85d4..34b6e59f2968 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -16,7 +16,7 @@ 15 -> DViCO FusionHDTV DVB-T1 [18ac:db00] 16 -> KWorld LTV883RF 17 -> DViCO FusionHDTV 3 Gold-Q [18ac:d810] - 18 -> Hauppauge Nova-T DVB-T [0070:9002] + 18 -> Hauppauge Nova-T DVB-T [0070:9002,0070:9001] 19 -> Conexant DVB-T reference design [14f1:0187] 20 -> Provideo PV259 [1540:2580] 21 -> DViCO FusionHDTV DVB-T Plus [18ac:db10] @@ -35,3 +35,11 @@ 34 -> ATI HDTV Wonder [1002:a101] 35 -> WinFast DTV1000-T [107d:665f] 36 -> AVerTV 303 (M126) [1461:000a] + 37 -> Hauppauge Nova-S-Plus DVB-S [0070:9201,0070:9202] + 38 -> Hauppauge Nova-SE2 DVB-S [0070:9200] + 39 -> KWorld DVB-S 100 [17de:08b2] + 40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid [0070:9400,0070:9402] + 41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802] + 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025] + 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1] + 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50] diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index efb708ec116a..cb3a59bbeb17 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -56,7 +56,7 @@ 55 -> LifeView FlyDVB-T DUO [5168:0502,5168:0306] 56 -> Avermedia AVerTV 307 [1461:a70a] 57 -> Avermedia AVerTV GO 007 FM [1461:f31f] - 58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0370,1421:1370] + 58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0351,1421:0370,1421:1370] 59 -> Kworld/Tevion V-Stream Xpert TV PVR7134 60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502] 61 -> Philips TOUGH DVB-T reference design [1131:2004] @@ -81,4 +81,5 @@ 80 -> ASUS Digimatrix TV [1043:0210] 81 -> Philips Tiger reference design [1131:2018] 82 -> MSI TV@Anywhere plus [1462:6231] - + 83 -> Terratec Cinergy 250 PCI TV [153b:1160] + 84 -> LifeView FlyDVB Trio [5168:0319] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 9d6544ea9f41..0bf3d5bf9ef8 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -40,7 +40,7 @@ tuner=38 - Philips PAL/SECAM multi (FM1216ME MK3) tuner=39 - LG NTSC (newer TAPC series) tuner=40 - HITACHI V7-J180AT tuner=41 - Philips PAL_MK (FI1216 MK) -tuner=42 - Philips 1236D ATSC/NTSC daul in +tuner=42 - Philips 1236D ATSC/NTSC dual in tuner=43 - Philips NTSC MK3 (FM1236MK3 or FM1236/F) tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant) tuner=45 - Microtune 4049 FM5 @@ -50,7 +50,7 @@ tuner=48 - Tenna TNF 8831 BGFF) tuner=49 - Microtune 4042 FI5 ATSC/NTSC dual in tuner=50 - TCL 2002N tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3) -tuner=52 - Thomson DDT 7610 (ATSC/NTSC) +tuner=52 - Thomson DTT 7610 (ATSC/NTSC) tuner=53 - Philips FQ1286 tuner=54 - tda8290+75 tuner=55 - TCL 2002MB @@ -58,7 +58,7 @@ tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4) tuner=57 - Philips FQ1236A MK4 tuner=58 - Ymec TVision TVF-8531MF/8831MF/8731MF tuner=59 - Ymec TVision TVF-5533MF -tuner=60 - Thomson DDT 7611 (ATSC/NTSC) +tuner=60 - Thomson DTT 761X (ATSC/NTSC) tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF tuner=62 - Philips TEA5767HN FM Radio tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner diff --git a/MAINTAINERS b/MAINTAINERS index 8024d1b70065..07420161e669 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -546,13 +546,6 @@ W: http://linuxtv.org T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git S: Maintained -BUSLOGIC SCSI DRIVER -P: Leonard N. Zubkoff -M: Leonard N. Zubkoff <lnz@dandelion.com> -L: linux-scsi@vger.kernel.org -W: http://www.dandelion.com/Linux/ -S: Maintained - COMMON INTERNET FILE SYSTEM (CIFS) P: Steve French M: sfrench@samba.org @@ -251,7 +251,7 @@ export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD # If it is set to "silent_", nothing wil be printed at all, since # the variable $(silent_cmd_cc_o_c) doesn't exist. # -# A simple variant is to prefix commands with $(Q) - that's usefull +# A simple variant is to prefix commands with $(Q) - that's useful # for commands that shall be hidden in non-verbose mode. # # $(Q)ln $@ :< diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7a74e3e5f916..50b9afa8ae6d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -99,13 +99,6 @@ config ARCH_EBSA110 Ethernet interface, two PCMCIA sockets, two serial ports and a parallel port. -config ARCH_CAMELOT - bool "Epxa10db" - help - This enables support for Altera's Excalibur XA10 development board. - If you would like to build your kernel to run on one of these boards - then you must say 'Y' here. Otherwise say 'N' - config ARCH_FOOTBRIDGE bool "FootBridge" select FOOTBRIDGE @@ -213,12 +206,16 @@ config ARCH_AAEC2000 help This enables support for systems based on the Agilent AAEC-2000 +config ARCH_AT91RM9200 + bool "AT91RM9200" + help + Say Y here if you intend to run this kernel on an AT91RM9200-based + board. + endchoice source "arch/arm/mach-clps711x/Kconfig" -source "arch/arm/mach-epxa10db/Kconfig" - source "arch/arm/mach-footbridge/Kconfig" source "arch/arm/mach-integrator/Kconfig" @@ -253,6 +250,8 @@ source "arch/arm/mach-aaec2000/Kconfig" source "arch/arm/mach-realview/Kconfig" +source "arch/arm/mach-at91rm9200/Kconfig" + # Definitions to make life easier config ARCH_ACORN bool @@ -418,7 +417,8 @@ config LEDS ARCH_EBSA285 || ARCH_IMX || ARCH_INTEGRATOR || \ ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \ ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ - ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE + ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ + ARCH_AT91RM9200 help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. diff --git a/arch/arm/Makefile b/arch/arm/Makefile index afaf3a1e903c..1fa2a1011584 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -84,7 +84,6 @@ endif machine-$(CONFIG_ARCH_PXA) := pxa machine-$(CONFIG_ARCH_L7200) := l7200 machine-$(CONFIG_ARCH_INTEGRATOR) := integrator - machine-$(CONFIG_ARCH_CAMELOT) := epxa10db textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000 machine-$(CONFIG_ARCH_CLPS711X) := clps711x machine-$(CONFIG_ARCH_IOP3XX) := iop3xx @@ -100,6 +99,7 @@ endif machine-$(CONFIG_ARCH_H720X) := h720x machine-$(CONFIG_ARCH_AAEC2000) := aaec2000 machine-$(CONFIG_ARCH_REALVIEW) := realview + machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200 ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 6b505ce41a75..35ffe0f4ece7 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -21,10 +21,6 @@ ifeq ($(CONFIG_ARCH_SHARK),y) OBJS += head-shark.o ofw-shark.o endif -ifeq ($(CONFIG_ARCH_CAMELOT),y) -OBJS += head-epxa10db.o -endif - ifeq ($(CONFIG_ARCH_L7200),y) OBJS += head-l7200.o endif @@ -50,6 +46,10 @@ ifeq ($(CONFIG_PXA_SHARPSL),y) OBJS += head-sharpsl.o endif +ifeq ($(CONFIG_ARCH_AT91RM9200),y) +OBJS += head-at91rm9200.o +endif + ifeq ($(CONFIG_DEBUG_ICEDCC),y) OBJS += ice-dcc.o endif diff --git a/arch/arm/boot/compressed/head-at91rm9200.S b/arch/arm/boot/compressed/head-at91rm9200.S new file mode 100644 index 000000000000..2119ea62b547 --- /dev/null +++ b/arch/arm/boot/compressed/head-at91rm9200.S @@ -0,0 +1,57 @@ +/* + * linux/arch/arm/boot/compressed/head-at91rm9200.S + * + * Copyright (C) 2003 SAN People + * + * 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. + * + */ +#include <asm/mach-types.h> + + .section ".start", "ax" + + @ Atmel AT91RM9200-DK : 262 + mov r3, #(MACH_TYPE_AT91RM9200DK & 0xff) + orr r3, r3, #(MACH_TYPE_AT91RM9200DK & 0xff00) + cmp r7, r3 + beq 99f + + @ Cogent CSB337 : 399 + mov r3, #(MACH_TYPE_CSB337 & 0xff) + orr r3, r3, #(MACH_TYPE_CSB337 & 0xff00) + cmp r7, r3 + beq 99f + + @ Cogent CSB637 : 648 + mov r3, #(MACH_TYPE_CSB637 & 0xff) + orr r3, r3, #(MACH_TYPE_CSB637 & 0xff00) + cmp r7, r3 + beq 99f + + @ Atmel AT91RM9200-EK : 705 + mov r3, #(MACH_TYPE_AT91RM9200EK & 0xff) + orr r3, r3, #(MACH_TYPE_AT91RM9200EK & 0xff00) + cmp r7, r3 + beq 99f + + @ Conitec Carmeva : 769 + mov r3, #(MACH_TYPE_CARMEVA & 0xff) + orr r3, r3, #(MACH_TYPE_CARMEVA & 0xff00) + cmp r7, r3 + beq 99f + + @ KwikByte KB920x : 612 + mov r3, #(MACH_TYPE_KB9200 & 0xff) + orr r3, r3, #(MACH_TYPE_KB9200 & 0xff00) + cmp r7, r3 + beq 99f + + @ Unknown board, use the AT91RM9200DK board + @ mov r7, #MACH_TYPE_AT91RM9200 + mov r7, #(MACH_TYPE_AT91RM9200DK & 0xff) + orr r7, r7, #(MACH_TYPE_AT91RM9200DK & 0xff00) + +99: diff --git a/arch/arm/boot/compressed/head-epxa10db.S b/arch/arm/boot/compressed/head-epxa10db.S deleted file mode 100644 index 757681f12a39..000000000000 --- a/arch/arm/boot/compressed/head-epxa10db.S +++ /dev/null @@ -1,5 +0,0 @@ -#include <asm/mach-types.h> -#include <asm/arch/excalibur.h> - - .section ".start", "ax" - mov r7, #MACH_TYPE_CAMELOT diff --git a/arch/arm/configs/assabet_defconfig b/arch/arm/configs/assabet_defconfig index ccbb4c0d58c4..089c9d598409 100644 --- a/arch/arm/configs/assabet_defconfig +++ b/arch/arm/configs/assabet_defconfig @@ -63,7 +63,6 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig index 5d92af975d87..cfe6bd8e81cd 100644 --- a/arch/arm/configs/badge4_defconfig +++ b/arch/arm/configs/badge4_defconfig @@ -66,7 +66,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/bast_defconfig b/arch/arm/configs/bast_defconfig index 35e3a99bcbb6..6886001b5366 100644 --- a/arch/arm/configs/bast_defconfig +++ b/arch/arm/configs/bast_defconfig @@ -64,7 +64,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/cerfcube_defconfig b/arch/arm/configs/cerfcube_defconfig index d8fe0f40408f..f81a60005cd3 100644 --- a/arch/arm/configs/cerfcube_defconfig +++ b/arch/arm/configs/cerfcube_defconfig @@ -65,7 +65,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/clps7500_defconfig b/arch/arm/configs/clps7500_defconfig index 908758371405..af9ae5389131 100644 --- a/arch/arm/configs/clps7500_defconfig +++ b/arch/arm/configs/clps7500_defconfig @@ -57,7 +57,6 @@ CONFIG_ARCH_CLPS7500=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig index 40dfe07a8bce..15468a0cf70e 100644 --- a/arch/arm/configs/collie_defconfig +++ b/arch/arm/configs/collie_defconfig @@ -71,7 +71,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig index 06229026f78b..3c3461e83398 100644 --- a/arch/arm/configs/corgi_defconfig +++ b/arch/arm/configs/corgi_defconfig @@ -87,7 +87,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/ebsa110_defconfig b/arch/arm/configs/ebsa110_defconfig index 6f61929b97a8..afcfff6140f2 100644 --- a/arch/arm/configs/ebsa110_defconfig +++ b/arch/arm/configs/ebsa110_defconfig @@ -63,7 +63,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set CONFIG_ARCH_EBSA110=y -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/edb7211_defconfig b/arch/arm/configs/edb7211_defconfig index 78b08ed4d5f4..6ba7355ff85b 100644 --- a/arch/arm/configs/edb7211_defconfig +++ b/arch/arm/configs/edb7211_defconfig @@ -57,7 +57,6 @@ CONFIG_BASE_SMALL=0 CONFIG_ARCH_CLPS711X=y # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig index fd7c0042bcca..9592e3925c79 100644 --- a/arch/arm/configs/enp2611_defconfig +++ b/arch/arm/configs/enp2611_defconfig @@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig index 96342afa9c5f..fbe312e757cb 100644 --- a/arch/arm/configs/ep80219_defconfig +++ b/arch/arm/configs/ep80219_defconfig @@ -64,7 +64,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y diff --git a/arch/arm/configs/epxa10db_defconfig b/arch/arm/configs/epxa10db_defconfig deleted file mode 100644 index 9fb8b58c4954..000000000000 --- a/arch/arm/configs/epxa10db_defconfig +++ /dev/null @@ -1,644 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-rc1-bk2 -# Sun Mar 27 22:46:51 2005 -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_IOMAP=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y -# CONFIG_IKCONFIG is not set -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_KMOD is not set - -# -# System Type -# -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -CONFIG_ARCH_CAMELOT=y -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set - -# -# Epxa10db -# - -# -# PLD hotswap support -# -CONFIG_PLD=y -# CONFIG_PLD_HOTSWAP is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_ARM922T=y -CONFIG_CPU_32v4=y -CONFIG_CPU_ABRT_EV4T=y -CONFIG_CPU_CACHE_V4WT=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_TLB_V4WBI=y - -# -# Processor Features -# -# CONFIG_ARM_THUMB is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set - -# -# Bus support -# - -# -# PCCARD (PCMCIA/CardBus) support -# -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -# CONFIG_PREEMPT is not set -CONFIG_ALIGNMENT_TRAP=y - -# -# Boot options -# -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="mem=32M console=ttyUA0,115200 initrd=0x00200000,8M root=/dev/ram0 rw" -# CONFIG_XIP_KERNEL is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set -# CONFIG_ARTHUR is not set - -# -# Power management options -# -# CONFIG_PM is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_ATA_OVER_ETH is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -CONFIG_PPP=y -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=y -CONFIG_PPP_SYNC_TTY=y -CONFIG_PPP_DEFLATE=y -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_RAW is not set -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_UART00=y -CONFIG_SERIAL_UART00_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# -# CONFIG_TCG_TPM is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Misc devices -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -# CONFIG_FB is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set - -# -# XFS support -# -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVPTS_FS_XATTR is not set -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -CONFIG_SMB_FS=y -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -# CONFIG_DEBUG_KERNEL is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_FRAME_POINTER=y -# CONFIG_DEBUG_USER is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Hardware crypto devices -# - -# -# Library routines -# -CONFIG_CRC_CCITT=y -CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/configs/footbridge_defconfig b/arch/arm/configs/footbridge_defconfig index 9737c4850721..2a612d23120b 100644 --- a/arch/arm/configs/footbridge_defconfig +++ b/arch/arm/configs/footbridge_defconfig @@ -63,7 +63,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set CONFIG_ARCH_FOOTBRIDGE=y # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/fortunet_defconfig b/arch/arm/configs/fortunet_defconfig index b6f688d850dc..65dc73a88c43 100644 --- a/arch/arm/configs/fortunet_defconfig +++ b/arch/arm/configs/fortunet_defconfig @@ -57,7 +57,6 @@ CONFIG_BASE_SMALL=0 CONFIG_ARCH_CLPS711X=y # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/h3600_defconfig b/arch/arm/configs/h3600_defconfig index b9de07de80fe..7a0da0b7facb 100644 --- a/arch/arm/configs/h3600_defconfig +++ b/arch/arm/configs/h3600_defconfig @@ -65,7 +65,6 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/h7201_defconfig b/arch/arm/configs/h7201_defconfig index 39c13a354541..116920aecef7 100644 --- a/arch/arm/configs/h7201_defconfig +++ b/arch/arm/configs/h7201_defconfig @@ -60,7 +60,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/h7202_defconfig b/arch/arm/configs/h7202_defconfig index fbf5c244c696..9d62ed16bf57 100644 --- a/arch/arm/configs/h7202_defconfig +++ b/arch/arm/configs/h7202_defconfig @@ -63,7 +63,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/hackkit_defconfig b/arch/arm/configs/hackkit_defconfig index fb41a36a5a68..a45b57582b86 100644 --- a/arch/arm/configs/hackkit_defconfig +++ b/arch/arm/configs/hackkit_defconfig @@ -66,7 +66,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig index 27ee76825254..d1ba7fdde818 100644 --- a/arch/arm/configs/integrator_defconfig +++ b/arch/arm/configs/integrator_defconfig @@ -65,7 +65,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set CONFIG_ARCH_INTEGRATOR=y # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig index e71443b97390..c07628ceaf0c 100644 --- a/arch/arm/configs/iq31244_defconfig +++ b/arch/arm/configs/iq31244_defconfig @@ -65,7 +65,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig index ab5ad23b27da..18fa1615fdfd 100644 --- a/arch/arm/configs/iq80321_defconfig +++ b/arch/arm/configs/iq80321_defconfig @@ -64,7 +64,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig index bb536133ef87..f50035de1fff 100644 --- a/arch/arm/configs/iq80331_defconfig +++ b/arch/arm/configs/iq80331_defconfig @@ -64,7 +64,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y diff --git a/arch/arm/configs/iq80332_defconfig b/arch/arm/configs/iq80332_defconfig index 305f01f3a729..18b3f372ed68 100644 --- a/arch/arm/configs/iq80332_defconfig +++ b/arch/arm/configs/iq80332_defconfig @@ -64,7 +64,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig index e6a4d2656fe5..d9d6bb86a6fa 100644 --- a/arch/arm/configs/ixdp2400_defconfig +++ b/arch/arm/configs/ixdp2400_defconfig @@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig index 5572cf95d5f8..2dc9d499c7d7 100644 --- a/arch/arm/configs/ixdp2401_defconfig +++ b/arch/arm/configs/ixdp2401_defconfig @@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig index 0fddbde85835..4248123815e9 100644 --- a/arch/arm/configs/ixdp2800_defconfig +++ b/arch/arm/configs/ixdp2800_defconfig @@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig index 89b9aa06aa91..ea8f4b478fa3 100644 --- a/arch/arm/configs/ixdp2801_defconfig +++ b/arch/arm/configs/ixdp2801_defconfig @@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig index 613afab62720..4975b914f923 100644 --- a/arch/arm/configs/ixp4xx_defconfig +++ b/arch/arm/configs/ixp4xx_defconfig @@ -85,7 +85,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/jornada720_defconfig b/arch/arm/configs/jornada720_defconfig index b88aeba82bc0..ad1048db96fb 100644 --- a/arch/arm/configs/jornada720_defconfig +++ b/arch/arm/configs/jornada720_defconfig @@ -63,7 +63,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/lart_defconfig b/arch/arm/configs/lart_defconfig index 7033829ed145..c3a932844160 100644 --- a/arch/arm/configs/lart_defconfig +++ b/arch/arm/configs/lart_defconfig @@ -62,7 +62,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/lpd7a400_defconfig b/arch/arm/configs/lpd7a400_defconfig index d64706d3ff35..67eaa26c2647 100644 --- a/arch/arm/configs/lpd7a400_defconfig +++ b/arch/arm/configs/lpd7a400_defconfig @@ -60,7 +60,6 @@ CONFIG_BASE_SMALL=0 # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/lpd7a404_defconfig b/arch/arm/configs/lpd7a404_defconfig index 87cbedfb303f..208d591ebfce 100644 --- a/arch/arm/configs/lpd7a404_defconfig +++ b/arch/arm/configs/lpd7a404_defconfig @@ -60,7 +60,6 @@ CONFIG_BASE_SMALL=0 # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig index 4bc8717c6f57..81daadcbe0ba 100644 --- a/arch/arm/configs/lubbock_defconfig +++ b/arch/arm/configs/lubbock_defconfig @@ -63,7 +63,6 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/lusl7200_defconfig b/arch/arm/configs/lusl7200_defconfig index 3ca64cabc92c..42f6a77bc3c0 100644 --- a/arch/arm/configs/lusl7200_defconfig +++ b/arch/arm/configs/lusl7200_defconfig @@ -62,7 +62,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig index 153d68594beb..b112bd75bda2 100644 --- a/arch/arm/configs/mainstone_defconfig +++ b/arch/arm/configs/mainstone_defconfig @@ -63,7 +63,6 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/mx1ads_defconfig b/arch/arm/configs/mx1ads_defconfig index 6517d167acf0..d16f6cd6e039 100644 --- a/arch/arm/configs/mx1ads_defconfig +++ b/arch/arm/configs/mx1ads_defconfig @@ -63,7 +63,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig index 7fb1f7c7bf43..3d35255c64ed 100644 --- a/arch/arm/configs/neponset_defconfig +++ b/arch/arm/configs/neponset_defconfig @@ -65,7 +65,6 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/netwinder_defconfig b/arch/arm/configs/netwinder_defconfig index 6e81acf94c2f..2cae1ead9f9b 100644 --- a/arch/arm/configs/netwinder_defconfig +++ b/arch/arm/configs/netwinder_defconfig @@ -58,7 +58,6 @@ CONFIG_BASE_SMALL=0 # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set CONFIG_ARCH_FOOTBRIDGE=y # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig index 529f0f72e1e9..ee3ecbd9002d 100644 --- a/arch/arm/configs/omap_h2_1610_defconfig +++ b/arch/arm/configs/omap_h2_1610_defconfig @@ -85,7 +85,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/pleb_defconfig b/arch/arm/configs/pleb_defconfig index 10fec890578d..24e8bdd4cb91 100644 --- a/arch/arm/configs/pleb_defconfig +++ b/arch/arm/configs/pleb_defconfig @@ -63,7 +63,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig index 21c327883d8c..b71d31a4bb56 100644 --- a/arch/arm/configs/pxa255-idp_defconfig +++ b/arch/arm/configs/pxa255-idp_defconfig @@ -63,7 +63,6 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig index 0485b2f1cc20..3f1ec4e304f7 100644 --- a/arch/arm/configs/realview_defconfig +++ b/arch/arm/configs/realview_defconfig @@ -65,7 +65,6 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig index 19184c1010ad..b498afdc03b6 100644 --- a/arch/arm/configs/rpc_defconfig +++ b/arch/arm/configs/rpc_defconfig @@ -66,7 +66,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 3f97590c91f2..33f31080a98c 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -85,7 +85,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/shannon_defconfig b/arch/arm/configs/shannon_defconfig index e3facc4fe792..d052c8f80515 100644 --- a/arch/arm/configs/shannon_defconfig +++ b/arch/arm/configs/shannon_defconfig @@ -62,7 +62,6 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/shark_defconfig b/arch/arm/configs/shark_defconfig index 271823f0d708..c48d17062262 100644 --- a/arch/arm/configs/shark_defconfig +++ b/arch/arm/configs/shark_defconfig @@ -66,7 +66,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/simpad_defconfig b/arch/arm/configs/simpad_defconfig index 5373eeb7d578..2e5a616cc98d 100644 --- a/arch/arm/configs/simpad_defconfig +++ b/arch/arm/configs/simpad_defconfig @@ -64,7 +64,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/smdk2410_defconfig b/arch/arm/configs/smdk2410_defconfig index 2c60865fda19..4d123d33c7df 100644 --- a/arch/arm/configs/smdk2410_defconfig +++ b/arch/arm/configs/smdk2410_defconfig @@ -58,7 +58,6 @@ CONFIG_BASE_SMALL=0 # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig index 9895539533d6..d1ace3abfd8a 100644 --- a/arch/arm/configs/spitz_defconfig +++ b/arch/arm/configs/spitz_defconfig @@ -87,7 +87,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index d72f2c754268..2687a225aa6a 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -64,7 +64,6 @@ CONFIG_KMOD=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index b5645c4462cf..1d50d2b98f55 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -710,7 +710,8 @@ int setup_irq(unsigned int irq, struct irqaction *new) desc->pending = 0; desc->disable_depth = 1; - if (new->flags & SA_TRIGGER_MASK) { + if (new->flags & SA_TRIGGER_MASK && + desc->chip->set_type) { unsigned int type = new->flags & SA_TRIGGER_MASK; desc->chip->set_type(irq, type); } diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig new file mode 100644 index 000000000000..4b7218fc3eb1 --- /dev/null +++ b/arch/arm/mach-at91rm9200/Kconfig @@ -0,0 +1,54 @@ +if ARCH_AT91RM9200 + +menu "AT91RM9200 Implementations" + +comment "AT91RM9200 Board Type" + +config ARCH_AT91RM9200DK + bool "Atmel AT91RM9200-DK Development board" + depends on ARCH_AT91RM9200 + help + Select this if you are using Atmel's AT91RM9200-DK Development board + +config MACH_AT91RM9200EK + bool "Atmel AT91RM9200-EK Evaluation Kit" + depends on ARCH_AT91RM9200 + help + Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit + +config MACH_CSB337 + bool "Cogent CSB337 board" + depends on ARCH_AT91RM9200 + help + Select this if you are using Cogent's CSB337 board + +config MACH_CSB637 + bool "Cogent CSB637 board" + depends on ARCH_AT91RM9200 + help + Select this if you are using Cogent's CSB637 board + +config MACH_CARMEVA + bool "Conitec's ARM&EVA" + depends on ARCH_AT91RM9200 + help + Select this if you are using Conitec's AT91RM9200-MCU-Module + +config MACH_KB9200 + bool "KwikByte's KB920x" + depends on ARCH_AT91RM9200 + help + Select this if you are using KwikByte's KB920x board + + +comment "AT91RM9200 Feature Selections" + +config AT91_PROGRAMMABLE_CLOCKS + bool "Programmable Clocks" + help + Select this if you need to program one or more of the PCK0..PCK3 + programmable clock outputs. + +endmenu + +endif diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile new file mode 100644 index 000000000000..1f2805ca6e21 --- /dev/null +++ b/arch/arm/mach-at91rm9200/Makefile @@ -0,0 +1,27 @@ +# +# Makefile for the linux kernel. +# + +obj-y := clock.o irq.o time.o gpio.o common.o devices.o +obj-m := +obj-n := +obj- := + +# Board-specific support +#obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o +#obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o +#obj-$(CONFIG_MACH_CSB337) += board-csb337.o +#obj-$(CONFIG_MACH_CSB637) += board-csb637.o +#obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o +#obj-$(CONFIG_MACH_KB9200) += board-kb9202.o + +# LEDs support +#led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o +#led-$(CONFIG_MACH_AT91RM9200EK) += leds.o +#led-$(CONFIG_MACH_CSB337) += leds.o +#led-$(CONFIG_MACH_CSB637) += leds.o +#led-$(CONFIG_MACH_KB9200) += leds.o +obj-$(CONFIG_LEDS) += $(led-y) + +# VGA support +#obj-$(CONFIG_FB_S1D13XXX) += ics1523.o diff --git a/arch/arm/mach-at91rm9200/Makefile.boot b/arch/arm/mach-at91rm9200/Makefile.boot new file mode 100644 index 000000000000..e667dcc7cd34 --- /dev/null +++ b/arch/arm/mach-at91rm9200/Makefile.boot @@ -0,0 +1,9 @@ +# Note: the following conditions must always be true: +# ZRELADDR == virt_to_phys(TEXTADDR) +# PARAMS_PHYS must be within 4MB of ZRELADDR +# INITRD_PHYS must be in RAM + + zreladdr-y := 0x20008000 +params_phys-y := 0x20000100 +initrd_phys-y := 0x20410000 + diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c new file mode 100644 index 000000000000..ec8195a2a3cc --- /dev/null +++ b/arch/arm/mach-at91rm9200/clock.c @@ -0,0 +1,620 @@ +/* + * linux/arch/arm/mach-at91rm9200/clock.c + * + * Copyright (C) 2005 David Brownell + * Copyright (C) 2005 Ivan Kokshaysky + * + * 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. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/spinlock.h> +#include <linux/delay.h> +#include <linux/clk.h> + +#include <asm/semaphore.h> +#include <asm/io.h> +#include <asm/mach-types.h> + +#include <asm/arch/hardware.h> +#include <asm/arch/board.h> /* for master clock global */ + +#include "generic.h" + +#undef DEBUG + +/* + * There's a lot more which can be done with clocks, including cpufreq + * integration, slow clock mode support (for system suspend), letting + * PLLB be used at other rates (on boards that don't need USB), etc. + */ + +struct clk { + const char *name; + unsigned long rate_hz; + struct clk *parent; + u32 pmc_mask; + void (*mode)(struct clk *, int); + unsigned id:2; /* PCK0..3, or 32k/main/a/b */ + unsigned primary:1; + unsigned pll:1; + unsigned programmable:1; + u16 users; +}; + +static spinlock_t clk_lock; +static u32 at91_pllb_usb_init; + +/* + * Four primary clock sources: two crystal oscillators (32K, main), and + * two PLLs. PLLA usually runs the master clock; and PLLB must run at + * 48 MHz (unless no USB function clocks are needed). The main clock and + * both PLLs are turned off to run in "slow clock mode" (system suspend). + */ +static struct clk clk32k = { + .name = "clk32k", + .rate_hz = AT91_SLOW_CLOCK, + .users = 1, /* always on */ + .id = 0, + .primary = 1, +}; +static struct clk main_clk = { + .name = "main", + .pmc_mask = 1 << 0, /* in PMC_SR */ + .users = 1, + .id = 1, + .primary = 1, +}; +static struct clk plla = { + .name = "plla", + .parent = &main_clk, + .pmc_mask = 1 << 1, /* in PMC_SR */ + .id = 2, + .primary = 1, + .pll = 1, +}; + +static void pllb_mode(struct clk *clk, int is_on) +{ + u32 value; + + if (is_on) { + is_on = AT91_PMC_LOCKB; + value = at91_pllb_usb_init; + } else + value = 0; + + at91_sys_write(AT91_CKGR_PLLBR, value); + + do { + cpu_relax(); + } while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != is_on); +} + +static struct clk pllb = { + .name = "pllb", + .parent = &main_clk, + .pmc_mask = 1 << 2, /* in PMC_SR */ + .mode = pllb_mode, + .id = 3, + .primary = 1, + .pll = 1, +}; + +static void pmc_sys_mode(struct clk *clk, int is_on) +{ + if (is_on) + at91_sys_write(AT91_PMC_SCER, clk->pmc_mask); + else + at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask); +} + +/* USB function clocks (PLLB must be 48 MHz) */ +static struct clk udpck = { + .name = "udpck", + .parent = &pllb, + .pmc_mask = AT91_PMC_UDP, + .mode = pmc_sys_mode, +}; +static struct clk uhpck = { + .name = "uhpck", + .parent = &pllb, + .pmc_mask = AT91_PMC_UHP, + .mode = pmc_sys_mode, +}; + +#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS +/* + * The four programmable clocks can be parented by any primary clock. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .mode = pmc_sys_mode, + .programmable = 1, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .mode = pmc_sys_mode, + .programmable = 1, + .id = 1, +}; +static struct clk pck2 = { + .name = "pck2", + .pmc_mask = AT91_PMC_PCK2, + .mode = pmc_sys_mode, + .programmable = 1, + .id = 2, +}; +static struct clk pck3 = { + .name = "pck3", + .pmc_mask = AT91_PMC_PCK3, + .mode = pmc_sys_mode, + .programmable = 1, + .id = 3, +}; +#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ + + +/* + * The master clock is divided from the CPU clock (by 1-4). It's used for + * memory, interfaces to on-chip peripherals, the AIC, and sometimes more + * (e.g baud rate generation). It's sourced from one of the primary clocks. + */ +static struct clk mck = { + .name = "mck", + .pmc_mask = 1 << 3, /* in PMC_SR */ + .users = 1, /* (must be) always on */ +}; + +static void pmc_periph_mode(struct clk *clk, int is_on) +{ + if (is_on) + at91_sys_write(AT91_PMC_PCER, clk->pmc_mask); + else + at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask); +} + +static struct clk udc_clk = { + .name = "udc_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_UDP, + .mode = pmc_periph_mode, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_UHP, + .mode = pmc_periph_mode, +}; + +static struct clk *const clock_list[] = { + /* four primary clocks -- MUST BE FIRST! */ + &clk32k, + &main_clk, + &plla, + &pllb, + + /* PLLB children (USB) */ + &udpck, + &uhpck, + +#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS + /* programmable clocks */ + &pck0, + &pck1, + &pck2, + &pck3, +#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ + + /* MCK and peripherals */ + &mck, + // usart0..usart3 + // mmc + &udc_clk, + // i2c + // spi + // ssc0..ssc2 + // tc0..tc5 + &ohci_clk, + // ether +}; + + +/* clocks are all static for now; no refcounting necessary */ +struct clk *clk_get(struct device *dev, const char *id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(clock_list); i++) { + if (strcmp(id, clock_list[i]->name) == 0) + return clock_list[i]; + } + + return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); + +static void __clk_enable(struct clk *clk) +{ + if (clk->parent) + __clk_enable(clk->parent); + if (clk->users++ == 0 && clk->mode) + clk->mode(clk, 1); +} + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clk_lock, flags); + return 0; +} +EXPORT_SYMBOL(clk_enable); + +static void __clk_disable(struct clk *clk) +{ + BUG_ON(clk->users == 0); + if (--clk->users == 0 && clk->mode) + clk->mode(clk, 0); + if (clk->parent) + __clk_disable(clk->parent); +} + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clk_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + unsigned long flags; + unsigned long rate; + + spin_lock_irqsave(&clk_lock, flags); + for (;;) { + rate = clk->rate_hz; + if (rate || !clk->parent) + break; + clk = clk->parent; + } + spin_unlock_irqrestore(&clk_lock, flags); + return rate; +} +EXPORT_SYMBOL(clk_get_rate); + +/*------------------------------------------------------------------------*/ + +#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS + +/* + * For now, only the programmable clocks support reparenting (MCK could + * do this too, with care) or rate changing (the PLLs could do this too, + * ditto MCK but that's more for cpufreq). Drivers may reparent to get + * a better rate match; we don't. + */ + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + unsigned prescale; + unsigned long actual; + + if (!clk->programmable) + return -EINVAL; + spin_lock_irqsave(&clk_lock, flags); + + actual = clk->parent->rate_hz; + for (prescale = 0; prescale < 7; prescale++) { + if (actual && actual <= rate) + break; + actual >>= 1; + } + + spin_unlock_irqrestore(&clk_lock, flags); + return (prescale < 7) ? actual : -ENOENT; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + unsigned prescale; + unsigned long actual; + + if (!clk->programmable) + return -EINVAL; + if (clk->users) + return -EBUSY; + spin_lock_irqsave(&clk_lock, flags); + + actual = clk->parent->rate_hz; + for (prescale = 0; prescale < 7; prescale++) { + if (actual && actual <= rate) { + u32 pckr; + + pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); + pckr &= 0x03; + pckr |= prescale << 2; + at91_sys_write(AT91_PMC_PCKR(clk->id), pckr); + clk->rate_hz = actual; + break; + } + actual >>= 1; + } + + spin_unlock_irqrestore(&clk_lock, flags); + return (prescale < 7) ? actual : -ENOENT; +} +EXPORT_SYMBOL(clk_set_rate); + +struct clk *clk_get_parent(struct clk *clk) +{ + return clk->parent; +} +EXPORT_SYMBOL(clk_get_parent); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + unsigned long flags; + + if (clk->users) + return -EBUSY; + if (!parent->primary || !clk->programmable) + return -EINVAL; + spin_lock_irqsave(&clk_lock, flags); + + clk->rate_hz = parent->rate_hz; + clk->parent = parent; + at91_sys_write(AT91_PMC_PCKR(clk->id), parent->id); + + spin_unlock_irqrestore(&clk_lock, flags); + return 0; +} +EXPORT_SYMBOL(clk_set_parent); + +#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ + +/*------------------------------------------------------------------------*/ + +#ifdef CONFIG_DEBUG_FS + +static int at91_clk_show(struct seq_file *s, void *unused) +{ + u32 scsr, pcsr, sr; + unsigned i; + + seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR)); + seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR)); + + seq_printf(s, "MOR = %8x\n", at91_sys_read(AT91_CKGR_MOR)); + seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR)); + seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR)); + seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR)); + + seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR)); + for (i = 0; i < 4; i++) + seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i))); + seq_printf(s, "SR = %8x\n", sr = at91_sys_read(AT91_PMC_SR)); + + seq_printf(s, "\n"); + + for (i = 0; i < ARRAY_SIZE(clock_list); i++) { + char *state; + struct clk *clk = clock_list[i]; + + if (clk->mode == pmc_sys_mode) + state = (scsr & clk->pmc_mask) ? "on" : "off"; + else if (clk->mode == pmc_periph_mode) + state = (pcsr & clk->pmc_mask) ? "on" : "off"; + else if (clk->pmc_mask) + state = (sr & clk->pmc_mask) ? "on" : "off"; + else if (clk == &clk32k || clk == &main_clk) + state = "on"; + else + state = ""; + + seq_printf(s, "%-10s users=%d %-3s %9ld Hz %s\n", + clk->name, clk->users, state, clk_get_rate(clk), + clk->parent ? clk->parent->name : ""); + } + return 0; +} + +static int at91_clk_open(struct inode *inode, struct file *file) +{ + return single_open(file, at91_clk_show, NULL); +} + +static struct file_operations at91_clk_operations = { + .open = at91_clk_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init at91_clk_debugfs_init(void) +{ + /* /sys/kernel/debug/at91_clk */ + (void) debugfs_create_file("at91_clk", S_IFREG | S_IRUGO, NULL, NULL, &at91_clk_operations); + + return 0; +} +postcore_initcall(at91_clk_debugfs_init); + +#endif + +/*------------------------------------------------------------------------*/ + +static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg) +{ + unsigned mul, div; + + div = reg & 0xff; + mul = (reg >> 16) & 0x7ff; + if (div && mul) { + freq /= div; + freq *= mul + 1; + } else + freq = 0; + if (pll == &pllb && (reg & (1 << 28))) + freq /= 2; + return freq; +} + +static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq) +{ + unsigned i, div = 0, mul = 0, diff = 1 << 30; + unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00; + + /* PLL output max 240 MHz (or 180 MHz per errata) */ + if (out_freq > 240000000) + goto fail; + + for (i = 1; i < 256; i++) { + int diff1; + unsigned input, mul1; + + /* + * PLL input between 1MHz and 32MHz per spec, but lower + * frequences seem necessary in some cases so allow 100K. + */ + input = main_freq / i; + if (input < 100000) + continue; + if (input > 32000000) + continue; + + mul1 = out_freq / input; + if (mul1 > 2048) + continue; + if (mul1 < 2) + goto fail; + + diff1 = out_freq - input * mul1; + if (diff1 < 0) + diff1 = -diff1; + if (diff > diff1) { + diff = diff1; + div = i; + mul = mul1; + if (diff == 0) + break; + } + } + if (i == 256 && diff > (out_freq >> 5)) + goto fail; + return ret | ((mul - 1) << 16) | div; +fail: + return 0; +} + +int __init at91_clock_init(unsigned long main_clock) +{ + unsigned tmp, freq, mckr; + + spin_lock_init(&clk_lock); + + /* + * When the bootloader initialized the main oscillator correctly, + * there's no problem using the cycle counter. But if it didn't, + * or when using oscillator bypass mode, we must be told the speed + * of the main clock. + */ + if (!main_clock) { + do { + tmp = at91_sys_read(AT91_CKGR_MCFR); + } while (!(tmp & 0x10000)); + main_clock = (tmp & 0xffff) * (AT91_SLOW_CLOCK / 16); + } + main_clk.rate_hz = main_clock; + + /* report if PLLA is more than mildly overclocked */ + plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR)); + if (plla.rate_hz > 209000000) + pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); + + /* + * USB clock init: choose 48 MHz PLLB value, turn all clocks off, + * disable 48MHz clock during usb peripheral suspend. + * + * REVISIT: assumes MCK doesn't derive from PLLB! + */ + at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | 0x10000000; + pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); + at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP)); + at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); + at91_sys_write(AT91_CKGR_PLLBR, 0); + at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); + + /* + * MCK and CPU derive from one of those primary clocks. + * For now, assume this parentage won't change. + */ + mckr = at91_sys_read(AT91_PMC_MCKR); + mck.parent = clock_list[mckr & AT91_PMC_CSS]; + mck.parent->users++; + freq = mck.parent->rate_hz; + freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ + mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ + + printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n", + freq / 1000000, (unsigned) mck.rate_hz / 1000000, + (unsigned) main_clock / 1000000, + ((unsigned) main_clock % 1000000) / 1000); + + /* FIXME get rid of master_clock global */ + at91_master_clock = mck.rate_hz; + +#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS + /* establish PCK0..PCK3 parentage */ + for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) { + struct clk *clk = clock_list[tmp], *parent; + u32 pckr; + + if (!clk->programmable) + continue; + + pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); + parent = clock_list[pckr & 3]; + clk->parent = parent; + clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3)); + } +#else + /* disable unused clocks */ + at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); +#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ + + /* FIXME several unused clocks may still be active... provide + * a CONFIG option to turn off all unused clocks at some point + * before driver init starts. + */ + + return 0; +} diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c new file mode 100644 index 000000000000..3848fd2d5596 --- /dev/null +++ b/arch/arm/mach-at91rm9200/common.c @@ -0,0 +1,115 @@ +/* + * arch/arm/mach-at91rm9200/common.c + * + * Copyright (C) 2005 SAN People + * + * 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. + * + */ + +#include <linux/config.h> +#include <linux/module.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <asm/arch/hardware.h> + +static struct map_desc at91rm9200_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_SPI, + .pfn = __phys_to_pfn(AT91_BASE_SPI), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_SSC2, + .pfn = __phys_to_pfn(AT91_BASE_SSC2), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_SSC1, + .pfn = __phys_to_pfn(AT91_BASE_SSC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_SSC0, + .pfn = __phys_to_pfn(AT91_BASE_SSC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_US3, + .pfn = __phys_to_pfn(AT91_BASE_US3), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_US2, + .pfn = __phys_to_pfn(AT91_BASE_US2), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_US1, + .pfn = __phys_to_pfn(AT91_BASE_US1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_US0, + .pfn = __phys_to_pfn(AT91_BASE_US0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_EMAC, + .pfn = __phys_to_pfn(AT91_BASE_EMAC), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_TWI, + .pfn = __phys_to_pfn(AT91_BASE_TWI), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_MCI, + .pfn = __phys_to_pfn(AT91_BASE_MCI), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_UDP, + .pfn = __phys_to_pfn(AT91_BASE_UDP), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_TCB1, + .pfn = __phys_to_pfn(AT91_BASE_TCB1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_TCB0, + .pfn = __phys_to_pfn(AT91_BASE_TCB0), + .length = SZ_16K, + .type = MT_DEVICE, + }, +}; + +void __init at91rm9200_map_io(void) +{ + iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); +} + + +unsigned long at91_master_clock; + +EXPORT_SYMBOL(at91_master_clock); + + +int at91_serial_map[AT91_NR_UART]; +int at91_console_port; + +EXPORT_SYMBOL(at91_serial_map); +EXPORT_SYMBOL(at91_console_port); diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c new file mode 100644 index 000000000000..8df3e5245651 --- /dev/null +++ b/arch/arm/mach-at91rm9200/devices.c @@ -0,0 +1,291 @@ +/* + * arch/arm/mach-at91rm9200/devices.c + * + * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> + * Copyright (C) 2005 David Brownell + * + * 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. + * + */ +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <linux/config.h> +#include <linux/platform_device.h> + +#include <asm/arch/board.h> +#include <asm/arch/pio.h> + + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource at91rm9200_usbh_resource[] = { + [0] = { + .start = AT91_UHP_BASE, + .end = AT91_UHP_BASE + SZ_1M -1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_UHP, + .end = AT91_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_usbh_device = { + .name = "at91rm9200-ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = at91rm9200_usbh_resource, + .num_resources = ARRAY_SIZE(at91rm9200_usbh_resource), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + if (!data) + return; + + usbh_data = *data; + platform_device_register(&at91rm9200_usbh_device); +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource at91_udc_resources[] = { + { + .start = AT91_BASE_UDP, + .end = AT91_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91rm9200_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = at91_udc_resources, + .num_resources = ARRAY_SIZE(at91_udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + if (data->pullup_pin) + at91_set_gpio_output(data->pullup_pin, 0); + + udc_data = *data; + platform_device_register(&at91rm9200_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Ethernet + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE) +static u64 eth_dmamask = 0xffffffffUL; +static struct at91_eth_data eth_data; + +static struct platform_device at91rm9200_eth_device = { + .name = "at91_ether", + .id = -1, + .dev = { + .dma_mask = ð_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = ð_data, + }, + .num_resources = 0, +}; + +void __init at91_add_device_eth(struct at91_eth_data *data) +{ + if (!data) + return; + + if (data->phy_irq_pin) { + at91_set_gpio_input(data->phy_irq_pin, 0); + at91_set_deglitch(data->phy_irq_pin, 1); + } + + /* Pins used for MII and RMII */ + at91_set_A_periph(AT91_PIN_PA16, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PA15, 0); /* EMDC */ + at91_set_A_periph(AT91_PIN_PA14, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PA13, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PA12, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PA11, 0); /* ECRS_ECRSDV */ + at91_set_A_periph(AT91_PIN_PA10, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PA9, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PA8, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PA7, 0); /* ETXCK_EREFCK */ + + if (!data->is_rmii) { + at91_set_B_periph(AT91_PIN_PB19, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PB18, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PB17, 0); /* ERXDV */ + at91_set_B_periph(AT91_PIN_PB16, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PB15, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PB14, 0); /* ETXER */ + at91_set_B_periph(AT91_PIN_PB13, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PB12, 0); /* ETX2 */ + } + + eth_data = *data; + platform_device_register(&at91rm9200_eth_device); +} +#else +void __init at91_add_device_eth(struct at91_eth_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Compact Flash / PCMCIA + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) +static struct at91_cf_data cf_data; + +static struct platform_device at91rm9200_cf_device = { + .name = "at91_cf", + .id = -1, + .dev = { + .platform_data = &cf_data, + }, + .num_resources = 0, +}; + +void __init at91_add_device_cf(struct at91_cf_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->irq_pin) { + at91_set_gpio_input(data->irq_pin, 1); + at91_set_deglitch(data->irq_pin, 1); + } + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + + /* outputs, initially off */ + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + at91_set_gpio_output(data->rst_pin, 0); + + cf_data = *data; + platform_device_register(&at91rm9200_cf_device); +} +#else +void __init at91_add_device_cf(struct at91_cf_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91RM9200) || defined(CONFIG_MMC_AT91RM9200_MODULE) +static u64 mmc_dmamask = 0xffffffffUL; +static struct at91_mmc_data mmc_data; + +static struct resource at91_mmc_resources[] = { + { + .start = AT91_BASE_MCI, + .end = AT91_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91rm9200_mmc_device = { + .name = "at91rm9200_mci", + .id = -1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc_data, + }, + .resource = at91_mmc_resources, + .num_resources = ARRAY_SIZE(at91_mmc_resources), +}; + +void __init at91_add_device_mmc(struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA27, 0); + + if (data->is_b) { + /* CMD */ + at91_set_B_periph(AT91_PIN_PA8, 0); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA9, 0); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PA10, 0); + at91_set_B_periph(AT91_PIN_PA11, 0); + at91_set_B_periph(AT91_PIN_PA12, 0); + } + } else { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA28, 0); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA29, 0); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PB3, 0); + at91_set_B_periph(AT91_PIN_PB4, 0); + at91_set_B_periph(AT91_PIN_PB5, 0); + } + } + + mmc_data = *data; + platform_device_register(&at91rm9200_mmc_device); +} +#else +void __init at91_add_device_mmc(struct at91_mmc_data *data) {} +#endif + +/* -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h new file mode 100644 index 000000000000..9bd541eba0a0 --- /dev/null +++ b/arch/arm/mach-at91rm9200/generic.h @@ -0,0 +1,18 @@ +/* + * linux/arch/arm/mach-at91rm9200/generic.h + * + * Copyright (C) 2005 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +void at91_gpio_irq_setup(unsigned banks); + +struct sys_timer; +extern struct sys_timer at91rm9200_timer; + +extern void __init at91rm9200_map_io(void); + +extern int __init at91_clock_init(unsigned long main_clock); diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c new file mode 100644 index 000000000000..2fd2ef583e4d --- /dev/null +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -0,0 +1,302 @@ +/* + * linux/arch/arm/mach-at91rm9200/gpio.c + * + * Copyright (C) 2005 HP 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. + */ + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/module.h> + +#include <asm/io.h> +#include <asm/mach/irq.h> +#include <asm/arch/hardware.h> +#include <asm/arch/gpio.h> + +static const u32 pio_controller_offset[4] = { + AT91_PIOA, + AT91_PIOB, + AT91_PIOC, + AT91_PIOD, +}; + +static inline void __iomem *pin_to_controller(unsigned pin) +{ + void __iomem *sys_base = (void __iomem *) AT91_VA_BASE_SYS; + + pin -= PIN_BASE; + pin /= 32; + if (likely(pin < BGA_GPIO_BANKS)) + return sys_base + pio_controller_offset[pin]; + + return NULL; +} + +static inline unsigned pin_to_mask(unsigned pin) +{ + pin -= PIN_BASE; + return 1 << (pin % 32); +} + + +/*--------------------------------------------------------------------------*/ + +/* Not all hardware capabilities are exposed through these calls; they + * only encapsulate the most common features and modes. (So if you + * want to change signals in groups, do it directly.) + * + * Bootloaders will usually handle some of the pin multiplexing setup. + * The intent is certainly that by the time Linux is fully booted, all + * pins should have been fully initialized. These setup calls should + * only be used by board setup routines, or possibly in driver probe(). + * + * For bootloaders doing all that setup, these calls could be inlined + * as NOPs so Linux won't duplicate any setup code + */ + + +/* + * mux the pin to the "A" internal peripheral role. + */ +int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + + __raw_writel(mask, pio + PIO_IDR); + __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); + __raw_writel(mask, pio + PIO_ASR); + __raw_writel(mask, pio + PIO_PDR); + return 0; +} +EXPORT_SYMBOL(at91_set_A_periph); + + +/* + * mux the pin to the "B" internal peripheral role. + */ +int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + + __raw_writel(mask, pio + PIO_IDR); + __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); + __raw_writel(mask, pio + PIO_BSR); + __raw_writel(mask, pio + PIO_PDR); + return 0; +} +EXPORT_SYMBOL(at91_set_B_periph); + + +/* + * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and + * configure it for an input. + */ +int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + + __raw_writel(mask, pio + PIO_IDR); + __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); + __raw_writel(mask, pio + PIO_ODR); + __raw_writel(mask, pio + PIO_PER); + return 0; +} +EXPORT_SYMBOL(at91_set_gpio_input); + + +/* + * mux the pin to the gpio controller (instead of "A" or "B" peripheral), + * and configure it for an output. + */ +int __init_or_module at91_set_gpio_output(unsigned pin, int value) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + + __raw_writel(mask, pio + PIO_IDR); + __raw_writel(mask, pio + PIO_PUDR); + __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR)); + __raw_writel(mask, pio + PIO_OER); + __raw_writel(mask, pio + PIO_PER); + return 0; +} +EXPORT_SYMBOL(at91_set_gpio_output); + + +/* + * enable/disable the glitch filter; mostly used with IRQ handling. + */ +int __init_or_module at91_set_deglitch(unsigned pin, int is_on) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR)); + return 0; +} +EXPORT_SYMBOL(at91_set_deglitch); + +/*--------------------------------------------------------------------------*/ + + +/* + * assuming the pin is muxed as a gpio output, set its value. + */ +int at91_set_gpio_value(unsigned pin, int value) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (!pio) + return -EINVAL; + __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR)); + return 0; +} +EXPORT_SYMBOL(at91_set_gpio_value); + + +/* + * read the pin's value (works even if it's not muxed as a gpio). + */ +int at91_get_gpio_value(unsigned pin) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + u32 pdsr; + + if (!pio) + return -EINVAL; + pdsr = __raw_readl(pio + PIO_PDSR); + return (pdsr & mask) != 0; +} +EXPORT_SYMBOL(at91_get_gpio_value); + +/*--------------------------------------------------------------------------*/ + + +/* Several AIC controller irqs are dispatched through this GPIO handler. + * To use any AT91_PIN_* as an externally triggered IRQ, first call + * at91_set_gpio_input() then maybe enable its glitch filter. + * Then just request_irq() with the pin ID; it works like any ARM IRQ + * handler, though it always triggers on rising and falling edges. + * + * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after + * configuring them with at91_set_a_periph() or at91_set_b_periph(). + * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering. + */ + +static void gpio_irq_mask(unsigned pin) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio) + __raw_writel(mask, pio + PIO_IDR); +} + +static void gpio_irq_unmask(unsigned pin) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio) + __raw_writel(mask, pio + PIO_IER); +} + +static int gpio_irq_type(unsigned pin, unsigned type) +{ + return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL; +} + +static struct irqchip gpio_irqchip = { + .mask = gpio_irq_mask, + .unmask = gpio_irq_unmask, + .set_type = gpio_irq_type, +}; + +static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs) +{ + unsigned pin; + struct irqdesc *gpio; + void __iomem *pio; + u32 isr; + + pio = (void __force __iomem *) desc->chipdata; + + /* temporarily mask (level sensitive) parent IRQ */ + desc->chip->ack(irq); + for (;;) { + isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR); + if (!isr) + break; + + pin = (unsigned) desc->data; + gpio = &irq_desc[pin]; + + while (isr) { + if (isr & 1) + gpio->handle(pin, gpio, regs); + pin++; + gpio++; + isr >>= 1; + } + } + desc->chip->unmask(irq); + /* now it may re-trigger */ +} + +/* call this from board-specific init_irq */ +void __init at91_gpio_irq_setup(unsigned banks) +{ + unsigned pioc, pin, id; + + if (banks > 4) + banks = 4; + for (pioc = 0, pin = PIN_BASE, id = AT91_ID_PIOA; + pioc < banks; + pioc++, id++) { + void __iomem *controller; + unsigned i; + + controller = (void __iomem *) AT91_VA_BASE_SYS + pio_controller_offset[pioc]; + __raw_writel(~0, controller + PIO_IDR); + + set_irq_data(id, (void *) pin); + set_irq_chipdata(id, (void __force *) controller); + + for (i = 0; i < 32; i++, pin++) { + set_irq_chip(pin, &gpio_irqchip); + set_irq_handler(pin, do_simple_IRQ); + set_irq_flags(pin, IRQF_VALID); + } + + set_irq_chained_handler(id, gpio_irq_handler); + + /* enable the PIO peripheral clock */ + at91_sys_write(AT91_PMC_PCER, 1 << id); + } + pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks); +} diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c new file mode 100644 index 000000000000..cb62bc83a1dd --- /dev/null +++ b/arch/arm/mach-at91rm9200/irq.c @@ -0,0 +1,170 @@ +/* + * linux/arch/arm/mach-at91rm9200/irq.c + * + * Copyright (C) 2004 SAN People + * Copyright (C) 2004 ATMEL + * Copyright (C) Rick Bronson + * + * 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/config.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/types.h> + +#include <asm/hardware.h> +#include <asm/irq.h> +#include <asm/mach-types.h> +#include <asm/setup.h> + +#include <asm/mach/arch.h> +#include <asm/mach/irq.h> +#include <asm/mach/map.h> + +#include "generic.h" + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller */ + 7, /* System Peripheral */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C */ + 0, /* Parallel IO Controller D */ + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 6, /* USART 3 */ + 0, /* Multimedia Card Interface */ + 4, /* USB Device Port */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface */ + 5, /* Serial Synchronous Controller */ + 5, /* Serial Synchronous Controller */ + 5, /* Serial Synchronous Controller */ + 0, /* Timer Counter 0 */ + 0, /* Timer Counter 1 */ + 0, /* Timer Counter 2 */ + 0, /* Timer Counter 3 */ + 0, /* Timer Counter 4 */ + 0, /* Timer Counter 5 */ + 3, /* USB Host port */ + 3, /* Ethernet MAC */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0 /* Advanced Interrupt Controller */ +}; + + +static void at91rm9200_mask_irq(unsigned int irq) +{ + /* Disable interrupt on AIC */ + at91_sys_write(AT91_AIC_IDCR, 1 << irq); +} + +static void at91rm9200_unmask_irq(unsigned int irq) +{ + /* Enable interrupt on AIC */ + at91_sys_write(AT91_AIC_IECR, 1 << irq); +} + +static int at91rm9200_irq_type(unsigned irq, unsigned type) +{ + unsigned int smr, srctype; + + /* change triggering only for FIQ and external IRQ0..IRQ6 */ + if ((irq < AT91_ID_IRQ0) && (irq != AT91_ID_FIQ)) + return -EINVAL; + + switch (type) { + case IRQT_HIGH: + srctype = AT91_AIC_SRCTYPE_HIGH; + break; + case IRQT_RISING: + srctype = AT91_AIC_SRCTYPE_RISING; + break; + case IRQT_LOW: + srctype = AT91_AIC_SRCTYPE_LOW; + break; + case IRQT_FALLING: + srctype = AT91_AIC_SRCTYPE_FALLING; + break; + default: + return -EINVAL; + } + + smr = at91_sys_read(AT91_AIC_SMR(irq)) & ~AT91_AIC_SRCTYPE; + at91_sys_write(AT91_AIC_SMR(irq), smr | srctype); + return 0; +} + +static struct irqchip at91rm9200_irq_chip = { + .ack = at91rm9200_mask_irq, + .mask = at91rm9200_mask_irq, + .unmask = at91rm9200_unmask_irq, + .set_type = at91rm9200_irq_type, +}; + +/* + * Initialize the AIC interrupt controller. + */ +void __init at91rm9200_init_irq(unsigned int priority[NR_AIC_IRQS]) +{ + unsigned int i; + + /* No priority list specified for this board -> use defaults */ + if (priority == NULL) + priority = at91rm9200_default_irq_priority; + + /* + * The IVR is used by macro get_irqnr_and_base to read and verify. + * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred. + */ + for (i = 0; i < NR_AIC_IRQS; i++) { + /* Put irq number in Source Vector Register: */ + at91_sys_write(AT91_AIC_SVR(i), i); + /* Store the Source Mode Register as defined in table above */ + at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); + + set_irq_chip(i, &at91rm9200_irq_chip); + set_irq_handler(i, do_level_IRQ); + set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + + /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */ + if (i < 8) + at91_sys_write(AT91_AIC_EOICR, 0); + } + + /* + * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS + * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU + */ + at91_sys_write(AT91_AIC_SPU, NR_AIC_IRQS); + + /* No debugging in AIC: Debug (Protect) Control Register */ + at91_sys_write(AT91_AIC_DCR, 0); + + /* Disable and clear all interrupts initially */ + at91_sys_write(AT91_AIC_IDCR, 0xFFFFFFFF); + at91_sys_write(AT91_AIC_ICCR, 0xFFFFFFFF); +} diff --git a/arch/arm/mach-at91rm9200/time.c b/arch/arm/mach-at91rm9200/time.c new file mode 100644 index 000000000000..1b6dd2deeb22 --- /dev/null +++ b/arch/arm/mach-at91rm9200/time.c @@ -0,0 +1,127 @@ +/* + * linux/arch/arm/mach-at91rm9200/time.c + * + * Copyright (C) 2003 SAN People + * Copyright (C) 2003 ATMEL + * + * 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/config.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/mach/time.h> + +/* + * The ST_CRTR is updated asynchronously to the master clock. It is therefore + * necessary to read it twice (with the same value) to ensure accuracy. + */ +static inline unsigned long read_CRTR(void) { + unsigned long x1, x2; + + do { + x1 = at91_sys_read(AT91_ST_CRTR); + x2 = at91_sys_read(AT91_ST_CRTR); + } while (x1 != x2); + + return x1; +} + +/* + * Returns number of microseconds since last timer interrupt. Note that interrupts + * will have been disabled by do_gettimeofday() + * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. + * 'tick' is usecs per jiffy (linux/timex.h). + */ +static unsigned long at91rm9200_gettimeoffset(void) +{ + unsigned long elapsed; + + elapsed = (read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV; + + return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; +} + +/* + * IRQ handler for the timer. + */ +static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long rtar; + + if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */ + write_seqlock(&xtime_lock); + + do { + timer_tick(regs); + rtar = (at91_sys_read(AT91_ST_RTAR) + LATCH) & AT91_ST_ALMV; + at91_sys_write(AT91_ST_RTAR, rtar); + } while (((read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV) >= LATCH); + + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; + } + else + return IRQ_NONE; /* not handled */ +} + +static struct irqaction at91rm9200_timer_irq = { + .name = "at91_tick", + .flags = SA_SHIRQ | SA_INTERRUPT, + .handler = at91rm9200_timer_interrupt +}; + +/* + * Set up timer interrupt. + */ +void __init at91rm9200_timer_init(void) +{ + /* Disable all timer interrupts */ + at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); + (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */ + + /* + * Make IRQs happen for the system timer. + */ + setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); + + /* Set initial alarm to 0 */ + at91_sys_write(AT91_ST_RTAR, 0); + + /* Real time counter incremented every 30.51758 microseconds */ + at91_sys_write(AT91_ST_RTMR, 1); + + /* Set Period Interval timer */ + at91_sys_write(AT91_ST_PIMR, LATCH); + + /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */ + tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE; + + /* Enable Period Interval Timer interrupt */ + at91_sys_write(AT91_ST_IER, AT91_ST_PITS); +} + +struct sys_timer at91rm9200_timer = { + .init = at91rm9200_timer_init, + .offset = at91rm9200_gettimeoffset, +}; diff --git a/arch/arm/mach-epxa10db/Kconfig b/arch/arm/mach-epxa10db/Kconfig deleted file mode 100644 index 55d896dd4950..000000000000 --- a/arch/arm/mach-epxa10db/Kconfig +++ /dev/null @@ -1,23 +0,0 @@ -if ARCH_CAMELOT - -menu "Epxa10db" - -comment "PLD hotswap support" - -config PLD - bool - default y - -config PLD_HOTSWAP - bool "Support for PLD device hotplugging (experimental)" - depends on EXPERIMENTAL - help - This enables support for the dynamic loading and configuration of - compatible drivers when the contents of the PLD are changed. This - is still experimental and requires configuration tools which are - not yet generally available. Say N here. You must enable the kernel - module loader for this feature to work. - -endmenu - -endif diff --git a/arch/arm/mach-epxa10db/Makefile b/arch/arm/mach-epxa10db/Makefile deleted file mode 100644 index 24fbd7d3a3c1..000000000000 --- a/arch/arm/mach-epxa10db/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# Object file lists. - -obj-y := arch.o irq.o mm.o time.o -obj-m := -obj-n := -obj- := - diff --git a/arch/arm/mach-epxa10db/Makefile.boot b/arch/arm/mach-epxa10db/Makefile.boot deleted file mode 100644 index 28bec7d3fc88..000000000000 --- a/arch/arm/mach-epxa10db/Makefile.boot +++ /dev/null @@ -1,2 +0,0 @@ - zreladdr-y := 0x00008000 - diff --git a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c deleted file mode 100644 index 44c56571d183..000000000000 --- a/arch/arm/mach-epxa10db/arch.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * linux/arch/arm/mach-epxa10db/arch.c - * - * Copyright (C) 2000 Deep Blue Solutions Ltd - * Copyright (C) 2001 Altera Corporation - * - * 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/types.h> -#include <linux/init.h> -#include <linux/serial_8250.h> - -#include <asm/hardware.h> -#include <asm/setup.h> -#include <asm/mach-types.h> - -#include <asm/mach/arch.h> - -static struct plat_serial8250_port serial_platform_data[] = { - { - .iobase = 0x3f8, - .irq = IRQ_UARTINT0, -#error FIXME - .uartclk = 0, - .regshift = 0, - .iotype = UPIO_PORT, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, - }, - { - .iobase = 0x2f8, - .irq = IRQ_UARTINT1, -#error FIXME - .uartclk = 0, - .regshift = 0, - .iotype = UPIO_PORT, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, - }, - { }, -}; - -static struct platform_device serial_device = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM, - .dev = { - .platform_data = serial_platform_data, - }, -}; - -extern void epxa10db_map_io(void); -extern void epxa10db_init_irq(void); -extern struct sys_timer epxa10db_timer; - -MACHINE_START(CAMELOT, "Altera Epxa10db") - /* Maintainer: Altera Corporation */ - .phys_ram = 0x00000000, - .phys_io = 0x7fffc000, - .io_pg_offst = ((0xffffc000) >> 18) & 0xfffc, - .map_io = epxa10db_map_io, - .init_irq = epxa10db_init_irq, - .timer = &epxa10db_timer, -MACHINE_END - diff --git a/arch/arm/mach-epxa10db/irq.c b/arch/arm/mach-epxa10db/irq.c deleted file mode 100644 index 9bf927e13309..000000000000 --- a/arch/arm/mach-epxa10db/irq.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * linux/arch/arm/mach-epxa10db/irq.c - * - * Copyright (C) 2001 Altera Corporation - * - * 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/ioport.h> -#include <linux/stddef.h> -#include <linux/timer.h> -#include <linux/list.h> -#include <asm/io.h> -#include <asm/hardware.h> -#include <asm/irq.h> -#include <asm/mach/irq.h> -#include <asm/arch/platform.h> -#include <asm/arch/int_ctrl00.h> - - -static void epxa_mask_irq(unsigned int irq) -{ - writel(1 << irq, INT_MC(IO_ADDRESS(EXC_INT_CTRL00_BASE))); -} - -static void epxa_unmask_irq(unsigned int irq) -{ - writel(1 << irq, INT_MS(IO_ADDRESS(EXC_INT_CTRL00_BASE))); -} - - -static struct irqchip epxa_irq_chip = { - .ack = epxa_mask_irq, - .mask = epxa_mask_irq, - .unmask = epxa_unmask_irq, -}; - -static struct resource irq_resource = { - .name = "irq_handler", - .start = IO_ADDRESS(EXC_INT_CTRL00_BASE), - .end = IO_ADDRESS(INT_PRIORITY_FC(EXC_INT_CTRL00_BASE))+4, -}; - -void __init epxa10db_init_irq(void) -{ - unsigned int i; - - request_resource(&iomem_resource, &irq_resource); - - /* - * This bit sets up the interrupt controller using - * the 6 PLD interrupts mode (the default) each - * irqs is assigned a priority which is the same - * as its interrupt number. This scheme is used because - * its easy, but you may want to change it depending - * on the contents of your PLD - */ - - writel(3,INT_MODE(IO_ADDRESS(EXC_INT_CTRL00_BASE))); - for (i = 0; i < NR_IRQS; i++){ - writel(i+1, INT_PRIORITY_P0(IO_ADDRESS(EXC_INT_CTRL00_BASE)) + (4*i)); - set_irq_chip(i,&epxa_irq_chip); - set_irq_handler(i,do_level_IRQ); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); - } - - /* Disable all interrupts */ - writel(-1,INT_MC(IO_ADDRESS(EXC_INT_CTRL00_BASE))); - -} diff --git a/arch/arm/mach-epxa10db/mm.c b/arch/arm/mach-epxa10db/mm.c deleted file mode 100644 index cfd0d2182d44..000000000000 --- a/arch/arm/mach-epxa10db/mm.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * linux/arch/arm/mach-epxa10db/mm.c - * - * MM routines for Altera'a Epxa10db board - * - * Copyright (C) 2001 Altera Corporation - * - * 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/kernel.h> -#include <linux/init.h> - -#include <asm/hardware.h> -#include <asm/io.h> -#include <asm/sizes.h> -#include <asm/page.h> - -#include <asm/mach/map.h> - -/* Page table mapping for I/O region */ - -static struct map_desc epxa10db_io_desc[] __initdata = { - { - .virtual = IO_ADDRESS(EXC_REGISTERS_BASE), - .pfn = __phys_to_pfn(EXC_REGISTERS_BASE), - .length = SZ_16K, - .type = MT_DEVICE - }, { - .virtual = IO_ADDRESS(EXC_PLD_BLOCK0_BASE), - .pfn = __phys_to_pfn(EXC_PLD_BLOCK0_BASE), - .length = SZ_16K, - .type = MT_DEVICE - }, { - .virtual = IO_ADDRESS(EXC_PLD_BLOCK1_BASE), - .pfn =__phys_to_pfn(EXC_PLD_BLOCK1_BASE), - .length = SZ_16K, - .type = MT_DEVICE - }, { - .virtual = IO_ADDRESS(EXC_PLD_BLOCK2_BASE), - .physical = __phys_to_pfn(EXC_PLD_BLOCK2_BASE), - .length = SZ_16K, - .type = MT_DEVICE - }, { - .virtual = IO_ADDRESS(EXC_PLD_BLOCK3_BASE), - .pfn = __phys_to_pfn(EXC_PLD_BLOCK3_BASE), - .length = SZ_16K, - .type = MT_DEVICE - }, { - .virtual = FLASH_VADDR(EXC_EBI_BLOCK0_BASE), - .pfn = __phys_to_pfn(EXC_EBI_BLOCK0_BASE), - .length = SZ_16M, - .type = MT_DEVICE - } -}; - -void __init epxa10db_map_io(void) -{ - iotable_init(epxa10db_io_desc, ARRAY_SIZE(epxa10db_io_desc)); -} diff --git a/arch/arm/mach-epxa10db/time.c b/arch/arm/mach-epxa10db/time.c deleted file mode 100644 index 4b1084dde8dd..000000000000 --- a/arch/arm/mach-epxa10db/time.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * linux/arch/arm/mach-epxa10db/time.c - * - * Copyright (C) 2000 Deep Blue Solutions - * Copyright (C) 2001 Altera Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/sched.h> - -#include <asm/hardware.h> -#include <asm/system.h> -#include <asm/leds.h> - -#include <asm/mach/time.h> - -#define TIMER00_TYPE (volatile unsigned int*) -#include <asm/arch/timer00.h> - -static int epxa10db_set_rtc(void) -{ - return 1; -} - -static int epxa10db_rtc_init(void) -{ - set_rtc = epxa10db_set_rtc; - - return 0; -} - -__initcall(epxa10db_rtc_init); - - -/* - * IRQ handler for the timer - */ -static irqreturn_t -epxa10db_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - write_seqlock(&xtime_lock); - - // ...clear the interrupt - *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))|=TIMER0_CR_CI_MSK; - - timer_tick(regs); - write_sequnlock(&xtime_lock); - - return IRQ_HANDLED; -} - -static struct irqaction epxa10db_timer_irq = { - .name = "Excalibur Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, - .handler = epxa10db_timer_interrupt, -}; - -/* - * Set up timer interrupt, and return the current time in seconds. - */ -static void __init epxa10db_timer_init(void) -{ - /* Start the timer */ - *TIMER0_LIMIT(IO_ADDRESS(EXC_TIMER00_BASE))=(unsigned int)(EXC_AHB2_CLK_FREQUENCY/200); - *TIMER0_PRESCALE(IO_ADDRESS(EXC_TIMER00_BASE))=1; - *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))=TIMER0_CR_IE_MSK | TIMER0_CR_S_MSK; - - setup_irq(IRQ_TIMER0, &epxa10db_timer_irq); -} - -struct sys_timer epxa10db_timer = { - .init = epxa10db_timer_init, -}; diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index bd900b7ab33c..92ff5dc07351 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c @@ -184,7 +184,7 @@ static void __init omap_perseus2_map_io(void) omap_writel(0x00000088, OMAP730_FLASH_ACFG_0); /* - * Ethernet support trough the debug board + * Ethernet support through the debug board * CS1 timings setup */ omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1); diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index 5830ae3ddd19..fc09ba92d66a 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -253,100 +253,101 @@ struct clk s3c24xx_uclk = { /* clock definitions */ static struct clk init_clocks[] = { - { .name = "nand", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_NAND - }, - { .name = "lcd", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_LCDC - }, - { .name = "usb-host", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBH - }, - { .name = "usb-device", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBD - }, - { .name = "timers", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_PWMT - }, - { .name = "sdi", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SDI - }, - { .name = "uart", - .id = 0, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART0 - }, - { .name = "uart", - .id = 1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART1 - }, - { .name = "uart", - .id = 2, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART2 - }, - { .name = "gpio", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_GPIO - }, - { .name = "rtc", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_RTC - }, - { .name = "adc", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_ADC - }, - { .name = "i2c", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIC - }, - { .name = "iis", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIS - }, - { .name = "spi", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SPI - }, - { .name = "watchdog", - .id = -1, - .parent = &clk_p, - .ctrlbit = 0 + { + .name = "nand", + .id = -1, + .parent = &clk_h, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_NAND, + }, { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_LCDC, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_USBH, + }, { + .name = "usb-device", + .id = -1, + .parent = &clk_h, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_USBD, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_PWMT, + }, { + .name = "sdi", + .id = -1, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_SDI, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART2, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_GPIO, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_RTC, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_ADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_IIC, + }, { + .name = "iis", + .id = -1, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_IIS, + }, { + .name = "spi", + .id = -1, + .parent = &clk_p, + .enable = s3c24xx_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_SPI, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = 0, } }; @@ -390,16 +391,15 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, clk_p.rate = pclk; clk_f.rate = fclk; - /* it looks like just setting the register here is not good - * enough, and causes the odd hang at initial boot time, so - * do all of them indivdually. + /* We must be careful disabling the clocks we are not intending to + * be using at boot time, as subsytems such as the LCD which do + * their own DMA requests to the bus can cause the system to lockup + * if they where in the middle of requesting bus access. * - * I think disabling the LCD clock if the LCD is active is - * very dangerous, and therefore the bootloader should be - * careful to not enable the LCD clock if it is not needed. - * - * and of course, this looks neater - */ + * Disabling the LCD clock if the LCD is active is very dangerous, + * and therefore the bootloader should be careful to not enable + * the LCD clock if it is not needed. + */ s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0); s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index e84fdde6edf8..3b79d0e23455 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -62,8 +62,8 @@ config CPU_ARM720T # ARM920T config CPU_ARM920T bool "Support ARM920T processor" if !ARCH_S3C2410 - depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 - default y if ARCH_S3C2410 + depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200 + default y if ARCH_S3C2410 || ARCH_AT91RM9200 select CPU_32v4 select CPU_ABRT_EV4T select CPU_CACHE_V4WT @@ -83,8 +83,8 @@ config CPU_ARM920T # ARM922T config CPU_ARM922T bool "Support ARM922T processor" if ARCH_INTEGRATOR - depends on ARCH_CAMELOT || ARCH_LH7A40X || ARCH_INTEGRATOR - default y if ARCH_CAMELOT || ARCH_LH7A40X + depends on ARCH_LH7A40X || ARCH_INTEGRATOR + default y if ARCH_LH7A40X select CPU_32v4 select CPU_ABRT_EV4T select CPU_CACHE_V4WT diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 10901398e4a2..de3ce1eec2ec 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -86,11 +86,12 @@ remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, } static int -remap_area_pages(unsigned long start, unsigned long phys_addr, +remap_area_pages(unsigned long start, unsigned long pfn, unsigned long size, unsigned long flags) { unsigned long address = start; unsigned long end = start + size; + unsigned long phys_addr = __pfn_to_phys(pfn); int err = 0; pgd_t * dir; @@ -130,36 +131,44 @@ remap_area_pages(unsigned long start, unsigned long phys_addr, * mapping. See include/asm-arm/proc-armv/pgtable.h for more information. */ void __iomem * +__ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, + unsigned long flags) +{ + unsigned long addr; + struct vm_struct * area; + + area = get_vm_area(size, VM_IOREMAP); + if (!area) + return NULL; + addr = (unsigned long)area->addr; + if (remap_area_pages(addr, pfn, size, flags)) { + vfree(addr); + return NULL; + } + return (void __iomem *) (offset + (char *)addr); +} +EXPORT_SYMBOL(__ioremap_pfn); + +void __iomem * __ioremap(unsigned long phys_addr, size_t size, unsigned long flags) { - void * addr; - struct vm_struct * area; - unsigned long offset, last_addr; + unsigned long last_addr; + unsigned long offset = phys_addr & ~PAGE_MASK; + unsigned long pfn = __phys_to_pfn(phys_addr); - /* Don't allow wraparound or zero size */ + /* + * Don't allow wraparound or zero size + */ last_addr = phys_addr + size - 1; if (!size || last_addr < phys_addr) return NULL; /* - * Mappings have to be page-aligned + * Page align the mapping size */ - offset = phys_addr & ~PAGE_MASK; - phys_addr &= PAGE_MASK; size = PAGE_ALIGN(last_addr + 1) - phys_addr; - /* - * Ok, go for it.. - */ - area = get_vm_area(size, VM_IOREMAP); - if (!area) - return NULL; - addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { - vfree(addr); - return NULL; - } - return (void __iomem *) (offset + (char *)addr); + return __ioremap_pfn(pfn, offset, size, flags); } EXPORT_SYMBOL(__ioremap); diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 465487470d0e..d0f9bb5e9023 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Fri Nov 25 14:43:04 2005 +# Last update: Mon Jan 9 12:56:42 2006 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -910,3 +910,31 @@ mbus MACH_MBUS MBUS 896 nadia2vb MACH_NADIA2VB NADIA2VB 897 r1000 MACH_R1000 R1000 898 hw90250 MACH_HW90250 HW90250 899 +omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900 +davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901 +omap_tornado MACH_OMAP_TORNADO OMAP_TORNADO 902 +olocreek MACH_OLOCREEK OLOCREEK 903 +palmz72 MACH_PALMZ72 PALMZ72 904 +nxdb500 MACH_NXDB500 NXDB500 905 +apf9328 MACH_APF9328 APF9328 906 +omap_wipoq MACH_OMAP_WIPOQ OMAP_WIPOQ 907 +omap_twip MACH_OMAP_TWIP OMAP_TWIP 908 +xscale_treo650 MACH_XSCALE_PALMTREO650 XSCALE_PALMTREO650 909 +acumen MACH_ACUMEN ACUMEN 910 +xp100 MACH_XP100 XP100 911 +fs2410 MACH_FS2410 FS2410 912 +pxa270_cerf MACH_PXA270_CERF PXA270_CERF 913 +sq2ftlpalm MACH_SQ2FTLPALM SQ2FTLPALM 914 +bsemserver MACH_BSEMSERVER BSEMSERVER 915 +netclient MACH_NETCLIENT NETCLIENT 916 +xscale_palmtt5 MACH_XSCALE_PALMTT5 XSCALE_PALMTT5 917 +xscale_palmtc MACH_OMAP_PALMTC OMAP_PALMTC 918 +omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919 +argonlvevb MACH_ARGONLVEVB ARGONLVEVB 920 +rea_2d MACH_REA_2D REA_2D 921 +eti3e524 MACH_TI3E524 TI3E524 922 +ateb9200 MACH_ATEB9200 ATEB9200 923 +auckland MACH_AUCKLAND AUCKLAND 924 +ak3220m MACH_AK3320M AK3320M 925 +duramax MACH_DURAMAX DURAMAX 926 +n35 MACH_N35 N35 927 diff --git a/arch/i386/crypto/aes-i586-asm.S b/arch/i386/crypto/aes-i586-asm.S index 7b73c67cb4e8..911b15377f2e 100644 --- a/arch/i386/crypto/aes-i586-asm.S +++ b/arch/i386/crypto/aes-i586-asm.S @@ -255,18 +255,17 @@ aes_enc_blk: xor 8(%ebp),%r4 xor 12(%ebp),%r5 - sub $8,%esp // space for register saves on stack - add $16,%ebp // increment to next round key - sub $10,%r3 - je 4f // 10 rounds for 128-bit key - add $32,%ebp - sub $2,%r3 - je 3f // 12 rounds for 128-bit key - add $32,%ebp - -2: fwd_rnd1( -64(%ebp) ,ft_tab) // 14 rounds for 128-bit key + sub $8,%esp // space for register saves on stack + add $16,%ebp // increment to next round key + cmp $12,%r3 + jb 4f // 10 rounds for 128-bit key + lea 32(%ebp),%ebp + je 3f // 12 rounds for 192-bit key + lea 32(%ebp),%ebp + +2: fwd_rnd1( -64(%ebp) ,ft_tab) // 14 rounds for 256-bit key fwd_rnd2( -48(%ebp) ,ft_tab) -3: fwd_rnd1( -32(%ebp) ,ft_tab) // 12 rounds for 128-bit key +3: fwd_rnd1( -32(%ebp) ,ft_tab) // 12 rounds for 192-bit key fwd_rnd2( -16(%ebp) ,ft_tab) 4: fwd_rnd1( (%ebp) ,ft_tab) // 10 rounds for 128-bit key fwd_rnd2( +16(%ebp) ,ft_tab) @@ -334,18 +333,17 @@ aes_dec_blk: xor 8(%ebp),%r4 xor 12(%ebp),%r5 - sub $8,%esp // space for register saves on stack - sub $16,%ebp // increment to next round key - sub $10,%r3 - je 4f // 10 rounds for 128-bit key - sub $32,%ebp - sub $2,%r3 - je 3f // 12 rounds for 128-bit key - sub $32,%ebp + sub $8,%esp // space for register saves on stack + sub $16,%ebp // increment to next round key + cmp $12,%r3 + jb 4f // 10 rounds for 128-bit key + lea -32(%ebp),%ebp + je 3f // 12 rounds for 192-bit key + lea -32(%ebp),%ebp -2: inv_rnd1( +64(%ebp), it_tab) // 14 rounds for 128-bit key +2: inv_rnd1( +64(%ebp), it_tab) // 14 rounds for 256-bit key inv_rnd2( +48(%ebp), it_tab) -3: inv_rnd1( +32(%ebp), it_tab) // 12 rounds for 128-bit key +3: inv_rnd1( +32(%ebp), it_tab) // 12 rounds for 192-bit key inv_rnd2( +16(%ebp), it_tab) 4: inv_rnd1( (%ebp), it_tab) // 10 rounds for 128-bit key inv_rnd2( -16(%ebp), it_tab) diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c index 88ee85c3b43b..a50397b1d5c7 100644 --- a/arch/i386/crypto/aes.c +++ b/arch/i386/crypto/aes.c @@ -36,6 +36,8 @@ * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> * */ + +#include <asm/byteorder.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -59,7 +61,6 @@ struct aes_ctx { }; #define WPOLY 0x011b -#define u32_in(x) le32_to_cpup((const __le32 *)(x)) #define bytes2word(b0, b1, b2, b3) \ (((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0)) @@ -93,7 +94,6 @@ static u32 rcon_tab[RC_LENGTH]; u32 ft_tab[4][256]; u32 fl_tab[4][256]; -static u32 ls_tab[4][256]; static u32 im_tab[4][256]; u32 il_tab[4][256]; u32 it_tab[4][256]; @@ -144,15 +144,6 @@ static void gen_tabs(void) fl_tab[2][i] = upr(w, 2); fl_tab[3][i] = upr(w, 3); - /* - * table for key schedule if fl_tab above is - * not of the required form - */ - ls_tab[0][i] = w; - ls_tab[1][i] = upr(w, 1); - ls_tab[2][i] = upr(w, 2); - ls_tab[3][i] = upr(w, 3); - b = fi(inv_affine((u8)i)); w = bytes2word(fe(b), f9(b), fd(b), fb(b)); @@ -393,13 +384,14 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) int i; u32 ss[8]; struct aes_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; /* encryption schedule */ - ctx->ekey[0] = ss[0] = u32_in(in_key); - ctx->ekey[1] = ss[1] = u32_in(in_key + 4); - ctx->ekey[2] = ss[2] = u32_in(in_key + 8); - ctx->ekey[3] = ss[3] = u32_in(in_key + 12); + ctx->ekey[0] = ss[0] = le32_to_cpu(key[0]); + ctx->ekey[1] = ss[1] = le32_to_cpu(key[1]); + ctx->ekey[2] = ss[2] = le32_to_cpu(key[2]); + ctx->ekey[3] = ss[3] = le32_to_cpu(key[3]); switch(key_len) { case 16: @@ -410,8 +402,8 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 24: - ctx->ekey[4] = ss[4] = u32_in(in_key + 16); - ctx->ekey[5] = ss[5] = u32_in(in_key + 20); + ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]); + ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]); for (i = 0; i < 7; i++) ke6(ctx->ekey, i); kel6(ctx->ekey, 7); @@ -419,10 +411,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 32: - ctx->ekey[4] = ss[4] = u32_in(in_key + 16); - ctx->ekey[5] = ss[5] = u32_in(in_key + 20); - ctx->ekey[6] = ss[6] = u32_in(in_key + 24); - ctx->ekey[7] = ss[7] = u32_in(in_key + 28); + ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]); + ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]); + ctx->ekey[6] = ss[6] = le32_to_cpu(key[6]); + ctx->ekey[7] = ss[7] = le32_to_cpu(key[7]); for (i = 0; i < 6; i++) ke8(ctx->ekey, i); kel8(ctx->ekey, 6); @@ -436,10 +428,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) /* decryption schedule */ - ctx->dkey[0] = ss[0] = u32_in(in_key); - ctx->dkey[1] = ss[1] = u32_in(in_key + 4); - ctx->dkey[2] = ss[2] = u32_in(in_key + 8); - ctx->dkey[3] = ss[3] = u32_in(in_key + 12); + ctx->dkey[0] = ss[0] = le32_to_cpu(key[0]); + ctx->dkey[1] = ss[1] = le32_to_cpu(key[1]); + ctx->dkey[2] = ss[2] = le32_to_cpu(key[2]); + ctx->dkey[3] = ss[3] = le32_to_cpu(key[3]); switch (key_len) { case 16: @@ -450,8 +442,8 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 24: - ctx->dkey[4] = ff(ss[4] = u32_in(in_key + 16)); - ctx->dkey[5] = ff(ss[5] = u32_in(in_key + 20)); + ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4])); + ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5])); kdf6(ctx->dkey, 0); for (i = 1; i < 7; i++) kd6(ctx->dkey, i); @@ -459,10 +451,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 32: - ctx->dkey[4] = ff(ss[4] = u32_in(in_key + 16)); - ctx->dkey[5] = ff(ss[5] = u32_in(in_key + 20)); - ctx->dkey[6] = ff(ss[6] = u32_in(in_key + 24)); - ctx->dkey[7] = ff(ss[7] = u32_in(in_key + 28)); + ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4])); + ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5])); + ctx->dkey[6] = ff(ss[6] = le32_to_cpu(key[6])); + ctx->dkey[7] = ff(ss[7] = le32_to_cpu(key[7])); kdf8(ctx->dkey, 0); for (i = 1; i < 6; i++) kd8(ctx->dkey, i); @@ -484,6 +476,8 @@ static inline void aes_decrypt(void *ctx, u8 *dst, const u8 *src) static struct crypto_alg aes_alg = { .cra_name = "aes", + .cra_driver_name = "aes-i586", + .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), diff --git a/arch/i386/kernel/cpu/changelog b/arch/i386/kernel/cpu/changelog deleted file mode 100644 index cef76b80a710..000000000000 --- a/arch/i386/kernel/cpu/changelog +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Enhanced CPU type detection by Mike Jagdis, Patrick St. Jean - * and Martin Mares, November 1997. - * - * Force Cyrix 6x86(MX) and M II processors to report MTRR capability - * and Cyrix "coma bug" recognition by - * Zoltán Böszörményi <zboszor@mail.externet.hu> February 1999. - * - * Force Centaur C6 processors to report MTRR capability. - * Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999. - * - * Intel Mobile Pentium II detection fix. Sean Gilley, June 1999. - * - * IDT Winchip tweaks, misc clean ups. - * Dave Jones <davej@suse.de>, August 1999 - * - * Better detection of Centaur/IDT WinChip models. - * Bart Hartgers <bart@etpmod.phys.tue.nl>, August 1999. - * - * Cleaned up cache-detection code - * Dave Jones <davej@suse.de>, October 1999 - * - * Added proper L2 cache detection for Coppermine - * Dragan Stancevic <visitor@valinux.com>, October 1999 - * - * Added the original array for capability flags but forgot to credit - * myself :) (~1998) Fixed/cleaned up some cpu_model_info and other stuff - * Jauder Ho <jauderho@carumba.com>, January 2000 - * - * Detection for Celeron coppermine, identify_cpu() overhauled, - * and a few other clean ups. - * Dave Jones <davej@suse.de>, April 2000 - * - * Pentium III FXSR, SSE support - * General FPU state handling cleanups - * Gareth Hughes <gareth@valinux.com>, May 2000 - * - * Added proper Cascades CPU and L2 cache detection for Cascades - * and 8-way type cache happy bunch from Intel:^) - * Dragan Stancevic <visitor@valinux.com>, May 2000 - * - * Forward port AMD Duron errata T13 from 2.2.17pre - * Dave Jones <davej@suse.de>, August 2000 - * - * Forward port lots of fixes/improvements from 2.2.18pre - * Cyrix III, Pentium IV support. - * Dave Jones <davej@suse.de>, October 2000 - * - * Massive cleanup of CPU detection and bug handling; - * Transmeta CPU detection, - * H. Peter Anvin <hpa@zytor.com>, November 2000 - * - * VIA C3 Support. - * Dave Jones <davej@suse.de>, March 2001 - * - * AMD Athlon/Duron/Thunderbird bluesmoke support. - * Dave Jones <davej@suse.de>, April 2001. - * - * CacheSize bug workaround updates for AMD, Intel & VIA Cyrix. - * Dave Jones <davej@suse.de>, September, October 2001. - * - */ - diff --git a/arch/i386/kernel/cpu/mtrr/changelog b/arch/i386/kernel/cpu/mtrr/changelog deleted file mode 100644 index af1368535955..000000000000 --- a/arch/i386/kernel/cpu/mtrr/changelog +++ /dev/null @@ -1,229 +0,0 @@ - ChangeLog - - Prehistory Martin Tischhäuser <martin@ikcbarka.fzk.de> - Initial register-setting code (from proform-1.0). - 19971216 Richard Gooch <rgooch@atnf.csiro.au> - Original version for /proc/mtrr interface, SMP-safe. - v1.0 - 19971217 Richard Gooch <rgooch@atnf.csiro.au> - Bug fix for ioctls()'s. - Added sample code in Documentation/mtrr.txt - v1.1 - 19971218 Richard Gooch <rgooch@atnf.csiro.au> - Disallow overlapping regions. - 19971219 Jens Maurer <jmaurer@menuett.rhein-main.de> - Register-setting fixups. - v1.2 - 19971222 Richard Gooch <rgooch@atnf.csiro.au> - Fixups for kernel 2.1.75. - v1.3 - 19971229 David Wragg <dpw@doc.ic.ac.uk> - Register-setting fixups and conformity with Intel conventions. - 19971229 Richard Gooch <rgooch@atnf.csiro.au> - Cosmetic changes and wrote this ChangeLog ;-) - 19980106 Richard Gooch <rgooch@atnf.csiro.au> - Fixups for kernel 2.1.78. - v1.4 - 19980119 David Wragg <dpw@doc.ic.ac.uk> - Included passive-release enable code (elsewhere in PCI setup). - v1.5 - 19980131 Richard Gooch <rgooch@atnf.csiro.au> - Replaced global kernel lock with private spinlock. - v1.6 - 19980201 Richard Gooch <rgooch@atnf.csiro.au> - Added wait for other CPUs to complete changes. - v1.7 - 19980202 Richard Gooch <rgooch@atnf.csiro.au> - Bug fix in definition of <set_mtrr> for UP. - v1.8 - 19980319 Richard Gooch <rgooch@atnf.csiro.au> - Fixups for kernel 2.1.90. - 19980323 Richard Gooch <rgooch@atnf.csiro.au> - Move SMP BIOS fixup before secondary CPUs call <calibrate_delay> - v1.9 - 19980325 Richard Gooch <rgooch@atnf.csiro.au> - Fixed test for overlapping regions: confused by adjacent regions - 19980326 Richard Gooch <rgooch@atnf.csiro.au> - Added wbinvd in <set_mtrr_prepare>. - 19980401 Richard Gooch <rgooch@atnf.csiro.au> - Bug fix for non-SMP compilation. - 19980418 David Wragg <dpw@doc.ic.ac.uk> - Fixed-MTRR synchronisation for SMP and use atomic operations - instead of spinlocks. - 19980418 Richard Gooch <rgooch@atnf.csiro.au> - Differentiate different MTRR register classes for BIOS fixup. - v1.10 - 19980419 David Wragg <dpw@doc.ic.ac.uk> - Bug fix in variable MTRR synchronisation. - v1.11 - 19980419 Richard Gooch <rgooch@atnf.csiro.au> - Fixups for kernel 2.1.97. - v1.12 - 19980421 Richard Gooch <rgooch@atnf.csiro.au> - Safer synchronisation across CPUs when changing MTRRs. - v1.13 - 19980423 Richard Gooch <rgooch@atnf.csiro.au> - Bugfix for SMP systems without MTRR support. - v1.14 - 19980427 Richard Gooch <rgooch@atnf.csiro.au> - Trap calls to <mtrr_add> and <mtrr_del> on non-MTRR machines. - v1.15 - 19980427 Richard Gooch <rgooch@atnf.csiro.au> - Use atomic bitops for setting SMP change mask. - v1.16 - 19980428 Richard Gooch <rgooch@atnf.csiro.au> - Removed spurious diagnostic message. - v1.17 - 19980429 Richard Gooch <rgooch@atnf.csiro.au> - Moved register-setting macros into this file. - Moved setup code from init/main.c to i386-specific areas. - v1.18 - 19980502 Richard Gooch <rgooch@atnf.csiro.au> - Moved MTRR detection outside conditionals in <mtrr_init>. - v1.19 - 19980502 Richard Gooch <rgooch@atnf.csiro.au> - Documentation improvement: mention Pentium II and AGP. - v1.20 - 19980521 Richard Gooch <rgooch@atnf.csiro.au> - Only manipulate interrupt enable flag on local CPU. - Allow enclosed uncachable regions. - v1.21 - 19980611 Richard Gooch <rgooch@atnf.csiro.au> - Always define <main_lock>. - v1.22 - 19980901 Richard Gooch <rgooch@atnf.csiro.au> - Removed module support in order to tidy up code. - Added sanity check for <mtrr_add>/<mtrr_del> before <mtrr_init>. - Created addition queue for prior to SMP commence. - v1.23 - 19980902 Richard Gooch <rgooch@atnf.csiro.au> - Ported patch to kernel 2.1.120-pre3. - v1.24 - 19980910 Richard Gooch <rgooch@atnf.csiro.au> - Removed sanity checks and addition queue: Linus prefers an OOPS. - v1.25 - 19981001 Richard Gooch <rgooch@atnf.csiro.au> - Fixed harmless compiler warning in include/asm-i386/mtrr.h - Fixed version numbering and history for v1.23 -> v1.24. - v1.26 - 19990118 Richard Gooch <rgooch@atnf.csiro.au> - Added devfs support. - v1.27 - 19990123 Richard Gooch <rgooch@atnf.csiro.au> - Changed locking to spin with reschedule. - Made use of new <smp_call_function>. - v1.28 - 19990201 Zoltán Böszörményi <zboszor@mail.externet.hu> - Extended the driver to be able to use Cyrix style ARRs. - 19990204 Richard Gooch <rgooch@atnf.csiro.au> - Restructured Cyrix support. - v1.29 - 19990204 Zoltán Böszörményi <zboszor@mail.externet.hu> - Refined ARR support: enable MAPEN in set_mtrr_prepare() - and disable MAPEN in set_mtrr_done(). - 19990205 Richard Gooch <rgooch@atnf.csiro.au> - Minor cleanups. - v1.30 - 19990208 Zoltán Böszörményi <zboszor@mail.externet.hu> - Protect plain 6x86s (and other processors without the - Page Global Enable feature) against accessing CR4 in - set_mtrr_prepare() and set_mtrr_done(). - 19990210 Richard Gooch <rgooch@atnf.csiro.au> - Turned <set_mtrr_up> and <get_mtrr> into function pointers. - v1.31 - 19990212 Zoltán Böszörményi <zboszor@mail.externet.hu> - Major rewrite of cyrix_arr_init(): do not touch ARRs, - leave them as the BIOS have set them up. - Enable usage of all 8 ARRs. - Avoid multiplications by 3 everywhere and other - code clean ups/speed ups. - 19990213 Zoltán Böszörményi <zboszor@mail.externet.hu> - Set up other Cyrix processors identical to the boot cpu. - Since Cyrix don't support Intel APIC, this is l'art pour l'art. - Weigh ARRs by size: - If size <= 32M is given, set up ARR# we were given. - If size > 32M is given, set up ARR7 only if it is free, - fail otherwise. - 19990214 Zoltán Böszörményi <zboszor@mail.externet.hu> - Also check for size >= 256K if we are to set up ARR7, - mtrr_add() returns the value it gets from set_mtrr() - 19990218 Zoltán Böszörményi <zboszor@mail.externet.hu> - Remove Cyrix "coma bug" workaround from here. - Moved to linux/arch/i386/kernel/setup.c and - linux/include/asm-i386/bugs.h - 19990228 Richard Gooch <rgooch@atnf.csiro.au> - Added MTRRIOC_KILL_ENTRY ioctl(2) - Trap for counter underflow in <mtrr_file_del>. - Trap for 4 MiB aligned regions for PPro, stepping <= 7. - 19990301 Richard Gooch <rgooch@atnf.csiro.au> - Created <get_free_region> hook. - 19990305 Richard Gooch <rgooch@atnf.csiro.au> - Temporarily disable AMD support now MTRR capability flag is set. - v1.32 - 19990308 Zoltán Böszörményi <zboszor@mail.externet.hu> - Adjust my changes (19990212-19990218) to Richard Gooch's - latest changes. (19990228-19990305) - v1.33 - 19990309 Richard Gooch <rgooch@atnf.csiro.au> - Fixed typo in <printk> message. - 19990310 Richard Gooch <rgooch@atnf.csiro.au> - Support K6-II/III based on Alan Cox's <alan@redhat.com> patches. - v1.34 - 19990511 Bart Hartgers <bart@etpmod.phys.tue.nl> - Support Centaur C6 MCR's. - 19990512 Richard Gooch <rgooch@atnf.csiro.au> - Minor cleanups. - v1.35 - 19990707 Zoltán Böszörményi <zboszor@mail.externet.hu> - Check whether ARR3 is protected in cyrix_get_free_region() - and mtrr_del(). The code won't attempt to delete or change it - from now on if the BIOS protected ARR3. It silently skips ARR3 - in cyrix_get_free_region() or returns with an error code from - mtrr_del(). - 19990711 Zoltán Böszörményi <zboszor@mail.externet.hu> - Reset some bits in the CCRs in cyrix_arr_init() to disable SMM - if ARR3 isn't protected. This is needed because if SMM is active - and ARR3 isn't protected then deleting and setting ARR3 again - may lock up the processor. With SMM entirely disabled, it does - not happen. - 19990812 Zoltán Böszörményi <zboszor@mail.externet.hu> - Rearrange switch() statements so the driver accomodates to - the fact that the AMD Athlon handles its MTRRs the same way - as Intel does. - 19990814 Zoltán Böszörményi <zboszor@mail.externet.hu> - Double check for Intel in mtrr_add()'s big switch() because - that revision check is only valid for Intel CPUs. - 19990819 Alan Cox <alan@redhat.com> - Tested Zoltan's changes on a pre production Athlon - 100% - success. - 19991008 Manfred Spraul <manfreds@colorfullife.com> - replaced spin_lock_reschedule() with a normal semaphore. - v1.36 - 20000221 Richard Gooch <rgooch@atnf.csiro.au> - Compile fix if procfs and devfs not enabled. - Formatting changes. - v1.37 - 20001109 H. Peter Anvin <hpa@zytor.com> - Use the new centralized CPU feature detects. - - v1.38 - 20010309 Dave Jones <davej@suse.de> - Add support for Cyrix III. - - v1.39 - 20010312 Dave Jones <davej@suse.de> - Ugh, I broke AMD support. - Reworked fix by Troels Walsted Hansen <troels@thule.no> - - v1.40 - 20010327 Dave Jones <davej@suse.de> - Adapted Cyrix III support to include VIA C3. - - v2.0 - 20020306 Patrick Mochel <mochel@osdl.org> - Split mtrr.c -> mtrr/*.c - Converted to Linux Kernel Coding Style - Fixed several minor nits in form - Moved some SMP-only functions out, so they can be used - for power management in the future. - TODO: Fix user interface cruft. diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index c30a16df6440..e8a53552b13d 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c @@ -222,6 +222,10 @@ void kernel_map_pages(struct page *page, int numpages, int enable) { if (PageHighMem(page)) return; + if (!enable) + mutex_debug_check_no_locks_freed(page_address(page), + page_address(page+numpages)); + /* the return value is ignored - the calls cannot fail, * large pages are disabled at boot time. */ diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 06be405be399..9c89eebc356f 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -1171,7 +1171,8 @@ static int __init vpe_module_init(void) return -ENODEV; } - if ((major = register_chrdev(0, module_name, &vpe_fops) < 0)) { + major = register_chrdev(0, module_name, &vpe_fops); + if (major < 0) { printk("VPE loader: unable to register character device\n"); return major; } diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 977ee3adaf2d..34ab0daec3a7 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -972,7 +972,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, #endif #ifdef CONFIG_PPC_RTAS - /* To help early debugging via the front panel, we retreive a minimal + /* To help early debugging via the front panel, we retrieve a minimal * set of RTAS infos now if available */ { diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4283fa33f784..ae2e2a31a705 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -632,7 +632,7 @@ void rtas_stop_self(void) } /* - * Call early during boot, before mem init or bootmem, to retreive the RTAS + * Call early during boot, before mem init or bootmem, to retrieve the RTAS * informations from the device-tree and allocate the RMO buffer for userland * accesses. */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 98e9f0595dd8..81567e931260 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -438,7 +438,7 @@ void __init setup_system(void) /* * Fill the ppc64_caches & systemcfg structures with informations - * retreived from the device-tree. Need to be called before + * retrieved from the device-tree. Need to be called before * finish_device_tree() since the later requires some of the * informations filled up here to properly parse the interrupt * tree. diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 5bb433cbe41b..149351a84b94 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -368,7 +368,7 @@ static unsigned long __init htab_get_table_size(void) unsigned long mem_size, rnd_mem_size, pteg_count; /* If hash size isn't already provided by the platform, we try to - * retreive it from the device-tree. If it's not there neither, we + * retrieve it from the device-tree. If it's not there neither, we * calculate it now based on the total RAM size */ if (ppc64_pft_size == 0) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 1f3507c75e90..d2ba358c6e38 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -137,7 +137,7 @@ spufs_delete_inode(struct inode *inode) static void spufs_prune_dir(struct dentry *dir) { struct dentry *dentry, *tmp; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) { spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); @@ -154,7 +154,7 @@ static void spufs_prune_dir(struct dentry *dir) } } shrink_dcache_parent(dir); - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); } static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) @@ -162,15 +162,15 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) struct spu_context *ctx; /* remove all entries */ - down(&root->i_sem); + mutex_lock(&root->i_mutex); spufs_prune_dir(dir_dentry); - up(&root->i_sem); + mutex_unlock(&root->i_mutex); /* We have to give up the mm_struct */ ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx; spu_forget(ctx); - /* XXX Do we need to hold i_sem here ? */ + /* XXX Do we need to hold i_mutex here ? */ return simple_rmdir(root, dir_dentry); } @@ -330,7 +330,7 @@ long spufs_create_thread(struct nameidata *nd, out_dput: dput(dentry); out_dir: - up(&nd->dentry->d_inode->i_sem); + mutex_unlock(&nd->dentry->d_inode->i_mutex); out: return ret; } diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index a4b50c4109c2..a415e8d2f7af 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -80,7 +80,7 @@ static struct freq_attr* g5_cpu_freqs_attr[] = { }; /* Power mode data is an array of the 32 bits PCR values to use for - * the various frequencies, retreived from the device-tree + * the various frequencies, retrieved from the device-tree */ static u32 *g5_pmode_data; static int g5_pmode_max; diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 46a6ad60a8f5..a3fb3376ffa0 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,46 +1,67 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11 -# Sun Mar 6 20:47:29 2005 +# Linux kernel version: 2.6.15 +# Mon Jan 9 14:36:29 2006 # +CONFIG_SPARC=y +CONFIG_SPARC64=y CONFIG_64BIT=y CONFIG_MMU=y CONFIG_TIME_INTERPOLATION=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_SPARC64_PAGE_SIZE_8KB=y +# CONFIG_SPARC64_PAGE_SIZE_64KB is not set +# CONFIG_SPARC64_PAGE_SIZE_512KB is not set +# CONFIG_SPARC64_PAGE_SIZE_4MB is not set +CONFIG_SECCOMP=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 # # Code maturity level options # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_LOCK_KERNEL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=15 -CONFIG_HOTPLUG=y -CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -52,20 +73,32 @@ CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y -CONFIG_STOP_MACHINE=y + +# +# Block layer +# + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_SYSVIPC_COMPAT=y # # General machine setup # -CONFIG_BBC_I2C=m -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_SMP=y +# CONFIG_SMP is not set # CONFIG_PREEMPT is not set -CONFIG_NR_CPUS=4 CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=m # CONFIG_CPU_FREQ_DEBUG is not set CONFIG_CPU_FREQ_STAT=m CONFIG_CPU_FREQ_STAT_DETAILS=y @@ -75,15 +108,22 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=m CONFIG_CPU_FREQ_GOV_USERSPACE=m CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_US3_FREQ=m CONFIG_US2E_FREQ=m -CONFIG_SPARC64=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_HUGETLB_PAGE_SIZE_4MB=y # CONFIG_HUGETLB_PAGE_SIZE_512K is not set # CONFIG_HUGETLB_PAGE_SIZE_64K is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_GENERIC_ISA_DMA=y CONFIG_SBUS=y CONFIG_SBUSCHAR=y @@ -91,130 +131,142 @@ CONFIG_SUN_AUXIO=y CONFIG_SUN_IO=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_RTC=y # CONFIG_PCI_LEGACY_PROC is not set -# CONFIG_PCI_NAMES is not set +# CONFIG_PCI_DEBUG is not set CONFIG_SUN_OPENPROMFS=m CONFIG_SPARC32_COMPAT=y CONFIG_COMPAT=y -CONFIG_UID16=y CONFIG_BINFMT_ELF32=y # CONFIG_BINFMT_AOUT32 is not set + +# +# Executable file formats +# CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m -CONFIG_SOLARIS_EMUL=m +# CONFIG_SOLARIS_EMUL is not set +# CONFIG_CMDLINE_BOOL is not set # -# Parallel port support +# Networking # -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_FIFO=y -# CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y -CONFIG_PRINTER=m -CONFIG_ENVCTRL=m -CONFIG_DISPLAY7SEG=m -# CONFIG_CMDLINE_BOOL is not set +CONFIG_NET=y # -# Generic Driver Options +# Networking options # -CONFIG_STANDALONE=y -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -CONFIG_FW_LOADER=m -# CONFIG_DEBUG_DRIVER is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +CONFIG_TCP_CONG_ADVANCED=y # -# Graphics support +# TCP congestion control # -CONFIG_FB=y -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_TILEBLITTING=y -# CONFIG_FB_CIRRUS is not set -CONFIG_FB_PM2=y -# CONFIG_FB_PM2_FIFO_DISCONNECT is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_BW2 is not set -# CONFIG_FB_CG3 is not set -CONFIG_FB_CG6=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -CONFIG_FB_ATY=y -CONFIG_FB_ATY_CT=y -# CONFIG_FB_ATY_GENERIC_LCD is not set -# CONFIG_FB_ATY_XL_INIT is not set -CONFIG_FB_ATY_GX=y -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -CONFIG_FB_SBUS=y -CONFIG_FB_FFB=y -# CONFIG_FB_TCX is not set -# CONFIG_FB_CG14 is not set -# CONFIG_FB_P9100 is not set -# CONFIG_FB_LEO is not set -# CONFIG_FB_PCI is not set -# CONFIG_FB_VIRTUAL is not set +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +# CONFIG_NETFILTER is not set # -# Console display driver support +# DCCP Configuration (EXPERIMENTAL) # -# CONFIG_PROM_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -CONFIG_FONT_SUN8x16=y -# CONFIG_FONT_SUN12x22 is not set +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m # -# Logo configuration +# DCCP CCIDs Configuration (EXPERIMENTAL) # -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -CONFIG_LOGO_SUN_CLUT224=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m # -# Serial drivers +# DCCP Kernel Hacking # +# CONFIG_IP_DCCP_DEBUG is not set +# CONFIG_IP_DCCP_UNLOAD_HACK is not set # -# Non-8250 serial port support +# SCTP Configuration (EXPERIMENTAL) # -CONFIG_SERIAL_SUNCORE=y -CONFIG_SERIAL_SUNZILOG=y -CONFIG_SERIAL_SUNZILOG_CONSOLE=y -CONFIG_SERIAL_SUNSU=y -CONFIG_SERIAL_SUNSU_CONSOLE=y -CONFIG_SERIAL_SUNSAB=m -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set # -# Misc Linux/SPARC drivers +# QoS and/or fair queueing # -CONFIG_SUN_OPENPROMIO=m -CONFIG_SUN_MOSTEK_RTC=y -CONFIG_OBP_FLASH=m -# CONFIG_SUN_BPP is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=m # # Memory Technology Devices (MTD) @@ -222,10 +274,18 @@ CONFIG_OBP_FLASH=m # CONFIG_MTD is not set # +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -234,22 +294,13 @@ CONFIG_OBP_FLASH=m CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_SX8=m +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_UB=m # CONFIG_BLK_DEV_RAM is not set CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_INITRAMFS_SOURCE="" CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 CONFIG_CDROM_PKTCDVD_WCACHE=y - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_ATA_OVER_ETH=m # @@ -265,7 +316,7 @@ CONFIG_BLK_DEV_IDE=y CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_IDETAPE=m +# CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set @@ -278,7 +329,7 @@ CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set # CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_BLK_DEV_GENERIC is not set -CONFIG_BLK_DEV_OPTI621=m +# CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y @@ -286,27 +337,25 @@ CONFIG_IDEDMA_ONLYDISK=y # CONFIG_BLK_DEV_AEC62XX is not set CONFIG_BLK_DEV_ALI15X3=y # CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=m -CONFIG_BLK_DEV_CMD64X=m -CONFIG_BLK_DEV_TRIFLEX=m -CONFIG_BLK_DEV_CY82C693=m -CONFIG_BLK_DEV_CS5520=m -CONFIG_BLK_DEV_CS5530=m -CONFIG_BLK_DEV_HPT34X=m -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=m -CONFIG_BLK_DEV_SC1200=m -CONFIG_BLK_DEV_PIIX=m -CONFIG_BLK_DEV_NS87415=m -CONFIG_BLK_DEV_PDC202XX_OLD=m -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=m -# CONFIG_PDC202XX_FORCE is not set -CONFIG_BLK_DEV_SVWKS=m -CONFIG_BLK_DEV_SIIMAGE=m -CONFIG_BLK_DEV_SLC90E66=m -CONFIG_BLK_DEV_TRM290=m -CONFIG_BLK_DEV_VIA82CXXX=m +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set @@ -316,6 +365,7 @@ CONFIG_IDEDMA_AUTO=y # # SCSI device support # +CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_PROC_FS=y @@ -323,11 +373,12 @@ CONFIG_SCSI_PROC_FS=y # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set CONFIG_BLK_DEV_SR=m CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs @@ -340,89 +391,42 @@ CONFIG_SCSI_CONSTANTS=y # SCSI Transport Attributes # CONFIG_SCSI_SPI_ATTRS=y -CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers # -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_SCSI_3W_9XXX=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AACRAID=m +CONFIG_ISCSI_TCP=m +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set -CONFIG_SCSI_SATA=y -CONFIG_SCSI_SATA_AHCI=m -CONFIG_SCSI_SATA_SVW=m -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_SATA_NV=m -CONFIG_SCSI_SATA_PROMISE=m -CONFIG_SCSI_SATA_QSTOR=m -CONFIG_SCSI_SATA_SX4=m -CONFIG_SCSI_SATA_SIL=m -CONFIG_SCSI_SATA_SIS=m -CONFIG_SCSI_SATA_ULI=m -CONFIG_SCSI_SATA_VIA=m -CONFIG_SCSI_SATA_VITESSE=m -CONFIG_SCSI_DMX3191D=m -CONFIG_SCSI_EATA_PIO=m +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set -CONFIG_SCSI_IPS=m -CONFIG_SCSI_INITIO=m -CONFIG_SCSI_INIA100=m -CONFIG_SCSI_PPA=m -CONFIG_SCSI_IMM=m -# CONFIG_SCSI_IZIP_EPP16 is not set -# CONFIG_SCSI_IZIP_SLOW_CTR is not set -CONFIG_SCSI_SYM53C8XX_2=y -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=y -CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y +# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLOGICPTI=m +# CONFIG_SCSI_QLOGICPTI is not set CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA21XX is not set -# CONFIG_SCSI_QLA22XX is not set -# CONFIG_SCSI_QLA2300 is not set -# CONFIG_SCSI_QLA2322 is not set -# CONFIG_SCSI_QLA6312 is not set -CONFIG_SCSI_DC395x=m +# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -CONFIG_SCSI_DEBUG=m -CONFIG_SCSI_SUNESP=y - -# -# Fibre Channel support -# -CONFIG_FC4=m - -# -# FC4 drivers -# -CONFIG_FC4_SOC=m -CONFIG_FC4_SOCAL=m - -# -# FC4 targets -# -CONFIG_SCSI_PLUTO=m -CONFIG_SCSI_FCAL=m +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_SUNESP is not set # # Multi-device support (RAID and LVM) @@ -442,427 +446,34 @@ CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m +# CONFIG_DM_MULTIPATH is not set # # Fusion MPT device support # -CONFIG_FUSION=m -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support # -CONFIG_IEEE1394=m - -# -# Subsystem Options -# -# CONFIG_IEEE1394_VERBOSEDEBUG is not set -CONFIG_IEEE1394_OUI_DB=y -CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y -CONFIG_IEEE1394_CONFIG_ROM_IP1394=y - -# -# Device Drivers -# -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m - -# -# Protocol Drivers -# -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -CONFIG_ARPD=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -CONFIG_INET_TUNNEL=y -CONFIG_IP_TCPDIAG=y -# CONFIG_IP_TCPDIAG_IPV6 is not set - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 - -# -# IPVS transport protocol load balancing support -# -CONFIG_IP_VS_PROTO_TCP=y -CONFIG_IP_VS_PROTO_UDP=y -CONFIG_IP_VS_PROTO_ESP=y -CONFIG_IP_VS_PROTO_AH=y - -# -# IPVS scheduler -# -CONFIG_IP_VS_RR=m -CONFIG_IP_VS_WRR=m -CONFIG_IP_VS_LC=m -CONFIG_IP_VS_WLC=m -CONFIG_IP_VS_LBLC=m -CONFIG_IP_VS_LBLCR=m -CONFIG_IP_VS_DH=m -CONFIG_IP_VS_SH=m -CONFIG_IP_VS_SED=m -CONFIG_IP_VS_NQ=m - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_INET6_TUNNEL=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_BRIDGE_NETFILTER=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_CT_ACCT=y -CONFIG_IP_NF_CONNTRACK_MARK=y -CONFIG_IP_NF_CT_PROTO_SCTP=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_MATCH_PHYSDEV=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_REALM=m -CONFIG_IP_NF_MATCH_SCTP=m -CONFIG_IP_NF_MATCH_COMMENT=m -CONFIG_IP_NF_MATCH_CONNMARK=m -CONFIG_IP_NF_MATCH_HASHLIMIT=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_CLASSIFY=m -CONFIG_IP_NF_TARGET_CONNMARK=m -CONFIG_IP_NF_TARGET_CLUSTERIP=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_TARGET_NOTRACK=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m - -# -# IPv6: Netfilter Configuration -# -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_MATCH_PHYSDEV=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_IP6_NF_RAW=m - -# -# DECnet: Netfilter Configuration -# -CONFIG_DECNET_NF_GRABULATOR=m - -# -# Bridge: Netfilter Configuration -# -CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m -CONFIG_BRIDGE_EBT_802_3=m -CONFIG_BRIDGE_EBT_AMONG=m -CONFIG_BRIDGE_EBT_ARP=m -CONFIG_BRIDGE_EBT_IP=m -CONFIG_BRIDGE_EBT_LIMIT=m -CONFIG_BRIDGE_EBT_MARK=m -CONFIG_BRIDGE_EBT_PKTTYPE=m -CONFIG_BRIDGE_EBT_STP=m -CONFIG_BRIDGE_EBT_VLAN=m -CONFIG_BRIDGE_EBT_ARPREPLY=m -CONFIG_BRIDGE_EBT_DNAT=m -CONFIG_BRIDGE_EBT_MARK_T=m -CONFIG_BRIDGE_EBT_REDIRECT=m -CONFIG_BRIDGE_EBT_SNAT=m -CONFIG_BRIDGE_EBT_LOG=m -CONFIG_BRIDGE_EBT_ULOG=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=m - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -# CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_ATM_BR2684_IPFILTER=y -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -CONFIG_DECNET=m -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_LLC=m -CONFIG_LLC2=m -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m -# CONFIG_DEV_APPLETALK is not set -CONFIG_X25=m -CONFIG_LAPB=m -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -# CONFIG_NET_SCH_CLK_JIFFIES is not set -# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set -CONFIG_NET_SCH_CLK_CPU=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_ATM=y -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_NETEM=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -CONFIG_NET_CLS_BASIC=m -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_CLS_U32_PERF=y -CONFIG_NET_CLS_IND=y -CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_STACK=32 -CONFIG_NET_EMATCH_CMP=m -CONFIG_NET_EMATCH_NBYTE=m -CONFIG_NET_EMATCH_U32=m -CONFIG_NET_EMATCH_META=m -CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_POLICE=m -CONFIG_NET_ACT_GACT=m -CONFIG_GACT_PROB=y -CONFIG_NET_ACT_MIRRED=m -CONFIG_NET_ACT_IPT=m -CONFIG_NET_ACT_PEDIT=m - -# -# Network testing -# -CONFIG_NET_PKTGEN=m -CONFIG_NETPOLL=y -# CONFIG_NETPOLL_RX is not set -# CONFIG_NETPOLL_TRAP is not set -CONFIG_NET_POLL_CONTROLLER=y -CONFIG_HAMRADIO=y - -# -# Packet Radio protocols -# -CONFIG_AX25=m -CONFIG_AX25_DAMA_SLAVE=y -CONFIG_NETROM=m -CONFIG_ROSE=m - -# -# AX.25 network device drivers -# -# CONFIG_BPQETHER is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -# CONFIG_BAYCOM_PAR is not set -# CONFIG_YAM is not set -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -# CONFIG_IRTTY_SIR is not set - -# -# Dongle support -# - -# -# Old SIR device drivers -# - -# -# Old Serial dongle support -# +# CONFIG_IEEE1394 is not set # -# FIR device drivers +# I2O device support # -# CONFIG_USB_IRDA is not set -CONFIG_SIGMATEL_FIR=m -# CONFIG_VLSI_FIR is not set -CONFIG_BT=m -CONFIG_BT_L2CAP=m -CONFIG_BT_SCO=m -CONFIG_BT_RFCOMM=m -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=m -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_CMTP=m -CONFIG_BT_HIDP=m +# CONFIG_I2O is not set # -# Bluetooth device drivers +# Network device support # -CONFIG_BT_HCIUSB=m -CONFIG_BT_HCIUSB_SCO=y -CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_HCIUART_BCSP=y -CONFIG_BT_HCIUART_BCSP_TXCRC=y -CONFIG_BT_HCIBCM203X=m -CONFIG_BT_HCIBPA10X=m -CONFIG_BT_HCIBFUSB=m -CONFIG_BT_HCIVHCI=m CONFIG_NETDEVICES=y CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -# CONFIG_ETHERTAP is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices @@ -870,86 +481,73 @@ CONFIG_TUN=m # CONFIG_ARCNET is not set # +# PHY device support +# +# CONFIG_PHYLIB is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=m -CONFIG_SUNLANCE=y -CONFIG_HAPPYMEAL=y -CONFIG_SUNBMAC=m -CONFIG_SUNQE=m -CONFIG_SUNGEM=y -CONFIG_NET_VENDOR_3COM=y -CONFIG_VORTEX=m -CONFIG_TYPHOON=m +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +CONFIG_CASSINI=m +# CONFIG_NET_VENDOR_3COM is not set # # Tulip family network device support # -CONFIG_NET_TULIP=y -CONFIG_DE2104X=m -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set -CONFIG_TULIP_NAPI=y -CONFIG_TULIP_NAPI_HW_MITIGATION=y -CONFIG_DE4X5=m -CONFIG_WINBOND_840=m -# CONFIG_DM9102 is not set +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set CONFIG_NET_PCI=y -CONFIG_PCNET32=m +# CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_ADAPTEC_STARFIRE_NAPI=y -CONFIG_B44=m -CONFIG_FORCEDETH=m -CONFIG_DGRS=m -CONFIG_EEPRO100=m -CONFIG_E100=m -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set # CONFIG_8139CP is not set -CONFIG_8139TOO=m -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_OLD_RX_RESET is not set -CONFIG_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -CONFIG_SUNDANCE_MMIO=y -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_VIA_RHINE is not set # # Ethernet (1000 Mbit) # -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set CONFIG_E1000=m CONFIG_E1000_NAPI=y -CONFIG_MYRI_SBUS=m -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_R8169_NAPI=y -CONFIG_R8169_VLAN=y -CONFIG_SK98LIN=m -CONFIG_VIA_VELOCITY=m +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=m +CONFIG_BNX2=m # # Ethernet (10000 Mbit) # -CONFIG_IXGB=m -CONFIG_IXGB_NAPI=y -CONFIG_S2IO=m -CONFIG_S2IO_NAPI=y -CONFIG_2BUFF_MODE=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set # # Token Ring devices @@ -959,140 +557,31 @@ CONFIG_2BUFF_MODE=y # # Wireless LAN (non-hamradio) # -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set - -# -# Wireless 802.11b ISA/PCI cards support -# -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_TMD_HERMES=m -CONFIG_PCI_HERMES=m -CONFIG_ATMEL=m -CONFIG_PCI_ATMEL=m - -# -# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support -# -CONFIG_PRISM54=m -CONFIG_NET_WIRELESS=y +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# ATM drivers -# -CONFIG_ATM_TCP=m -# CONFIG_ATM_LANAI is not set -# CONFIG_ATM_ENI is not set -# CONFIG_ATM_FIRESTREAM is not set -# CONFIG_ATM_ZATM is not set -# CONFIG_ATM_IDT77252 is not set -# CONFIG_ATM_AMBASSADOR is not set -# CONFIG_ATM_HORIZON is not set -CONFIG_ATM_FORE200E_MAYBE=m -CONFIG_ATM_FORE200E_PCA=y -CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y -CONFIG_ATM_FORE200E_SBA=y -CONFIG_ATM_FORE200E_SBA_DEFAULT_FW=y -CONFIG_ATM_FORE200E_USE_TASKLET=y -CONFIG_ATM_FORE200E_TX_RETRY=16 -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_FORE200E=m -CONFIG_ATM_HE=m -CONFIG_ATM_HE_USE_SUNI=y -CONFIG_FDDI=y -# CONFIG_DEFXX is not set -CONFIG_SKFP=m -CONFIG_HIPPI=y -# CONFIG_ROADRUNNER is not set -CONFIG_PLIP=m -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -# CONFIG_SLIP_MODE_SLIP6 is not set -CONFIG_NET_FC=y -CONFIG_SHAPER=m -CONFIG_NETCONSOLE=m +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem # -CONFIG_ISDN=m - -# -# Old ISDN4Linux -# -# CONFIG_ISDN_I4L is not set - -# -# CAPI subsystem -# -CONFIG_ISDN_CAPI=m -# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set -# CONFIG_ISDN_CAPI_MIDDLEWARE is not set -CONFIG_ISDN_CAPI_CAPI20=m - -# -# CAPI hardware drivers -# - -# -# Active AVM cards -# -CONFIG_CAPI_AVM=y -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m -CONFIG_ISDN_DRV_AVMB1_T1PCI=m -CONFIG_ISDN_DRV_AVMB1_C4=m - -# -# Active Eicon DIVA Server cards -# -CONFIG_CAPI_EICON=y -CONFIG_ISDN_DIVAS=m -CONFIG_ISDN_DIVAS_BRIPCI=y -CONFIG_ISDN_DIVAS_PRIPCI=y -CONFIG_ISDN_DIVAS_DIVACAPI=m -CONFIG_ISDN_DIVAS_USERIDI=m -CONFIG_ISDN_DIVAS_MAINT=m +# CONFIG_ISDN is not set # # Telephony Support # -CONFIG_PHONE=m -CONFIG_PHONE_IXJ=m - -# -# Unix98 PTY support -# -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# XFree86 DRI support -# -CONFIG_DRM=y -CONFIG_DRM_TDFX=m -# CONFIG_DRM_R128 is not set +# CONFIG_PHONE is not set # # Input device support @@ -1112,26 +601,6 @@ CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set # -# Input I/O drivers -# -CONFIG_GAMEPORT=m -CONFIG_SOUND_GAMEPORT=m -# CONFIG_GAMEPORT_NS558 is not set -# CONFIG_GAMEPORT_L4 is not set -# CONFIG_GAMEPORT_EMU10K1 is not set -# CONFIG_GAMEPORT_VORTEX is not set -# CONFIG_GAMEPORT_FM801 is not set -CONFIG_GAMEPORT_CS461X=m -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -# CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PARKBD is not set -CONFIG_SERIO_PCIPS2=m -CONFIG_SERIO_LIBPS2=y -CONFIG_SERIO_RAW=m - -# # Input Device Drivers # CONFIG_INPUT_KEYBOARD=y @@ -1143,7 +612,7 @@ CONFIG_KEYBOARD_LKKBD=m CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y CONFIG_MOUSE_SERIAL=y -CONFIG_MOUSE_VSXXXAA=m +# CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y @@ -1151,406 +620,250 @@ CONFIG_INPUT_SPARCSPKR=y # CONFIG_INPUT_UINPUT is not set # -# I2C support +# Hardware I/O ports # -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=m +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_PCIPS2=m +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +# CONFIG_GAMEPORT is not set # -# I2C Algorithms +# Character devices # -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_ALGOPCF=m -CONFIG_I2C_ALGOPCA=m +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set # -# I2C Hardware Bus support +# Serial drivers # -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI1563=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_AMD756=m -# CONFIG_I2C_AMD756_S4882 is not set -CONFIG_I2C_AMD8111=m -CONFIG_I2C_I801=m -CONFIG_I2C_I810=m -CONFIG_I2C_ISA=m -CONFIG_I2C_NFORCE2=m -CONFIG_I2C_PARPORT=m -CONFIG_I2C_PARPORT_LIGHT=m -CONFIG_I2C_PIIX4=m -CONFIG_I2C_PROSAVAGE=m -CONFIG_I2C_SAVAGE4=m -CONFIG_SCx200_ACB=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_SIS630=m -CONFIG_I2C_SIS96X=m -CONFIG_I2C_STUB=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m -CONFIG_I2C_PCA_ISA=m - -# -# Hardware Sensors Chip support -# -CONFIG_I2C_SENSOR=m -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM1026=m -CONFIG_SENSORS_ADM1031=m -CONFIG_SENSORS_ASB100=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_FSCHER=m -CONFIG_SENSORS_FSCPOS=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_LM63=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM77=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM83=m -CONFIG_SENSORS_LM85=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM90=m -CONFIG_SENSORS_MAX1619=m -CONFIG_SENSORS_PC87360=m -CONFIG_SENSORS_SMSC47B397=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_W83L785TS=m -CONFIG_SENSORS_W83627HF=m - -# -# Other I2C Chip support -# -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_PCF8574=m -CONFIG_SENSORS_PCF8591=m -CONFIG_SENSORS_RTC8564=m -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # -# File systems +# Non-8250 serial port support # -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_SECURITY=y -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -CONFIG_FS_POSIX_ACL=y +CONFIG_SERIAL_SUNCORE=y +# CONFIG_SERIAL_SUNZILOG is not set +CONFIG_SERIAL_SUNSU=y +CONFIG_SERIAL_SUNSU_CONSOLE=y +CONFIG_SERIAL_SUNSAB=m +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set # -# XFS support +# IPMI # -CONFIG_XFS_FS=m -CONFIG_XFS_EXPORT=y -# CONFIG_XFS_RT is not set -CONFIG_XFS_QUOTA=y -CONFIG_XFS_SECURITY=y -CONFIG_XFS_POSIX_ACL=y -CONFIG_MINIX_FS=m -CONFIG_ROMFS_FS=m -# CONFIG_QUOTA is not set -CONFIG_QUOTACTL=y -CONFIG_DNOTIFY=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m +# CONFIG_IPMI_HANDLER is not set # -# CD-ROM/DVD Filesystems +# Watchdog Cards # -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -CONFIG_UDF_FS=m -CONFIG_UDF_NLS=y +# CONFIG_WATCHDOG is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # -# DOS/FAT/NT Filesystems +# Ftape, the floppy tape device driver # -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set # -# Pseudo filesystems +# TPM devices # -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS_XATTR=y -# CONFIG_DEVPTS_FS_SECURITY is not set -CONFIG_TMPFS=y -CONFIG_TMPFS_XATTR=y -CONFIG_TMPFS_SECURITY=y -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_RAMFS=y +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set # -# Miscellaneous filesystems +# I2C support # -CONFIG_ADFS_FS=m -# CONFIG_ADFS_FS_RW is not set -CONFIG_AFFS_FS=m -CONFIG_HFS_FS=m -CONFIG_HFSPLUS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -CONFIG_BFS_FS=m -CONFIG_EFS_FS=m -CONFIG_CRAMFS=m -CONFIG_VXFS_FS=m -CONFIG_HPFS_FS=m -CONFIG_QNX4FS_FS=m -CONFIG_SYSV_FS=m -CONFIG_UFS_FS=m -CONFIG_UFS_FS_WRITE=y +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set # -# Network File Systems +# I2C Algorithms # -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_V4=y -CONFIG_NFS_DIRECTIO=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_V4=y -CONFIG_NFSD_TCP=y -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m -CONFIG_SUNRPC=m -CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_RPCSEC_GSS_SPKM3=m -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_XATTR is not set -# CONFIG_CIFS_EXPERIMENTAL is not set -CONFIG_NCP_FS=m -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set -CONFIG_AFS_FS=m -CONFIG_RXRPC=m +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set # -# Partition Types +# I2C Hardware Bus support # -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SUN_PARTITION=y +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_RTC_X1205_I2C is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set # -# Native Language Support +# Dallas's 1-wire bus # -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ASCII=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m +# CONFIG_W1 is not set # -# Multimedia devices +# Hardware Monitoring support # -CONFIG_VIDEO_DEV=y +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # -# Video For Linux +# Misc devices # # -# Video Adapters +# Multimedia Capabilities Port drivers # -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_BWQCAM=m -CONFIG_VIDEO_CQCAM=m -CONFIG_VIDEO_W9966=m -CONFIG_VIDEO_CPIA=m -CONFIG_VIDEO_CPIA_PP=m -CONFIG_VIDEO_CPIA_USB=m -CONFIG_VIDEO_SAA5246A=m -CONFIG_VIDEO_SAA5249=m -CONFIG_TUNER_3036=m -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_SAA7134 is not set -CONFIG_VIDEO_MXB=m -CONFIG_VIDEO_DPC=m -CONFIG_VIDEO_HEXIUM_ORION=m -CONFIG_VIDEO_HEXIUM_GEMINI=m -CONFIG_VIDEO_CX88=m -CONFIG_VIDEO_OVCAMCHIP=m # -# Radio Adapters +# Multimedia devices # -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m +# CONFIG_VIDEO_DEV is not set # # Digital Video Broadcasting Devices # -CONFIG_DVB=y -CONFIG_DVB_CORE=m - -# -# Supported SAA7146 based PCI Adapters -# -CONFIG_DVB_AV7110=m -# CONFIG_DVB_AV7110_OSD is not set -CONFIG_DVB_BUDGET=m -CONFIG_DVB_BUDGET_CI=m -CONFIG_DVB_BUDGET_AV=m -CONFIG_DVB_BUDGET_PATCH=m - -# -# Supported USB Adapters -# -# CONFIG_DVB_TTUSB_BUDGET is not set -CONFIG_DVB_TTUSB_DEC=m -CONFIG_DVB_DIBUSB=m -# CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES is not set -CONFIG_DVB_DIBCOM_DEBUG=y -CONFIG_DVB_CINERGYT2=m -# CONFIG_DVB_CINERGYT2_TUNING is not set - -# -# Supported FlexCopII (B2C2) Adapters -# -CONFIG_DVB_B2C2_SKYSTAR=m -CONFIG_DVB_B2C2_USB=m +# CONFIG_DVB is not set # -# Supported BT878 Adapters -# -CONFIG_DVB_BT8XX=m - -# -# Supported DVB Frontends -# - -# -# Customise DVB Frontends -# - -# -# DVB-S (satellite) frontends -# -CONFIG_DVB_STV0299=m -CONFIG_DVB_CX24110=m -CONFIG_DVB_TDA8083=m -CONFIG_DVB_TDA80XX=m -CONFIG_DVB_MT312=m -CONFIG_DVB_VES1X93=m - -# -# DVB-T (terrestrial) frontends +# Graphics support # -CONFIG_DVB_SP8870=m -CONFIG_DVB_SP887X=m -CONFIG_DVB_CX22700=m -CONFIG_DVB_CX22702=m -CONFIG_DVB_L64781=m -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_NXT6000=m -CONFIG_DVB_MT352=m -CONFIG_DVB_DIB3000MB=m -CONFIG_DVB_DIB3000MC=m +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_SBUS is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_PCI is not set +# CONFIG_FB_VIRTUAL is not set # -# DVB-C (cable) frontends +# Console display driver support # -CONFIG_DVB_ATMEL_AT76C651=m -CONFIG_DVB_VES1820=m -CONFIG_DVB_TDA10021=m -CONFIG_DVB_STV0297=m +# CONFIG_PROM_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +CONFIG_FONT_SUN8x16=y +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set # -# ATSC (North American/Korean Terresterial DTV) frontends +# Logo configuration # -CONFIG_DVB_NXT2002=m -CONFIG_VIDEO_SAA7146=m -CONFIG_VIDEO_SAA7146_VV=m -CONFIG_VIDEO_VIDEOBUF=m -CONFIG_VIDEO_TUNER=m -CONFIG_VIDEO_BUF=m -CONFIG_VIDEO_BTCX=m -CONFIG_VIDEO_IR=m -CONFIG_VIDEO_TVEEPROM=m +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +CONFIG_LOGO_SUN_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -1563,7 +876,6 @@ CONFIG_SOUND=m CONFIG_SND=m CONFIG_SND_TIMER=m CONFIG_SND_PCM=m -CONFIG_SND_HWDEP=m CONFIG_SND_RAWMIDI=m CONFIG_SND_SEQUENCER=m CONFIG_SND_SEQ_DUMMY=m @@ -1571,8 +883,9 @@ CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=m CONFIG_SND_PCM_OSS=m CONFIG_SND_SEQUENCER_OSS=y -CONFIG_SND_BIT32_EMUL=m # CONFIG_SND_RTCTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -1580,59 +893,58 @@ CONFIG_SND_BIT32_EMUL=m # Generic devices # CONFIG_SND_MPU401_UART=m -CONFIG_SND_OPL3_LIB=m -CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m CONFIG_SND_DUMMY=m CONFIG_SND_VIRMIDI=m -# CONFIG_SND_MTPAV is not set +CONFIG_SND_MTPAV=m # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set # # PCI devices # -CONFIG_SND_AC97_CODEC=m +# CONFIG_SND_AD1889 is not set CONFIG_SND_ALI5451=m -CONFIG_SND_ATIIXP=m -CONFIG_SND_ATIIXP_MODEM=m -CONFIG_SND_AU8810=m -CONFIG_SND_AU8820=m -CONFIG_SND_AU8830=m -CONFIG_SND_AZT3328=m -CONFIG_SND_BT87X=m -# CONFIG_SND_BT87X_OVERCLOCK is not set -CONFIG_SND_CS46XX=m -# CONFIG_SND_CS46XX_NEW_DSP is not set -CONFIG_SND_CS4281=m -CONFIG_SND_EMU10K1=m -CONFIG_SND_EMU10K1X=m -CONFIG_SND_CA0106=m -CONFIG_SND_KORG1212=m -CONFIG_SND_MIXART=m -CONFIG_SND_NM256=m +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set -# CONFIG_SND_HDSP is not set -CONFIG_SND_TRIDENT=m -CONFIG_SND_YMFPCI=m -CONFIG_SND_ALS4000=m -CONFIG_SND_CMIPCI=m -CONFIG_SND_ENS1370=m -CONFIG_SND_ENS1371=m -CONFIG_SND_ES1938=m -CONFIG_SND_ES1968=m -CONFIG_SND_MAESTRO3=m -CONFIG_SND_FM801=m -CONFIG_SND_FM801_TEA575X=m -CONFIG_SND_ICE1712=m -# CONFIG_SND_ICE1724 is not set -CONFIG_SND_INTEL8X0=m -CONFIG_SND_INTEL8X0M=m -CONFIG_SND_SONICVIBES=m +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set -CONFIG_SND_VIA82XX_MODEM=m -CONFIG_SND_VX222=m +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set # # USB devices @@ -1642,12 +954,20 @@ CONFIG_SND_VX222=m # # ALSA Sparc devices # -CONFIG_SND_SUN_AMD7930=m +# CONFIG_SND_SUN_AMD7930 is not set CONFIG_SND_SUN_CS4231=m +# CONFIG_SND_SUN_DBRI is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set # # USB support # +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1658,8 +978,6 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_OTG is not set -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y # # USB Host Controller Drivers @@ -1667,36 +985,29 @@ CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_UHCI_HCD=m -CONFIG_USB_SL811_HCD=m +# CONFIG_USB_SL811_HCD is not set # # USB Device Class drivers # -# CONFIG_USB_AUDIO is not set +# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set # -# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # -# CONFIG_USB_MIDI is not set -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# may also be needed; see USB_STORAGE Help for more information # -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_RW_DETECT=y -# CONFIG_USB_STORAGE_DATAFAB is not set -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set # # USB Input Devices @@ -1706,135 +1017,75 @@ CONFIG_USB_HIDINPUT=y # CONFIG_HID_FF is not set CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -CONFIG_USB_MTOUCH=m -CONFIG_USB_EGALAX=m +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set -CONFIG_USB_ATI_REMOTE=m +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set # # USB Imaging devices # -CONFIG_USB_MDC800=m -CONFIG_USB_MICROTEK=m +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set # # USB Multimedia devices # # CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -CONFIG_USB_SN9C102=m -# CONFIG_USB_STV680 is not set -CONFIG_USB_W9968CF=m - -# -# USB Network Adapters -# -CONFIG_USB_CATC=m -CONFIG_USB_KAWETH=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_USBNET=m - -# -# USB Host-to-Host Cables -# -CONFIG_USB_ALI_M5632=y -CONFIG_USB_AN2720=y -CONFIG_USB_BELKIN=y -CONFIG_USB_GENESYS=y -CONFIG_USB_NET1080=y -CONFIG_USB_PL2301=y -CONFIG_USB_KC2190=y # -# Intelligent USB Devices/Gadgets +# Video4Linux support is needed for USB Multimedia device support # -CONFIG_USB_ARMLINUX=y -CONFIG_USB_EPSON2888=y -CONFIG_USB_ZAURUS=y -CONFIG_USB_CDCETHER=y # # USB Network Adapters # -CONFIG_USB_AX8817X=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_MON is not set # # USB port drivers # -CONFIG_USB_USS720=m # # USB Serial Converter support # -CONFIG_USB_SERIAL=m -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_CYPRESS_M8=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=m -# CONFIG_USB_SERIAL_VISOR is not set -CONFIG_USB_SERIAL_IPAQ=m -# CONFIG_USB_SERIAL_IR is not set -CONFIG_USB_SERIAL_EDGEPORT=m -# CONFIG_USB_SERIAL_EDGEPORT_TI is not set -CONFIG_USB_SERIAL_GARMIN=m -CONFIG_USB_SERIAL_IPW=m -CONFIG_USB_SERIAL_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set -CONFIG_USB_SERIAL_KLSI=m -# CONFIG_USB_SERIAL_KOBIL_SCT is not set -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_PL2303=m -# CONFIG_USB_SERIAL_SAFE is not set -CONFIG_USB_SERIAL_TI=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_EZUSB=y +# CONFIG_USB_SERIAL is not set # # USB Miscellaneous drivers # -CONFIG_USB_EMI62=m -CONFIG_USB_EMI26=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_RIO500=m -CONFIG_USB_LEGOTOWER=m -CONFIG_USB_LCD=m -CONFIG_USB_LED=m -CONFIG_USB_CYTHERM=m -CONFIG_USB_PHIDGETKIT=m -CONFIG_USB_PHIDGETSERVO=m -CONFIG_USB_IDMOUSE=m -CONFIG_USB_TEST=m +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set # -# USB ATM/DSL drivers +# USB DSL modem support # -CONFIG_USB_ATM=m -CONFIG_USB_SPEEDTOUCH=m # # USB Gadget Support @@ -1842,50 +1093,185 @@ CONFIG_USB_SPEEDTOUCH=m # CONFIG_USB_GADGET is not set # +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# # InfiniBand support # -CONFIG_INFINIBAND=m -CONFIG_INFINIBAND_MTHCA=m -# CONFIG_INFINIBAND_MTHCA_DEBUG is not set -CONFIG_INFINIBAND_IPOIB=m -# CONFIG_INFINIBAND_IPOIB_DEBUG is not set +# CONFIG_INFINIBAND is not set # -# Watchdog Cards +# SN Devices +# + +# +# Misc Linux/SPARC drivers +# +CONFIG_SUN_OPENPROMIO=m +CONFIG_SUN_MOSTEK_RTC=y +# CONFIG_OBP_FLASH is not set +# CONFIG_SUN_BPP is not set +# CONFIG_BBC_I2C is not set +# CONFIG_ENVCTRL is not set +# CONFIG_DISPLAY7SEG is not set + +# +# Fibre Channel support +# +# CONFIG_FC4 is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + # -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set # -# Watchdog Device Drivers +# DOS/FAT/NT Filesystems # -CONFIG_SOFT_WATCHDOG=m -CONFIG_WATCHDOG_CP1XXX=m -CONFIG_WATCHDOG_RIO=m +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set # -# PCI-based Watchdog Cards +# Pseudo filesystems # -CONFIG_PCIPCWATCHDOG=m -CONFIG_WDTPCI=m -CONFIG_WDT_501_PCI=y +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_RELAYFS_FS=m +# CONFIG_CONFIGFS_FS is not set # -# USB-based Watchdog Cards +# Miscellaneous filesystems # -CONFIG_USBPCWATCHDOG=m +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set # -# Profiling support +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_SUN_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Instrumentation Support # CONFIG_PROFILING=y CONFIG_OPROFILE=m +CONFIG_KPROBES=y # # Kernel hacking # +CONFIG_PRINTK_TIME=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1894,12 +1280,13 @@ CONFIG_SCHEDSTATS=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_KPROBES=y # CONFIG_DEBUG_DCFLUSH is not set # CONFIG_STACK_DEBUG is not set # CONFIG_DEBUG_BOOTMEM is not set -CONFIG_HAVE_DEC_LOCK=y +# CONFIG_DEBUG_PAGEALLOC is not set # # Security options @@ -1945,6 +1332,7 @@ CONFIG_CRYPTO_TEST=m # Library routines # CONFIG_CRC_CCITT=m +CONFIG_CRC16=m CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 11a848402fb1..710002991888 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1657,13 +1657,10 @@ ret_sys_call: /* Check if force_successful_syscall_return() * was invoked. */ - ldub [%curptr + TI_SYS_NOERROR], %l0 - brz,pt %l0, 1f - nop - ba,pt %xcc, 80f + ldub [%curptr + TI_SYS_NOERROR], %l2 + brnz,a,pn %l2, 80f stb %g0, [%curptr + TI_SYS_NOERROR] -1: cmp %o0, -ERESTART_RESTARTBLOCK bgeu,pn %xcc, 1f andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6 diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 9e8362ea3104..30bcaf58e3ab 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -14,6 +14,7 @@ #include <linux/signal.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/pm.h> #include <asm/system.h> #include <asm/ebus.h> @@ -70,6 +71,9 @@ void machine_power_off(void) machine_halt(); } +void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); + #ifdef CONFIG_PCI static int powerd(void *__unused) { diff --git a/arch/x86_64/crypto/aes.c b/arch/x86_64/crypto/aes.c index acfdaa28791e..fb1b961a2e2f 100644 --- a/arch/x86_64/crypto/aes.c +++ b/arch/x86_64/crypto/aes.c @@ -74,8 +74,6 @@ static inline u8 byte(const u32 x, const unsigned n) return x >> (n << 3); } -#define u32_in(x) le32_to_cpu(*(const __le32 *)(x)) - struct aes_ctx { u32 key_length; @@ -234,6 +232,7 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { struct aes_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; u32 i, j, t, u, v, w; if (key_len != 16 && key_len != 24 && key_len != 32) { @@ -243,10 +242,10 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, ctx->key_length = key_len; - D_KEY[key_len + 24] = E_KEY[0] = u32_in(in_key); - D_KEY[key_len + 25] = E_KEY[1] = u32_in(in_key + 4); - D_KEY[key_len + 26] = E_KEY[2] = u32_in(in_key + 8); - D_KEY[key_len + 27] = E_KEY[3] = u32_in(in_key + 12); + D_KEY[key_len + 24] = E_KEY[0] = le32_to_cpu(key[0]); + D_KEY[key_len + 25] = E_KEY[1] = le32_to_cpu(key[1]); + D_KEY[key_len + 26] = E_KEY[2] = le32_to_cpu(key[2]); + D_KEY[key_len + 27] = E_KEY[3] = le32_to_cpu(key[3]); switch (key_len) { case 16: @@ -256,17 +255,17 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, break; case 24: - E_KEY[4] = u32_in(in_key + 16); - t = E_KEY[5] = u32_in(in_key + 20); + E_KEY[4] = le32_to_cpu(key[4]); + t = E_KEY[5] = le32_to_cpu(key[5]); for (i = 0; i < 8; ++i) loop6 (i); break; case 32: - E_KEY[4] = u32_in(in_key + 16); - E_KEY[5] = u32_in(in_key + 20); - E_KEY[6] = u32_in(in_key + 24); - t = E_KEY[7] = u32_in(in_key + 28); + E_KEY[4] = le32_to_cpu(key[4]); + E_KEY[5] = le32_to_cpu(key[5]); + E_KEY[6] = le32_to_cpu(key[6]); + t = E_KEY[7] = le32_to_cpu(key[7]); for (i = 0; i < 7; ++i) loop8(i); break; @@ -290,6 +289,8 @@ extern void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in); static struct crypto_alg aes_alg = { .cra_name = "aes", + .cra_driver_name = "aes-x86_64", + .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index cb6e38ed2b1d..937d81f62f43 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -201,7 +201,7 @@ again: if ((signed long)(get_ccount() - next) > 0) goto again; - /* Allow platform to do something usefull (Wdog). */ + /* Allow platform to do something useful (Wdog). */ platform_heartbeat(); diff --git a/crypto/Kconfig b/crypto/Kconfig index 52e1d4108a99..c442f2e7ce46 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -157,7 +157,7 @@ config CRYPTO_SERPENT config CRYPTO_AES tristate "AES cipher algorithms" - depends on CRYPTO && !(X86 || UML_X86) + depends on CRYPTO help AES cipher algorithms (FIPS-197). AES uses the Rijndael algorithm. diff --git a/crypto/aes.c b/crypto/aes.c index 5df92888ef5a..0a6a5c143686 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -73,9 +73,6 @@ byte(const u32 x, const unsigned n) return x >> (n << 3); } -#define u32_in(x) le32_to_cpu(*(const u32 *)(x)) -#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from)) - struct aes_ctx { int key_length; u32 E[60]; @@ -256,6 +253,7 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { struct aes_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; u32 i, t, u, v, w; if (key_len != 16 && key_len != 24 && key_len != 32) { @@ -265,10 +263,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) ctx->key_length = key_len; - E_KEY[0] = u32_in (in_key); - E_KEY[1] = u32_in (in_key + 4); - E_KEY[2] = u32_in (in_key + 8); - E_KEY[3] = u32_in (in_key + 12); + E_KEY[0] = le32_to_cpu(key[0]); + E_KEY[1] = le32_to_cpu(key[1]); + E_KEY[2] = le32_to_cpu(key[2]); + E_KEY[3] = le32_to_cpu(key[3]); switch (key_len) { case 16: @@ -278,17 +276,17 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 24: - E_KEY[4] = u32_in (in_key + 16); - t = E_KEY[5] = u32_in (in_key + 20); + E_KEY[4] = le32_to_cpu(key[4]); + t = E_KEY[5] = le32_to_cpu(key[5]); for (i = 0; i < 8; ++i) loop6 (i); break; case 32: - E_KEY[4] = u32_in (in_key + 16); - E_KEY[5] = u32_in (in_key + 20); - E_KEY[6] = u32_in (in_key + 24); - t = E_KEY[7] = u32_in (in_key + 28); + E_KEY[4] = le32_to_cpu(key[4]); + E_KEY[5] = le32_to_cpu(key[5]); + E_KEY[6] = le32_to_cpu(key[6]); + t = E_KEY[7] = le32_to_cpu(key[7]); for (i = 0; i < 7; ++i) loop8 (i); break; @@ -324,13 +322,15 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) { const struct aes_ctx *ctx = ctx_arg; + const __le32 *src = (const __le32 *)in; + __le32 *dst = (__le32 *)out; u32 b0[4], b1[4]; const u32 *kp = E_KEY + 4; - b0[0] = u32_in (in) ^ E_KEY[0]; - b0[1] = u32_in (in + 4) ^ E_KEY[1]; - b0[2] = u32_in (in + 8) ^ E_KEY[2]; - b0[3] = u32_in (in + 12) ^ E_KEY[3]; + b0[0] = le32_to_cpu(src[0]) ^ E_KEY[0]; + b0[1] = le32_to_cpu(src[1]) ^ E_KEY[1]; + b0[2] = le32_to_cpu(src[2]) ^ E_KEY[2]; + b0[3] = le32_to_cpu(src[3]) ^ E_KEY[3]; if (ctx->key_length > 24) { f_nround (b1, b0, kp); @@ -353,10 +353,10 @@ static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) f_nround (b1, b0, kp); f_lround (b0, b1, kp); - u32_out (out, b0[0]); - u32_out (out + 4, b0[1]); - u32_out (out + 8, b0[2]); - u32_out (out + 12, b0[3]); + dst[0] = cpu_to_le32(b0[0]); + dst[1] = cpu_to_le32(b0[1]); + dst[2] = cpu_to_le32(b0[2]); + dst[3] = cpu_to_le32(b0[3]); } /* decrypt a block of text */ @@ -377,14 +377,16 @@ static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in) { const struct aes_ctx *ctx = ctx_arg; + const __le32 *src = (const __le32 *)in; + __le32 *dst = (__le32 *)out; u32 b0[4], b1[4]; const int key_len = ctx->key_length; const u32 *kp = D_KEY + key_len + 20; - b0[0] = u32_in (in) ^ E_KEY[key_len + 24]; - b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25]; - b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26]; - b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27]; + b0[0] = le32_to_cpu(src[0]) ^ E_KEY[key_len + 24]; + b0[1] = le32_to_cpu(src[1]) ^ E_KEY[key_len + 25]; + b0[2] = le32_to_cpu(src[2]) ^ E_KEY[key_len + 26]; + b0[3] = le32_to_cpu(src[3]) ^ E_KEY[key_len + 27]; if (key_len > 24) { i_nround (b1, b0, kp); @@ -407,18 +409,21 @@ static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in) i_nround (b1, b0, kp); i_lround (b0, b1, kp); - u32_out (out, b0[0]); - u32_out (out + 4, b0[1]); - u32_out (out + 8, b0[2]); - u32_out (out + 12, b0[3]); + dst[0] = cpu_to_le32(b0[0]); + dst[1] = cpu_to_le32(b0[1]); + dst[2] = cpu_to_le32(b0[2]); + dst[3] = cpu_to_le32(b0[3]); } static struct crypto_alg aes_alg = { .cra_name = "aes", + .cra_driver_name = "aes-generic", + .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), .cra_u = { diff --git a/crypto/anubis.c b/crypto/anubis.c index 3925eb0133cb..2c796bdb91a6 100644 --- a/crypto/anubis.c +++ b/crypto/anubis.c @@ -32,8 +32,10 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> +#include <asm/byteorder.h> #include <asm/scatterlist.h> #include <linux/crypto.h> +#include <linux/types.h> #define ANUBIS_MIN_KEY_SIZE 16 #define ANUBIS_MAX_KEY_SIZE 40 @@ -461,8 +463,8 @@ static const u32 rc[] = { static int anubis_setkey(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { - - int N, R, i, pos, r; + const __be32 *key = (const __be32 *)in_key; + int N, R, i, r; u32 kappa[ANUBIS_MAX_N]; u32 inter[ANUBIS_MAX_N]; @@ -483,13 +485,8 @@ static int anubis_setkey(void *ctx_arg, const u8 *in_key, ctx->R = R = 8 + N; /* * map cipher key to initial key state (mu): */ - for (i = 0, pos = 0; i < N; i++, pos += 4) { - kappa[i] = - (in_key[pos ] << 24) ^ - (in_key[pos + 1] << 16) ^ - (in_key[pos + 2] << 8) ^ - (in_key[pos + 3] ); - } + for (i = 0; i < N; i++) + kappa[i] = be32_to_cpu(key[i]); /* * generate R + 1 round keys: @@ -578,7 +575,9 @@ static int anubis_setkey(void *ctx_arg, const u8 *in_key, static void anubis_crypt(u32 roundKey[ANUBIS_MAX_ROUNDS + 1][4], u8 *ciphertext, const u8 *plaintext, const int R) { - int i, pos, r; + const __be32 *src = (const __be32 *)plaintext; + __be32 *dst = (__be32 *)ciphertext; + int i, r; u32 state[4]; u32 inter[4]; @@ -586,14 +585,8 @@ static void anubis_crypt(u32 roundKey[ANUBIS_MAX_ROUNDS + 1][4], * map plaintext block to cipher state (mu) * and add initial round key (sigma[K^0]): */ - for (i = 0, pos = 0; i < 4; i++, pos += 4) { - state[i] = - (plaintext[pos ] << 24) ^ - (plaintext[pos + 1] << 16) ^ - (plaintext[pos + 2] << 8) ^ - (plaintext[pos + 3] ) ^ - roundKey[0][i]; - } + for (i = 0; i < 4; i++) + state[i] = be32_to_cpu(src[i]) ^ roundKey[0][i]; /* * R - 1 full rounds: @@ -663,13 +656,8 @@ static void anubis_crypt(u32 roundKey[ANUBIS_MAX_ROUNDS + 1][4], * map cipher state to ciphertext block (mu^{-1}): */ - for (i = 0, pos = 0; i < 4; i++, pos += 4) { - u32 w = inter[i]; - ciphertext[pos ] = (u8)(w >> 24); - ciphertext[pos + 1] = (u8)(w >> 16); - ciphertext[pos + 2] = (u8)(w >> 8); - ciphertext[pos + 3] = (u8)(w ); - } + for (i = 0; i < 4; i++) + dst[i] = cpu_to_be32(inter[i]); } static void anubis_encrypt(void *ctx_arg, u8 *dst, const u8 *src) @@ -689,6 +677,7 @@ static struct crypto_alg anubis_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = ANUBIS_BLOCK_SIZE, .cra_ctxsize = sizeof (struct anubis_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(anubis_alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/api.c b/crypto/api.c index 40ae42e9b6a6..e26156f71839 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -3,6 +3,7 @@ * * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> * * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> * and Nettle, by Niels Möller. @@ -18,9 +19,11 @@ #include <linux/init.h> #include <linux/crypto.h> #include <linux/errno.h> +#include <linux/kernel.h> #include <linux/kmod.h> #include <linux/rwsem.h> #include <linux/slab.h> +#include <linux/string.h> #include "internal.h" LIST_HEAD(crypto_alg_list); @@ -39,6 +42,7 @@ static inline void crypto_alg_put(struct crypto_alg *alg) static struct crypto_alg *crypto_alg_lookup(const char *name) { struct crypto_alg *q, *alg = NULL; + int best = -1; if (!name) return NULL; @@ -46,11 +50,23 @@ static struct crypto_alg *crypto_alg_lookup(const char *name) down_read(&crypto_alg_sem); list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!(strcmp(q->cra_name, name))) { - if (crypto_alg_get(q)) - alg = q; + int exact, fuzzy; + + exact = !strcmp(q->cra_driver_name, name); + fuzzy = !strcmp(q->cra_name, name); + if (!exact && !(fuzzy && q->cra_priority > best)) + continue; + + if (unlikely(!crypto_alg_get(q))) + continue; + + best = q->cra_priority; + if (alg) + crypto_alg_put(alg); + alg = q; + + if (exact) break; - } } up_read(&crypto_alg_sem); @@ -207,9 +223,26 @@ void crypto_free_tfm(struct crypto_tfm *tfm) kfree(tfm); } +static inline int crypto_set_driver_name(struct crypto_alg *alg) +{ + static const char suffix[] = "-generic"; + char *driver_name = (char *)alg->cra_driver_name; + int len; + + if (*driver_name) + return 0; + + len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); + if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME) + return -ENAMETOOLONG; + + memcpy(driver_name + len, suffix, sizeof(suffix)); + return 0; +} + int crypto_register_alg(struct crypto_alg *alg) { - int ret = 0; + int ret; struct crypto_alg *q; if (alg->cra_alignmask & (alg->cra_alignmask + 1)) @@ -218,13 +251,20 @@ int crypto_register_alg(struct crypto_alg *alg) if (alg->cra_alignmask & alg->cra_blocksize) return -EINVAL; - if (alg->cra_blocksize > PAGE_SIZE) + if (alg->cra_blocksize > PAGE_SIZE / 8) + return -EINVAL; + + if (alg->cra_priority < 0) return -EINVAL; + ret = crypto_set_driver_name(alg); + if (unlikely(ret)) + return ret; + down_write(&crypto_alg_sem); list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!(strcmp(q->cra_name, alg->cra_name))) { + if (!strcmp(q->cra_driver_name, alg->cra_driver_name)) { ret = -EEXIST; goto out; } diff --git a/crypto/blowfish.c b/crypto/blowfish.c index a8b29d54e7d8..7f710b201f20 100644 --- a/crypto/blowfish.c +++ b/crypto/blowfish.c @@ -19,8 +19,10 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> +#include <asm/byteorder.h> #include <asm/scatterlist.h> #include <linux/crypto.h> +#include <linux/types.h> #define BF_BLOCK_SIZE 8 #define BF_MIN_KEY_SIZE 4 @@ -451,6 +453,7 @@ static struct crypto_alg alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = BF_BLOCK_SIZE, .cra_ctxsize = sizeof(struct bf_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/cast5.c b/crypto/cast5.c index bc42f42b4fe3..8834c8580c04 100644 --- a/crypto/cast5.c +++ b/crypto/cast5.c @@ -21,11 +21,13 @@ */ +#include <asm/byteorder.h> #include <linux/init.h> #include <linux/crypto.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/string.h> +#include <linux/types.h> #define CAST5_BLOCK_SIZE 8 #define CAST5_MIN_KEY_SIZE 5 @@ -578,6 +580,8 @@ static const u32 sb8[256] = { static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf) { struct cast5_ctx *c = (struct cast5_ctx *) ctx; + const __be32 *src = (const __be32 *)inbuf; + __be32 *dst = (__be32 *)outbuf; u32 l, r, t; u32 I; /* used by the Fx macros */ u32 *Km; @@ -589,8 +593,8 @@ static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf) /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) */ - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + l = be32_to_cpu(src[0]); + r = be32_to_cpu(src[1]); /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: * Li = Ri-1; @@ -634,19 +638,15 @@ static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf) /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and * concatenate to form the ciphertext.) */ - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; + dst[0] = cpu_to_be32(r); + dst[1] = cpu_to_be32(l); } static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf) { struct cast5_ctx *c = (struct cast5_ctx *) ctx; + const __be32 *src = (const __be32 *)inbuf; + __be32 *dst = (__be32 *)outbuf; u32 l, r, t; u32 I; u32 *Km; @@ -655,8 +655,8 @@ static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf) Km = c->Km; Kr = c->Kr; - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + l = be32_to_cpu(src[0]); + r = be32_to_cpu(src[1]); if (!(c->rr)) { t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); @@ -690,14 +690,8 @@ static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf) t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]); } - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; + dst[0] = cpu_to_be32(r); + dst[1] = cpu_to_be32(l); } static void key_schedule(u32 * x, u32 * z, u32 * k) @@ -782,7 +776,7 @@ cast5_setkey(void *ctx, const u8 * key, unsigned key_len, u32 * flags) u32 x[4]; u32 z[4]; u32 k[16]; - u8 p_key[16]; + __be32 p_key[4]; struct cast5_ctx *c = (struct cast5_ctx *) ctx; if (key_len < 5 || key_len > 16) { @@ -796,12 +790,10 @@ cast5_setkey(void *ctx, const u8 * key, unsigned key_len, u32 * flags) memcpy(p_key, key, key_len); - x[0] = p_key[0] << 24 | p_key[1] << 16 | p_key[2] << 8 | p_key[3]; - x[1] = p_key[4] << 24 | p_key[5] << 16 | p_key[6] << 8 | p_key[7]; - x[2] = - p_key[8] << 24 | p_key[9] << 16 | p_key[10] << 8 | p_key[11]; - x[3] = - p_key[12] << 24 | p_key[13] << 16 | p_key[14] << 8 | p_key[15]; + x[0] = be32_to_cpu(p_key[0]); + x[1] = be32_to_cpu(p_key[1]); + x[2] = be32_to_cpu(p_key[2]); + x[3] = be32_to_cpu(p_key[3]); key_schedule(x, z, k); for (i = 0; i < 16; i++) @@ -817,6 +809,7 @@ static struct crypto_alg alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = CAST5_BLOCK_SIZE, .cra_ctxsize = sizeof(struct cast5_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { diff --git a/crypto/cast6.c b/crypto/cast6.c index 3eb081073423..9e28740ba775 100644 --- a/crypto/cast6.c +++ b/crypto/cast6.c @@ -18,11 +18,13 @@ */ +#include <asm/byteorder.h> #include <linux/init.h> #include <linux/crypto.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/string.h> +#include <linux/types.h> #define CAST6_BLOCK_SIZE 16 #define CAST6_MIN_KEY_SIZE 16 @@ -384,7 +386,7 @@ cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags) { int i; u32 key[8]; - u8 p_key[32]; /* padded key */ + __be32 p_key[8]; /* padded key */ struct cast6_ctx *c = (struct cast6_ctx *) ctx; if (key_len < 16 || key_len > 32 || key_len % 4 != 0) { @@ -395,14 +397,14 @@ cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags) memset (p_key, 0, 32); memcpy (p_key, in_key, key_len); - key[0] = p_key[0] << 24 | p_key[1] << 16 | p_key[2] << 8 | p_key[3]; /* A */ - key[1] = p_key[4] << 24 | p_key[5] << 16 | p_key[6] << 8 | p_key[7]; /* B */ - key[2] = p_key[8] << 24 | p_key[9] << 16 | p_key[10] << 8 | p_key[11]; /* C */ - key[3] = p_key[12] << 24 | p_key[13] << 16 | p_key[14] << 8 | p_key[15]; /* D */ - key[4] = p_key[16] << 24 | p_key[17] << 16 | p_key[18] << 8 | p_key[19]; /* E */ - key[5] = p_key[20] << 24 | p_key[21] << 16 | p_key[22] << 8 | p_key[23]; /* F */ - key[6] = p_key[24] << 24 | p_key[25] << 16 | p_key[26] << 8 | p_key[27]; /* G */ - key[7] = p_key[28] << 24 | p_key[29] << 16 | p_key[30] << 8 | p_key[31]; /* H */ + key[0] = be32_to_cpu(p_key[0]); /* A */ + key[1] = be32_to_cpu(p_key[1]); /* B */ + key[2] = be32_to_cpu(p_key[2]); /* C */ + key[3] = be32_to_cpu(p_key[3]); /* D */ + key[4] = be32_to_cpu(p_key[4]); /* E */ + key[5] = be32_to_cpu(p_key[5]); /* F */ + key[6] = be32_to_cpu(p_key[6]); /* G */ + key[7] = be32_to_cpu(p_key[7]); /* H */ @@ -444,14 +446,16 @@ static inline void QBAR (u32 * block, u8 * Kr, u32 * Km) { static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { struct cast6_ctx * c = (struct cast6_ctx *)ctx; + const __be32 *src = (const __be32 *)inbuf; + __be32 *dst = (__be32 *)outbuf; u32 block[4]; u32 * Km; u8 * Kr; - block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; - block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11]; - block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15]; + block[0] = be32_to_cpu(src[0]); + block[1] = be32_to_cpu(src[1]); + block[2] = be32_to_cpu(src[2]); + block[3] = be32_to_cpu(src[3]); Km = c->Km[0]; Kr = c->Kr[0]; Q (block, Kr, Km); Km = c->Km[1]; Kr = c->Kr[1]; Q (block, Kr, Km); @@ -465,35 +469,25 @@ static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { Km = c->Km[9]; Kr = c->Kr[9]; QBAR (block, Kr, Km); Km = c->Km[10]; Kr = c->Kr[10]; QBAR (block, Kr, Km); Km = c->Km[11]; Kr = c->Kr[11]; QBAR (block, Kr, Km); - - outbuf[0] = (block[0] >> 24) & 0xff; - outbuf[1] = (block[0] >> 16) & 0xff; - outbuf[2] = (block[0] >> 8) & 0xff; - outbuf[3] = block[0] & 0xff; - outbuf[4] = (block[1] >> 24) & 0xff; - outbuf[5] = (block[1] >> 16) & 0xff; - outbuf[6] = (block[1] >> 8) & 0xff; - outbuf[7] = block[1] & 0xff; - outbuf[8] = (block[2] >> 24) & 0xff; - outbuf[9] = (block[2] >> 16) & 0xff; - outbuf[10] = (block[2] >> 8) & 0xff; - outbuf[11] = block[2] & 0xff; - outbuf[12] = (block[3] >> 24) & 0xff; - outbuf[13] = (block[3] >> 16) & 0xff; - outbuf[14] = (block[3] >> 8) & 0xff; - outbuf[15] = block[3] & 0xff; + + dst[0] = cpu_to_be32(block[0]); + dst[1] = cpu_to_be32(block[1]); + dst[2] = cpu_to_be32(block[2]); + dst[3] = cpu_to_be32(block[3]); } static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { struct cast6_ctx * c = (struct cast6_ctx *)ctx; + const __be32 *src = (const __be32 *)inbuf; + __be32 *dst = (__be32 *)outbuf; u32 block[4]; u32 * Km; u8 * Kr; - block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; - block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11]; - block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15]; + block[0] = be32_to_cpu(src[0]); + block[1] = be32_to_cpu(src[1]); + block[2] = be32_to_cpu(src[2]); + block[3] = be32_to_cpu(src[3]); Km = c->Km[11]; Kr = c->Kr[11]; Q (block, Kr, Km); Km = c->Km[10]; Kr = c->Kr[10]; Q (block, Kr, Km); @@ -508,22 +502,10 @@ static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { Km = c->Km[1]; Kr = c->Kr[1]; QBAR (block, Kr, Km); Km = c->Km[0]; Kr = c->Kr[0]; QBAR (block, Kr, Km); - outbuf[0] = (block[0] >> 24) & 0xff; - outbuf[1] = (block[0] >> 16) & 0xff; - outbuf[2] = (block[0] >> 8) & 0xff; - outbuf[3] = block[0] & 0xff; - outbuf[4] = (block[1] >> 24) & 0xff; - outbuf[5] = (block[1] >> 16) & 0xff; - outbuf[6] = (block[1] >> 8) & 0xff; - outbuf[7] = block[1] & 0xff; - outbuf[8] = (block[2] >> 24) & 0xff; - outbuf[9] = (block[2] >> 16) & 0xff; - outbuf[10] = (block[2] >> 8) & 0xff; - outbuf[11] = block[2] & 0xff; - outbuf[12] = (block[3] >> 24) & 0xff; - outbuf[13] = (block[3] >> 16) & 0xff; - outbuf[14] = (block[3] >> 8) & 0xff; - outbuf[15] = block[3] & 0xff; + dst[0] = cpu_to_be32(block[0]); + dst[1] = cpu_to_be32(block[1]); + dst[2] = cpu_to_be32(block[2]); + dst[3] = cpu_to_be32(block[3]); } static struct crypto_alg alg = { @@ -531,6 +513,7 @@ static struct crypto_alg alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = CAST6_BLOCK_SIZE, .cra_ctxsize = sizeof(struct cast6_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { diff --git a/crypto/cipher.c b/crypto/cipher.c index dfd4bcfc5975..65bcea0cd17c 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -212,9 +212,10 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc, struct crypto_tfm *tfm = desc->tfm; void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block; int bsize = crypto_tfm_alg_blocksize(tfm); + unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm); - u8 stack[src == dst ? bsize : 0]; - u8 *buf = stack; + u8 stack[src == dst ? bsize + alignmask : 0]; + u8 *buf = (u8 *)ALIGN((unsigned long)stack, alignmask + 1); u8 **dst_p = src == dst ? &buf : &dst; void (*fn)(void *, u8 *, const u8 *) = desc->crfn; diff --git a/crypto/crc32c.c b/crypto/crc32c.c index 256956cd9377..953362423a5c 100644 --- a/crypto/crc32c.c +++ b/crypto/crc32c.c @@ -16,6 +16,7 @@ #include <linux/string.h> #include <linux/crypto.h> #include <linux/crc32c.h> +#include <linux/types.h> #include <asm/byteorder.h> #define CHKSUM_BLOCK_SIZE 32 diff --git a/crypto/des.c b/crypto/des.c index a3c863dddded..7bb548653dc6 100644 --- a/crypto/des.c +++ b/crypto/des.c @@ -12,11 +12,13 @@ * */ +#include <asm/byteorder.h> #include <linux/bitops.h> #include <linux/init.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/crypto.h> +#include <linux/types.h> #define DES_KEY_SIZE 8 #define DES_EXPKEY_WORDS 32 @@ -947,6 +949,7 @@ static struct crypto_alg des_alg = { .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct des_ctx), .cra_module = THIS_MODULE, + .cra_alignmask = 3, .cra_list = LIST_HEAD_INIT(des_alg.cra_list), .cra_u = { .cipher = { .cia_min_keysize = DES_KEY_SIZE, diff --git a/crypto/internal.h b/crypto/internal.h index 37aa652ce5ce..959e602909a6 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -2,6 +2,7 @@ * Cryptographic API. * * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> * * 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 @@ -16,10 +17,15 @@ #include <linux/highmem.h> #include <linux/interrupt.h> #include <linux/init.h> +#include <linux/list.h> #include <linux/kernel.h> +#include <linux/rwsem.h> #include <linux/slab.h> #include <asm/kmap_types.h> +extern struct list_head crypto_alg_list; +extern struct rw_semaphore crypto_alg_sem; + extern enum km_type crypto_km_types[]; static inline enum km_type crypto_kmap_type(int out) diff --git a/crypto/khazad.c b/crypto/khazad.c index 738cb0dd1e7c..807f2bf4ea24 100644 --- a/crypto/khazad.c +++ b/crypto/khazad.c @@ -22,8 +22,10 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> +#include <asm/byteorder.h> #include <asm/scatterlist.h> #include <linux/crypto.h> +#include <linux/types.h> #define KHAZAD_KEY_SIZE 16 #define KHAZAD_BLOCK_SIZE 8 @@ -755,8 +757,8 @@ static const u64 c[KHAZAD_ROUNDS + 1] = { static int khazad_setkey(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { - struct khazad_ctx *ctx = ctx_arg; + const __be64 *key = (const __be64 *)in_key; int r; const u64 *S = T7; u64 K2, K1; @@ -767,22 +769,8 @@ static int khazad_setkey(void *ctx_arg, const u8 *in_key, return -EINVAL; } - K2 = ((u64)in_key[ 0] << 56) ^ - ((u64)in_key[ 1] << 48) ^ - ((u64)in_key[ 2] << 40) ^ - ((u64)in_key[ 3] << 32) ^ - ((u64)in_key[ 4] << 24) ^ - ((u64)in_key[ 5] << 16) ^ - ((u64)in_key[ 6] << 8) ^ - ((u64)in_key[ 7] ); - K1 = ((u64)in_key[ 8] << 56) ^ - ((u64)in_key[ 9] << 48) ^ - ((u64)in_key[10] << 40) ^ - ((u64)in_key[11] << 32) ^ - ((u64)in_key[12] << 24) ^ - ((u64)in_key[13] << 16) ^ - ((u64)in_key[14] << 8) ^ - ((u64)in_key[15] ); + K2 = be64_to_cpu(key[0]); + K1 = be64_to_cpu(key[1]); /* setup the encrypt key */ for (r = 0; r <= KHAZAD_ROUNDS; r++) { @@ -820,19 +808,12 @@ static int khazad_setkey(void *ctx_arg, const u8 *in_key, static void khazad_crypt(const u64 roundKey[KHAZAD_ROUNDS + 1], u8 *ciphertext, const u8 *plaintext) { - + const __be64 *src = (const __be64 *)plaintext; + __be64 *dst = (__be64 *)ciphertext; int r; u64 state; - state = ((u64)plaintext[0] << 56) ^ - ((u64)plaintext[1] << 48) ^ - ((u64)plaintext[2] << 40) ^ - ((u64)plaintext[3] << 32) ^ - ((u64)plaintext[4] << 24) ^ - ((u64)plaintext[5] << 16) ^ - ((u64)plaintext[6] << 8) ^ - ((u64)plaintext[7] ) ^ - roundKey[0]; + state = be64_to_cpu(*src) ^ roundKey[0]; for (r = 1; r < KHAZAD_ROUNDS; r++) { state = T0[(int)(state >> 56) ] ^ @@ -856,15 +837,7 @@ static void khazad_crypt(const u64 roundKey[KHAZAD_ROUNDS + 1], (T7[(int)(state ) & 0xff] & 0x00000000000000ffULL) ^ roundKey[KHAZAD_ROUNDS]; - ciphertext[0] = (u8)(state >> 56); - ciphertext[1] = (u8)(state >> 48); - ciphertext[2] = (u8)(state >> 40); - ciphertext[3] = (u8)(state >> 32); - ciphertext[4] = (u8)(state >> 24); - ciphertext[5] = (u8)(state >> 16); - ciphertext[6] = (u8)(state >> 8); - ciphertext[7] = (u8)(state ); - + *dst = cpu_to_be64(state); } static void khazad_encrypt(void *ctx_arg, u8 *dst, const u8 *src) @@ -884,6 +857,7 @@ static struct crypto_alg khazad_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = KHAZAD_BLOCK_SIZE, .cra_ctxsize = sizeof (struct khazad_ctx), + .cra_alignmask = 7, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(khazad_alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/md4.c b/crypto/md4.c index bef6a9e5ac9b..a2d6df5c0f8c 100644 --- a/crypto/md4.c +++ b/crypto/md4.c @@ -24,6 +24,7 @@ #include <linux/crypto.h> #include <linux/kernel.h> #include <linux/string.h> +#include <linux/types.h> #include <asm/byteorder.h> #define MD4_DIGEST_SIZE 16 diff --git a/crypto/md5.c b/crypto/md5.c index 1ed45f9c263e..7f041aef5da2 100644 --- a/crypto/md5.c +++ b/crypto/md5.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/string.h> #include <linux/crypto.h> +#include <linux/types.h> #include <asm/byteorder.h> #define MD5_DIGEST_SIZE 16 diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c index a470bcb3693e..4f6ab23e14ad 100644 --- a/crypto/michael_mic.c +++ b/crypto/michael_mic.c @@ -10,10 +10,12 @@ * published by the Free Software Foundation. */ +#include <asm/byteorder.h> #include <linux/init.h> #include <linux/module.h> #include <linux/string.h> #include <linux/crypto.h> +#include <linux/types.h> struct michael_mic_ctx { @@ -43,21 +45,6 @@ do { \ } while (0) -static inline u32 get_le32(const u8 *p) -{ - return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); -} - - -static inline void put_le32(u8 *p, u32 v) -{ - p[0] = v; - p[1] = v >> 8; - p[2] = v >> 16; - p[3] = v >> 24; -} - - static void michael_init(void *ctx) { struct michael_mic_ctx *mctx = ctx; @@ -68,6 +55,7 @@ static void michael_init(void *ctx) static void michael_update(void *ctx, const u8 *data, unsigned int len) { struct michael_mic_ctx *mctx = ctx; + const __le32 *src; if (mctx->pending_len) { int flen = 4 - mctx->pending_len; @@ -81,21 +69,23 @@ static void michael_update(void *ctx, const u8 *data, unsigned int len) if (mctx->pending_len < 4) return; - mctx->l ^= get_le32(mctx->pending); + src = (const __le32 *)mctx->pending; + mctx->l ^= le32_to_cpup(src); michael_block(mctx->l, mctx->r); mctx->pending_len = 0; } + src = (const __le32 *)data; + while (len >= 4) { - mctx->l ^= get_le32(data); + mctx->l ^= le32_to_cpup(src++); michael_block(mctx->l, mctx->r); - data += 4; len -= 4; } if (len > 0) { mctx->pending_len = len; - memcpy(mctx->pending, data, len); + memcpy(mctx->pending, src, len); } } @@ -104,6 +94,7 @@ static void michael_final(void *ctx, u8 *out) { struct michael_mic_ctx *mctx = ctx; u8 *data = mctx->pending; + __le32 *dst = (__le32 *)out; /* Last block and padding (0x5a, 4..7 x 0) */ switch (mctx->pending_len) { @@ -125,8 +116,8 @@ static void michael_final(void *ctx, u8 *out) /* l ^= 0; */ michael_block(mctx->l, mctx->r); - put_le32(out, mctx->l); - put_le32(out + 4, mctx->r); + dst[0] = cpu_to_le32(mctx->l); + dst[1] = cpu_to_le32(mctx->r); } @@ -134,13 +125,16 @@ static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) { struct michael_mic_ctx *mctx = ctx; + const __le32 *data = (const __le32 *)key; + if (keylen != 8) { if (flags) *flags = CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } - mctx->l = get_le32(key); - mctx->r = get_le32(key + 4); + + mctx->l = le32_to_cpu(data[0]); + mctx->r = le32_to_cpu(data[1]); return 0; } diff --git a/crypto/proc.c b/crypto/proc.c index 630ba91c08f1..c0a5dd7ce2cc 100644 --- a/crypto/proc.c +++ b/crypto/proc.c @@ -4,6 +4,7 @@ * Procfs information. * * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> * * 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 @@ -18,9 +19,6 @@ #include <linux/seq_file.h> #include "internal.h" -extern struct list_head crypto_alg_list; -extern struct rw_semaphore crypto_alg_sem; - static void *c_start(struct seq_file *m, loff_t *pos) { struct list_head *v; @@ -53,7 +51,9 @@ static int c_show(struct seq_file *m, void *p) struct crypto_alg *alg = (struct crypto_alg *)p; seq_printf(m, "name : %s\n", alg->cra_name); + seq_printf(m, "driver : %s\n", alg->cra_driver_name); seq_printf(m, "module : %s\n", module_name(alg->cra_module)); + seq_printf(m, "priority : %d\n", alg->cra_priority); switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_CIPHER: diff --git a/crypto/serpent.c b/crypto/serpent.c index 3cf2c5067eea..52ad1a492620 100644 --- a/crypto/serpent.c +++ b/crypto/serpent.c @@ -20,6 +20,7 @@ #include <linux/errno.h> #include <asm/byteorder.h> #include <linux/crypto.h> +#include <linux/types.h> /* Key is padded to the maximum of 256 bits before round key generation. * Any key length <= 256 bits (32 bytes) is allowed by the algorithm. @@ -552,6 +553,7 @@ static struct crypto_alg tnepres_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = SERPENT_BLOCK_SIZE, .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(serpent_alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/sha1.c b/crypto/sha1.c index 4016f3b8ce9b..21571ed35b7e 100644 --- a/crypto/sha1.c +++ b/crypto/sha1.c @@ -21,6 +21,7 @@ #include <linux/mm.h> #include <linux/crypto.h> #include <linux/cryptohash.h> +#include <linux/types.h> #include <asm/scatterlist.h> #include <asm/byteorder.h> @@ -48,23 +49,33 @@ static void sha1_init(void *ctx) static void sha1_update(void *ctx, const u8 *data, unsigned int len) { struct sha1_ctx *sctx = ctx; - unsigned int i, j; - u32 temp[SHA_WORKSPACE_WORDS]; + unsigned int partial, done; + const u8 *src; - j = (sctx->count >> 3) & 0x3f; - sctx->count += len << 3; + partial = sctx->count & 0x3f; + sctx->count += len; + done = 0; + src = data; - if ((j + len) > 63) { - memcpy(&sctx->buffer[j], data, (i = 64-j)); - sha_transform(sctx->state, sctx->buffer, temp); - for ( ; i + 63 < len; i += 64) { - sha_transform(sctx->state, &data[i], temp); + if ((partial + len) > 63) { + u32 temp[SHA_WORKSPACE_WORDS]; + + if (partial) { + done = -partial; + memcpy(sctx->buffer + partial, data, done + 64); + src = sctx->buffer; } - j = 0; + + do { + sha_transform(sctx->state, src, temp); + done += 64; + src = data + done; + } while (done + 63 < len); + + memset(temp, 0, sizeof(temp)); + partial = 0; } - else i = 0; - memset(temp, 0, sizeof(temp)); - memcpy(&sctx->buffer[j], &data[i], len - i); + memcpy(sctx->buffer + partial, src, len - done); } @@ -72,37 +83,24 @@ static void sha1_update(void *ctx, const u8 *data, unsigned int len) static void sha1_final(void* ctx, u8 *out) { struct sha1_ctx *sctx = ctx; - u32 i, j, index, padlen; - u64 t; - u8 bits[8] = { 0, }; + __be32 *dst = (__be32 *)out; + u32 i, index, padlen; + __be64 bits; static const u8 padding[64] = { 0x80, }; - t = sctx->count; - bits[7] = 0xff & t; t>>=8; - bits[6] = 0xff & t; t>>=8; - bits[5] = 0xff & t; t>>=8; - bits[4] = 0xff & t; t>>=8; - bits[3] = 0xff & t; t>>=8; - bits[2] = 0xff & t; t>>=8; - bits[1] = 0xff & t; t>>=8; - bits[0] = 0xff & t; + bits = cpu_to_be64(sctx->count << 3); /* Pad out to 56 mod 64 */ - index = (sctx->count >> 3) & 0x3f; + index = sctx->count & 0x3f; padlen = (index < 56) ? (56 - index) : ((64+56) - index); sha1_update(sctx, padding, padlen); /* Append length */ - sha1_update(sctx, bits, sizeof bits); + sha1_update(sctx, (const u8 *)&bits, sizeof(bits)); /* Store state in digest */ - for (i = j = 0; i < 5; i++, j += 4) { - u32 t2 = sctx->state[i]; - out[j+3] = t2 & 0xff; t2>>=8; - out[j+2] = t2 & 0xff; t2>>=8; - out[j+1] = t2 & 0xff; t2>>=8; - out[j ] = t2 & 0xff; - } + for (i = 0; i < 5; i++) + dst[i] = cpu_to_be32(sctx->state[i]); /* Wipe context */ memset(sctx, 0, sizeof *sctx); diff --git a/crypto/sha256.c b/crypto/sha256.c index c78da50a9b7a..9d5ef674d6a9 100644 --- a/crypto/sha256.c +++ b/crypto/sha256.c @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/mm.h> #include <linux/crypto.h> +#include <linux/types.h> #include <asm/scatterlist.h> #include <asm/byteorder.h> @@ -279,22 +280,15 @@ static void sha256_update(void *ctx, const u8 *data, unsigned int len) static void sha256_final(void* ctx, u8 *out) { struct sha256_ctx *sctx = ctx; - u8 bits[8]; - unsigned int index, pad_len, t; - int i, j; + __be32 *dst = (__be32 *)out; + __be32 bits[2]; + unsigned int index, pad_len; + int i; static const u8 padding[64] = { 0x80, }; /* Save number of bits */ - t = sctx->count[0]; - bits[7] = t; t >>= 8; - bits[6] = t; t >>= 8; - bits[5] = t; t >>= 8; - bits[4] = t; - t = sctx->count[1]; - bits[3] = t; t >>= 8; - bits[2] = t; t >>= 8; - bits[1] = t; t >>= 8; - bits[0] = t; + bits[1] = cpu_to_be32(sctx->count[0]); + bits[0] = cpu_to_be32(sctx->count[1]); /* Pad out to 56 mod 64. */ index = (sctx->count[0] >> 3) & 0x3f; @@ -302,16 +296,11 @@ static void sha256_final(void* ctx, u8 *out) sha256_update(sctx, padding, pad_len); /* Append length (before padding) */ - sha256_update(sctx, bits, 8); + sha256_update(sctx, (const u8 *)bits, sizeof(bits)); /* Store state in digest */ - for (i = j = 0; i < 8; i++, j += 4) { - t = sctx->state[i]; - out[j+3] = t; t >>= 8; - out[j+2] = t; t >>= 8; - out[j+1] = t; t >>= 8; - out[j ] = t; - } + for (i = 0; i < 8; i++) + dst[i] = cpu_to_be32(sctx->state[i]); /* Zeroize sensitive information. */ memset(sctx, 0, sizeof(*sctx)); diff --git a/crypto/sha512.c b/crypto/sha512.c index c663438322e9..3e6e9392310c 100644 --- a/crypto/sha512.c +++ b/crypto/sha512.c @@ -17,6 +17,7 @@ #include <linux/mm.h> #include <linux/init.h> #include <linux/crypto.h> +#include <linux/types.h> #include <asm/scatterlist.h> #include <asm/byteorder.h> @@ -235,39 +236,17 @@ static void sha512_final(void *ctx, u8 *hash) { struct sha512_ctx *sctx = ctx; - static u8 padding[128] = { 0x80, }; - - u32 t; - u64 t2; - u8 bits[128]; + __be64 *dst = (__be64 *)hash; + __be32 bits[4]; unsigned int index, pad_len; - int i, j; - - index = pad_len = t = i = j = 0; - t2 = 0; + int i; /* Save number of bits */ - t = sctx->count[0]; - bits[15] = t; t>>=8; - bits[14] = t; t>>=8; - bits[13] = t; t>>=8; - bits[12] = t; - t = sctx->count[1]; - bits[11] = t; t>>=8; - bits[10] = t; t>>=8; - bits[9 ] = t; t>>=8; - bits[8 ] = t; - t = sctx->count[2]; - bits[7 ] = t; t>>=8; - bits[6 ] = t; t>>=8; - bits[5 ] = t; t>>=8; - bits[4 ] = t; - t = sctx->count[3]; - bits[3 ] = t; t>>=8; - bits[2 ] = t; t>>=8; - bits[1 ] = t; t>>=8; - bits[0 ] = t; + bits[3] = cpu_to_be32(sctx->count[0]); + bits[2] = cpu_to_be32(sctx->count[1]); + bits[1] = cpu_to_be32(sctx->count[2]); + bits[0] = cpu_to_be32(sctx->count[3]); /* Pad out to 112 mod 128. */ index = (sctx->count[0] >> 3) & 0x7f; @@ -275,21 +254,12 @@ sha512_final(void *ctx, u8 *hash) sha512_update(sctx, padding, pad_len); /* Append length (before padding) */ - sha512_update(sctx, bits, 16); + sha512_update(sctx, (const u8 *)bits, sizeof(bits)); /* Store state in digest */ - for (i = j = 0; i < 8; i++, j += 8) { - t2 = sctx->state[i]; - hash[j+7] = (char)t2 & 0xff; t2>>=8; - hash[j+6] = (char)t2 & 0xff; t2>>=8; - hash[j+5] = (char)t2 & 0xff; t2>>=8; - hash[j+4] = (char)t2 & 0xff; t2>>=8; - hash[j+3] = (char)t2 & 0xff; t2>>=8; - hash[j+2] = (char)t2 & 0xff; t2>>=8; - hash[j+1] = (char)t2 & 0xff; t2>>=8; - hash[j ] = (char)t2 & 0xff; - } - + for (i = 0; i < 8; i++) + dst[i] = cpu_to_be64(sctx->state[i]); + /* Zeroize sensitive information. */ memset(sctx, 0, sizeof(struct sha512_ctx)); } diff --git a/crypto/tea.c b/crypto/tea.c index 5924efdd3a16..a6a02b30e470 100644 --- a/crypto/tea.c +++ b/crypto/tea.c @@ -22,8 +22,10 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> +#include <asm/byteorder.h> #include <asm/scatterlist.h> #include <linux/crypto.h> +#include <linux/types.h> #define TEA_KEY_SIZE 16 #define TEA_BLOCK_SIZE 8 @@ -35,9 +37,6 @@ #define XTEA_ROUNDS 32 #define XTEA_DELTA 0x9e3779b9 -#define u32_in(x) le32_to_cpu(*(const __le32 *)(x)) -#define u32_out(to, from) (*(__le32 *)(to) = cpu_to_le32(from)) - struct tea_ctx { u32 KEY[4]; }; @@ -49,8 +48,8 @@ struct xtea_ctx { static int tea_setkey(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { - struct tea_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; if (key_len != 16) { @@ -58,10 +57,10 @@ static int tea_setkey(void *ctx_arg, const u8 *in_key, return -EINVAL; } - ctx->KEY[0] = u32_in (in_key); - ctx->KEY[1] = u32_in (in_key + 4); - ctx->KEY[2] = u32_in (in_key + 8); - ctx->KEY[3] = u32_in (in_key + 12); + ctx->KEY[0] = le32_to_cpu(key[0]); + ctx->KEY[1] = le32_to_cpu(key[1]); + ctx->KEY[2] = le32_to_cpu(key[2]); + ctx->KEY[3] = le32_to_cpu(key[3]); return 0; @@ -73,9 +72,11 @@ static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) u32 k0, k1, k2, k3; struct tea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); k0 = ctx->KEY[0]; k1 = ctx->KEY[1]; @@ -90,19 +91,20 @@ static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3); } - u32_out (dst, y); - u32_out (dst + 4, z); + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) { u32 y, z, n, sum; u32 k0, k1, k2, k3; - struct tea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); k0 = ctx->KEY[0]; k1 = ctx->KEY[1]; @@ -119,16 +121,15 @@ static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) sum -= TEA_DELTA; } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static int xtea_setkey(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { - struct xtea_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; if (key_len != 16) { @@ -136,10 +137,10 @@ static int xtea_setkey(void *ctx_arg, const u8 *in_key, return -EINVAL; } - ctx->KEY[0] = u32_in (in_key); - ctx->KEY[1] = u32_in (in_key + 4); - ctx->KEY[2] = u32_in (in_key + 8); - ctx->KEY[3] = u32_in (in_key + 12); + ctx->KEY[0] = le32_to_cpu(key[0]); + ctx->KEY[1] = le32_to_cpu(key[1]); + ctx->KEY[2] = le32_to_cpu(key[2]); + ctx->KEY[3] = le32_to_cpu(key[3]); return 0; @@ -147,14 +148,15 @@ static int xtea_setkey(void *ctx_arg, const u8 *in_key, static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) { - u32 y, z, sum = 0; u32 limit = XTEA_DELTA * XTEA_ROUNDS; struct xtea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); while (sum != limit) { y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]); @@ -162,19 +164,19 @@ static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]); } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) { - u32 y, z, sum; struct tea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); sum = XTEA_DELTA * XTEA_ROUNDS; @@ -184,22 +186,22 @@ static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]); } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src) { - u32 y, z, sum = 0; u32 limit = XTEA_DELTA * XTEA_ROUNDS; struct xtea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); while (sum != limit) { y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; @@ -207,19 +209,19 @@ static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src) z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src) { - u32 y, z, sum; struct tea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); sum = XTEA_DELTA * XTEA_ROUNDS; @@ -229,9 +231,8 @@ static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src) y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3]; } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static struct crypto_alg tea_alg = { @@ -239,6 +240,7 @@ static struct crypto_alg tea_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = TEA_BLOCK_SIZE, .cra_ctxsize = sizeof (struct tea_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(tea_alg.cra_list), .cra_u = { .cipher = { @@ -254,6 +256,7 @@ static struct crypto_alg xtea_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = XTEA_BLOCK_SIZE, .cra_ctxsize = sizeof (struct xtea_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list), .cra_u = { .cipher = { @@ -269,6 +272,7 @@ static struct crypto_alg xeta_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = XTEA_BLOCK_SIZE, .cra_ctxsize = sizeof (struct xtea_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/tgr192.c b/crypto/tgr192.c index f0a45cf716d0..2d8e44f6fbe9 100644 --- a/crypto/tgr192.c +++ b/crypto/tgr192.c @@ -24,8 +24,10 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> +#include <asm/byteorder.h> #include <asm/scatterlist.h> #include <linux/crypto.h> +#include <linux/types.h> #define TGR192_DIGEST_SIZE 24 #define TGR160_DIGEST_SIZE 20 @@ -467,18 +469,10 @@ static void tgr192_transform(struct tgr192_ctx *tctx, const u8 * data) u64 a, b, c, aa, bb, cc; u64 x[8]; int i; - const u8 *ptr = data; - - for (i = 0; i < 8; i++, ptr += 8) { - x[i] = (((u64)ptr[7] ) << 56) ^ - (((u64)ptr[6] & 0xffL) << 48) ^ - (((u64)ptr[5] & 0xffL) << 40) ^ - (((u64)ptr[4] & 0xffL) << 32) ^ - (((u64)ptr[3] & 0xffL) << 24) ^ - (((u64)ptr[2] & 0xffL) << 16) ^ - (((u64)ptr[1] & 0xffL) << 8) ^ - (((u64)ptr[0] & 0xffL) ); - } + const __le64 *ptr = (const __le64 *)data; + + for (i = 0; i < 8; i++) + x[i] = le64_to_cpu(ptr[i]); /* save */ a = aa = tctx->a; @@ -558,9 +552,10 @@ static void tgr192_update(void *ctx, const u8 * inbuf, unsigned int len) static void tgr192_final(void *ctx, u8 * out) { struct tgr192_ctx *tctx = ctx; + __be64 *dst = (__be64 *)out; + __be64 *be64p; + __le32 *le32p; u32 t, msb, lsb; - u8 *p; - int i, j; tgr192_update(tctx, NULL, 0); /* flush */ ; @@ -594,41 +589,16 @@ static void tgr192_final(void *ctx, u8 * out) memset(tctx->hash, 0, 56); /* fill next block with zeroes */ } /* append the 64 bit count */ - tctx->hash[56] = lsb; - tctx->hash[57] = lsb >> 8; - tctx->hash[58] = lsb >> 16; - tctx->hash[59] = lsb >> 24; - tctx->hash[60] = msb; - tctx->hash[61] = msb >> 8; - tctx->hash[62] = msb >> 16; - tctx->hash[63] = msb >> 24; + le32p = (__le32 *)&tctx->hash[56]; + le32p[0] = cpu_to_le32(lsb); + le32p[1] = cpu_to_le32(msb); + tgr192_transform(tctx, tctx->hash); - p = tctx->hash; - *p++ = tctx->a >> 56; *p++ = tctx->a >> 48; *p++ = tctx->a >> 40; - *p++ = tctx->a >> 32; *p++ = tctx->a >> 24; *p++ = tctx->a >> 16; - *p++ = tctx->a >> 8; *p++ = tctx->a;\ - *p++ = tctx->b >> 56; *p++ = tctx->b >> 48; *p++ = tctx->b >> 40; - *p++ = tctx->b >> 32; *p++ = tctx->b >> 24; *p++ = tctx->b >> 16; - *p++ = tctx->b >> 8; *p++ = tctx->b; - *p++ = tctx->c >> 56; *p++ = tctx->c >> 48; *p++ = tctx->c >> 40; - *p++ = tctx->c >> 32; *p++ = tctx->c >> 24; *p++ = tctx->c >> 16; - *p++ = tctx->c >> 8; *p++ = tctx->c; - - - /* unpack the hash */ - j = 7; - for (i = 0; i < 8; i++) { - out[j--] = (tctx->a >> 8 * i) & 0xff; - } - j = 15; - for (i = 0; i < 8; i++) { - out[j--] = (tctx->b >> 8 * i) & 0xff; - } - j = 23; - for (i = 0; i < 8; i++) { - out[j--] = (tctx->c >> 8 * i) & 0xff; - } + be64p = (__be64 *)tctx->hash; + dst[0] = be64p[0] = cpu_to_be64(tctx->a); + dst[1] = be64p[1] = cpu_to_be64(tctx->b); + dst[2] = be64p[2] = cpu_to_be64(tctx->c); } static void tgr160_final(void *ctx, u8 * out) diff --git a/crypto/twofish.c b/crypto/twofish.c index 4efff8cf9958..a26d885486fb 100644 --- a/crypto/twofish.c +++ b/crypto/twofish.c @@ -37,6 +37,8 @@ * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the * Third Edition. */ + +#include <asm/byteorder.h> #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> @@ -621,13 +623,11 @@ static const u8 calc_sb_tbl[512] = { * whitening subkey number m. */ #define INPACK(n, x, m) \ - x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ - ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] + x = le32_to_cpu(src[n]) ^ ctx->w[m] #define OUTUNPACK(n, x, m) \ x ^= ctx->w[m]; \ - out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ - out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 + dst[n] = cpu_to_le32(x) #define TF_MIN_KEY_SIZE 16 #define TF_MAX_KEY_SIZE 32 @@ -804,6 +804,8 @@ static int twofish_setkey(void *cx, const u8 *key, static void twofish_encrypt(void *cx, u8 *out, const u8 *in) { struct twofish_ctx *ctx = cx; + const __le32 *src = (const __le32 *)in; + __le32 *dst = (__le32 *)out; /* The four 32-bit chunks of the text. */ u32 a, b, c, d; @@ -839,6 +841,8 @@ static void twofish_encrypt(void *cx, u8 *out, const u8 *in) static void twofish_decrypt(void *cx, u8 *out, const u8 *in) { struct twofish_ctx *ctx = cx; + const __le32 *src = (const __le32 *)in; + __le32 *dst = (__le32 *)out; /* The four 32-bit chunks of the text. */ u32 a, b, c, d; @@ -875,6 +879,7 @@ static struct crypto_alg alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = TF_BLOCK_SIZE, .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/wp512.c b/crypto/wp512.c index fd6e20e1f291..b226a126cfae 100644 --- a/crypto/wp512.c +++ b/crypto/wp512.c @@ -22,8 +22,10 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> +#include <asm/byteorder.h> #include <asm/scatterlist.h> #include <linux/crypto.h> +#include <linux/types.h> #define WP512_DIGEST_SIZE 64 #define WP384_DIGEST_SIZE 48 @@ -778,19 +780,10 @@ static void wp512_process_buffer(struct wp512_ctx *wctx) { u64 block[8]; /* mu(buffer) */ u64 state[8]; /* the cipher state */ u64 L[8]; - u8 *buffer = wctx->buffer; + const __be64 *buffer = (const __be64 *)wctx->buffer; - for (i = 0; i < 8; i++, buffer += 8) { - block[i] = - (((u64)buffer[0] ) << 56) ^ - (((u64)buffer[1] & 0xffL) << 48) ^ - (((u64)buffer[2] & 0xffL) << 40) ^ - (((u64)buffer[3] & 0xffL) << 32) ^ - (((u64)buffer[4] & 0xffL) << 24) ^ - (((u64)buffer[5] & 0xffL) << 16) ^ - (((u64)buffer[6] & 0xffL) << 8) ^ - (((u64)buffer[7] & 0xffL) ); - } + for (i = 0; i < 8; i++) + block[i] = be64_to_cpu(buffer[i]); state[0] = block[0] ^ (K[0] = wctx->hash[0]); state[1] = block[1] ^ (K[1] = wctx->hash[1]); @@ -1069,7 +1062,7 @@ static void wp512_final(void *ctx, u8 *out) u8 *bitLength = wctx->bitLength; int bufferBits = wctx->bufferBits; int bufferPos = wctx->bufferPos; - u8 *digest = out; + __be64 *digest = (__be64 *)out; buffer[bufferPos] |= 0x80U >> (bufferBits & 7); bufferPos++; @@ -1088,17 +1081,8 @@ static void wp512_final(void *ctx, u8 *out) memcpy(&buffer[WP512_BLOCK_SIZE - WP512_LENGTHBYTES], bitLength, WP512_LENGTHBYTES); wp512_process_buffer(wctx); - for (i = 0; i < WP512_DIGEST_SIZE/8; i++) { - digest[0] = (u8)(wctx->hash[i] >> 56); - digest[1] = (u8)(wctx->hash[i] >> 48); - digest[2] = (u8)(wctx->hash[i] >> 40); - digest[3] = (u8)(wctx->hash[i] >> 32); - digest[4] = (u8)(wctx->hash[i] >> 24); - digest[5] = (u8)(wctx->hash[i] >> 16); - digest[6] = (u8)(wctx->hash[i] >> 8); - digest[7] = (u8)(wctx->hash[i] ); - digest += 8; - } + for (i = 0; i < WP512_DIGEST_SIZE/8; i++) + digest[i] = cpu_to_be64(wctx->hash[i]); wctx->bufferBits = bufferBits; wctx->bufferPos = bufferPos; } diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 1bbdd1693d57..889855d8d9f9 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -15,7 +15,6 @@ #include <linux/amba/bus.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/sizes.h> #define to_amba_device(d) container_of(d, struct amba_device, dev) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index a452b13620a2..864729046e22 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -215,7 +215,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, unsigned offset, bv_offs; int len, ret; - down(&mapping->host->i_sem); + mutex_lock(&mapping->host->i_mutex); index = pos >> PAGE_CACHE_SHIFT; offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1); bv_offs = bvec->bv_offset; @@ -278,7 +278,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, } ret = 0; out: - up(&mapping->host->i_sem); + mutex_unlock(&mapping->host->i_mutex); return ret; unlock: unlock_page(page); @@ -527,12 +527,12 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio) lo->lo_pending++; loop_add_bio(lo, old_bio); spin_unlock_irq(&lo->lo_lock); - up(&lo->lo_bh_mutex); + complete(&lo->lo_bh_done); return 0; out: if (lo->lo_pending == 0) - up(&lo->lo_bh_mutex); + complete(&lo->lo_bh_done); spin_unlock_irq(&lo->lo_lock); bio_io_error(old_bio, old_bio->bi_size); return 0; @@ -593,23 +593,20 @@ static int loop_thread(void *data) lo->lo_pending = 1; /* - * up sem, we are running + * complete it, we are running */ - up(&lo->lo_sem); + complete(&lo->lo_done); for (;;) { int pending; - /* - * interruptible just to not contribute to load avg - */ - if (down_interruptible(&lo->lo_bh_mutex)) + if (wait_for_completion_interruptible(&lo->lo_bh_done)) continue; spin_lock_irq(&lo->lo_lock); /* - * could be upped because of tear-down, not pending work + * could be completed because of tear-down, not pending work */ if (unlikely(!lo->lo_pending)) { spin_unlock_irq(&lo->lo_lock); @@ -632,7 +629,7 @@ static int loop_thread(void *data) break; } - up(&lo->lo_sem); + complete(&lo->lo_done); return 0; } @@ -843,7 +840,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, set_blocksize(bdev, lo_blocksize); kernel_thread(loop_thread, lo, CLONE_KERNEL); - down(&lo->lo_sem); + wait_for_completion(&lo->lo_done); return 0; out_putf: @@ -909,10 +906,10 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) lo->lo_state = Lo_rundown; lo->lo_pending--; if (!lo->lo_pending) - up(&lo->lo_bh_mutex); + complete(&lo->lo_bh_done); spin_unlock_irq(&lo->lo_lock); - down(&lo->lo_sem); + wait_for_completion(&lo->lo_done); lo->lo_backing_file = NULL; @@ -1289,8 +1286,8 @@ static int __init loop_init(void) if (!lo->lo_queue) goto out_mem4; init_MUTEX(&lo->lo_ctl_mutex); - init_MUTEX_LOCKED(&lo->lo_sem); - init_MUTEX_LOCKED(&lo->lo_bh_mutex); + init_completion(&lo->lo_done); + init_completion(&lo->lo_bh_done); lo->lo_number = i; spin_lock_init(&lo->lo_lock); disk->major = LOOP_MAJOR; diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index a7e0975c8c9f..2ae08b343b93 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c @@ -27,8 +27,8 @@ #include <linux/time.h> #include <linux/hdreg.h> #include <linux/dma-mapping.h> +#include <linux/completion.h> #include <asm/io.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #if 0 @@ -303,7 +303,7 @@ struct carm_host { struct work_struct fsm_task; - struct semaphore probe_sem; + struct completion probe_comp; }; struct carm_response { @@ -1346,7 +1346,7 @@ static void carm_fsm_task (void *_data) } case HST_PROBE_FINISHED: - up(&host->probe_sem); + complete(&host->probe_comp); break; case HST_ERROR: @@ -1622,7 +1622,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) host->flags = pci_dac ? FL_DAC : 0; spin_lock_init(&host->lock); INIT_WORK(&host->fsm_task, carm_fsm_task, host); - init_MUTEX_LOCKED(&host->probe_sem); + init_completion(&host->probe_comp); for (i = 0; i < ARRAY_SIZE(host->req); i++) host->req[i].tag = i; @@ -1691,8 +1691,8 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_free_irq; - DPRINTK("waiting for probe_sem\n"); - down(&host->probe_sem); + DPRINTK("waiting for probe_comp\n"); + wait_for_completion(&host->probe_comp); printk(KERN_INFO "%s: pci %s, ports %d, io %lx, irq %u, major %d\n", host->name, pci_name(pdev), (int) CARM_MAX_PORTS, diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index 01f035173328..ce127f7ec0f6 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -32,7 +32,7 @@ History: 18 mrt 1995: 0.24 Working background read-ahead. (still problems) 26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2). Statistics implemented, though separate stats206.h. - Accessible trough ioctl 0x1000 (just a number). + Accessible through ioctl 0x1000 (just a number). Hard to choose between v1.2 development and 1.1.75. Bottom-half doesn't work with 1.2... 0.25a: fixed... typo. Still problems... diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 5b2d18035073..704c3c07f0ab 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -741,7 +741,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) { loff_t ret; - down(&file->f_dentry->d_inode->i_sem); + mutex_lock(&file->f_dentry->d_inode->i_mutex); switch (orig) { case 0: file->f_pos = offset; @@ -756,7 +756,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) default: ret = -EINVAL; } - up(&file->f_dentry->d_inode->i_sem); + mutex_unlock(&file->f_dentry->d_inode->i_mutex); return ret; } diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 145275ebdd7e..5765f672e853 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -153,6 +153,21 @@ static struct sysrq_key_op sysrq_mountro_op = { /* END SYNC SYSRQ HANDLERS BLOCK */ +#ifdef CONFIG_DEBUG_MUTEXES + +static void +sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty) +{ + mutex_debug_show_all_locks(); +} + +static struct sysrq_key_op sysrq_showlocks_op = { + .handler = sysrq_handle_showlocks, + .help_msg = "show-all-locks(D)", + .action_msg = "Show Locks Held", +}; + +#endif /* SHOW SYSRQ HANDLERS BLOCK */ @@ -294,7 +309,11 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { #else /* c */ NULL, #endif +#ifdef CONFIG_DEBUG_MUTEXES +/* d */ &sysrq_showlocks_op, +#else /* d */ NULL, +#endif /* e */ &sysrq_term_op, /* f */ &sysrq_moom_op, /* g */ NULL, diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c index e75045fe2641..3e8410b5a65e 100644 --- a/drivers/char/watchdog/cpu5wdt.c +++ b/drivers/char/watchdog/cpu5wdt.c @@ -28,6 +28,7 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/timer.h> +#include <linux/completion.h> #include <linux/jiffies.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -57,7 +58,7 @@ static int ticks = 10000; /* some device data */ static struct { - struct semaphore stop; + struct completion stop; volatile int running; struct timer_list timer; volatile int queue; @@ -85,7 +86,7 @@ static void cpu5wdt_trigger(unsigned long unused) } else { /* ticks doesn't matter anyway */ - up(&cpu5wdt_device.stop); + complete(&cpu5wdt_device.stop); } } @@ -239,7 +240,7 @@ static int __devinit cpu5wdt_init(void) if ( !val ) printk(KERN_INFO PFX "sorry, was my fault\n"); - init_MUTEX_LOCKED(&cpu5wdt_device.stop); + init_completion(&cpu5wdt_device.stop); cpu5wdt_device.queue = 0; clear_bit(0, &cpu5wdt_device.inuse); @@ -269,7 +270,7 @@ static void __devexit cpu5wdt_exit(void) { if ( cpu5wdt_device.queue ) { cpu5wdt_device.queue = 0; - down(&cpu5wdt_device.stop); + wait_for_completion(&cpu5wdt_device.stop); } misc_deregister(&cpu5wdt_misc); diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 71407c578afe..64819aa7cac4 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -99,9 +99,6 @@ byte(const uint32_t x, const unsigned n) return x >> (n << 3); } -#define uint32_t_in(x) le32_to_cpu(*(const uint32_t *)(x)) -#define uint32_t_out(to, from) (*(uint32_t *)(to) = cpu_to_le32(from)) - #define E_KEY ctx->E #define D_KEY ctx->D @@ -294,6 +291,7 @@ static int aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t *flags) { struct aes_ctx *ctx = aes_ctx(ctx_arg); + const __le32 *key = (const __le32 *)in_key; uint32_t i, t, u, v, w; uint32_t P[AES_EXTENDED_KEY_SIZE]; uint32_t rounds; @@ -313,10 +311,10 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t ctx->E = ctx->e_data; ctx->D = ctx->e_data; - E_KEY[0] = uint32_t_in (in_key); - E_KEY[1] = uint32_t_in (in_key + 4); - E_KEY[2] = uint32_t_in (in_key + 8); - E_KEY[3] = uint32_t_in (in_key + 12); + E_KEY[0] = le32_to_cpu(key[0]); + E_KEY[1] = le32_to_cpu(key[1]); + E_KEY[2] = le32_to_cpu(key[2]); + E_KEY[3] = le32_to_cpu(key[3]); /* Prepare control words. */ memset(&ctx->cword, 0, sizeof(ctx->cword)); @@ -343,17 +341,17 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t break; case 24: - E_KEY[4] = uint32_t_in (in_key + 16); - t = E_KEY[5] = uint32_t_in (in_key + 20); + E_KEY[4] = le32_to_cpu(key[4]); + t = E_KEY[5] = le32_to_cpu(key[5]); for (i = 0; i < 8; ++i) loop6 (i); break; case 32: - E_KEY[4] = uint32_t_in (in_key + 16); - E_KEY[5] = uint32_t_in (in_key + 20); - E_KEY[6] = uint32_t_in (in_key + 24); - t = E_KEY[7] = uint32_t_in (in_key + 28); + E_KEY[4] = le32_to_cpu(in_key[4]); + E_KEY[5] = le32_to_cpu(in_key[5]); + E_KEY[6] = le32_to_cpu(in_key[6]); + t = E_KEY[7] = le32_to_cpu(in_key[7]); for (i = 0; i < 7; ++i) loop8 (i); break; @@ -468,6 +466,8 @@ static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, static struct crypto_alg aes_alg = { .cra_name = "aes", + .cra_driver_name = "aes-padlock", + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), diff --git a/drivers/crypto/padlock.h b/drivers/crypto/padlock.h index 3cf2b7a12348..b78489bc298a 100644 --- a/drivers/crypto/padlock.h +++ b/drivers/crypto/padlock.h @@ -17,7 +17,7 @@ /* Control word. */ struct cword { - int __attribute__ ((__packed__)) + unsigned int __attribute__ ((__packed__)) rounds:4, algo:3, keygen:1, diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 1ddaa71a8f45..7cb2d86601db 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -655,7 +655,7 @@ static void hwif_release_dev (struct device *dev) { ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev); - up(&hwif->gendev_rel_sem); + complete(&hwif->gendev_rel_comp); } static void hwif_register (ide_hwif_t *hwif) @@ -1327,7 +1327,7 @@ static void drive_release_dev (struct device *dev) drive->queue = NULL; spin_unlock_irq(&ide_lock); - up(&drive->gendev_rel_sem); + complete(&drive->gendev_rel_comp); } /* diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index b069b13b75a7..ec5a4cb173b0 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -222,7 +222,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) hwif->mwdma_mask = 0x80; /* disable all mwdma */ hwif->swdma_mask = 0x80; /* disable all swdma */ - sema_init(&hwif->gendev_rel_sem, 0); + init_completion(&hwif->gendev_rel_comp); default_hwif_iops(hwif); default_hwif_transport(hwif); @@ -245,7 +245,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) drive->is_flash = 0; drive->vdma = 0; INIT_LIST_HEAD(&drive->list); - sema_init(&drive->gendev_rel_sem, 0); + init_completion(&drive->gendev_rel_comp); } } @@ -602,7 +602,7 @@ void ide_unregister(unsigned int index) } spin_unlock_irq(&ide_lock); device_unregister(&drive->gendev); - down(&drive->gendev_rel_sem); + wait_for_completion(&drive->gendev_rel_comp); spin_lock_irq(&ide_lock); } hwif->present = 0; @@ -662,7 +662,7 @@ void ide_unregister(unsigned int index) /* More messed up locking ... */ spin_unlock_irq(&ide_lock); device_unregister(&hwif->gendev); - down(&hwif->gendev_rel_sem); + wait_for_completion(&hwif->gendev_rel_comp); /* * Remove us from the kernel's knowledge diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 3f0df3330fb2..ebd9976fc811 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -20,7 +20,6 @@ #include <linux/spinlock.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/system.h> #include <asm/hardware/sa1111.h> diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 207cae366256..0a37aded4b54 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -138,7 +138,7 @@ static struct dentry *get_node(int num) { char s[10]; struct dentry *root = capifs_root; - down(&root->d_inode->i_sem); + mutex_lock(&root->d_inode->i_mutex); return lookup_one_len(s, root, sprintf(s, "%d", num)); } @@ -159,7 +159,7 @@ void capifs_new_ncci(unsigned int number, dev_t device) dentry = get_node(number); if (!IS_ERR(dentry) && !dentry->d_inode) d_instantiate(dentry, inode); - up(&capifs_root->d_inode->i_sem); + mutex_unlock(&capifs_root->d_inode->i_mutex); } void capifs_free_ncci(unsigned int number) @@ -175,7 +175,7 @@ void capifs_free_ncci(unsigned int number) } dput(dentry); } - up(&capifs_root->d_inode->i_sem); + mutex_unlock(&capifs_root->d_inode->i_mutex); } static int __init capifs_init(void) diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index 8d0958c38b6b..4f50ee5767a2 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -630,12 +630,12 @@ static int read_eeprom(int cpu, struct mpu_data *out) sprintf(nodename, "/u3@0,f8000000/i2c@f8001000/cpuid@a%d", cpu ? 2 : 0); np = of_find_node_by_path(nodename); if (np == NULL) { - printk(KERN_ERR "therm_pm72: Failed to retreive cpuid node from device-tree\n"); + printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid node from device-tree\n"); return -ENODEV; } data = (u8 *)get_property(np, "cpuid", &len); if (data == NULL) { - printk(KERN_ERR "therm_pm72: Failed to retreive cpuid property from device-tree\n"); + printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid property from device-tree\n"); of_node_put(np); return -ENODEV; } diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c index 80ddf9776bde..eb69a601e765 100644 --- a/drivers/macintosh/windfarm_pm81.c +++ b/drivers/macintosh/windfarm_pm81.c @@ -26,7 +26,7 @@ * (typically the drive fan) * - the main control (first control) gets the target value scaled with * the first pair of factors, and is then modified as below - * - the value of the target of the CPU Fan control loop is retreived, + * - the value of the target of the CPU Fan control loop is retrieved, * scaled with the second pair of factors, and the max of that and * the scaled target is applied to the main control. * diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 0e481512f918..5c210b0a4cb0 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -837,9 +837,9 @@ static void __set_size(struct mapped_device *md, sector_t size) { set_capacity(md->disk, size); - down(&md->suspended_bdev->bd_inode->i_sem); + mutex_lock(&md->suspended_bdev->bd_inode->i_mutex); i_size_write(md->suspended_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); - up(&md->suspended_bdev->bd_inode->i_sem); + mutex_unlock(&md->suspended_bdev->bd_inode->i_mutex); } static int __bind(struct mapped_device *md, struct dm_table *t) diff --git a/drivers/md/md.c b/drivers/md/md.c index e423a16ba3c9..0302723fa21f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3460,9 +3460,9 @@ static int update_size(mddev_t *mddev, unsigned long size) bdev = bdget_disk(mddev->gendisk, 0); if (bdev) { - down(&bdev->bd_inode->i_sem); + mutex_lock(&bdev->bd_inode->i_mutex); i_size_write(bdev->bd_inode, mddev->array_size << 10); - up(&bdev->bd_inode->i_sem); + mutex_unlock(&bdev->bd_inode->i_mutex); bdput(bdev); } } @@ -3486,9 +3486,9 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks) bdev = bdget_disk(mddev->gendisk, 0); if (bdev) { - down(&bdev->bd_inode->i_sem); + mutex_lock(&bdev->bd_inode->i_mutex); i_size_write(bdev->bd_inode, mddev->array_size << 10); - up(&bdev->bd_inode->i_sem); + mutex_unlock(&bdev->bd_inode->i_mutex); bdput(bdev); } } diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 09ec964dec5c..b614612be7b4 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -253,7 +253,10 @@ static int fops_open(struct inode *inode, struct file *file) if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { DEB_S(("initializing vbi...\n")); - result = saa7146_vbi_uops.open(dev,file); + if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) + result = saa7146_vbi_uops.open(dev,file); + if (dev->ext_vv_data->vbi_fops.open) + dev->ext_vv_data->vbi_fops.open(inode, file); } else { DEB_S(("initializing video...\n")); result = saa7146_video_uops.open(dev,file); @@ -289,7 +292,10 @@ static int fops_release(struct inode *inode, struct file *file) return -ERESTARTSYS; if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - saa7146_vbi_uops.release(dev,file); + if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) + saa7146_vbi_uops.release(dev,file); + if (dev->ext_vv_data->vbi_fops.release) + dev->ext_vv_data->vbi_fops.release(inode, file); } else { saa7146_video_uops.release(dev,file); } @@ -332,6 +338,7 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma) BUG(); return 0; } + return videobuf_mmap_mapper(q,vma); } @@ -381,7 +388,10 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof } case V4L2_BUF_TYPE_VBI_CAPTURE: { // DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count)); - return saa7146_vbi_uops.read(file,data,count,ppos); + if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) + return saa7146_vbi_uops.read(file,data,count,ppos); + else + return -EINVAL; } break; default: @@ -390,12 +400,31 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof } } +static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos) +{ + struct saa7146_fh *fh = file->private_data; + + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return -EINVAL; + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (fh->dev->ext_vv_data->vbi_fops.write) + return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos); + else + return -EINVAL; + default: + BUG(); + return -EINVAL; + } +} + static struct file_operations video_fops = { .owner = THIS_MODULE, .open = fops_open, .release = fops_release, .read = fops_read, + .write = fops_write, .poll = fops_poll, .mmap = fops_mmap, .ioctl = fops_ioctl, @@ -467,7 +496,8 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM); saa7146_video_uops.init(dev,vv); - saa7146_vbi_uops.init(dev,vv); + if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) + saa7146_vbi_uops.init(dev,vv); dev->vv_data = vv; dev->vv_callback = &vv_callback; diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c index ec52dff8cb69..33bec8a6843b 100644 --- a/drivers/media/common/saa7146_hlp.c +++ b/drivers/media/common/saa7146_hlp.c @@ -562,19 +562,26 @@ static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int int b_depth = vv->ov_fmt->depth; int b_bpl = vv->ov_fb.fmt.bytesperline; - u32 base = (u32)vv->ov_fb.base; + /* The unsigned long cast is to remove a 64-bit compile warning since + it looks like a 64-bit address is cast to a 32-bit value, even + though the base pointer is really a 32-bit physical address that + goes into a 32-bit DMA register. + FIXME: might not work on some 64-bit platforms, but see the FIXME + in struct v4l2_framebuffer (videodev2.h) for that. + */ + u32 base = (u32)(unsigned long)vv->ov_fb.base; struct saa7146_video_dma vdma1; /* calculate memory offsets for picture, look if we shall top-down-flip */ vdma1.pitch = 2*b_bpl; if ( 0 == vv->vflip ) { - vdma1.base_even = (u32)base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8)); + vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8)); vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2); vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2)); } else { - vdma1.base_even = (u32)base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8)); + vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8)); vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2); vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2)); } diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index 063986ec16b5..468d3c959075 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -500,9 +500,9 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff } struct saa7146_use_ops saa7146_vbi_uops = { - .init = vbi_init, - .open = vbi_open, + .init = vbi_init, + .open = vbi_open, .release = vbi_close, .irq_done = vbi_irq_done, - .read = vbi_read, + .read = vbi_read, }; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 1d961023b837..7ebac7949df3 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -151,8 +151,8 @@ static int try_win(struct saa7146_dev *dev, struct v4l2_window *win) if (V4L2_FIELD_ANY == field) { field = (win->w.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_TOP; + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_TOP; } switch (field) { case V4L2_FIELD_TOP: @@ -1114,10 +1114,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int return 0; } case VIDIOC_OVERLAY: - - - - { int on = *(int *)arg; int err = 0; @@ -1359,7 +1355,6 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) saa7146_buffer_queue(fh->dev,&vv->video_q,buf); } - static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { struct file *file = q->priv_data; diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 21a9045b3ef6..0b940e152b79 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -298,7 +298,7 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir } static int lgdt3303_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) + struct dvb_frontend_parameters* params) { struct flexcop_device *fc = fe->dvb->priv; u8 buf[4]; @@ -485,12 +485,16 @@ static struct stv0297_config alps_tdee4_stv0297_config = { /* try to figure out the frontend, each card/box can have on of the following list */ int flexcop_frontend_init(struct flexcop_device *fc) { + struct dvb_frontend_ops *ops; + /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */ if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) { - fc->fe->ops->set_voltage = flexcop_set_voltage; + ops = fc->fe->ops; + + ops->set_voltage = flexcop_set_voltage; - fc->fe_sleep = fc->fe->ops->sleep; - fc->fe->ops->sleep = flexcop_sleep; + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; fc->dev_type = FC_SKY; info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address); @@ -522,15 +526,17 @@ int flexcop_frontend_init(struct flexcop_device *fc) } else /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { - fc->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; - fc->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst; - fc->fe->ops->set_tone = flexcop_set_tone; - fc->fe->ops->set_voltage = flexcop_set_voltage; + ops = fc->fe->ops; + + ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; + ops->diseqc_send_burst = flexcop_diseqc_send_burst; + ops->set_tone = flexcop_set_tone; + ops->set_voltage = flexcop_set_voltage; - fc->fe_sleep = fc->fe->ops->sleep; - fc->fe->ops->sleep = flexcop_sleep; + fc->fe_sleep = ops->sleep; + ops->sleep = flexcop_sleep; - fc->dev_type = FC_SKY_OLD; + fc->dev_type = FC_SKY_OLD; info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address); } @@ -540,8 +546,9 @@ int flexcop_frontend_init(struct flexcop_device *fc) } else { if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { err("frontend registration failed!"); - if (fc->fe->ops->release != NULL) - fc->fe->ops->release(fc->fe); + ops = fc->fe->ops; + if (ops->release != NULL) + ops->release(fc->fe); fc->fe = NULL; return -EINVAL; } diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h index 23cc6431e2b8..3153f9513c63 100644 --- a/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/drivers/media/dvb/b2c2/flexcop-reg.h @@ -39,11 +39,13 @@ extern const char *flexcop_device_names[]; /* FlexCop IBI Registers */ #if defined(__LITTLE_ENDIAN) #include "flexcop_ibi_value_le.h" -#elif defined(__BIG_ENDIAN) +#else +#if defined(__BIG_ENDIAN) #include "flexcop_ibi_value_be.h" #else #error no endian defined #endif +#endif #define fc_data_Tag_ID_DVB 0x3e #define fc_data_Tag_ID_ATSC 0x3f diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 8977c7a313df..3a2ff1cc24b7 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1341,30 +1341,40 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; } -static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) +static int dst_set_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters* p, + unsigned int mode_flags, + int *delay, + fe_status_t *status) { struct dst_state *state = fe->demodulator_priv; - dst_set_freq(state, p->frequency); - dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); + if (p != NULL) { + dst_set_freq(state, p->frequency); + dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); - if (state->dst_type == DST_TYPE_IS_SAT) { - if (state->type_flags & DST_TYPE_HAS_OBS_REGS) - dst_set_inversion(state, p->inversion); - dst_set_fec(state, p->u.qpsk.fec_inner); - dst_set_symbolrate(state, p->u.qpsk.symbol_rate); - dst_set_polarization(state); - dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate); - - } else if (state->dst_type == DST_TYPE_IS_TERR) - dst_set_bandwidth(state, p->u.ofdm.bandwidth); - else if (state->dst_type == DST_TYPE_IS_CABLE) { - dst_set_fec(state, p->u.qam.fec_inner); - dst_set_symbolrate(state, p->u.qam.symbol_rate); - dst_set_modulation(state, p->u.qam.modulation); + if (state->dst_type == DST_TYPE_IS_SAT) { + if (state->type_flags & DST_TYPE_HAS_OBS_REGS) + dst_set_inversion(state, p->inversion); + dst_set_fec(state, p->u.qpsk.fec_inner); + dst_set_symbolrate(state, p->u.qpsk.symbol_rate); + dst_set_polarization(state); + dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate); + + } else if (state->dst_type == DST_TYPE_IS_TERR) + dst_set_bandwidth(state, p->u.ofdm.bandwidth); + else if (state->dst_type == DST_TYPE_IS_CABLE) { + dst_set_fec(state, p->u.qam.fec_inner); + dst_set_symbolrate(state, p->u.qam.symbol_rate); + dst_set_modulation(state, p->u.qam.modulation); + } + dst_write_tuna(fe); } - dst_write_tuna(fe); + if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) + dst_read_status(fe, status); + + *delay = HZ/10; return 0; } @@ -1445,7 +1455,7 @@ static struct dvb_frontend_ops dst_dvbt_ops = { .release = dst_release, .init = dst_init, - .set_frontend = dst_set_frontend, + .tune = dst_set_frontend, .get_frontend = dst_get_frontend, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, @@ -1469,7 +1479,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = { .release = dst_release, .init = dst_init, - .set_frontend = dst_set_frontend, + .tune = dst_set_frontend, .get_frontend = dst_get_frontend, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, @@ -1496,7 +1506,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = { .release = dst_release, .init = dst_init, - .set_frontend = dst_set_frontend, + .tune = dst_set_frontend, .get_frontend = dst_get_frontend, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index 2239651969c8..c650b4bf7f5f 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -283,16 +283,17 @@ static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, hw_buffer->msg[4] = 0x03; hw_buffer->msg[5] = length & 0xff; hw_buffer->msg[6] = 0x00; + /* * Need to compute length for EN50221 section 8.3.2, for the time being * assuming 8.3.2 is not applicable */ memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length); } + return 0; } - static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply) { if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) { diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 77977e9c013e..01b4e0aac049 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -600,7 +600,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) struct dst_state* state = NULL; switch(type) { -#ifdef BTTV_BOARD_DVICO_DVBT_LITE case BTTV_BOARD_DVICO_DVBT_LITE: card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter); if (card->fe != NULL) { @@ -608,22 +607,15 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) card->fe->ops->info.frequency_max = 862000000; } break; -#endif -#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE: lgdt330x_reset(card); card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter); if (card->fe != NULL) dprintk ("dvb_bt8xx: lgdt330x detected\n"); break; -#endif -#ifdef BTTV_BOARD_TWINHAN_VP3021 - case BTTV_BOARD_TWINHAN_VP3021: -#else case BTTV_BOARD_NEBULA_DIGITV: -#endif /* * It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK); * this would be a cleaner solution than trying each frontend in turn. @@ -812,9 +804,7 @@ static int dvb_bt8xx_probe(struct device *dev) card->irq_err_ignore = 0; break; -#ifdef BTTV_BOARD_DVICO_DVBT_LITE case BTTV_BOARD_DVICO_DVBT_LITE: -#endif card->gpio_mode = 0x0400C060; card->op_sync_orin = 0; card->irq_err_ignore = 0; @@ -823,19 +813,13 @@ static int dvb_bt8xx_probe(struct device *dev) * DA_APP(parallel) */ break; -#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE: -#endif card->gpio_mode = 0x0400c060; card->op_sync_orin = BT878_RISC_SYNC_MASK; card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR; break; -#ifdef BTTV_BOARD_TWINHAN_VP3021 - case BTTV_BOARD_TWINHAN_VP3021: -#else case BTTV_BOARD_NEBULA_DIGITV: -#endif case BTTV_BOARD_AVDVBT_761: card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5); card->op_sync_orin = 0; diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig index 7cf4c4a888ec..6018fcdba1e6 100644 --- a/drivers/media/dvb/cinergyT2/Kconfig +++ b/drivers/media/dvb/cinergyT2/Kconfig @@ -21,35 +21,35 @@ config DVB_CINERGYT2_TUNING config DVB_CINERGYT2_STREAM_URB_COUNT int "Number of queued USB Request Blocks for Highspeed Stream Transfers" depends on DVB_CINERGYT2_TUNING - default "32" + default "32" help USB Request Blocks for Highspeed Stream transfers are scheduled in a queue for the Host Controller. Usually the default value is a safe choice. - You may increase this number if you are using this device in a - Server Environment with many high-traffic USB Highspeed devices + You may increase this number if you are using this device in a + Server Environment with many high-traffic USB Highspeed devices sharing the same USB bus. config DVB_CINERGYT2_STREAM_BUF_SIZE int "Size of URB Stream Buffers for Highspeed Transfers" depends on DVB_CINERGYT2_TUNING - default "512" + default "512" help Should be a multiple of native buffer size of 512 bytes. Default value is a safe choice. - You may increase this number if you are using this device in a - Server Environment with many high-traffic USB Highspeed devices + You may increase this number if you are using this device in a + Server Environment with many high-traffic USB Highspeed devices sharing the same USB bus. config DVB_CINERGYT2_QUERY_INTERVAL int "Status update interval [milliseconds]" depends on DVB_CINERGYT2_TUNING - default "250" + default "250" help This is the interval for status readouts from the demodulator. You may try lower values if you need more responsive signal quality @@ -64,9 +64,9 @@ config DVB_CINERGYT2_QUERY_INTERVAL config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE bool "Register the onboard IR Remote Control Receiver as Input Device" depends on DVB_CINERGYT2_TUNING - default "yes" + default "yes" help - Enable this option if you want to use the onboard Infrared Remote + Enable this option if you want to use the onboard Infrared Remote Control Receiver as Linux-Input device. Right now only the keycode table for the default Remote Control @@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE config DVB_CINERGYT2_RC_QUERY_INTERVAL int "Infrared Remote Controller update interval [milliseconds]" depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE - default "50" + default "50" help If you have a very fast-repeating remote control you can try lower values, for normal consumer receivers the default value should be diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 1d69bf031fb9..c4b4c5b6b7c8 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -131,6 +131,8 @@ struct cinergyt2 { wait_queue_head_t poll_wq; int pending_fe_events; + int disconnect_pending; + atomic_t inuse; void *streambuf; dma_addr_t streambuf_dmahandle; @@ -343,7 +345,7 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *demux = dvbdmxfeed->demux; struct cinergyt2 *cinergyt2 = demux->priv; - if (down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (cinergyt2->streaming == 0) @@ -359,7 +361,7 @@ static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *demux = dvbdmxfeed->demux; struct cinergyt2 *cinergyt2 = demux->priv; - if (down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (--cinergyt2->streaming == 0) @@ -479,23 +481,37 @@ static int cinergyt2_open (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; - int err; + int err = -ERESTARTSYS; - if ((err = dvb_generic_open(inode, file))) + if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; + + if ((err = dvb_generic_open(inode, file))) { + up(&cinergyt2->sem); return err; + } - if (down_interruptible(&cinergyt2->sem)) - return -ERESTARTSYS; if ((file->f_flags & O_ACCMODE) != O_RDONLY) { cinergyt2_sleep(cinergyt2, 0); schedule_delayed_work(&cinergyt2->query_work, HZ/2); } + atomic_inc(&cinergyt2->inuse); + up(&cinergyt2->sem); return 0; } +static void cinergyt2_unregister(struct cinergyt2 *cinergyt2) +{ + dvb_unregister_device(cinergyt2->fedev); + dvb_unregister_adapter(&cinergyt2->adapter); + + cinergyt2_free_stream_urbs(cinergyt2); + kfree(cinergyt2); +} + static int cinergyt2_release (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; @@ -504,7 +520,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file) if (down_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; - if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { cancel_delayed_work(&cinergyt2->query_work); flush_scheduled_work(); cinergyt2_sleep(cinergyt2, 1); @@ -512,6 +528,11 @@ static int cinergyt2_release (struct inode *inode, struct file *file) up(&cinergyt2->sem); + if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) { + warn("delayed unregister in release"); + cinergyt2_unregister(cinergyt2); + } + return dvb_generic_release(inode, file); } @@ -519,7 +540,14 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct { struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; + + if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) + return -ERESTARTSYS; + poll_wait(file, &cinergyt2->poll_wq, wait); + + up(&cinergyt2->sem); + return (POLLIN | POLLRDNORM | POLLPRI); } @@ -564,10 +592,15 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file, (__u16 __user *) arg); case FE_READ_UNCORRECTED_BLOCKS: - /* UNC are already converted to host byte order... */ - return put_user(stat->uncorrected_block_count, - (__u32 __user *) arg); + { + uint32_t unc_count; + + unc_count = stat->uncorrected_block_count; + stat->uncorrected_block_count = 0; + /* UNC are already converted to host byte order... */ + return put_user(unc_count,(__u32 __user *) arg); + } case FE_SET_FRONTEND: { struct dvbt_set_parameters_msg *param = &cinergyt2->param; @@ -580,7 +613,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file, if (copy_from_user(&p, (void __user*) arg, sizeof(p))) return -EFAULT; - if (down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; @@ -691,7 +724,7 @@ static void cinergyt2_query_rc (void *data) struct cinergyt2_rc_event rc_events[12]; int n, len, i; - if (down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) return; len = cinergyt2_command(cinergyt2, buf, sizeof(buf), @@ -786,7 +819,6 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { cancel_delayed_work(&cinergyt2->rc_query_work); - flush_scheduled_work(); input_unregister_device(cinergyt2->rc_input_dev); } @@ -817,7 +849,7 @@ static void cinergyt2_query (void *data) uint8_t lock_bits; uint32_t unc; - if (down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) return; unc = s->uncorrected_block_count; @@ -917,28 +949,25 @@ static void cinergyt2_disconnect (struct usb_interface *intf) { struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - if (down_interruptible(&cinergyt2->sem)) - return; + flush_scheduled_work(); cinergyt2_unregister_rc(cinergyt2); + cancel_delayed_work(&cinergyt2->query_work); + wake_up_interruptible(&cinergyt2->poll_wq); + cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx); - dvb_net_release(&cinergyt2->dvbnet); - dvb_dmxdev_release(&cinergyt2->dmxdev); - dvb_dmx_release(&cinergyt2->demux); - dvb_unregister_device(cinergyt2->fedev); - dvb_unregister_adapter(&cinergyt2->adapter); + cinergyt2->disconnect_pending = 1; - cinergyt2_free_stream_urbs(cinergyt2); - up(&cinergyt2->sem); - kfree(cinergyt2); + if (!atomic_read(&cinergyt2->inuse)) + cinergyt2_unregister(cinergyt2); } static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) { struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - if (down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (state.event > PM_EVENT_ON) { @@ -961,7 +990,7 @@ static int cinergyt2_resume (struct usb_interface *intf) struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); struct dvbt_set_parameters_msg *param = &cinergyt2->param; - if (down_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; if (!cinergyt2->sleeping) { @@ -1014,4 +1043,3 @@ module_exit (cinergyt2_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Holger Waechtler, Daniel Mack"); - diff --git a/drivers/media/dvb/dvb-core/Kconfig b/drivers/media/dvb/dvb-core/Kconfig index a9a7b3421048..12ee912a5705 100644 --- a/drivers/media/dvb/dvb-core/Kconfig +++ b/drivers/media/dvb/dvb-core/Kconfig @@ -5,7 +5,7 @@ config DVB_CORE help DVB core utility functions for device handling, software fallbacks etc. Say Y when you have a DVB card and want to use it. Say Y if your want - to build your drivers outside the kernel, but need the DVB core. All + to build your drivers outside the kernel, but need the DVB core. All in-kernel drivers will select this automatically if needed. If unsure say N. diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile index c6baac20f529..7adb50c1e8eb 100644 --- a/drivers/media/dvb/dvb-core/Makefile +++ b/drivers/media/dvb/dvb-core/Makefile @@ -3,7 +3,7 @@ # dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_ca_en50221.o dvb_frontend.o \ + dvb_ca_en50221.o dvb_frontend.o \ dvb_net.o dvb_ringbuffer.o obj-$(CONFIG_DVB_CORE) += dvb-core.o diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 5956c35d34ac..4bb779aeff6a 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -1745,9 +1745,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca) for (i = 0; i < ca->slot_count; i++) { dvb_ca_en50221_slot_shutdown(ca, i); - if (ca->slot_info[i].rx_buffer.data != NULL) { - vfree(ca->slot_info[i].rx_buffer.data); - } + vfree(ca->slot_info[i].rx_buffer.data); } kfree(ca->slot_info); dvb_unregister_device(ca->dvbdev); diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c index c49fd0bd7181..772003fb1821 100644 --- a/drivers/media/dvb/dvb-core/dvb_filter.c +++ b/drivers/media/dvb/dvb-core/dvb_filter.c @@ -409,16 +409,16 @@ static u8 *skip_pes_header(u8 **bufp) if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */ if (buf[7] & PTS_ONLY) - pts = buf+9; + pts = buf+9; else pts = NULL; buf = inbuf + 9 + inbuf[8]; } else { /* mpeg1 */ for (buf = inbuf + 6; *buf == 0xff; buf++) - if (buf == inbuf + 6 + 16) { - break; - } + if (buf == inbuf + 6 + 16) { + break; + } if ((*buf & 0xc0) == 0x40) - buf += 2; + buf += 2; skip = mpeg1_skip_table [*buf >> 4]; if (skip == 5 || skip == 10) pts = buf; else pts = NULL; @@ -529,9 +529,9 @@ static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_t pic->picture_header = 0; pic->sequence_header_data = ( INIT_HORIZONTAL_SIZE << 20 ) - | ( INIT_VERTICAL_SIZE << 8 ) - | ( INIT_ASPECT_RATIO << 4 ) - | ( INIT_FRAME_RATE ); + | ( INIT_VERTICAL_SIZE << 8 ) + | ( INIT_ASPECT_RATIO << 4 ) + | ( INIT_FRAME_RATE ); pic->mpeg1_flag = 0; pic->vinfo.horizontal_size = INIT_DISP_HORIZONTAL_SIZE; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 95ea5095e07e..4a08c4ab6730 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -92,6 +92,7 @@ static DECLARE_MUTEX(frontend_mutex); struct dvb_frontend_private { + /* thread/frontend values */ struct dvb_device *dvbdev; struct dvb_frontend_parameters parameters; struct dvb_fe_events events; @@ -100,20 +101,25 @@ struct dvb_frontend_private { wait_queue_head_t wait_queue; pid_t thread_pid; unsigned long release_jiffies; - int state; - int bending; - int lnb_drift; - int inversion; - int auto_step; - int auto_sub_step; - int started_auto_step; - int min_delay; - int max_drift; - int step_size; - int exit; - int wakeup; + unsigned int exit; + unsigned int wakeup; fe_status_t status; - fe_sec_tone_mode_t tone; + unsigned long tune_mode_flags; + unsigned int delay; + + /* swzigzag values */ + unsigned int state; + unsigned int bending; + int lnb_drift; + unsigned int inversion; + unsigned int auto_step; + unsigned int auto_sub_step; + unsigned int started_auto_step; + unsigned int min_delay; + unsigned int max_drift; + unsigned int step_size; + int quality; + unsigned int check_wrapped; }; @@ -208,21 +214,21 @@ static void dvb_frontend_init(struct dvb_frontend *fe) fe->ops->init(fe); } -static void update_delay(int *quality, int *delay, int min_delay, int locked) +static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) { - int q2; + int q2; - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s\n", __FUNCTION__); - if (locked) - (*quality) = (*quality * 220 + 36*256) / 256; - else - (*quality) = (*quality * 220 + 0) / 256; + if (locked) + (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256; + else + (fepriv->quality) = (fepriv->quality * 220 + 0) / 256; - q2 = *quality - 128; - q2 *= q2; + q2 = fepriv->quality - 128; + q2 *= q2; - *delay = min_delay + q2 * HZ / (128*128); + fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128); } /** @@ -232,7 +238,7 @@ static void update_delay(int *quality, int *delay, int min_delay, int locked) * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT * @returns Number of complete iterations that have been performed. */ -static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped) +static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped) { int autoinversion; int ready = 0; @@ -321,6 +327,129 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped) return 0; } +static void dvb_frontend_swzigzag(struct dvb_frontend *fe) +{ + fe_status_t s; + struct dvb_frontend_private *fepriv = fe->frontend_priv; + + /* if we've got no parameters, just keep idling */ + if (fepriv->state & FESTATE_IDLE) { + fepriv->delay = 3*HZ; + fepriv->quality = 0; + return; + } + + /* in SCAN mode, we just set the frontend when asked and leave it alone */ + if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { + if (fepriv->state & FESTATE_RETUNE) { + if (fe->ops->set_frontend) + fe->ops->set_frontend(fe, &fepriv->parameters); + fepriv->state = FESTATE_TUNED; + } + fepriv->delay = 3*HZ; + fepriv->quality = 0; + return; + } + + /* get the frontend status */ + if (fepriv->state & FESTATE_RETUNE) { + s = 0; + } else { + if (fe->ops->read_status) + fe->ops->read_status(fe, &s); + if (s != fepriv->status) { + dvb_frontend_add_event(fe, s); + fepriv->status = s; + } + } + + /* if we're not tuned, and we have a lock, move to the TUNED state */ + if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { + dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); + fepriv->state = FESTATE_TUNED; + + /* if we're tuned, then we have determined the correct inversion */ + if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && + (fepriv->parameters.inversion == INVERSION_AUTO)) { + fepriv->parameters.inversion = fepriv->inversion; + } + return; + } + + /* if we are tuned already, check we're still locked */ + if (fepriv->state & FESTATE_TUNED) { + dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); + + /* we're tuned, and the lock is still good... */ + if (s & FE_HAS_LOCK) { + return; + } else { /* if we _WERE_ tuned, but now don't have a lock */ + fepriv->state = FESTATE_ZIGZAG_FAST; + fepriv->started_auto_step = fepriv->auto_step; + fepriv->check_wrapped = 0; + } + } + + /* don't actually do anything if we're in the LOSTLOCK state, + * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ + if ((fepriv->state & FESTATE_LOSTLOCK) && + (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { + dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); + return; + } + + /* don't do anything if we're in the DISEQC state, since this + * might be someone with a motorized dish controlled by DISEQC. + * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ + if (fepriv->state & FESTATE_DISEQC) { + dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); + return; + } + + /* if we're in the RETUNE state, set everything up for a brand + * new scan, keeping the current inversion setting, as the next + * tune is _very_ likely to require the same */ + if (fepriv->state & FESTATE_RETUNE) { + fepriv->lnb_drift = 0; + fepriv->auto_step = 0; + fepriv->auto_sub_step = 0; + fepriv->started_auto_step = 0; + fepriv->check_wrapped = 0; + } + + /* fast zigzag. */ + if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { + fepriv->delay = fepriv->min_delay; + + /* peform a tune */ + if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) { + /* OK, if we've run out of trials at the fast speed. + * Drop back to slow for the _next_ attempt */ + fepriv->state = FESTATE_SEARCHING_SLOW; + fepriv->started_auto_step = fepriv->auto_step; + return; + } + fepriv->check_wrapped = 1; + + /* if we've just retuned, enter the ZIGZAG_FAST state. + * This ensures we cannot return from an + * FE_SET_FRONTEND ioctl before the first frontend tune + * occurs */ + if (fepriv->state & FESTATE_RETUNE) { + fepriv->state = FESTATE_TUNING_FAST; + } + } + + /* slow zigzag */ + if (fepriv->state & FESTATE_SEARCHING_SLOW) { + dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); + + /* Note: don't bother checking for wrapping; we stay in this + * state until we get a lock */ + dvb_frontend_swzigzag_autotune(fe, 0); + } +} + static int dvb_frontend_is_exiting(struct dvb_frontend *fe) { struct dvb_frontend_private *fepriv = fe->frontend_priv; @@ -330,7 +459,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe) if (fepriv->dvbdev->writers == 1) if (time_after(jiffies, fepriv->release_jiffies + - dvb_shutdown_timeout * HZ)) + dvb_shutdown_timeout * HZ)) return 1; return 0; @@ -355,18 +484,14 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe) wake_up_interruptible(&fepriv->wait_queue); } -/* - * FIXME: use linux/kthread.h - */ static int dvb_frontend_thread(void *data) { struct dvb_frontend *fe = data; struct dvb_frontend_private *fepriv = fe->frontend_priv; unsigned long timeout; char name [15]; - int quality = 0, delay = 3*HZ; fe_status_t s; - int check_wrapped = 0; + struct dvb_frontend_parameters *params; dprintk("%s\n", __FUNCTION__); @@ -377,6 +502,9 @@ static int dvb_frontend_thread(void *data) sigfillset(¤t->blocked); unlock_kernel(); + fepriv->check_wrapped = 0; + fepriv->quality = 0; + fepriv->delay = 3*HZ; fepriv->status = 0; dvb_frontend_init(fe); fepriv->wakeup = 0; @@ -386,7 +514,7 @@ static int dvb_frontend_thread(void *data) timeout = wait_event_interruptible_timeout(fepriv->wait_queue, dvb_frontend_should_wakeup(fe), - delay); + fepriv->delay); if (0 != dvb_frontend_is_exiting(fe)) { /* got signal or quitting */ break; @@ -397,108 +525,22 @@ static int dvb_frontend_thread(void *data) if (down_interruptible(&fepriv->sem)) break; - /* if we've got no parameters, just keep idling */ - if (fepriv->state & FESTATE_IDLE) { - delay = 3*HZ; - quality = 0; - continue; - } + /* do an iteration of the tuning loop */ + if (fe->ops->tune) { + /* have we been asked to retune? */ + params = NULL; + if (fepriv->state & FESTATE_RETUNE) { + params = &fepriv->parameters; + fepriv->state = FESTATE_TUNED; + } - /* get the frontend status */ - if (fepriv->state & FESTATE_RETUNE) { - s = 0; - } else { - if (fe->ops->read_status) - fe->ops->read_status(fe, &s); + fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); if (s != fepriv->status) { dvb_frontend_add_event(fe, s); fepriv->status = s; } - } - /* if we're not tuned, and we have a lock, move to the TUNED state */ - if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { - update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); - fepriv->state = FESTATE_TUNED; - - /* if we're tuned, then we have determined the correct inversion */ - if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && - (fepriv->parameters.inversion == INVERSION_AUTO)) { - fepriv->parameters.inversion = fepriv->inversion; - } - continue; - } - - /* if we are tuned already, check we're still locked */ - if (fepriv->state & FESTATE_TUNED) { - update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); - - /* we're tuned, and the lock is still good... */ - if (s & FE_HAS_LOCK) - continue; - else { /* if we _WERE_ tuned, but now don't have a lock */ - fepriv->state = FESTATE_ZIGZAG_FAST; - fepriv->started_auto_step = fepriv->auto_step; - check_wrapped = 0; - } - } - - /* don't actually do anything if we're in the LOSTLOCK state, - * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ - if ((fepriv->state & FESTATE_LOSTLOCK) && - (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { - update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); - continue; - } - - /* don't do anything if we're in the DISEQC state, since this - * might be someone with a motorized dish controlled by DISEQC. - * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ - if (fepriv->state & FESTATE_DISEQC) { - update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); - continue; - } - - /* if we're in the RETUNE state, set everything up for a brand - * new scan, keeping the current inversion setting, as the next - * tune is _very_ likely to require the same */ - if (fepriv->state & FESTATE_RETUNE) { - fepriv->lnb_drift = 0; - fepriv->auto_step = 0; - fepriv->auto_sub_step = 0; - fepriv->started_auto_step = 0; - check_wrapped = 0; - } - - /* fast zigzag. */ - if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { - delay = fepriv->min_delay; - - /* peform a tune */ - if (dvb_frontend_autotune(fe, check_wrapped)) { - /* OK, if we've run out of trials at the fast speed. - * Drop back to slow for the _next_ attempt */ - fepriv->state = FESTATE_SEARCHING_SLOW; - fepriv->started_auto_step = fepriv->auto_step; - continue; - } - check_wrapped = 1; - - /* if we've just retuned, enter the ZIGZAG_FAST state. - * This ensures we cannot return from an - * FE_SET_FRONTEND ioctl before the first frontend tune - * occurs */ - if (fepriv->state & FESTATE_RETUNE) { - fepriv->state = FESTATE_TUNING_FAST; - } - } - - /* slow zigzag */ - if (fepriv->state & FESTATE_SEARCHING_SLOW) { - update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); - - /* Note: don't bother checking for wrapping; we stay in this - * state until we get a lock */ - dvb_frontend_autotune(fe, 0); + } else { + dvb_frontend_swzigzag(fe); } } @@ -733,7 +775,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; - fepriv->tone = (fe_sec_tone_mode_t) parg; } break; @@ -747,7 +788,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, case FE_DISHNETWORK_SEND_LEGACY_CMD: if (fe->ops->dishnetwork_send_legacy_command) { - err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg); + err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } else if (fe->ops->set_voltage) { @@ -767,13 +808,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, * initialization, so parg is 8 bits and does not * include the initialization or start bit */ - unsigned int cmd = ((unsigned int) parg) << 1; + unsigned long cmd = ((unsigned long) parg) << 1; struct timeval nexttime; struct timeval tv[10]; int i; u8 last = 1; if (dvb_frontend_debug) - printk("%s switch command: 0x%04x\n", __FUNCTION__, cmd); + printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd); do_gettimeofday(&nexttime); if (dvb_frontend_debug) memcpy(&tv[0], &nexttime, sizeof(struct timeval)); @@ -814,7 +855,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, case FE_ENABLE_HIGH_LNB_VOLTAGE: if (fe->ops->enable_high_lnb_voltage) - err = fe->ops->enable_high_lnb_voltage(fe, (int) parg); + err = fe->ops->enable_high_lnb_voltage(fe, (long) parg); break; case FE_SET_FRONTEND: { @@ -891,6 +932,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg); } break; + + case FE_SET_FRONTEND_TUNE_MODE: + fepriv->tune_mode_flags = (unsigned long) parg; + break; }; up (&fepriv->sem); @@ -932,6 +977,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) /* empty event queue */ fepriv->events.eventr = fepriv->events.eventw = 0; + + /* normal tune mode when opened R/W */ + fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; } return ret; @@ -990,7 +1038,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb, init_MUTEX (&fepriv->events.sem); fe->dvb = dvb; fepriv->inversion = INVERSION_OFF; - fepriv->tone = SEC_TONE_OFF; printk ("DVB: registering frontend %i (%s)...\n", fe->dvb->num, diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 1e0840d02f1f..70a6d14efda7 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -58,10 +58,19 @@ struct dvb_frontend_ops { int (*init)(struct dvb_frontend* fe); int (*sleep)(struct dvb_frontend* fe); + /* if this is set, it overrides the default swzigzag */ + int (*tune)(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params, + unsigned int mode_flags, + int *delay, + fe_status_t *status); + + /* these two are only used for the swzigzag code */ int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); - int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); + int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); + int (*read_status)(struct dvb_frontend* fe, fe_status_t* status); int (*read_ber)(struct dvb_frontend* fe, u32* ber); int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength); @@ -74,8 +83,9 @@ struct dvb_frontend_ops { int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd); int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); - int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, int arg); - int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd); + int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg); + int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd); + int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable); }; #define MAX_EVENT 8 diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 86bba81e851e..6711eb6a058c 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -1222,7 +1222,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) return if_num; } -static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num) +static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num) { struct net_device *net = dvbnet->device[num]; struct dvb_net_priv *priv; @@ -1296,9 +1296,9 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if ((unsigned int) parg >= DVB_NET_DEVICES_MAX) + if ((unsigned long) parg >= DVB_NET_DEVICES_MAX) return -EINVAL; - ret = dvb_net_remove_if(dvbnet, (unsigned int) parg); + ret = dvb_net_remove_if(dvbnet, (unsigned long) parg); if (!ret) module_put(dvbdev->adapter->module); return ret; diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c index 283c6e9339a4..77ad2410f4d3 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c @@ -112,10 +112,10 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; if (split > 0) { if (!usermem) - memcpy(buf, rbuf->data+rbuf->pread, split); + memcpy(buf, rbuf->data+rbuf->pread, split); else - if (copy_to_user(buf, rbuf->data+rbuf->pread, split)) - return -EFAULT; + if (copy_to_user(buf, rbuf->data+rbuf->pread, split)) + return -EFAULT; buf += split; todo -= split; rbuf->pread = 0; @@ -124,7 +124,7 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in memcpy(buf, rbuf->data+rbuf->pread, todo); else if (copy_to_user(buf, rbuf->data+rbuf->pread, todo)) - return -EFAULT; + return -EFAULT; rbuf->pread = (rbuf->pread + todo) % rbuf->size; @@ -167,7 +167,7 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le } ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, - int offset, u8* buf, size_t len, int usermem) + int offset, u8* buf, size_t len, int usermem) { size_t todo; size_t split; @@ -183,10 +183,10 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; if (split > 0) { if (!usermem) - memcpy(buf, rbuf->data+idx, split); + memcpy(buf, rbuf->data+idx, split); else - if (copy_to_user(buf, rbuf->data+idx, split)) - return -EFAULT; + if (copy_to_user(buf, rbuf->data+idx, split)) + return -EFAULT; buf += split; todo -= split; idx = 0; @@ -195,7 +195,7 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, memcpy(buf, rbuf->data+idx, todo); else if (copy_to_user(buf, rbuf->data+idx, todo)) - return -EFAULT; + return -EFAULT; return len; } @@ -209,12 +209,12 @@ void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx) // clean up disposed packets while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) { if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) { - pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8; - pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1); - DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE); + pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8; + pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1); + DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE); } else { - // first packet is not disposed, so we stop cleaning now - break; + // first packet is not disposed, so we stop cleaning now + break; } } } @@ -242,8 +242,8 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* curpktstatus = rbuf->data[(idx + 2) % rbuf->size]; if (curpktstatus == PKT_READY) { - *pktlen = curpktlen; - return idx; + *pktlen = curpktlen; + return idx; } consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE; diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h index fa476f662f82..6d2560972771 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h @@ -106,7 +106,7 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); ** returns number of bytes transferred or -EFAULT */ extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, - size_t len, int usermem); + size_t len, int usermem); /* write routines & macros */ @@ -121,7 +121,7 @@ extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, ** returns number of bytes transferred or -EFAULT */ extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, - size_t len); + size_t len); /** @@ -133,7 +133,7 @@ extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, * returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL. */ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, - size_t len); + size_t len); /** * Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this @@ -149,7 +149,7 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, * returns Number of bytes read, or -EFAULT. */ extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, - int offset, u8* buf, size_t len, int usermem); + int offset, u8* buf, size_t len, int usermem); /** * Dispose of a packet in the ring buffer. diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index a4aee8665854..06b696e9acbd 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -92,10 +92,10 @@ static int dvb_device_open(struct inode *inode, struct file *file) old_fops = file->f_op; file->f_op = fops_get(dvbdev->fops); if(file->f_op->open) - err = file->f_op->open(inode,file); + err = file->f_op->open(inode,file); if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); + fops_put(file->f_op); + file->f_op = fops_get(old_fops); } fops_put(old_fops); return err; @@ -356,18 +356,18 @@ int dvb_usercopy(struct inode *inode, struct file *file, case _IOC_WRITE: case (_IOC_WRITE | _IOC_READ): if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; + parg = sbuf; } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; } err = -EFAULT; if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) - goto out; + goto out; break; } @@ -384,7 +384,7 @@ int dvb_usercopy(struct inode *inode, struct file *file, case _IOC_READ: case (_IOC_WRITE | _IOC_READ): if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; + err = -EFAULT; break; } diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h index 0cc6e4a0e27c..74ed5853f0fb 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb/dvb-core/dvbdev.h @@ -97,7 +97,7 @@ we simply define out own dvb_usercopy(), which will hopefully become generic_usercopy() someday... */ extern int dvb_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, + unsigned int cmd, unsigned long arg, int (*func)(struct inode *inode, struct file *file, unsigned int cmd, void *arg)); diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 54e2b29076b1..90a69d343b79 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -37,16 +37,16 @@ config DVB_USB_DIBUSB_MB DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. Devices supported by this driver: - TwinhanDTV USB-Ter (VP7041) - TwinhanDTV Magic Box (VP7041e) - KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0 - Hama DVB-T USB1.1-Box - DiBcom USB1.1 reference devices (non-public) - Ultima Electronic/Artec T1 USB TVBOX + Artec T1 USB1.1 boxes + Avermedia AverTV DVBT USB1.1 Compro Videomate DVB-U2000 - DVB-T USB + DiBcom USB1.1 reference devices (non-public) Grandtec DVB-T USB - Avermedia AverTV DVBT USB1.1 - Artec T1 USB1.1 boxes + Hama DVB-T USB1.1-Box + KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0 + TwinhanDTV Magic Box (VP7041e) + TwinhanDTV USB-Ter (VP7041) + Ultima Electronic/Artec T1 USB TVBOX The VP7041 seems to be identical to "CTS Portable" (Chinese Television System). @@ -54,6 +54,12 @@ config DVB_USB_DIBUSB_MB Say Y if you own such a device and want to use it. You should build it as a module. +config DVB_USB_DIBUSB_MB_FAULTY + bool "Support faulty USB IDs" + depends on DVB_USB_DIBUSB_MB + help + Support for faulty USB IDs due to an invalid EEPROM on some Artec devices. + config DVB_USB_DIBUSB_MC tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" depends on DVB_USB @@ -63,8 +69,8 @@ config DVB_USB_DIBUSB_MC DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. Devices supported by this driver: - DiBcom USB2.0 reference devices (non-public) Artec T1 USB2.0 boxes + DiBcom USB2.0 reference devices (non-public) Say Y if you own such a device and want to use it. You should build it as a module. diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index d05fab01cccd..358ed153865f 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -11,10 +11,11 @@ * design, so it can be reused for the "analogue-only" device (if it will * appear at all). * - * TODO: check if the cx25840-driver (from ivtv) can be used for the analogue - * part + * TODO: Use the cx25840-driver for the analogue part * * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net) + * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) * * 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 @@ -25,6 +26,9 @@ #include "cxusb.h" #include "cx22702.h" +#include "lgdt330x.h" +#include "mt352.h" +#include "mt352_priv.h" /* debug */ int dvb_usb_cxusb_debug; @@ -156,6 +160,99 @@ static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff) return 0; } +static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + u8 ircode[4]; + int i; + + cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4); + + *event = 0; + *state = REMOTE_NO_KEY_PRESSED; + + for (i = 0; i < d->props.rc_key_map_size; i++) { + if (keymap[i].custom == ircode[2] && + keymap[i].data == ircode[3]) { + *event = keymap[i].event; + *state = REMOTE_KEY_PRESSED; + + return 0; + } + } + + return 0; +} + +struct dvb_usb_rc_key dvico_mce_rc_keys[] = { + { 0xfe, 0x02, KEY_TV }, + { 0xfe, 0x0e, KEY_MP3 }, + { 0xfe, 0x1a, KEY_DVD }, + { 0xfe, 0x1e, KEY_FAVORITES }, + { 0xfe, 0x16, KEY_SETUP }, + { 0xfe, 0x46, KEY_POWER2 }, + { 0xfe, 0x0a, KEY_EPG }, + { 0xfe, 0x49, KEY_BACK }, + { 0xfe, 0x4d, KEY_MENU }, + { 0xfe, 0x51, KEY_UP }, + { 0xfe, 0x5b, KEY_LEFT }, + { 0xfe, 0x5f, KEY_RIGHT }, + { 0xfe, 0x53, KEY_DOWN }, + { 0xfe, 0x5e, KEY_OK }, + { 0xfe, 0x59, KEY_INFO }, + { 0xfe, 0x55, KEY_TAB }, + { 0xfe, 0x0f, KEY_PREVIOUSSONG },/* Replay */ + { 0xfe, 0x12, KEY_NEXTSONG }, /* Skip */ + { 0xfe, 0x42, KEY_ENTER }, /* Windows/Start */ + { 0xfe, 0x15, KEY_VOLUMEUP }, + { 0xfe, 0x05, KEY_VOLUMEDOWN }, + { 0xfe, 0x11, KEY_CHANNELUP }, + { 0xfe, 0x09, KEY_CHANNELDOWN }, + { 0xfe, 0x52, KEY_CAMERA }, + { 0xfe, 0x5a, KEY_TUNER }, /* Live */ + { 0xfe, 0x19, KEY_OPEN }, + { 0xfe, 0x0b, KEY_1 }, + { 0xfe, 0x17, KEY_2 }, + { 0xfe, 0x1b, KEY_3 }, + { 0xfe, 0x07, KEY_4 }, + { 0xfe, 0x50, KEY_5 }, + { 0xfe, 0x54, KEY_6 }, + { 0xfe, 0x48, KEY_7 }, + { 0xfe, 0x4c, KEY_8 }, + { 0xfe, 0x58, KEY_9 }, + { 0xfe, 0x13, KEY_ANGLE }, /* Aspect */ + { 0xfe, 0x03, KEY_0 }, + { 0xfe, 0x1f, KEY_ZOOM }, + { 0xfe, 0x43, KEY_REWIND }, + { 0xfe, 0x47, KEY_PLAYPAUSE }, + { 0xfe, 0x4f, KEY_FASTFORWARD }, + { 0xfe, 0x57, KEY_MUTE }, + { 0xfe, 0x0d, KEY_STOP }, + { 0xfe, 0x01, KEY_RECORD }, + { 0xfe, 0x4e, KEY_POWER }, +}; + +static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) +{ + static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; + static u8 reset [] = { RESET, 0x80 }; + static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; + static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; + static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; + static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; + + 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, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); + mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); + + return 0; +} + struct cx22702_config cxusb_cx22702_config = { .demod_address = 0x63, @@ -165,17 +262,47 @@ struct cx22702_config cxusb_cx22702_config = { .pll_set = dvb_usb_pll_set_i2c, }; +struct lgdt330x_config cxusb_lgdt330x_config = { + .demod_address = 0x0e, + .demod_chip = LGDT3303, + .pll_set = dvb_usb_pll_set_i2c, +}; + +struct mt352_config cxusb_dee1601_config = { + .demod_address = 0x0f, + .demod_init = cxusb_dee1601_demod_init, + .pll_set = dvb_usb_pll_set, +}; + /* Callbacks for DVB USB */ -static int cxusb_tuner_attach(struct dvb_usb_device *d) +static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d) { u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 }; d->pll_addr = 0x61; - memcpy(d->pll_init,bpll,4); + memcpy(d->pll_init, bpll, 4); d->pll_desc = &dvb_pll_fmd1216me; return 0; } -static int cxusb_frontend_attach(struct dvb_usb_device *d) +static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d) +{ + u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 }; + /* bpll[2] : unset bit 3, set bits 4&5 + bpll[3] : 0x50 - digital, 0x20 - analog */ + d->pll_addr = 0x61; + memcpy(d->pll_init, bpll, 4); + d->pll_desc = &dvb_pll_tdvs_tua6034; + return 0; +} + +static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d) +{ + d->pll_addr = 0x61; + d->pll_desc = &dvb_pll_thomson_dtt7579; + return 0; +} + +static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d) { u8 b; if (usb_set_interface(d->udev,0,6) < 0) @@ -189,22 +316,84 @@ static int cxusb_frontend_attach(struct dvb_usb_device *d) return -EIO; } +static int cxusb_lgdt330x_frontend_attach(struct dvb_usb_device *d) +{ + if (usb_set_interface(d->udev,0,7) < 0) + err("set interface failed"); + + cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0); + + if ((d->fe = lgdt330x_attach(&cxusb_lgdt330x_config, &d->i2c_adap)) != NULL) + return 0; + + return -EIO; +} + +static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d) +{ + if (usb_set_interface(d->udev,0,0) < 0) + err("set interface failed"); + + cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0); + + if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) + return 0; + + return -EIO; +} + +/* + * DViCO bluebird firmware needs the "warm" product ID to be patched into the + * firmware file before download. + */ + +#define BLUEBIRD_01_ID_OFFSET 6638 +static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw) +{ + if (fw->size < BLUEBIRD_01_ID_OFFSET + 4) + return -EINVAL; + + if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && + fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { + + /* FIXME: are we allowed to change the fw-data ? */ + fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1; + fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8; + + return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2); + } + + return -EINVAL; +} + /* DVB USB Driver stuff */ -static struct dvb_usb_properties cxusb_properties; +static struct dvb_usb_properties cxusb_medion_properties; +static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties; +static struct dvb_usb_properties cxusb_bluebird_dee1601_properties; static int cxusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE,NULL); + if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 || + dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || + dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0) { + return 0; + } + + return -EINVAL; } static struct usb_device_id cxusb_table [] = { { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_COLD) }, + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_WARM) }, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, cxusb_table); -static struct dvb_usb_properties cxusb_properties = { +static struct dvb_usb_properties cxusb_medion_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = CYPRESS_FX2, @@ -213,8 +402,8 @@ static struct dvb_usb_properties cxusb_properties = { .streaming_ctrl = cxusb_streaming_ctrl, .power_ctrl = cxusb_power_ctrl, - .frontend_attach = cxusb_frontend_attach, - .tuner_attach = cxusb_tuner_attach, + .frontend_attach = cxusb_cx22702_frontend_attach, + .tuner_attach = cxusb_fmd1216me_tuner_attach, .i2c_algo = &cxusb_i2c_algo, @@ -240,6 +429,91 @@ static struct dvb_usb_properties cxusb_properties = { } }; +static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-bluebird-01.fw", + .download_firmware = bluebird_patch_dvico_firmware_download, + /* use usb alt setting 0 for EP4 transfer (dvb-t), + use usb alt setting 7 for EP2 transfer (atsc) */ + + .size_of_priv = sizeof(struct cxusb_state), + + .streaming_ctrl = cxusb_streaming_ctrl, + .power_ctrl = cxusb_power_ctrl, + .frontend_attach = cxusb_lgdt330x_frontend_attach, + .tuner_attach = cxusb_lgh064f_tuner_attach, + + .i2c_algo = &cxusb_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + /* parameter for the MPEG2-data transfer */ + .urb = { + .type = DVB_USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, + + .num_device_descs = 1, + .devices = { + { "DViCO FusionHDTV5 USB Gold", + { &cxusb_table[1], NULL }, + { &cxusb_table[2], NULL }, + }, + } +}; + +static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-bluebird-01.fw", + .download_firmware = bluebird_patch_dvico_firmware_download, + /* use usb alt setting 0 for EP4 transfer (dvb-t), + use usb alt setting 7 for EP2 transfer (atsc) */ + + .size_of_priv = sizeof(struct cxusb_state), + + .streaming_ctrl = cxusb_streaming_ctrl, + .power_ctrl = cxusb_power_ctrl, + .frontend_attach = cxusb_dee1601_frontend_attach, + .tuner_attach = cxusb_dee1601_tuner_attach, + + .i2c_algo = &cxusb_i2c_algo, + + .rc_interval = 150, + .rc_key_map = dvico_mce_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys), + .rc_query = cxusb_rc_query, + + .generic_bulk_ctrl_endpoint = 0x01, + /* parameter for the MPEG2-data transfer */ + .urb = { + .type = DVB_USB_BULK, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, + + .num_device_descs = 1, + .devices = { + { "DViCO FusionHDTV DVB-T Dual USB", + { &cxusb_table[3], NULL }, + { &cxusb_table[4], NULL }, + }, + } +}; + static struct usb_driver cxusb_driver = { .name = "dvb_usb_cxusb", .probe = cxusb_probe, diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h index 135c2a81f581..087c99427853 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.h +++ b/drivers/media/dvb/dvb-usb/cxusb.h @@ -21,6 +21,8 @@ extern int dvb_usb_cxusb_debug; #define CMD_STREAMING_ON 0x36 #define CMD_STREAMING_OFF 0x37 +#define CMD_GET_IR_CODE 0x47 + #define CMD_ANALOG 0x50 #define CMD_DIGITAL 0x51 diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index 52ac3e5adf5d..dd5a13195886 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -65,11 +65,11 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_device *d) d->tuner_pass_ctrl(d->fe,0,msg[0].addr); if (b2[0] == 0xfe) { - info("this device has the Thomson Cable onboard. Which is default."); + info("This device has the Thomson Cable onboard. Which is default."); dibusb_thomson_tuner_attach(d); } else { u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab }; - info("this device has the Panasonic ENV77H11D5 onboard."); + info("This device has the Panasonic ENV77H11D5 onboard."); d->pll_addr = 0x60; memcpy(d->pll_init,bpll,4); d->pll_desc = &dvb_pll_tda665x; @@ -98,15 +98,15 @@ static int dibusb_probe(struct usb_interface *intf, /* do not change the order of the ID table */ static struct usb_device_id dibusb_dib3000mb_table [] = { -/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD)}, -/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM)}, +/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD) }, +/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM) }, /* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) }, /* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) }, /* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) }, /* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) }, /* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) }, -/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, -/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, +/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, +/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, /* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) }, /* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) }, /* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) }, @@ -117,27 +117,34 @@ static struct usb_device_id dibusb_dib3000mb_table [] = { /* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) }, /* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) }, /* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) }, -/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, -/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, -/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, -/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, +/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, +/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, +/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, +/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, /* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) }, /* device ID with default DIBUSB2_0-firmware and with the hacked firmware */ /* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) }, -/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) }, -/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) }, +/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) }, +/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) }, /* 27 */ { USB_DEVICE(USB_VID_KWORLD, USB_PID_KWORLD_VSTREAM_COLD) }, -/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, -/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, +/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, +/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, -// #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs +/* + * XXX: As Artec just 'forgot' to program the EEPROM on some Artec T1 devices + * we don't catch these faulty IDs (namely 'Cypress FX1 USB controller') that + * have been left on the device. If you don't have such a device but an Artec + * device that's supposed to work with this driver but is not detected by it, + * free to enable CONFIG_DVB_USB_DIBUSB_MB_FAULTY via your kernel config. + */ -#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs +#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY /* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, #endif + { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table); @@ -257,7 +264,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = { } }, -#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs +#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY .num_device_descs = 2, #else .num_device_descs = 1, @@ -267,11 +274,12 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = { { &dibusb_dib3000mb_table[20], NULL }, { &dibusb_dib3000mb_table[21], NULL }, }, -#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs +#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY { "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)", { &dibusb_dib3000mb_table[30], NULL }, { NULL }, }, + { NULL }, #endif } }; @@ -323,6 +331,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = { { &dibusb_dib3000mb_table[27], NULL }, { NULL } }, + { NULL }, } }; @@ -369,6 +378,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = { { &dibusb_dib3000mb_table[28], NULL }, { &dibusb_dib3000mb_table[29], NULL }, }, + { NULL }, } }; diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 450417a9e64b..e6c55c9c9417 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -32,7 +32,7 @@ static int digitv_ctrl_msg(struct dvb_usb_device *d, sndbuf[1] = vv; sndbuf[2] = wo ? wlen : rlen; - if (!wo) { + if (wo) { memcpy(&sndbuf[3],wbuf,wlen); dvb_usb_generic_write(d,sndbuf,7); } else { diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index 6e2bac873445..130ea7f21f5e 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c @@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = { .cold_ids = { &dtt200u_usb_table[0], NULL }, .warm_ids = { &dtt200u_usb_table[1], NULL }, }, - { NULL }, + { 0 }, } }; @@ -160,7 +160,7 @@ static struct dvb_usb_properties wt220u_properties = { .pid_filter_count = 15, .usb_ctrl = CYPRESS_FX2, - .firmware = "dvb-usb-wt220u-01.fw", + .firmware = "dvb-usb-wt220u-02.fw", .power_ctrl = dtt200u_power_ctrl, .streaming_ctrl = dtt200u_streaming_ctrl, @@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = { .cold_ids = { &dtt200u_usb_table[2], NULL }, .warm_ids = { &dtt200u_usb_table[3], NULL }, }, - { NULL }, + { 0 }, } }; diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h index 6f1f3042e21a..005b0a7df358 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.h +++ b/drivers/media/dvb/dvb-usb/dtt200u.h @@ -13,6 +13,7 @@ #define _DVB_USB_DTT200U_H_ #define DVB_USB_LOG_PREFIX "dtt200u" + #include "dvb-usb.h" extern int dvb_usb_dtt200u_debug; @@ -25,15 +26,15 @@ extern int dvb_usb_dtt200u_debug; * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal) */ -#define GET_SPEED 0x00 -#define GET_TUNE_STATUS 0x81 -#define GET_RC_CODE 0x84 -#define GET_CONFIGURATION 0x88 -#define GET_AGC 0x89 -#define GET_SNR 0x8a -#define GET_VIT_ERR_CNT 0x8c -#define GET_RS_ERR_CNT 0x8d -#define GET_RS_UNCOR_BLK_CNT 0x8e +#define GET_SPEED 0x00 +#define GET_TUNE_STATUS 0x81 +#define GET_RC_CODE 0x84 +#define GET_CONFIGURATION 0x88 +#define GET_AGC 0x89 +#define GET_SNR 0x8a +#define GET_VIT_ERR_CNT 0x8c +#define GET_RS_ERR_CNT 0x8d +#define GET_RS_UNCOR_BLK_CNT 0x8e /* write * 01 - init @@ -44,12 +45,12 @@ extern int dvb_usb_dtt200u_debug; * 08 - transfer switch */ -#define SET_INIT 0x01 -#define SET_RF_FREQ 0x02 -#define SET_BANDWIDTH 0x03 -#define SET_PID_FILTER 0x04 -#define RESET_PID_FILTER 0x05 -#define SET_STREAMING 0x08 +#define SET_INIT 0x01 +#define SET_RF_FREQ 0x02 +#define SET_BANDWIDTH 0x03 +#define SET_PID_FILTER 0x04 +#define RESET_PID_FILTER 0x05 +#define SET_STREAMING 0x08 extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h index 7300489d3e24..a3460bf2d9fa 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h @@ -24,7 +24,7 @@ extern int dvb_usb_disable_rc_polling; #define deb_mem(args...) dprintk(dvb_usb_debug,0x80,args) /* commonly used methods */ -extern int usb_cypress_load_firmware(struct usb_device *, const char *, int); +extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_properties *); extern int dvb_usb_urb_submit(struct dvb_usb_device *); extern int dvb_usb_urb_kill(struct dvb_usb_device *); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c index 5244e39770a0..8535895819fb 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c @@ -9,7 +9,6 @@ */ #include "dvb-usb-common.h" -#include <linux/firmware.h> #include <linux/usb.h> struct usb_cypress_controller { @@ -19,9 +18,10 @@ struct usb_cypress_controller { }; static struct usb_cypress_controller cypress[] = { - { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 }, - { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 }, - { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, + { .id = DEVICE_SPECIFIC, .name = "Device specific", .cpu_cs_register = 0 }, + { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 }, + { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 }, + { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, }; /* @@ -30,71 +30,117 @@ static struct usb_cypress_controller cypress[] = { static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len) { return usb_control_msg(udev, usb_sndctrlpipe(udev,0), - 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ); + 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000); } -int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type) +int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type) { - const struct firmware *fw = NULL; - u16 addr; - u8 *b,*p; - int ret = 0,i; + struct hexline hx; + u8 reset; + int ret,pos=0; - if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) { - err("did not find the firmware file. (%s) " - "Please see linux/Documentation/dvb/ for more details on firmware-problems.", - filename); + /* stop the CPU */ + reset = 1; + if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1) + err("could not stop the USB controller CPU."); + + while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) { + deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk); + ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len); + + if (ret != hx.len) { + err("error while transferring firmware " + "(transferred size: %d, block size: %d)", + ret,hx.len); + ret = -EINVAL; + break; + } + } + if (ret < 0) { + err("firmware download failed at %d with %d",pos,ret); return ret; } - info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name); - - p = kmalloc(fw->size,GFP_KERNEL); - if (p != NULL) { - u8 reset; - /* - * you cannot use the fw->data as buffer for - * usb_control_msg, a new buffer has to be - * created - */ - memcpy(p,fw->data,fw->size); - - /* stop the CPU */ - reset = 1; - if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1) - err("could not stop the USB controller CPU."); - for(i = 0; p[i+3] == 0 && i < fw->size; ) { - b = (u8 *) &p[i]; - addr = cpu_to_le16( *((u16 *) &b[1]) ); - - deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]); - - ret = usb_cypress_writemem(udev,addr,&b[4],b[0]); - - if (ret != b[0]) { - err("error while transferring firmware " - "(transferred size: %d, block size: %d)", - ret,b[0]); - ret = -EINVAL; - break; - } - i += 5 + b[0]; - } - /* length in ret */ - if (ret > 0) - ret = 0; + if (ret == 0) { /* restart the CPU */ reset = 0; if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) { err("could not restart the USB controller CPU."); ret = -EINVAL; } + } else + ret = -EIO; - kfree(p); - } else { - ret = -ENOMEM; + return ret; +} +EXPORT_SYMBOL(usb_cypress_load_firmware); + +int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties *props) +{ + int ret; + const struct firmware *fw = NULL; + + if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) { + err("did not find the firmware file. (%s) " + "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)", + props->firmware,ret); + return ret; } - release_firmware(fw); + info("downloading firmware from file '%s'",props->firmware); + + switch (props->usb_ctrl) { + case CYPRESS_AN2135: + case CYPRESS_AN2235: + case CYPRESS_FX2: + ret = usb_cypress_load_firmware(udev, fw, props->usb_ctrl); + break; + case DEVICE_SPECIFIC: + if (props->download_firmware) + ret = props->download_firmware(udev,fw); + else { + err("BUG: driver didn't specified a download_firmware-callback, although it claims to have a DEVICE_SPECIFIC one."); + ret = -EINVAL; + } + break; + default: + ret = -EINVAL; + break; + } + + release_firmware(fw); return ret; } + +int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos) +{ + u8 *b = (u8 *) &fw->data[*pos]; + int data_offs = 4; + if (*pos >= fw->size) + return 0; + + memset(hx,0,sizeof(struct hexline)); + + hx->len = b[0]; + + if ((*pos + hx->len + 4) >= fw->size) + return -EINVAL; + + hx->addr = le16_to_cpu( *((u16 *) &b[1]) ); + hx->type = b[3]; + + if (hx->type == 0x04) { + /* b[4] and b[5] are the Extended linear address record data field */ + hx->addr |= (b[4] << 24) | (b[5] << 16); +/* hx->len -= 2; + data_offs += 2; */ + } + memcpy(hx->data,&b[data_offs],hx->len); + hx->chk = b[hx->len + data_offs]; + + *pos += hx->len + 5; + + return *pos; +} +EXPORT_SYMBOL(dvb_usb_get_hexline); + diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c index da970947dfc7..9b254532af4d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c @@ -52,9 +52,8 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe) struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 }; int ret = 0; - /* if there is nothing to initialize */ - if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 && - d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00) + /* if pll_desc is not used */ + if (d->pll_desc == NULL) return 0; if (d->tuner_pass_ctrl) @@ -80,6 +79,9 @@ int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep { struct dvb_usb_device *d = fe->dvb->priv; + if (d->pll_desc == NULL) + return 0; + deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc); b[0] = d->pll_addr << 1; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 6be99e537e12..d22934383226 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -86,11 +86,15 @@ #define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 #define USB_PID_NEBULA_DIGITV 0x0201 -#define USB_PID_DVICO_BLUEBIRD_LGZ201 0xdb00 -#define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10 #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 -#define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01 -#define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11 +#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 +#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM 0xd501 +#define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD 0xdb00 +#define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM 0xdb01 +#define USB_PID_DVICO_BLUEBIRD_TH7579_COLD 0xdb10 +#define USB_PID_DVICO_BLUEBIRD_TH7579_WARM 0xdb11 +#define USB_PID_DVICO_BLUEBIRD_DEE1601_COLD 0xdb50 +#define USB_PID_DVICO_BLUEBIRD_DEE1601_WARM 0xdb51 #define USB_PID_MEDION_MD95700 0x0932 #define USB_PID_KYE_DVB_T_COLD 0x701e #define USB_PID_KYE_DVB_T_WARM 0x701f diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index dd8e0b94edba..2e23060cbbca 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c @@ -138,6 +138,9 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties int ret = -ENOMEM,cold=0; + if (du != NULL) + *du = NULL; + if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) { deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n"); return -ENODEV; @@ -145,38 +148,40 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties if (cold) { info("found a '%s' in cold state, will try to load a firmware",desc->name); - ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl); - } else { - info("found a '%s' in warm state.",desc->name); - d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL); - if (d == NULL) { - err("no memory for 'struct dvb_usb_device'"); + ret = dvb_usb_download_firmware(udev,props); + if (!props->no_reconnect) return ret; + } + + info("found a '%s' in warm state.",desc->name); + d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL); + if (d == NULL) { + err("no memory for 'struct dvb_usb_device'"); + return ret; + } + memset(d,0,sizeof(struct dvb_usb_device)); + + d->udev = udev; + memcpy(&d->props,props,sizeof(struct dvb_usb_properties)); + d->desc = desc; + d->owner = owner; + + if (d->props.size_of_priv > 0) { + d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL); + if (d->priv == NULL) { + err("no memory for priv in 'struct dvb_usb_device'"); + kfree(d); + return -ENOMEM; } - memset(d,0,sizeof(struct dvb_usb_device)); - - d->udev = udev; - memcpy(&d->props,props,sizeof(struct dvb_usb_properties)); - d->desc = desc; - d->owner = owner; - - if (d->props.size_of_priv > 0) { - d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL); - if (d->priv == NULL) { - err("no memory for priv in 'struct dvb_usb_device'"); - kfree(d); - return -ENOMEM; - } - memset(d->priv,0,d->props.size_of_priv); - } + memset(d->priv,0,d->props.size_of_priv); + } - usb_set_intfdata(intf, d); + usb_set_intfdata(intf, d); - if (du != NULL) - *du = d; + if (du != NULL) + *du = d; - ret = dvb_usb_init(d); - } + ret = dvb_usb_init(d); if (ret == 0) info("%s successfully initialized and connected.",desc->name); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index b4a1a98006c7..dd568396e594 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -10,8 +10,8 @@ #include <linux/config.h> #include <linux/input.h> -#include <linux/module.h> #include <linux/usb.h> +#include <linux/firmware.h> #include "dvb_frontend.h" #include "dvb_demux.h" @@ -94,7 +94,11 @@ struct dvb_usb_device; * @usb_ctrl: which USB device-side controller is in use. Needed for firmware * download. * @firmware: name of the firmware file. - * + * @download_firmware: called to download the firmware when the usb_ctrl is + * DEVICE_SPECIFIC. + * @no_reconnect: device doesn't do a reconnect after downloading the firmware, + so do the warm initialization right after it + * @size_of_priv: how many bytes shall be allocated for the private field * of struct dvb_usb_device. * @@ -142,11 +146,14 @@ struct dvb_usb_properties { int caps; int pid_filter_count; -#define CYPRESS_AN2135 0 -#define CYPRESS_AN2235 1 -#define CYPRESS_FX2 2 +#define DEVICE_SPECIFIC 0 +#define CYPRESS_AN2135 1 +#define CYPRESS_AN2235 2 +#define CYPRESS_FX2 3 int usb_ctrl; - const char *firmware; + const char firmware[FIRMWARE_NAME_MAX]; + int (*download_firmware) (struct usb_device *, const struct firmware *); + int no_reconnect; int size_of_priv; @@ -326,5 +333,15 @@ extern int dvb_usb_pll_init_i2c(struct dvb_frontend *); extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]); extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *); +/* commonly used firmware download types and function */ +struct hexline { + u8 len; + u32 addr; + u8 type; + u8 data[255]; + u8 chk; +}; +extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *); +extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type); #endif diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c index fac48fc7a4ac..412039d8dbae 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c @@ -129,10 +129,6 @@ static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6]) dibusb_read_eeprom_byte(d,i, &b); mac[5 - (i - 136)] = b; - -/* deb_ee("%02x ",b); - if ((i+1) % 16 == 0) - deb_ee("\n");*/ } return 0; @@ -153,7 +149,7 @@ static struct usb_device_id nova_t_table [] = { /* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, nova_t_table); +MODULE_DEVICE_TABLE(usb, nova_t_table); static struct dvb_usb_properties nova_t_properties = { .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, @@ -198,6 +194,7 @@ static struct dvb_usb_properties nova_t_properties = { { &nova_t_table[0], NULL }, { &nova_t_table[1], NULL }, }, + { NULL }, } }; diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c index 104b5d016c7b..0885d9fb2bf2 100644 --- a/drivers/media/dvb/dvb-usb/vp702x-fe.c +++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c @@ -190,7 +190,7 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe, } static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, - struct dvb_diseqc_master_cmd *m) + struct dvb_diseqc_master_cmd *m) { struct vp702x_fe_state *st = fe->demodulator_priv; u8 cmd[8],ibuf[10]; diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h index 4a3e8c7eca2b..a808d48e7bf2 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.h +++ b/drivers/media/dvb/dvb-usb/vp702x.h @@ -13,47 +13,47 @@ extern int dvb_usb_vp702x_debug; /* commands are read and written with USB control messages */ /* consecutive read/write operation */ -#define REQUEST_OUT 0xB2 -#define REQUEST_IN 0xB3 +#define REQUEST_OUT 0xB2 +#define REQUEST_IN 0xB3 /* the out-buffer of these consecutive operations contain sub-commands when b[0] = 0 * request: 0xB2; i: 0; v: 0; b[0] = 0, b[1] = subcmd, additional buffer * the returning buffer looks as follows * request: 0xB3; i: 0; v: 0; b[0] = 0xB3, additional buffer */ -#define GET_TUNER_STATUS 0x05 +#define GET_TUNER_STATUS 0x05 /* additional in buffer: * 0 1 2 3 4 5 6 7 8 * N/A N/A 0x05 signal-quality N/A N/A signal-strength lock==0 N/A */ -#define GET_SYSTEM_STRING 0x06 +#define GET_SYSTEM_STRING 0x06 /* additional in buffer: * 0 1 2 3 4 5 6 7 8 * N/A 'U' 'S' 'B' '7' '0' '2' 'X' N/A */ -#define SET_DISEQC_CMD 0x08 +#define SET_DISEQC_CMD 0x08 /* additional out buffer: * 0 1 2 3 4 * len X1 X2 X3 X4 * additional in buffer: * 0 1 2 - * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */ + * N/A 0 0 b[1] == b[2] == 0 -> success, failure otherwise */ -#define SET_LNB_POWER 0x09 +#define SET_LNB_POWER 0x09 /* additional out buffer: * 0 1 2 * 0x00 0xff 1 = on, 0 = off * additional in buffer: * 0 1 2 - * N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */ + * N/A 0 0 b[1] == b[2] == 0 -> success failure otherwise */ -#define GET_MAC_ADDRESS 0x0A +#define GET_MAC_ADDRESS 0x0A /* #define GET_MAC_ADDRESS 0x0B */ /* additional in buffer: * 0 1 2 3 4 5 6 7 8 * N/A N/A 0x0A or 0x0B MAC0 MAC1 MAC2 MAC3 MAC4 MAC5 */ -#define SET_PID_FILTER 0x11 +#define SET_PID_FILTER 0x11 /* additional in buffer: * 0 1 ... 14 15 16 * PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */ @@ -64,39 +64,38 @@ extern int dvb_usb_vp702x_debug; * freq0 freq1 divstep srate0 srate1 srate2 flag chksum */ - /* one direction requests */ -#define READ_REMOTE_REQ 0xB4 +#define READ_REMOTE_REQ 0xB4 /* IN i: 0; v: 0; b[0] == request, b[1] == key */ -#define READ_PID_NUMBER_REQ 0xB5 +#define READ_PID_NUMBER_REQ 0xB5 /* IN i: 0; v: 0; b[0] == request, b[1] == 0, b[2] = pid number */ -#define WRITE_EEPROM_REQ 0xB6 +#define WRITE_EEPROM_REQ 0xB6 /* OUT i: offset; v: value to write; no extra buffer */ -#define READ_EEPROM_REQ 0xB7 +#define READ_EEPROM_REQ 0xB7 /* IN i: bufferlen; v: offset; buffer with bufferlen bytes */ -#define READ_STATUS 0xB8 +#define READ_STATUS 0xB8 /* IN i: 0; v: 0; bufferlen 10 */ -#define READ_TUNER_REG_REQ 0xB9 +#define READ_TUNER_REG_REQ 0xB9 /* IN i: 0; v: register; b[0] = value */ -#define READ_FX2_REG_REQ 0xBA +#define READ_FX2_REG_REQ 0xBA /* IN i: offset; v: 0; b[0] = value */ -#define WRITE_FX2_REG_REQ 0xBB +#define WRITE_FX2_REG_REQ 0xBB /* OUT i: offset; v: value to write; 1 byte extra buffer */ -#define SET_TUNER_POWER_REQ 0xBC +#define SET_TUNER_POWER_REQ 0xBC /* IN i: 0 = power off, 1 = power on */ -#define WRITE_TUNER_REG_REQ 0xBD +#define WRITE_TUNER_REG_REQ 0xBD /* IN i: register, v: value to write, no extra buffer */ -#define RESET_TUNER 0xBE +#define RESET_TUNER 0xBE /* IN i: 0, v: 0, no extra buffer */ extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index 3835235b68df..028204956bb0 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = { .cold_ids = { &vp7045_usb_table[2], NULL }, .warm_ids = { &vp7045_usb_table[3], NULL }, }, - { NULL }, + { 0 }, } }; diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 8e269e1c1f9d..db3a8b40031e 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -16,6 +16,12 @@ config DVB_CX24110 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_CX24123 + tristate "Conexant CX24123 based" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + config DVB_TDA8083 tristate "Philips TDA8083 based" depends on DVB_CORE @@ -50,18 +56,19 @@ comment "DVB-T (terrestrial) frontends" depends on DVB_CORE config DVB_SP8870 - tristate "Spase sp8870 based" + tristate "Spase sp8870 based" depends on DVB_CORE select FW_LOADER help - A DVB-T tuner module. Say Y when you want to support this frontend. + A DVB-T tuner module. Say Y when you want to support this frontend. This driver needs external firmware. Please use the command "<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to - download/extract it, and then copy it to /usr/lib/hotplug/firmware. + download/extract it, and then copy it to /usr/lib/hotplug/firmware + or /lib/firmware (depending on configuration of firmware hotplug). config DVB_SP887X - tristate "Spase sp887x based" + tristate "Spase sp887x based" depends on DVB_CORE select FW_LOADER help @@ -69,7 +76,8 @@ config DVB_SP887X This driver needs external firmware. Please use the command "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to - download/extract it, and then copy it to /usr/lib/hotplug/firmware. + download/extract it, and then copy it to /usr/lib/hotplug/firmware + or /lib/firmware (depending on configuration of firmware hotplug). config DVB_CX22700 tristate "Conexant CX22700 based" @@ -78,10 +86,10 @@ config DVB_CX22700 A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_CX22702 - tristate "Conexant cx22702 demodulator (OFDM)" - depends on DVB_CORE - help - A DVB-T tuner module. Say Y when you want to support this frontend. + tristate "Conexant cx22702 demodulator (OFDM)" + depends on DVB_CORE + help + A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_L64781 tristate "LSI L64781" @@ -98,8 +106,9 @@ config DVB_TDA1004X This driver needs external firmware. Please use the commands "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045", - "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to - download/extract them, and then copy them to /usr/lib/hotplug/firmware. + "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to + download/extract them, and then copy them to /usr/lib/hotplug/firmware + or /lib/firmware (depending on configuration of firmware hotplug). config DVB_NXT6000 tristate "NxtWave Communications NXT6000 based" @@ -140,13 +149,13 @@ config DVB_VES1820 tristate "VLSI VES1820 based" depends on DVB_CORE help - A DVB-C tuner module. Say Y when you want to support this frontend. + A DVB-C tuner module. Say Y when you want to support this frontend. config DVB_TDA10021 tristate "Philips TDA10021 based" depends on DVB_CORE help - A DVB-C tuner module. Say Y when you want to support this frontend. + A DVB-C tuner module. Say Y when you want to support this frontend. config DVB_STV0297 tristate "ST STV0297 based" @@ -164,6 +173,11 @@ config DVB_NXT2002 help An ATSC 8VSB tuner module. Say Y when you want to support this frontend. + This driver needs external firmware. Please use the command + "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to + download/extract it, and then copy it to /usr/lib/hotplug/firmware + or /lib/firmware (depending on configuration of firmware hotplug). + config DVB_NXT200X tristate "Nextwave NXT2002/NXT2004 based" depends on DVB_CORE @@ -172,6 +186,12 @@ config DVB_NXT200X An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. + This driver needs external firmware. Please use the commands + "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" and + "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to + download/extract them, and then copy them to /usr/lib/hotplug/firmware + or /lib/firmware (depending on configuration of firmware hotplug). + config DVB_OR51211 tristate "or51211 based (pcHDTV HD2000 card)" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index a98760fe08a1..615ec830e1c9 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o obj-$(CONFIG_DVB_BCM3510) += bcm3510.o obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o +obj-$(CONFIG_DVB_CX24123) += cx24123.o diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c index 8ceb9a33c7af..3b132bafd4de 100644 --- a/drivers/media/dvb/frontends/bcm3510.c +++ b/drivers/media/dvb/frontends/bcm3510.c @@ -255,7 +255,7 @@ static int bcm3510_bert_reset(struct bcm3510_state *st) bcm3510_register_value b; int ret; - if ((ret < bcm3510_readB(st,0xfa,&b)) < 0) + if ((ret = bcm3510_readB(st,0xfa,&b)) < 0) return ret; b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b); @@ -623,13 +623,13 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe) err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret); return ret; } - deb_info("got firmware: %d\n",fw->size); + deb_info("got firmware: %zd\n",fw->size); b = fw->data; for (i = 0; i < fw->size;) { addr = le16_to_cpu( *( (u16 *)&b[i] ) ); len = le16_to_cpu( *( (u16 *)&b[i+2] ) ); - deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size); + deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size); if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) { err("firmware download failed: %d\n",ret); return ret; diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c index 5de0e6d350b1..0fc899f81c5e 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb/frontends/cx22702.c @@ -195,6 +195,16 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet return 0; } +static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct cx22702_state* state = fe->demodulator_priv; + dprintk ("%s(%d)\n", __FUNCTION__, enable); + if (enable) + return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe); + else + return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) | 1); +} + /* 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) { @@ -202,7 +212,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet struct cx22702_state* state = fe->demodulator_priv; /* set PLL */ - cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe); + cx22702_i2c_gate_ctrl(fe, 1); if (state->config->pll_set) { state->config->pll_set(fe, p); } else if (state->config->pll_desc) { @@ -216,7 +226,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet } else { BUG(); } - cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1); + cx22702_i2c_gate_ctrl(fe, 0); /* set inversion */ cx22702_set_inversion (state, p->inversion); @@ -349,11 +359,10 @@ static int cx22702_init (struct dvb_frontend* fe) cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02); /* init PLL */ - if (state->config->pll_init) { - cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) & 0xfe); + if (state->config->pll_init) state->config->pll_init(fe); - cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1); - } + + cx22702_i2c_gate_ctrl(fe, 0); return 0; } @@ -531,6 +540,7 @@ static struct dvb_frontend_ops cx22702_ops = { .read_signal_strength = cx22702_read_signal_strength, .read_snr = cx22702_read_snr, .read_ucblocks = cx22702_read_ucblocks, + .i2c_gate_ctrl = cx22702_i2c_gate_ctrl, }; module_param(debug, int, 0644); diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index 0c4db80ec332..d15d32c51dc5 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -27,7 +27,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> -#include <linux/jiffies.h> #include "dvb_frontend.h" #include "cx24110.h" @@ -56,7 +55,7 @@ static int debug; static struct {u8 reg; u8 data;} cx24110_regdata[]= /* Comments beginning with @ denote this value should - be the default */ + be the default */ {{0x09,0x01}, /* SoftResetAll */ {0x09,0x00}, /* release reset */ {0x01,0xe8}, /* MSB of code rate 27.5MS/s */ @@ -67,26 +66,26 @@ static struct {u8 reg; u8 data;} cx24110_regdata[]= {0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */ {0x0a,0x00}, /* @ partial chip disables, do not set */ {0x0b,0x01}, /* set output clock in gapped mode, start signal low - active for first byte */ + active for first byte */ {0x0c,0x11}, /* no parity bytes, large hold time, serial data out */ {0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */ {0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1 - to avoid starting the BER counter. Reset the - CRC test bit. Finite counting selected */ + to avoid starting the BER counter. Reset the + CRC test bit. Finite counting selected */ {0x15,0xff}, /* @ size of the limited time window for RS BER - estimation. It is <value>*256 RS blocks, this - gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */ + estimation. It is <value>*256 RS blocks, this + gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */ {0x16,0x00}, /* @ enable all RS output ports */ {0x17,0x04}, /* @ time window allowed for the RS to sync */ {0x18,0xae}, /* @ allow all standard DVB code rates to be scanned - for automatically */ + for automatically */ /* leave the current code rate and normalization - registers as they are after reset... */ + registers as they are after reset... */ {0x21,0x10}, /* @ during AutoAcq, search each viterbi setting - only once */ + only once */ {0x23,0x18}, /* @ size of the limited time window for Viterbi BER - estimation. It is <value>*65536 channel bits, i.e. - approx. 38ms at 27.5MS/s, rate 3/4 */ + estimation. It is <value>*65536 channel bits, i.e. + approx. 38ms at 27.5MS/s, rate 3/4 */ {0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */ /* leave front-end AGC parameters at default values */ /* leave decimation AGC parameters at default values */ diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c new file mode 100644 index 000000000000..d661c6f9cbe5 --- /dev/null +++ b/drivers/media/dvb/frontends/cx24123.c @@ -0,0 +1,889 @@ +/* + Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver + + Copyright (C) 2005 Steven Toth <stoth@hauppauge.com> + + Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc> + + 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/slab.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> + +#include "dvb_frontend.h" +#include "cx24123.h" + +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk (KERN_DEBUG "cx24123: " args); \ + } while (0) + +struct cx24123_state +{ + struct i2c_adapter* i2c; + struct dvb_frontend_ops ops; + const struct cx24123_config* config; + + struct dvb_frontend frontend; + + u32 lastber; + u16 snr; + u8 lnbreg; + + /* Some PLL specifics for tuning */ + u32 VCAarg; + u32 VGAarg; + u32 bandselectarg; + u32 pllarg; + + /* The Demod/Tuner can't easily provide these, we cache them */ + u32 currentfreq; + u32 currentsymbolrate; +}; + +/* Various tuner defaults need to be established for a given symbol rate Sps */ +static struct +{ + u32 symbolrate_low; + u32 symbolrate_high; + u32 VCAslope; + u32 VCAoffset; + u32 VGA1offset; + u32 VGA2offset; + u32 VCAprogdata; + u32 VGAprogdata; +} cx24123_AGC_vals[] = +{ + { + .symbolrate_low = 1000000, + .symbolrate_high = 4999999, + .VCAslope = 0x07, + .VCAoffset = 0x0f, + .VGA1offset = 0x1f8, + .VGA2offset = 0x1f8, + .VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8, + .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07, + }, + { + .symbolrate_low = 5000000, + .symbolrate_high = 14999999, + .VCAslope = 0x1f, + .VCAoffset = 0x1f, + .VGA1offset = 0x1e0, + .VGA2offset = 0x180, + .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, + .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f, + }, + { + .symbolrate_low = 15000000, + .symbolrate_high = 45000000, + .VCAslope = 0x3f, + .VCAoffset = 0x3f, + .VGA1offset = 0x180, + .VGA2offset = 0x100, + .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180, + .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f, + }, +}; + +/* + * Various tuner defaults need to be established for a given frequency kHz. + * fixme: The bounds on the bands do not match the doc in real life. + * fixme: Some of them have been moved, other might need adjustment. + */ +static struct +{ + u32 freq_low; + u32 freq_high; + u32 bandselect; + u32 VCOdivider; + u32 VCOnumber; + u32 progdata; +} cx24123_bandselect_vals[] = +{ + { + .freq_low = 950000, + .freq_high = 1018999, + .bandselect = 0x40, + .VCOdivider = 4, + .VCOnumber = 7, + .progdata = (0 << 18) | (0 << 9) | 0x40, + }, + { + .freq_low = 1019000, + .freq_high = 1074999, + .bandselect = 0x80, + .VCOdivider = 4, + .VCOnumber = 8, + .progdata = (0 << 18) | (0 << 9) | 0x80, + }, + { + .freq_low = 1075000, + .freq_high = 1227999, + .bandselect = 0x01, + .VCOdivider = 2, + .VCOnumber = 1, + .progdata = (0 << 18) | (1 << 9) | 0x01, + }, + { + .freq_low = 1228000, + .freq_high = 1349999, + .bandselect = 0x02, + .VCOdivider = 2, + .VCOnumber = 2, + .progdata = (0 << 18) | (1 << 9) | 0x02, + }, + { + .freq_low = 1350000, + .freq_high = 1481999, + .bandselect = 0x04, + .VCOdivider = 2, + .VCOnumber = 3, + .progdata = (0 << 18) | (1 << 9) | 0x04, + }, + { + .freq_low = 1482000, + .freq_high = 1595999, + .bandselect = 0x08, + .VCOdivider = 2, + .VCOnumber = 4, + .progdata = (0 << 18) | (1 << 9) | 0x08, + }, + { + .freq_low = 1596000, + .freq_high = 1717999, + .bandselect = 0x10, + .VCOdivider = 2, + .VCOnumber = 5, + .progdata = (0 << 18) | (1 << 9) | 0x10, + }, + { + .freq_low = 1718000, + .freq_high = 1855999, + .bandselect = 0x20, + .VCOdivider = 2, + .VCOnumber = 6, + .progdata = (0 << 18) | (1 << 9) | 0x20, + }, + { + .freq_low = 1856000, + .freq_high = 2035999, + .bandselect = 0x40, + .VCOdivider = 2, + .VCOnumber = 7, + .progdata = (0 << 18) | (1 << 9) | 0x40, + }, + { + .freq_low = 2036000, + .freq_high = 2149999, + .bandselect = 0x80, + .VCOdivider = 2, + .VCOnumber = 8, + .progdata = (0 << 18) | (1 << 9) | 0x80, + }, +}; + +static struct { + u8 reg; + u8 data; +} cx24123_regdata[] = +{ + {0x00, 0x03}, /* Reset system */ + {0x00, 0x00}, /* Clear reset */ + {0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */ + {0x03, 0x07}, + {0x04, 0x10}, + {0x05, 0x04}, + {0x06, 0x31}, + {0x0d, 0x02}, + {0x0e, 0x03}, + {0x0f, 0xfe}, + {0x10, 0x01}, + {0x14, 0x01}, + {0x15, 0x98}, + {0x16, 0x00}, + {0x17, 0x01}, + {0x1b, 0x05}, + {0x1c, 0x80}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x20, 0x41}, + {0x21, 0x15}, + {0x27, 0x14}, + {0x28, 0x46}, + {0x29, 0x00}, + {0x2a, 0xb0}, + {0x2b, 0x73}, + {0x2c, 0x00}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x8c}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x03}, + {0x36, 0x02}, + {0x37, 0x3a}, + {0x3a, 0x00}, /* Enable AGC accumulator */ + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x05}, + {0x56, 0x41}, + {0x57, 0xff}, + {0x67, 0x83}, +}; + +static int cx24123_writereg(struct cx24123_state* state, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; + int err; + + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { + printk("%s: writereg error(err == %i, reg == 0x%02x," + " data == 0x%02x)\n", __FUNCTION__, err, reg, data); + return -EREMOTEIO; + } + + return 0; +} + +static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data) +{ + u8 buf[] = { reg, data }; + /* fixme: put the intersil addr int the config */ + struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 }; + int err; + + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { + printk("%s: writelnbreg error (err == %i, reg == 0x%02x," + " data == 0x%02x)\n", __FUNCTION__, err, reg, data); + return -EREMOTEIO; + } + + /* cache the write, no way to read back */ + state->lnbreg = data; + + return 0; +} + +static int cx24123_readreg(struct cx24123_state* state, u8 reg) +{ + 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_transfer(state->i2c, msg, 2); + + if (ret != 2) { + printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret); + return ret; + } + + return b1[0]; +} + +static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg) +{ + return state->lnbreg; +} + +static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion) +{ + switch (inversion) { + case INVERSION_OFF: + cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f); + cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); + break; + case INVERSION_ON: + cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80); + cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); + break; + case INVERSION_AUTO: + cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_inversion_t *inversion) +{ + u8 val; + + val = cx24123_readreg(state, 0x1b) >> 7; + + if (val == 0) + *inversion = INVERSION_OFF; + else + *inversion = INVERSION_ON; + + return 0; +} + +static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) +{ + if ( (fec < FEC_NONE) || (fec > FEC_AUTO) ) + fec = FEC_AUTO; + + /* Hardware has 5/11 and 3/5 but are never unused */ + switch (fec) { + case FEC_NONE: + return cx24123_writereg(state, 0x0f, 0x01); + case FEC_1_2: + return cx24123_writereg(state, 0x0f, 0x02); + case FEC_2_3: + return cx24123_writereg(state, 0x0f, 0x04); + case FEC_3_4: + return cx24123_writereg(state, 0x0f, 0x08); + case FEC_5_6: + return cx24123_writereg(state, 0x0f, 0x20); + case FEC_7_8: + return cx24123_writereg(state, 0x0f, 0x80); + case FEC_AUTO: + return cx24123_writereg(state, 0x0f, 0xae); + default: + return -EOPNOTSUPP; + } +} + +static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) +{ + int ret; + u8 val; + + ret = cx24123_readreg (state, 0x1b); + if (ret < 0) + return ret; + val = ret & 0x07; + switch (val) { + case 1: + *fec = FEC_1_2; + break; + case 3: + *fec = FEC_2_3; + break; + case 4: + *fec = FEC_3_4; + break; + case 5: + *fec = FEC_4_5; + break; + case 6: + *fec = FEC_5_6; + break; + case 7: + *fec = FEC_7_8; + break; + case 2: /* *fec = FEC_3_5; break; */ + case 0: /* *fec = FEC_5_11; break; */ + *fec = FEC_AUTO; + break; + default: + *fec = FEC_NONE; // can't happen + } + + return 0; +} + +/* fixme: Symbol rates < 3MSps may not work because of precision loss */ +static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) +{ + u32 val; + + val = (srate / 1185) * 100; + + /* Compensate for scaling up, by removing 17 symbols per 1Msps */ + val = val - (17 * (srate / 1000000)); + + cx24123_writereg(state, 0x08, (val >> 16) & 0xff ); + cx24123_writereg(state, 0x09, (val >> 8) & 0xff ); + cx24123_writereg(state, 0x0a, (val ) & 0xff ); + + return 0; +} + +/* + * Based on the required frequency and symbolrate, the tuner AGC has to be configured + * and the correct band selected. Calculate those values + */ +static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct cx24123_state *state = fe->demodulator_priv; + u32 ndiv = 0, adiv = 0, vco_div = 0; + int i = 0; + + /* Defaults for low freq, low rate */ + state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; + state->VGAarg = cx24123_AGC_vals[0].VGAprogdata; + state->bandselectarg = cx24123_bandselect_vals[0].progdata; + vco_div = cx24123_bandselect_vals[0].VCOdivider; + + /* For the given symbolerate, determine the VCA and VGA programming bits */ + for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++) + { + if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) && + (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { + state->VCAarg = cx24123_AGC_vals[i].VCAprogdata; + state->VGAarg = cx24123_AGC_vals[i].VGAprogdata; + } + } + + /* For the given frequency, determine the bandselect programming bits */ + for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++) + { + if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && + (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) { + state->bandselectarg = cx24123_bandselect_vals[i].progdata; + vco_div = cx24123_bandselect_vals[i].VCOdivider; + } + } + + /* Determine the N/A dividers for the requested lband freq (in kHz). */ + /* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */ + ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff; + adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f; + + if (adiv == 0) + adiv++; + + /* determine the correct pll frequency values. */ + /* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */ + state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14); + state->pllarg |= (ndiv << 5) | adiv; + + return 0; +} + +/* + * Tuner data is 21 bits long, must be left-aligned in data. + * Tuner cx24109 is written through a dedicated 3wire interface on the demod chip. + */ +static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data) +{ + struct cx24123_state *state = fe->demodulator_priv; + unsigned long timeout; + + /* align the 21 bytes into to bit23 boundary */ + data = data << 3; + + /* Reset the demod pll word length to 0x15 bits */ + cx24123_writereg(state, 0x21, 0x15); + + /* write the msb 8 bits, wait for the send to be completed */ + timeout = jiffies + msecs_to_jiffies(40); + cx24123_writereg(state, 0x22, (data >> 16) & 0xff); + while ((cx24123_readreg(state, 0x20) & 0x40) == 0) { + if (time_after(jiffies, timeout)) { + printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__); + return -EREMOTEIO; + } + msleep(10); + } + + /* send another 8 bytes, wait for the send to be completed */ + timeout = jiffies + msecs_to_jiffies(40); + cx24123_writereg(state, 0x22, (data>>8) & 0xff ); + while ((cx24123_readreg(state, 0x20) & 0x40) == 0) { + if (time_after(jiffies, timeout)) { + printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__); + return -EREMOTEIO; + } + msleep(10); + } + + /* send the lower 5 bits of this byte, padded with 3 LBB, wait for the send to be completed */ + timeout = jiffies + msecs_to_jiffies(40); + cx24123_writereg(state, 0x22, (data) & 0xff ); + while ((cx24123_readreg(state, 0x20) & 0x80)) { + if (time_after(jiffies, timeout)) { + printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__); + return -EREMOTEIO; + } + msleep(10); + } + + /* Trigger the demod to configure the tuner */ + cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) | 2); + cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) & 0xfd); + + return 0; +} + +static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct cx24123_state *state = fe->demodulator_priv; + + if (cx24123_pll_calculate(fe, p) != 0) { + printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__); + return -EINVAL; + } + + /* Write the new VCO/VGA */ + cx24123_pll_writereg(fe, p, state->VCAarg); + cx24123_pll_writereg(fe, p, state->VGAarg); + + /* Write the new bandselect and pll args */ + cx24123_pll_writereg(fe, p, state->bandselectarg); + cx24123_pll_writereg(fe, p, state->pllarg); + + return 0; +} + +static int cx24123_initfe(struct dvb_frontend* fe) +{ + struct cx24123_state *state = fe->demodulator_priv; + int i; + + /* Configure the demod to a good set of defaults */ + for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++) + cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); + + if (state->config->pll_init) + state->config->pll_init(fe); + + /* Configure the LNB for 14V */ + if (state->config->use_isl6421) + cx24123_writelnbreg(state, 0x0, 0x2a); + + return 0; +} + +static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + struct cx24123_state *state = fe->demodulator_priv; + u8 val; + + switch (state->config->use_isl6421) { + + case 1: + + val = cx24123_readlnbreg(state, 0x0); + + switch (voltage) { + case SEC_VOLTAGE_13: + return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */ + case SEC_VOLTAGE_18: + return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */ + case SEC_VOLTAGE_OFF: + return cx24123_writelnbreg(state, 0x0, val & 0x30); + default: + return -EINVAL; + }; + + case 0: + + val = cx24123_readreg(state, 0x29); + + switch (voltage) { + case SEC_VOLTAGE_13: + dprintk("%s: setting voltage 13V\n", __FUNCTION__); + if (state->config->enable_lnb_voltage) + state->config->enable_lnb_voltage(fe, 1); + return cx24123_writereg(state, 0x29, val | 0x80); + case SEC_VOLTAGE_18: + dprintk("%s: setting voltage 18V\n", __FUNCTION__); + if (state->config->enable_lnb_voltage) + state->config->enable_lnb_voltage(fe, 1); + return cx24123_writereg(state, 0x29, val & 0x7f); + case SEC_VOLTAGE_OFF: + dprintk("%s: setting voltage off\n", __FUNCTION__); + if (state->config->enable_lnb_voltage) + state->config->enable_lnb_voltage(fe, 0); + return 0; + default: + return -EINVAL; + }; + } + + return 0; +} + +static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd *cmd) +{ + /* fixme: Implement diseqc */ + printk("%s: No support yet\n",__FUNCTION__); + + return -ENOTSUPP; +} + +static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + struct cx24123_state *state = fe->demodulator_priv; + + int sync = cx24123_readreg(state, 0x14); + int lock = cx24123_readreg(state, 0x20); + + *status = 0; + if (lock & 0x01) + *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; + if (sync & 0x04) + *status |= FE_HAS_VITERBI; + if (sync & 0x08) + *status |= FE_HAS_CARRIER; + if (sync & 0x80) + *status |= FE_HAS_SYNC | FE_HAS_LOCK; + + return 0; +} + +/* + * Configured to return the measurement of errors in blocks, because no UCBLOCKS value + * is available, so this value doubles up to satisfy both measurements + */ +static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber) +{ + struct cx24123_state *state = fe->demodulator_priv; + + state->lastber = + ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) | + (cx24123_readreg(state, 0x1d) << 8 | + cx24123_readreg(state, 0x1e)); + + /* Do the signal quality processing here, it's derived from the BER. */ + /* Scale the BER from a 24bit to a SNR 16 bit where higher = better */ + if (state->lastber < 5000) + state->snr = 655*100; + else if ( (state->lastber >= 5000) && (state->lastber < 55000) ) + state->snr = 655*90; + else if ( (state->lastber >= 55000) && (state->lastber < 150000) ) + state->snr = 655*80; + else if ( (state->lastber >= 150000) && (state->lastber < 250000) ) + state->snr = 655*70; + else if ( (state->lastber >= 250000) && (state->lastber < 450000) ) + state->snr = 655*65; + else + state->snr = 0; + + *ber = state->lastber; + + return 0; +} + +static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) +{ + struct cx24123_state *state = fe->demodulator_priv; + *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */ + + return 0; +} + +static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr) +{ + struct cx24123_state *state = fe->demodulator_priv; + *snr = state->snr; + + return 0; +} + +static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct cx24123_state *state = fe->demodulator_priv; + *ucblocks = state->lastber; + + return 0; +} + +static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct cx24123_state *state = fe->demodulator_priv; + + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 0); + + state->currentfreq=p->frequency; + state->currentsymbolrate = p->u.qpsk.symbol_rate; + + cx24123_set_inversion(state, p->inversion); + cx24123_set_fec(state, p->u.qpsk.fec_inner); + cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate); + cx24123_pll_tune(fe, p); + + /* Enable automatic aquisition and reset cycle */ + cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07)); + cx24123_writereg(state, 0x00, 0x10); + cx24123_writereg(state, 0x00, 0); + + return 0; +} + +static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct cx24123_state *state = fe->demodulator_priv; + + if (cx24123_get_inversion(state, &p->inversion) != 0) { + printk("%s: Failed to get inversion status\n",__FUNCTION__); + return -EREMOTEIO; + } + if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) { + printk("%s: Failed to get fec status\n",__FUNCTION__); + return -EREMOTEIO; + } + p->frequency = state->currentfreq; + p->u.qpsk.symbol_rate = state->currentsymbolrate; + + return 0; +} + +static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct cx24123_state *state = fe->demodulator_priv; + u8 val; + + switch (state->config->use_isl6421) { + case 1: + + val = cx24123_readlnbreg(state, 0x0); + + switch (tone) { + case SEC_TONE_ON: + return cx24123_writelnbreg(state, 0x0, val | 0x10); + case SEC_TONE_OFF: + return cx24123_writelnbreg(state, 0x0, val & 0x2f); + default: + printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); + return -EINVAL; + } + + case 0: + + val = cx24123_readreg(state, 0x29); + + switch (tone) { + case SEC_TONE_ON: + dprintk("%s: setting tone on\n", __FUNCTION__); + return cx24123_writereg(state, 0x29, val | 0x10); + case SEC_TONE_OFF: + dprintk("%s: setting tone off\n",__FUNCTION__); + return cx24123_writereg(state, 0x29, val & 0xef); + default: + printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); + return -EINVAL; + } + } + + return 0; +} + +static void cx24123_release(struct dvb_frontend* fe) +{ + struct cx24123_state* state = fe->demodulator_priv; + dprintk("%s\n",__FUNCTION__); + kfree(state); +} + +static struct dvb_frontend_ops cx24123_ops; + +struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, + struct i2c_adapter* i2c) +{ + struct cx24123_state* state = NULL; + int ret; + + dprintk("%s\n",__FUNCTION__); + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL); + if (state == NULL) { + printk("Unable to kmalloc\n"); + goto error; + } + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops)); + state->lastber = 0; + state->snr = 0; + state->lnbreg = 0; + state->VCAarg = 0; + state->VGAarg = 0; + state->bandselectarg = 0; + state->pllarg = 0; + state->currentfreq = 0; + state->currentsymbolrate = 0; + + /* check if the demod is there */ + ret = cx24123_readreg(state, 0x00); + if ((ret != 0xd1) && (ret != 0xe1)) { + printk("Version != d1 or e1\n"); + goto error; + } + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + + return NULL; +} + +static struct dvb_frontend_ops cx24123_ops = { + + .info = { + .name = "Conexant CX24123/CX24109", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 1011, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_INVERSION_AUTO | + 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_RECOVER + }, + + .release = cx24123_release, + + .init = cx24123_initfe, + .set_frontend = cx24123_set_frontend, + .get_frontend = cx24123_get_frontend, + .read_status = cx24123_read_status, + .read_ber = cx24123_read_ber, + .read_signal_strength = cx24123_read_signal_strength, + .read_snr = cx24123_read_snr, + .read_ucblocks = cx24123_read_ucblocks, + .diseqc_send_master_cmd = cx24123_send_diseqc_msg, + .set_tone = cx24123_set_tone, + .set_voltage = cx24123_set_voltage, +}; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware"); +MODULE_AUTHOR("Steven Toth"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(cx24123_attach); diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h new file mode 100644 index 000000000000..0c922b5e9263 --- /dev/null +++ b/drivers/media/dvb/frontends/cx24123.h @@ -0,0 +1,51 @@ +/* + Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver + + Copyright (C) 2005 Steven Toth <stoth@hauppauge.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 CX24123_H +#define CX24123_H + +#include <linux/dvb/frontend.h> + +struct cx24123_config +{ + /* the demodulator's i2c address */ + u8 demod_address; + + /* + cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip + for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits + from register 0x29 of the CX24123 demodulator + */ + int use_isl6421; + + /* PLL maintenance */ + int (*pll_init)(struct dvb_frontend* fe); + int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); + + /* Need to set device param for start_dma */ + int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); + + void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on); +}; + +extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, + struct i2c_adapter* i2c); + +#endif /* CX24123_H */ diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index f857b869616c..a3d57ce9dd12 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -107,18 +107,19 @@ struct dvb_pll_desc dvb_pll_microtune_4042 = { }; EXPORT_SYMBOL(dvb_pll_microtune_4042); -struct dvb_pll_desc dvb_pll_thomson_dtt7611 = { - .name = "Thomson dtt7611", - .min = 44000000, - .max = 958000000, +struct dvb_pll_desc dvb_pll_thomson_dtt761x = { + /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ + .name = "Thomson dtt761x", + .min = 57000000, + .max = 863000000, .count = 3, .entries = { - { 157250000, 44000000, 62500, 0x8e, 0x39 }, - { 454000000, 44000000, 62500, 0x8e, 0x3a }, + { 147000000, 44000000, 62500, 0x8e, 0x39 }, + { 417000000, 44000000, 62500, 0x8e, 0x3a }, { 999999999, 44000000, 62500, 0x8e, 0x3c }, }, }; -EXPORT_SYMBOL(dvb_pll_thomson_dtt7611); +EXPORT_SYMBOL(dvb_pll_thomson_dtt761x); struct dvb_pll_desc dvb_pll_unknown_1 = { .name = "unknown 1", /* used by dntv live dvb-t */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 497d31dcf41e..24d4d2e9acd8 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -25,7 +25,7 @@ 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_microtune_4042; -extern struct dvb_pll_desc dvb_pll_thomson_dtt7611; +extern struct dvb_pll_desc dvb_pll_thomson_dtt761x; extern struct dvb_pll_desc dvb_pll_unknown_1; extern struct dvb_pll_desc dvb_pll_tua6010xs; diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index cb5301865d07..9d214643b87a 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -27,6 +27,7 @@ * DViCO FusionHDTV 3 Gold-T * DViCO FusionHDTV 5 Gold * DViCO FusionHDTV 5 Lite + * DViCO FusionHDTV 5 USB Gold * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) * * TODO: @@ -402,6 +403,8 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, state->config->pll_set(fe, param); /* Keep track of the new frequency */ + /* FIXME this is the wrong way to do this... */ + /* The tuner is shared with the video4linux analog API */ state->current_frequency = param->frequency; lgdt330x_SwReset(state); diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index 8d672283c93d..ec4e641acc64 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -501,7 +501,8 @@ static int mt312_set_frontend(struct dvb_frontend* fe, case ID_VP310: // For now we will do this only for the VP310. // It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03 - if ((ret = mt312_readreg(state, CONFIG, &config_val) < 0)) + ret = mt312_readreg(state, CONFIG, &config_val); + if (ret < 0) return ret; if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz { diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c index 52c416043a62..4f263e65ba14 100644 --- a/drivers/media/dvb/frontends/nxt2002.c +++ b/drivers/media/dvb/frontends/nxt2002.c @@ -22,7 +22,8 @@ /* * This driver needs external firmware. Please use the command * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to - * download/extract it, and then copy it to /usr/lib/hotplug/firmware. + * download/extract it, and then copy it to /usr/lib/hotplug/firmware + * or /lib/firmware (depending on configuration of firmware hotplug). */ #define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" #define CRC_CCIT_MASK 0x1021 diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c index a458a3bfff70..a16eeba0020d 100644 --- a/drivers/media/dvb/frontends/nxt6000.c +++ b/drivers/media/dvb/frontends/nxt6000.c @@ -574,11 +574,11 @@ static struct dvb_frontend_ops nxt6000_ops = { .symbol_rate_max = 9360000, /* FIXME */ .symbol_rate_tolerance = 4000, .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO, }, .release = nxt6000_release, diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index 531f76246e5f..7c3aed1f546b 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c @@ -25,7 +25,8 @@ /* * This driver needs external firmware. Please use the command * "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to - * download/extract it, and then copy it to /usr/lib/hotplug/firmware. + * download/extract it, and then copy it to /usr/lib/hotplug/firmware + * or /lib/firmware (depending on configuration of firmware hotplug). */ #define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw" @@ -112,7 +113,7 @@ static int or51211_load_firmware (struct dvb_frontend* fe, u8 tudata[585]; int i; - dprintk("Firmware is %d bytes\n",fw->size); + dprintk("Firmware is %zd bytes\n",fw->size); /* Get eprom data */ tudata[0] = 17; diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index 18715091aed8..d69477596921 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -521,8 +521,8 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state, case FEC_3_4: s5h1420_writereg(state, 0x30, 0x04); - s5h1420_writereg(state, 0x31, 0x12 | inversion); - break; + s5h1420_writereg(state, 0x31, 0x12 | inversion); + break; case FEC_5_6: s5h1420_writereg(state, 0x30, 0x08); diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c index fc06cd6b46c3..73829e647e50 100644 --- a/drivers/media/dvb/frontends/sp8870.c +++ b/drivers/media/dvb/frontends/sp8870.c @@ -22,7 +22,8 @@ /* * This driver needs external firmware. Please use the command * "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to - * download/extract it, and then copy it to /usr/lib/hotplug/firmware. + * download/extract it, and then copy it to /usr/lib/hotplug/firmware + * or /lib/firmware (depending on configuration of firmware hotplug). */ #define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw" diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c index e3b665782243..eb8a602198ca 100644 --- a/drivers/media/dvb/frontends/sp887x.c +++ b/drivers/media/dvb/frontends/sp887x.c @@ -5,7 +5,8 @@ /* * This driver needs external firmware. Please use the command * "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to - * download/extract it, and then copy it to /usr/lib/hotplug/firmware. + * download/extract it, and then copy it to /usr/lib/hotplug/firmware + * or /lib/firmware (depending on configuration of firmware hotplug). */ #define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw" @@ -581,7 +582,7 @@ static struct dvb_frontend_ops sp887x_ops = { .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_RECOVER + FE_CAN_RECOVER }, .release = sp887x_release, diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 177d71d56b67..5bcd00f792e6 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -131,6 +131,13 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len return ret == 2 ? 0 : ret; } +int stv0299_enable_plli2c (struct dvb_frontend* fe) +{ + struct stv0299_state* state = fe->demodulator_priv; + + return stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ +} + static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec) { dprintk ("%s\n", __FUNCTION__); @@ -387,7 +394,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag }; } -static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) +static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd) { struct stv0299_state* state = fe->demodulator_priv; u8 reg0x08; @@ -407,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) cmd = cmd << 1; if (debug_legacy_dish_switch) - printk ("%s switch command: 0x%04x\n",__FUNCTION__, cmd); + printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd); do_gettimeofday (&nexttime); if (debug_legacy_dish_switch) @@ -717,5 +724,6 @@ MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, " "Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(stv0299_enable_plli2c); EXPORT_SYMBOL(stv0299_writereg); EXPORT_SYMBOL(stv0299_attach); diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h index 9af3d71c89db..32c87b4c2f13 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb/frontends/stv0299.h @@ -94,6 +94,7 @@ struct stv0299_config }; extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data); +extern int stv0299_enable_plli2c (struct dvb_frontend* fe); extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, struct i2c_adapter* i2c); diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 425cd19136fe..21255cac9793 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -95,7 +95,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg) 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 } }; + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; int ret; ret = i2c_transfer (state->i2c, msg, 2); @@ -434,7 +434,7 @@ static struct dvb_frontend_ops tda10021_ops = { .frequency_max = 858000000, .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */ .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */ - #if 0 +#if 0 .frequency_tolerance = ???, .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */ #endif diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index dd02aff467fe..c63e9a5084eb 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -23,7 +23,8 @@ * This driver needs external firmware. Please use the commands * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045", * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to - * download/extract them, and then copy them to /usr/lib/hotplug/firmware. + * download/extract them, and then copy them to /usr/lib/hotplug/firmware + * or /lib/firmware (depending on configuration of firmware hotplug). */ #define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw" #define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw" @@ -271,32 +272,57 @@ static int tda10045h_set_bandwidth(struct tda1004x_state *state, static int tda10046h_set_bandwidth(struct tda1004x_state *state, fe_bandwidth_t bandwidth) { - static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e }; - static u8 bandwidth_7mhz[] = { 0x6e, 0x02, 0x53, 0xc8, 0x25 }; - static u8 bandwidth_8mhz[] = { 0x60, 0x12, 0xa8, 0xe4, 0xbd }; - + static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 }; + static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f }; + static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d }; + + static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 }; + static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab }; + static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 }; + int tda10046_clk53m; + + if ((state->config->if_freq == TDA10046_FREQ_045) || + (state->config->if_freq == TDA10046_FREQ_052)) + tda10046_clk53m = 0; + else + tda10046_clk53m = 1; switch (bandwidth) { case BANDWIDTH_6_MHZ: - tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz)); + if (tda10046_clk53m) + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M, + sizeof(bandwidth_6mhz_53M)); + else + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M, + sizeof(bandwidth_6mhz_48M)); if (state->config->if_freq == TDA10046_FREQ_045) { - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x09); - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x4f); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab); } break; case BANDWIDTH_7_MHZ: - tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz)); + if (tda10046_clk53m) + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M, + sizeof(bandwidth_7mhz_53M)); + else + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M, + sizeof(bandwidth_7mhz_48M)); if (state->config->if_freq == TDA10046_FREQ_045) { - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a); - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x79); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00); } break; case BANDWIDTH_8_MHZ: - tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz)); + if (tda10046_clk53m) + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M, + sizeof(bandwidth_8mhz_53M)); + else + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M, + sizeof(bandwidth_8mhz_48M)); if (state->config->if_freq == TDA10046_FREQ_045) { - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b); - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55); } break; @@ -418,9 +444,22 @@ static int tda10045_fwupload(struct dvb_frontend* fe) static void tda10046_init_plls(struct dvb_frontend* fe) { struct tda1004x_state* state = fe->demodulator_priv; + int tda10046_clk53m; + + if ((state->config->if_freq == TDA10046_FREQ_045) || + (state->config->if_freq == TDA10046_FREQ_052)) + tda10046_clk53m = 0; + else + tda10046_clk53m = 1; tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0); - tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x0a); // PLL M = 10 + if(tda10046_clk53m) { + printk(KERN_INFO "tda1004x: setting up plls for 53MHz sampling clock\n"); + tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x08); // PLL M = 8 + } else { + printk(KERN_INFO "tda1004x: setting up plls for 48MHz sampling clock\n"); + tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3 + } if (state->config->xtal_freq == TDA10046_XTAL_4M ) { dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__); tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 @@ -428,26 +467,32 @@ static void tda10046_init_plls(struct dvb_frontend* fe) dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__); tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3 } - tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99); + if(tda10046_clk53m) + tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x67); + else + tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x72); + /* Note clock frequency is handled implicitly */ switch (state->config->if_freq) { - case TDA10046_FREQ_3617: - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4); - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c); - break; - case TDA10046_FREQ_3613: - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4); - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x13); - break; case TDA10046_FREQ_045: - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b); - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00); break; case TDA10046_FREQ_052: - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c); - tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x06); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xc7); + break; + case TDA10046_FREQ_3617: + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x59); + break; + case TDA10046_FREQ_3613: + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f); break; } tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz + /* let the PLLs settle */ + msleep(120); } static int tda10046_fwupload(struct dvb_frontend* fe) @@ -462,13 +507,13 @@ static int tda10046_fwupload(struct dvb_frontend* fe) /* let the clocks recover from sleep */ msleep(5); + /* The PLLs need to be reprogrammed after sleep */ + tda10046_init_plls(fe); + /* don't re-upload unless necessary */ if (tda1004x_check_upload_ok(state) == 0) return 0; - /* set parameters */ - tda10046_init_plls(fe); - if (state->config->request_firmware != NULL) { /* request the firmware, this will block until someone uploads it */ printk(KERN_INFO "tda1004x: waiting for firmware upload...\n"); @@ -484,7 +529,6 @@ static int tda10046_fwupload(struct dvb_frontend* fe) return ret; } else { /* boot from firmware eeprom */ - /* Hac Note: we might need to do some GPIO Magic here */ printk(KERN_INFO "tda1004x: booting from eeprom\n"); tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4); msleep(300); @@ -606,10 +650,9 @@ static int tda10046_init(struct dvb_frontend* fe) // tda setup tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer - tda1004x_write_byteI(state, TDA1004X_AUTO, 7); // select HP stream - tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer + tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream + tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer - tda10046_init_plls(fe); switch (state->config->agc_config) { case TDA10046_AGC_DEFAULT: tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup @@ -626,25 +669,22 @@ static int tda10046_init(struct dvb_frontend* fe) case TDA10046_AGC_TDA827X: tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold - tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x0E); // Gain Renormalize - tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities + tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize + tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities break; } + tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // } tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // } tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // } - tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1 + tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 0x12); // IF gain 2, TUN gain 1 tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); - tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup - tda1004x_write_byteI(state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config - tda1004x_write_byteI(state, TDA10046H_GPIO_SELECT, 8); // GPIO select - state->initialised = 1; return 0; } @@ -686,9 +726,9 @@ static int tda1004x_set_fe(struct dvb_frontend* fe, // Set standard params.. or put them to auto if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) || - (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) || - (fe_params->u.ofdm.constellation == QAM_AUTO) || - (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) { + (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) || + (fe_params->u.ofdm.constellation == QAM_AUTO) || + (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) { tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits @@ -851,6 +891,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe, static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params) { struct tda1004x_state* state = fe->demodulator_priv; + dprintk("%s\n", __FUNCTION__); // inversion status @@ -875,16 +916,18 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete break; } break; - case TDA1004X_DEMOD_TDA10046: switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) { - case 0x60: + case 0x5c: + case 0x54: fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; break; - case 0x6e: + case 0x6a: + case 0x60: fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; break; - case 0x80: + case 0x7b: + case 0x70: fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; break; } diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig index f02842be0d60..84f8f9f52869 100644 --- a/drivers/media/dvb/pluto2/Kconfig +++ b/drivers/media/dvb/pluto2/Kconfig @@ -8,7 +8,7 @@ config DVB_PLUTO2 Support for PCI cards based on the Pluto2 FPGA like the Satelco Easywatch Mobile Terrestrial DVB-T Receiver. - Since these cards have no MPEG decoder onboard, they transmit + Since these cards have no MPEG decoder onboard, they transmit only compressed MPEG data over the PCI bus, so you need an external software decoder to watch TV on your computer. diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index fa5034a9ecf5..5b2aadb8385c 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -18,9 +18,10 @@ config DVB_AV7110 This driver only supports the fullfeatured cards with onboard MPEG2 decoder. - This driver needs an external firmware. Please use the script - "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to - download/extract it, and then copy it to /usr/lib/hotplug/firmware. + This driver needs an external firmware. Please use the script + "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to + download/extract it, and then copy it to /usr/lib/hotplug/firmware + or /lib/firmware (depending on configuration of firmware hotplug). Say Y if you own such a card and want to use it. diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile index 825ab1c38a4f..a690730ac39d 100644 --- a/drivers/media/dvb/ttpci/Makefile +++ b/drivers/media/dvb/ttpci/Makefile @@ -16,7 +16,7 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ hostprogs-y := fdump ifdef CONFIG_DVB_AV7110_FIRMWARE -$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h +$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h $(obj)/av7110_firm.h: $(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@ diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 7dae91e5863c..8ce4146f55f1 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -133,7 +133,13 @@ static void init_av7110_av(struct av7110 *av7110) /* remaining inits according to card and frontend type */ av7110->analog_tuner_flags = 0; av7110->current_input = 0; - if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) { + if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) { + printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n", + av7110->dvb_adapter.num); + av7110->adac_type = DVB_ADAC_MSP34x5; + av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on + } + else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) { printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n", av7110->dvb_adapter.num); av7110->adac_type = DVB_ADAC_CRYSTAL; @@ -156,10 +162,10 @@ static void init_av7110_av(struct av7110 *av7110) else { av7110->adac_type = adac; printk("dvb-ttpci: adac type set to %d @ card %d\n", - av7110->dvb_adapter.num, av7110->adac_type); + av7110->adac_type, av7110->dvb_adapter.num); } - if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) { + if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) { // switch DVB SCART on ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); if (ret < 0) @@ -190,17 +196,15 @@ static void recover_arm(struct av7110 *av7110) av7110_bootarm(av7110); msleep(100); - restart_feeds(av7110); - av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config); -} -static void arm_error(struct av7110 *av7110) -{ - dprintk(4, "%p\n",av7110); + init_av7110_av(av7110); + + /* card-specific recovery */ + if (av7110->recover) + av7110->recover(av7110); - av7110->arm_errors++; - av7110->arm_ready = 0; - recover_arm(av7110); + restart_feeds(av7110); + av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config); } static void av7110_arm_sync(struct av7110 *av7110) @@ -240,26 +244,22 @@ static int arm_thread(void *data) if (down_interruptible(&av7110->dcomlock)) break; - newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2); up(&av7110->dcomlock); - if (newloops == av7110->arm_loops) { + if (newloops == av7110->arm_loops || av7110->arm_errors > 3) { printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n", av7110->dvb_adapter.num); - arm_error(av7110); - av7710_set_video_mode(av7110, vidmode); - - init_av7110_av(av7110); + recover_arm(av7110); if (down_interruptible(&av7110->dcomlock)) break; - newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1; up(&av7110->dcomlock); } av7110->arm_loops = newloops; + av7110->arm_errors = 0; } av7110->arm_thread = NULL; @@ -510,10 +510,6 @@ static void gpioirq(unsigned long data) iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); av7110->video_size.h = h_ar & 0xfff; - dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n", - av7110->video_size.w, - av7110->video_size.h, - av7110->video_size.aspect_ratio); event.type = VIDEO_EVENT_SIZE_CHANGED; event.u.size.w = av7110->video_size.w; @@ -535,6 +531,11 @@ static void gpioirq(unsigned long data) event.u.size.aspect_ratio = VIDEO_FORMAT_4_3; av7110->videostate.video_format = VIDEO_FORMAT_4_3; } + + dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n", + av7110->video_size.w, av7110->video_size.h, + av7110->video_size.aspect_ratio); + dvb_video_add_event(av7110, &event); break; } @@ -714,6 +715,8 @@ static struct dvb_device dvbdev_osd = { static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, u16 subpid, u16 pcrpid) { + u16 aflags = 0; + dprintk(4, "%p\n", av7110); if (vpid == 0x1fff || apid == 0x1fff || @@ -725,8 +728,11 @@ static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, av7110->pids[DMX_PES_PCR] = 0; } - return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 5, - pcrpid, vpid, apid, ttpid, subpid); + if (av7110->audiostate.bypass_mode) + aflags |= 0x8000; + + return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6, + pcrpid, vpid, apid, ttpid, subpid, aflags); } int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, @@ -1043,7 +1049,7 @@ static void restart_feeds(struct av7110 *av7110) struct dvb_demux *dvbdmx = &av7110->demux; struct dvb_demux_feed *feed; int mode; - int i; + int i, j; dprintk(4, "%p\n", av7110); @@ -1051,10 +1057,21 @@ static void restart_feeds(struct av7110 *av7110) av7110->playing = 0; av7110->rec_mode = 0; - for (i = 0; i < dvbdmx->filternum; i++) { + for (i = 0; i < dvbdmx->feednum; i++) { feed = &dvbdmx->feed[i]; - if (feed->state == DMX_STATE_GO) + if (feed->state == DMX_STATE_GO) { + if (feed->type == DMX_TYPE_SEC) { + for (j = 0; j < dvbdmx->filternum; j++) { + if (dvbdmx->filter[j].type != DMX_TYPE_SEC) + continue; + if (dvbdmx->filter[j].filter.parent != &feed->feed.sec) + continue; + if (dvbdmx->filter[j].state == DMX_STATE_GO) + dvbdmx->filter[j].state = DMX_STATE_READY; + } + } av7110_start_feed(feed); + } } if (mode) @@ -1483,9 +1500,9 @@ static int get_firmware(struct av7110* av7110) if (ret == -ENOENT) { printk(KERN_ERR "dvb-ttpci: could not load firmware," " file not found: dvb-ttpci-01.fw\n"); - printk(KERN_ERR "dvb-ttpci: usually this should be in" - " /usr/lib/hotplug/firmware\n"); - printk(KERN_ERR "dvb-ttpci: and can be downloaded here" + printk(KERN_ERR "dvb-ttpci: usually this should be in " + "/usr/lib/hotplug/firmware or /lib/firmware\n"); + printk(KERN_ERR "dvb-ttpci: and can be downloaded from" " http://www.linuxtv.org/download/dvb/firmware/\n"); } else printk(KERN_ERR "dvb-ttpci: cannot request firmware" @@ -2110,8 +2127,10 @@ static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_p struct av7110* av7110 = fe->dvb->priv; int ret = av7110_fe_lock_fix(av7110, 0); - if (!ret) + if (!ret) { + av7110->saved_fe_params = *params; ret = av7110->fe_set_frontend(fe, params); + } return ret; } @@ -2153,8 +2172,10 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe, struct av7110* av7110 = fe->dvb->priv; int ret = av7110_fe_lock_fix(av7110, 0); - if (!ret) + if (!ret) { + av7110->saved_master_cmd = *cmd; ret = av7110->fe_diseqc_send_master_cmd(fe, cmd); + } return ret; } @@ -2163,8 +2184,10 @@ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_ struct av7110* av7110 = fe->dvb->priv; int ret = av7110_fe_lock_fix(av7110, 0); - if (!ret) + if (!ret) { + av7110->saved_minicmd = minicmd; ret = av7110->fe_diseqc_send_burst(fe, minicmd); + } return ret; } @@ -2173,8 +2196,10 @@ static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) struct av7110* av7110 = fe->dvb->priv; int ret = av7110_fe_lock_fix(av7110, 0); - if (!ret) + if (!ret) { + av7110->saved_tone = tone; ret = av7110->fe_set_tone(fe, tone); + } return ret; } @@ -2183,12 +2208,14 @@ static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t volta struct av7110* av7110 = fe->dvb->priv; int ret = av7110_fe_lock_fix(av7110, 0); - if (!ret) + if (!ret) { + av7110->saved_voltage = voltage; ret = av7110->fe_set_voltage(fe, voltage); + } return ret; } -static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd) +static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd) { struct av7110* av7110 = fe->dvb->priv; @@ -2198,6 +2225,23 @@ static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, un return ret; } +static void dvb_s_recover(struct av7110* av7110) +{ + av7110_fe_init(av7110->fe); + + av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage); + if (av7110->saved_master_cmd.msg_len) { + msleep(20); + av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd); + } + msleep(20); + av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd); + msleep(20); + av7110_fe_set_tone(av7110->fe, av7110->saved_tone); + + av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params); +} + static u8 read_pwm(struct av7110* av7110) { u8 b = 0xff; @@ -2235,6 +2279,7 @@ static int frontend_init(struct av7110 *av7110) av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; av7110->fe->ops->set_tone = av7110_set_tone; + av7110->recover = dvb_s_recover; break; } @@ -2244,15 +2289,17 @@ static int frontend_init(struct av7110 *av7110) av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; av7110->fe->ops->set_tone = av7110_set_tone; + av7110->recover = dvb_s_recover; break; } // Try the grundig 29504-451 - av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); + av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; av7110->fe->ops->set_tone = av7110_set_tone; + av7110->recover = dvb_s_recover; break; } @@ -2274,12 +2321,12 @@ static int frontend_init(struct av7110 *av7110) case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X // ALPS TDLB7 - av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap); + av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap); break; case 0x0002: // Hauppauge/TT DVB-C premium rev2.X - av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); + av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); break; case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */ @@ -2289,6 +2336,7 @@ static int frontend_init(struct av7110 *av7110) av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; av7110->fe->ops->set_tone = av7110_set_tone; + av7110->recover = dvb_s_recover; } break; @@ -2314,8 +2362,11 @@ static int frontend_init(struct av7110 *av7110) case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */ /* ALPS BSBE1 */ av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap); - if (av7110->fe) + if (av7110->fe) { av7110->fe->ops->set_voltage = lnbp21_set_voltage; + av7110->fe->ops->dishnetwork_send_legacy_command = NULL; + av7110->recover = dvb_s_recover; + } break; } } diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index cce00ef293e9..6ea30df2e823 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -98,7 +98,8 @@ struct av7110 { int adac_type; /* audio DAC type */ #define DVB_ADAC_TI 0 #define DVB_ADAC_CRYSTAL 1 -#define DVB_ADAC_MSP 2 +#define DVB_ADAC_MSP34x0 2 +#define DVB_ADAC_MSP34x5 3 #define DVB_ADAC_NONE -1 @@ -228,6 +229,9 @@ struct av7110 { struct dvb_video_events video_events; video_size_t video_size; + u16 wssMode; + u16 wssData; + u32 ir_config; u32 ir_command; void (*ir_handler)(struct av7110 *av7110, u32 ircom); @@ -245,6 +249,15 @@ struct av7110 { struct dvb_frontend* fe; fe_status_t fe_status; + + /* crash recovery */ + void (*recover)(struct av7110* av7110); + struct dvb_frontend_parameters saved_fe_params; + fe_sec_voltage_t saved_voltage; + fe_sec_tone_mode_t saved_tone; + struct dvb_diseqc_master_cmd saved_master_cmd; + fe_sec_mini_cmd_t saved_minicmd; + int (*fe_init)(struct dvb_frontend* fe); int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status); int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe); @@ -252,7 +265,7 @@ struct av7110 { int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd); int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); - int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd); + int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd); int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index 0696a5a4f855..400facec7407 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c @@ -309,7 +309,7 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright) i2c_writereg(av7110, 0x20, 0x04, volright); return 0; - case DVB_ADAC_MSP: + case DVB_ADAC_MSP34x0: vol = (volleft > volright) ? volleft : volright; val = (vol * 0x73 / 255) << 8; if (vol > 0) @@ -1256,7 +1256,9 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, break; case AUDIO_SET_BYPASS_MODE: - ret = -EINVAL; + if (FW_VERSION(av7110->arm_app) < 0x2621) + ret = -EINVAL; + av7110->audiostate.bypass_mode = (int)arg; break; case AUDIO_CHANNEL_SELECT: @@ -1295,7 +1297,11 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, break; case AUDIO_GET_CAPABILITIES: - *(int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2; + if (FW_VERSION(av7110->arm_app) < 0x2621) + *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2; + else + *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 | + AUDIO_CAP_MP1 | AUDIO_CAP_MP2; break; case AUDIO_CLEAR_BUFFER: diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 87106e8bf35b..cb377452b57d 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -230,6 +230,8 @@ int av7110_bootarm(struct av7110 *av7110) dprintk(4, "%p\n", av7110); + av7110->arm_ready = 0; + saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ @@ -361,6 +363,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) break; if (err) { printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__); + av7110->arm_errors++; return -ETIMEDOUT; } msleep(1); @@ -1206,9 +1209,9 @@ int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap) switch (cap->cmd) { case OSD_CAP_MEMSIZE: if (FW_4M_SDRAM(av7110->arm_app)) - cap->val = 1000000; + cap->val = 1000000; else - cap->val = 92000; + cap->val = 92000; return 0; default: return -EINVAL; diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h index 2a5e87ba1052..84b83299b8be 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.h +++ b/drivers/media/dvb/ttpci/av7110_hw.h @@ -167,7 +167,8 @@ enum av7110_encoder_command { LoadVidCode, SetMonitorType, SetPanScanType, - SetFreezeMode + SetFreezeMode, + SetWSSConfig }; enum av7110_rec_play_state { diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index f5e59fc924af..9138132ad25f 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -17,6 +17,8 @@ static int av_cnt; static struct av7110 *av_list[4]; static struct input_dev *input_dev; +static u8 delay_timer_finished; + static u16 key_map [256] = { KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO, @@ -112,13 +114,16 @@ static void av7110_emit_key(unsigned long parm) if (timer_pending(&keyup_timer)) { del_timer(&keyup_timer); if (keyup_timer.data != keycode || new_toggle != old_toggle) { + delay_timer_finished = 0; input_event(input_dev, EV_KEY, keyup_timer.data, !!0); input_event(input_dev, EV_KEY, keycode, !0); } else - input_event(input_dev, EV_KEY, keycode, 2); - - } else + if (delay_timer_finished) + input_event(input_dev, EV_KEY, keycode, 2); + } else { + delay_timer_finished = 0; input_event(input_dev, EV_KEY, keycode, !0); + } keyup_timer.expires = jiffies + UP_TIMEOUT; keyup_timer.data = keycode; @@ -145,7 +150,8 @@ static void input_register_keys(void) static void input_repeat_key(unsigned long data) { - /* dummy routine to disable autorepeat in the input driver */ + /* called by the input driver after rep[REP_DELAY] ms */ + delay_timer_finished = 1; } diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index b5aea4129fa7..94cf38c7e8a8 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -490,6 +490,58 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index); break; } + case VIDIOC_G_SLICED_VBI_CAP: + { + struct v4l2_sliced_vbi_cap *cap = arg; + dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n"); + memset(cap, 0, sizeof *cap); + if (FW_VERSION(av7110->arm_app) >= 0x2623) { + cap->service_set = V4L2_SLICED_WSS_625; + cap->service_lines[0][23] = V4L2_SLICED_WSS_625; + } + break; + } + case VIDIOC_G_FMT: + { + struct v4l2_format *f = arg; + dprintk(2, "VIDIOC_G_FMT:\n"); + if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT || + FW_VERSION(av7110->arm_app) < 0x2623) + return -EAGAIN; /* handled by core driver */ + memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced); + if (av7110->wssMode) { + f->fmt.sliced.service_set = V4L2_SLICED_WSS_625; + f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; + f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data); + } + break; + } + case VIDIOC_S_FMT: + { + struct v4l2_format *f = arg; + dprintk(2, "VIDIOC_S_FMT\n"); + if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT || + FW_VERSION(av7110->arm_app) < 0x2623) + return -EAGAIN; /* handled by core driver */ + if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 && + f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) { + memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced); + /* WSS controlled by firmware */ + av7110->wssMode = 0; + av7110->wssData = 0; + return av7110_fw_cmd(av7110, COMTYPE_ENCODER, + SetWSSConfig, 1, 0); + } else { + memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced); + f->fmt.sliced.service_set = V4L2_SLICED_WSS_625; + f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; + f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data); + /* WSS controlled by userspace */ + av7110->wssMode = 1; + av7110->wssData = 0; + } + break; + } default: printk("no such ioctl\n"); return -ENOIOCTLCMD; @@ -497,6 +549,46 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) return 0; } +static int av7110_vbi_reset(struct inode *inode, struct file *file) +{ + struct saa7146_fh *fh = file->private_data; + struct saa7146_dev *dev = fh->dev; + struct av7110 *av7110 = (struct av7110*) dev->ext_priv; + + dprintk(2, "%s\n", __FUNCTION__); + av7110->wssMode = 0; + av7110->wssData = 0; + if (FW_VERSION(av7110->arm_app) < 0x2623) + return 0; + else + return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0); +} + +static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos) +{ + struct saa7146_fh *fh = file->private_data; + struct saa7146_dev *dev = fh->dev; + struct av7110 *av7110 = (struct av7110*) dev->ext_priv; + struct v4l2_sliced_vbi_data d; + int rc; + + dprintk(2, "%s\n", __FUNCTION__); + if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d) + return -EINVAL; + if (copy_from_user(&d, data, count)) + return -EFAULT; + if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23) + return -EINVAL; + if (d.id) { + av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0]; + rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, + 2, 1, av7110->wssData); + } else { + av7110->wssData = 0; + rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0); + } + return (rc < 0) ? rc : count; +} /**************************************************************************** * INITIALIZATION @@ -512,6 +604,9 @@ static struct saa7146_extension_ioctls ioctls[] = { { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE }, { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, + { VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE }, + { VIDIOC_G_FMT, SAA7146_BEFORE }, + { VIDIOC_S_FMT, SAA7146_BEFORE }, { 0, 0 } }; @@ -587,7 +682,7 @@ int av7110_init_analog_module(struct av7110 *av7110) printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n", av7110->dvb_adapter.num); - av7110->adac_type = DVB_ADAC_MSP; + av7110->adac_type = DVB_ADAC_MSP34x0; msleep(100); // the probing above resets the msp... msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1); msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2); @@ -692,12 +787,11 @@ int av7110_init_v4l(struct av7110 *av7110) saa7146_vv_release(dev); return -ENODEV; } - if (av7110->analog_tuner_flags) { - if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) { - ERR(("cannot register vbi v4l2 device. skipping.\n")); - } else { + if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) { + ERR(("cannot register vbi v4l2 device. skipping.\n")); + } else { + if (av7110->analog_tuner_flags) av7110->analog_tuner_flags |= ANALOG_TUNER_VBI; - } } return 0; } @@ -778,7 +872,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) static struct saa7146_ext_vv av7110_vv_data_st = { .inputs = 1, .audios = 1, - .capabilities = 0, + .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT, .flags = 0, .stds = &standard[0], @@ -787,12 +881,16 @@ static struct saa7146_ext_vv av7110_vv_data_st = { .ioctls = &ioctls[0], .ioctl = av7110_ioctl, + + .vbi_fops.open = av7110_vbi_reset, + .vbi_fops.release = av7110_vbi_reset, + .vbi_fops.write = av7110_vbi_write, }; static struct saa7146_ext_vv av7110_vv_data_c = { .inputs = 1, .audios = 1, - .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, + .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT, .flags = SAA7146_USE_PORT_B_FOR_VBI, .stds = &standard[0], @@ -801,5 +899,9 @@ static struct saa7146_ext_vv av7110_vv_data_c = { .ioctls = &ioctls[0], .ioctl = av7110_ioctl, + + .vbi_fops.open = av7110_vbi_reset, + .vbi_fops.release = av7110_vbi_reset, + .vbi_fops.write = av7110_vbi_write, }; diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 9f51bae7194c..f9d00452e639 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -127,7 +127,7 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI); udelay(1); - result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0); + result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1); if (result == -ETIMEDOUT) budget_av->slot_status = 0; @@ -145,7 +145,7 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI); udelay(1); - result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0); + result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1); if (result == -ETIMEDOUT) budget_av->slot_status = 0; @@ -192,7 +192,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) { struct budget_av *budget_av = (struct budget_av *) ca->data; struct saa7146_dev *saa = budget_av->budget.dev; - int timeout = 500; // 5 seconds (4.4.6 Ready) + int timeout = 50; // 5 seconds (4.4.6 Ready) if (slot != 0) return -EINVAL; @@ -256,19 +256,37 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open { struct budget_av *budget_av = (struct budget_av *) ca->data; struct saa7146_dev *saa = budget_av->budget.dev; + int cam_present = 0; if (slot != 0) return -EINVAL; - if (!budget_av->slot_status) { + if (!budget_av->slot_status) + { + // first of all test the card detect line saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); udelay(1); if (saa7146_read(saa, PSR) & MASK_06) { + cam_present = 1; + } + saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); + + // that is unreliable however, so try and read from IO memory + if (!cam_present) + { + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); + if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT) + { + cam_present = 1; + } + } + + // did we find something? + if (cam_present) { printk(KERN_INFO "budget-av: cam inserted\n"); budget_av->slot_status = 1; } - saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); } else if (!open) { saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT) @@ -484,6 +502,140 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe, return 0; } +#define MIN2(a,b) ((a) < (b) ? (a) : (b)) +#define MIN3(a,b,c) MIN2(MIN2(a,b),c) + +static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct dvb_frontend_parameters *params) +{ + u8 reg0 [2] = { 0x00, 0x00 }; + u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 }; + u8 reg2 [3] = { 0x02, 0x00, 0x00 }; + int _fband; + int first_ZF; + int R, A, N, P, M; + struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 }; + int freq = params->frequency; + + first_ZF = (freq) / 1000; + + if (abs(MIN2(abs(first_ZF-1190),abs(first_ZF-1790))) < + abs(MIN3(abs(first_ZF-1202),abs(first_ZF-1542),abs(first_ZF-1890)))) + _fband = 2; + else + _fband = 3; + + if (_fband == 2) { + if (((first_ZF >= 950) && (first_ZF < 1350)) || + ((first_ZF >= 1430) && (first_ZF < 1950))) + reg0[1] = 0x07; + else if (((first_ZF >= 1350) && (first_ZF < 1430)) || + ((first_ZF >= 1950) && (first_ZF < 2150))) + reg0[1] = 0x0B; + } + + if(_fband == 3) { + if (((first_ZF >= 950) && (first_ZF < 1350)) || + ((first_ZF >= 1455) && (first_ZF < 1950))) + reg0[1] = 0x07; + else if (((first_ZF >= 1350) && (first_ZF < 1420)) || + ((first_ZF >= 1950) && (first_ZF < 2150))) + reg0[1] = 0x0B; + else if ((first_ZF >= 1420) && (first_ZF < 1455)) + reg0[1] = 0x0F; + } + + if (first_ZF > 1525) + reg1[1] |= 0x80; + else + reg1[1] &= 0x7F; + + if (_fband == 2) { + if (first_ZF > 1430) { /* 1430MHZ */ + reg1[1] &= 0xCF; /* N2 */ + reg2[1] &= 0xCF; /* R2 */ + reg2[1] |= 0x10; + } else { + reg1[1] &= 0xCF; /* N2 */ + reg1[1] |= 0x20; + reg2[1] &= 0xCF; /* R2 */ + reg2[1] |= 0x10; + } + } + + if (_fband == 3) { + if ((first_ZF >= 1455) && + (first_ZF < 1630)) { + reg1[1] &= 0xCF; /* N2 */ + reg1[1] |= 0x20; + reg2[1] &= 0xCF; /* R2 */ + } else { + if (first_ZF < 1455) { + reg1[1] &= 0xCF; /* N2 */ + reg1[1] |= 0x20; + reg2[1] &= 0xCF; /* R2 */ + reg2[1] |= 0x10; + } else { + if (first_ZF >= 1630) { + reg1[1] &= 0xCF; /* N2 */ + reg2[1] &= 0xCF; /* R2 */ + reg2[1] |= 0x10; + } + } + } + } + + /* set ports, enable P0 for symbol rates > 4Ms/s */ + if (params->u.qpsk.symbol_rate >= 4000000) + reg1[1] |= 0x0c; + else + reg1[1] |= 0x04; + + reg2[1] |= 0x0c; + + R = 64; + A = 64; + P = 64; //32 + + M = (freq * R) / 4; /* in Mhz */ + N = (M - A * 1000) / (P * 1000); + + reg1[1] |= (N >> 9) & 0x03; + reg1[2] = (N >> 1) & 0xff; + reg1[3] = (N << 7) & 0x80; + + reg2[1] |= (R >> 8) & 0x03; + reg2[2] = R & 0xFF; /* R */ + + reg1[3] |= A & 0x7f; /* A */ + + if (P == 64) + reg1[1] |= 0x40; /* Prescaler 64/65 */ + + reg0[1] |= 0x03; + + /* already enabled - do not reenable i2c repeater or TX fails */ + msg.buf = reg0; + msg.len = sizeof(reg0); + if (i2c_transfer(i2c, &msg, 1) != 1) + return -EIO; + + stv0299_enable_plli2c(fe); + msg.buf = reg1; + msg.len = sizeof(reg1); + if (i2c_transfer(i2c, &msg, 1) != 1) + return -EIO; + + stv0299_enable_plli2c(fe); + msg.buf = reg2; + msg.len = sizeof(reg2); + if (i2c_transfer(i2c, &msg, 1) != 1) + return -EIO; + + return 0; +} + static u8 typhoon_cinergy1200s_inittab[] = { 0x01, 0x15, 0x02, 0x30, @@ -553,6 +705,18 @@ static struct stv0299_config cinergy_1200s_config = { .pll_set = philips_su1278_ty_ci_pll_set, }; +static struct stv0299_config cinergy_1200s_1894_0010_config = { + .demod_address = 0x68, + .inittab = typhoon_cinergy1200s_inittab, + .mclk = 88000000UL, + .invert = 1, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, + .pll_set = philips_su1278sh2_tua6100_pll_set, +}; static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { @@ -749,6 +913,15 @@ static void frontend_init(struct budget_av *budget_av) switch (saa->pci->subsystem_device) { case SUBID_DVBS_KNC1: + if (saa->pci->subsystem_vendor == 0x1894) { + fe = stv0299_attach(&cinergy_1200s_1894_0010_config, + &budget_av->budget.i2c_adap); + } else { + fe = stv0299_attach(&typhoon_config, + &budget_av->budget.i2c_adap); + } + break; + case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBS_TYPHOON: fe = stv0299_attach(&typhoon_config, @@ -1003,6 +1176,7 @@ MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T); static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56), MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010), + MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010), MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011), MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 017fcbccb8cc..633e68c341c8 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -404,9 +404,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, tasklet_init(&budget->vpe_tasklet, vpeirq, (unsigned long) budget); /* frontend power on */ - if (bi->type == BUDGET_FS_ACTIVY) - saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); - else + if (bi->type != BUDGET_FS_ACTIVY) saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); if (budget_register(budget) == 0) { diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index fafe6407b3d0..238c77b52f89 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -112,6 +112,7 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long * Routines for the Fujitsu Siemens Activy budget card * 22 kHz tone and DiSEqC are handled by the frontend. * Voltage must be set here. + * GPIO 1: LNBP EN, GPIO 2: LNBP VSEL */ static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage) { @@ -121,11 +122,16 @@ static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage) switch (voltage) { case SEC_VOLTAGE_13: + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO); break; case SEC_VOLTAGE_18: + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); break; + case SEC_VOLTAGE_OFF: + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); + break; default: return -EINVAL; } @@ -206,7 +212,7 @@ static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) return 0; } -static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg) +static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, long arg) { struct budget* budget = (struct budget*) fe->dvb->priv; u8 buf; @@ -580,6 +586,7 @@ static void frontend_init(struct budget *budget) if (budget->dvb_frontend) { budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage; budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; + budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; if (lnbp21_init(budget)) { printk("%s: No LNBP21 found!\n", __FUNCTION__); goto error_out; @@ -624,7 +631,7 @@ static void frontend_init(struct budget *budget) budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage; - break; + budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; } break; @@ -632,7 +639,7 @@ static void frontend_init(struct budget *budget) budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage; - break; + budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; } break; diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c index 18aa22b5478d..1f31e91195b0 100644 --- a/drivers/media/dvb/ttpci/ttpci-eeprom.c +++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c @@ -13,7 +13,7 @@ Holger Waechtler Convergence Copyright (C) 2002-2003 Ralph Metzler <rjkm@metzlerbros.de> - Metzler Brothers Systementwicklung GbR + Metzler Brothers Systementwicklung GbR 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 diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig index c6c1d41a2efb..914587d52b57 100644 --- a/drivers/media/dvb/ttusb-budget/Kconfig +++ b/drivers/media/dvb/ttusb-budget/Kconfig @@ -10,7 +10,7 @@ config DVB_TTUSB_BUDGET Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'Nova-USB'. - These devices don't have a MPEG decoder built in, so you need + These devices don't have a MPEG decoder built in, so you need an external software decoder to watch TV. Say Y if you own such a device and want to use it. diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig index c334526af66f..83611012ef34 100644 --- a/drivers/media/dvb/ttusb-dec/Kconfig +++ b/drivers/media/dvb/ttusb-dec/Kconfig @@ -8,14 +8,15 @@ config DVB_TTUSB_DEC produced by Hauppauge, shipped under the brand name 'DEC2000-t' and 'DEC3000-s'. - Even if these devices have a MPEG decoder built in, they transmit + Even if these devices have a MPEG decoder built in, they transmit only compressed MPEG data over the USB bus, so you need an external software decoder to watch TV on your computer. - This driver needs external firmware. Please use the commands - "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t", - "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t", - "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s", - download/extract them, and then copy them to /usr/lib/hotplug/firmware. + This driver needs external firmware. Please use the commands + "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t", + "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t", + "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s", + download/extract them, and then copy them to /usr/lib/hotplug/firmware + or /lib/firmware (depending on configuration of firmware hotplug). Say Y if you own such a device and want to use it. diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 8abc21890129..d8966d1d25ee 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -369,7 +369,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode, static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data) { - struct ttusb_dec *dec = (struct ttusb_dec *)priv; + struct ttusb_dec *dec = priv; dec->audio_filter->feed->cb.ts(data, 188, NULL, 0, &dec->audio_filter->feed->feed.ts, @@ -380,7 +380,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data) static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data) { - struct ttusb_dec *dec = (struct ttusb_dec *)priv; + struct ttusb_dec *dec = priv; dec->video_filter->feed->cb.ts(data, 188, NULL, 0, &dec->video_filter->feed->feed.ts, @@ -965,8 +965,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed) case DMX_TS_PES_TELETEXT: dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid; - dprintk(" pes_type: DMX_TS_PES_TELETEXT\n"); - break; + dprintk(" pes_type: DMX_TS_PES_TELETEXT(not supported)\n"); + return -ENOSYS; case DMX_TS_PES_PCR: dprintk(" pes_type: DMX_TS_PES_PCR\n"); @@ -975,8 +975,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed) break; case DMX_TS_PES_OTHER: - dprintk(" pes_type: DMX_TS_PES_OTHER\n"); - break; + dprintk(" pes_type: DMX_TS_PES_OTHER(not supported)\n"); + return -ENOSYS; default: dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type); @@ -1182,7 +1182,7 @@ static void ttusb_dec_init_tasklet(struct ttusb_dec *dec) (unsigned long)dec); } -static int ttusb_init_rc(struct ttusb_dec *dec) +static int ttusb_init_rc( struct ttusb_dec *dec) { struct input_dev *input_dev; u8 b[] = { 0x00, 0x01 }; @@ -1203,13 +1203,12 @@ static int ttusb_init_rc(struct ttusb_dec *dec) input_dev->keycode = rc_keys; for (i = 0; i < ARRAY_SIZE(rc_keys); i++) - set_bit(rc_keys[i], input_dev->keybit); + set_bit(rc_keys[i], input_dev->keybit); input_register_device(input_dev); if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) printk("%s: usb_submit_urb failed\n",__FUNCTION__); - /* enable irq pipe */ ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL); @@ -1395,6 +1394,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec) /* We can't trust the USB IDs that some firmwares give the box */ switch (model) { + case 0x00070001: case 0x00070008: case 0x0007000c: ttusb_dec_set_model(dec, TTUSB_DEC3000S); @@ -1588,7 +1588,7 @@ static int fe_send_command(struct dvb_frontend* fe, const u8 command, int param_length, const u8 params[], int *result_length, u8 cmd_result[]) { - struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv; + struct ttusb_dec* dec = fe->dvb->priv; return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result); } diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c index 725af3af5b27..a5a46175fa09 100644 --- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c +++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c @@ -42,8 +42,39 @@ struct ttusbdecfe_state { static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status) { - *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | - FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; + struct ttusbdecfe_state* state = fe->demodulator_priv; + u8 b[] = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + u8 result[4]; + int len, ret; + + *status=0; + + ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result); + if(ret) + return ret; + + if(len != 4) { + printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__); + return -EIO; + } + + switch(result[3]) { + case 1: /* not tuned yet */ + case 2: /* no signal/no lock*/ + break; + case 3: /* signal found and locked*/ + *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | + FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; + break; + case 4: + *status = FE_TIMEDOUT; + break; + default: + pr_info("%s: returned unknown value: %d\n", + __FUNCTION__, result[3]); + return -EIO; + } return 0; } @@ -64,6 +95,16 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron return 0; } +static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe, + struct dvb_frontend_tune_settings* fesettings) +{ + fesettings->min_delay_ms = 1500; + /* Drift compensation makes no sense for DVB-T */ + fesettings->step_size = 0; + fesettings->max_drift = 0; + return 0; +} + static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv; @@ -212,6 +253,8 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = { .set_frontend = ttusbdecfe_dvbt_set_frontend, + .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings, + .read_status = ttusbdecfe_read_status, }; @@ -223,11 +266,11 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = { .frequency_min = 950000, .frequency_max = 2150000, .frequency_stepsize = 125, + .symbol_rate_min = 1000000, /* guessed */ + .symbol_rate_max = 45000000, /* guessed */ .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_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, + FE_CAN_QPSK }, .release = ttusbdecfe_release, diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c index c2ebe8754a95..dc292da2605f 100644 --- a/drivers/media/radio/miropcm20-radio.c +++ b/drivers/media/radio/miropcm20-radio.c @@ -220,6 +220,7 @@ static struct file_operations pcm20_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = pcm20_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 877c770558e9..914deab4e044 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -299,6 +299,7 @@ static struct file_operations rtrack_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = rt_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 5319a9c9a979..523be820f9c6 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -256,6 +256,7 @@ static struct file_operations aztech_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = az_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 9b0406318f2d..f1b5ac81e9d2 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -490,6 +490,7 @@ static struct file_operations cadet_fops = { .release = cadet_release, .read = cadet_read, .ioctl = cadet_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 78b2888bf581..69ac8aa73eba 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -301,6 +301,7 @@ static struct file_operations gemtek_pci_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = gemtek_pci_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 6418f03b9ce4..47173be97b9f 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -233,6 +233,7 @@ static struct file_operations gemtek_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = gemtek_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index e5e2021a7312..c30effdf711f 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -72,6 +72,7 @@ static struct file_operations maestro_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = radio_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 7b33d8f2f8f8..c975ddd86cd5 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -80,6 +80,7 @@ static struct file_operations maxiradio_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = radio_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static struct video_device maxiradio_radio = diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index b2256d675b44..28a47c9e7a81 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -199,6 +199,7 @@ static struct file_operations rtrack2_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = rt_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 6f03ce4dd7b0..0229f792a059 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -225,6 +225,7 @@ static struct file_operations fmi_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = fmi_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 71971e9bb342..099ffb3b9c71 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -48,7 +48,7 @@ static int io = 0x384; static int radio_nr = -1; /* hw precision is 12.5 kHz - * It is only usefull to give freq in intervall of 200 (=0.0125Mhz), + * It is only useful to give freq in intervall of 200 (=0.0125Mhz), * other bits will be truncated */ #define RSF16_ENCODE(x) ((x)/200+856) @@ -356,6 +356,7 @@ static struct file_operations fmr2_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = fmr2_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index b03573c6840e..fcfde2e4f195 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -276,6 +276,7 @@ static struct file_operations terratec_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = tt_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index b300bedf7c74..5a099a50d4d0 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c @@ -255,6 +255,7 @@ static struct file_operations trust_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = tr_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index f304f3c14763..8ac9a8ef9094 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -261,6 +261,7 @@ static struct file_operations typhoon_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = typhoon_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 4c6d6fb49034..d590e80c922e 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -313,6 +313,7 @@ static struct file_operations zoltrix_fops = .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = zol_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index fc87efc5049c..2fe260fff85d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -7,6 +7,15 @@ menu "Video For Linux" comment "Video Adapters" +config VIDEO_ADV_DEBUG + bool "Enable advanced debug functionality" + depends on VIDEO_DEV + default n + ---help--- + Say Y here to enable advanced debugging functionality on some + V4L devices. + In doubt, say N. + config VIDEO_BT848 tristate "BT848 Video For Linux" depends on VIDEO_DEV && PCI && I2C @@ -342,6 +351,6 @@ config VIDEO_DECODER depends on VIDEO_DEV && I2C && EXPERIMENTAL ---help--- Say Y here to compile drivers for SAA7115, SAA7127 and CX25840 - video decoders. + video decoders. endmenu diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 82060f9909d8..dd24896906fe 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -3,15 +3,19 @@ # bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ - bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o + bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \ + bttv-input.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 tea5767.o -obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o + +msp3400-objs := msp3400-driver.o msp3400-kthreads.o + +obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \ - tda7432.o tda9875.o ir-kbd-i2c.o ir-kbd-gpio.o + tda7432.o tda9875.o ir-kbd-i2c.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_VIDEO_ZR36120) += zoran.o diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 881cdcb1875d..7d5a068353f2 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -749,6 +749,7 @@ static struct file_operations ar_fops = { .release = video_exclusive_release, .read = ar_read, .ioctl = ar_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 1c3ff5f38a6d..dda4aa6bef27 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c @@ -30,8 +30,9 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/slab.h> - #include <media/audiochip.h> +#include <media/v4l2-common.h> + #include "bttv.h" #include "bt832.h" @@ -42,9 +43,10 @@ static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; -/* ---------------------------------------------------------------------- */ +int debug = 0; /* debug output */ +module_param(debug, int, 0644); -#define dprintk if (debug) printk +/* ---------------------------------------------------------------------- */ static int bt832_detach(struct i2c_client *client); @@ -61,23 +63,26 @@ int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf) int i,rc; buf[0]=0x80; // start at register 0 with auto-increment if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) - printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc); + v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 1)\n",rc); for(i=0;i<65;i++) buf[i]=0; if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) - printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc); + v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 65)\n",rc); // Note: On READ the first byte is the current index // (e.g. 0x80, what we just wrote) - if(1) { + if(debug>1) { int i; - printk("BT832 hexdump:\n"); + v4l_dbg(2,i2c_client_s,"hexdump:"); for(i=1;i<65;i++) { if(i!=1) { - if(((i-1)%8)==0) printk(" "); - if(((i-1)%16)==0) printk("\n"); + if(((i-1)%8)==0) printk(" "); + if(((i-1)%16)==0) { + printk("\n"); + v4l_dbg(2,i2c_client_s,"hexdump:"); + } } printk(" %02x",buf[i]); } @@ -96,56 +101,56 @@ int bt832_init(struct i2c_client *i2c_client_s) bt832_hexdump(i2c_client_s,buf); if(buf[0x40] != 0x31) { - printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); + v4l_err(i2c_client_s,"This i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); kfree(buf); return 0; } - printk("Write 0 tp VPSTATUS\n"); + v4l_err(i2c_client_s,"Write 0 tp VPSTATUS\n"); buf[0]=BT832_VP_STATUS; // Reg.52 buf[1]= 0x00; if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); + v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc); bt832_hexdump(i2c_client_s,buf); // Leave low power mode: - printk("Bt832: leave low power mode.\n"); + v4l_err(i2c_client_s,"leave low power mode.\n"); buf[0]=BT832_CAM_SETUP0; //0x39 57 buf[1]=0x08; if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc); + v4l_err(i2c_client_s,"i2c i/o error LLPM: rc == %d (should be 2)\n",rc); bt832_hexdump(i2c_client_s,buf); - printk("Write 0 tp VPSTATUS\n"); + v4l_info(i2c_client_s,"Write 0 tp VPSTATUS\n"); buf[0]=BT832_VP_STATUS; // Reg.52 buf[1]= 0x00; if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); + v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc); bt832_hexdump(i2c_client_s,buf); // Enable Output - printk("Enable Output\n"); + v4l_info(i2c_client_s,"Enable Output\n"); buf[0]=BT832_VP_CONTROL1; // Reg.40 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); + v4l_err(i2c_client_s,"i2c i/o error EO: rc == %d (should be 2)\n",rc); bt832_hexdump(i2c_client_s,buf); // for testing (even works when no camera attached) - printk("bt832: *** Generate NTSC M Bars *****\n"); + v4l_info(i2c_client_s,"*** Generate NTSC M Bars *****\n"); buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42 buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc); + v4l_info(i2c_client_s,"i2c i/o error MBAR: rc == %d (should be 2)\n",rc); - printk("Bt832: Camera Present: %s\n", + v4l_info(i2c_client_s,"Camera Present: %s\n", (buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no"); bt832_hexdump(i2c_client_s,buf); @@ -159,13 +164,9 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) { struct bt832 *t; - printk("bt832_attach\n"); - client_template.adapter = adap; client_template.addr = addr; - printk("bt832: chip found @ 0x%x\n", addr<<1); - if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) return -ENOMEM; memset(t,0,sizeof(*t)); @@ -173,6 +174,9 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); + v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1); + + if(! bt832_init(&t->client)) { bt832_detach(&t->client); return -1; @@ -183,13 +187,8 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) 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_HW_B_BT848) - return i2c_probe(adap, &addr_data, bt832_attach); -#endif return 0; } @@ -197,7 +196,7 @@ static int bt832_detach(struct i2c_client *client) { struct bt832 *t = i2c_get_clientdata(client); - printk("bt832: detach.\n"); + v4l_info(&t->client,"dettach\n"); i2c_detach_client(client); kfree(t); return 0; @@ -208,7 +207,8 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct bt832 *t = i2c_get_clientdata(client); - printk("bt832: command %x\n",cmd); + if (debug>1) + v4l_i2c_print_ioctl(&t->client,cmd); switch (cmd) { case BT832_HEXDUMP: { @@ -219,7 +219,7 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) } break; case BT832_REATTACH: - printk("bt832: re-attach\n"); + v4l_info(&t->client,"re-attach\n"); i2c_del_driver(&driver); i2c_add_driver(&driver); break; @@ -231,9 +231,9 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) static struct i2c_driver driver = { .driver = { - .name = "i2c bt832 driver", + .name = "bt832", }, - .id = -1, /* FIXME */ + .id = 0, /* FIXME */ .attach_adapter = bt832_probe, .detach_client = bt832_detach, .command = bt832_command, diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 012be639aa18..1621ab133d23 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -38,6 +38,7 @@ #include <asm/io.h> #include "bttvp.h" +#include <media/v4l2-common.h> /* fwd decl */ static void boot_msp34xx(struct bttv *btv, int pin); @@ -292,6 +293,9 @@ static struct CARD { /* likely broken, vendor id doesn't match the other magic views ... * { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */ + /* Duplicate PCI ID, reconfigure for this board during the eeprom read. + * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB, "Hauppauge ImpactVCB" }, */ + /* DVB cards (using pci function .1 for mpeg data xfer) */ { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, @@ -2136,7 +2140,6 @@ struct tvcard bttv_tvcards[] = { .has_remote = 1, .gpiomask = 0x1b, .no_gpioirq = 1, - .any_irq = 1, }, [BTTV_BOARD_PV143] = { /* Jorge Boncompte - DTI2 <jorge@dti2.net> */ @@ -2817,6 +2820,22 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .has_radio = 1, }, + /* ---- card 0x8f ---------------------------------- */ + [BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = { + .name = "Hauppauge ImpactVCB (bt878)", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x0f, /* old: 7 */ + .muxsel = { 0, 1, 3, 2}, /* Composite 0-3 */ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -3037,26 +3056,33 @@ static void miro_pinnacle_gpio(struct bttv *btv) switch (id) { case 1: info = "PAL / mono"; + btv->tda9887_conf = TDA9887_INTERCARRIER; break; case 2: info = "PAL+SECAM / stereo"; btv->has_radio = 1; + btv->tda9887_conf = TDA9887_QSS; break; case 3: info = "NTSC / stereo"; btv->has_radio = 1; + btv->tda9887_conf = TDA9887_QSS; break; case 4: info = "PAL+SECAM / mono"; + btv->tda9887_conf = TDA9887_QSS; break; case 5: info = "NTSC / mono"; + btv->tda9887_conf = TDA9887_INTERCARRIER; break; case 6: info = "NTSC / stereo"; + btv->tda9887_conf = TDA9887_INTERCARRIER; break; case 7: info = "PAL / stereo"; + btv->tda9887_conf = TDA9887_INTERCARRIER; break; default: info = "oops: unknown card"; @@ -3067,8 +3093,7 @@ static void miro_pinnacle_gpio(struct bttv *btv) printk(KERN_INFO "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n", btv->c.nr, id, info, btv->has_radio ? "yes" : "no"); - btv->tuner_type = 33; - btv->pinnacle_id = id; + btv->tuner_type = TUNER_MT2032; } } @@ -3370,9 +3395,9 @@ void __devinit bttv_init_card2(struct bttv *btv) bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); } - if (btv->pinnacle_id != UNSET) { - bttv_call_i2c_clients(btv, AUDC_CONFIG_PINNACLE, - &btv->pinnacle_id); + if (btv->tda9887_conf) { + bttv_call_i2c_clients(btv, TDA9887_SET_CONFIG, + &btv->tda9887_conf); } btv->svhs = bttv_tvcards[btv->c.type].svhs; @@ -3387,8 +3412,6 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->has_remote=1; if (!bttv_tvcards[btv->c.type].no_gpioirq) btv->gpioirq=1; - if (bttv_tvcards[btv->c.type].any_irq) - btv->any_irq = 1; if (bttv_tvcards[btv->c.type].audio_hook) btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; @@ -3424,7 +3447,7 @@ void __devinit bttv_init_card2(struct bttv *btv) /* tuner modules */ tda9887 = 0; - if (btv->pinnacle_id != UNSET) + if (btv->tda9887_conf) tda9887 = 1; if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb && bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0) @@ -3471,6 +3494,21 @@ static void __devinit hauppauge_eeprom(struct bttv *btv) tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data); btv->tuner_type = tv.tuner_type; btv->has_radio = tv.has_radio; + + printk("bttv%d: Hauppauge eeprom indicates model#%d\n", + btv->c.nr, tv.model); + + /* + * Some of the 878 boards have duplicate PCI IDs. Switch the board + * type based on model #. + */ + if(tv.model == 64900) { + printk("bttv%d: Switching board type from %s to %s\n", + btv->c.nr, + bttv_tvcards[btv->c.type].name, + bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name); + btv->c.type = BTTV_BOARD_HAUPPAUGE_IMPACTVCB; + } } static int terratec_active_radio_upgrade(struct bttv *btv) diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 00bd8ea5eaeb..0e6970346788 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -34,13 +34,14 @@ #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/kdev_t.h> +#include "bttvp.h" +#include <media/v4l2-common.h> + #include <linux/dma-mapping.h> #include <asm/io.h> #include <asm/byteorder.h> -#include "bttvp.h" - #include "rds.h" @@ -210,6 +211,9 @@ const struct bttv_tvnorm bttv_tvnorms[] = { .vdelay = 0x20, .vbipack = 255, .sram = 0, + /* ITU-R frame line number of the first VBI line + we can capture, of the first and second field. */ + .vbistart = { 7,320 }, },{ .v4l2_id = V4L2_STD_NTSC_M, .name = "NTSC", @@ -226,6 +230,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { .vdelay = 0x1a, .vbipack = 144, .sram = 1, + .vbistart = { 10, 273 }, },{ .v4l2_id = V4L2_STD_SECAM, .name = "SECAM", @@ -242,6 +247,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { .vdelay = 0x20, .vbipack = 255, .sram = 0, /* like PAL, correct? */ + .vbistart = { 7, 320 }, },{ .v4l2_id = V4L2_STD_PAL_Nc, .name = "PAL-Nc", @@ -258,6 +264,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { .vdelay = 0x1a, .vbipack = 144, .sram = -1, + .vbistart = { 7, 320 }, },{ .v4l2_id = V4L2_STD_PAL_M, .name = "PAL-M", @@ -274,6 +281,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { .vdelay = 0x1a, .vbipack = 144, .sram = -1, + .vbistart = { 10, 273 }, },{ .v4l2_id = V4L2_STD_PAL_N, .name = "PAL-N", @@ -290,6 +298,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { .vdelay = 0x20, .vbipack = 144, .sram = -1, + .vbistart = { 7, 320}, },{ .v4l2_id = V4L2_STD_NTSC_M_JP, .name = "NTSC-JP", @@ -306,6 +315,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { .vdelay = 0x16, .vbipack = 144, .sram = -1, + .vbistart = {10, 273}, },{ /* that one hopefully works with the strange timing * which video recorders produce when playing a NTSC @@ -326,6 +336,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { .vbipack = 255, .vtotal = 524, .sram = -1, + .vbistart = { 10, 273 }, } }; static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); @@ -1510,14 +1521,6 @@ static struct videobuf_queue_ops bttv_video_qops = { .buf_release = buffer_release, }; -static const char *v4l1_ioctls[] = { - "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT", - "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ", - "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT", - "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", - "SMICROCODE", "GVBIFMT", "SVBIFMT" }; -#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) - static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) { switch (cmd) { @@ -2206,22 +2209,9 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, unsigned long flags; int retval = 0; - if (bttv_debug > 1) { - switch (_IOC_TYPE(cmd)) { - case 'v': - printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n", - btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ? - v4l1_ioctls[_IOC_NR(cmd)] : "???"); - break; - case 'V': - printk("bttv%d: ioctl 0x%x (v4l2, %s)\n", - btv->c.nr, cmd, v4l2_ioctl_names[_IOC_NR(cmd)]); - break; - default: - printk("bttv%d: ioctl 0x%x (???)\n", - btv->c.nr, cmd); - } - } + if (bttv_debug > 1) + v4l_print_ioctl(btv->c.name, cmd); + if (btv->errors) bttv_reinit_bt848(btv); @@ -2570,10 +2560,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, fmt->count[0] = fmt2.fmt.vbi.count[0]; fmt->start[1] = fmt2.fmt.vbi.start[1]; fmt->count[1] = fmt2.fmt.vbi.count[1]; - if (fmt2.fmt.vbi.flags & VBI_UNSYNC) - fmt->flags |= V4L2_VBI_UNSYNC; - if (fmt2.fmt.vbi.flags & VBI_INTERLACED) - fmt->flags |= V4L2_VBI_INTERLACED; + if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC) + fmt->flags |= VBI_UNSYNC; + if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED) + fmt->flags |= VBI_INTERLACED; return 0; } case VIDIOCSVBIFMT: @@ -3120,6 +3110,7 @@ static struct file_operations bttv_fops = .open = bttv_open, .release = bttv_release, .ioctl = bttv_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, .read = bttv_read, .mmap = bttv_mmap, @@ -3229,6 +3220,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOCSFREQ: case VIDIOCGAUDIO: case VIDIOCSAUDIO: + case VIDIOC_LOG_STATUS: return bttv_common_ioctls(btv,cmd,arg); default: @@ -3701,8 +3693,8 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) btv=(struct bttv *)dev_id; - if (btv->any_irq) - handled = bttv_any_irq(&btv->c); + if (btv->custom_irq) + handled = btv->custom_irq(btv); count=0; while (1) { @@ -3738,9 +3730,9 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) if (astat&BT848_INT_VSYNC) btv->field_count++; - if (astat & BT848_INT_GPINT) { + if ((astat & BT848_INT_GPINT) && btv->remote) { wake_up(&btv->gpioq); - bttv_gpio_irq(&btv->c); + bttv_input_irq(btv); } if (astat & BT848_INT_I2CDONE) { @@ -3946,7 +3938,6 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->i2c_rc = -1; btv->tuner_type = UNSET; - btv->pinnacle_id = UNSET; btv->new_input = UNSET; btv->has_radio=radio[btv->c.nr]; @@ -4065,11 +4056,11 @@ static int __devinit bttv_probe(struct pci_dev *dev, } /* add subdevices */ - if (btv->has_remote) - bttv_sub_add_device(&btv->c, "remote"); if (bttv_tvcards[btv->c.type].has_dvb) bttv_sub_add_device(&btv->c, "dvb"); + bttv_input_init(btv); + /* everything is fine */ bttv_num++; return 0; @@ -4104,6 +4095,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) /* tell gpio modules we are leaving ... */ btv->shutdown=1; wake_up(&btv->gpioq); + bttv_input_fini(btv); bttv_sub_del_devices(&btv->c); /* unregister i2c_bus + input */ diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index 616a5b7e510c..575ce8b8e714 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c @@ -113,24 +113,6 @@ void bttv_gpio_irq(struct bttv_core *core) } } -int bttv_any_irq(struct bttv_core *core) -{ - struct bttv_sub_driver *drv; - struct bttv_sub_device *dev; - struct list_head *item; - int handled = 0; - - 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->any_irq) { - if (drv->any_irq(dev)) - handled = 1; - } - } - return handled; -} - /* ----------------------------------------------------------------------- */ /* external: sub-driver register/unregister */ diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index d6418c023d39..748d630c7fe4 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -28,10 +28,11 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> -#include <linux/jiffies.h> -#include <asm/io.h> #include "bttvp.h" +#include <media/v4l2-common.h> +#include <linux/jiffies.h> +#include <asm/io.h> static struct i2c_algo_bit_data bttv_i2c_algo_bit_template; static struct i2c_adapter bttv_i2c_adap_sw_template; @@ -105,10 +106,8 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = { static struct i2c_adapter bttv_i2c_adap_sw_template = { .owner = THIS_MODULE, -#ifdef I2C_CLASS_TV_ANALOG .class = I2C_CLASS_TV_ANALOG, -#endif - .name = "bt848", + .name = "bttv", .id = I2C_HW_B_BT848, .client_register = attach_inform, }; @@ -275,10 +274,8 @@ static struct i2c_algorithm bttv_algo = { }; static struct i2c_adapter bttv_i2c_adap_hw_template = { - .owner = THIS_MODULE, -#ifdef I2C_CLASS_TV_ANALOG + .owner = THIS_MODULE, .class = I2C_CLASS_TV_ANALOG, -#endif .name = "bt878", .id = I2C_HW_B_BT848 /* FIXME */, .algo = &bttv_algo, @@ -441,12 +438,10 @@ int __devinit init_bttv_i2c(struct bttv *btv) i2c_set_adapdata(&btv->c.i2c_adap, btv); btv->i2c_client.adapter = &btv->c.i2c_adap; -#ifdef I2C_CLASS_TV_ANALOG if (bttv_tvcards[btv->c.type].no_video) btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG; if (bttv_tvcards[btv->c.type].has_dvb) btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL; -#endif if (btv->use_i2c_hw) { btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap); diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/bttv-input.c index de1385e5d05e..12197f1b2757 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/bttv-input.c @@ -24,11 +24,9 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/input.h> -#include <linux/pci.h> - -#include <media/ir-common.h> #include "bttv.h" +#include "bttvp.h" /* ---------------------------------------------------------------------- */ @@ -156,9 +154,6 @@ static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { /* ---------------------------------------------------------------------- */ -/* Ricardo Cerqueira <v4l@cerqueira.org> */ -/* Weird matching, since the remote has "uncommon" keys */ - static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { [ 30 ] = KEY_POWER, // power @@ -279,34 +274,6 @@ static IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { [0x36] = KEY_PC }; -struct IR { - struct bttv_sub_device *sub; - struct input_dev *input; - struct ir_input_state ir; - char name[32]; - char phys[32]; - - /* Usual gpio signalling */ - - u32 mask_keycode; - u32 mask_keydown; - u32 mask_keyup; - u32 polling; - u32 last_gpio; - struct work_struct work; - struct timer_list timer; - - /* RC5 gpio */ - u32 rc5_gpio; - struct timer_list timer_end; /* timer_end for code completion */ - struct timer_list timer_keyup; /* timer_end for key release */ - u32 last_rc5; /* last good rc5 code */ - u32 last_bit; /* last raw bit seen */ - u32 code; /* raw code under construction */ - struct timeval base_time; /* time of last seen code */ - int active; /* building raw code */ -}; - static int debug; module_param(debug, int, 0644); /* debug level (0,1,2) */ static int repeat_delay = 500; @@ -314,31 +281,17 @@ module_param(repeat_delay, int, 0644); static int repeat_period = 33; module_param(repeat_period, int, 0644); -#define DEVNAME "ir-kbd-gpio" -#define dprintk(fmt, arg...) if (debug) \ - printk(KERN_DEBUG DEVNAME ": " fmt , ## arg) - -static void ir_irq(struct bttv_sub_device *sub); -static int ir_probe(struct device *dev); -static int ir_remove(struct device *dev); - -static struct bttv_sub_driver driver = { - .drv = { - .name = DEVNAME, - .probe = ir_probe, - .remove = ir_remove, - }, - .gpio_irq = ir_irq, -}; +#define DEVNAME "bttv-input" /* ---------------------------------------------------------------------- */ -static void ir_handle_key(struct IR *ir) +static void ir_handle_key(struct bttv *btv) { + struct bttv_ir *ir = btv->remote; u32 gpio,data; /* read gpio value */ - gpio = bttv_gpio_read(ir->sub->core); + gpio = bttv_gpio_read(&btv->c); if (ir->polling) { if (ir->last_gpio == gpio) return; @@ -347,56 +300,36 @@ static void ir_handle_key(struct IR *ir) /* extract data */ data = ir_extract_bits(gpio, ir->mask_keycode); - dprintk(DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n", + dprintk(KERN_INFO DEVNAME ": 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); - } - + if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || + (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { + ir_input_keydown(ir->dev,&ir->ir,data,data); } else { - /* can't disturgissh keydown/up :-/ */ - ir_input_keydown(ir->input, &ir->ir, data, data); - ir_input_nokey(ir->input, &ir->ir); + ir_input_nokey(ir->dev,&ir->ir); } -} - -static void ir_irq(struct bttv_sub_device *sub) -{ - struct IR *ir = dev_get_drvdata(&sub->dev); - if (!ir->polling) - ir_handle_key(ir); } -static void ir_timer(unsigned long data) +void bttv_input_irq(struct bttv *btv) { - struct IR *ir = (struct IR*)data; + struct bttv_ir *ir = btv->remote; - schedule_work(&ir->work); + if (!ir->polling) + ir_handle_key(btv); } -static void ir_work(void *data) +static void bttv_input_timer(unsigned long data) { - struct IR *ir = data; + struct bttv *btv = (struct bttv*)data; + struct bttv_ir *ir = btv->remote; unsigned long timeout; - ir_handle_key(ir); + ir_handle_key(btv); timeout = jiffies + (ir->polling * HZ / 1000); mod_timer(&ir->timer, timeout); } @@ -435,26 +368,26 @@ static u32 rc5_decode(unsigned int code) rc5 |= 1; break; case 3: - dprintk("bad code: %x\n", org_code); + dprintk(KERN_WARNING "bad code: %x\n", org_code); return 0; } } - dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " + dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " "instr=%x\n", rc5, org_code, RC5_START(rc5), RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); return rc5; } -static int ir_rc5_irq(struct bttv_sub_device *sub) +static int bttv_rc5_irq(struct bttv *btv) { - struct IR *ir = dev_get_drvdata(&sub->dev); + struct bttv_ir *ir = btv->remote; struct timeval tv; u32 gpio; u32 gap; unsigned long current_jiffies, timeout; /* read gpio port */ - gpio = bttv_gpio_read(ir->sub->core); + gpio = bttv_gpio_read(&btv->c); /* remote IRQ? */ if (!(gpio & 0x20)) @@ -493,14 +426,15 @@ static int ir_rc5_irq(struct bttv_sub_device *sub) } /* toggle GPIO pin 4 to reset the irq */ - bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4)); - bttv_gpio_write(ir->sub->core, gpio | (1 << 4)); + bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); + bttv_gpio_write(&btv->c, gpio | (1 << 4)); return 1; } -static void ir_rc5_timer_end(unsigned long data) + +static void bttv_rc5_timer_end(unsigned long data) { - struct IR *ir = (struct IR *)data; + struct bttv_ir *ir = (struct bttv_ir *)data; struct timeval tv; unsigned long current_jiffies, timeout; u32 gap; @@ -519,20 +453,20 @@ static void ir_rc5_timer_end(unsigned long data) /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */ if (gap < 28000) { - dprintk("spurious timer_end\n"); + dprintk(KERN_WARNING "spurious timer_end\n"); return; } ir->active = 0; if (ir->last_bit < 20) { /* ignore spurious codes (caused by light/other remotes) */ - dprintk("short code: %x\n", ir->code); + dprintk(KERN_WARNING "short code: %x\n", ir->code); } else { u32 rc5 = rc5_decode(ir->code); /* two start bits? */ if (RC5_START(rc5) != 3) { - dprintk("rc5 start bits invalid: %u\n", RC5_START(rc5)); + dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5)); /* right address? */ } else if (RC5_ADDR(rc5) == 0x0) { @@ -542,10 +476,10 @@ static void ir_rc5_timer_end(unsigned long data) /* Good code, decide if repeat/repress */ if (toggle != RC5_TOGGLE(ir->last_rc5) || instr != RC5_INSTR(ir->last_rc5)) { - dprintk("instruction %x, toggle %x\n", instr, + dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr, toggle); - ir_input_nokey(ir->input, &ir->ir); - ir_input_keydown(ir->input, &ir->ir, instr, + ir_input_nokey(ir->dev, &ir->ir); + ir_input_keydown(ir->dev, &ir->ir, instr, instr); } @@ -560,34 +494,37 @@ static void ir_rc5_timer_end(unsigned long data) } } -static void ir_rc5_timer_keyup(unsigned long data) +static void bttv_rc5_timer_keyup(unsigned long data) { - struct IR *ir = (struct IR *)data; + struct bttv_ir *ir = (struct bttv_ir *)data; - dprintk("key released\n"); - ir_input_nokey(ir->input, &ir->ir); + dprintk(KERN_DEBUG "key released\n"); + ir_input_nokey(ir->dev, &ir->ir); } /* ---------------------------------------------------------------------- */ -static int ir_probe(struct device *dev) +int bttv_input_init(struct bttv *btv) { - struct bttv_sub_device *sub = to_bttv_sub_dev(dev); - struct IR *ir; - struct input_dev *input_dev; + struct bttv_ir *ir; IR_KEYTAB_TYPE *ir_codes = NULL; + struct input_dev *input_dev; int ir_type = IR_TYPE_OTHER; - ir = kzalloc(sizeof(*ir), GFP_KERNEL); + if (!btv->has_remote) + return -ENODEV; + + ir = kzalloc(sizeof(*ir),GFP_KERNEL); input_dev = input_allocate_device(); if (!ir || !input_dev) { kfree(ir); input_free_device(input_dev); return -ENOMEM; } + memset(ir,0,sizeof(*ir)); /* detect & configure */ - switch (sub->core->type) { + switch (btv->c.type) { case BTTV_BOARD_AVERMEDIA: case BTTV_BOARD_AVPHONE98: case BTTV_BOARD_AVERMEDIA98: @@ -643,12 +580,12 @@ static int ir_probe(struct device *dev) break; case BTTV_BOARD_NEBULA_DIGITV: ir_codes = ir_codes_nebula; - driver.any_irq = ir_rc5_irq; - driver.gpio_irq = NULL; + btv->custom_irq = bttv_rc5_irq; ir->rc5_gpio = 1; break; } if (NULL == ir_codes) { + dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type); kfree(ir); input_free_device(input_dev); return -ENODEV; @@ -657,109 +594,92 @@ static int ir_probe(struct device *dev) if (ir->rc5_gpio) { u32 gpio; /* enable remote irq */ - bttv_gpio_inout(sub->core, (1 << 4), 1 << 4); - gpio = bttv_gpio_read(sub->core); - bttv_gpio_write(sub->core, gpio & ~(1 << 4)); - bttv_gpio_write(sub->core, gpio | (1 << 4)); + bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4); + gpio = bttv_gpio_read(&btv->c); + bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); + bttv_gpio_write(&btv->c, gpio | (1 << 4)); } else { /* init hardware-specific stuff */ - bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0); + bttv_gpio_inout(&btv->c, ir->mask_keycode | ir->mask_keydown, 0); } /* init input device */ + ir->dev = input_dev; + snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", - sub->core->type); + btv->c.type); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", - pci_name(sub->core->pci)); + pci_name(btv->c.pci)); ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_PCI; input_dev->id.version = 1; - if (sub->core->pci->subsystem_vendor) { - input_dev->id.vendor = sub->core->pci->subsystem_vendor; - input_dev->id.product = sub->core->pci->subsystem_device; + if (btv->c.pci->subsystem_vendor) { + input_dev->id.vendor = btv->c.pci->subsystem_vendor; + input_dev->id.product = btv->c.pci->subsystem_device; } else { - input_dev->id.vendor = sub->core->pci->vendor; - input_dev->id.product = sub->core->pci->device; + input_dev->id.vendor = btv->c.pci->vendor; + input_dev->id.product = btv->c.pci->device; } - input_dev->cdev.dev = &sub->core->pci->dev; - - ir->input = input_dev; - ir->sub = sub; + input_dev->cdev.dev = &btv->c.pci->dev; + btv->remote = ir; if (ir->polling) { - INIT_WORK(&ir->work, ir_work, ir); init_timer(&ir->timer); - ir->timer.function = ir_timer; - ir->timer.data = (unsigned long)ir; - schedule_work(&ir->work); + ir->timer.function = bttv_input_timer; + ir->timer.data = (unsigned long)btv; + ir->timer.expires = jiffies + HZ; + add_timer(&ir->timer); } else if (ir->rc5_gpio) { /* set timer_end for code completion */ init_timer(&ir->timer_end); - ir->timer_end.function = ir_rc5_timer_end; + ir->timer_end.function = bttv_rc5_timer_end; ir->timer_end.data = (unsigned long)ir; init_timer(&ir->timer_keyup); - ir->timer_keyup.function = ir_rc5_timer_keyup; + ir->timer_keyup.function = bttv_rc5_timer_keyup; ir->timer_keyup.data = (unsigned long)ir; } /* all done */ - dev_set_drvdata(dev, ir); - input_register_device(ir->input); + input_register_device(btv->remote->dev); + printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); /* the remote isn't as bouncy as a keyboard */ - ir->input->rep[REP_DELAY] = repeat_delay; - ir->input->rep[REP_PERIOD] = repeat_period; + ir->dev->rep[REP_DELAY] = repeat_delay; + ir->dev->rep[REP_PERIOD] = repeat_period; return 0; } -static int ir_remove(struct device *dev) +void bttv_input_fini(struct bttv *btv) { - struct IR *ir = dev_get_drvdata(dev); + if (btv->remote == NULL) + return; - if (ir->polling) { - del_timer(&ir->timer); + if (btv->remote->polling) { + del_timer_sync(&btv->remote->timer); flush_scheduled_work(); } - if (ir->rc5_gpio) { + + if (btv->remote->rc5_gpio) { u32 gpio; - del_timer(&ir->timer_end); + del_timer_sync(&btv->remote->timer_end); flush_scheduled_work(); - gpio = bttv_gpio_read(ir->sub->core); - bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4)); + gpio = bttv_gpio_read(&btv->c); + bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); } - input_unregister_device(ir->input); - kfree(ir); - return 0; -} - -/* ---------------------------------------------------------------------- */ - -MODULE_AUTHOR("Gerd Knorr, Pavel Machek"); -MODULE_DESCRIPTION("input driver for bt8x8 gpio IR remote controls"); -MODULE_LICENSE("GPL"); - -static int ir_init(void) -{ - return bttv_sub_register(&driver, "remote"); + input_unregister_device(btv->remote->dev); + kfree(btv->remote); + btv->remote = NULL; } -static void ir_fini(void) -{ - bttv_sub_unregister(&driver); -} - -module_init(ir_init); -module_exit(ir_fini); - /* * Local variables: diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c index f4f58c60f152..72afdd64b882 100644 --- a/drivers/media/video/bttv-vbi.c +++ b/drivers/media/video/bttv-vbi.c @@ -31,6 +31,12 @@ #include <asm/io.h> #include "bttvp.h" +/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate: + bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC + HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge + of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */ +#define VBI_OFFSET ((64 + 0) * 2) + #define VBI_DEFLINES 16 #define VBI_MAXLINES 32 @@ -163,40 +169,30 @@ void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines) void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f) { const struct bttv_tvnorm *tvnorm; - u32 start0,start1; - s32 count0,count1,count; + s64 count0,count1,count; tvnorm = &bttv_tvnorms[fh->btv->tvnorm]; f->type = V4L2_BUF_TYPE_VBI_CAPTURE; f->fmt.vbi.sampling_rate = tvnorm->Fsc; f->fmt.vbi.samples_per_line = 2048; f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - f->fmt.vbi.offset = 244; + f->fmt.vbi.offset = VBI_OFFSET; f->fmt.vbi.flags = 0; - switch (fh->btv->tvnorm) { - case 1: /* NTSC */ - start0 = 10; - start1 = 273; - break; - case 0: /* PAL */ - case 2: /* SECAM */ - default: - start0 = 7; - start1 = 320; - } - count0 = (f->fmt.vbi.start[0] + f->fmt.vbi.count[0]) - start0; - count1 = (f->fmt.vbi.start[1] + f->fmt.vbi.count[1]) - start1; - count = max(count0,count1); - if (count > VBI_MAXLINES) - count = VBI_MAXLINES; - if (count < 1) - count = 1; + /* s64 to prevent overflow. */ + count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0] + - tvnorm->vbistart[0]; + count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1] + - tvnorm->vbistart[1]; + count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES); - f->fmt.vbi.start[0] = start0; - f->fmt.vbi.start[1] = start1; + f->fmt.vbi.start[0] = tvnorm->vbistart[0]; + f->fmt.vbi.start[1] = tvnorm->vbistart[1]; f->fmt.vbi.count[0] = count; f->fmt.vbi.count[1] = count; + + f->fmt.vbi.reserved[0] = 0; + f->fmt.vbi.reserved[1] = 0; } void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f) @@ -209,21 +205,12 @@ void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f) f->fmt.vbi.sampling_rate = tvnorm->Fsc; f->fmt.vbi.samples_per_line = 2048; f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - f->fmt.vbi.offset = 244; + f->fmt.vbi.offset = VBI_OFFSET; + f->fmt.vbi.start[0] = tvnorm->vbistart[0]; + f->fmt.vbi.start[1] = tvnorm->vbistart[1]; f->fmt.vbi.count[0] = fh->lines; f->fmt.vbi.count[1] = fh->lines; f->fmt.vbi.flags = 0; - switch (fh->btv->tvnorm) { - case 1: /* NTSC */ - f->fmt.vbi.start[0] = 10; - f->fmt.vbi.start[1] = 273; - break; - case 0: /* PAL */ - case 2: /* SECAM */ - default: - f->fmt.vbi.start[0] = 7; - f->fmt.vbi.start[1] = 319; - } } /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 93298f06e019..9feaa6bab207 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -16,6 +16,8 @@ #include <linux/videodev.h> #include <linux/i2c.h> +#include <media/ir-common.h> +#include <media/ir-kbd-i2c.h> /* ---------------------------------------------------------- */ /* exported by bttv-cards.c */ @@ -163,6 +165,7 @@ #define BTTV_BOARD_OSPREY440 0x8c #define BTTV_BOARD_ASOUND_SKYEYE 0x8d #define BTTV_BOARD_SABRENT_TVFM 0x8e +#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f /* i2c address list */ #define I2C_TSA5522 0xc2 @@ -210,6 +213,34 @@ struct bttv_core { struct bttv; + +struct bttv_ir { + struct input_dev *dev; + struct ir_input_state ir; + char name[32]; + char phys[32]; + + /* Usual gpio signalling */ + + u32 mask_keycode; + u32 mask_keydown; + u32 mask_keyup; + u32 polling; + u32 last_gpio; + struct work_struct work; + struct timer_list timer; + + /* RC5 gpio */ + u32 rc5_gpio; + struct timer_list timer_end; /* timer_end for code completion */ + struct timer_list timer_keyup; /* timer_end for key release */ + u32 last_rc5; /* last good rc5 code */ + u32 last_bit; /* last raw bit seen */ + u32 code; /* raw code under construction */ + struct timeval base_time; /* time of last seen code */ + int active; /* building raw code */ +}; + struct tvcard { char *name; @@ -235,7 +266,6 @@ struct tvcard unsigned int has_dvb:1; unsigned int has_remote:1; unsigned int no_gpioirq:1; - unsigned int any_irq:1; /* other settings */ unsigned int pll; @@ -335,7 +365,6 @@ struct bttv_sub_driver { struct device_driver drv; char wanted[BUS_ID_SIZE]; void (*gpio_irq)(struct bttv_sub_device *sub); - int (*any_irq)(struct bttv_sub_device *sub); }; #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) @@ -363,6 +392,10 @@ extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, unsigned char b2, int both); extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); +extern int bttv_input_init(struct bttv *dev); +extern void bttv_input_fini(struct bttv *dev); +extern void bttv_input_irq(struct bttv *dev); + #endif /* _BTTV_H_ */ /* * Local variables: diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 1e6a5632c3c7..dd00c20ab95e 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -73,6 +73,8 @@ #define UNSET (-1U) +#define clamp(x, low, high) min (max (low, x), high) + /* ---------------------------------------------------------- */ struct bttv_tvnorm { @@ -88,6 +90,9 @@ struct bttv_tvnorm { u8 vbipack; u16 vtotal; int sram; + /* ITU-R frame line number of the first VBI line we can + capture, of the first and second field. */ + u16 vbistart[2]; }; extern const struct bttv_tvnorm bttv_tvnorms[]; @@ -209,7 +214,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); -int bttv_any_irq(struct bttv_core *core); /* ---------------------------------------------------------- */ @@ -270,12 +274,13 @@ struct bttv { /* card configuration info */ unsigned int cardid; /* pci subsystem id (bt878 based ones) */ unsigned int tuner_type; /* tuner chip type */ - unsigned int pinnacle_id; + unsigned int tda9887_conf; unsigned int svhs; struct bttv_pll_info pll; int triton1; int gpioirq; - int any_irq; + int (*custom_irq)(struct bttv *btv); + int use_i2c_hw; /* old gpio interface */ @@ -300,7 +305,7 @@ struct bttv { /* infrared remote */ int has_remote; - struct bttv_input *remote; + struct bttv_ir *remote; /* locking */ spinlock_t s_lock; diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 0065d0c240d1..6bad93ef969f 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -875,6 +875,7 @@ static struct file_operations qcam_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = qcam_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .read = qcam_read, .llseek = no_llseek, }; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 75442ec49f35..9976db4f6da8 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -687,6 +687,7 @@ static struct file_operations qcam_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = qcam_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .read = qcam_read, .llseek = no_llseek, }; diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c new file mode 100644 index 000000000000..6194b0125576 --- /dev/null +++ b/drivers/media/video/compat_ioctl32.c @@ -0,0 +1,732 @@ +/* + * ioctl32.c: Conversion between 32bit and 64bit native ioctls. + * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de> + * + * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) + * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs + * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) + * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be) + * + * These routines maintain argument size conversion between 32bit and 64bit + * ioctls. + */ + +#include <linux/config.h> +#include <linux/compat.h> +#include <linux/videodev.h> +#include <linux/videodev2.h> +#include <linux/module.h> +#include <linux/smp_lock.h> + +#ifdef CONFIG_COMPAT +struct video_tuner32 { + compat_int_t tuner; + char name[32]; + compat_ulong_t rangelow, rangehigh; + u32 flags; /* It is really u32 in videodev.h */ + u16 mode, signal; +}; + +static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) +{ + if(get_user(kp->tuner, &up->tuner)) + return -EFAULT; + __copy_from_user(kp->name, up->name, 32); + __get_user(kp->rangelow, &up->rangelow); + __get_user(kp->rangehigh, &up->rangehigh); + __get_user(kp->flags, &up->flags); + __get_user(kp->mode, &up->mode); + __get_user(kp->signal, &up->signal); + return 0; +} + +static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) +{ + if(put_user(kp->tuner, &up->tuner)) + return -EFAULT; + __copy_to_user(up->name, kp->name, 32); + __put_user(kp->rangelow, &up->rangelow); + __put_user(kp->rangehigh, &up->rangehigh); + __put_user(kp->flags, &up->flags); + __put_user(kp->mode, &up->mode); + __put_user(kp->signal, &up->signal); + return 0; +} + +struct video_buffer32 { + compat_caddr_t base; + compat_int_t height, width, depth, bytesperline; +}; + +static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) +{ + u32 tmp; + + if (get_user(tmp, &up->base)) + return -EFAULT; + + /* This is actually a physical address stored + * as a void pointer. + */ + kp->base = (void *)(unsigned long) tmp; + + __get_user(kp->height, &up->height); + __get_user(kp->width, &up->width); + __get_user(kp->depth, &up->depth); + __get_user(kp->bytesperline, &up->bytesperline); + return 0; +} + +static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) +{ + u32 tmp = (u32)((unsigned long)kp->base); + + if(put_user(tmp, &up->base)) + return -EFAULT; + __put_user(kp->height, &up->height); + __put_user(kp->width, &up->width); + __put_user(kp->depth, &up->depth); + __put_user(kp->bytesperline, &up->bytesperline); + return 0; +} + +struct video_clip32 { + s32 x, y, width, height; /* Its really s32 in videodev.h */ + compat_caddr_t next; +}; + +struct video_window32 { + u32 x, y, width, height, chromakey, flags; + compat_caddr_t clips; + compat_int_t clipcount; +}; + +static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = -ENOIOCTLCMD; + + if (file->f_op->unlocked_ioctl) + ret = file->f_op->unlocked_ioctl(file, cmd, arg); + else if (file->f_op->ioctl) { + lock_kernel(); + ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg); + unlock_kernel(); + } + + return ret; +} + + +/* You get back everything except the clips... */ +static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) +{ + if(put_user(kp->x, &up->x)) + return -EFAULT; + __put_user(kp->y, &up->y); + __put_user(kp->width, &up->width); + __put_user(kp->height, &up->height); + __put_user(kp->chromakey, &up->chromakey); + __put_user(kp->flags, &up->flags); + __put_user(kp->clipcount, &up->clipcount); + return 0; +} + +struct v4l2_clip32 +{ + struct v4l2_rect c; + compat_caddr_t next; +}; + +struct v4l2_window32 +{ + struct v4l2_rect w; + enum v4l2_field field; + __u32 chromakey; + compat_caddr_t clips; /* actually struct v4l2_clip32 * */ + __u32 clipcount; + compat_caddr_t bitmap; +}; + +static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) +{ + if (copy_from_user(&kp->w, &up->w, sizeof(up->w))) + return -EFAULT; + __get_user(kp->field, &up->field); + __get_user(kp->chromakey, &up->chromakey); + __get_user(kp->clipcount, &up->clipcount); + if (kp->clipcount > 2048) + return -EINVAL; + if (kp->clipcount) { + struct v4l2_clip32 *uclips = compat_ptr(up->clips); + struct v4l2_clip *kclips; + int n = kp->clipcount; + + kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); + kp->clips = kclips; + while (--n >= 0) { + copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c)); + kclips->next = n ? kclips + 1 : 0; + uclips += 1; + kclips += 1; + } + } else + kp->clips = 0; + return 0; +} + +static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) +{ + if (copy_to_user(&up->w, &kp->w, sizeof(up->w))) + return -EFAULT; + __put_user(kp->field, &up->field); + __put_user(kp->chromakey, &up->chromakey); + __put_user(kp->clipcount, &up->clipcount); + return 0; +} + +static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) +{ + return copy_from_user(kp, up, sizeof(struct v4l2_pix_format)); +} + +static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) +{ + return copy_to_user(up, kp, sizeof(struct v4l2_pix_format)); +} + +static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) +{ + return copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)); +} + +static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) +{ + return copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)); +} + +struct v4l2_format32 +{ + enum v4l2_buf_type type; + union + { + struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE + struct v4l2_window32 win; // V4L2_BUF_TYPE_VIDEO_OVERLAY + struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE + __u8 raw_data[200]; // user-defined + } fmt; +}; + +static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) +{ + if(get_user(kp->type, &up->type)) + return -EFAULT; + switch (kp->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); + case V4L2_BUF_TYPE_VBI_CAPTURE: + return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); + default: + printk("compat_ioctl : unexpected VIDIOC_FMT type %d\n", + kp->type); + return -ENXIO; + } +} + +static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) +{ + if(put_user(kp->type, &up->type)) + return -EFAULT; + switch (kp->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); + case V4L2_BUF_TYPE_VBI_CAPTURE: + return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); + default: + return -ENXIO; + } +} + +struct v4l2_standard32 +{ + __u32 index; + __u32 id[2]; /* __u64 would get the alignment wrong */ + __u8 name[24]; + struct v4l2_fract frameperiod; /* Frames, not fields */ + __u32 framelines; + __u32 reserved[4]; +}; + +static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) +{ + /* other fields are not set by the user, nor used by the driver */ + return get_user(kp->index, &up->index); +} + +static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) +{ + if(put_user(kp->index, &up->index)) + return -EFAULT; + __copy_to_user(up->id, &kp->id, sizeof(__u64)); + __copy_to_user(up->name, kp->name, 24); + __put_user(kp->frameperiod, &up->frameperiod); + __put_user(kp->framelines, &up->framelines); + __copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)); + return 0; +} + +struct v4l2_buffer32 +{ + __u32 index; + enum v4l2_buf_type type; + __u32 bytesused; + __u32 flags; + enum v4l2_field field; + struct compat_timeval timestamp; + struct v4l2_timecode timecode; + __u32 sequence; + + /* memory location */ + enum v4l2_memory memory; + union { + __u32 offset; + compat_long_t userptr; + } m; + __u32 length; + __u32 input; + __u32 reserved; +}; + +static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) +{ + + if (get_user(kp->index, &up->index)) + return -EFAULT; + __get_user(kp->type, &up->type); + __get_user(kp->flags, &up->flags); + __get_user(kp->memory, &up->memory); + __get_user(kp->input, &up->input); + switch(kp->memory) { + case V4L2_MEMORY_MMAP: + break; + case V4L2_MEMORY_USERPTR: + { + unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr); + + __get_user(kp->length, &up->length); + __get_user(kp->m.userptr, &tmp); + } + break; + case V4L2_MEMORY_OVERLAY: + __get_user(kp->m.offset, &up->m.offset); + break; + } + return 0; +} + +static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) +{ + if (put_user(kp->index, &up->index)) + return -EFAULT; + __put_user(kp->type, &up->type); + __put_user(kp->flags, &up->flags); + __put_user(kp->memory, &up->memory); + __put_user(kp->input, &up->input); + switch(kp->memory) { + case V4L2_MEMORY_MMAP: + __put_user(kp->length, &up->length); + __put_user(kp->m.offset, &up->m.offset); + break; + case V4L2_MEMORY_USERPTR: + __put_user(kp->length, &up->length); + __put_user(kp->m.userptr, &up->m.userptr); + break; + case V4L2_MEMORY_OVERLAY: + __put_user(kp->m.offset, &up->m.offset); + break; + } + __put_user(kp->bytesused, &up->bytesused); + __put_user(kp->field, &up->field); + __put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec); + __put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec); + __copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)); + __put_user(kp->sequence, &up->sequence); + __put_user(kp->reserved, &up->reserved); + return 0; +} + +struct v4l2_framebuffer32 +{ + __u32 capability; + __u32 flags; + compat_caddr_t base; + struct v4l2_pix_format fmt; +}; + +static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) +{ + u32 tmp; + + if (get_user(tmp, &up->base)) + return -EFAULT; + kp->base = compat_ptr(tmp); + __get_user(kp->capability, &up->capability); + __get_user(kp->flags, &up->flags); + get_v4l2_pix_format(&kp->fmt, &up->fmt); + return 0; +} + +static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) +{ + u32 tmp = (u32)((unsigned long)kp->base); + + if(put_user(tmp, &up->base)) + return -EFAULT; + __put_user(kp->capability, &up->capability); + __put_user(kp->flags, &up->flags); + put_v4l2_pix_format(&kp->fmt, &up->fmt); + return 0; +} + +struct v4l2_input32 /* identical layout, but different size */ +{ + __u32 index; /* Which input */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of input */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 tuner; /* Associated tuner */ + __u32 std[2]; /* __u64 would get the padding wrong */ + __u32 status; + __u32 reserved[4]; +}; + +#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) +#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) +#define VIDIOCGWIN32 _IOR('v',9, struct video_window32) +#define VIDIOCSWIN32 _IOW('v',10, struct video_window32) +#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32) +#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32) +#define VIDIOCGFREQ32 _IOR('v',14, u32) +#define VIDIOCSFREQ32 _IOW('v',15, u32) + +#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32) +#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32) +#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32) +#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) +#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) +/* VIDIOC_OVERLAY is now _IOW, but was _IOWR */ +#define VIDIOC_OVERLAY32 _IOWR ('V', 14, compat_int_t) +#define VIDIOC_QBUF32 _IOWR ('V', 15, struct v4l2_buffer32) +#define VIDIOC_DQBUF32 _IOWR ('V', 17, struct v4l2_buffer32) +#define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t) +#define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t) +#define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32) +#define VIDIOC_ENUMINPUT32 _IOWR ('V', 26, struct v4l2_input32) +/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */ +#define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control) +#define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t) +#define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t) +#define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32) + +enum { + MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip) +}; + +static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct video_window32 __user *up = compat_ptr(arg); + struct video_window __user *vw; + struct video_clip __user *p; + int nclips; + u32 n; + + if (get_user(nclips, &up->clipcount)) + return -EFAULT; + + /* Peculiar interface... */ + if (nclips < 0) + nclips = VIDEO_CLIPMAP_SIZE; + + if (nclips > MaxClips) + return -ENOMEM; + + vw = compat_alloc_user_space(sizeof(struct video_window) + + nclips * sizeof(struct video_clip)); + + p = nclips ? (struct video_clip __user *)(vw + 1) : NULL; + + if (get_user(n, &up->x) || put_user(n, &vw->x) || + get_user(n, &up->y) || put_user(n, &vw->y) || + get_user(n, &up->width) || put_user(n, &vw->width) || + get_user(n, &up->height) || put_user(n, &vw->height) || + get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) || + get_user(n, &up->flags) || put_user(n, &vw->flags) || + get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) || + get_user(n, &up->clips) || put_user(p, &vw->clips)) + return -EFAULT; + + if (nclips) { + struct video_clip32 __user *u = compat_ptr(n); + int i; + if (!u) + return -EINVAL; + for (i = 0; i < nclips; i++, u++, p++) { + s32 v; + if (get_user(v, &u->x) || + put_user(v, &p->x) || + get_user(v, &u->y) || + put_user(v, &p->y) || + get_user(v, &u->width) || + put_user(v, &p->width) || + get_user(v, &u->height) || + put_user(v, &p->height) || + put_user(NULL, &p->next)) + return -EFAULT; + } + } + + return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw); +} + +static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + union { + struct video_tuner vt; + struct video_buffer vb; + struct video_window vw; + struct v4l2_format v2f; + struct v4l2_buffer v2b; + struct v4l2_framebuffer v2fb; + struct v4l2_standard v2s; + unsigned long vx; + } karg; + void __user *up = compat_ptr(arg); + int compatible_arg = 1; + int err = 0; + + /* First, convert the command. */ + switch(cmd) { + case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; + case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; + case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; + case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; + case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; + case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; + case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; + case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; + case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; + case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; + case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break; + case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break; + case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break; + case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break; + case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; + case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; + case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; + case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break; + case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break; + case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break; + case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; + case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; + case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break; + }; + + switch(cmd) { + case VIDIOCSTUNER: + case VIDIOCGTUNER: + err = get_video_tuner32(&karg.vt, up); + compatible_arg = 0; + + break; + + case VIDIOCSFBUF: + err = get_video_buffer32(&karg.vb, up); + compatible_arg = 0; + break; + + case VIDIOCSFREQ: + case VIDIOC_S_INPUT: + case VIDIOC_OVERLAY: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: + err = get_user(karg.vx, (u32 __user *)up); + compatible_arg = 0; + break; + + case VIDIOC_S_FBUF: + err = get_v4l2_framebuffer32(&karg.v2fb, up); + compatible_arg = 0; + break; + + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: + err = get_v4l2_format32(&karg.v2f, up); + compatible_arg = 0; + break; + + case VIDIOC_QUERYBUF: + case VIDIOC_QBUF: + case VIDIOC_DQBUF: + err = get_v4l2_buffer32(&karg.v2b, up); + compatible_arg = 0; + break; + + case VIDIOC_ENUMSTD: + err = get_v4l2_standard32(&karg.v2s, up); + compatible_arg = 0; + break; + + case VIDIOCGWIN: + case VIDIOCGFBUF: + case VIDIOCGFREQ: + case VIDIOC_G_FBUF: + case VIDIOC_G_INPUT: + compatible_arg = 0; + }; + + if(err) + goto out; + + if(compatible_arg) + err = native_ioctl(file, cmd, (unsigned long)up); + else { + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + err = native_ioctl(file, cmd, (unsigned long)&karg); + set_fs(old_fs); + } + if(err == 0) { + switch(cmd) { + case VIDIOCGTUNER: + err = put_video_tuner32(&karg.vt, up); + break; + + case VIDIOCGWIN: + err = put_video_window32(&karg.vw, up); + break; + + case VIDIOCGFBUF: + err = put_video_buffer32(&karg.vb, up); + break; + + case VIDIOC_G_FBUF: + err = put_v4l2_framebuffer32(&karg.v2fb, up); + break; + + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: + err = put_v4l2_format32(&karg.v2f, up); + break; + + case VIDIOC_QUERYBUF: + case VIDIOC_QBUF: + case VIDIOC_DQBUF: + err = put_v4l2_buffer32(&karg.v2b, up); + break; + + case VIDIOC_ENUMSTD: + err = put_v4l2_standard32(&karg.v2s, up); + break; + + case VIDIOCGFREQ: + case VIDIOC_G_INPUT: + err = put_user(((u32)karg.vx), (u32 __user *)up); + break; + }; + } +out: + return err; +} + +long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = -ENOIOCTLCMD; + + if (!file->f_op->ioctl) + return ret; + + switch (cmd) { + case VIDIOCSWIN32: + ret = do_set_window(file, cmd, arg); + break; + case VIDIOCGTUNER32: + case VIDIOCSTUNER32: + case VIDIOCGWIN32: + case VIDIOCGFBUF32: + case VIDIOCSFBUF32: + case VIDIOCGFREQ32: + case VIDIOCSFREQ32: + case VIDIOC_QUERYCAP: + case VIDIOC_ENUM_FMT: + case VIDIOC_G_FMT32: + case VIDIOC_S_FMT32: + case VIDIOC_REQBUFS: + case VIDIOC_QUERYBUF32: + case VIDIOC_G_FBUF32: + case VIDIOC_S_FBUF32: + case VIDIOC_OVERLAY32: + case VIDIOC_QBUF32: + case VIDIOC_DQBUF32: + case VIDIOC_STREAMON32: + case VIDIOC_STREAMOFF32: + case VIDIOC_G_PARM: + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case VIDIOC_ENUMSTD32: + case VIDIOC_ENUMINPUT32: + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL32: + case VIDIOC_QUERYCTRL: + case VIDIOC_G_INPUT32: + case VIDIOC_S_INPUT32: + case VIDIOC_TRY_FMT32: + ret = do_video_ioctl(file, cmd, arg); + break; + + /* Little v, the video4linux ioctls (conflict?) */ + case VIDIOCGCAP: + case VIDIOCGCHAN: + case VIDIOCSCHAN: + case VIDIOCGPICT: + case VIDIOCSPICT: + case VIDIOCCAPTURE: + case VIDIOCKEY: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + case VIDIOCSYNC: + case VIDIOCMCAPTURE: + case VIDIOCGMBUF: + case VIDIOCGUNIT: + case VIDIOCGCAPTURE: + case VIDIOCSCAPTURE: + + /* BTTV specific... */ + case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]): + case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]): + case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int): + case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */ + case _IOR('v' , BASE_VIDIOCPRIVATE+4, int): + case _IOR('v' , BASE_VIDIOCPRIVATE+5, int): + case _IOR('v' , BASE_VIDIOCPRIVATE+6, int): + case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): + ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); + break; + } + return ret; +} +#else +long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} +#endif +EXPORT_SYMBOL_GPL(v4l_compat_ioctl32); + +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index b7ec9bf45085..9f59541155d9 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -3807,6 +3807,7 @@ static struct file_operations cpia_fops = { .read = cpia_read, .mmap = cpia_mmap, .ioctl = cpia_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c index 643ead1a87ee..b421068f7ea3 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/video/cs53l32a.c @@ -27,7 +27,7 @@ #include <linux/i2c.h> #include <linux/i2c-id.h> #include <linux/videodev.h> -#include <media/audiochip.h> +#include <media/v4l2-common.h> MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); MODULE_AUTHOR("Martin Vaughan"); @@ -39,21 +39,6 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On"); -#define cs53l32a_dbg(fmt, arg...) \ - do { \ - if (debug) \ - printk(KERN_INFO "%s debug %d-%04x: " fmt, \ - client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); \ - } while (0) - -#define cs53l32a_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) -#define cs53l32a_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) - static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; @@ -74,50 +59,59 @@ static int cs53l32a_read(struct i2c_client *client, u8 reg) static int cs53l32a_command(struct i2c_client *client, unsigned int cmd, void *arg) { - int *input = arg; + struct v4l2_audio *input = arg; + struct v4l2_control *ctrl = arg; switch (cmd) { - case AUDC_SET_INPUT: - switch (*input) { - case AUDIO_TUNER: - cs53l32a_write(client, 0x01, 0x01); - break; - case AUDIO_EXTERN: - cs53l32a_write(client, 0x01, 0x21); - break; - case AUDIO_MUTE: - cs53l32a_write(client, 0x03, 0xF0); - break; - case AUDIO_UNMUTE: - cs53l32a_write(client, 0x03, 0x30); - break; - default: - cs53l32a_err("Invalid input %d.\n", *input); + case VIDIOC_S_AUDIO: + /* There are 2 physical inputs, but the second input can be + placed in two modes, the first mode bypasses the PGA (gain), + the second goes through the PGA. Hence there are three + possible inputs to choose from. */ + if (input->index > 2) { + v4l_err(client, "Invalid input %d.\n", input->index); return -EINVAL; } + cs53l32a_write(client, 0x01, 0x01 + (input->index << 4)); + break; + + case VIDIOC_G_AUDIO: + memset(input, 0, sizeof(*input)); + input->index = (cs53l32a_read(client, 0x01) >> 4) & 3; + break; + + case VIDIOC_G_CTRL: + if (ctrl->id == V4L2_CID_AUDIO_MUTE) { + ctrl->value = (cs53l32a_read(client, 0x03) & 0xc0) != 0; + break; + } + if (ctrl->id != V4L2_CID_AUDIO_VOLUME) + return -EINVAL; + ctrl->value = (s8)cs53l32a_read(client, 0x04); break; case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - - if (ctrl->id != V4L2_CID_AUDIO_VOLUME) - return -EINVAL; - if (ctrl->value > 12 || ctrl->value < -90) - return -EINVAL; - cs53l32a_write(client, 0x04, (u8) ctrl->value); - cs53l32a_write(client, 0x05, (u8) ctrl->value); + if (ctrl->id == V4L2_CID_AUDIO_MUTE) { + cs53l32a_write(client, 0x03, ctrl->value ? 0xf0 : 0x30); break; } + if (ctrl->id != V4L2_CID_AUDIO_VOLUME) + return -EINVAL; + if (ctrl->value > 12 || ctrl->value < -96) + return -EINVAL; + cs53l32a_write(client, 0x04, (u8) ctrl->value); + cs53l32a_write(client, 0x05, (u8) ctrl->value); + break; case VIDIOC_LOG_STATUS: { u8 v = cs53l32a_read(client, 0x01); u8 m = cs53l32a_read(client, 0x03); + s8 vol = cs53l32a_read(client, 0x04); - cs53l32a_info("Input: %s%s\n", - v == 0x21 ? "external line in" : "tuner", + v4l_info(client, "Input: %d%s\n", (v >> 4) & 3, (m & 0xC0) ? " (muted)" : ""); + v4l_info(client, "Volume: %d dB\n", vol); break; } @@ -157,12 +151,12 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind) client->driver = &i2c_driver; snprintf(client->name, sizeof(client->name) - 1, "cs53l32a"); - cs53l32a_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); for (i = 1; i <= 7; i++) { u8 v = cs53l32a_read(client, i); - cs53l32a_dbg("Read Reg %d %02x\n", i, v); + v4l_dbg(1, client, "Read Reg %d %02x\n", i, v); } /* Set cs53l32a internal register for Adaptec 2010/2410 setup */ @@ -180,7 +174,7 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind) for (i = 1; i <= 7; i++) { u8 v = cs53l32a_read(client, i); - cs53l32a_dbg("Read Reg %d %02x\n", i, v); + v4l_dbg(1, client, "Read Reg %d %02x\n", i, v); } i2c_attach_client(client); @@ -190,11 +184,7 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind) static int cs53l32a_probe(struct i2c_adapter *adapter) { -#ifdef I2C_CLASS_TV_ANALOG if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif return i2c_probe(adapter, &addr_data, cs53l32a_attach); return 0; } diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index 740908f8027d..cb9a7981e408 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c @@ -23,11 +23,13 @@ #include "cx25840.h" -inline static int set_audclk_freq(struct i2c_client *client, - enum v4l2_audio_clock_freq freq) +static int set_audclk_freq(struct i2c_client *client, u32 freq) { struct cx25840_state *state = i2c_get_clientdata(client); + if (freq != 32000 && freq != 44100 && freq != 48000) + return -EINVAL; + /* assert soft reset */ cx25840_and_or(client, 0x810, ~0x1, 0x01); @@ -35,10 +37,9 @@ inline static int set_audclk_freq(struct i2c_client *client, /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ cx25840_write(client, 0x127, 0x50); - switch (state->audio_input) { - case AUDIO_TUNER: + if (state->aud_input != CX25840_AUDIO_SERIAL) { switch (freq) { - case V4L2_AUDCLK_32_KHZ: + case 32000: /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x0f040610); @@ -51,7 +52,7 @@ inline static int set_audclk_freq(struct i2c_client *client, cx25840_write4(client, 0x90c, 0x7ff70108); break; - case V4L2_AUDCLK_441_KHZ: + case 44100: /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x0f040910); @@ -64,7 +65,7 @@ inline static int set_audclk_freq(struct i2c_client *client, cx25840_write4(client, 0x90c, 0x596d0108); break; - case V4L2_AUDCLK_48_KHZ: + case 48000: /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x0f040a10); @@ -77,14 +78,9 @@ inline static int set_audclk_freq(struct i2c_client *client, cx25840_write4(client, 0x90c, 0xaa4f0108); break; } - break; - - case AUDIO_EXTERN_1: - case AUDIO_EXTERN_2: - case AUDIO_INTERN: - case AUDIO_RADIO: + } else { switch (freq) { - case V4L2_AUDCLK_32_KHZ: + case 32000: /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x0f04081e); @@ -103,7 +99,7 @@ inline static int set_audclk_freq(struct i2c_client *client, cx25840_write(client, 0x127, 0x54); break; - case V4L2_AUDCLK_441_KHZ: + case 44100: /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x0f040918); @@ -119,7 +115,7 @@ inline static int set_audclk_freq(struct i2c_client *client, cx25840_write4(client, 0x90c, 0x85730108); break; - case V4L2_AUDCLK_48_KHZ: + case 48000: /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x0f040a18); @@ -135,7 +131,6 @@ inline static int set_audclk_freq(struct i2c_client *client, cx25840_write4(client, 0x90c, 0x55550108); break; } - break; } /* deassert soft reset */ @@ -146,51 +141,36 @@ inline static int set_audclk_freq(struct i2c_client *client, return 0; } -static int set_input(struct i2c_client *client, int audio_input) +void cx25840_audio_set_path(struct i2c_client *client) { struct cx25840_state *state = i2c_get_clientdata(client); - cx25840_dbg("set audio input (%d)\n", audio_input); - /* stop microcontroller */ cx25840_and_or(client, 0x803, ~0x10, 0); /* Mute everything to prevent the PFFT! */ cx25840_write(client, 0x8d3, 0x1f); - switch (audio_input) { - case AUDIO_TUNER: - /* Set Path1 to Analog Demod Main Channel */ - cx25840_write4(client, 0x8d0, 0x7038061f); - - /* When the microcontroller detects the - * audio format, it will unmute the lines */ - cx25840_and_or(client, 0x803, ~0x10, 0x10); - break; - - case AUDIO_EXTERN_1: - case AUDIO_EXTERN_2: - case AUDIO_INTERN: - case AUDIO_RADIO: + if (state->aud_input == CX25840_AUDIO_SERIAL) { /* Set Path1 to Serial Audio Input */ cx25840_write4(client, 0x8d0, 0x12100101); /* The microcontroller should not be started for the * non-tuner inputs: autodetection is specific for * TV audio. */ - break; + } else { + /* Set Path1 to Analog Demod Main Channel */ + cx25840_write4(client, 0x8d0, 0x7038061f); - default: - cx25840_dbg("Invalid audio input selection %d\n", audio_input); - return -EINVAL; + /* When the microcontroller detects the + * audio format, it will unmute the lines */ + cx25840_and_or(client, 0x803, ~0x10, 0x10); } - state->audio_input = audio_input; - - return set_audclk_freq(client, state->audclk_freq); + set_audclk_freq(client, state->audclk_freq); } -inline static int get_volume(struct i2c_client *client) +static int get_volume(struct i2c_client *client) { /* Volume runs +18dB to -96dB in 1/2dB steps * change to fit the msp3400 -114dB to +12dB range */ @@ -201,7 +181,7 @@ inline static int get_volume(struct i2c_client *client) return vol << 9; } -inline static void set_volume(struct i2c_client *client, int volume) +static void set_volume(struct i2c_client *client, int volume) { /* First convert the volume to msp3400 values (0-127) */ int vol = volume >> 9; @@ -218,7 +198,7 @@ inline static void set_volume(struct i2c_client *client, int volume) cx25840_write(client, 0x8d4, 228 - (vol * 2)); } -inline static int get_bass(struct i2c_client *client) +static int get_bass(struct i2c_client *client) { /* bass is 49 steps +12dB to -12dB */ @@ -228,13 +208,13 @@ inline static int get_bass(struct i2c_client *client) return bass; } -inline static void set_bass(struct i2c_client *client, int bass) +static void set_bass(struct i2c_client *client, int bass) { /* PATH1_EQ_BASS_VOL */ cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff)); } -inline static int get_treble(struct i2c_client *client) +static int get_treble(struct i2c_client *client) { /* treble is 49 steps +12dB to -12dB */ @@ -244,13 +224,13 @@ inline static int get_treble(struct i2c_client *client) return treble; } -inline static void set_treble(struct i2c_client *client, int treble) +static void set_treble(struct i2c_client *client, int treble) { /* PATH1_EQ_TREBLE_VOL */ cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff)); } -inline static int get_balance(struct i2c_client *client) +static int get_balance(struct i2c_client *client) { /* balance is 7 bit, 0 to -96dB */ @@ -264,7 +244,7 @@ inline static int get_balance(struct i2c_client *client) return balance << 8; } -inline static void set_balance(struct i2c_client *client, int balance) +static void set_balance(struct i2c_client *client, int balance) { int bal = balance >> 8; if (bal > 0x80) { @@ -280,17 +260,17 @@ inline static void set_balance(struct i2c_client *client, int balance) } } -inline static int get_mute(struct i2c_client *client) +static int get_mute(struct i2c_client *client) { /* check SRC1_MUTE_EN */ return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0; } -inline static void set_mute(struct i2c_client *client, int mute) +static void set_mute(struct i2c_client *client, int mute) { struct cx25840_state *state = i2c_get_clientdata(client); - if (state->audio_input == AUDIO_TUNER) { + if (state->aud_input != CX25840_AUDIO_SERIAL) { /* Must turn off microcontroller in order to mute sound. * Not sure if this is the best method, but it does work. * If the microcontroller is running, then it will undo any @@ -314,10 +294,9 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) struct v4l2_control *ctrl = arg; switch (cmd) { - case AUDC_SET_INPUT: - return set_input(client, *(int *)arg); case VIDIOC_INT_AUDIO_CLOCK_FREQ: - return set_audclk_freq(client, *(enum v4l2_audio_clock_freq *)arg); + return set_audclk_freq(client, *(u32 *)arg); + case VIDIOC_G_CTRL: switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: @@ -339,6 +318,7 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) return -EINVAL; } break; + case VIDIOC_S_CTRL: switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: @@ -360,6 +340,7 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) return -EINVAL; } break; + default: return -EINVAL; } diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 3b09f46dddf6..d45237d508c4 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -43,11 +43,11 @@ MODULE_LICENSE("GPL"); static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; -int cx25840_debug = 0; +int debug = 0; -module_param(cx25840_debug, bool, 0644); +module_param(debug, bool, 0644); -MODULE_PARM_DESC(cx25840_debug, "Debugging messages [0=Off (default) 1=On]"); +MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]"); I2C_CLIENT_INSMOD; @@ -115,13 +115,13 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, /* ----------------------------------------------------------------------- */ -static int set_input(struct i2c_client *, enum cx25840_input); -static void input_change(struct i2c_client *); +static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, + enum cx25840_audio_input aud_input); static void log_status(struct i2c_client *client); /* ----------------------------------------------------------------------- */ -static inline void init_dll1(struct i2c_client *client) +static void init_dll1(struct i2c_client *client) { /* This is the Hauppauge sequence used to * initialize the Delay Lock Loop 1 (ADC DLL). */ @@ -135,7 +135,7 @@ static inline void init_dll1(struct i2c_client *client) cx25840_write(client, 0x15b, 0x10); } -static inline void init_dll2(struct i2c_client *client) +static void init_dll2(struct i2c_client *client) { /* This is the Hauppauge sequence used to * initialize the Delay Lock Loop 2 (ADC DLL). */ @@ -195,10 +195,8 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw) /* AC97 shift */ cx25840_write(client, 0x8cf, 0x0f); - /* (re)set video input */ - set_input(client, state->input); - /* (re)set audio input */ - cx25840_audio(client, AUDC_SET_INPUT, &state->audio_input); + /* (re)set input */ + set_input(client, state->vid_input, state->aud_input); /* start microcontroller */ cx25840_and_or(client, 0x803, ~0x10, 0x10); @@ -223,7 +221,7 @@ static void input_change(struct i2c_client *client) cx25840_write(client, 0x80b, 0x10); } else if (std & V4L2_STD_NTSC) { /* NTSC */ - if (state->cardtype == CARDTYPE_PVR150_WORKAROUND) { + if (state->pvr150_workaround) { /* Certain Hauppauge PVR150 models have a hardware bug that causes audio to drop out. For these models the audio standard must be set explicitly. @@ -259,72 +257,68 @@ static void input_change(struct i2c_client *client) } } -static int set_input(struct i2c_client *client, enum cx25840_input input) +static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, + enum cx25840_audio_input aud_input) { struct cx25840_state *state = i2c_get_clientdata(client); + u8 is_composite = (vid_input >= CX25840_COMPOSITE1 && + vid_input <= CX25840_COMPOSITE8); + u8 reg; - cx25840_dbg("decoder set input (%d)\n", input); + v4l_dbg(1, client, "decoder set video input %d, audio input %d\n", + vid_input, aud_input); - switch (input) { - case CX25840_TUNER: - cx25840_dbg("now setting Tuner input\n"); - - if (state->cardtype == CARDTYPE_PVR150 || - state->cardtype == CARDTYPE_PVR150_WORKAROUND) { - /* CH_SEL_ADC2=1 */ - cx25840_and_or(client, 0x102, ~0x2, 0x02); - } - - /* Video Input Control */ - if (state->cardtype == CARDTYPE_PG600) { - cx25840_write(client, 0x103, 0x11); - } else { - cx25840_write(client, 0x103, 0x46); - } - - /* INPUT_MODE=0 */ - cx25840_and_or(client, 0x401, ~0x6, 0x00); - break; - - case CX25840_COMPOSITE0: - case CX25840_COMPOSITE1: - cx25840_dbg("now setting Composite input\n"); + if (is_composite) { + reg = 0xf0 + (vid_input - CX25840_COMPOSITE1); + } else { + int luma = vid_input & 0xf0; + int chroma = vid_input & 0xf00; - /* Video Input Control */ - if (state->cardtype == CARDTYPE_PG600) { - cx25840_write(client, 0x103, 0x00); - } else { - cx25840_write(client, 0x103, 0x02); + if ((vid_input & ~0xff0) || + luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 || + chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) { + v4l_err(client, "0x%04x is not a valid video input!\n", vid_input); + return -EINVAL; } - - /* INPUT_MODE=0 */ - cx25840_and_or(client, 0x401, ~0x6, 0x00); - break; - - case CX25840_SVIDEO0: - case CX25840_SVIDEO1: - cx25840_dbg("now setting S-Video input\n"); - - /* CH_SEL_ADC2=0 */ - cx25840_and_or(client, 0x102, ~0x2, 0x00); - - /* Video Input Control */ - if (state->cardtype == CARDTYPE_PG600) { - cx25840_write(client, 0x103, 0x02); + reg = 0xf0 + ((luma - CX25840_SVIDEO_LUMA1) >> 4); + if (chroma >= CX25840_SVIDEO_CHROMA7) { + reg &= 0x3f; + reg |= (chroma - CX25840_SVIDEO_CHROMA7) >> 2; } else { - cx25840_write(client, 0x103, 0x10); + reg &= 0xcf; + reg |= (chroma - CX25840_SVIDEO_CHROMA4) >> 4; } + } - /* INPUT_MODE=1 */ - cx25840_and_or(client, 0x401, ~0x6, 0x02); + switch (aud_input) { + case CX25840_AUDIO_SERIAL: + /* do nothing, use serial audio input */ break; + case CX25840_AUDIO4: reg &= ~0x30; break; + case CX25840_AUDIO5: reg &= ~0x30; reg |= 0x10; break; + case CX25840_AUDIO6: reg &= ~0x30; reg |= 0x20; break; + case CX25840_AUDIO7: reg &= ~0xc0; break; + case CX25840_AUDIO8: reg &= ~0xc0; reg |= 0x40; break; default: - cx25840_err("%d is not a valid input!\n", input); + v4l_err(client, "0x%04x is not a valid audio input!\n", aud_input); return -EINVAL; } - state->input = input; + cx25840_write(client, 0x103, reg); + /* Set INPUT_MODE to Composite (0) or S-Video (1) */ + cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); + /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ + cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); + /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ + if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30) + cx25840_and_or(client, 0x102, ~0x4, 4); + else + cx25840_and_or(client, 0x102, ~0x4, 0); + + state->vid_input = vid_input; + state->aud_input = aud_input; + cx25840_audio_set_path(client); input_change(client); return 0; } @@ -395,23 +389,14 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) struct cx25840_state *state = i2c_get_clientdata(client); switch (ctrl->id) { - case CX25840_CID_CARDTYPE: - switch (ctrl->value) { - case CARDTYPE_PVR150: - case CARDTYPE_PVR150_WORKAROUND: - case CARDTYPE_PG600: - state->cardtype = ctrl->value; - break; - default: - return -ERANGE; - } - - set_input(client, state->input); + case CX25840_CID_ENABLE_PVR150_WORKAROUND: + state->pvr150_workaround = ctrl->value; + set_input(client, state->vid_input, state->aud_input); break; case V4L2_CID_BRIGHTNESS: if (ctrl->value < 0 || ctrl->value > 255) { - cx25840_err("invalid brightness setting %d\n", + v4l_err(client, "invalid brightness setting %d\n", ctrl->value); return -ERANGE; } @@ -421,7 +406,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) case V4L2_CID_CONTRAST: if (ctrl->value < 0 || ctrl->value > 127) { - cx25840_err("invalid contrast setting %d\n", + v4l_err(client, "invalid contrast setting %d\n", ctrl->value); return -ERANGE; } @@ -431,7 +416,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) case V4L2_CID_SATURATION: if (ctrl->value < 0 || ctrl->value > 127) { - cx25840_err("invalid saturation setting %d\n", + v4l_err(client, "invalid saturation setting %d\n", ctrl->value); return -ERANGE; } @@ -442,7 +427,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) case V4L2_CID_HUE: if (ctrl->value < -127 || ctrl->value > 127) { - cx25840_err("invalid hue setting %d\n", ctrl->value); + v4l_err(client, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } @@ -455,6 +440,9 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); + + default: + return -EINVAL; } return 0; @@ -465,11 +453,11 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) struct cx25840_state *state = i2c_get_clientdata(client); switch (ctrl->id) { - case CX25840_CID_CARDTYPE: - ctrl->value = state->cardtype; + case CX25840_CID_ENABLE_PVR150_WORKAROUND: + ctrl->value = state->pvr150_workaround; break; case V4L2_CID_BRIGHTNESS: - ctrl->value = cx25840_read(client, 0x414) + 128; + ctrl->value = (s8)cx25840_read(client, 0x414) + 128; break; case V4L2_CID_CONTRAST: ctrl->value = cx25840_read(client, 0x415) >> 1; @@ -478,7 +466,7 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) ctrl->value = cx25840_read(client, 0x420) >> 1; break; case V4L2_CID_HUE: - ctrl->value = cx25840_read(client, 0x422); + ctrl->value = (s8)cx25840_read(client, 0x422); break; case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_BASS: @@ -527,7 +515,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { - cx25840_err("%dx%d is not a valid size!\n", + v4l_err(client, "%dx%d is not a valid size!\n", pix->width, pix->height); return -ERANGE; } @@ -545,7 +533,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) else filter = 3; - cx25840_dbg("decoder set size %dx%d -> scale %ux%u\n", + v4l_dbg(1, client, "decoder set size %dx%d -> scale %ux%u\n", pix->width, pix->height, HSC, VSC); /* HSCALE=HSC */ @@ -574,17 +562,98 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) /* ----------------------------------------------------------------------- */ +static struct v4l2_queryctrl cx25840_qctrl[] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 128, + .flags = 0, + }, { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 64, + .flags = 0, + }, { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 64, + .flags = 0, + }, { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = -128, + .maximum = 127, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + .id = V4L2_CID_AUDIO_VOLUME, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Volume", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 58880, + .flags = 0, + }, { + .id = V4L2_CID_AUDIO_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Balance", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + .flags = 0, + }, { + .id = V4L2_CID_AUDIO_MUTE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .flags = 0, + }, { + .id = V4L2_CID_AUDIO_BASS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Bass", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + }, { + .id = V4L2_CID_AUDIO_TREBLE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Treble", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + }, +}; + +/* ----------------------------------------------------------------------- */ + static int cx25840_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct cx25840_state *state = i2c_get_clientdata(client); struct v4l2_tuner *vt = arg; - int result = 0; switch (cmd) { - case 0: - break; - #ifdef CONFIG_VIDEO_ADV_DEBUG /* ioctls to allow direct access to the * cx25840 registers for testing */ @@ -615,18 +684,16 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, return cx25840_vbi(client, cmd, arg); case VIDIOC_INT_AUDIO_CLOCK_FREQ: - case AUDC_SET_INPUT: - result = cx25840_audio(client, cmd, arg); - break; + return cx25840_audio(client, cmd, arg); case VIDIOC_STREAMON: - cx25840_dbg("enable output\n"); + v4l_dbg(1, client, "enable output\n"); cx25840_write(client, 0x115, 0x8c); cx25840_write(client, 0x116, 0x07); break; case VIDIOC_STREAMOFF: - cx25840_dbg("disable output\n"); + v4l_dbg(1, client, "disable output\n"); cx25840_write(client, 0x115, 0x00); cx25840_write(client, 0x116, 0x00); break; @@ -636,28 +703,58 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, break; case VIDIOC_G_CTRL: - result = get_v4lctrl(client, (struct v4l2_control *)arg); - break; + return get_v4lctrl(client, (struct v4l2_control *)arg); case VIDIOC_S_CTRL: - result = set_v4lctrl(client, (struct v4l2_control *)arg); - break; + return set_v4lctrl(client, (struct v4l2_control *)arg); + + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + int i; + + for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++) + if (qc->id && qc->id == cx25840_qctrl[i].id) { + memcpy(qc, &cx25840_qctrl[i], sizeof(*qc)); + return 0; + } + return -EINVAL; + } case VIDIOC_G_STD: *(v4l2_std_id *)arg = cx25840_get_v4lstd(client); break; case VIDIOC_S_STD: - result = set_v4lstd(client, *(v4l2_std_id *)arg); + state->radio = 0; + return set_v4lstd(client, *(v4l2_std_id *)arg); + + case AUDC_SET_RADIO: + state->radio = 1; break; case VIDIOC_G_INPUT: - *(int *)arg = state->input; + *(int *)arg = state->vid_input; break; case VIDIOC_S_INPUT: - result = set_input(client, *(int *)arg); + return set_input(client, *(enum cx25840_video_input *)arg, state->aud_input); + + case VIDIOC_S_AUDIO: + { + struct v4l2_audio *input = arg; + + return set_input(client, state->vid_input, input->index); + } + + case VIDIOC_G_AUDIO: + { + struct v4l2_audio *input = arg; + + memset(input, 0, sizeof(*input)); + input->index = state->aud_input; break; + } case VIDIOC_S_FREQUENCY: input_change(client); @@ -670,6 +767,9 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, u8 vpres = cx25840_read(client, 0x80a) & 0x10; int val = 0; + if (state->radio) + break; + vt->capability |= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; @@ -724,12 +824,10 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, break; case VIDIOC_G_FMT: - result = get_v4lfmt(client, (struct v4l2_format *)arg); - break; + return get_v4lfmt(client, (struct v4l2_format *)arg); case VIDIOC_S_FMT: - result = set_v4lfmt(client, (struct v4l2_format *)arg); - break; + return set_v4lfmt(client, (struct v4l2_format *)arg); case VIDIOC_INT_RESET: cx25840_initialize(client, 0); @@ -741,11 +839,10 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, break; default: - cx25840_err("invalid ioctl %x\n", cmd); return -EINVAL; } - return result; + return 0; } /* ----------------------------------------------------------------------- */ @@ -775,7 +872,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, client->driver = &i2c_driver_cx25840; snprintf(client->name, sizeof(client->name) - 1, "cx25840"); - cx25840_dbg("detecting cx25840 client on address 0x%x\n", address << 1); + v4l_dbg(1, client, "detecting cx25840 client on address 0x%x\n", address << 1); device_id = cx25840_read(client, 0x101) << 8; device_id |= cx25840_read(client, 0x100); @@ -783,12 +880,12 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, /* The high byte of the device ID should be * 0x84 if chip is present */ if ((device_id & 0xff00) != 0x8400) { - cx25840_dbg("cx25840 not found\n"); + v4l_dbg(1, client, "cx25840 not found\n"); kfree(client); return 0; } - cx25840_info("cx25%3x-2%x found @ 0x%x (%s)\n", + v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", (device_id & 0xfff0) >> 4, (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, address << 1, adapter->name); @@ -801,10 +898,10 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, i2c_set_clientdata(client, state); memset(state, 0, sizeof(struct cx25840_state)); - state->input = CX25840_TUNER; - state->audclk_freq = V4L2_AUDCLK_48_KHZ; - state->audio_input = AUDIO_TUNER; - state->cardtype = CARDTYPE_PVR150; + state->vid_input = CX25840_COMPOSITE7; + state->aud_input = CX25840_AUDIO8; + state->audclk_freq = 48000; + state->pvr150_workaround = 0; cx25840_initialize(client, 1); @@ -815,11 +912,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, static int cx25840_attach_adapter(struct i2c_adapter *adapter) { -#ifdef I2C_CLASS_TV_ANALOG if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif return i2c_probe(adapter, &addr_data, &cx25840_detect_client); return 0; } @@ -846,9 +939,7 @@ static struct i2c_driver i2c_driver_cx25840 = { .driver = { .name = "cx25840", }, - .id = I2C_DRIVERID_CX25840, - .attach_adapter = cx25840_attach_adapter, .detach_client = cx25840_detach_client, .command = cx25840_command, @@ -892,11 +983,13 @@ static void log_status(struct i2c_client *client) u8 pref_mode = cx25840_read(client, 0x809); u8 afc0 = cx25840_read(client, 0x80b); u8 mute_ctl = cx25840_read(client, 0x8d3); + int vid_input = state->vid_input; + int aud_input = state->aud_input; char *p; - cx25840_info("Video signal: %spresent\n", + v4l_info(client, "Video signal: %spresent\n", (microctrl_vidfmt & 0x10) ? "" : "not "); - cx25840_info("Detected format: %s\n", + v4l_info(client, "Detected format: %s\n", fmt_strs[gen_stat1 & 0xf]); switch (mod_det_stat0) { @@ -911,7 +1004,7 @@ static void log_status(struct i2c_client *client) case 0xfe: p = "forced mode"; break; default: p = "not defined"; } - cx25840_info("Detected audio mode: %s\n", p); + v4l_info(client, "Detected audio mode: %s\n", p); switch (mod_det_stat1) { case 0x00: p = "not defined"; break; @@ -937,10 +1030,10 @@ static void log_status(struct i2c_client *client) case 0xff: p = "no detected audio standard"; break; default: p = "not defined"; } - cx25840_info("Detected audio standard: %s\n", p); - cx25840_info("Audio muted: %s\n", + v4l_info(client, "Detected audio standard: %s\n", p); + v4l_info(client, "Audio muted: %s\n", (mute_ctl & 0x2) ? "yes" : "no"); - cx25840_info("Audio microcontroller: %s\n", + v4l_info(client, "Audio microcontroller: %s\n", (download_ctl & 0x10) ? "running" : "stopped"); switch (audio_config >> 4) { @@ -962,7 +1055,7 @@ static void log_status(struct i2c_client *client) case 0x0f: p = "automatic detection"; break; default: p = "undefined"; } - cx25840_info("Configured audio standard: %s\n", p); + v4l_info(client, "Configured audio standard: %s\n", p); if ((audio_config >> 4) < 0xF) { switch (audio_config & 0xF) { @@ -979,7 +1072,7 @@ static void log_status(struct i2c_client *client) case 0x0a: p = "SAP"; break; default: p = "undefined"; } - cx25840_info("Configured audio mode: %s\n", p); + v4l_info(client, "Configured audio mode: %s\n", p); } else { switch (audio_config & 0xF) { case 0x00: p = "BG"; break; @@ -995,30 +1088,27 @@ static void log_status(struct i2c_client *client) case 0x0f: p = "automatic standard and mode detection"; break; default: p = "undefined"; } - cx25840_info("Configured audio system: %s\n", p); + v4l_info(client, "Configured audio system: %s\n", p); } - cx25840_info("Specified standard: %s\n", + v4l_info(client, "Specified standard: %s\n", vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); - switch (state->input) { - case CX25840_COMPOSITE0: p = "Composite 0"; break; - case CX25840_COMPOSITE1: p = "Composite 1"; break; - case CX25840_SVIDEO0: p = "S-Video 0"; break; - case CX25840_SVIDEO1: p = "S-Video 1"; break; - case CX25840_TUNER: p = "Tuner"; break; + if (vid_input >= CX25840_COMPOSITE1 && + vid_input <= CX25840_COMPOSITE8) { + v4l_info(client, "Specified video input: Composite %d\n", + vid_input - CX25840_COMPOSITE1 + 1); + } else { + v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n", + (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); } - cx25840_info("Specified input: %s\n", p); - cx25840_info("Specified audio input: %s\n", - state->audio_input == 0 ? "Tuner" : "External"); - - switch (state->audclk_freq) { - case V4L2_AUDCLK_441_KHZ: p = "44.1 kHz"; break; - case V4L2_AUDCLK_48_KHZ: p = "48 kHz"; break; - case V4L2_AUDCLK_32_KHZ: p = "32 kHz"; break; - default: p = "undefined"; + if (aud_input) { + v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input); + } else { + v4l_info(client, "Specified audio input: External\n"); } - cx25840_info("Specified audioclock freq: %s\n", p); + + v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq); switch (pref_mode & 0xf) { case 0: p = "mono/language A"; break; @@ -1031,7 +1121,7 @@ static void log_status(struct i2c_client *client) case 7: p = "language AB"; break; default: p = "undefined"; } - cx25840_info("Preferred audio mode: %s\n", p); + v4l_info(client, "Preferred audio mode: %s\n", p); if ((audio_config & 0xf) == 0xf) { switch ((afc0 >> 3) & 0x3) { @@ -1040,7 +1130,7 @@ static void log_status(struct i2c_client *client) case 2: p = "autodetect"; break; default: p = "undefined"; } - cx25840_info("Selected 65 MHz format: %s\n", p); + v4l_info(client, "Selected 65 MHz format: %s\n", p); switch (afc0 & 0x7) { case 0: p = "chroma"; break; @@ -1050,6 +1140,6 @@ static void log_status(struct i2c_client *client) case 4: p = "autodetect"; break; default: p = "undefined"; } - cx25840_info("Selected 45 MHz format: %s\n", p); + v4l_info(client, "Selected 45 MHz format: %s\n", p); } } diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index df9d50a75542..e1a7823d82cd 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -15,7 +15,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - #include <linux/module.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -38,7 +37,7 @@ module_param(firmware, charp, 0444); MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]"); MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]"); -static inline void set_i2c_delay(struct i2c_client *client, int delay) +static void set_i2c_delay(struct i2c_client *client, int delay) { struct i2c_algo_bit_data *algod = client->adapter->algo_data; @@ -52,7 +51,7 @@ static inline void set_i2c_delay(struct i2c_client *client, int delay) } } -static inline void start_fw_load(struct i2c_client *client) +static void start_fw_load(struct i2c_client *client) { /* DL_ADDR_LB=0 DL_ADDR_HB=0 */ cx25840_write(client, 0x800, 0x00); @@ -66,7 +65,7 @@ static inline void start_fw_load(struct i2c_client *client) set_i2c_delay(client, 3); } -static inline void end_fw_load(struct i2c_client *client) +static void end_fw_load(struct i2c_client *client) { if (fastfw) set_i2c_delay(client, 10); @@ -77,38 +76,47 @@ static inline void end_fw_load(struct i2c_client *client) cx25840_write(client, 0x803, 0x03); } -static inline int check_fw_load(struct i2c_client *client, int size) +static int check_fw_load(struct i2c_client *client, int size) { /* DL_ADDR_HB DL_ADDR_LB */ int s = cx25840_read(client, 0x801) << 8; s |= cx25840_read(client, 0x800); if (size != s) { - cx25840_err("firmware %s load failed\n", firmware); + v4l_err(client, "firmware %s load failed\n", firmware); return -EINVAL; } - cx25840_info("loaded %s firmware (%d bytes)\n", firmware, size); + v4l_info(client, "loaded %s firmware (%d bytes)\n", firmware, size); return 0; } -static inline int fw_write(struct i2c_client *client, u8 * data, int size) +static int fw_write(struct i2c_client *client, u8 * data, int size) { - if (i2c_master_send(client, data, size) < size) { + int sent; + + if ((sent = i2c_master_send(client, data, size)) < size) { if (fastfw) { - cx25840_err("333MHz i2c firmware load failed\n"); + v4l_err(client, "333MHz i2c firmware load failed\n"); fastfw = 0; set_i2c_delay(client, 10); + if (sent > 2) { + u16 dl_addr = cx25840_read(client, 0x801) << 8; + dl_addr |= cx25840_read(client, 0x800); + dl_addr -= sent - 2; + cx25840_write(client, 0x801, dl_addr >> 8); + cx25840_write(client, 0x800, dl_addr & 0xff); + } + if (i2c_master_send(client, data, size) < size) { - cx25840_err - ("100MHz i2c firmware load failed\n"); + v4l_err(client, "100MHz i2c firmware load failed\n"); return -ENOSYS; } } else { - cx25840_err("firmware load i2c failure\n"); + v4l_err(client, "firmware load i2c failure\n"); return -ENOSYS; } @@ -124,7 +132,7 @@ int cx25840_loadfw(struct i2c_client *client) int size, send, retval; if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { - cx25840_err("unable to open firmware %s\n", firmware); + v4l_err(client, "unable to open firmware %s\n", firmware); return -EINVAL; } diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 13ba4e15ddea..04d879da7d63 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c @@ -22,7 +22,7 @@ #include "cx25840.h" -static inline int odd_parity(u8 c) +static int odd_parity(u8 c) { c ^= (c >> 4); c ^= (c >> 2); @@ -31,7 +31,7 @@ static inline int odd_parity(u8 c) return c & 1; } -static inline int decode_vps(u8 * dst, u8 * p) +static int decode_vps(u8 * dst, u8 * p) { static const u8 biphase_tbl[] = { 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h index 40aa59f9c525..fd22f30dcc1b 100644 --- a/drivers/media/video/cx25840/cx25840.h +++ b/drivers/media/video/cx25840/cx25840.h @@ -24,48 +24,60 @@ #include <linux/videodev2.h> #include <linux/i2c.h> -extern int cx25840_debug; - -#define cx25840_dbg(fmt, arg...) do { if (cx25840_debug) \ - printk(KERN_INFO "%s debug %d-%04x: " fmt, \ - client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) - -#define cx25840_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) - -#define cx25840_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) - -#define CX25840_CID_CARDTYPE (V4L2_CID_PRIVATE_BASE+0) - -/* The CARDTYPE_PVR150_WORKAROUND cardtype activates a workaround for a - hardware bug that is present in PVR150 (and possible PVR500) cards that - have certain NTSC tuners (tveeprom model numbers 85, 99 and 112). The +/* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is + present in Hauppauge PVR-150 (and possibly PVR-500) cards that have + certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The audio autodetect fails on some channels for these models and the workaround is to select the audio standard explicitly. Many thanks to Hauppauge for providing this information. */ -enum cx25840_cardtype { - CARDTYPE_PVR150, - CARDTYPE_PG600, - CARDTYPE_PVR150_WORKAROUND, +#define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0) + +enum cx25840_video_input { + /* Composite video inputs In1-In8 */ + CX25840_COMPOSITE1 = 1, + CX25840_COMPOSITE2, + CX25840_COMPOSITE3, + CX25840_COMPOSITE4, + CX25840_COMPOSITE5, + CX25840_COMPOSITE6, + CX25840_COMPOSITE7, + CX25840_COMPOSITE8, + + /* S-Video inputs consist of one luma input (In1-In4) ORed with one + chroma input (In5-In8) */ + CX25840_SVIDEO_LUMA1 = 0x10, + CX25840_SVIDEO_LUMA2 = 0x20, + CX25840_SVIDEO_LUMA3 = 0x30, + CX25840_SVIDEO_LUMA4 = 0x40, + CX25840_SVIDEO_CHROMA4 = 0x400, + CX25840_SVIDEO_CHROMA5 = 0x500, + CX25840_SVIDEO_CHROMA6 = 0x600, + CX25840_SVIDEO_CHROMA7 = 0x700, + CX25840_SVIDEO_CHROMA8 = 0x800, + + /* S-Video aliases for common luma/chroma combinations */ + CX25840_SVIDEO1 = 0x510, + CX25840_SVIDEO2 = 0x620, + CX25840_SVIDEO3 = 0x730, + CX25840_SVIDEO4 = 0x840, }; -enum cx25840_input { - CX25840_TUNER, - CX25840_COMPOSITE0, - CX25840_COMPOSITE1, - CX25840_SVIDEO0, - CX25840_SVIDEO1 +enum cx25840_audio_input { + /* Audio inputs: serial or In4-In8 */ + CX25840_AUDIO_SERIAL, + CX25840_AUDIO4 = 4, + CX25840_AUDIO5, + CX25840_AUDIO6, + CX25840_AUDIO7, + CX25840_AUDIO8, }; struct cx25840_state { - enum cx25840_cardtype cardtype; - enum cx25840_input input; - int audio_input; - enum v4l2_audio_clock_freq audclk_freq; + int pvr150_workaround; + int radio; + enum cx25840_video_input vid_input; + enum cx25840_audio_input aud_input; + u32 audclk_freq; }; /* ----------------------------------------------------------------------- */ @@ -84,6 +96,7 @@ int cx25840_loadfw(struct i2c_client *client); /* ----------------------------------------------------------------------- */ /* cx25850-audio.c */ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg); +void cx25840_audio_set_path(struct i2c_client *client); /* ----------------------------------------------------------------------- */ /* cx25850-vbi.c */ diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 85ba4106dc79..76fcb4e995c9 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -29,6 +29,21 @@ config VIDEO_CX88_DVB You must also select one or more DVB/ATSC demodulators. If you are unsure which you need, choose all of them. +config VIDEO_CX88_ALSA + tristate "ALSA DMA audio support" + depends on VIDEO_CX88 && SND + select SND_PCM_OSS + ---help--- + This is a video4linux driver for direct (DMA) audio on + Conexant 2388x based TV cards. + It only works with boards with function 01 enabled. + To check if your board supports, use lspci -n. + If supported, you should see 1471:8801 or 1471:8811 + PCI device. + + To compile this driver as a module, choose M here: the + module will be called cx88-alsa. + config VIDEO_CX88_DVB_ALL_FRONTENDS bool "Build all supported frontends for cx2388x based TV cards" default y @@ -38,6 +53,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS select DVB_CX22702 select DVB_LGDT330X select DVB_NXT200X + select DVB_CX24123 ---help--- This builds cx88-dvb with all currently supported frontend demodulators. If you wish to tweak your configuration, and @@ -89,3 +105,12 @@ config VIDEO_CX88_DVB_NXT200X ---help--- This adds ATSC 8VSB and QAM64/256 support for cards based on the Connexant 2388x chip and the NXT2002/NXT2004 demodulator. + +config VIDEO_CX88_DVB_CX24123 + bool "Conexant CX24123 DVB-S Support" + default y + depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS + select DVB_CX24123 + ---help--- + This adds DVB-S support for cards based on the + Connexant 2388x chip and the CX24123 demodulator. diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 54401b02b7ce..e4b2134fe567 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -4,7 +4,7 @@ cx8800-objs := cx88-video.o cx88-vbi.o cx8802-objs := cx88-mpeg.o obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o -obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o +obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o EXTRA_CFLAGS += -I$(src)/.. EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core @@ -16,5 +16,7 @@ extra-cflags-$(CONFIG_DVB_OR51132) += -DHAVE_OR51132=1 extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1 extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 +extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1 +extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1 EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c new file mode 100644 index 000000000000..7695b521eb35 --- /dev/null +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -0,0 +1,848 @@ +/* + * + * Support for audio capture + * PCI function #1 of the cx2388x. + * + * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> + * (c) 2005 Mauro Carvalho Chehab <mchehab@brturbo.com.br> + * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> + * Based on dummy.c by Jaroslav Kysela <perex@suse.cz> + * + * 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/init.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <asm/delay.h> +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/control.h> +#include <sound/initval.h> + +#include "cx88.h" +#include "cx88-reg.h" + +#define dprintk(level,fmt, arg...) if (debug >= level) \ + printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg) + +#define dprintk_core(level,fmt, arg...) if (debug >= level) \ + printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg) + + +/**************************************************************************** + Data type declarations - Can be moded to a header file later + ****************************************************************************/ + +/* These can be replaced after done */ +#define MIXER_ADDR_LAST MAX_CX88_INPUT + +struct cx88_audio_dev { + struct cx88_core *core; + struct cx88_dmaqueue q; + + /* pci i/o */ + struct pci_dev *pci; + unsigned char pci_rev,pci_lat; + + /* audio controls */ + int irq; + + snd_card_t *card; + + spinlock_t reg_lock; + + unsigned int dma_size; + unsigned int period_size; + unsigned int num_periods; + + struct videobuf_dmabuf dma_risc; + + int mixer_volume[MIXER_ADDR_LAST+1][2]; + int capture_source[MIXER_ADDR_LAST+1][2]; + + long int read_count; + long int read_offset; + + struct cx88_buffer *buf; + + long opened; + snd_pcm_substream_t *substream; + +}; +typedef struct cx88_audio_dev snd_cx88_card_t; + + + +/**************************************************************************** + Module global static vars + ****************************************************************************/ + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ +static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; +static snd_card_t *snd_cx88_cards[SNDRV_CARDS]; + +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s)."); + + +/**************************************************************************** + Module macros + ****************************************************************************/ + +MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); +MODULE_AUTHOR("Ricardo Cerqueira"); +MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@brturbo.com.br>"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{Conexant,23881}," + "{{Conexant,23882}," + "{{Conexant,23883}"); +static unsigned int debug = 0; +module_param(debug,int,0644); +MODULE_PARM_DESC(debug,"enable debug messages"); + +/**************************************************************************** + Module specific funtions + ****************************************************************************/ + +/* + * BOARD Specific: Sets audio DMA + */ + +int _cx88_start_audio_dma(snd_cx88_card_t *chip) +{ + struct cx88_buffer *buf = chip->buf; + struct cx88_core *core=chip->core; + struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; + + + dprintk(1, "Starting audio DMA for %i bytes/line and %i (%i) lines at address %08x\n",buf->bpl, chip->num_periods, audio_ch->fifo_size / buf->bpl, audio_ch->fifo_start); + + /* setup fifo + format - out channel */ + cx88_sram_channel_setup(chip->core, &cx88_sram_channels[SRAM_CH25], + buf->bpl, buf->risc.dma); + + /* sets bpl size */ + cx_write(MO_AUDD_LNGTH, buf->bpl); + + /* reset counter */ + cx_write(MO_AUDD_GPCNTRL,GP_COUNT_CONTROL_RESET); + + dprintk(1,"Enabling IRQ, setting mask from 0x%x to 0x%x\n",chip->core->pci_irqmask,(chip->core->pci_irqmask | 0x02)); + /* enable irqs */ + cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | 0x02); + + + /* Enables corresponding bits at AUD_INT_STAT */ + cx_write(MO_AUD_INTMSK, + (1<<16)| + (1<<12)| + (1<<4)| + (1<<0) + ); + + /* start dma */ + cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ + cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */ + + if (debug) + cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); + + return 0; +} + +/* + * BOARD Specific: Resets audio DMA + */ +int _cx88_stop_audio_dma(snd_cx88_card_t *chip) +{ + struct cx88_core *core=chip->core; + dprintk(1, "Stopping audio DMA\n"); + + /* stop dma */ + cx_clear(MO_AUD_DMACNTRL, 0x11); + + /* disable irqs */ + cx_clear(MO_PCI_INTMSK, 0x02); + cx_clear(MO_AUD_INTMSK, + (1<<16)| + (1<<12)| + (1<<4)| + (1<<0) + ); + + if (debug) + cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); + + return 0; +} + +#define MAX_IRQ_LOOP 10 + +/* + * BOARD Specific: IRQ dma bits + */ +static char *cx88_aud_irqs[32] = { + "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ + NULL, /* reserved */ + "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ + NULL, /* reserved */ + "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ + NULL, /* reserved */ + "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ + NULL, /* reserved */ + "opc_err", "par_err", "rip_err", /* 16-18 */ + "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ +}; + +/* + * BOARD Specific: Threats IRQ audio specific calls + */ +static void cx8801_aud_irq(snd_cx88_card_t *chip) +{ + struct cx88_core *core = chip->core; + u32 status, mask; + u32 count; + + status = cx_read(MO_AUD_INTSTAT); + mask = cx_read(MO_AUD_INTMSK); + if (0 == (status & mask)) { + spin_unlock(&chip->reg_lock); + return; + } + cx_write(MO_AUD_INTSTAT, status); + if (debug > 1 || (status & mask & ~0xff)) + cx88_print_irqbits(core->name, "irq aud", + cx88_aud_irqs, status, mask); + /* risc op code error */ + if (status & (1 << 16)) { + printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name); + cx_clear(MO_AUD_DMACNTRL, 0x11); + cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); + } + + /* risc1 downstream */ + if (status & 0x01) { + spin_lock(&chip->reg_lock); + count = cx_read(MO_AUDD_GPCNT); + spin_unlock(&chip->reg_lock); + if (chip->read_count == 0) + chip->read_count += chip->dma_size; + } + + if (chip->read_count >= chip->period_size) { + dprintk(2, "Elapsing period\n"); + snd_pcm_period_elapsed(chip->substream); + } + + dprintk(3,"Leaving audio IRQ handler...\n"); + + /* FIXME: Any other status should deserve a special handling? */ +} + +/* + * BOARD Specific: Handles IRQ calls + */ +static irqreturn_t cx8801_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + snd_cx88_card_t *chip = dev_id; + struct cx88_core *core = chip->core; + u32 status; + int loop, handled = 0; + + for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { + status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x02); + if (0 == status) + goto out; + dprintk( 3, "cx8801_irq\n" ); + dprintk( 3, " loop: %d/%d\n", loop, MAX_IRQ_LOOP ); + dprintk( 3, " status: %d\n", status ); + handled = 1; + cx_write(MO_PCI_INTSTAT, status); + + if (status & 0x02) + { + dprintk( 2, " ALSA IRQ handling\n" ); + cx8801_aud_irq(chip); + } + }; + + if (MAX_IRQ_LOOP == loop) { + dprintk( 0, "clearing mask\n" ); + dprintk(1,"%s/0: irq loop -- clearing mask\n", + core->name); + cx_clear(MO_PCI_INTMSK,0x02); + } + + out: + return IRQ_RETVAL(handled); +} + + +static int dsp_buffer_free(snd_cx88_card_t *chip) +{ + BUG_ON(!chip->dma_size); + + dprintk(2,"Freeing buffer\n"); + videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc); + videobuf_dma_free(&chip->dma_risc); + btcx_riscmem_free(chip->pci,&chip->buf->risc); + kfree(chip->buf); + + chip->dma_size = 0; + + return 0; +} + +/**************************************************************************** + ALSA PCM Interface + ****************************************************************************/ + +/* + * Digital hardware definition + */ +static snd_pcm_hardware_t snd_cx88_digital_hw = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = (2*2048), + .period_bytes_min = 256, + .period_bytes_max = 2048, + .periods_min = 2, + .periods_max = 16, +}; + +/* + * audio pcm capture runtime free + */ +static void snd_card_cx88_runtime_free(snd_pcm_runtime_t *runtime) +{ +} +/* + * audio pcm capture open callback + */ +static int snd_cx88_pcm_open(snd_pcm_substream_t *substream) +{ + snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; + int err; + + if (test_and_set_bit(0, &chip->opened)) + return -EBUSY; + + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) + goto _error; + + chip->substream = substream; + + chip->read_count = 0; + chip->read_offset = 0; + + runtime->private_free = snd_card_cx88_runtime_free; + runtime->hw = snd_cx88_digital_hw; + + return 0; +_error: + dprintk(1,"Error opening PCM!\n"); + clear_bit(0, &chip->opened); + smp_mb__after_clear_bit(); + return err; +} + +/* + * audio close callback + */ +static int snd_cx88_close(snd_pcm_substream_t *substream) +{ + snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); + + clear_bit(0, &chip->opened); + smp_mb__after_clear_bit(); + + return 0; +} + +/* + * hw_params callback + */ +static int snd_cx88_hw_params(snd_pcm_substream_t * substream, + snd_pcm_hw_params_t * hw_params) +{ + snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); + struct cx88_buffer *buf; + + if (substream->runtime->dma_area) { + dsp_buffer_free(chip); + substream->runtime->dma_area = NULL; + } + + + chip->period_size = params_period_bytes(hw_params); + chip->num_periods = params_periods(hw_params); + chip->dma_size = chip->period_size * params_periods(hw_params); + + BUG_ON(!chip->dma_size); + + dprintk(1,"Setting buffer\n"); + + buf = kmalloc(sizeof(*buf),GFP_KERNEL); + if (NULL == buf) + return -ENOMEM; + memset(buf,0,sizeof(*buf)); + + + buf->vb.memory = V4L2_MEMORY_MMAP; + buf->vb.width = chip->period_size; + buf->vb.height = chip->num_periods; + buf->vb.size = chip->dma_size; + buf->vb.field = V4L2_FIELD_NONE; + + videobuf_dma_init(&buf->vb.dma); + videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE, + (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); + + videobuf_dma_pci_map(chip->pci,&buf->vb.dma); + + + cx88_risc_databuffer(chip->pci, &buf->risc, + buf->vb.dma.sglist, + buf->vb.width, buf->vb.height); + + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + buf->vb.state = STATE_PREPARED; + + buf->bpl = chip->period_size; + chip->buf = buf; + chip->dma_risc = buf->vb.dma; + + dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages); + substream->runtime->dma_area = chip->dma_risc.vmalloc; + return 0; +} + +/* + * hw free callback + */ +static int snd_cx88_hw_free(snd_pcm_substream_t * substream) +{ + + snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); + + if (substream->runtime->dma_area) { + dsp_buffer_free(chip); + substream->runtime->dma_area = NULL; + } + + return 0; +} + +/* + * prepare callback + */ +static int snd_cx88_prepare(snd_pcm_substream_t *substream) +{ + return 0; +} + + +/* + * trigger callback + */ +static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd) +{ + snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); + int err; + + spin_lock(&chip->reg_lock); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + err=_cx88_start_audio_dma(chip); + break; + case SNDRV_PCM_TRIGGER_STOP: + err=_cx88_stop_audio_dma(chip); + break; + default: + err=-EINVAL; + break; + } + + spin_unlock(&chip->reg_lock); + + return err; +} + +/* + * pointer callback + */ +static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream) +{ + snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; + + if (chip->read_count) { + chip->read_count -= snd_pcm_lib_period_bytes(substream); + chip->read_offset += snd_pcm_lib_period_bytes(substream); + if (chip->read_offset == chip->dma_size) + chip->read_offset = 0; + } + + dprintk(2, "Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count); + return bytes_to_frames(runtime, chip->read_offset); + +} + +/* + * operators + */ +static snd_pcm_ops_t snd_cx88_pcm_ops = { + .open = snd_cx88_pcm_open, + .close = snd_cx88_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_cx88_hw_params, + .hw_free = snd_cx88_hw_free, + .prepare = snd_cx88_prepare, + .trigger = snd_cx88_card_trigger, + .pointer = snd_cx88_pointer, +}; + +/* + * create a PCM device + */ +static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name) +{ + int err; + snd_pcm_t *pcm; + + err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); + if (err < 0) + return err; + pcm->private_data = chip; + strcpy(pcm->name, name); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops); + + return 0; +} + +/**************************************************************************** + CONTROL INTERFACE + ****************************************************************************/ +static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info) +{ + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + info->count = 1; + info->value.integer.min = 0; + info->value.integer.max = 0x3f; + + return 0; +} + +/* OK - TODO: test it */ +static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +{ + snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); + struct cx88_core *core=chip->core; + + value->value.integer.value[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); + + return 0; +} + +/* OK - TODO: test it */ +static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +{ + snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); + struct cx88_core *core=chip->core; + int v; + u32 old_control; + + spin_lock_irq(&chip->reg_lock); + old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); + v = 0x3f - (value->value.integer.value[0] & 0x3f); + cx_andor(AUD_VOL_CTL, 0x3f, v); + spin_unlock_irq(&chip->reg_lock); + + return v != old_control; +} + +static snd_kcontrol_new_t snd_cx88_capture_volume = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Volume", + .info = snd_cx88_capture_volume_info, + .get = snd_cx88_capture_volume_get, + .put = snd_cx88_capture_volume_put, +}; + + +/**************************************************************************** + Basic Flow for Sound Devices + ****************************************************************************/ + +/* + * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio + * Only boards with eeprom and byte 1 at eeprom=1 have it + */ + +struct pci_device_id cx88_audio_pci_tbl[] = { + {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, + {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, + {0, } +}; +MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl); + +/* + * Chip-specific destructor + */ + +static int snd_cx88_free(snd_cx88_card_t *chip) +{ + + if (chip->irq >= 0){ + synchronize_irq(chip->irq); + free_irq(chip->irq, chip); + } + + cx88_core_put(chip->core,chip->pci); + + pci_disable_device(chip->pci); + return 0; +} + +/* + * Component Destructor + */ +static void snd_cx88_dev_free(snd_card_t * card) +{ + snd_cx88_card_t *chip = card->private_data; + + snd_cx88_free(chip); +} + + +/* + * Alsa Constructor - Component probe + */ + +static int devno=0; +static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, + snd_cx88_card_t **rchip) +{ + snd_cx88_card_t *chip; + struct cx88_core *core; + int err; + + *rchip = NULL; + + err = pci_enable_device(pci); + if (err < 0) + return err; + + pci_set_master(pci); + + chip = (snd_cx88_card_t *) card->private_data; + + core = cx88_core_get(pci); + + if (!pci_dma_supported(pci,0xffffffff)) { + dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name); + err = -EIO; + cx88_core_put(core,pci); + return err; + } + + + /* pci init */ + chip->card = card; + chip->pci = pci; + chip->irq = -1; + spin_lock_init(&chip->reg_lock); + + cx88_reset(core); + if (NULL == core) { + err = -EINVAL; + kfree (chip); + return err; + } + chip->core = core; + + /* get irq */ + err = request_irq(chip->pci->irq, cx8801_irq, + SA_SHIRQ | SA_INTERRUPT, chip->core->name, chip); + if (err < 0) { + dprintk(0, "%s: can't get IRQ %d\n", + chip->core->name, chip->pci->irq); + return err; + } + + /* print pci info */ + pci_read_config_byte(pci, PCI_CLASS_REVISION, &chip->pci_rev); + pci_read_config_byte(pci, PCI_LATENCY_TIMER, &chip->pci_lat); + + dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, " + "latency: %d, mmio: 0x%lx\n", core->name, devno, + pci_name(pci), chip->pci_rev, pci->irq, + chip->pci_lat,pci_resource_start(pci,0)); + + chip->irq = pci->irq; + synchronize_irq(chip->irq); + + snd_card_set_dev(card, &pci->dev); + + *rchip = chip; + + return 0; +} + +static int __devinit cx88_audio_initdev(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + snd_card_t *card; + snd_cx88_card_t *chip; + int err; + + if (devno >= SNDRV_CARDS) + return (-ENODEV); + + if (!enable[devno]) { + ++devno; + return (-ENOENT); + } + + card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t)); + if (!card) + return (-ENOMEM); + + card->private_free = snd_cx88_dev_free; + + err = snd_cx88_create(card, pci, &chip); + if (err < 0) + return (err); + + err = snd_cx88_pcm(chip, 0, "CX88 Digital"); + + if (err < 0) { + snd_card_free(card); + return (err); + } + + err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip)); + if (err < 0) { + snd_card_free(card); + return (err); + } + + strcpy (card->driver, "CX88x"); + sprintf(card->shortname, "Conexant CX%x", pci->device); + sprintf(card->longname, "%s at %#lx", + card->shortname, pci_resource_start(pci, 0)); + strcpy (card->mixername, "CX88"); + + dprintk (0, "%s/%i: ALSA support for cx2388x boards\n", + card->driver,devno); + + err = snd_card_register(card); + if (err < 0) { + snd_card_free(card); + return (err); + } + snd_cx88_cards[devno] = card; + + pci_set_drvdata(pci,card); + + devno++; + return 0; +} +/* + * ALSA destructor + */ +static void __devexit cx88_audio_finidev(struct pci_dev *pci) +{ + struct cx88_audio_dev *card = pci_get_drvdata(pci); + + snd_card_free((void *)card); + + pci_set_drvdata(pci, NULL); + + devno--; +} + +/* + * PCI driver definition + */ + +static struct pci_driver cx88_audio_pci_driver = { + .name = "cx88_audio", + .id_table = cx88_audio_pci_tbl, + .probe = cx88_audio_initdev, + .remove = cx88_audio_finidev, + SND_PCI_PM_CALLBACKS +}; + +/**************************************************************************** + LINUX MODULE INIT + ****************************************************************************/ + +/* + * module init + */ +static int cx88_audio_init(void) +{ + printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n", + (CX88_VERSION_CODE >> 16) & 0xff, + (CX88_VERSION_CODE >> 8) & 0xff, + CX88_VERSION_CODE & 0xff); +#ifdef SNAPSHOT + printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", + SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); +#endif + return pci_register_driver(&cx88_audio_pci_driver); +} + +/* + * module remove + */ +static void cx88_audio_fini(void) +{ + + pci_unregister_driver(&cx88_audio_pci_driver); +} + +module_init(cx88_audio_init); +module_exit(cx88_audio_fini); + +/* ----------------------------------------------------------- */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 74e57a53116f..a49062119313 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -32,10 +32,10 @@ #include <linux/firmware.h> #include "cx88.h" +#include <media/v4l2-common.h> MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards"); -MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>"); -MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); +MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_LICENSE("GPL"); static unsigned int mpegbufs = 32; @@ -1375,7 +1375,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, struct cx88_core *core = dev->core; if (debug > 1) - cx88_print_ioctl(core->name,cmd); + v4l_print_ioctl(core->name,cmd); switch (cmd) { @@ -1689,6 +1689,18 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params)); memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params)); + if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) { + + if (core->tuner_formats & V4L2_STD_525_60) { + dev->height = 480; + dev->params.vi_frame_rate = 30; + } else { + dev->height = 576; + dev->params.vi_frame_rate = 25; + } + + } + err = cx8802_init_common(dev); if (0 != err) goto fail_free; diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 951709aa88ba..a76d54503b6f 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -611,12 +611,12 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0xed12, /* internal decoder */ + .gpio0 = 0xed1a, .gpio2 = 0x00ff, },{ .type = CX88_VMUX_DEBUG, .vmux = 0, - .gpio0 = 0xff01, /* mono from tuner chip */ + .gpio0 = 0xff01, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, @@ -708,7 +708,7 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { .name = "DViCO FusionHDTV 3 Gold-T", - .tuner_type = TUNER_THOMSON_DTT7611, + .tuner_type = TUNER_THOMSON_DTT761X, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -897,6 +897,158 @@ struct cx88_board cx88_boards[] = { .gpio3 = 0x0000, }}, }, + [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = { + .name = "Hauppauge Nova-S-Plus DVB-S", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + }}, + .dvb = 1, + }, + [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = { + .name = "Hauppauge Nova-SE2 DVB-S", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, + .dvb = 1, + }, + [CX88_BOARD_KWORLD_DVBS_100] = { + .name = "KWorld DVB-S 100", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + }}, + .dvb = 1, + }, + [CX88_BOARD_HAUPPAUGE_HVR1100] = { + .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + }}, + /* fixme: Add radio support */ + .dvb = 1, + }, + [CX88_BOARD_HAUPPAUGE_HVR1100LP] = { + .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + }}, + /* fixme: Add radio support */ + .dvb = 1, + }, + [CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = { + .name = "digitalnow DNTV Live! DVB-T Pro", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | + TDA9887_PORT2_ACTIVE, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0xf80808, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0xf80808, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0xf80808, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0xf80808, + }, + .dvb = 1, + }, + [CX88_BOARD_KWORLD_DVB_T_CX22702] = { + /* Kworld V-stream Xpert DVB-T with Thomson tuner */ + /* DTT 7579 Conexant CX22702-19 Conexant CX2388x */ + /* Manenti Marco <marco_manenti@colman.it> */ + .name = "KWorld/VStream XPert DVB-T with cx22702", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0700, + .gpio2 = 0x0101, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0700, + .gpio2 = 0x0101, + }}, + .dvb = 1, + }, + [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = { + .name = "DViCO FusionHDTV DVB-T Dual Digital", + .tuner_type = TUNER_ABSENT, /* No analog tuner */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000027df, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000027df, + }}, + .dvb = 1, + }, + }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1044,6 +1196,54 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1461, .subdevice = 0x000a, .card = CX88_BOARD_AVERTV_303, + },{ + .subvendor = 0x0070, + .subdevice = 0x9200, + .card = CX88_BOARD_HAUPPAUGE_NOVASE2_S1, + },{ + .subvendor = 0x0070, + .subdevice = 0x9201, + .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1, + },{ + .subvendor = 0x0070, + .subdevice = 0x9202, + .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1, + },{ + .subvendor = 0x17de, + .subdevice = 0x08b2, + .card = CX88_BOARD_KWORLD_DVBS_100, + },{ + .subvendor = 0x0070, + .subdevice = 0x9400, + .card = CX88_BOARD_HAUPPAUGE_HVR1100, + },{ + .subvendor = 0x0070, + .subdevice = 0x9402, + .card = CX88_BOARD_HAUPPAUGE_HVR1100, + },{ + .subvendor = 0x0070, + .subdevice = 0x9800, + .card = CX88_BOARD_HAUPPAUGE_HVR1100LP, + },{ + .subvendor = 0x0070, + .subdevice = 0x9802, + .card = CX88_BOARD_HAUPPAUGE_HVR1100LP, + },{ + .subvendor = 0x0070, + .subdevice = 0x9001, + .card = CX88_BOARD_HAUPPAUGE_DVB_T1, + },{ + .subvendor = 0x1822, + .subdevice = 0x0025, + .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO, + },{ + .subvendor = 0x17de, + .subdevice = 0x08a1, + .card = CX88_BOARD_KWORLD_DVB_T_CX22702, + },{ + .subvendor = 0x18ac, + .subdevice = 0xdb50, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); @@ -1075,20 +1275,19 @@ static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) core->name, core->tuner_type, eeprom_data[0]); } - -/* ----------------------------------------------------------------------- */ - static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) { struct tveeprom tv; tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data); core->tuner_type = tv.tuner_type; + core->tuner_formats = tv.tuner_formats; core->has_radio = tv.has_radio; /* Make sure we support the board model */ switch (tv.model) { + case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ case 90002: /* Nova-T-PCI (9002) */ case 92001: /* Nova-S-Plus (Video and IR) */ case 92002: /* Nova-S-Plus (Video and IR) */ @@ -1096,7 +1295,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) case 90500: /* Nova-T-PCI (oem) */ case 90501: /* Nova-T-PCI (oem/IR) */ case 92000: /* Nova-SE2 (OEM, No Video or IR) */ - + case 94009: /* WinTV-HVR1100 (Video and IR Retail) */ + case 94501: /* WinTV-HVR1100 (Video and IR OEM) */ + case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */ /* known */ break; default: @@ -1211,12 +1412,21 @@ void cx88_card_setup(struct cx88_core *core) if (0 == core->i2c_rc) leadtek_eeprom(core,eeprom); break; + case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: + case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: case CX88_BOARD_HAUPPAUGE_DVB_T1: + case CX88_BOARD_HAUPPAUGE_HVR1100: + case CX88_BOARD_HAUPPAUGE_HVR1100LP: if (0 == core->i2c_rc) hauppauge_eeprom(core,eeprom); break; + case CX88_BOARD_KWORLD_DVBS_100: + cx_write(MO_GP0_IO, 0x000007f8); + cx_write(MO_GP1_IO, 0x00000001); + break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: /* GPIO0:0 is hooked to mt352 reset pin */ cx_set(MO_GP0_IO, 0x00000101); cx_clear(MO_GP0_IO, 0x00000001); @@ -1232,6 +1442,9 @@ void cx88_card_setup(struct cx88_core *core) cx_clear(MO_GP0_IO, 0x00000007); cx_set(MO_GP2_IO, 0x00000101); break; + case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: + cx_write(MO_GP0_IO, 0x00080808); + break; case CX88_BOARD_ATI_HDTVWONDER: if (0 == core->i2c_rc) { /* enable tuner */ diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index bb6eb54e19ce..9975be1aca38 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -34,6 +34,7 @@ #include <linux/videodev2.h> #include "cx88.h" +#include <media/v4l2-common.h> MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); @@ -76,60 +77,6 @@ static unsigned int cx88_devcount; static LIST_HEAD(cx88_devlist); static DECLARE_MUTEX(devlist); -/* ------------------------------------------------------------------ */ -/* debug help functions */ - -static const char *v4l1_ioctls[] = { - "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT", - "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ", - "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT", - "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", - "SMICROCODE", "GVBIFMT", "SVBIFMT" }; -#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) - -static const char *v4l2_ioctls[] = { - "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT", - "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF", - "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON", - "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD", - "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER", - "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL", - "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43", - "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT", - "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR", - "S_MODULATOR" -}; -#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) - -void cx88_print_ioctl(char *name, unsigned int cmd) -{ - char *dir; - - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: dir = "--"; break; - case _IOC_READ: dir = "r-"; break; - case _IOC_WRITE: dir = "-w"; break; - case _IOC_READ | _IOC_WRITE: dir = "rw"; break; - default: dir = "??"; break; - } - switch (_IOC_TYPE(cmd)) { - case 'v': - printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n", - name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ? - v4l1_ioctls[_IOC_NR(cmd)] : "???"); - break; - case 'V': - printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n", - name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ? - v4l2_ioctls[_IOC_NR(cmd)] : "???"); - break; - default: - printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n", - name, cmd, dir, _IOC_NR(cmd)); - } -} - -/* ------------------------------------------------------------------ */ #define NO_SYNC_LINE (-1U) static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, @@ -291,9 +238,9 @@ cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf) * channel 22 (u video) - 2.0k * channel 23 (v video) - 2.0k * channel 24 (vbi) - 4.0k - * channels 25+26 (audio) - 0.5k + * channels 25+26 (audio) - 4.0k * channel 28 (mpeg) - 4.0k - * TOTAL = 25.5k + * TOTAL = 29.0k * * Every channel has 160 bytes control data (64 bytes instruction * queue and 6 CDT entries), which is close to 2k total. @@ -359,7 +306,7 @@ struct sram_channel cx88_sram_channels[] = { .ctrl_start = 0x180680, .cdt = 0x180680 + 64, .fifo_start = 0x185400, - .fifo_size = 0x000200, + .fifo_size = 0x001000, .ptr1_reg = MO_DMA25_PTR1, .ptr2_reg = MO_DMA25_PTR2, .cnt1_reg = MO_DMA25_CNT1, @@ -371,7 +318,7 @@ struct sram_channel cx88_sram_channels[] = { .ctrl_start = 0x180720, .cdt = 0x180680 + 64, /* same as audio IN */ .fifo_start = 0x185400, /* same as audio IN */ - .fifo_size = 0x000200, /* same as audio IN */ + .fifo_size = 0x001000, /* same as audio IN */ .ptr1_reg = MO_DMA26_PTR1, .ptr2_reg = MO_DMA26_PTR2, .cnt1_reg = MO_DMA26_CNT1, @@ -382,7 +329,7 @@ struct sram_channel cx88_sram_channels[] = { .cmds_start = 0x180200, .ctrl_start = 0x1807C0, .cdt = 0x1807C0 + 64, - .fifo_start = 0x185600, + .fifo_start = 0x186400, .fifo_size = 0x001000, .ptr1_reg = MO_DMA28_PTR1, .ptr2_reg = MO_DMA28_PTR2, @@ -848,7 +795,6 @@ int cx88_start_audio_dma(struct cx88_core *core) /* start dma */ cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */ - return 0; } @@ -1208,7 +1154,6 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) /* ------------------------------------------------------------------ */ -EXPORT_SYMBOL(cx88_print_ioctl); EXPORT_SYMBOL(cx88_print_irqbits); EXPORT_SYMBOL(cx88_core_irq); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 99ea955f5987..42c012aaa849 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -3,7 +3,7 @@ * device driver for Conexant 2388x based TV cards * MPEG Transport Stream (DVB) routines * - * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au> + * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] * * This program is free software; you can redistribute it and/or modify @@ -31,10 +31,14 @@ #include "cx88.h" #include "dvb-pll.h" +#include <media/v4l2-common.h> #ifdef HAVE_MT352 # include "mt352.h" # include "mt352_priv.h" +# ifdef HAVE_VP3054_I2C +# include "cx88-vp3054-i2c.h" +# endif #endif #ifdef HAVE_CX22702 # include "cx22702.h" @@ -48,6 +52,9 @@ #ifdef HAVE_NXT200X # include "nxt200x.h" #endif +#ifdef HAVE_CX24123 +# include "cx24123.h" +#endif MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); @@ -125,6 +132,27 @@ static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) return 0; } +static int dvico_dual_demod_init(struct dvb_frontend *fe) +{ + static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; + static u8 reset [] = { RESET, 0x80 }; + static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; + static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; + static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; + static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; + + 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, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); + mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); + + return 0; +} + static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) { static u8 clock_config [] = { 0x89, 0x38, 0x39 }; @@ -172,6 +200,98 @@ static struct mt352_config dntv_live_dvbt_config = { .demod_init = dntv_live_dvbt_demod_init, .pll_set = mt352_pll_set, }; + +static struct mt352_config dvico_fusionhdtv_dual = { + .demod_address = 0x0F, + .demod_init = dvico_dual_demod_init, + .pll_set = mt352_pll_set, +}; + +#ifdef HAVE_VP3054_I2C +static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) +{ + static u8 clock_config [] = { 0x89, 0x38, 0x38 }; + static u8 reset [] = { 0x50, 0x80 }; + static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x40, 0x40 }; + static u8 dntv_extra[] = { 0xB5, 0x7A }; + static u8 capt_range_cfg[] = { 0x75, 0x32 }; + + 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)); + + 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 philips_fmd1216_pll_init(struct dvb_frontend *fe) +{ + struct cx8802_dev *dev= fe->dvb->priv; + + /* this message is to set up ATC and ALC */ + static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; + struct i2c_msg msg = + { .addr = dev->core->pll_addr, .flags = 0, + .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; + int err; + + if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} + +static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params, + u8* pllbuf) +{ + struct cx8802_dev *dev= fe->dvb->priv; + struct i2c_msg msg = + { .addr = dev->core->pll_addr, .flags = 0, + .buf = pllbuf+1, .len = 4 }; + int err; + + /* Switch PLL to DVB mode */ + err = philips_fmd1216_pll_init(fe); + if (err) + return err; + + /* Tune PLL */ + pllbuf[0] = dev->core->pll_addr << 1; + dvb_pll_configure(dev->core->pll_desc, pllbuf+1, + params->frequency, + params->u.ofdm.bandwidth); + if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "cx88-dvb: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, pllbuf[0], pllbuf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} + +static struct mt352_config dntv_live_dvbt_pro_config = { + .demod_address = 0x0f, + .no_tuner = 1, + .demod_init = dntv_live_dvbt_pro_demod_init, + .pll_set = dntv_live_dvbt_pro_pll_set, +}; +#endif #endif #ifdef HAVE_CX22702 @@ -188,6 +308,12 @@ static struct cx22702_config hauppauge_novat_config = { .pll_address = 0x61, .pll_desc = &dvb_pll_thomson_dtt759x, }; +static struct cx22702_config hauppauge_hvr1100_config = { + .demod_address = 0x63, + .output_mode = CX22702_SERIAL_OUTPUT, + .pll_address = 0x61, + .pll_desc = &dvb_pll_fmd1216me, +}; #endif #ifdef HAVE_OR51132 @@ -314,6 +440,40 @@ static struct nxt200x_config ati_hdtvwonder = { }; #endif +#ifdef HAVE_CX24123 +static int cx24123_set_ts_param(struct dvb_frontend* fe, + int is_punctured) +{ + struct cx8802_dev *dev= fe->dvb->priv; + dev->ts_gen_cntrl = 0x2; + return 0; +} + +static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on) +{ + struct cx8802_dev *dev= fe->dvb->priv; + struct cx88_core *core = dev->core; + + if (on) + cx_write(MO_GP0_IO, 0x000006f9); + else + cx_write(MO_GP0_IO, 0x000006fB); +} + +static struct cx24123_config hauppauge_novas_config = { + .demod_address = 0x55, + .use_isl6421 = 1, + .set_ts_params = cx24123_set_ts_param, +}; + +static struct cx24123_config kworld_dvbs_100_config = { + .demod_address = 0x15, + .use_isl6421 = 0, + .set_ts_params = cx24123_set_ts_param, + .enable_lnb_voltage = cx24123_enable_lnb_voltage, +}; +#endif + static int dvb_register(struct cx8802_dev *dev) { /* init struct videobuf_dvb */ @@ -329,10 +489,16 @@ static int dvb_register(struct cx8802_dev *dev) break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: + case CX88_BOARD_KWORLD_DVB_T_CX22702: case CX88_BOARD_WINFAST_DTV1000: dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, &dev->core->i2c_adap); break; + case CX88_BOARD_HAUPPAUGE_HVR1100: + case CX88_BOARD_HAUPPAUGE_HVR1100LP: + dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, + &dev->core->i2c_adap); + break; #endif #ifdef HAVE_MT352 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: @@ -355,6 +521,24 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, &dev->core->i2c_adap); break; + case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: +#ifdef HAVE_VP3054_I2C + dev->core->pll_addr = 0x61; + dev->core->pll_desc = &dvb_pll_fmd1216me; + dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config, + &((struct vp3054_i2c_state *)dev->card_priv)->adap); +#else + printk("%s: built without vp3054 support\n", dev->core->name); +#endif + break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: + /* The tin box says DEE1601, but it seems to be DTT7579 + * compatible, with a slightly different MT352 AGC gain. */ + dev->core->pll_addr = 0x61; + dev->core->pll_desc = &dvb_pll_thomson_dtt7579; + dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual, + &dev->core->i2c_adap); + break; #endif #ifdef HAVE_OR51132 case CX88_BOARD_PCHDTV_HD3000: @@ -393,7 +577,7 @@ static int dvb_register(struct cx8802_dev *dev) cx_set(MO_GP0_IO, 9); mdelay(200); dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_thomson_dtt7611; + dev->core->pll_desc = &dvb_pll_thomson_dtt761x; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, &dev->core->i2c_adap); } @@ -421,6 +605,17 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); break; #endif +#ifdef HAVE_CX24123 + case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: + case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: + dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, + &dev->core->i2c_adap); + break; + case CX88_BOARD_KWORLD_DVBS_100: + dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, + &dev->core->i2c_adap); + break; +#endif default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); @@ -473,6 +668,12 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, if (0 != err) goto fail_free; +#ifdef HAVE_VP3054_I2C + err = vp3054_i2c_probe(dev); + if (0 != err) + goto fail_free; +#endif + /* dvb stuff */ printk("%s/2: cx2388x based dvb card\n", core->name); videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, @@ -484,6 +685,9 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, err = dvb_register(dev); if (0 != err) goto fail_fini; + + /* Maintain a reference to cx88-video can query the 8802 device. */ + core->dvbdev = dev; return 0; fail_fini: @@ -499,9 +703,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev) { struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + /* Destroy any 8802 reference. */ + dev->core->dvbdev = NULL; + /* dvb */ videobuf_dvb_unregister(&dev->dvb); +#ifdef HAVE_VP3054_I2C + vp3054_i2c_remove(dev); +#endif + /* common */ cx8802_fini_common(dev); cx88_core_put(dev->core,dev->pci); diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 4a8fb161b16a..f720901e9638 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -30,6 +30,7 @@ #include <asm/io.h> #include "cx88.h" +#include <media/v4l2-common.h> static unsigned int i2c_debug = 0; module_param(i2c_debug, int, 0644); @@ -135,7 +136,17 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) { if (0 != core->i2c_rc) return; - i2c_clients_command(&core->i2c_adap, cmd, arg); + + if (core->dvbdev) { + if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl) + core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); + + i2c_clients_command(&core->i2c_adap, cmd, arg); + + if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl) + core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); + } else + i2c_clients_command(&core->i2c_adap, cmd, arg); } static struct i2c_algo_bit_data cx8800_i2c_algo_template = { diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 461019dca901..286c85b6bdf9 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -5,7 +5,7 @@ * * Copyright (c) 2003 Pavel Machek * Copyright (c) 2004 Gerd Knorr - * Copyright (c) 2004 Chris Pascoe + * Copyright (c) 2004, 2005 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 @@ -29,9 +29,8 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <media/ir-common.h> - #include "cx88.h" +#include <media/ir-common.h> /* ---------------------------------------------------------------------- */ @@ -258,6 +257,114 @@ static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { /* ---------------------------------------------------------------------- */ +/* AVERTV STUDIO 303 Remote */ +static IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { + [ 0x2a ] = KEY_KP1, + [ 0x32 ] = KEY_KP2, + [ 0x3a ] = KEY_KP3, + [ 0x4a ] = KEY_KP4, + [ 0x52 ] = KEY_KP5, + [ 0x5a ] = KEY_KP6, + [ 0x6a ] = KEY_KP7, + [ 0x72 ] = KEY_KP8, + [ 0x7a ] = KEY_KP9, + [ 0x0e ] = KEY_KP0, + + [ 0x02 ] = KEY_POWER, + [ 0x22 ] = KEY_VIDEO, + [ 0x42 ] = KEY_AUDIO, + [ 0x62 ] = KEY_ZOOM, + [ 0x0a ] = KEY_TV, + [ 0x12 ] = KEY_CD, + [ 0x1a ] = KEY_TEXT, + + [ 0x16 ] = KEY_SUBTITLE, + [ 0x1e ] = KEY_REWIND, + [ 0x06 ] = KEY_PRINT, + + [ 0x2e ] = KEY_SEARCH, + [ 0x36 ] = KEY_SLEEP, + [ 0x3e ] = KEY_SHUFFLE, + [ 0x26 ] = KEY_MUTE, + + [ 0x4e ] = KEY_RECORD, + [ 0x56 ] = KEY_PAUSE, + [ 0x5e ] = KEY_STOP, + [ 0x46 ] = KEY_PLAY, + + [ 0x6e ] = KEY_RED, + [ 0x0b ] = KEY_GREEN, + [ 0x66 ] = KEY_YELLOW, + [ 0x03 ] = KEY_BLUE, + + [ 0x76 ] = KEY_LEFT, + [ 0x7e ] = KEY_RIGHT, + [ 0x13 ] = KEY_DOWN, + [ 0x1b ] = KEY_UP, +}; + +/* ---------------------------------------------------------------------- */ + +/* DigitalNow DNTV Live! DVB-T Pro Remote */ +static IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { + [ 0x16 ] = KEY_POWER, + [ 0x5b ] = KEY_HOME, + + [ 0x55 ] = KEY_TV, /* live tv */ + [ 0x58 ] = KEY_TUNER, /* digital Radio */ + [ 0x5a ] = KEY_RADIO, /* FM radio */ + [ 0x59 ] = KEY_DVD, /* dvd menu */ + [ 0x03 ] = KEY_1, + [ 0x01 ] = KEY_2, + [ 0x06 ] = KEY_3, + [ 0x09 ] = KEY_4, + [ 0x1d ] = KEY_5, + [ 0x1f ] = KEY_6, + [ 0x0d ] = KEY_7, + [ 0x19 ] = KEY_8, + [ 0x1b ] = KEY_9, + [ 0x0c ] = KEY_CANCEL, + [ 0x15 ] = KEY_0, + [ 0x4a ] = KEY_CLEAR, + [ 0x13 ] = KEY_BACK, + [ 0x00 ] = KEY_TAB, + [ 0x4b ] = KEY_UP, + [ 0x4e ] = KEY_LEFT, + [ 0x4f ] = KEY_OK, + [ 0x52 ] = KEY_RIGHT, + [ 0x51 ] = KEY_DOWN, + [ 0x1e ] = KEY_VOLUMEUP, + [ 0x0a ] = KEY_VOLUMEDOWN, + [ 0x02 ] = KEY_CHANNELDOWN, + [ 0x05 ] = KEY_CHANNELUP, + [ 0x11 ] = KEY_RECORD, + [ 0x14 ] = KEY_PLAY, + [ 0x4c ] = KEY_PAUSE, + [ 0x1a ] = KEY_STOP, + [ 0x40 ] = KEY_REWIND, + [ 0x12 ] = KEY_FASTFORWARD, + [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */ + [ 0x42 ] = KEY_NEXTSONG, /* skip >| */ + [ 0x54 ] = KEY_CAMERA, /* capture */ + [ 0x50 ] = KEY_LANGUAGE, /* sap */ + [ 0x47 ] = KEY_TV2, /* pip */ + [ 0x4d ] = KEY_SCREEN, + [ 0x43 ] = KEY_SUBTITLE, + [ 0x10 ] = KEY_MUTE, + [ 0x49 ] = KEY_AUDIO, /* l/r */ + [ 0x07 ] = KEY_SLEEP, + [ 0x08 ] = KEY_VIDEO, /* a/v */ + [ 0x0e ] = KEY_PREVIOUS, /* recall */ + [ 0x45 ] = KEY_ZOOM, /* zoom + */ + [ 0x46 ] = KEY_ANGLE, /* zoom - */ + [ 0x56 ] = KEY_RED, + [ 0x57 ] = KEY_GREEN, + [ 0x5c ] = KEY_YELLOW, + [ 0x5d ] = KEY_BLUE, +}; + +/* ---------------------------------------------------------------------- */ + struct cx88_IR { struct cx88_core *core; struct input_dev *input; @@ -266,7 +373,7 @@ struct cx88_IR { char phys[32]; /* sample from gpio pin 16 */ - int sampling; + u32 sampling; u32 samples[16]; int scount; unsigned long release; @@ -384,10 +491,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: ir_codes = ir_codes_cinergy_1400; ir_type = IR_TYPE_PD; - ir->sampling = 1; + ir->sampling = 0xeb04; /* address */ break; case CX88_BOARD_HAUPPAUGE: case CX88_BOARD_HAUPPAUGE_DVB_T1: + case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: + case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: + case CX88_BOARD_HAUPPAUGE_HVR1100: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; ir->sampling = 1; @@ -427,6 +537,19 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keyup = 0x40; ir->polling = 1; /* ms */ break; + case CX88_BOARD_AVERTV_303: + case CX88_BOARD_AVERTV_STUDIO_303: + ir_codes = ir_codes_avertv_303; + ir->gpio_addr = MO_GP2_IO; + ir->mask_keycode = 0xfb; + ir->mask_keydown = 0x02; + ir->polling = 50; /* ms */ + break; + case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: + ir_codes = ir_codes_dntv_live_dvbt_pro; + ir_type = IR_TYPE_PD; + ir->sampling = 0xff00; /* address */ + break; } if (NULL == ir_codes) { @@ -484,6 +607,10 @@ int cx88_ir_fini(struct cx88_core *core) if (NULL == ir) return 0; + if (ir->sampling) { + cx_write(MO_DDSCFG_IO, 0x0); + core->pci_irqmask &= ~(1 << 18); + } if (ir->polling) { del_timer(&ir->timer); flush_scheduled_work(); @@ -535,6 +662,7 @@ void cx88_ir_irq(struct cx88_core *core) /* decode it */ switch (core->board) { case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: + case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); if (ircode == 0xffffffff) { /* decoding error */ @@ -550,7 +678,7 @@ void cx88_ir_irq(struct cx88_core *core) break; } - if ((ircode & 0xffff) != 0xeb04) { /* wrong address */ + if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */ ir_dprintk("pulse distance decoded wrong address\n"); break; } @@ -567,6 +695,8 @@ void cx88_ir_irq(struct cx88_core *core) break; case CX88_BOARD_HAUPPAUGE: case CX88_BOARD_HAUPPAUGE_DVB_T1: + case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: + case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); if ((ircode & 0xfffff000) != 0x3000) diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 35e6d0c2b872..c79cc1d2bf8b 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -78,6 +78,11 @@ static int cx8802_start_dma(struct cx8802_dev *dev, case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: cx_write(TS_SOP_STAT, 1<<13); break; + case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: + case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: + cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ + udelay(100); + break; default: cx_write(TS_SOP_STAT, 0x00); break; diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index a1b120c8a9b5..24118e43e73a 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -132,14 +132,22 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) { u32 volume; +#ifndef USING_CX88_ALSA /* restart dma; This avoids buzz in NICAM and is good in others */ cx88_stop_audio_dma(core); +#endif cx_write(AUD_RATE_THRES_DMD, 0x000000C0); +#ifndef USING_CX88_ALSA cx88_start_audio_dma(core); +#endif if (cx88_boards[core->board].blackbird) { /* sets sound input from external adc */ - cx_set(AUD_CTL, EN_I2SIN_ENABLE); + if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) + cx_clear(AUD_CTL, EN_I2SIN_ENABLE); + else + cx_set(AUD_CTL, EN_I2SIN_ENABLE); + cx_write(AUD_I2SINPUTCNTL, 4); cx_write(AUD_BAUDRATE, 1); /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 24a48f8a48c1..9a02515fe18b 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -33,6 +33,7 @@ #include <asm/div64.h> #include "cx88.h" +#include <media/v4l2-common.h> /* Include V4L1 specific functions. Should be removed soon */ #include <linux/videodev.h> @@ -240,7 +241,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .minimum = 0, .maximum = 0xff, .step = 1, - .default_value = 0, + .default_value = 0x3f, .type = V4L2_CTRL_TYPE_INTEGER, }, .off = 0, @@ -271,7 +272,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .minimum = 0, .maximum = 0xff, .step = 1, - .default_value = 0, + .default_value = 0x7f, .type = V4L2_CTRL_TYPE_INTEGER, }, .off = 0, @@ -285,6 +286,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .name = "Mute", .minimum = 0, .maximum = 1, + .default_value = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, }, .reg = AUD_VOL_CTL, @@ -298,7 +300,7 @@ static struct cx88_ctrl cx8800_ctls[] = { .minimum = 0, .maximum = 0x3f, .step = 1, - .default_value = 0, + .default_value = 0x1f, .type = V4L2_CTRL_TYPE_INTEGER, }, .reg = AUD_VOL_CTL, @@ -917,6 +919,9 @@ static int get_control(struct cx88_core *core, struct v4l2_control *ctl) ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift; break; } + printk("get_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", + ctl->id, c->reg, ctl->value, + c->mask, c->sreg ? " [shadowed]" : ""); return 0; } @@ -925,13 +930,13 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) { /* struct cx88_core *core = dev->core; */ struct cx88_ctrl *c = NULL; - u32 v_sat_value; - u32 value; + u32 value,mask; int i; - - for (i = 0; i < CX8800_CTLS; i++) - if (cx8800_ctls[i].v.id == ctl->id) + for (i = 0; i < CX8800_CTLS; i++) { + if (cx8800_ctls[i].v.id == ctl->id) { c = &cx8800_ctls[i]; + } + } if (NULL == c) return -EINVAL; @@ -939,6 +944,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) ctl->value = c->v.minimum; if (ctl->value > c->v.maximum) ctl->value = c->v.maximum; + mask=c->mask; switch (ctl->id) { case V4L2_CID_AUDIO_BALANCE: value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value; @@ -948,56 +954,44 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) break; case V4L2_CID_SATURATION: /* special v_sat handling */ - v_sat_value = ctl->value - (0x7f - 0x5a); - if (v_sat_value > 0xff) - v_sat_value = 0xff; - if (v_sat_value < 0x00) - v_sat_value = 0x00; - cx_andor(MO_UV_SATURATION, 0xff00, v_sat_value << 8); - /* fall through to default route for u_sat */ + + value = ((ctl->value - c->off) << c->shift) & c->mask; + + if (core->tvnorm->id & V4L2_STD_SECAM) { + /* For SECAM, both U and V sat should be equal */ + value=value<<8|value; + } else { + /* Keeps U Saturation proportional to V Sat */ + value=(value*0x5a)/0x7f<<8|value; + } + mask=0xffff; + break; default: value = ((ctl->value - c->off) << c->shift) & c->mask; break; } - dprintk(1,"set_control id=0x%X reg=0x%x val=0x%x%s\n", - ctl->id, c->reg, value, c->sreg ? " [shadowed]" : ""); + printk("set_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", + ctl->id, c->reg, value, + mask, c->sreg ? " [shadowed]" : ""); if (c->sreg) { - cx_sandor(c->sreg, c->reg, c->mask, value); + cx_sandor(c->sreg, c->reg, mask, value); } else { - cx_andor(c->reg, c->mask, value); + cx_andor(c->reg, mask, value); } return 0; } -/* static void init_controls(struct cx8800_dev *dev) */ static void init_controls(struct cx88_core *core) { - static struct v4l2_control mute = { - .id = V4L2_CID_AUDIO_MUTE, - .value = 1, - }; - static struct v4l2_control volume = { - .id = V4L2_CID_AUDIO_VOLUME, - .value = 0x3f, - }; - static struct v4l2_control hue = { - .id = V4L2_CID_HUE, - .value = 0x80, - }; - static struct v4l2_control contrast = { - .id = V4L2_CID_CONTRAST, - .value = 0x80, - }; - static struct v4l2_control brightness = { - .id = V4L2_CID_BRIGHTNESS, - .value = 0x80, - }; + struct v4l2_control ctrl; + int i; - set_control(core,&mute); - set_control(core,&volume); - set_control(core,&hue); - set_control(core,&contrast); - set_control(core,&brightness); + for (i = 0; i < CX8800_CTLS; i++) { + ctrl.id=cx8800_ctls[i].v.id; + ctrl.value=cx8800_ctls[i].v.default_value + +cx8800_ctls[i].off; + set_control(core, &ctrl); + } } /* ------------------------------------------------------------------ */ @@ -1125,7 +1119,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, int err; if (video_debug > 1) - cx88_print_ioctl(core->name,cmd); + v4l_print_ioctl(core->name,cmd); switch (cmd) { /* --- capabilities ------------------------------------------ */ @@ -1261,7 +1255,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, dprintk( 1, "CORE IOCTL: 0x%x\n", cmd ); if (video_debug > 1) - cx88_print_ioctl(core->name,cmd); + v4l_print_ioctl(core->name,cmd); switch (cmd) { /* ---------- tv norms ---------- */ @@ -1481,7 +1475,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, struct cx88_core *core = dev->core; if (video_debug > 1) - cx88_print_ioctl(core->name,cmd); + v4l_print_ioctl(core->name,cmd); switch (cmd) { case VIDIOC_QUERYCAP: @@ -1740,6 +1734,7 @@ static struct file_operations video_fops = .poll = video_poll, .mmap = video_mmap, .ioctl = video_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; @@ -1767,6 +1762,7 @@ static struct file_operations radio_fops = .open = video_open, .release = video_release, .ioctl = radio_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; @@ -1928,8 +1924,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* initial device configuration */ down(&core->lock); - init_controls(core); cx88_set_tvnorm(core,tvnorms); + init_controls(core); video_mux(core,0); up(&core->lock); diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c new file mode 100644 index 000000000000..372cd29cedbd --- /dev/null +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -0,0 +1,173 @@ +/* + + cx88-vp3054-i2c.c -- support for the secondary I2C bus of the + DNTV Live! DVB-T Pro (VP-3054), wired as: + GPIO[0] -> SCL, GPIO[1] -> SDA + + (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> + + 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/moduleparam.h> +#include <linux/init.h> + +#include <asm/io.h> + +#include "cx88.h" +#include "cx88-vp3054-i2c.h" + + +/* ----------------------------------------------------------------------- */ + +static void vp3054_bit_setscl(void *data, int state) +{ + struct cx8802_dev *dev = data; + struct cx88_core *core = dev->core; + struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; + + if (state) { + vp3054_i2c->state |= 0x0001; /* SCL high */ + vp3054_i2c->state &= ~0x0100; /* external pullup */ + } else { + vp3054_i2c->state &= ~0x0001; /* SCL low */ + vp3054_i2c->state |= 0x0100; /* drive pin */ + } + cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state); + cx_read(MO_GP0_IO); +} + +static void vp3054_bit_setsda(void *data, int state) +{ + struct cx8802_dev *dev = data; + struct cx88_core *core = dev->core; + struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; + + if (state) { + vp3054_i2c->state |= 0x0002; /* SDA high */ + vp3054_i2c->state &= ~0x0200; /* tristate pin */ + } else { + vp3054_i2c->state &= ~0x0002; /* SDA low */ + vp3054_i2c->state |= 0x0200; /* drive pin */ + } + cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state); + cx_read(MO_GP0_IO); +} + +static int vp3054_bit_getscl(void *data) +{ + struct cx8802_dev *dev = data; + struct cx88_core *core = dev->core; + u32 state; + + state = cx_read(MO_GP0_IO); + return (state & 0x01) ? 1 : 0; +} + +static int vp3054_bit_getsda(void *data) +{ + struct cx8802_dev *dev = data; + struct cx88_core *core = dev->core; + u32 state; + + state = cx_read(MO_GP0_IO); + return (state & 0x02) ? 1 : 0; +} + +/* ----------------------------------------------------------------------- */ + +static struct i2c_algo_bit_data vp3054_i2c_algo_template = { + .setsda = vp3054_bit_setsda, + .setscl = vp3054_bit_setscl, + .getsda = vp3054_bit_getsda, + .getscl = vp3054_bit_getscl, + .udelay = 16, + .mdelay = 10, + .timeout = 200, +}; + +/* ----------------------------------------------------------------------- */ + +static struct i2c_adapter vp3054_i2c_adap_template = { + .name = "cx2388x", + .owner = THIS_MODULE, + .id = I2C_HW_B_CX2388x, +}; + +static struct i2c_client vp3054_i2c_client_template = { + .name = "VP-3054", +}; + +int vp3054_i2c_probe(struct cx8802_dev *dev) +{ + struct cx88_core *core = dev->core; + struct vp3054_i2c_state *vp3054_i2c; + int rc; + + if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) + return 0; + + dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL); + if (dev->card_priv == NULL) + return -ENOMEM; + vp3054_i2c = dev->card_priv; + + memcpy(&vp3054_i2c->adap, &vp3054_i2c_adap_template, + sizeof(vp3054_i2c->adap)); + memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, + sizeof(vp3054_i2c->algo)); + memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template, + sizeof(vp3054_i2c->client)); + + vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL; + + vp3054_i2c->adap.dev.parent = &dev->pci->dev; + strlcpy(vp3054_i2c->adap.name, core->name, + sizeof(vp3054_i2c->adap.name)); + vp3054_i2c->algo.data = dev; + i2c_set_adapdata(&vp3054_i2c->adap, dev); + vp3054_i2c->adap.algo_data = &vp3054_i2c->algo; + vp3054_i2c->client.adapter = &vp3054_i2c->adap; + + vp3054_bit_setscl(dev,1); + vp3054_bit_setsda(dev,1); + + rc = i2c_bit_add_bus(&vp3054_i2c->adap); + if (0 != rc) { + printk("%s: vp3054_i2c register FAILED\n", core->name); + + kfree(dev->card_priv); + dev->card_priv = NULL; + } + + return rc; +} + +void vp3054_i2c_remove(struct cx8802_dev *dev) +{ + struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; + + if (vp3054_i2c == NULL || + dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) + return; + + i2c_bit_del_bus(&vp3054_i2c->adap); + kfree(vp3054_i2c); +} + +EXPORT_SYMBOL(vp3054_i2c_probe); +EXPORT_SYMBOL(vp3054_i2c_remove); diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h new file mode 100644 index 000000000000..b7a0a04d2423 --- /dev/null +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h @@ -0,0 +1,35 @@ +/* + + cx88-vp3054-i2c.h -- support for the secondary I2C bus of the + DNTV Live! DVB-T Pro (VP-3054), wired as: + GPIO[0] -> SCL, GPIO[1] -> SDA + + (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> + + 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. + +*/ + +/* ----------------------------------------------------------------------- */ +struct vp3054_i2c_state { + struct i2c_adapter adap; + struct i2c_algo_bit_data algo; + struct i2c_client client; + u32 state; +}; + +/* ----------------------------------------------------------------------- */ +int vp3054_i2c_probe(struct cx8802_dev *dev); +void vp3054_i2c_remove(struct cx8802_dev *dev); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 77beafc5c327..e9fd55b57fa6 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -179,6 +179,14 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_ATI_HDTVWONDER 34 #define CX88_BOARD_WINFAST_DTV1000 35 #define CX88_BOARD_AVERTV_303 36 +#define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1 37 +#define CX88_BOARD_HAUPPAUGE_NOVASE2_S1 38 +#define CX88_BOARD_KWORLD_DVBS_100 39 +#define CX88_BOARD_HAUPPAUGE_HVR1100 40 +#define CX88_BOARD_HAUPPAUGE_HVR1100LP 41 +#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO 42 +#define CX88_BOARD_KWORLD_DVB_T_CX22702 43 +#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -280,6 +288,9 @@ struct cx88_core { unsigned int tda9887_conf; unsigned int has_radio; + /* Supported V4L _STD_ tuner formats */ + unsigned int tuner_formats; + /* config info -- dvb */ struct dvb_pll_desc *pll_desc; unsigned int pll_addr; @@ -301,6 +312,9 @@ struct cx88_core { /* various v4l controls */ u32 freq; + + /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ + struct cx8802_dev *dvbdev; }; struct cx8800_dev; @@ -411,6 +425,8 @@ struct cx8802_dev { struct videobuf_dvb dvb; void* fe_handle; int (*fe_release)(void *handle); + + void *card_priv; /* for switching modulation types */ unsigned char ts_gen_cntrl; @@ -447,7 +463,6 @@ struct cx8802_dev { extern void cx88_print_irqbits(char *name, char *tag, char **strings, u32 bits, u32 mask); -extern void cx88_print_ioctl(char *name, unsigned int cmd); extern int cx88_core_irq(struct cx88_core *core, u32 status); extern void cx88_wakeup(struct cx88_core *core, diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 57779e63f35d..58f7b4194a0d 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -30,6 +30,7 @@ #include <media/tuner.h> #include <media/audiochip.h> #include <media/tveeprom.h> +#include <media/v4l2-common.h> #include "msp3400.h" #include "em28xx.h" @@ -261,7 +262,6 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->model == EM2820_BOARD_HAUPPAUGE_WINTV_USB_2) { struct tveeprom tv; - struct v4l2_audioout ao; #ifdef CONFIG_MODULES request_module("tveeprom"); request_module("ir-kbd-i2c"); @@ -274,12 +274,8 @@ void em28xx_card_setup(struct em28xx *dev) dev->tuner_type= tv.tuner_type; if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { + dev->i2s_speed=2048000; dev->has_msp34xx=1; - memset (&ao,0,sizeof(ao)); - - ao.index=2; - ao.mode=V4L2_AUDMODE_32BITS; - em28xx_i2c_call_clients(dev, VIDIOC_S_AUDOUT, &ao); } else dev->has_msp34xx=0; } diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 0cfe75416ec6..dff3893f32fd 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -32,7 +32,7 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ -static unsigned int core_debug; +static unsigned int core_debug = 0; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); @@ -41,7 +41,7 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int reg_debug; +static unsigned int reg_debug = 0; module_param(reg_debug,int,0644); MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); @@ -50,7 +50,7 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int isoc_debug; +static unsigned int isoc_debug = 0; module_param(isoc_debug,int,0644); MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); @@ -63,59 +63,6 @@ static int alt = EM28XX_PINOUT; module_param(alt, int, 0644); MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); -/* ------------------------------------------------------------------ */ -/* debug help functions */ - -static const char *v4l1_ioctls[] = { - "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT", - "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ", - "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT", - "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", - "SMICROCODE", "GVBIFMT", "SVBIFMT" }; -#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) - -static const char *v4l2_ioctls[] = { - "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT", - "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF", - "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON", - "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD", - "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER", - "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL", - "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43", - "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT", - "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR", - "S_MODULATOR" -}; -#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) - -void em28xx_print_ioctl(char *name, unsigned int cmd) -{ - char *dir; - - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: dir = "--"; break; - case _IOC_READ: dir = "r-"; break; - case _IOC_WRITE: dir = "-w"; break; - case _IOC_READ | _IOC_WRITE: dir = "rw"; break; - default: dir = "??"; break; - } - switch (_IOC_TYPE(cmd)) { - case 'v': - printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n", - name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ? - v4l1_ioctls[_IOC_NR(cmd)] : "???"); - break; - case 'V': - printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n", - name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ? - v4l2_ioctls[_IOC_NR(cmd)] : "???"); - break; - default: - printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n", - name, cmd, dir, _IOC_NR(cmd)); - } -} - /* * em28xx_request_buffers() @@ -126,7 +73,7 @@ u32 em28xx_request_buffers(struct em28xx *dev, u32 count) const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */ void *buff = NULL; u32 i; - em28xx_coredbg("requested %i buffers with size %zd", count, imagesize); + em28xx_coredbg("requested %i buffers with size %zi", count, imagesize); if (count > EM28XX_NUM_FRAMES) count = EM28XX_NUM_FRAMES; diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index d14bcf4ceaea..0591a705b7a1 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -28,6 +28,7 @@ #include <linux/video_decoder.h> #include "em28xx.h" +#include <media/v4l2-common.h> #include <media/tuner.h> /* ----------------------------------------------------------- */ @@ -486,9 +487,7 @@ static struct i2c_adapter em28xx_adap_template = { .inc_use = inc_use, .dec_use = dec_use, #endif -#ifdef I2C_CLASS_TV_ANALOG .class = I2C_CLASS_TV_ANALOG, -#endif .name = "em28xx", .id = I2C_HW_B_EM28XX, .algo = &em28xx_algo, diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 3a56120397ae..fdc255918dde 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -32,6 +32,7 @@ #include "em28xx.h" #include <media/tuner.h> +#include <media/v4l2-common.h> #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \ "Markus Rechberger <mrechberger@gmail.com>, " \ @@ -106,8 +107,32 @@ static const unsigned char saa7114_i2c_init[] = { #define TVNORMS ARRAY_SIZE(tvnorms) /* supported controls */ +/* Common to all boards */ static struct v4l2_queryctrl em28xx_qctrl[] = { { + .id = V4L2_CID_AUDIO_VOLUME, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Volume", + .minimum = 0x0, + .maximum = 0x1f, + .step = 0x1, + .default_value = 0x1f, + .flags = 0, + },{ + .id = V4L2_CID_AUDIO_MUTE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .flags = 0, + } +}; + +/* FIXME: These are specific to saa711x - should be moved to its code */ +static struct v4l2_queryctrl saa711x_qctrl[] = { + { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", @@ -135,24 +160,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { .default_value = 0x10, .flags = 0, },{ - .id = V4L2_CID_AUDIO_VOLUME, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Volume", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x1f, - .flags = 0, - },{ - .id = V4L2_CID_AUDIO_MUTE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - .flags = 0, - },{ .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Red chroma balance", @@ -179,7 +186,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { .step = 0x1, .default_value = 0x20, .flags = 0, - } + } }; static struct usb_driver em28xx_usb_driver; @@ -280,6 +287,8 @@ static void video_mux(struct em28xx *dev, int index) em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); if (dev->has_msp34xx) { + if (dev->i2s_speed) + em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput); ainput = EM28XX_AUDIO_SRC_TUNER; em28xx_audio_source(dev, ainput); @@ -674,7 +683,6 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) */ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) { - s32 tmp; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = dev->mute; @@ -682,6 +690,16 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_VOLUME: ctrl->value = dev->volume; return 0; + default: + return -EINVAL; + } +} + +/*FIXME: should be moved to saa711x */ +static int saa711x_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) +{ + s32 tmp; + switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: if ((tmp = em28xx_brightness_get(dev)) < 0) return -EIO; @@ -731,6 +749,15 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) case V4L2_CID_AUDIO_VOLUME: dev->volume = ctrl->value; return em28xx_audio_analog_set(dev); + default: + return -EINVAL; + } +} + +/*FIXME: should be moved to saa711x */ +static int saa711x_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) +{ + switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: return em28xx_brightness_set(dev, ctrl->value); case V4L2_CID_CONTRAST: @@ -994,14 +1021,34 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; - u8 i, n; - n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]); - for (i = 0; i < n; i++) - if (qc->id && qc->id == em28xx_qctrl[i].id) { - memcpy(qc, &(em28xx_qctrl[i]), + int i, id=qc->id; + + memset(qc,0,sizeof(*qc)); + qc->id=id; + + if (!dev->has_msp34xx) { + for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { + if (qc->id && qc->id == em28xx_qctrl[i].id) { + memcpy(qc, &(em28xx_qctrl[i]), + sizeof(*qc)); + return 0; + } + } + } + if (dev->decoder == EM28XX_TVP5150) { + em28xx_i2c_call_clients(dev,cmd,qc); + if (qc->type) + return 0; + else + return -EINVAL; + } + for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { + if (qc->id && qc->id == saa711x_qctrl[i].id) { + memcpy(qc, &(saa711x_qctrl[i]), sizeof(*qc)); return 0; } + } return -EINVAL; } @@ -1009,29 +1056,64 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, case VIDIOC_G_CTRL: { struct v4l2_control *ctrl = arg; + int retval=-EINVAL; + if (!dev->has_msp34xx) + retval=em28xx_get_ctrl(dev, ctrl); + if (retval==-EINVAL) { + if (dev->decoder == EM28XX_TVP5150) { + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; + } - return em28xx_get_ctrl(dev, ctrl); + return saa711x_get_ctrl(dev, ctrl); + } else return retval; } - case VIDIOC_S_CTRL_OLD: /* ??? */ case VIDIOC_S_CTRL: { struct v4l2_control *ctrl = arg; - u8 i, n; - - - n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]); - for (i = 0; i < n; i++) - if (ctrl->id == em28xx_qctrl[i].id) { - if (ctrl->value < - em28xx_qctrl[i].minimum - || ctrl->value > - em28xx_qctrl[i].maximum) - return -ERANGE; + u8 i; + + if (!dev->has_msp34xx){ + for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { + if (ctrl->id == em28xx_qctrl[i].id) { + if (ctrl->value < + em28xx_qctrl[i].minimum + || ctrl->value > + em28xx_qctrl[i].maximum) + return -ERANGE; + return em28xx_set_ctrl(dev, ctrl); + } + } + } - return em28xx_set_ctrl(dev, ctrl); + if (dev->decoder == EM28XX_TVP5150) { + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; + } else if (!dev->has_msp34xx) { + for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { + if (ctrl->id == em28xx_qctrl[i].id) { + if (ctrl->value < + em28xx_qctrl[i].minimum + || ctrl->value > + em28xx_qctrl[i].maximum) + return -ERANGE; + return em28xx_set_ctrl(dev, ctrl); + } } + for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { + if (ctrl->id == saa711x_qctrl[i].id) { + if (ctrl->value < + saa711x_qctrl[i].minimum + || ctrl->value > + saa711x_qctrl[i].maximum) + return -ERANGE; + return saa711x_set_ctrl(dev, ctrl); + } + } + } + return -EINVAL; } @@ -1187,7 +1269,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, return -ENODEV; if (video_debug > 1) - em28xx_print_ioctl(dev->name,cmd); + v4l_print_ioctl(dev->name,cmd); switch (cmd) { @@ -1564,6 +1646,8 @@ static struct file_operations em28xx_v4l_fops = { .poll = em28xx_v4l2_poll, .mmap = em28xx_v4l2_mmap, .llseek = no_llseek, + .compat_ioctl = v4l_compat_ioctl32, + }; /******************************** usb interface *****************************************/ @@ -1848,9 +1932,12 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) struct em28xx *dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); +/*FIXME: IR should be disconnected */ + if (!dev) return; + down_write(&em28xx_disconnect); down(&dev->lock); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 5c7a41ce69f3..33de9d846af5 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -1,5 +1,5 @@ /* - em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices + em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> Ludovico Cavedon <cavedon@sssup.it> @@ -216,6 +216,8 @@ struct em28xx { unsigned int has_msp34xx:1; unsigned int has_tda9887:1; + u32 i2s_speed; /* I2S speed for audio digital stream */ + enum em28xx_decoder decoder; int tuner_type; /* type of the tuner */ @@ -293,8 +295,6 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir); /* Provided by em28xx-core.c */ -void em28xx_print_ioctl(char *name, unsigned int cmd); - u32 em28xx_request_buffers(struct em28xx *dev, u32 count); void em28xx_queue_unusedframes(struct em28xx *dev); void em28xx_release_buffers(struct em28xx *dev); diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 3cc1d6a6019b..58b0e6982822 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -279,7 +279,7 @@ static int ir_probe(struct i2c_adapter *adap); static struct i2c_driver driver = { .driver = { - .name = "ir remote kbd driver", + .name = "ir-kbd-i2c", }, .id = I2C_DRIVERID_INFRARED, .attach_adapter = ir_probe, @@ -304,18 +304,20 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); input_dev = input_allocate_device(); if (!ir || !input_dev) { - kfree(ir); input_free_device(input_dev); + kfree(ir); return -ENOMEM; } + memset(ir,0,sizeof(*ir)); ir->c = client_template; ir->input = input_dev; - i2c_set_clientdata(&ir->c, ir); ir->c.adapter = adap; ir->c.addr = addr; + i2c_set_clientdata(&ir->c, ir); + switch(addr) { case 0x64: name = "Pixelview"; @@ -378,13 +380,15 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->c.dev.bus_id); /* init + register input device */ - ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); - input_dev->id.bustype = BUS_I2C; - input_dev->name = ir->c.name; - input_dev->phys = ir->phys; + ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes); + input_dev->id.bustype = BUS_I2C; + input_dev->name = ir->c.name; + input_dev->phys = ir->phys; /* register event device */ input_register_device(ir->input); + printk(DEVNAME ": %s detected at %s [%s]\n", + ir->input->name,ir->input->phys,adap->name); /* start polling via eventd */ INIT_WORK(&ir->work, ir_work, ir); diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 3f2a882bc20a..2869464aee0d 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1754,6 +1754,7 @@ static struct file_operations meye_fops = { .release = meye_release, .mmap = meye_mmap, .ioctl = meye_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .poll = meye_poll, .llseek = no_llseek, }; diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c new file mode 100644 index 000000000000..aa8c556b6ba1 --- /dev/null +++ b/drivers/media/video/msp3400-driver.c @@ -0,0 +1,1274 @@ +/* + * Programming the mspx4xx sound processor family + * + * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org> + * + * what works and what doesn't: + * + * AM-Mono + * Support for Hauppauge cards added (decoding handled by tuner) added by + * Frederic Crozat <fcrozat@mail.dotcom.fr> + * + * FM-Mono + * should work. The stereo modes are backward compatible to FM-mono, + * therefore FM-Mono should be allways available. + * + * FM-Stereo (B/G, used in germany) + * should work, with autodetect + * + * FM-Stereo (satellite) + * should work, no autodetect (i.e. default is mono, but you can + * switch to stereo -- untested) + * + * NICAM (B/G, L , used in UK, Scandinavia, Spain and France) + * should work, with autodetect. Support for NICAM was added by + * Pekka Pietikainen <pp@netppl.fi> + * + * TODO: + * - better SAT support + * + * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch) + * using soundcore instead of OSS + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/videodev.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <media/audiochip.h> +#include <linux/kthread.h> +#include <linux/suspend.h> +#include "msp3400.h" + +/* ---------------------------------------------------------------------- */ + +MODULE_DESCRIPTION("device driver for msp34xx TV sound processor"); +MODULE_AUTHOR("Gerd Knorr"); +MODULE_LICENSE("GPL"); + +/* module parameters */ +static int opmode = OPMODE_AUTO; +int debug = 0; /* debug output */ +int once = 0; /* no continous stereo monitoring */ +int amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), + the autoscan seems work well only with FM... */ +int standard = 1; /* Override auto detect of audio standard, if needed. */ +int dolby = 0; + +int stereo_threshold = 0x190; /* a2 threshold for stereo/bilingual + (msp34xxg only) 0x00a0-0x03c0 */ + +/* read-only */ +module_param(opmode, int, 0444); + +/* read-write */ +module_param(once, bool, 0644); +module_param(debug, int, 0644); +module_param(stereo_threshold, int, 0644); +module_param(standard, int, 0644); +module_param(amsound, bool, 0644); +module_param(dolby, bool, 0644); + +MODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Autodetect, 2=Autodetect and autoselect"); +MODULE_PARM_DESC(once, "No continuous stereo monitoring"); +MODULE_PARM_DESC(debug, "Enable debug messages [0-3]"); +MODULE_PARM_DESC(stereo_threshold, "Sets signal threshold to activate stereo"); +MODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect"); +MODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan"); +MODULE_PARM_DESC(dolby, "Activates Dolby processsing"); + +/* ---------------------------------------------------------------------- */ + +/* control subaddress */ +#define I2C_MSP_CONTROL 0x00 +/* demodulator unit subaddress */ +#define I2C_MSP_DEM 0x10 +/* DSP unit subaddress */ +#define I2C_MSP_DSP 0x12 + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x80 >> 1, 0x88 >> 1, I2C_CLIENT_END }; +I2C_CLIENT_INSMOD; + +/* ----------------------------------------------------------------------- */ +/* functions for talking to the MSP3400C Sound processor */ + +int msp_reset(struct i2c_client *client) +{ + /* reset and read revision code */ + static u8 reset_off[3] = { I2C_MSP_CONTROL, 0x80, 0x00 }; + static u8 reset_on[3] = { I2C_MSP_CONTROL, 0x00, 0x00 }; + static u8 write[3] = { I2C_MSP_DSP + 1, 0x00, 0x1e }; + u8 read[2]; + struct i2c_msg reset[2] = { + { client->addr, I2C_M_IGNORE_NAK, 3, reset_off }, + { client->addr, I2C_M_IGNORE_NAK, 3, reset_on }, + }; + struct i2c_msg test[2] = { + { client->addr, 0, 3, write }, + { client->addr, I2C_M_RD, 2, read }, + }; + + v4l_dbg(3, client, "msp_reset\n"); + if (i2c_transfer(client->adapter, &reset[0], 1) != 1 || + i2c_transfer(client->adapter, &reset[1], 1) != 1 || + i2c_transfer(client->adapter, test, 2) != 2) { + v4l_err(client, "chip reset failed\n"); + return -1; + } + return 0; +} + +static int msp_read(struct i2c_client *client, int dev, int addr) +{ + int err, retval; + u8 write[3]; + u8 read[2]; + struct i2c_msg msgs[2] = { + { client->addr, 0, 3, write }, + { client->addr, I2C_M_RD, 2, read } + }; + + write[0] = dev + 1; + write[1] = addr >> 8; + write[2] = addr & 0xff; + + for (err = 0; err < 3; err++) { + if (i2c_transfer(client->adapter, msgs, 2) == 2) + break; + v4l_warn(client, "I/O error #%d (read 0x%02x/0x%02x)\n", err, + dev, addr); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(msecs_to_jiffies(10)); + } + if (err == 3) { + v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n"); + msp_reset(client); + return -1; + } + retval = read[0] << 8 | read[1]; + v4l_dbg(3, client, "msp_read(0x%x, 0x%x): 0x%x\n", dev, addr, retval); + return retval; +} + +int msp_read_dem(struct i2c_client *client, int addr) +{ + return msp_read(client, I2C_MSP_DEM, addr); +} + +int msp_read_dsp(struct i2c_client *client, int addr) +{ + return msp_read(client, I2C_MSP_DSP, addr); +} + +static int msp_write(struct i2c_client *client, int dev, int addr, int val) +{ + int err; + u8 buffer[5]; + + buffer[0] = dev; + buffer[1] = addr >> 8; + buffer[2] = addr & 0xff; + buffer[3] = val >> 8; + buffer[4] = val & 0xff; + + v4l_dbg(3, client, "msp_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val); + for (err = 0; err < 3; err++) { + if (i2c_master_send(client, buffer, 5) == 5) + break; + v4l_warn(client, "I/O error #%d (write 0x%02x/0x%02x)\n", err, + dev, addr); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(msecs_to_jiffies(10)); + } + if (err == 3) { + v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n"); + msp_reset(client); + return -1; + } + return 0; +} + +int msp_write_dem(struct i2c_client *client, int addr, int val) +{ + return msp_write(client, I2C_MSP_DEM, addr, val); +} + +int msp_write_dsp(struct i2c_client *client, int addr, int val) +{ + return msp_write(client, I2C_MSP_DSP, addr, val); +} + +/* ----------------------------------------------------------------------- * + * bits 9 8 5 - SCART DSP input Select: + * 0 0 0 - SCART 1 to DSP input (reset position) + * 0 1 0 - MONO to DSP input + * 1 0 0 - SCART 2 to DSP input + * 1 1 1 - Mute DSP input + * + * bits 11 10 6 - SCART 1 Output Select: + * 0 0 0 - undefined (reset position) + * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS) + * 1 0 0 - MONO input to SCART 1 Output + * 1 1 0 - SCART 1 DA to SCART 1 Output + * 0 0 1 - SCART 2 DA to SCART 1 Output + * 0 1 1 - SCART 1 Input to SCART 1 Output + * 1 1 1 - Mute SCART 1 Output + * + * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART): + * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position) + * 0 1 0 - SCART 1 Input to SCART 2 Output + * 1 0 0 - MONO input to SCART 2 Output + * 0 0 1 - SCART 2 DA to SCART 2 Output + * 0 1 1 - SCART 2 Input to SCART 2 Output + * 1 1 0 - Mute SCART 2 Output + * + * Bits 4 to 0 should be zero. + * ----------------------------------------------------------------------- */ + +static int scarts[3][9] = { + /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ + /* SCART DSP Input select */ + { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, + /* SCART1 Output select */ + { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, + /* SCART2 Output select */ + { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, +}; + +static char *scart_names[] = { + "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute" +}; + +void msp_set_scart(struct i2c_client *client, int in, int out) +{ + struct msp_state *state = i2c_get_clientdata(client); + + state->in_scart=in; + + if (in >= 1 && in <= 8 && out >= 0 && out <= 2) { + if (-1 == scarts[out][in]) + return; + + state->acb &= ~scarts[out][SCART_MASK]; + state->acb |= scarts[out][in]; + } else + state->acb = 0xf60; /* Mute Input and SCART 1 Output */ + + v4l_dbg(1, client, "scart switch: %s => %d (ACB=0x%04x)\n", + scart_names[in], out, state->acb); + msp_write_dsp(client, 0x13, state->acb); + + /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */ + msp_write_dem(client, 0x40, state->i2s_mode); +} + +void msp_set_mute(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + v4l_dbg(1, client, "mute audio\n"); + msp_write_dsp(client, 0x0000, 0); + msp_write_dsp(client, 0x0007, 1); + if (state->has_scart2_out_volume) + msp_write_dsp(client, 0x0040, 1); + if (state->has_headphones) + msp_write_dsp(client, 0x0006, 0); +} + +void msp_set_audio(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + int bal = 0, bass, treble, loudness; + int val = 0; + + if (!state->muted) + val = (state->volume * 0x7f / 65535) << 8; + + v4l_dbg(1, client, "mute=%s volume=%d\n", + state->muted ? "on" : "off", state->volume); + + msp_write_dsp(client, 0x0000, val); + msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1)); + if (state->has_scart2_out_volume) + msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1)); + if (state->has_headphones) + msp_write_dsp(client, 0x0006, val); + if (!state->has_sound_processing) + return; + + if (val) + bal = (u8)((state->balance / 256) - 128); + bass = ((state->bass - 32768) * 0x60 / 65535) << 8; + treble = ((state->treble - 32768) * 0x60 / 65535) << 8; + loudness = state->loudness ? ((5 * 4) << 8) : 0; + + v4l_dbg(1, client, "balance=%d bass=%d treble=%d loudness=%d\n", + state->balance, state->bass, state->treble, state->loudness); + + msp_write_dsp(client, 0x0001, bal << 8); + msp_write_dsp(client, 0x0002, bass); + msp_write_dsp(client, 0x0003, treble); + msp_write_dsp(client, 0x0004, loudness); + if (!state->has_headphones) + return; + msp_write_dsp(client, 0x0030, bal << 8); + msp_write_dsp(client, 0x0031, bass); + msp_write_dsp(client, 0x0032, treble); + msp_write_dsp(client, 0x0033, loudness); +} + +int msp_modus(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + if (state->radio) { + v4l_dbg(1, client, "video mode selected to Radio\n"); + return 0x0003; + } + + if (state->v4l2_std & V4L2_STD_PAL) { + v4l_dbg(1, client, "video mode selected to PAL\n"); + +#if 1 + /* experimental: not sure this works with all chip versions */ + return 0x7003; +#else + /* previous value, try this if it breaks ... */ + return 0x1003; +#endif + } + if (state->v4l2_std & V4L2_STD_NTSC) { + v4l_dbg(1, client, "video mode selected to NTSC\n"); + return 0x2003; + } + if (state->v4l2_std & V4L2_STD_SECAM) { + v4l_dbg(1, client, "video mode selected to SECAM\n"); + return 0x0003; + } + return 0x0003; +} + +/* ------------------------------------------------------------------------ */ + + +static void msp_wake_thread(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + if (NULL == state->kthread) + return; + msp_set_mute(client); + state->watch_stereo = 0; + state->restart = 1; + wake_up_interruptible(&state->wq); +} + +int msp_sleep(struct msp_state *state, int timeout) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&state->wq, &wait); + if (!kthread_should_stop()) { + if (timeout < 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } else { + schedule_timeout_interruptible + (msecs_to_jiffies(timeout)); + } + } + + remove_wait_queue(&state->wq, &wait); + try_to_freeze(); + return state->restart; +} + +/* ------------------------------------------------------------------------ */ + +static int msp_mode_v4l2_to_v4l1(int rxsubchans) +{ + int mode = 0; + + if (rxsubchans & V4L2_TUNER_SUB_STEREO) + mode |= VIDEO_SOUND_STEREO; + if (rxsubchans & V4L2_TUNER_SUB_LANG2) + mode |= VIDEO_SOUND_LANG2; + if (rxsubchans & V4L2_TUNER_SUB_LANG1) + mode |= VIDEO_SOUND_LANG1; + if (mode == 0) + mode |= VIDEO_SOUND_MONO; + return mode; +} + +static int msp_mode_v4l1_to_v4l2(int mode) +{ + if (mode & VIDEO_SOUND_STEREO) + return V4L2_TUNER_MODE_STEREO; + if (mode & VIDEO_SOUND_LANG2) + return V4L2_TUNER_MODE_LANG2; + if (mode & VIDEO_SOUND_LANG1) + return V4L2_TUNER_MODE_LANG1; + return V4L2_TUNER_MODE_MONO; +} + +static void msp_any_detect_stereo(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + switch (state->opmode) { + case OPMODE_MANUAL: + case OPMODE_AUTODETECT: + autodetect_stereo(client); + break; + case OPMODE_AUTOSELECT: + msp34xxg_detect_stereo(client); + break; + } +} + +static struct v4l2_queryctrl msp_qctrl_std[] = { + { + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 58880, + .flags = 0, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .flags = 0, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, +}; + +static struct v4l2_queryctrl msp_qctrl_sound_processing[] = { + { + .id = V4L2_CID_AUDIO_BALANCE, + .name = "Balance", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + .flags = 0, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_AUDIO_BASS, + .name = "Bass", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_AUDIO_TREBLE, + .name = "Treble", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_AUDIO_LOUDNESS, + .name = "Loudness", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .flags = 0, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, +}; + + +static void msp_any_set_audmode(struct i2c_client *client, int audmode) +{ + struct msp_state *state = i2c_get_clientdata(client); + + switch (state->opmode) { + case OPMODE_MANUAL: + case OPMODE_AUTODETECT: + state->watch_stereo = 0; + msp3400c_setstereo(client, audmode); + break; + case OPMODE_AUTOSELECT: + msp34xxg_set_audmode(client, audmode); + break; + } +} + +static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +{ + struct msp_state *state = i2c_get_clientdata(client); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = state->volume; + break; + + case V4L2_CID_AUDIO_MUTE: + ctrl->value = state->muted; + break; + + case V4L2_CID_AUDIO_BALANCE: + if (!state->has_sound_processing) + return -EINVAL; + ctrl->value = state->balance; + break; + + case V4L2_CID_AUDIO_BASS: + if (!state->has_sound_processing) + return -EINVAL; + ctrl->value = state->bass; + break; + + case V4L2_CID_AUDIO_TREBLE: + if (!state->has_sound_processing) + return -EINVAL; + ctrl->value = state->treble; + break; + + case V4L2_CID_AUDIO_LOUDNESS: + if (!state->has_sound_processing) + return -EINVAL; + ctrl->value = state->loudness; + break; + + default: + return -EINVAL; + } + return 0; +} + +static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +{ + struct msp_state *state = i2c_get_clientdata(client); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + state->volume = ctrl->value; + if (state->volume == 0) + state->balance = 32768; + break; + + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value < 0 || ctrl->value >= 2) + return -ERANGE; + state->muted = ctrl->value; + break; + + case V4L2_CID_AUDIO_BASS: + if (!state->has_sound_processing) + return -EINVAL; + state->bass = ctrl->value; + break; + + case V4L2_CID_AUDIO_TREBLE: + if (!state->has_sound_processing) + return -EINVAL; + state->treble = ctrl->value; + break; + + case V4L2_CID_AUDIO_LOUDNESS: + if (!state->has_sound_processing) + return -EINVAL; + state->loudness = ctrl->value; + break; + + case V4L2_CID_AUDIO_BALANCE: + if (!state->has_sound_processing) + return -EINVAL; + state->balance = ctrl->value; + break; + + default: + return -EINVAL; + } + msp_set_audio(client); + return 0; +} + +static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + struct msp_state *state = i2c_get_clientdata(client); + u16 *sarg = arg; + int scart = 0; + + if (debug >= 2) + v4l_i2c_print_ioctl(client, cmd); + + switch (cmd) { + case AUDC_SET_INPUT: + if (*sarg == state->input) + break; + state->input = *sarg; + switch (*sarg) { + case AUDIO_RADIO: + /* Hauppauge uses IN2 for the radio */ + state->mode = MSP_MODE_FM_RADIO; + scart = SCART_IN2; + break; + case AUDIO_EXTERN_1: + /* IN1 is often used for external input ... */ + state->mode = MSP_MODE_EXTERN; + scart = SCART_IN1; + break; + case AUDIO_EXTERN_2: + /* ... sometimes it is IN2 through ;) */ + state->mode = MSP_MODE_EXTERN; + scart = SCART_IN2; + break; + case AUDIO_TUNER: + state->mode = -1; + break; + default: + if (*sarg & AUDIO_MUTE) + msp_set_scart(client, SCART_MUTE, 0); + break; + } + if (scart) { + state->rxsubchans = V4L2_TUNER_SUB_STEREO; + state->audmode = V4L2_TUNER_MODE_STEREO; + msp_set_scart(client, scart, 0); + msp_write_dsp(client, 0x000d, 0x1900); + if (state->opmode != OPMODE_AUTOSELECT) + msp3400c_setstereo(client, state->audmode); + } + msp_wake_thread(client); + break; + + case AUDC_SET_RADIO: + if (state->radio) + return 0; + state->radio = 1; + v4l_dbg(1, client, "switching to radio mode\n"); + state->watch_stereo = 0; + switch (state->opmode) { + case OPMODE_MANUAL: + /* set msp3400 to FM radio mode */ + msp3400c_setmode(client, MSP_MODE_FM_RADIO); + msp3400c_setcarrier(client, MSP_CARRIER(10.7), + MSP_CARRIER(10.7)); + msp_set_audio(client); + break; + case OPMODE_AUTODETECT: + case OPMODE_AUTOSELECT: + /* the thread will do for us */ + msp_wake_thread(client); + break; + } + break; + + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + + va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE; + if (state->has_sound_processing) + va->flags |= VIDEO_AUDIO_BALANCE | + VIDEO_AUDIO_BASS | + VIDEO_AUDIO_TREBLE; + if (state->muted) + va->flags |= VIDEO_AUDIO_MUTE; + va->volume = state->volume; + va->balance = state->volume ? state->balance : 32768; + va->bass = state->bass; + va->treble = state->treble; + + if (state->radio) + break; + if (state->opmode == OPMODE_AUTOSELECT) + msp_any_detect_stereo(client); + va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans); + break; + } + + case VIDIOCSAUDIO: + { + struct video_audio *va = arg; + + state->muted = (va->flags & VIDEO_AUDIO_MUTE); + state->volume = va->volume; + state->balance = va->balance; + state->bass = va->bass; + state->treble = va->treble; + msp_set_audio(client); + + if (va->mode != 0 && state->radio == 0) + msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode)); + break; + } + + case VIDIOCSCHAN: + { + struct video_channel *vc = arg; + int update = 0; + v4l2_std_id std; + + if (state->radio) + update = 1; + state->radio = 0; + if (vc->norm == VIDEO_MODE_PAL) + std = V4L2_STD_PAL; + else if (vc->norm == VIDEO_MODE_SECAM) + std = V4L2_STD_SECAM; + else + std = V4L2_STD_NTSC; + if (std != state->v4l2_std) { + state->v4l2_std = std; + update = 1; + } + if (update) + msp_wake_thread(client); + break; + } + + case VIDIOCSFREQ: + case VIDIOC_S_FREQUENCY: + { + /* new channel -- kick audio carrier scan */ + msp_wake_thread(client); + break; + } + + /* msp34xx specific */ + case MSP_SET_MATRIX: + { + struct msp_matrix *mspm = arg; + + msp_set_scart(client, mspm->input, mspm->output); + break; + } + + /* --- v4l2 ioctls --- */ + case VIDIOC_S_STD: + { + v4l2_std_id *id = arg; + int update = state->radio || state->v4l2_std != *id; + + state->v4l2_std = *id; + state->radio = 0; + if (update) + msp_wake_thread(client); + return 0; + } + + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + + if (i->index != 0) + return -EINVAL; + + i->type = V4L2_INPUT_TYPE_TUNER; + switch (i->index) { + case AUDIO_RADIO: + strcpy(i->name, "Radio"); + break; + case AUDIO_EXTERN_1: + strcpy(i->name, "Extern 1"); + break; + case AUDIO_EXTERN_2: + strcpy(i->name, "Extern 2"); + break; + case AUDIO_TUNER: + strcpy(i->name, "Television"); + break; + default: + return -EINVAL; + } + return 0; + } + + case VIDIOC_G_AUDIO: + { + struct v4l2_audio *a = arg; + + memset(a, 0, sizeof(*a)); + + switch (a->index) { + case AUDIO_RADIO: + strcpy(a->name, "Radio"); + break; + case AUDIO_EXTERN_1: + strcpy(a->name, "Extern 1"); + break; + case AUDIO_EXTERN_2: + strcpy(a->name, "Extern 2"); + break; + case AUDIO_TUNER: + strcpy(a->name, "Television"); + break; + default: + return -EINVAL; + } + + msp_any_detect_stereo(client); + if (state->audmode == V4L2_TUNER_MODE_STEREO) { + a->capability = V4L2_AUDCAP_STEREO; + } + + break; + } + + case VIDIOC_S_AUDIO: + { + struct v4l2_audio *sarg = arg; + + switch (sarg->index) { + case AUDIO_RADIO: + /* Hauppauge uses IN2 for the radio */ + state->mode = MSP_MODE_FM_RADIO; + scart = SCART_IN2; + break; + case AUDIO_EXTERN_1: + /* IN1 is often used for external input ... */ + state->mode = MSP_MODE_EXTERN; + scart = SCART_IN1; + break; + case AUDIO_EXTERN_2: + /* ... sometimes it is IN2 through ;) */ + state->mode = MSP_MODE_EXTERN; + scart = SCART_IN2; + break; + case AUDIO_TUNER: + state->mode = -1; + break; + } + if (scart) { + state->rxsubchans = V4L2_TUNER_SUB_STEREO; + state->audmode = V4L2_TUNER_MODE_STEREO; + msp_set_scart(client, scart, 0); + msp_write_dsp(client, 0x000d, 0x1900); + } + if (sarg->capability == V4L2_AUDCAP_STEREO) { + state->audmode = V4L2_TUNER_MODE_STEREO; + } else { + state->audmode &= ~V4L2_TUNER_MODE_STEREO; + } + msp_any_set_audmode(client, state->audmode); + msp_wake_thread(client); + break; + } + + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *vt = arg; + + if (state->radio) + break; + if (state->opmode == OPMODE_AUTOSELECT) + msp_any_detect_stereo(client); + vt->audmode = state->audmode; + vt->rxsubchans = state->rxsubchans; + vt->capability = V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; + break; + } + + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; + + if (state->radio) + break; + /* only set audmode */ + if (vt->audmode != -1 && vt->audmode != 0) + msp_any_set_audmode(client, vt->audmode); + break; + } + + case VIDIOC_G_AUDOUT: + { + struct v4l2_audioout *a = (struct v4l2_audioout *)arg; + int idx = a->index; + + memset(a, 0, sizeof(*a)); + + switch (idx) { + case 0: + strcpy(a->name, "Scart1 Out"); + break; + case 1: + strcpy(a->name, "Scart2 Out"); + break; + case 2: + strcpy(a->name, "I2S Out"); + break; + default: + return -EINVAL; + } + break; + + } + + case VIDIOC_S_AUDOUT: + { + struct v4l2_audioout *a = (struct v4l2_audioout *)arg; + + if (a->index < 0 || a->index > 2) + return -EINVAL; + + v4l_dbg(1, client, "Setting audio out on msp34xx to input %i\n", a->index); + msp_set_scart(client, state->in_scart, a->index + 1); + + break; + } + + case VIDIOC_INT_I2S_CLOCK_FREQ: + { + u32 *a = (u32 *)arg; + + v4l_dbg(1, client, "Setting I2S speed to %d\n", *a); + + switch (*a) { + case 1024000: + state->i2s_mode = 0; + break; + case 2048000: + state->i2s_mode = 1; + break; + default: + return -EINVAL; + } + break; + } + + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + int i; + + for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++) + if (qc->id && qc->id == msp_qctrl_std[i].id) { + memcpy(qc, &msp_qctrl_std[i], sizeof(*qc)); + return 0; + } + if (!state->has_sound_processing) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++) + if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) { + memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc)); + return 0; + } + return -EINVAL; + } + + case VIDIOC_G_CTRL: + return msp_get_ctrl(client, arg); + + case VIDIOC_S_CTRL: + return msp_set_ctrl(client, arg); + + case VIDIOC_LOG_STATUS: + { + const char *p; + + if (state->opmode == OPMODE_AUTOSELECT) + msp_any_detect_stereo(client); + v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", + client->name, state->rev1, state->rev2); + v4l_info(client, "Audio: volume %d%s\n", + state->volume, state->muted ? " (muted)" : ""); + if (state->has_sound_processing) { + v4l_info(client, "Audio: balance %d bass %d treble %d loudness %s\n", + state->balance, state->bass, state->treble, + state->loudness ? "on" : "off"); + } + switch (state->mode) { + case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break; + case MSP_MODE_FM_RADIO: p = "FM Radio"; break; + case MSP_MODE_FM_TERRA: p = "Terrestial FM-mono + FM-stereo"; break; + case MSP_MODE_FM_SAT: p = "Satellite FM-mono"; break; + case MSP_MODE_FM_NICAM1: p = "NICAM/FM (B/G, D/K)"; break; + case MSP_MODE_FM_NICAM2: p = "NICAM/FM (I)"; break; + case MSP_MODE_AM_NICAM: p = "NICAM/AM (L)"; break; + case MSP_MODE_BTSC: p = "BTSC"; break; + case MSP_MODE_EXTERN: p = "External input"; break; + default: p = "unknown"; break; + } + if (state->opmode == OPMODE_MANUAL) { + v4l_info(client, "Mode: %s (%s%s)\n", p, + (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", + (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); + } else { + v4l_info(client, "Mode: %s\n", p); + v4l_info(client, "Standard: %s (%s%s)\n", + msp_standard_std_name(state->std), + (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", + (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); + } + v4l_info(client, "ACB: 0x%04x\n", state->acb); + break; + } + + default: + /* nothing */ + break; + } + return 0; +} + +static int msp_suspend(struct device * dev, pm_message_t state) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + v4l_dbg(1, client, "suspend\n"); + msp_reset(client); + return 0; +} + +static int msp_resume(struct device * dev) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + v4l_dbg(1, client, "resume\n"); + msp_wake_thread(client); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static struct i2c_driver i2c_driver; + +static int msp_attach(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct msp_state *state; + int (*thread_func)(void *data) = NULL; + int msp_hard; + int msp_family; + int msp_revision; + int msp_product, msp_prod_hi, msp_prod_lo; + int msp_rom; + + client = kmalloc(sizeof(*client), GFP_KERNEL); + if (client == NULL) + return -ENOMEM; + memset(client, 0, sizeof(*client)); + client->addr = address; + client->adapter = adapter; + client->driver = &i2c_driver; + snprintf(client->name, sizeof(client->name) - 1, "msp3400"); + + if (msp_reset(client) == -1) { + v4l_dbg(1, client, "msp3400 not found\n"); + kfree(client); + return -1; + } + + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) { + kfree(client); + return -ENOMEM; + } + i2c_set_clientdata(client, state); + + memset(state, 0, sizeof(*state)); + state->v4l2_std = V4L2_STD_NTSC; + state->volume = 58880; /* 0db gain */ + state->balance = 32768; /* 0db gain */ + state->bass = 32768; + state->treble = 32768; + state->loudness = 0; + state->input = -1; + state->muted = 0; + state->i2s_mode = 0; + init_waitqueue_head(&state->wq); + + state->rev1 = msp_read_dsp(client, 0x1e); + if (state->rev1 != -1) + state->rev2 = msp_read_dsp(client, 0x1f); + v4l_dbg(1, client, "rev1=0x%04x, rev2=0x%04x\n", state->rev1, state->rev2); + if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) { + v4l_dbg(1, client, "not an msp3400 (cannot read chip version)\n"); + kfree(state); + kfree(client); + return -1; + } + + msp_set_audio(client); + + msp_family = ((state->rev1 >> 4) & 0x0f) + 3; + msp_product = (state->rev2 >> 8) & 0xff; + msp_prod_hi = msp_product / 10; + msp_prod_lo = msp_product % 10; + msp_revision = (state->rev1 & 0x0f) + '@'; + msp_hard = ((state->rev1 >> 8) & 0xff) + '@'; + msp_rom = state->rev2 & 0x1f; + snprintf(client->name, sizeof(client->name), "MSP%d4%02d%c-%c%d", + msp_family, msp_product, + msp_revision, msp_hard, msp_rom); + + /* Has NICAM support: all mspx41x and mspx45x products have NICAM */ + state->has_nicam = msp_prod_hi == 1 || msp_prod_hi == 5; + /* Has radio support: was added with revision G */ + state->has_radio = msp_revision >= 'G'; + /* Has headphones output: not for stripped down products */ + state->has_headphones = msp_prod_lo < 5; + /* Has scart4 input: not in pre D revisions, not in stripped D revs */ + state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5); + /* Has scart2 and scart3 inputs and scart2 output: not in stripped + down products of the '3' family */ + state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5; + /* Has scart2 a volume control? Not in pre-D revisions. */ + state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out; + /* Has a configurable i2s out? */ + state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7; + /* Has subwoofer output: not in pre-D revs and not in stripped down products */ + state->has_subwoofer = msp_revision >= 'D' && msp_prod_lo < 5; + /* Has soundprocessing (bass/treble/balance/loudness/equalizer): not in + stripped down products */ + state->has_sound_processing = msp_prod_lo < 7; + /* Has Virtual Dolby Surround: only in msp34x1 */ + state->has_virtual_dolby_surround = msp_revision == 'G' && msp_prod_lo == 1; + /* Has Virtual Dolby Surround & Dolby Pro Logic: only in msp34x2 */ + state->has_dolby_pro_logic = msp_revision == 'G' && msp_prod_lo == 2; + + state->opmode = opmode; + if (state->opmode == OPMODE_AUTO) { + /* MSP revision G and up have both autodetect and autoselect */ + if (msp_revision >= 'G') + state->opmode = OPMODE_AUTOSELECT; + /* MSP revision D and up have autodetect */ + else if (msp_revision >= 'D') + state->opmode = OPMODE_AUTODETECT; + else + state->opmode = OPMODE_MANUAL; + } + + /* hello world :-) */ + v4l_info(client, "%s found @ 0x%x (%s)\n", client->name, address << 1, adapter->name); + v4l_info(client, "%s ", client->name); + if (state->has_nicam && state->has_radio) + printk("supports nicam and radio, "); + else if (state->has_nicam) + printk("supports nicam, "); + else if (state->has_radio) + printk("supports radio, "); + printk("mode is "); + + /* version-specific initialization */ + switch (state->opmode) { + case OPMODE_MANUAL: + printk("manual"); + thread_func = msp3400c_thread; + break; + case OPMODE_AUTODETECT: + printk("autodetect"); + thread_func = msp3410d_thread; + break; + case OPMODE_AUTOSELECT: + printk("autodetect and autoselect"); + thread_func = msp34xxg_thread; + break; + } + printk("\n"); + + /* startup control thread if needed */ + if (thread_func) { + state->kthread = kthread_run(thread_func, client, "msp34xx"); + + if (state->kthread == NULL) + v4l_warn(client, "kernel_thread() failed\n"); + msp_wake_thread(client); + } + + /* done */ + i2c_attach_client(client); + + return 0; +} + +static int msp_probe(struct i2c_adapter *adapter) +{ + if (adapter->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adapter, &addr_data, msp_attach); + return 0; +} + +static int msp_detach(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + int err; + + /* shutdown control thread */ + if (state->kthread) { + state->restart = 1; + kthread_stop(state->kthread); + } + msp_reset(client); + + err = i2c_detach_client(client); + if (err) { + return err; + } + + kfree(state); + kfree(client); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ +static struct i2c_driver i2c_driver = { + .id = I2C_DRIVERID_MSP3400, + .attach_adapter = msp_probe, + .detach_client = msp_detach, + .command = msp_command, + .driver = { + .name = "msp3400", + .suspend = msp_suspend, + .resume = msp_resume, + }, +}; + +static int __init msp3400_init_module(void) +{ + return i2c_add_driver(&i2c_driver); +} + +static void __exit msp3400_cleanup_module(void) +{ + i2c_del_driver(&i2c_driver); +} + +module_init(msp3400_init_module); +module_exit(msp3400_cleanup_module); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c new file mode 100644 index 000000000000..2b59b6847535 --- /dev/null +++ b/drivers/media/video/msp3400-kthreads.c @@ -0,0 +1,1010 @@ +/* + * Programming the mspx4xx sound processor family + * + * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/videodev.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <media/audiochip.h> +#include <linux/kthread.h> +#include <linux/suspend.h> +#include "msp3400.h" + +/* this one uses the automatic sound standard detection of newer msp34xx + chip versions */ +static struct { + int retval; + int main, second; + char *name; +} msp_stdlist[] = { + { 0x0000, 0, 0, "could not detect sound standard" }, + { 0x0001, 0, 0, "autodetect start" }, + { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" }, + { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" }, + { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" }, + { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" }, + { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" }, + { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" }, + { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" }, + { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" }, + { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" }, + { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" }, + { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" }, + { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" }, + { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" }, + { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" }, + { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" }, + { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" }, + { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" }, + { -1, 0, 0, NULL }, /* EOF */ +}; + +static struct msp3400c_init_data_dem { + int fir1[6]; + int fir2[6]; + int cdo1; + int cdo2; + int ad_cv; + int mode_reg; + int dsp_src; + int dsp_matrix; +} msp3400c_init_data[] = { + { /* AM (for carrier detect / msp3400) */ + {75, 19, 36, 35, 39, 40}, + {75, 19, 36, 35, 39, 40}, + MSP_CARRIER(5.5), MSP_CARRIER(5.5), + 0x00d0, 0x0500, 0x0020, 0x3000 + },{ /* AM (for carrier detect / msp3410) */ + {-1, -1, -8, 2, 59, 126}, + {-1, -1, -8, 2, 59, 126}, + MSP_CARRIER(5.5), MSP_CARRIER(5.5), + 0x00d0, 0x0100, 0x0020, 0x3000 + },{ /* FM Radio */ + {-8, -8, 4, 6, 78, 107}, + {-8, -8, 4, 6, 78, 107}, + MSP_CARRIER(10.7), MSP_CARRIER(10.7), + 0x00d0, 0x0480, 0x0020, 0x3000 + },{ /* Terrestial FM-mono + FM-stereo */ + {3, 18, 27, 48, 66, 72}, + {3, 18, 27, 48, 66, 72}, + MSP_CARRIER(5.5), MSP_CARRIER(5.5), + 0x00d0, 0x0480, 0x0030, 0x3000 + },{ /* Sat FM-mono */ + { 1, 9, 14, 24, 33, 37}, + { 3, 18, 27, 48, 66, 72}, + MSP_CARRIER(6.5), MSP_CARRIER(6.5), + 0x00c6, 0x0480, 0x0000, 0x3000 + },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */ + {-2, -8, -10, 10, 50, 86}, + {3, 18, 27, 48, 66, 72}, + MSP_CARRIER(5.5), MSP_CARRIER(5.5), + 0x00d0, 0x0040, 0x0120, 0x3000 + },{ /* NICAM/FM -- I (6.0/6.552) */ + {2, 4, -6, -4, 40, 94}, + {3, 18, 27, 48, 66, 72}, + MSP_CARRIER(6.0), MSP_CARRIER(6.0), + 0x00d0, 0x0040, 0x0120, 0x3000 + },{ /* NICAM/AM -- L (6.5/5.85) */ + {-2, -8, -10, 10, 50, 86}, + {-4, -12, -9, 23, 79, 126}, + MSP_CARRIER(6.5), MSP_CARRIER(6.5), + 0x00c6, 0x0140, 0x0120, 0x7c03 + }, +}; + +struct msp3400c_carrier_detect { + int cdo; + char *name; +}; + +static struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = { + /* main carrier */ + { MSP_CARRIER(4.5), "4.5 NTSC" }, + { MSP_CARRIER(5.5), "5.5 PAL B/G" }, + { MSP_CARRIER(6.0), "6.0 PAL I" }, + { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" } +}; + +static struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = { + /* PAL B/G */ + { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" }, + { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" } +}; + +static struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = { + /* PAL SAT / SECAM */ + { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" }, + { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" }, + { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" }, + { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" }, + { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" }, + { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" }, +}; + +/* ------------------------------------------------------------------------ */ + +const char *msp_standard_std_name(int std) +{ + int i; + + for (i = 0; msp_stdlist[i].name != NULL; i++) + if (msp_stdlist[i].retval == std) + return msp_stdlist[i].name; + return "unknown"; +} + +void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2) +{ + msp_write_dem(client, 0x0093, cdo1 & 0xfff); + msp_write_dem(client, 0x009b, cdo1 >> 12); + msp_write_dem(client, 0x00a3, cdo2 & 0xfff); + msp_write_dem(client, 0x00ab, cdo2 >> 12); + msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/ +} + +void msp3400c_setmode(struct i2c_client *client, int type) +{ + struct msp_state *state = i2c_get_clientdata(client); + int i; + + v4l_dbg(1, client, "setmode: %d\n", type); + state->mode = type; + state->audmode = V4L2_TUNER_MODE_MONO; + state->rxsubchans = V4L2_TUNER_SUB_MONO; + + msp_write_dem(client, 0x00bb, msp3400c_init_data[type].ad_cv); + + for (i = 5; i >= 0; i--) /* fir 1 */ + msp_write_dem(client, 0x0001, msp3400c_init_data[type].fir1[i]); + + msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */ + msp_write_dem(client, 0x0005, 0x0040); + msp_write_dem(client, 0x0005, 0x0000); + for (i = 5; i >= 0; i--) + msp_write_dem(client, 0x0005, msp3400c_init_data[type].fir2[i]); + + msp_write_dem(client, 0x0083, msp3400c_init_data[type].mode_reg); + + msp3400c_setcarrier(client, msp3400c_init_data[type].cdo1, + msp3400c_init_data[type].cdo2); + + msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/ + + if (dolby) { + msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ + msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */ + msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src); + } else { + msp_write_dsp(client, 0x0008, msp3400c_init_data[type].dsp_src); + msp_write_dsp(client, 0x0009, msp3400c_init_data[type].dsp_src); + msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src); + } + msp_write_dsp(client, 0x000a, msp3400c_init_data[type].dsp_src); + msp_write_dsp(client, 0x000e, msp3400c_init_data[type].dsp_matrix); + + if (state->has_nicam) { + /* nicam prescale */ + msp_write_dsp(client, 0x0010, 0x5a00); /* was: 0x3000 */ + } +} + +/* turn on/off nicam + stereo */ +void msp3400c_setstereo(struct i2c_client *client, int mode) +{ + static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; + struct msp_state *state = i2c_get_clientdata(client); + int nicam = 0; /* channel source: FM/AM or nicam */ + int src = 0; + + if (state->opmode == OPMODE_AUTOSELECT) { + /* this method would break everything, let's make sure + * it's never called + */ + v4l_dbg(1, client, "setstereo called with mode=%d instead of set_source (ignored)\n", + mode); + return; + } + + /* switch demodulator */ + switch (state->mode) { + case MSP_MODE_FM_TERRA: + v4l_dbg(1, client, "FM setstereo: %s\n", strmode[mode]); + msp3400c_setcarrier(client, state->second, state->main); + switch (mode) { + case V4L2_TUNER_MODE_STEREO: + msp_write_dsp(client, 0x000e, 0x3001); + break; + case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_LANG1: + case V4L2_TUNER_MODE_LANG2: + msp_write_dsp(client, 0x000e, 0x3000); + break; + } + break; + case MSP_MODE_FM_SAT: + v4l_dbg(1, client, "SAT setstereo: %s\n", strmode[mode]); + switch (mode) { + case V4L2_TUNER_MODE_MONO: + msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); + break; + case V4L2_TUNER_MODE_STEREO: + msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); + break; + case V4L2_TUNER_MODE_LANG1: + msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); + break; + case V4L2_TUNER_MODE_LANG2: + msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); + break; + } + break; + case MSP_MODE_FM_NICAM1: + case MSP_MODE_FM_NICAM2: + case MSP_MODE_AM_NICAM: + v4l_dbg(1, client, "NICAM setstereo: %s\n",strmode[mode]); + msp3400c_setcarrier(client,state->second,state->main); + if (state->nicam_on) + nicam=0x0100; + break; + case MSP_MODE_BTSC: + v4l_dbg(1, client, "BTSC setstereo: %s\n",strmode[mode]); + nicam=0x0300; + break; + case MSP_MODE_EXTERN: + v4l_dbg(1, client, "extern setstereo: %s\n",strmode[mode]); + nicam = 0x0200; + break; + case MSP_MODE_FM_RADIO: + v4l_dbg(1, client, "FM-Radio setstereo: %s\n",strmode[mode]); + break; + default: + v4l_dbg(1, client, "mono setstereo\n"); + return; + } + + /* switch audio */ + switch (mode) { + case V4L2_TUNER_MODE_STEREO: + src = 0x0020 | nicam; + break; + case V4L2_TUNER_MODE_MONO: + if (state->mode == MSP_MODE_AM_NICAM) { + v4l_dbg(1, client, "switching to AM mono\n"); + /* AM mono decoding is handled by tuner, not MSP chip */ + /* SCART switching control register */ + msp_set_scart(client, SCART_MONO, 0); + src = 0x0200; + break; + } + case V4L2_TUNER_MODE_LANG1: + src = 0x0000 | nicam; + break; + case V4L2_TUNER_MODE_LANG2: + src = 0x0010 | nicam; + break; + } + v4l_dbg(1, client, "setstereo final source/matrix = 0x%x\n", src); + + if (dolby) { + msp_write_dsp(client, 0x0008, 0x0520); + msp_write_dsp(client, 0x0009, 0x0620); + msp_write_dsp(client, 0x000a, src); + msp_write_dsp(client, 0x000b, src); + } else { + msp_write_dsp(client, 0x0008, src); + msp_write_dsp(client, 0x0009, src); + msp_write_dsp(client, 0x000a, src); + msp_write_dsp(client, 0x000b, src); + msp_write_dsp(client, 0x000c, src); + if (state->has_scart23_in_scart2_out) + msp_write_dsp(client, 0x0041, src); + } +} + +static void msp3400c_print_mode(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + if (state->main == state->second) { + v4l_dbg(1, client, "mono sound carrier: %d.%03d MHz\n", + state->main / 910000, (state->main / 910) % 1000); + } else { + v4l_dbg(1, client, "main sound carrier: %d.%03d MHz\n", + state->main / 910000, (state->main / 910) % 1000); + } + if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2) + v4l_dbg(1, client, "NICAM/FM carrier : %d.%03d MHz\n", + state->second / 910000, (state->second/910) % 1000); + if (state->mode == MSP_MODE_AM_NICAM) + v4l_dbg(1, client, "NICAM/AM carrier : %d.%03d MHz\n", + state->second / 910000, (state->second / 910) % 1000); + if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) { + v4l_dbg(1, client, "FM-stereo carrier : %d.%03d MHz\n", + state->second / 910000, (state->second / 910) % 1000); + } +} + +/* ----------------------------------------------------------------------- */ + +int autodetect_stereo(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + int val; + int rxsubchans = state->rxsubchans; + int newnicam = state->nicam_on; + int update = 0; + + switch (state->mode) { + case MSP_MODE_FM_TERRA: + val = msp_read_dsp(client, 0x18); + if (val > 32767) + val -= 65536; + v4l_dbg(2, client, "stereo detect register: %d\n", val); + if (val > 4096) { + rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; + } else if (val < -4096) { + rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + } else { + rxsubchans = V4L2_TUNER_SUB_MONO; + } + newnicam = 0; + break; + case MSP_MODE_FM_NICAM1: + case MSP_MODE_FM_NICAM2: + case MSP_MODE_AM_NICAM: + val = msp_read_dem(client, 0x23); + v4l_dbg(2, client, "nicam sync=%d, mode=%d\n", + val & 1, (val & 0x1e) >> 1); + + if (val & 1) { + /* nicam synced */ + switch ((val & 0x1e) >> 1) { + case 0: + case 8: + rxsubchans = V4L2_TUNER_SUB_STEREO; + break; + case 1: + case 9: + rxsubchans = V4L2_TUNER_SUB_MONO + | V4L2_TUNER_SUB_LANG1; + break; + case 2: + case 10: + rxsubchans = V4L2_TUNER_SUB_MONO + | V4L2_TUNER_SUB_LANG1 + | V4L2_TUNER_SUB_LANG2; + break; + default: + rxsubchans = V4L2_TUNER_SUB_MONO; + break; + } + newnicam = 1; + } else { + newnicam = 0; + rxsubchans = V4L2_TUNER_SUB_MONO; + } + break; + case MSP_MODE_BTSC: + val = msp_read_dem(client, 0x200); + v4l_dbg(2, client, "status=0x%x (pri=%s, sec=%s, %s%s%s)\n", + val, + (val & 0x0002) ? "no" : "yes", + (val & 0x0004) ? "no" : "yes", + (val & 0x0040) ? "stereo" : "mono", + (val & 0x0080) ? ", nicam 2nd mono" : "", + (val & 0x0100) ? ", bilingual/SAP" : ""); + rxsubchans = V4L2_TUNER_SUB_MONO; + if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO; + if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1; + break; + } + if (rxsubchans != state->rxsubchans) { + update = 1; + v4l_dbg(1, client, "watch: rxsubchans %d => %d\n", + state->rxsubchans,rxsubchans); + state->rxsubchans = rxsubchans; + } + if (newnicam != state->nicam_on) { + update = 1; + v4l_dbg(1, client, "watch: nicam %d => %d\n", + state->nicam_on,newnicam); + state->nicam_on = newnicam; + } + return update; +} + +/* + * A kernel thread for msp3400 control -- we don't want to block the + * in the ioctl while doing the sound carrier & stereo detect + */ +/* stereo/multilang monitoring */ +static void watch_stereo(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + if (autodetect_stereo(client)) { + if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) + msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO); + else if (state->rxsubchans & V4L2_TUNER_SUB_LANG1) + msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1); + else + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + } + + if (once) + state->watch_stereo = 0; +} + +int msp3400c_thread(void *data) +{ + struct i2c_client *client = data; + struct msp_state *state = i2c_get_clientdata(client); + struct msp3400c_carrier_detect *cd; + int count, max1,max2,val1,val2, val,this; + + + v4l_dbg(1, client, "msp3400 daemon started\n"); + for (;;) { + v4l_dbg(2, client, "msp3400 thread: sleep\n"); + msp_sleep(state, -1); + v4l_dbg(2, client, "msp3400 thread: wakeup\n"); + + restart: + v4l_dbg(1, client, "thread: restart scan\n"); + state->restart = 0; + if (kthread_should_stop()) + break; + + if (state->radio || MSP_MODE_EXTERN == state->mode) { + /* no carrier scan, just unmute */ + v4l_dbg(1, client, "thread: no carrier scan\n"); + msp_set_audio(client); + continue; + } + + /* mute */ + msp_set_mute(client); + msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ ); + val1 = val2 = 0; + max1 = max2 = -1; + state->watch_stereo = 0; + + /* some time for the tuner to sync */ + if (msp_sleep(state,200)) + goto restart; + + /* carrier detect pass #1 -- main carrier */ + cd = msp3400c_carrier_detect_main; + count = ARRAY_SIZE(msp3400c_carrier_detect_main); + + if (amsound && (state->v4l2_std & V4L2_STD_SECAM)) { + /* autodetect doesn't work well with AM ... */ + max1 = 3; + count = 0; + v4l_dbg(1, client, "AM sound override\n"); + } + + for (this = 0; this < count; this++) { + msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); + if (msp_sleep(state,100)) + goto restart; + val = msp_read_dsp(client, 0x1b); + if (val > 32767) + val -= 65536; + if (val1 < val) + val1 = val, max1 = this; + v4l_dbg(1, client, "carrier1 val: %5d / %s\n", val,cd[this].name); + } + + /* carrier detect pass #2 -- second (stereo) carrier */ + switch (max1) { + case 1: /* 5.5 */ + cd = msp3400c_carrier_detect_55; + count = ARRAY_SIZE(msp3400c_carrier_detect_55); + break; + case 3: /* 6.5 */ + cd = msp3400c_carrier_detect_65; + count = ARRAY_SIZE(msp3400c_carrier_detect_65); + break; + case 0: /* 4.5 */ + case 2: /* 6.0 */ + default: + cd = NULL; + count = 0; + break; + } + + if (amsound && (state->v4l2_std & V4L2_STD_SECAM)) { + /* autodetect doesn't work well with AM ... */ + cd = NULL; + count = 0; + max2 = 0; + } + for (this = 0; this < count; this++) { + msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); + if (msp_sleep(state,100)) + goto restart; + val = msp_read_dsp(client, 0x1b); + if (val > 32767) + val -= 65536; + if (val2 < val) + val2 = val, max2 = this; + v4l_dbg(1, client, "carrier2 val: %5d / %s\n", val,cd[this].name); + } + + /* program the msp3400 according to the results */ + state->main = msp3400c_carrier_detect_main[max1].cdo; + switch (max1) { + case 1: /* 5.5 */ + if (max2 == 0) { + /* B/G FM-stereo */ + state->second = msp3400c_carrier_detect_55[max2].cdo; + msp3400c_setmode(client, MSP_MODE_FM_TERRA); + state->nicam_on = 0; + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + state->watch_stereo = 1; + } else if (max2 == 1 && state->has_nicam) { + /* B/G NICAM */ + state->second = msp3400c_carrier_detect_55[max2].cdo; + msp3400c_setmode(client, MSP_MODE_FM_NICAM1); + state->nicam_on = 1; + msp3400c_setcarrier(client, state->second, state->main); + state->watch_stereo = 1; + } else { + goto no_second; + } + break; + case 2: /* 6.0 */ + /* PAL I NICAM */ + state->second = MSP_CARRIER(6.552); + msp3400c_setmode(client, MSP_MODE_FM_NICAM2); + state->nicam_on = 1; + msp3400c_setcarrier(client, state->second, state->main); + state->watch_stereo = 1; + break; + case 3: /* 6.5 */ + if (max2 == 1 || max2 == 2) { + /* D/K FM-stereo */ + state->second = msp3400c_carrier_detect_65[max2].cdo; + msp3400c_setmode(client, MSP_MODE_FM_TERRA); + state->nicam_on = 0; + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + state->watch_stereo = 1; + } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { + /* L NICAM or AM-mono */ + state->second = msp3400c_carrier_detect_65[max2].cdo; + msp3400c_setmode(client, MSP_MODE_AM_NICAM); + state->nicam_on = 0; + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + msp3400c_setcarrier(client, state->second, state->main); + /* volume prescale for SCART (AM mono input) */ + msp_write_dsp(client, 0x000d, 0x1900); + state->watch_stereo = 1; + } else if (max2 == 0 && state->has_nicam) { + /* D/K NICAM */ + state->second = msp3400c_carrier_detect_65[max2].cdo; + msp3400c_setmode(client, MSP_MODE_FM_NICAM1); + state->nicam_on = 1; + msp3400c_setcarrier(client, state->second, state->main); + state->watch_stereo = 1; + } else { + goto no_second; + } + break; + case 0: /* 4.5 */ + default: + no_second: + state->second = msp3400c_carrier_detect_main[max1].cdo; + msp3400c_setmode(client, MSP_MODE_FM_TERRA); + state->nicam_on = 0; + msp3400c_setcarrier(client, state->second, state->main); + state->rxsubchans = V4L2_TUNER_SUB_MONO; + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + break; + } + + /* unmute */ + msp_set_audio(client); + + if (debug) + msp3400c_print_mode(client); + + /* monitor tv audio mode */ + while (state->watch_stereo) { + if (msp_sleep(state,5000)) + goto restart; + watch_stereo(client); + } + } + v4l_dbg(1, client, "thread: exit\n"); + return 0; +} + + +int msp3410d_thread(void *data) +{ + struct i2c_client *client = data; + struct msp_state *state = i2c_get_clientdata(client); + int val, i, std; + + v4l_dbg(1, client, "msp3410 daemon started\n"); + + for (;;) { + v4l_dbg(2, client, "msp3410 thread: sleep\n"); + msp_sleep(state,-1); + v4l_dbg(2, client, "msp3410 thread: wakeup\n"); + + restart: + v4l_dbg(1, client, "thread: restart scan\n"); + state->restart = 0; + if (kthread_should_stop()) + break; + + if (state->mode == MSP_MODE_EXTERN) { + /* no carrier scan needed, just unmute */ + v4l_dbg(1, client, "thread: no carrier scan\n"); + msp_set_audio(client); + continue; + } + + /* put into sane state (and mute) */ + msp_reset(client); + + /* some time for the tuner to sync */ + if (msp_sleep(state,200)) + goto restart; + + /* start autodetect */ + if (state->radio) + std = 0x40; + else + std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; + state->watch_stereo = 0; + + if (debug) + v4l_dbg(1, client, "setting standard: %s (0x%04x)\n", + msp_standard_std_name(std), std); + + if (std != 1) { + /* programmed some specific mode */ + val = std; + } else { + /* triggered autodetect */ + msp_write_dem(client, 0x20, std); + for (;;) { + if (msp_sleep(state, 100)) + goto restart; + + /* check results */ + val = msp_read_dem(client, 0x7e); + if (val < 0x07ff) + break; + v4l_dbg(1, client, "detection still in progress\n"); + } + } + for (i = 0; msp_stdlist[i].name != NULL; i++) + if (msp_stdlist[i].retval == val) + break; + v4l_dbg(1, client, "current standard: %s (0x%04x)\n", + msp_standard_std_name(val), val); + state->main = msp_stdlist[i].main; + state->second = msp_stdlist[i].second; + state->std = val; + + if (amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) && + (val != 0x0009)) { + /* autodetection has failed, let backup */ + v4l_dbg(1, client, "autodetection failed," + " switching to backup standard: %s (0x%04x)\n", + msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val); + val = 0x0009; + msp_write_dem(client, 0x20, val); + } + + /* set various prescales */ + msp_write_dsp(client, 0x0d, 0x1900); /* scart */ + msp_write_dsp(client, 0x0e, 0x2403); /* FM */ + msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ + + /* set stereo */ + switch (val) { + case 0x0008: /* B/G NICAM */ + case 0x000a: /* I NICAM */ + if (val == 0x0008) + state->mode = MSP_MODE_FM_NICAM1; + else + state->mode = MSP_MODE_FM_NICAM2; + /* just turn on stereo */ + state->rxsubchans = V4L2_TUNER_SUB_STEREO; + state->nicam_on = 1; + state->watch_stereo = 1; + msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); + break; + case 0x0009: + state->mode = MSP_MODE_AM_NICAM; + state->rxsubchans = V4L2_TUNER_SUB_MONO; + state->nicam_on = 1; + msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO); + state->watch_stereo = 1; + break; + case 0x0020: /* BTSC */ + /* just turn on stereo */ + state->mode = MSP_MODE_BTSC; + state->rxsubchans = V4L2_TUNER_SUB_STEREO; + state->nicam_on = 0; + state->watch_stereo = 1; + msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); + break; + case 0x0040: /* FM radio */ + state->mode = MSP_MODE_FM_RADIO; + state->rxsubchans = V4L2_TUNER_SUB_STEREO; + state->audmode = V4L2_TUNER_MODE_STEREO; + state->nicam_on = 0; + state->watch_stereo = 0; + /* not needed in theory if we have radio, but + short programming enables carrier mute */ + msp3400c_setmode(client, MSP_MODE_FM_RADIO); + msp3400c_setcarrier(client, MSP_CARRIER(10.7), + MSP_CARRIER(10.7)); + /* scart routing */ + msp_set_scart(client,SCART_IN2,0); + /* msp34xx does radio decoding */ + msp_write_dsp(client, 0x08, 0x0020); + msp_write_dsp(client, 0x09, 0x0020); + msp_write_dsp(client, 0x0b, 0x0020); + break; + case 0x0003: + case 0x0004: + case 0x0005: + state->mode = MSP_MODE_FM_TERRA; + state->rxsubchans = V4L2_TUNER_SUB_MONO; + state->audmode = V4L2_TUNER_MODE_MONO; + state->nicam_on = 0; + state->watch_stereo = 1; + break; + } + + /* unmute, restore misc registers */ + msp_set_audio(client); + msp_write_dsp(client, 0x13, state->acb); + if (state->has_i2s_conf) + msp_write_dem(client, 0x40, state->i2s_mode); + + /* monitor tv audio mode */ + while (state->watch_stereo) { + if (msp_sleep(state,5000)) + goto restart; + watch_stereo(client); + } + } + v4l_dbg(1, client, "thread: exit\n"); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* msp34xxG + (autoselect no-thread) */ +/* this one uses both automatic standard detection and automatic sound */ +/* select which are available in the newer G versions */ +/* struct msp: only norm, acb and source are really used in this mode */ + +/* set the same 'source' for the loudspeaker, scart and quasi-peak detector + * the value for source is the same as bit 15:8 of DSP registers 0x08, + * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B + * + * this function replaces msp3400c_setstereo + */ +static void msp34xxg_set_source(struct i2c_client *client, int source) +{ + struct msp_state *state = i2c_get_clientdata(client); + + /* 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 ? 0x30 : 0x20); + + v4l_dbg(1, client, "set source to %d (0x%x)\n", source, value); + /* Loudspeaker Output */ + msp_write_dsp(client, 0x08, value); + /* SCART1 DA Output */ + msp_write_dsp(client, 0x0a, value); + /* Quasi-peak detector */ + msp_write_dsp(client, 0x0c, value); + /* + * set identification threshold. Personally, I + * I set it to a higher value that the default + * of 0x190 to ignore noisy stereo signals. + * this needs tuning. (recommended range 0x00a0-0x03c0) + * 0x7f0 = forced mono mode + */ + /* a2 threshold for stereo/bilingual */ + msp_write_dem(client, 0x22, stereo_threshold); + state->source = source; +} + +/* (re-)initialize the msp34xxg, according to the current norm in state->norm + * return 0 if it worked, -1 if it failed + */ +static int msp34xxg_reset(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + int modus, std; + + if (msp_reset(client)) + return -1; + + /* make sure that input/output is muted (paranoid mode) */ + /* ACB, mute DSP input, mute SCART 1 */ + if (msp_write_dsp(client, 0x13, 0x0f20)) + return -1; + + if (state->has_i2s_conf) + msp_write_dem(client, 0x40, state->i2s_mode); + + /* step-by-step initialisation, as described in the manual */ + modus = msp_modus(client); + if (state->radio) + std = 0x40; + else + std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; + modus &= ~0x03; /* STATUS_CHANGE = 0 */ + modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION = 1 */ + if (msp_write_dem(client, 0x30, modus)) + return -1; + if (msp_write_dem(client, 0x20, std)) + return -1; + + /* write the dsps that may have an influence on + standard/audio autodetection right now */ + msp34xxg_set_source(client, state->source); + + /* AM/FM Prescale [15:8] 75khz deviation */ + if (msp_write_dsp(client, 0x0e, 0x3000)) + return -1; + + /* NICAM Prescale 9db gain (as recommended) */ + if (msp_write_dsp(client, 0x10, 0x5a00)) + return -1; + + return 0; +} + +int msp34xxg_thread(void *data) +{ + struct i2c_client *client = data; + struct msp_state *state = i2c_get_clientdata(client); + int val, std, i; + + v4l_dbg(1, client, "msp34xxg daemon started\n"); + + state->source = 1; /* default */ + for (;;) { + v4l_dbg(2, client, "msp34xxg thread: sleep\n"); + msp_sleep(state, -1); + v4l_dbg(2, client, "msp34xxg thread: wakeup\n"); + + restart: + v4l_dbg(1, client, "thread: restart scan\n"); + state->restart = 0; + if (kthread_should_stop()) + break; + + /* setup the chip*/ + msp34xxg_reset(client); + std = standard; + if (std != 0x01) + goto unmute; + + /* watch autodetect */ + v4l_dbg(1, client, "triggered autodetect, waiting for result\n"); + for (i = 0; i < 10; i++) { + if (msp_sleep(state, 100)) + goto restart; + + /* check results */ + val = msp_read_dem(client, 0x7e); + if (val < 0x07ff) { + std = val; + break; + } + v4l_dbg(2, client, "detection still in progress\n"); + } + if (std == 1) { + v4l_dbg(1, client, "detection still in progress after 10 tries. giving up.\n"); + continue; + } + + unmute: + state->std = std; + v4l_dbg(1, client, "current standard: %s (0x%04x)\n", + msp_standard_std_name(std), std); + + /* unmute: dispatch sound to scart output, set scart volume */ + msp_set_audio(client); + + /* restore ACB */ + if (msp_write_dsp(client, 0x13, state->acb)) + return -1; + + msp_write_dem(client, 0x40, state->i2s_mode); + } + v4l_dbg(1, client, "thread: exit\n"); + return 0; +} + +void msp34xxg_detect_stereo(struct i2c_client *client) +{ + struct msp_state *state = i2c_get_clientdata(client); + + int status = msp_read_dem(client, 0x0200); + int is_bilingual = status & 0x100; + int is_stereo = status & 0x40; + + state->rxsubchans = 0; + if (is_stereo) + state->rxsubchans |= V4L2_TUNER_SUB_STEREO; + else + state->rxsubchans |= V4L2_TUNER_SUB_MONO; + if (is_bilingual) { + state->rxsubchans |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + /* I'm supposed to check whether it's SAP or not + * and set only LANG2/SAP in this case. Yet, the MSP + * does a lot of work to hide this and handle everything + * the same way. I don't want to work around it so unless + * this is a problem, I'll handle SAP just like lang1/lang2. + */ + } + v4l_dbg(1, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", + status, is_stereo, is_bilingual, state->rxsubchans); +} + +void msp34xxg_set_audmode(struct i2c_client *client, int audmode) +{ + struct msp_state *state = i2c_get_clientdata(client); + int source; + + switch (audmode) { + case V4L2_TUNER_MODE_MONO: + source = 0; /* mono only */ + break; + case V4L2_TUNER_MODE_STEREO: + source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ + /* problem: that could also mean 2 (scart input) */ + break; + case V4L2_TUNER_MODE_LANG1: + source = 3; /* stereo or A */ + break; + case V4L2_TUNER_MODE_LANG2: + source = 4; /* stereo or B */ + break; + default: + audmode = 0; + source = 1; + break; + } + state->audmode = audmode; + msp34xxg_set_source(client, source); +} + diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c deleted file mode 100644 index 183253e2dd91..000000000000 --- a/drivers/media/video/msp3400.c +++ /dev/null @@ -1,2229 +0,0 @@ -/* - * programming the msp34* sound processor family - * - * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org> - * - * what works and what doesn't: - * - * AM-Mono - * Support for Hauppauge cards added (decoding handled by tuner) added by - * Frederic Crozat <fcrozat@mail.dotcom.fr> - * - * FM-Mono - * should work. The stereo modes are backward compatible to FM-mono, - * therefore FM-Mono should be allways available. - * - * FM-Stereo (B/G, used in germany) - * should work, with autodetect - * - * FM-Stereo (satellite) - * should work, no autodetect (i.e. default is mono, but you can - * switch to stereo -- untested) - * - * NICAM (B/G, L , used in UK, Scandinavia, Spain and France) - * should work, with autodetect. Support for NICAM was added by - * Pekka Pietikainen <pp@netppl.fi> - * - * - * TODO: - * - better SAT support - * - * - * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch) - * using soundcore instead of OSS - * - */ - -#include <linux/config.h> -#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/i2c.h> -#include <linux/videodev.h> -#include <linux/init.h> -#include <linux/smp_lock.h> -#include <linux/kthread.h> -#include <linux/suspend.h> -#include <asm/semaphore.h> -#include <asm/pgtable.h> - -#include <media/audiochip.h> -#include "msp3400.h" - -#define msp3400_dbg(fmt, arg...) \ - do { \ - if (debug) \ - printk(KERN_INFO "%s debug %d-%04x: " fmt, \ - client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); \ - } while (0) - -/* Medium volume debug. */ -#define msp3400_dbg_mediumvol(fmt, arg...) \ - do { \ - if (debug >= 2) \ - printk(KERN_INFO "%s debug %d-%04x: " fmt, \ - client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); \ - } while (0) - -/* High volume debug. Use with care. */ -#define msp3400_dbg_highvol(fmt, arg...) \ - do { \ - if (debug >= 16) \ - printk(KERN_INFO "%s debug %d-%04x: " fmt, \ - client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); \ - } while (0) - -#define msp3400_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) -#define msp3400_warn(fmt, arg...) do { \ - printk(KERN_WARNING "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) -#define msp3400_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) - -#define OPMODE_AUTO -1 -#define OPMODE_MANUAL 0 -#define OPMODE_SIMPLE 1 /* use short programming (>= msp3410 only) */ -#define OPMODE_SIMPLER 2 /* use shorter programming (>= msp34xxG) */ - -/* insmod parameters */ -static int opmode = OPMODE_AUTO; -static int debug = 0; /* debug output */ -static int once = 0; /* no continous stereo monitoring */ -static int amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), - the autoscan seems work well only with FM... */ -static int standard = 1; /* Override auto detect of audio standard, if needed. */ -static int dolby = 0; - -static int stereo_threshold = 0x190; /* a2 threshold for stereo/bilingual - (msp34xxg only) 0x00a0-0x03c0 */ -#define DFP_COUNT 0x41 -static const int bl_dfp[] = { - 0x00, 0x01, 0x02, 0x03, 0x06, 0x08, 0x09, 0x0a, - 0x0b, 0x0d, 0x0e, 0x10 -}; - -#define IS_MSP34XX_G(msp) ((msp)->opmode==2) - -struct msp3400c { - int rev1,rev2; - - int opmode; - int nicam; - int mode; - int norm; - int stereo; - int nicam_on; - int acb; - int in_scart; - int i2s_mode; - int main, second; /* sound carrier */ - int input; - int source; /* see msp34xxg_set_source */ - - /* v4l2 */ - int audmode; - int rxsubchans; - - int muted; - int left, right; /* volume */ - int bass, treble; - - /* shadow register set */ - int dfp_regs[DFP_COUNT]; - - /* thread */ - struct task_struct *kthread; - wait_queue_head_t wq; - int restart:1; - int watch_stereo:1; -}; - -#define MIN(a,b) (((a)>(b))?(b):(a)) -#define MAX(a,b) (((a)>(b))?(a):(b)) -#define HAVE_NICAM(msp) (((msp->rev2>>8) & 0xff) != 00) -#define HAVE_SIMPLE(msp) ((msp->rev1 & 0xff) >= 'D'-'@') -#define HAVE_SIMPLER(msp) ((msp->rev1 & 0xff) >= 'G'-'@') -#define HAVE_RADIO(msp) ((msp->rev1 & 0xff) >= 'G'-'@') - -#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */ - -/* ---------------------------------------------------------------------- */ - -/* read-only */ -module_param(opmode, int, 0444); - -/* read-write */ -module_param(once, int, 0644); -module_param(debug, int, 0644); -module_param(stereo_threshold, int, 0644); -module_param(standard, int, 0644); -module_param(amsound, int, 0644); -module_param(dolby, int, 0644); - -MODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Simple, 2=Simpler"); -MODULE_PARM_DESC(once, "No continuous stereo monitoring"); -MODULE_PARM_DESC(debug, "Enable debug messages"); -MODULE_PARM_DESC(stereo_threshold, "Sets signal threshold to activate stereo"); -MODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect"); -MODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan"); -MODULE_PARM_DESC(dolby, "Activates Dolby processsing"); - -/* ---------------------------------------------------------------------- */ - -#define I2C_MSP3400C 0x80 -#define I2C_MSP3400C_ALT 0x88 - -#define I2C_MSP3400C_DEM 0x10 -#define I2C_MSP3400C_DFP 0x12 - -/* Addresses to scan */ -static unsigned short normal_i2c[] = { - I2C_MSP3400C >> 1, - I2C_MSP3400C_ALT >> 1, - I2C_CLIENT_END -}; -I2C_CLIENT_INSMOD; - -MODULE_DESCRIPTION("device driver for msp34xx TV sound processor"); -MODULE_AUTHOR("Gerd Knorr"); -MODULE_LICENSE("GPL"); - -/* ----------------------------------------------------------------------- */ -/* functions for talking to the MSP3400C Sound processor */ - -static int msp3400c_reset(struct i2c_client *client) -{ - /* reset and read revision code */ - static char reset_off[3] = { 0x00, 0x80, 0x00 }; - static char reset_on[3] = { 0x00, 0x00, 0x00 }; - static char write[3] = { I2C_MSP3400C_DFP + 1, 0x00, 0x1e }; - char read[2]; - struct i2c_msg reset[2] = { - { client->addr, I2C_M_IGNORE_NAK, 3, reset_off }, - { client->addr, I2C_M_IGNORE_NAK, 3, reset_on }, - }; - struct i2c_msg test[2] = { - { client->addr, 0, 3, write }, - { client->addr, I2C_M_RD, 2, read }, - }; - - msp3400_dbg_highvol("msp3400c_reset\n"); - if ( (1 != i2c_transfer(client->adapter,&reset[0],1)) || - (1 != i2c_transfer(client->adapter,&reset[1],1)) || - (2 != i2c_transfer(client->adapter,test,2)) ) { - msp3400_err("chip reset failed\n"); - return -1; - } - return 0; -} - -static int msp3400c_read(struct i2c_client *client, int dev, int addr) -{ - int err,retval; - - unsigned char write[3]; - unsigned char read[2]; - struct i2c_msg msgs[2] = { - { client->addr, 0, 3, write }, - { client->addr, I2C_M_RD, 2, read } - }; - - write[0] = dev+1; - write[1] = addr >> 8; - write[2] = addr & 0xff; - - for (err = 0; err < 3;) { - if (2 == i2c_transfer(client->adapter,msgs,2)) - break; - err++; - msp3400_warn("I/O error #%d (read 0x%02x/0x%02x)\n", err, - dev, addr); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(msecs_to_jiffies(10)); - } - if (3 == err) { - msp3400_warn("giving up, resetting chip. Sound will go off, sorry folks :-|\n"); - msp3400c_reset(client); - return -1; - } - retval = read[0] << 8 | read[1]; - msp3400_dbg_highvol("msp3400c_read(0x%x, 0x%x): 0x%x\n", dev, addr, retval); - return retval; -} - -static int msp3400c_write(struct i2c_client *client, int dev, int addr, int val) -{ - int err; - unsigned char buffer[5]; - - buffer[0] = dev; - buffer[1] = addr >> 8; - buffer[2] = addr & 0xff; - buffer[3] = val >> 8; - buffer[4] = val & 0xff; - - msp3400_dbg_highvol("msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val); - for (err = 0; err < 3;) { - if (5 == i2c_master_send(client, buffer, 5)) - break; - err++; - msp3400_warn("I/O error #%d (write 0x%02x/0x%02x)\n", err, - dev, addr); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(msecs_to_jiffies(10)); - } - if (3 == err) { - msp3400_warn("giving up, reseting chip. Sound will go off, sorry folks :-|\n"); - msp3400c_reset(client); - return -1; - } - return 0; -} - -/* ------------------------------------------------------------------------ */ - -/* This macro is allowed for *constants* only, gcc must calculate it - at compile time. Remember -- no floats in kernel mode */ -#define MSP_CARRIER(freq) ((int)((float)(freq/18.432)*(1<<24))) - -#define MSP_MODE_AM_DETECT 0 -#define MSP_MODE_FM_RADIO 2 -#define MSP_MODE_FM_TERRA 3 -#define MSP_MODE_FM_SAT 4 -#define MSP_MODE_FM_NICAM1 5 -#define MSP_MODE_FM_NICAM2 6 -#define MSP_MODE_AM_NICAM 7 -#define MSP_MODE_BTSC 8 -#define MSP_MODE_EXTERN 9 - -static struct MSP_INIT_DATA_DEM { - int fir1[6]; - int fir2[6]; - int cdo1; - int cdo2; - int ad_cv; - int mode_reg; - int dfp_src; - int dfp_matrix; -} msp_init_data[] = { - { /* AM (for carrier detect / msp3400) */ - {75, 19, 36, 35, 39, 40}, - {75, 19, 36, 35, 39, 40}, - MSP_CARRIER(5.5), MSP_CARRIER(5.5), - 0x00d0, 0x0500, 0x0020, 0x3000 - },{ /* AM (for carrier detect / msp3410) */ - {-1, -1, -8, 2, 59, 126}, - {-1, -1, -8, 2, 59, 126}, - MSP_CARRIER(5.5), MSP_CARRIER(5.5), - 0x00d0, 0x0100, 0x0020, 0x3000 - },{ /* FM Radio */ - {-8, -8, 4, 6, 78, 107}, - {-8, -8, 4, 6, 78, 107}, - MSP_CARRIER(10.7), MSP_CARRIER(10.7), - 0x00d0, 0x0480, 0x0020, 0x3000 - },{ /* Terrestial FM-mono + FM-stereo */ - {3, 18, 27, 48, 66, 72}, - {3, 18, 27, 48, 66, 72}, - MSP_CARRIER(5.5), MSP_CARRIER(5.5), - 0x00d0, 0x0480, 0x0030, 0x3000 - },{ /* Sat FM-mono */ - { 1, 9, 14, 24, 33, 37}, - { 3, 18, 27, 48, 66, 72}, - MSP_CARRIER(6.5), MSP_CARRIER(6.5), - 0x00c6, 0x0480, 0x0000, 0x3000 - },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */ - {-2, -8, -10, 10, 50, 86}, - {3, 18, 27, 48, 66, 72}, - MSP_CARRIER(5.5), MSP_CARRIER(5.5), - 0x00d0, 0x0040, 0x0120, 0x3000 - },{ /* NICAM/FM -- I (6.0/6.552) */ - {2, 4, -6, -4, 40, 94}, - {3, 18, 27, 48, 66, 72}, - MSP_CARRIER(6.0), MSP_CARRIER(6.0), - 0x00d0, 0x0040, 0x0120, 0x3000 - },{ /* NICAM/AM -- L (6.5/5.85) */ - {-2, -8, -10, 10, 50, 86}, - {-4, -12, -9, 23, 79, 126}, - MSP_CARRIER(6.5), MSP_CARRIER(6.5), - 0x00c6, 0x0140, 0x0120, 0x7c03 - }, -}; - -struct CARRIER_DETECT { - int cdo; - char *name; -}; - -static struct CARRIER_DETECT carrier_detect_main[] = { - /* main carrier */ - { MSP_CARRIER(4.5), "4.5 NTSC" }, - { MSP_CARRIER(5.5), "5.5 PAL B/G" }, - { MSP_CARRIER(6.0), "6.0 PAL I" }, - { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" } -}; - -static struct CARRIER_DETECT carrier_detect_55[] = { - /* PAL B/G */ - { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" }, - { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" } -}; - -static struct CARRIER_DETECT carrier_detect_65[] = { - /* PAL SAT / SECAM */ - { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" }, - { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" }, - { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" }, - { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" }, - { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" }, - { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" }, -}; - -#define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT)) - -/* ----------------------------------------------------------------------- * - * bits 9 8 5 - SCART DSP input Select: - * 0 0 0 - SCART 1 to DSP input (reset position) - * 0 1 0 - MONO to DSP input - * 1 0 0 - SCART 2 to DSP input - * 1 1 1 - Mute DSP input - * - * bits 11 10 6 - SCART 1 Output Select: - * 0 0 0 - undefined (reset position) - * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS) - * 1 0 0 - MONO input to SCART 1 Output - * 1 1 0 - SCART 1 DA to SCART 1 Output - * 0 0 1 - SCART 2 DA to SCART 1 Output - * 0 1 1 - SCART 1 Input to SCART 1 Output - * 1 1 1 - Mute SCART 1 Output - * - * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART): - * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position) - * 0 1 0 - SCART 1 Input to SCART 2 Output - * 1 0 0 - MONO input to SCART 2 Output - * 0 0 1 - SCART 2 DA to SCART 2 Output - * 0 1 1 - SCART 2 Input to SCART 2 Output - * 1 1 0 - Mute SCART 2 Output - * - * Bits 4 to 0 should be zero. - * ----------------------------------------------------------------------- */ - -static int scarts[3][9] = { - /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ - /* SCART DSP Input select */ - { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, - /* SCART1 Output select */ - { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, - /* SCART2 Output select */ - { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, -}; - -static char *scart_names[] = { - "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute" -}; - -static void msp3400c_set_scart(struct i2c_client *client, int in, int out) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - msp->in_scart=in; - - if (in >= 1 && in <= 8 && out >= 0 && out <= 2) { - if (-1 == scarts[out][in]) - return; - - msp->acb &= ~scarts[out][SCART_MASK]; - msp->acb |= scarts[out][in]; - } else - msp->acb = 0xf60; /* Mute Input and SCART 1 Output */ - - msp3400_dbg("scart switch: %s => %d (ACB=0x%04x)\n", - scart_names[in], out, msp->acb); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x13, msp->acb); - - /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */ - msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); -} - -/* ------------------------------------------------------------------------ */ - -static void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2) -{ - msp3400c_write(client,I2C_MSP3400C_DEM, 0x0093, cdo1 & 0xfff); - msp3400c_write(client,I2C_MSP3400C_DEM, 0x009b, cdo1 >> 12); - msp3400c_write(client,I2C_MSP3400C_DEM, 0x00a3, cdo2 & 0xfff); - msp3400c_write(client,I2C_MSP3400C_DEM, 0x00ab, cdo2 >> 12); - msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/ -} - -static void msp3400c_setvolume(struct i2c_client *client, - int muted, int left, int right) - { - int vol = 0, val = 0, balance = 0; - - if (!muted) { - /* 0x7f instead if 0x73 here has sound quality issues, - * probably due to overmodulation + clipping ... */ - vol = (left > right) ? left : right; - val = (vol * 0x73 / 65535) << 8; - } - if (vol > 0) { - balance = ((right - left) * 127) / vol; - } - - msp3400_dbg("setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n", - muted ? "on" : "off", left, right, val >> 8, balance); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007, - muted ? 0x1 : (val | 0x1)); - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0001, balance << 8); -} - -static void msp3400c_setbass(struct i2c_client *client, int bass) -{ - int val = ((bass-32768) * 0x60 / 65535) << 8; - - msp3400_dbg("setbass: %d 0x%02x\n", bass, val >> 8); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0002, val); /* loudspeaker */ -} - -static void msp3400c_settreble(struct i2c_client *client, int treble) -{ - int val = ((treble-32768) * 0x60 / 65535) << 8; - - msp3400_dbg("settreble: %d 0x%02x\n",treble, val>>8); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0003, val); /* loudspeaker */ -} - -static void msp3400c_setmode(struct i2c_client *client, int type) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int i; - - msp3400_dbg("setmode: %d\n",type); - msp->mode = type; - msp->audmode = V4L2_TUNER_MODE_MONO; - msp->rxsubchans = V4L2_TUNER_SUB_MONO; - - msp3400c_write(client,I2C_MSP3400C_DEM, 0x00bb, /* ad_cv */ - msp_init_data[type].ad_cv); - - for (i = 5; i >= 0; i--) /* fir 1 */ - msp3400c_write(client,I2C_MSP3400C_DEM, 0x0001, - msp_init_data[type].fir1[i]); - - msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0004); /* fir 2 */ - msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0040); - msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0000); - for (i = 5; i >= 0; i--) - msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, - msp_init_data[type].fir2[i]); - - msp3400c_write(client,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */ - msp_init_data[type].mode_reg); - - msp3400c_setcarrier(client, msp_init_data[type].cdo1, - msp_init_data[type].cdo2); - - msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/ - - if (dolby) { - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008, - 0x0520); /* I2S1 */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009, - 0x0620); /* I2S2 */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b, - msp_init_data[type].dfp_src); - } else { - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008, - msp_init_data[type].dfp_src); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009, - msp_init_data[type].dfp_src); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b, - msp_init_data[type].dfp_src); - } - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a, - msp_init_data[type].dfp_src); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, - msp_init_data[type].dfp_matrix); - - if (HAVE_NICAM(msp)) { - /* nicam prescale */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0010, 0x5a00); /* was: 0x3000 */ - } -} - -/* given a bitmask of VIDEO_SOUND_XXX returns the "best" in the bitmask */ -static int best_video_sound(int rxsubchans) -{ - if (rxsubchans & V4L2_TUNER_SUB_STEREO) - return V4L2_TUNER_MODE_STEREO; - if (rxsubchans & V4L2_TUNER_SUB_LANG1) - return V4L2_TUNER_MODE_LANG1; - if (rxsubchans & V4L2_TUNER_SUB_LANG2) - return V4L2_TUNER_MODE_LANG2; - return V4L2_TUNER_MODE_MONO; -} - -/* turn on/off nicam + stereo */ -static void msp3400c_setstereo(struct i2c_client *client, int mode) -{ - static char *strmode[] = { "0", "mono", "stereo", "3", - "lang1", "5", "6", "7", "lang2" - }; - struct msp3400c *msp = i2c_get_clientdata(client); - int nicam = 0; /* channel source: FM/AM or nicam */ - int src = 0; - - if (IS_MSP34XX_G(msp)) { - /* this method would break everything, let's make sure - * it's never called - */ - msp3400_dbg - ("DEBUG WARNING setstereo called with mode=%d instead of set_source (ignored)\n", - mode); - return; - } - - /* switch demodulator */ - switch (msp->mode) { - case MSP_MODE_FM_TERRA: - msp3400_dbg("FM setstereo: %s\n", strmode[mode]); - msp3400c_setcarrier(client,msp->second,msp->main); - switch (mode) { - case V4L2_TUNER_MODE_STEREO: - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3001); - break; - case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_LANG1: - case V4L2_TUNER_MODE_LANG2: - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3000); - break; - } - break; - case MSP_MODE_FM_SAT: - msp3400_dbg("SAT setstereo: %s\n", strmode[mode]); - switch (mode) { - case V4L2_TUNER_MODE_MONO: - msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); - break; - case V4L2_TUNER_MODE_STEREO: - msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); - break; - case V4L2_TUNER_MODE_LANG1: - msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); - break; - case V4L2_TUNER_MODE_LANG2: - msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); - break; - } - break; - case MSP_MODE_FM_NICAM1: - case MSP_MODE_FM_NICAM2: - case MSP_MODE_AM_NICAM: - msp3400_dbg("NICAM setstereo: %s\n",strmode[mode]); - msp3400c_setcarrier(client,msp->second,msp->main); - if (msp->nicam_on) - nicam=0x0100; - break; - case MSP_MODE_BTSC: - msp3400_dbg("BTSC setstereo: %s\n",strmode[mode]); - nicam=0x0300; - break; - case MSP_MODE_EXTERN: - msp3400_dbg("extern setstereo: %s\n",strmode[mode]); - nicam = 0x0200; - break; - case MSP_MODE_FM_RADIO: - msp3400_dbg("FM-Radio setstereo: %s\n",strmode[mode]); - break; - default: - msp3400_dbg("mono setstereo\n"); - return; - } - - /* switch audio */ - switch (best_video_sound(mode)) { - case V4L2_TUNER_MODE_STEREO: - src = 0x0020 | nicam; - break; - case V4L2_TUNER_MODE_MONO: - if (msp->mode == MSP_MODE_AM_NICAM) { - msp3400_dbg("switching to AM mono\n"); - /* AM mono decoding is handled by tuner, not MSP chip */ - /* SCART switching control register */ - msp3400c_set_scart(client,SCART_MONO,0); - src = 0x0200; - break; - } - case V4L2_TUNER_MODE_LANG1: - src = 0x0000 | nicam; - break; - case V4L2_TUNER_MODE_LANG2: - src = 0x0010 | nicam; - break; - } - msp3400_dbg("setstereo final source/matrix = 0x%x\n", src); - - if (dolby) { - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,0x0520); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,0x0620); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,src); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,src); - } else { - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,src); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,src); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,src); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,src); - } -} - -static void -msp3400c_print_mode(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - if (msp->main == msp->second) { - msp3400_dbg("mono sound carrier: %d.%03d MHz\n", - msp->main/910000,(msp->main/910)%1000); - } else { - msp3400_dbg("main sound carrier: %d.%03d MHz\n", - msp->main/910000,(msp->main/910)%1000); - } - if (msp->mode == MSP_MODE_FM_NICAM1 || msp->mode == MSP_MODE_FM_NICAM2) - msp3400_dbg("NICAM/FM carrier : %d.%03d MHz\n", - msp->second/910000,(msp->second/910)%1000); - if (msp->mode == MSP_MODE_AM_NICAM) - msp3400_dbg("NICAM/AM carrier : %d.%03d MHz\n", - msp->second/910000,(msp->second/910)%1000); - if (msp->mode == MSP_MODE_FM_TERRA && - msp->main != msp->second) { - msp3400_dbg("FM-stereo carrier : %d.%03d MHz\n", - msp->second/910000,(msp->second/910)%1000); - } -} - -#define MSP3400_MAX 4 -static struct i2c_client *msps[MSP3400_MAX]; -static void msp3400c_restore_dfp(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int i; - - for (i = 0; i < DFP_COUNT; i++) { - if (-1 == msp->dfp_regs[i]) - continue; - msp3400c_write(client, I2C_MSP3400C_DFP, i, msp->dfp_regs[i]); - } -} - -/* if the dfp_regs is set, set what's in there. Otherwise, set the default value */ -static int msp3400c_write_dfp_with_default(struct i2c_client *client, - int addr, int default_value) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int value = default_value; - if (addr < DFP_COUNT && -1 != msp->dfp_regs[addr]) - value = msp->dfp_regs[addr]; - return msp3400c_write(client, I2C_MSP3400C_DFP, addr, value); -} - -/* ----------------------------------------------------------------------- */ - -struct REGISTER_DUMP { - int addr; - char *name; -}; - -struct REGISTER_DUMP d1[] = { - {0x007e, "autodetect"}, - {0x0023, "C_AD_BITS "}, - {0x0038, "ADD_BITS "}, - {0x003e, "CIB_BITS "}, - {0x0057, "ERROR_RATE"}, -}; - -static int autodetect_stereo(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int val; - int rxsubchans = msp->rxsubchans; - int newnicam = msp->nicam_on; - int update = 0; - - switch (msp->mode) { - case MSP_MODE_FM_TERRA: - val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x18); - if (val > 32767) - val -= 65536; - msp3400_dbg("stereo detect register: %d\n",val); - if (val > 4096) { - rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; - } else if (val < -4096) { - rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - } else { - rxsubchans = V4L2_TUNER_SUB_MONO; - } - newnicam = 0; - break; - case MSP_MODE_FM_NICAM1: - case MSP_MODE_FM_NICAM2: - case MSP_MODE_AM_NICAM: - val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x23); - msp3400_dbg("nicam sync=%d, mode=%d\n", - val & 1, (val & 0x1e) >> 1); - - if (val & 1) { - /* nicam synced */ - switch ((val & 0x1e) >> 1) { - case 0: - case 8: - rxsubchans = V4L2_TUNER_SUB_STEREO; - break; - case 1: - case 9: - rxsubchans = V4L2_TUNER_SUB_MONO - | V4L2_TUNER_SUB_LANG1; - break; - case 2: - case 10: - rxsubchans = V4L2_TUNER_SUB_MONO - | V4L2_TUNER_SUB_LANG1 - | V4L2_TUNER_SUB_LANG2; - break; - default: - rxsubchans = V4L2_TUNER_SUB_MONO; - break; - } - newnicam=1; - } else { - newnicam = 0; - rxsubchans = V4L2_TUNER_SUB_MONO; - } - break; - case MSP_MODE_BTSC: - val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200); - msp3400_dbg("status=0x%x (pri=%s, sec=%s, %s%s%s)\n", - val, - (val & 0x0002) ? "no" : "yes", - (val & 0x0004) ? "no" : "yes", - (val & 0x0040) ? "stereo" : "mono", - (val & 0x0080) ? ", nicam 2nd mono" : "", - (val & 0x0100) ? ", bilingual/SAP" : ""); - rxsubchans = V4L2_TUNER_SUB_MONO; - if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO; - if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1; - break; - } - if (rxsubchans != msp->rxsubchans) { - update = 1; - msp3400_dbg("watch: rxsubchans %d => %d\n", - msp->rxsubchans,rxsubchans); - msp->rxsubchans = rxsubchans; - } - if (newnicam != msp->nicam_on) { - update = 1; - msp3400_dbg("watch: nicam %d => %d\n", - msp->nicam_on,newnicam); - msp->nicam_on = newnicam; - } - return update; -} - -/* - * A kernel thread for msp3400 control -- we don't want to block the - * in the ioctl while doing the sound carrier & stereo detect - */ - -static int msp34xx_sleep(struct msp3400c *msp, int timeout) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&msp->wq, &wait); - if (!kthread_should_stop()) { - if (timeout < 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - } else { - schedule_timeout_interruptible - (msecs_to_jiffies(timeout)); - } - } - - remove_wait_queue(&msp->wq, &wait); - try_to_freeze(); - return msp->restart; -} - -/* stereo/multilang monitoring */ -static void watch_stereo(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - if (autodetect_stereo(client)) { - if (msp->stereo & V4L2_TUNER_MODE_STEREO) - msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO); - else if (msp->stereo & VIDEO_SOUND_LANG1) - msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1); - else - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); - } - - if (once) - msp->watch_stereo = 0; -} - - -static int msp3400c_thread(void *data) -{ - struct i2c_client *client = data; - struct msp3400c *msp = i2c_get_clientdata(client); - struct CARRIER_DETECT *cd; - int count, max1,max2,val1,val2, val,this; - - - msp3400_info("msp3400 daemon started\n"); - for (;;) { - msp3400_dbg_mediumvol("msp3400 thread: sleep\n"); - msp34xx_sleep(msp,-1); - msp3400_dbg_mediumvol("msp3400 thread: wakeup\n"); - - restart: - msp3400_dbg("thread: restart scan\n"); - msp->restart = 0; - if (kthread_should_stop()) - break; - - if (VIDEO_MODE_RADIO == msp->norm || - MSP_MODE_EXTERN == msp->mode) { - /* no carrier scan, just unmute */ - msp3400_info("thread: no carrier scan\n"); - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - continue; - } - - /* mute */ - msp3400c_setvolume(client, msp->muted, 0, 0); - msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ ); - val1 = val2 = 0; - max1 = max2 = -1; - msp->watch_stereo = 0; - - /* some time for the tuner to sync */ - if (msp34xx_sleep(msp,200)) - goto restart; - - /* carrier detect pass #1 -- main carrier */ - cd = carrier_detect_main; - count = CARRIER_COUNT(carrier_detect_main); - - if (amsound && (msp->norm == VIDEO_MODE_SECAM)) { - /* autodetect doesn't work well with AM ... */ - max1 = 3; - count = 0; - msp3400_dbg("AM sound override\n"); - } - - for (this = 0; this < count; this++) { - msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); - if (msp34xx_sleep(msp,100)) - goto restart; - val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); - if (val > 32767) - val -= 65536; - if (val1 < val) - val1 = val, max1 = this; - msp3400_dbg("carrier1 val: %5d / %s\n", val,cd[this].name); - } - - /* carrier detect pass #2 -- second (stereo) carrier */ - switch (max1) { - case 1: /* 5.5 */ - cd = carrier_detect_55; - count = CARRIER_COUNT(carrier_detect_55); - break; - case 3: /* 6.5 */ - cd = carrier_detect_65; - count = CARRIER_COUNT(carrier_detect_65); - break; - case 0: /* 4.5 */ - case 2: /* 6.0 */ - default: - cd = NULL; - count = 0; - break; - } - - if (amsound && (msp->norm == VIDEO_MODE_SECAM)) { - /* autodetect doesn't work well with AM ... */ - cd = NULL; - count = 0; - max2 = 0; - } - for (this = 0; this < count; this++) { - msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); - if (msp34xx_sleep(msp,100)) - goto restart; - val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); - if (val > 32767) - val -= 65536; - if (val2 < val) - val2 = val, max2 = this; - msp3400_dbg("carrier2 val: %5d / %s\n", val,cd[this].name); - } - - /* programm the msp3400 according to the results */ - msp->main = carrier_detect_main[max1].cdo; - switch (max1) { - case 1: /* 5.5 */ - if (max2 == 0) { - /* B/G FM-stereo */ - msp->second = carrier_detect_55[max2].cdo; - msp3400c_setmode(client, MSP_MODE_FM_TERRA); - msp->nicam_on = 0; - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); - msp->watch_stereo = 1; - } else if (max2 == 1 && HAVE_NICAM(msp)) { - /* B/G NICAM */ - msp->second = carrier_detect_55[max2].cdo; - msp3400c_setmode(client, MSP_MODE_FM_NICAM1); - msp->nicam_on = 1; - msp3400c_setcarrier(client, msp->second, msp->main); - msp->watch_stereo = 1; - } else { - goto no_second; - } - break; - case 2: /* 6.0 */ - /* PAL I NICAM */ - msp->second = MSP_CARRIER(6.552); - msp3400c_setmode(client, MSP_MODE_FM_NICAM2); - msp->nicam_on = 1; - msp3400c_setcarrier(client, msp->second, msp->main); - msp->watch_stereo = 1; - break; - case 3: /* 6.5 */ - if (max2 == 1 || max2 == 2) { - /* D/K FM-stereo */ - msp->second = carrier_detect_65[max2].cdo; - msp3400c_setmode(client, MSP_MODE_FM_TERRA); - msp->nicam_on = 0; - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); - msp->watch_stereo = 1; - } else if (max2 == 0 && - msp->norm == VIDEO_MODE_SECAM) { - /* L NICAM or AM-mono */ - msp->second = carrier_detect_65[max2].cdo; - msp3400c_setmode(client, MSP_MODE_AM_NICAM); - msp->nicam_on = 0; - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); - msp3400c_setcarrier(client, msp->second, msp->main); - /* volume prescale for SCART (AM mono input) */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900); - msp->watch_stereo = 1; - } else if (max2 == 0 && HAVE_NICAM(msp)) { - /* D/K NICAM */ - msp->second = carrier_detect_65[max2].cdo; - msp3400c_setmode(client, MSP_MODE_FM_NICAM1); - msp->nicam_on = 1; - msp3400c_setcarrier(client, msp->second, msp->main); - msp->watch_stereo = 1; - } else { - goto no_second; - } - break; - case 0: /* 4.5 */ - default: - no_second: - msp->second = carrier_detect_main[max1].cdo; - msp3400c_setmode(client, MSP_MODE_FM_TERRA); - msp->nicam_on = 0; - msp3400c_setcarrier(client, msp->second, msp->main); - msp->rxsubchans = V4L2_TUNER_SUB_MONO; - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); - break; - } - - /* unmute */ - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - msp3400c_restore_dfp(client); - - if (debug) - msp3400c_print_mode(client); - - /* monitor tv audio mode */ - while (msp->watch_stereo) { - if (msp34xx_sleep(msp,5000)) - goto restart; - watch_stereo(client); - } - } - msp3400_dbg("thread: exit\n"); - return 0; -} - -/* ----------------------------------------------------------------------- */ -/* this one uses the automatic sound standard detection of newer */ -/* msp34xx chip versions */ - -static struct MODES { - int retval; - int main, second; - char *name; -} modelist[] = { - { 0x0000, 0, 0, "ERROR" }, - { 0x0001, 0, 0, "autodetect start" }, - { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" }, - { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" }, - { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" }, - { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" }, - { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" }, - { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" }, - { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" }, - { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" }, - { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" }, - { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" }, - { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" }, - { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" }, - { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" }, - { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" }, - { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" }, - { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" }, - { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" }, - { -1, 0, 0, NULL }, /* EOF */ -}; - -static inline const char *msp34xx_standard_mode_name(int mode) -{ - int i; - for (i = 0; modelist[i].name != NULL; i++) - if (modelist[i].retval == mode) - return modelist[i].name; - return "unknown"; -} - -static int msp34xx_modus(struct i2c_client *client, int norm) -{ - switch (norm) { - case VIDEO_MODE_PAL: - msp3400_dbg("video mode selected to PAL\n"); - -#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 */ - msp3400_dbg("video mode selected to NTSC\n"); - return 0x2003; - case VIDEO_MODE_SECAM: - msp3400_dbg("video mode selected to SECAM\n"); - return 0x0003; - case VIDEO_MODE_RADIO: - msp3400_dbg("video mode selected to Radio\n"); - return 0x0003; - case VIDEO_MODE_AUTO: - msp3400_dbg("video mode selected to Auto\n"); - return 0x2003; - default: - return 0x0003; - } -} - -static int msp34xx_standard(int norm) -{ - switch (norm) { - case VIDEO_MODE_PAL: - return 1; - case VIDEO_MODE_NTSC: /* BTSC */ - return 0x0020; - case VIDEO_MODE_SECAM: - return 1; - case VIDEO_MODE_RADIO: - return 0x0040; - default: - return 1; - } -} - -static int msp3410d_thread(void *data) -{ - struct i2c_client *client = data; - struct msp3400c *msp = i2c_get_clientdata(client); - int mode,val,i,std; - - msp3400_info("msp3410 daemon started\n"); - - for (;;) { - msp3400_dbg_mediumvol("msp3410 thread: sleep\n"); - msp34xx_sleep(msp,-1); - msp3400_dbg_mediumvol("msp3410 thread: wakeup\n"); - - restart: - msp3400_dbg("thread: restart scan\n"); - msp->restart = 0; - if (kthread_should_stop()) - break; - - if (msp->mode == MSP_MODE_EXTERN) { - /* no carrier scan needed, just unmute */ - msp3400_dbg("thread: no carrier scan\n"); - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - continue; - } - - /* put into sane state (and mute) */ - msp3400c_reset(client); - - /* some time for the tuner to sync */ - if (msp34xx_sleep(msp,200)) - goto restart; - - /* start autodetect */ - mode = msp34xx_modus(client, msp->norm); - std = msp34xx_standard(msp->norm); - msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode); - msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std); - msp->watch_stereo = 0; - - if (debug) - msp3400_dbg("setting mode: %s (0x%04x)\n", - msp34xx_standard_mode_name(std) ,std); - - if (std != 1) { - /* programmed some specific mode */ - val = std; - } else { - /* triggered autodetect */ - for (;;) { - if (msp34xx_sleep(msp,100)) - goto restart; - - /* check results */ - val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e); - if (val < 0x07ff) - break; - msp3400_dbg("detection still in progress\n"); - } - } - for (i = 0; modelist[i].name != NULL; i++) - if (modelist[i].retval == val) - break; - msp3400_dbg("current mode: %s (0x%04x)\n", - modelist[i].name ? modelist[i].name : "unknown", - val); - msp->main = modelist[i].main; - msp->second = modelist[i].second; - - if (amsound && (msp->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) { - /* autodetection has failed, let backup */ - msp3400_dbg("autodetection failed," - " switching to backup mode: %s (0x%04x)\n", - modelist[8].name ? modelist[8].name : "unknown",val); - val = 0x0009; - msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, val); - } - - /* set various prescales */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0d, 0x1900); /* scart */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* nicam */ - - /* set stereo */ - switch (val) { - case 0x0008: /* B/G NICAM */ - case 0x000a: /* I NICAM */ - if (val == 0x0008) - msp->mode = MSP_MODE_FM_NICAM1; - else - msp->mode = MSP_MODE_FM_NICAM2; - /* just turn on stereo */ - msp->rxsubchans = V4L2_TUNER_SUB_STEREO; - msp->nicam_on = 1; - msp->watch_stereo = 1; - msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); - break; - case 0x0009: - msp->mode = MSP_MODE_AM_NICAM; - msp->rxsubchans = V4L2_TUNER_SUB_MONO; - msp->nicam_on = 1; - msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO); - msp->watch_stereo = 1; - break; - case 0x0020: /* BTSC */ - /* just turn on stereo */ - msp->mode = MSP_MODE_BTSC; - msp->rxsubchans = V4L2_TUNER_SUB_STEREO; - msp->nicam_on = 0; - msp->watch_stereo = 1; - msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); - break; - case 0x0040: /* FM radio */ - msp->mode = MSP_MODE_FM_RADIO; - msp->rxsubchans = V4L2_TUNER_SUB_STEREO; - msp->audmode = V4L2_TUNER_MODE_STEREO; - msp->nicam_on = 0; - msp->watch_stereo = 0; - /* not needed in theory if HAVE_RADIO(), but - short programming enables carrier mute */ - msp3400c_setmode(client,MSP_MODE_FM_RADIO); - msp3400c_setcarrier(client, MSP_CARRIER(10.7), - MSP_CARRIER(10.7)); - /* scart routing */ - msp3400c_set_scart(client,SCART_IN2,0); - /* msp34xx does radio decoding */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0020); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x09, 0x0020); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0b, 0x0020); - break; - case 0x0003: - case 0x0004: - case 0x0005: - msp->mode = MSP_MODE_FM_TERRA; - msp->rxsubchans = V4L2_TUNER_SUB_MONO; - msp->audmode = V4L2_TUNER_MODE_MONO; - msp->nicam_on = 0; - msp->watch_stereo = 1; - break; - } - - /* unmute, restore misc registers */ - msp3400c_setbass(client, msp->bass); - msp3400c_settreble(client, msp->treble); - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - msp3400c_write(client, I2C_MSP3400C_DFP, 0x13, msp->acb); - msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); - msp3400c_restore_dfp(client); - - /* monitor tv audio mode */ - while (msp->watch_stereo) { - if (msp34xx_sleep(msp,5000)) - goto restart; - watch_stereo(client); - } - } - msp3400_dbg("thread: exit\n"); - return 0; -} - -/* ----------------------------------------------------------------------- */ -/* msp34xxG + (simpler no-thread) */ -/* this one uses both automatic standard detection and automatic sound */ -/* select which are available in the newer G versions */ -/* struct msp: only norm, acb and source are really used in this mode */ - -static void msp34xxg_set_source(struct i2c_client *client, int source); - -/* (re-)initialize the msp34xxg, according to the current norm in msp->norm - * return 0 if it worked, -1 if it failed - */ -static int msp34xxg_reset(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int modus,std; - - if (msp3400c_reset(client)) - return -1; - - /* make sure that input/output is muted (paranoid mode) */ - if (msp3400c_write(client, - I2C_MSP3400C_DFP, - 0x13, /* ACB */ - 0x0f20 /* mute DSP input, mute SCART 1 */)) - return -1; - - msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); - - /* step-by-step initialisation, as described in the manual */ - modus = msp34xx_modus(client, msp->norm); - std = msp34xx_standard(msp->norm); - modus &= ~0x03; /* STATUS_CHANGE=0 */ - modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION=1 */ - if (msp3400c_write(client, - I2C_MSP3400C_DEM, - 0x30/*MODUS*/, - modus)) - return -1; - if (msp3400c_write(client, - I2C_MSP3400C_DEM, - 0x20/*standard*/, - std)) - return -1; - - /* write the dfps that may have an influence on - standard/audio autodetection right now */ - msp34xxg_set_source(client, msp->source); - - if (msp3400c_write_dfp_with_default(client, 0x0e, /* AM/FM Prescale */ - 0x3000 - /* default: [15:8] 75khz deviation */ - )) - return -1; - - if (msp3400c_write_dfp_with_default(client, 0x10, /* NICAM Prescale */ - 0x5a00 - /* default: 9db gain (as recommended) */ - )) - return -1; - - return 0; -} - -static int msp34xxg_thread(void *data) -{ - struct i2c_client *client = data; - struct msp3400c *msp = i2c_get_clientdata(client); - int val, std, i; - - msp3400_info("msp34xxg daemon started\n"); - - msp->source = 1; /* default */ - for (;;) { - msp3400_dbg_mediumvol("msp34xxg thread: sleep\n"); - msp34xx_sleep(msp,-1); - msp3400_dbg_mediumvol("msp34xxg thread: wakeup\n"); - - restart: - msp3400_dbg("thread: restart scan\n"); - msp->restart = 0; - if (kthread_should_stop()) - break; - - /* setup the chip*/ - msp34xxg_reset(client); - std = standard; - if (std != 0x01) - goto unmute; - - /* watch autodetect */ - msp3400_dbg("triggered autodetect, waiting for result\n"); - for (i = 0; i < 10; i++) { - if (msp34xx_sleep(msp,100)) - goto restart; - - /* check results */ - val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e); - if (val < 0x07ff) { - std = val; - break; - } - msp3400_dbg("detection still in progress\n"); - } - if (0x01 == std) { - msp3400_dbg("detection still in progress after 10 tries. giving up.\n"); - continue; - } - - unmute: - msp3400_dbg("current mode: %s (0x%04x)\n", - msp34xx_standard_mode_name(std), std); - - /* unmute: dispatch sound to scart output, set scart volume */ - msp3400_dbg("unmute\n"); - - msp3400c_setbass(client, msp->bass); - msp3400c_settreble(client, msp->treble); - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - - /* restore ACB */ - if (msp3400c_write(client, - I2C_MSP3400C_DFP, - 0x13, /* ACB */ - msp->acb)) - return -1; - - msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); - } - msp3400_dbg("thread: exit\n"); - return 0; -} - -/* set the same 'source' for the loudspeaker, scart and quasi-peak detector - * the value for source is the same as bit 15:8 of DFP registers 0x08, - * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B - * - * this function replaces msp3400c_setstereo - */ -static void msp34xxg_set_source(struct i2c_client *client, int source) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - /* 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 ? 0x30:0x20); - msp3400_dbg("set source to %d (0x%x)\n", source, value); - msp3400c_write(client, - I2C_MSP3400C_DFP, - 0x08, /* Loudspeaker Output */ - value); - msp3400c_write(client, - I2C_MSP3400C_DFP, - 0x0a, /* SCART1 DA Output */ - value); - msp3400c_write(client, - I2C_MSP3400C_DFP, - 0x0c, /* Quasi-peak detector */ - value); - /* - * set identification threshold. Personally, I - * I set it to a higher value that the default - * of 0x190 to ignore noisy stereo signals. - * this needs tuning. (recommended range 0x00a0-0x03c0) - * 0x7f0 = forced mono mode - */ - msp3400c_write(client, - I2C_MSP3400C_DEM, - 0x22, /* a2 threshold for stereo/bilingual */ - stereo_threshold); - msp->source=source; -} - -static void msp34xxg_detect_stereo(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - int status = msp3400c_read(client, - I2C_MSP3400C_DEM, - 0x0200 /* STATUS */); - int is_bilingual = status&0x100; - int is_stereo = status&0x40; - - msp->rxsubchans = 0; - if (is_stereo) - msp->rxsubchans |= V4L2_TUNER_SUB_STEREO; - else - msp->rxsubchans |= V4L2_TUNER_SUB_MONO; - if (is_bilingual) { - msp->rxsubchans |= V4L2_TUNER_SUB_LANG1|V4L2_TUNER_SUB_LANG2; - /* I'm supposed to check whether it's SAP or not - * and set only LANG2/SAP in this case. Yet, the MSP - * does a lot of work to hide this and handle everything - * the same way. I don't want to work around it so unless - * this is a problem, I'll handle SAP just like lang1/lang2. - */ - } - msp3400_dbg("status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", - status, is_stereo, is_bilingual, msp->rxsubchans); -} - -static void msp34xxg_set_audmode(struct i2c_client *client, int audmode) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int source; - - switch (audmode) { - case V4L2_TUNER_MODE_MONO: - source=0; /* mono only */ - break; - case V4L2_TUNER_MODE_STEREO: - source=1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ - /* problem: that could also mean 2 (scart input) */ - break; - case V4L2_TUNER_MODE_LANG1: - source=3; /* stereo or A */ - break; - case V4L2_TUNER_MODE_LANG2: - source=4; /* stereo or B */ - break; - default: - audmode = 0; - source = 1; - break; - } - msp->audmode = audmode; - msp34xxg_set_source(client, source); -} - - -/* ----------------------------------------------------------------------- */ - -static int msp_attach(struct i2c_adapter *adap, int addr, int kind); -static int msp_detach(struct i2c_client *client); -static int msp_probe(struct i2c_adapter *adap); -static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg); - -static int msp_suspend(struct device * dev, pm_message_t state); -static int msp_resume(struct device * dev); - -static void msp_wake_thread(struct i2c_client *client); - -static struct i2c_driver driver = { - .id = I2C_DRIVERID_MSP3400, - .attach_adapter = msp_probe, - .detach_client = msp_detach, - .command = msp_command, - .driver = { - .name = "i2c msp3400 driver", - .suspend = msp_suspend, - .resume = msp_resume, - }, -}; - -static struct i2c_client client_template = -{ - .name = "(unset)", - .driver = &driver, -}; - -static int msp_attach(struct i2c_adapter *adap, int addr, int kind) -{ - struct msp3400c *msp; - struct i2c_client *client = &client_template; - int (*thread_func)(void *data) = NULL; - int i; - - client_template.adapter = adap; - client_template.addr = addr; - - if (-1 == msp3400c_reset(&client_template)) { - msp3400_dbg("no chip found\n"); - return -1; - } - - if (NULL == (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - if (NULL == (msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL))) { - kfree(client); - return -ENOMEM; - } - - memset(msp,0,sizeof(struct msp3400c)); - msp->norm = VIDEO_MODE_NTSC; - msp->left = 58880; /* 0db gain */ - msp->right = 58880; /* 0db gain */ - msp->bass = 32768; - msp->treble = 32768; - msp->input = -1; - msp->muted = 0; - msp->i2s_mode = 0; - for (i = 0; i < DFP_COUNT; i++) - msp->dfp_regs[i] = -1; - - i2c_set_clientdata(client, msp); - init_waitqueue_head(&msp->wq); - - if (-1 == msp3400c_reset(client)) { - kfree(msp); - kfree(client); - msp3400_dbg("no chip found\n"); - return -1; - } - - msp->rev1 = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1e); - if (-1 != msp->rev1) - msp->rev2 = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1f); - if ((-1 == msp->rev1) || (0 == msp->rev1 && 0 == msp->rev2)) { - kfree(msp); - kfree(client); - msp3400_dbg("error while reading chip version\n"); - return -1; - } - msp3400_dbg("rev1=0x%04x, rev2=0x%04x\n", msp->rev1, msp->rev2); - - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - - snprintf(client->name, sizeof(client->name), "MSP%c4%02d%c-%c%d", - ((msp->rev1>>4)&0x0f) + '3', - (msp->rev2>>8)&0xff, (msp->rev1&0x0f)+'@', - ((msp->rev1>>8)&0xff)+'@', msp->rev2&0x1f); - - msp->opmode = opmode; - if (OPMODE_AUTO == msp->opmode) { - if (HAVE_SIMPLER(msp)) - msp->opmode = OPMODE_SIMPLER; - else if (HAVE_SIMPLE(msp)) - msp->opmode = OPMODE_SIMPLE; - else - msp->opmode = OPMODE_MANUAL; - } - - /* hello world :-) */ - msp3400_info("chip=%s", client->name); - if (HAVE_NICAM(msp)) - printk(" +nicam"); - if (HAVE_SIMPLE(msp)) - printk(" +simple"); - if (HAVE_SIMPLER(msp)) - printk(" +simpler"); - if (HAVE_RADIO(msp)) - printk(" +radio"); - - /* version-specific initialization */ - switch (msp->opmode) { - case OPMODE_MANUAL: - printk(" mode=manual"); - thread_func = msp3400c_thread; - break; - case OPMODE_SIMPLE: - printk(" mode=simple"); - thread_func = msp3410d_thread; - break; - case OPMODE_SIMPLER: - printk(" mode=simpler"); - thread_func = msp34xxg_thread; - break; - } - printk("\n"); - - /* startup control thread if needed */ - if (thread_func) { - msp->kthread = kthread_run(thread_func, client, "msp34xx"); - - if (NULL == msp->kthread) - msp3400_warn("kernel_thread() failed\n"); - msp_wake_thread(client); - } - - /* done */ - i2c_attach_client(client); - - /* update our own array */ - for (i = 0; i < MSP3400_MAX; i++) { - if (NULL == msps[i]) { - msps[i] = client; - break; - } - } - - return 0; -} - -static int msp_detach(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int i; - - /* shutdown control thread */ - if (msp->kthread) { - msp->restart = 1; - kthread_stop(msp->kthread); - } - msp3400c_reset(client); - - /* update our own array */ - for (i = 0; i < MSP3400_MAX; i++) { - if (client == msps[i]) { - msps[i] = NULL; - break; - } - } - - i2c_detach_client(client); - - kfree(msp); - kfree(client); - return 0; -} - -static int msp_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, msp_attach); - return 0; -} - -static void msp_wake_thread(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - if (NULL == msp->kthread) - return; - msp3400c_setvolume(client,msp->muted,0,0); - msp->watch_stereo = 0; - msp->restart = 1; - wake_up_interruptible(&msp->wq); -} - -/* ----------------------------------------------------------------------- */ - -static int mode_v4l2_to_v4l1(int rxsubchans) -{ - int mode = 0; - - if (rxsubchans & V4L2_TUNER_SUB_STEREO) - mode |= VIDEO_SOUND_STEREO; - if (rxsubchans & V4L2_TUNER_SUB_LANG2) - mode |= VIDEO_SOUND_LANG2; - if (rxsubchans & V4L2_TUNER_SUB_LANG1) - mode |= VIDEO_SOUND_LANG1; - if (0 == mode) - mode |= VIDEO_SOUND_MONO; - return mode; -} - -static int mode_v4l1_to_v4l2(int mode) -{ - if (mode & VIDEO_SOUND_STEREO) - return V4L2_TUNER_MODE_STEREO; - if (mode & VIDEO_SOUND_LANG2) - return V4L2_TUNER_MODE_LANG2; - if (mode & VIDEO_SOUND_LANG1) - return V4L2_TUNER_MODE_LANG1; - return V4L2_TUNER_MODE_MONO; -} - -static void msp_any_detect_stereo(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - switch (msp->opmode) { - case OPMODE_MANUAL: - case OPMODE_SIMPLE: - autodetect_stereo(client); - break; - case OPMODE_SIMPLER: - msp34xxg_detect_stereo(client); - break; - } -} - -static void msp_any_set_audmode(struct i2c_client *client, int audmode) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - switch (msp->opmode) { - case OPMODE_MANUAL: - case OPMODE_SIMPLE: - msp->watch_stereo = 0; - msp3400c_setstereo(client, audmode); - break; - case OPMODE_SIMPLER: - msp34xxg_set_audmode(client, audmode); - break; - } -} - - -static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - __u16 *sarg = arg; - int scart = 0; - - switch (cmd) { - - case AUDC_SET_INPUT: - msp3400_dbg("AUDC_SET_INPUT(%d)\n",*sarg); - - if (*sarg == msp->input) - break; - msp->input = *sarg; - switch (*sarg) { - case AUDIO_RADIO: - /* Hauppauge uses IN2 for the radio */ - msp->mode = MSP_MODE_FM_RADIO; - scart = SCART_IN2; - break; - case AUDIO_EXTERN_1: - /* IN1 is often used for external input ... */ - msp->mode = MSP_MODE_EXTERN; - scart = SCART_IN1; - break; - case AUDIO_EXTERN_2: - /* ... sometimes it is IN2 through ;) */ - msp->mode = MSP_MODE_EXTERN; - scart = SCART_IN2; - break; - case AUDIO_TUNER: - msp->mode = -1; - break; - default: - if (*sarg & AUDIO_MUTE) - msp3400c_set_scart(client,SCART_MUTE,0); - break; - } - if (scart) { - msp->rxsubchans = V4L2_TUNER_SUB_STEREO; - msp->audmode = V4L2_TUNER_MODE_STEREO; - msp3400c_set_scart(client,scart,0); - msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); - if (msp->opmode != OPMODE_SIMPLER) - msp3400c_setstereo(client, msp->audmode); - } - msp_wake_thread(client); - break; - - case AUDC_SET_RADIO: - msp3400_dbg("AUDC_SET_RADIO\n"); - msp->norm = VIDEO_MODE_RADIO; - msp3400_dbg("switching to radio mode\n"); - msp->watch_stereo = 0; - switch (msp->opmode) { - case OPMODE_MANUAL: - /* set msp3400 to FM radio mode */ - msp3400c_setmode(client,MSP_MODE_FM_RADIO); - msp3400c_setcarrier(client, MSP_CARRIER(10.7), - MSP_CARRIER(10.7)); - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - break; - case OPMODE_SIMPLE: - case OPMODE_SIMPLER: - /* the thread will do for us */ - msp_wake_thread(client); - break; - } - break; - /* work-in-progress: hook to control the DFP registers */ - case MSP_SET_DFPREG: - { - struct msp_dfpreg *r = arg; - int i; - - if (r->reg < 0 || r->reg >= DFP_COUNT) - return -EINVAL; - for (i = 0; i < sizeof(bl_dfp) / sizeof(int); i++) - if (r->reg == bl_dfp[i]) - return -EINVAL; - msp->dfp_regs[r->reg] = r->value; - msp3400c_write(client, I2C_MSP3400C_DFP, r->reg, r->value); - return 0; - } - case MSP_GET_DFPREG: - { - struct msp_dfpreg *r = arg; - - if (r->reg < 0 || r->reg >= DFP_COUNT) - return -EINVAL; - r->value = msp3400c_read(client, I2C_MSP3400C_DFP, r->reg); - return 0; - } - - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - msp3400_dbg("VIDIOCGAUDIO\n"); - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE | - VIDEO_AUDIO_MUTABLE; - if (msp->muted) - va->flags |= VIDEO_AUDIO_MUTE; - - if (msp->muted) - va->flags |= VIDEO_AUDIO_MUTE; - va->volume = MAX(msp->left, msp->right); - va->balance = (32768 * MIN(msp->left, msp->right)) / - (va->volume ? va->volume : 1); - va->balance = (msp->left < msp->right) ? - (65535 - va->balance) : va->balance; - if (0 == va->volume) - va->balance = 32768; - va->bass = msp->bass; - va->treble = msp->treble; - - msp_any_detect_stereo(client); - va->mode = mode_v4l2_to_v4l1(msp->rxsubchans); - break; - } - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - - msp3400_dbg("VIDIOCSAUDIO\n"); - msp->muted = (va->flags & VIDEO_AUDIO_MUTE); - msp->left = (MIN(65536 - va->balance, 32768) * - va->volume) / 32768; - msp->right = (MIN(va->balance, 32768) * va->volume) / 32768; - msp->bass = va->bass; - msp->treble = va->treble; - msp3400_dbg("VIDIOCSAUDIO setting va->volume to %d\n", - va->volume); - msp3400_dbg("VIDIOCSAUDIO setting va->balance to %d\n", - va->balance); - msp3400_dbg("VIDIOCSAUDIO setting va->flags to %d\n", - va->flags); - msp3400_dbg("VIDIOCSAUDIO setting msp->left to %d\n", - msp->left); - msp3400_dbg("VIDIOCSAUDIO setting msp->right to %d\n", - msp->right); - msp3400_dbg("VIDIOCSAUDIO setting msp->bass to %d\n", - msp->bass); - msp3400_dbg("VIDIOCSAUDIO setting msp->treble to %d\n", - msp->treble); - msp3400_dbg("VIDIOCSAUDIO setting msp->mode to %d\n", - msp->mode); - msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - msp3400c_setbass(client, msp->bass); - msp3400c_settreble(client, msp->treble); - - if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) - msp_any_set_audmode(client,mode_v4l1_to_v4l2(va->mode)); - break; - } - - case VIDIOCSCHAN: - { - struct video_channel *vc = arg; - - msp3400_dbg("VIDIOCSCHAN (norm=%d)\n",vc->norm); - msp->norm = vc->norm; - msp_wake_thread(client); - break; - } - - case VIDIOCSFREQ: - case VIDIOC_S_FREQUENCY: - { - /* new channel -- kick audio carrier scan */ - msp3400_dbg("VIDIOCSFREQ\n"); - msp_wake_thread(client); - break; - } - - /* msp34xx specific */ - case MSP_SET_MATRIX: - { - struct msp_matrix *mspm = arg; - - msp3400_dbg("MSP_SET_MATRIX\n"); - msp3400c_set_scart(client, mspm->input, mspm->output); - break; - } - - /* --- v4l2 ioctls --- */ - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - - /*FIXME: use V4L2 mode flags on msp3400 instead of V4L1*/ - if (*id & V4L2_STD_PAL) { - msp->norm=VIDEO_MODE_PAL; - } else if (*id & V4L2_STD_SECAM) { - msp->norm=VIDEO_MODE_SECAM; - } else { - msp->norm=VIDEO_MODE_NTSC; - } - - msp_wake_thread(client); - return 0; - } - - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - - if (i->index != 0) - return -EINVAL; - - i->type = V4L2_INPUT_TYPE_TUNER; - switch (i->index) { - case AUDIO_RADIO: - strcpy(i->name,"Radio"); - break; - case AUDIO_EXTERN_1: - strcpy(i->name,"Extern 1"); - break; - case AUDIO_EXTERN_2: - strcpy(i->name,"Extern 2"); - break; - case AUDIO_TUNER: - strcpy(i->name,"Television"); - break; - default: - return -EINVAL; - } - return 0; - } - - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *a = arg; - - memset(a,0,sizeof(*a)); - - switch (a->index) { - case AUDIO_RADIO: - strcpy(a->name,"Radio"); - break; - case AUDIO_EXTERN_1: - strcpy(a->name,"Extern 1"); - break; - case AUDIO_EXTERN_2: - strcpy(a->name,"Extern 2"); - break; - case AUDIO_TUNER: - strcpy(a->name,"Television"); - break; - default: - return -EINVAL; - } - - msp_any_detect_stereo(client); - if (msp->audmode == V4L2_TUNER_MODE_STEREO) { - a->capability=V4L2_AUDCAP_STEREO; - } - - break; - } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *sarg = arg; - - switch (sarg->index) { - case AUDIO_RADIO: - /* Hauppauge uses IN2 for the radio */ - msp->mode = MSP_MODE_FM_RADIO; - scart = SCART_IN2; - break; - case AUDIO_EXTERN_1: - /* IN1 is often used for external input ... */ - msp->mode = MSP_MODE_EXTERN; - scart = SCART_IN1; - break; - case AUDIO_EXTERN_2: - /* ... sometimes it is IN2 through ;) */ - msp->mode = MSP_MODE_EXTERN; - scart = SCART_IN2; - break; - case AUDIO_TUNER: - msp->mode = -1; - break; - } - if (scart) { - msp->rxsubchans = V4L2_TUNER_SUB_STEREO; - msp->audmode = V4L2_TUNER_MODE_STEREO; - msp3400c_set_scart(client,scart,0); - msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); - } - if (sarg->capability==V4L2_AUDCAP_STEREO) { - msp->audmode = V4L2_TUNER_MODE_STEREO; - } else { - msp->audmode &= ~V4L2_TUNER_MODE_STEREO; - } - msp_any_set_audmode(client, msp->audmode); - msp_wake_thread(client); - break; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *vt = arg; - - msp_any_detect_stereo(client); - vt->audmode = msp->audmode; - vt->rxsubchans = msp->rxsubchans; - vt->capability = V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_LANG1| - V4L2_TUNER_CAP_LANG2; - break; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; - - /* only set audmode */ - if (vt->audmode != -1 && vt->audmode != 0) - msp_any_set_audmode(client, vt->audmode); - break; - } - - case VIDIOC_G_AUDOUT: - { - struct v4l2_audioout *a=(struct v4l2_audioout *)arg; - int idx=a->index; - - memset(a,0,sizeof(*a)); - - switch (idx) { - case 0: - strcpy(a->name,"Scart1 Out"); - break; - case 1: - strcpy(a->name,"Scart2 Out"); - break; - case 2: - strcpy(a->name,"I2S Out"); - break; - default: - return -EINVAL; - } - break; - - } - case VIDIOC_S_AUDOUT: - { - struct v4l2_audioout *a=(struct v4l2_audioout *)arg; - - if (a->index<0||a->index>2) - return -EINVAL; - - if (a->index==2) { - if (a->mode == V4L2_AUDMODE_32BITS) - msp->i2s_mode=1; - else - msp->i2s_mode=0; - } - msp3400_dbg("Setting audio out on msp34xx to input %i, mode %i\n", - a->index,msp->i2s_mode); - msp3400c_set_scart(client,msp->in_scart,a->index+1); - - break; - } - - default: - /* nothing */ - break; - } - return 0; -} - -static int msp_suspend(struct device * dev, pm_message_t state) -{ - struct i2c_client *client = container_of(dev, struct i2c_client, dev); - - msp3400_dbg("msp34xx: suspend\n"); - msp3400c_reset(client); - return 0; -} - -static int msp_resume(struct device * dev) -{ - struct i2c_client *client = container_of(dev, struct i2c_client, dev); - - msp3400_dbg("msp34xx: resume\n"); - msp_wake_thread(client); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static int __init msp3400_init_module(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit msp3400_cleanup_module(void) -{ - i2c_del_driver(&driver); -} - -module_init(msp3400_init_module); -module_exit(msp3400_cleanup_module); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index 2d9ff40f0b09..8a05cf500a8c 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -6,22 +6,28 @@ /* ---------------------------------------------------------------------- */ -struct msp_dfpreg { - int reg; - int value; -}; - struct msp_matrix { int input; int output; }; -#define MSP_SET_DFPREG _IOW('m',15,struct msp_dfpreg) -#define MSP_GET_DFPREG _IOW('m',16,struct msp_dfpreg) - /* ioctl for MSP_SET_MATRIX will have to be registered */ #define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix) +/* This macro is allowed for *constants* only, gcc must calculate it + at compile time. Remember -- no floats in kernel mode */ +#define MSP_CARRIER(freq) ((int)((float)(freq / 18.432) * (1 << 24))) + +#define MSP_MODE_AM_DETECT 0 +#define MSP_MODE_FM_RADIO 2 +#define MSP_MODE_FM_TERRA 3 +#define MSP_MODE_FM_SAT 4 +#define MSP_MODE_FM_NICAM1 5 +#define MSP_MODE_FM_NICAM2 6 +#define MSP_MODE_AM_NICAM 7 +#define MSP_MODE_BTSC 8 +#define MSP_MODE_EXTERN 9 + #define SCART_MASK 0 #define SCART_IN1 1 #define SCART_IN2 2 @@ -36,4 +42,84 @@ struct msp_matrix { #define SCART1_OUT 1 #define SCART2_OUT 2 +#define OPMODE_AUTO -1 +#define OPMODE_MANUAL 0 +#define OPMODE_AUTODETECT 1 /* use autodetect (>= msp3410 only) */ +#define OPMODE_AUTOSELECT 2 /* use autodetect & autoselect (>= msp34xxG) */ + +/* module parameters */ +extern int debug; +extern int once; +extern int amsound; +extern int standard; +extern int dolby; +extern int stereo_threshold; + +struct msp_state { + int rev1, rev2; + u8 has_nicam; + u8 has_radio; + u8 has_headphones; + u8 has_ntsc_jp_d_k3; + u8 has_scart4; + u8 has_scart23_in_scart2_out; + u8 has_scart2_out_volume; + u8 has_i2s_conf; + u8 has_subwoofer; + u8 has_sound_processing; + u8 has_virtual_dolby_surround; + u8 has_dolby_pro_logic; + + int radio; + int opmode; + int std; + int mode; + v4l2_std_id v4l2_std; + int nicam_on; + int acb; + int in_scart; + int i2s_mode; + int main, second; /* sound carrier */ + int input; + int source; /* see msp34xxg_set_source */ + + /* v4l2 */ + int audmode; + int rxsubchans; + + int volume, muted; + int balance, loudness; + int bass, treble; + + /* thread */ + struct task_struct *kthread; + wait_queue_head_t wq; + int restart:1; + int watch_stereo:1; +}; + +/* msp3400-driver.c */ +int msp_write_dem(struct i2c_client *client, int addr, int val); +int msp_write_dsp(struct i2c_client *client, int addr, int val); +int msp_read_dem(struct i2c_client *client, int addr); +int msp_read_dsp(struct i2c_client *client, int addr); +int msp_reset(struct i2c_client *client); +void msp_set_scart(struct i2c_client *client, int in, int out); +void msp_set_mute(struct i2c_client *client); +void msp_set_audio(struct i2c_client *client); +int msp_modus(struct i2c_client *client); +int msp_sleep(struct msp_state *state, int timeout); + +/* msp3400-kthreads.c */ +const char *msp_standard_std_name(int std); +void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2); +void msp3400c_setmode(struct i2c_client *client, int type); +void msp3400c_setstereo(struct i2c_client *client, int mode); +int autodetect_stereo(struct i2c_client *client); +int msp3400c_thread(void *data); +int msp3410d_thread(void *data); +int msp34xxg_thread(void *data); +void msp34xxg_detect_stereo(struct i2c_client *client); +void msp34xxg_set_audmode(struct i2c_client *client, int audmode); + #endif /* MSP3400_H */ diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 2180018f06de..2c19c9588c02 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -20,6 +20,9 @@ module_param(tv_antenna, int, 0644); static unsigned int radio_antenna = 0; module_param(radio_antenna, int, 0644); +/* from tuner-core.c */ +extern int debug; + /* ---------------------------------------------------------------------- */ #define MT2032 0x04 @@ -401,7 +404,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned div2a=(lo2/8)-1; div2b=lo2-(div2a+1)*8; - if (tuner_debug > 1) { + if (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); @@ -417,7 +420,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned buf[5]=div2a; if(num2!=0) buf[5]=buf[5]|0x40; - if (tuner_debug > 1) { + if (debug > 1) { int i; tuner_dbg("bufs is: "); for(i=0;i<6;i++) @@ -494,11 +497,18 @@ int microtune_init(struct i2c_client *c) t->tv_freq = NULL; t->radio_freq = NULL; t->standby = NULL; + if (t->std & V4L2_STD_525_60) { + tuner_dbg("pinnacle ntsc\n"); + t->radio_if2 = 41300 * 1000; + } else { + tuner_dbg("pinnacle pal\n"); + t->radio_if2 = 33300 * 1000; + } name = "unknown"; i2c_master_send(c,buf,1); i2c_master_recv(c,buf,21); - if (tuner_debug) { + if (debug) { int i; tuner_dbg("MT20xx hexdump:"); for(i=0;i<21;i++) { diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index d04793fb80fc..91681aa6c657 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -26,6 +26,7 @@ #include <media/saa7146_vv.h> #include <media/tuner.h> #include <linux/video_decoder.h> +#include <media/v4l2-common.h> #include "mxb.h" #include "tea6415c.h" diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 2504207b2e3d..9e6448639480 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -883,6 +883,7 @@ static struct file_operations pms_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = pms_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .read = pms_read, .llseek = no_llseek, }; diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index a51c7bd96618..73b4f0e2abf0 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -702,6 +702,7 @@ static struct file_operations saa_fops = { .open = saa5249_open, .release = saa5249_release, .ioctl = saa5249_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index d60a783e0473..e70b17ef36e9 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -427,18 +427,8 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind) static int saa6588_probe(struct i2c_adapter *adap) { -#ifdef I2C_CLASS_TV_ANALOG if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, saa6588_attach); -#else - switch (adap->id) { - case I2C_HW_B_BT848: - case I2C_HW_B_RIVA: - case I2C_HW_SAA7134: - return i2c_probe(adap, &addr_data, saa6588_attach); - break; - } -#endif return 0; } @@ -496,7 +486,7 @@ static int saa6588_command(struct i2c_client *client, unsigned int cmd, static struct i2c_driver driver = { .driver = { - .name = "i2c saa6588 driver", + .name = "saa6588", }, .id = -1, /* FIXME */ .attach_adapter = saa6588_probe, diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 29e28c742cd4..4a4bc69fb0e9 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -39,31 +39,18 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-common.h> +#include <media/audiochip.h> +#include <asm/div64.h> MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); MODULE_LICENSE("GPL"); static int debug = 0; -module_param(debug, int, 0644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define saa7115_dbg(fmt,arg...) \ - do { \ - if (debug) \ - printk(KERN_INFO "%s debug %d-%04x: " fmt, \ - client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); \ - } while (0) - -#define saa7115_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) -#define saa7115_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) - static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; @@ -73,12 +60,13 @@ struct saa7115_state { v4l2_std_id std; int input; int enable; + int radio; int bright; int contrast; int hue; int sat; enum v4l2_chip_ident ident; - enum v4l2_audio_clock_freq audclk_freq; + u32 audclk_freq; }; /* ----------------------------------------------------------------------- */ @@ -469,80 +457,6 @@ static const unsigned char saa7115_init_misc[] = { 0x00, 0x00 }; -/* ============== SAA7715 AUDIO settings ============= */ - -/* 48.0 kHz */ -static const unsigned char saa7115_cfg_48_audio[] = { - 0x34, 0xce, - 0x35, 0xfb, - 0x36, 0x30, - 0x00, 0x00 -}; - -/* 44.1 kHz */ -static const unsigned char saa7115_cfg_441_audio[] = { - 0x34, 0xf2, - 0x35, 0x00, - 0x36, 0x2d, - 0x00, 0x00 -}; - -/* 32.0 kHz */ -static const unsigned char saa7115_cfg_32_audio[] = { - 0x34, 0xdf, - 0x35, 0xa7, - 0x36, 0x20, - 0x00, 0x00 -}; - -/* 48.0 kHz 60hz */ -static const unsigned char saa7115_cfg_60hz_48_audio[] = { - 0x30, 0xcd, - 0x31, 0x20, - 0x32, 0x03, - 0x00, 0x00 -}; - -/* 48.0 kHz 50hz */ -static const unsigned char saa7115_cfg_50hz_48_audio[] = { - 0x30, 0x00, - 0x31, 0xc0, - 0x32, 0x03, - 0x00, 0x00 -}; - -/* 44.1 kHz 60hz */ -static const unsigned char saa7115_cfg_60hz_441_audio[] = { - 0x30, 0xbc, - 0x31, 0xdf, - 0x32, 0x02, - 0x00, 0x00 -}; - -/* 44.1 kHz 50hz */ -static const unsigned char saa7115_cfg_50hz_441_audio[] = { - 0x30, 0x00, - 0x31, 0x72, - 0x32, 0x03, - 0x00, 0x00 -}; - -/* 32.0 kHz 60hz */ -static const unsigned char saa7115_cfg_60hz_32_audio[] = { - 0x30, 0xde, - 0x31, 0x15, - 0x32, 0x02, - 0x00, 0x00 -}; - -/* 32.0 kHz 50hz */ -static const unsigned char saa7115_cfg_50hz_32_audio[] = { - 0x30, 0x00, - 0x31, 0x80, - 0x32, 0x02, - 0x00, 0x00 -}; - static int saa7115_odd_parity(u8 c) { c ^= (c >> 4); @@ -627,40 +541,38 @@ static int saa7115_decode_wss(u8 * p) } -static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq) +static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq) { struct saa7115_state *state = i2c_get_clientdata(client); + u32 acpf; + u32 acni; + u32 hz; + u64 f; - saa7115_dbg("set audio clock freq: %d\n", freq); - switch (freq) { - case V4L2_AUDCLK_32_KHZ: - saa7115_writeregs(client, saa7115_cfg_32_audio); - if (state->std & V4L2_STD_525_60) { - saa7115_writeregs(client, saa7115_cfg_60hz_32_audio); - } else { - saa7115_writeregs(client, saa7115_cfg_50hz_32_audio); - } - break; - case V4L2_AUDCLK_441_KHZ: - saa7115_writeregs(client, saa7115_cfg_441_audio); - if (state->std & V4L2_STD_525_60) { - saa7115_writeregs(client, saa7115_cfg_60hz_441_audio); - } else { - saa7115_writeregs(client, saa7115_cfg_50hz_441_audio); - } - break; - case V4L2_AUDCLK_48_KHZ: - saa7115_writeregs(client, saa7115_cfg_48_audio); - if (state->std & V4L2_STD_525_60) { - saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); - } else { - saa7115_writeregs(client, saa7115_cfg_50hz_48_audio); - } - break; - default: - saa7115_dbg("invalid audio setting %d\n", freq); - return -EINVAL; - } + v4l_dbg(1, client, "set audio clock freq: %d\n", freq); + + /* sanity check */ + if (freq < 32000 || freq > 48000) + return -EINVAL; + + /* hz is the refresh rate times 100 */ + hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000; + /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */ + acpf = (25600 * freq) / hz; + /* acni = (256 * freq * 2^23) / crystal_frequency = + (freq * 2^(8+23)) / crystal_frequency = + (freq << 31) / 32.11 MHz */ + f = freq; + f = f << 31; + do_div(f, 32110000); + acni = f; + + saa7115_write(client, 0x30, acpf & 0xff); + saa7115_write(client, 0x31, (acpf >> 8) & 0xff); + saa7115_write(client, 0x32, (acpf >> 16) & 0x03); + saa7115_write(client, 0x34, acni & 0xff); + saa7115_write(client, 0x35, (acni >> 8) & 0xff); + saa7115_write(client, 0x36, (acni >> 16) & 0x3f); state->audclk_freq = freq; return 0; } @@ -672,7 +584,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: if (ctrl->value < 0 || ctrl->value > 255) { - saa7115_err("invalid brightness setting %d\n", ctrl->value); + v4l_err(client, "invalid brightness setting %d\n", ctrl->value); return -ERANGE; } @@ -682,7 +594,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c case V4L2_CID_CONTRAST: if (ctrl->value < 0 || ctrl->value > 127) { - saa7115_err("invalid contrast setting %d\n", ctrl->value); + v4l_err(client, "invalid contrast setting %d\n", ctrl->value); return -ERANGE; } @@ -692,7 +604,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c case V4L2_CID_SATURATION: if (ctrl->value < 0 || ctrl->value > 127) { - saa7115_err("invalid saturation setting %d\n", ctrl->value); + v4l_err(client, "invalid saturation setting %d\n", ctrl->value); return -ERANGE; } @@ -702,13 +614,16 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c case V4L2_CID_HUE: if (ctrl->value < -127 || ctrl->value > 127) { - saa7115_err("invalid hue setting %d\n", ctrl->value); + v4l_err(client, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } state->hue = ctrl->value; saa7115_write(client, 0x0d, state->hue); break; + + default: + return -EINVAL; } return 0; @@ -743,12 +658,22 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) struct saa7115_state *state = i2c_get_clientdata(client); int taskb = saa7115_read(client, 0x80) & 0x10; + /* Prevent unnecessary standard changes. During a standard + change the I-Port is temporarily disabled. Any devices + reading from that port can get confused. + Note that VIDIOC_S_STD is also used to switch from + radio to TV mode, so if a VIDIOC_S_STD is broadcast to + all I2C devices then you do not want to have an unwanted + side-effect here. */ + if (std == state->std) + return; + // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. if (std & V4L2_STD_525_60) { - saa7115_dbg("decoder set standard 60 Hz\n"); + v4l_dbg(1, client, "decoder set standard 60 Hz\n"); saa7115_writeregs(client, saa7115_cfg_60hz_video); } else { - saa7115_dbg("decoder set standard 50 Hz\n"); + v4l_dbg(1, client, "decoder set standard 50 Hz\n"); saa7115_writeregs(client, saa7115_cfg_50hz_video); } @@ -773,24 +698,17 @@ static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client) static void saa7115_log_status(struct i2c_client *client) { struct saa7115_state *state = i2c_get_clientdata(client); - char *audfreq = "undefined"; int reg1e, reg1f; int signalOk; int vcr; - switch (state->audclk_freq) { - case V4L2_AUDCLK_32_KHZ: audfreq = "32 kHz"; break; - case V4L2_AUDCLK_441_KHZ: audfreq = "44.1 kHz"; break; - case V4L2_AUDCLK_48_KHZ: audfreq = "48 kHz"; break; - } - - saa7115_info("Audio frequency: %s\n", audfreq); + v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq); if (client->name[6] == '4') { /* status for the saa7114 */ reg1f = saa7115_read(client, 0x1f); signalOk = (reg1f & 0xc1) == 0x81; - saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad"); - saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); + v4l_info(client, "Video signal: %s\n", signalOk ? "ok" : "bad"); + v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); return; } @@ -801,21 +719,26 @@ static void saa7115_log_status(struct i2c_client *client) signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; vcr = !(reg1f & 0x10); - saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); - saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); + if (state->input >= 6) { + v4l_info(client, "Input: S-Video %d\n", state->input - 6); + } else { + v4l_info(client, "Input: Composite %d\n", state->input); + } + v4l_info(client, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); + v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); switch (reg1e & 0x03) { case 1: - saa7115_info("Detected format: NTSC\n"); + v4l_info(client, "Detected format: NTSC\n"); break; case 2: - saa7115_info("Detected format: PAL\n"); + v4l_info(client, "Detected format: PAL\n"); break; case 3: - saa7115_info("Detected format: SECAM\n"); + v4l_info(client, "Detected format: SECAM\n"); break; default: - saa7115_info("Detected format: BW/No color\n"); + v4l_info(client, "Detected format: BW/No color\n"); break; } } @@ -940,7 +863,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt pix = &(fmt->fmt.pix); - saa7115_dbg("decoder set size\n"); + v4l_dbg(1, client, "decoder set size\n"); /* FIXME need better bounds checking here */ if ((pix->width < 1) || (pix->width > 1440)) @@ -966,7 +889,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt HPSC = HPSC ? HPSC : 1; HFSC = (int)((1024 * 720) / (HPSC * pix->width)); - saa7115_dbg("Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); + v4l_dbg(1, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); /* FIXME hardcodes to "Task B" * write H prescaler integer */ saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f)); @@ -980,10 +903,10 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff)); } else { if (is_50hz) { - saa7115_dbg("Setting full 50hz width\n"); + v4l_dbg(1, client, "Setting full 50hz width\n"); saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x); } else { - saa7115_dbg("Setting full 60hz width\n"); + v4l_dbg(1, client, "Setting full 60hz width\n"); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); } } @@ -992,7 +915,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt if (pix->height != Vsrc) { VSCY = (int)((1024 * Vsrc) / pix->height); - saa7115_dbg("Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); + v4l_dbg(1, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); /* Correct Contrast and Luminance */ saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY)); @@ -1006,10 +929,10 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff)); } else { if (is_50hz) { - saa7115_dbg("Setting full 50Hz height\n"); + v4l_dbg(1, client, "Setting full 50Hz height\n"); saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y); } else { - saa7115_dbg("Setting full 60hz height\n"); + v4l_dbg(1, client, "Setting full 60hz height\n"); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); } } @@ -1089,6 +1012,48 @@ static void saa7115_decode_vbi_line(struct i2c_client *client, /* ============ SAA7115 AUDIO settings (end) ============= */ +static struct v4l2_queryctrl saa7115_qctrl[] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 128, + .flags = 0, + }, { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 64, + .flags = 0, + }, { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 64, + .flags = 0, + }, { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = -128, + .maximum = 127, + .step = 1, + .default_value = 0, + .flags = 0, + }, +}; + +/* ----------------------------------------------------------------------- */ + static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct saa7115_state *state = i2c_get_clientdata(client); @@ -1103,16 +1068,18 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg); case VIDIOC_INT_AUDIO_CLOCK_FREQ: - return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg); + return saa7115_set_audio_clock_freq(client, *(u32 *)arg); case VIDIOC_G_TUNER: { struct v4l2_tuner *vt = arg; int status; + if (state->radio) + break; status = saa7115_read(client, 0x1f); - saa7115_dbg("status: 0x%02x\n", status); + v4l_dbg(1, client, "status: 0x%02x\n", status); vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; break; } @@ -1127,20 +1094,38 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar case VIDIOC_S_CTRL: return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg); + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + int i; + + for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++) + if (qc->id && qc->id == saa7115_qctrl[i].id) { + memcpy(qc, &saa7115_qctrl[i], sizeof(*qc)); + return 0; + } + return -EINVAL; + } + case VIDIOC_G_STD: *(v4l2_std_id *)arg = saa7115_get_v4lstd(client); break; case VIDIOC_S_STD: + state->radio = 0; saa7115_set_v4lstd(client, *(v4l2_std_id *)arg); break; + case AUDC_SET_RADIO: + state->radio = 1; + break; + case VIDIOC_G_INPUT: *(int *)arg = state->input; break; case VIDIOC_S_INPUT: - saa7115_dbg("decoder set input %d\n", *iarg); + v4l_dbg(1, client, "decoder set input %d\n", *iarg); /* inputs from 0-9 are available */ if (*iarg < 0 || *iarg > 9) { return -EINVAL; @@ -1148,7 +1133,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar if (state->input == *iarg) break; - saa7115_dbg("now setting %s input\n", + v4l_dbg(1, client, "now setting %s input\n", *iarg >= 6 ? "S-Video" : "Composite"); state->input = *iarg; @@ -1165,7 +1150,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar case VIDIOC_STREAMON: case VIDIOC_STREAMOFF: - saa7115_dbg("%s output\n", + v4l_dbg(1, client, "%s output\n", (cmd == VIDIOC_STREAMON) ? "enable" : "disable"); if (state->enable != (cmd == VIDIOC_STREAMON)) { @@ -1179,7 +1164,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar break; case VIDIOC_INT_RESET: - saa7115_dbg("decoder RESET\n"); + v4l_dbg(1, client, "decoder RESET\n"); saa7115_writeregs(client, saa7115_cfg_reset_scaler); break; @@ -1273,19 +1258,19 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) client->driver = &i2c_driver_saa7115; snprintf(client->name, sizeof(client->name) - 1, "saa7115"); - saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1); + v4l_dbg(1, client, "detecting saa7115 client on address 0x%x\n", address << 1); saa7115_write(client, 0, 5); chip_id = saa7115_read(client, 0) & 0x0f; if (chip_id != 4 && chip_id != 5) { - saa7115_dbg("saa7115 not found\n"); + v4l_dbg(1, client, "saa7115 not found\n"); kfree(client); return 0; } if (chip_id == 4) { snprintf(client->name, sizeof(client->name) - 1, "saa7114"); } - saa7115_info("saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); + v4l_info(client, "saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL); i2c_set_clientdata(client, state); @@ -1297,14 +1282,15 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) state->std = V4L2_STD_NTSC; state->input = -1; state->enable = 1; + state->radio = 0; state->bright = 128; state->contrast = 64; state->hue = 0; state->sat = 64; state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; - state->audclk_freq = V4L2_AUDCLK_48_KHZ; + state->audclk_freq = 48000; - saa7115_dbg("writing init values\n"); + v4l_dbg(1, client, "writing init values\n"); /* init to 60hz/48khz */ saa7115_writeregs(client, saa7115_init_auto_input); @@ -1312,13 +1298,12 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); saa7115_writeregs(client, saa7115_cfg_60hz_video); - saa7115_writeregs(client, saa7115_cfg_48_audio); - saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); + saa7115_set_audio_clock_freq(client, state->audclk_freq); saa7115_writeregs(client, saa7115_cfg_reset_scaler); i2c_attach_client(client); - saa7115_dbg("status: (1E) 0x%02x, (1F) 0x%02x\n", + v4l_dbg(1, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", saa7115_read(client, 0x1e), saa7115_read(client, 0x1f)); return 0; @@ -1326,11 +1311,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) static int saa7115_probe(struct i2c_adapter *adapter) { -#ifdef I2C_CLASS_TV_ANALOG if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif return i2c_probe(adapter, &addr_data, &saa7115_attach); return 0; } diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 8008537391b5..f39a7be08588 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -567,9 +567,7 @@ static struct i2c_driver i2c_driver_saa711x = { .driver = { .name = "saa711x", }, - .id = I2C_DRIVERID_SAA711X, - .attach_adapter = saa711x_attach_adapter, .detach_client = saa711x_detach_client, .command = saa711x_command, diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index bca6ed0e2752..2009c1bc4720 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -66,30 +66,6 @@ module_param(test_image, int, 0644); MODULE_PARM_DESC(debug, "debug level (0-2)"); MODULE_PARM_DESC(test_image, "test_image (0-1)"); -#define saa7127_dbg(fmt, arg...) \ - do { \ - if (debug >= 1) \ - printk(KERN_INFO "%s debug %d-%04x: " fmt, \ - client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); \ - } while (0) - -/* High volume debug. Use with care. */ -#define saa7127_dbg_highvol(fmt, arg...) \ - do { \ - if (debug == 2) \ - printk(KERN_INFO "%s debug %d-%04x: " fmt, \ - client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); \ - } while (0) - -#define saa7127_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) -#define saa7127_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) - static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; @@ -336,7 +312,7 @@ static int saa7127_write(struct i2c_client *client, u8 reg, u8 val) if (i2c_smbus_write_byte_data(client, reg, val) == 0) return 0; } - saa7127_err("I2C Write Problem\n"); + v4l_err(client, "I2C Write Problem\n"); return -1; } @@ -362,7 +338,7 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat if (enable && (data->field != 0 || data->line != 16)) return -EINVAL; if (state->vps_enable != enable) { - saa7127_dbg("Turn VPS Signal %s\n", enable ? "on" : "off"); + v4l_dbg(1, client, "Turn VPS Signal %s\n", enable ? "on" : "off"); saa7127_write(client, 0x54, enable << 7); state->vps_enable = enable; } @@ -374,7 +350,7 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat state->vps_data[2] = data->data[11]; state->vps_data[3] = data->data[12]; state->vps_data[4] = data->data[13]; - saa7127_dbg("Set VPS data %02x %02x %02x %02x %02x\n", + v4l_dbg(1, client, "Set VPS data %02x %02x %02x %02x %02x\n", state->vps_data[0], state->vps_data[1], state->vps_data[2], state->vps_data[3], state->vps_data[4]); @@ -397,7 +373,7 @@ static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data if (enable && (data->field != 0 || data->line != 21)) return -EINVAL; if (state->cc_enable != enable) { - saa7127_dbg("Turn CC %s\n", enable ? "on" : "off"); + v4l_dbg(1, client, "Turn CC %s\n", enable ? "on" : "off"); saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, (state->xds_enable << 7) | (enable << 6) | 0x11); state->cc_enable = enable; @@ -405,7 +381,7 @@ static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data if (!enable) return 0; - saa7127_dbg_highvol("CC data: %04x\n", cc); + v4l_dbg(2, client, "CC data: %04x\n", cc); saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff); saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8); state->cc_data = cc; @@ -423,7 +399,7 @@ static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_dat if (enable && (data->field != 1 || data->line != 21)) return -EINVAL; if (state->xds_enable != enable) { - saa7127_dbg("Turn XDS %s\n", enable ? "on" : "off"); + v4l_dbg(1, client, "Turn XDS %s\n", enable ? "on" : "off"); saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, (enable << 7) | (state->cc_enable << 6) | 0x11); state->xds_enable = enable; @@ -431,7 +407,7 @@ static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_dat if (!enable) return 0; - saa7127_dbg_highvol("XDS data: %04x\n", xds); + v4l_dbg(2, client, "XDS data: %04x\n", xds); saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff); saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8); state->xds_data = xds; @@ -448,7 +424,7 @@ static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_dat if (enable && (data->field != 0 || data->line != 23)) return -EINVAL; if (state->wss_enable != enable) { - saa7127_dbg("Turn WSS %s\n", enable ? "on" : "off"); + v4l_dbg(1, client, "Turn WSS %s\n", enable ? "on" : "off"); saa7127_write(client, 0x27, enable << 7); state->wss_enable = enable; } @@ -457,7 +433,7 @@ static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_dat saa7127_write(client, 0x26, data->data[0]); saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f)); - saa7127_dbg("WSS mode: %s\n", wss_strs[data->data[0] & 0xf]); + v4l_dbg(1, client, "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]); state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0]; return 0; } @@ -469,11 +445,11 @@ static int saa7127_set_video_enable(struct i2c_client *client, int enable) struct saa7127_state *state = i2c_get_clientdata(client); if (enable) { - saa7127_dbg("Enable Video Output\n"); + v4l_dbg(1, client, "Enable Video Output\n"); saa7127_write(client, 0x2d, state->reg_2d); saa7127_write(client, 0x61, state->reg_61); } else { - saa7127_dbg("Disable Video Output\n"); + v4l_dbg(1, client, "Disable Video Output\n"); saa7127_write(client, 0x2d, (state->reg_2d & 0xf0)); saa7127_write(client, 0x61, (state->reg_61 | 0xc0)); } @@ -489,11 +465,11 @@ static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std) const struct i2c_reg_value *inittab; if (std & V4L2_STD_525_60) { - saa7127_dbg("Selecting 60 Hz video Standard\n"); + v4l_dbg(1, client, "Selecting 60 Hz video Standard\n"); inittab = saa7127_init_config_60hz; state->reg_61 = SAA7127_60HZ_DAC_CONTROL; } else { - saa7127_dbg("Selecting 50 Hz video Standard\n"); + v4l_dbg(1, client, "Selecting 50 Hz video Standard\n"); inittab = saa7127_init_config_50hz; state->reg_61 = SAA7127_50HZ_DAC_CONTROL; } @@ -544,7 +520,7 @@ static int saa7127_set_output_type(struct i2c_client *client, int output) default: return -EINVAL; } - saa7127_dbg("Selecting %s output type\n", output_strs[output]); + v4l_dbg(1, client, "Selecting %s output type\n", output_strs[output]); /* Configure Encoder */ saa7127_write(client, 0x2d, state->reg_2d); @@ -561,12 +537,12 @@ static int saa7127_set_input_type(struct i2c_client *client, int input) switch (input) { case SAA7127_INPUT_TYPE_NORMAL: /* avia */ - saa7127_dbg("Selecting Normal Encoder Input\n"); + v4l_dbg(1, client, "Selecting Normal Encoder Input\n"); state->reg_3a_cb = 0; break; case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */ - saa7127_dbg("Selecting Color Bar generator\n"); + v4l_dbg(1, client, "Selecting Color Bar generator\n"); state->reg_3a_cb = 0x80; break; @@ -633,14 +609,14 @@ static int saa7127_command(struct i2c_client *client, break; case VIDIOC_LOG_STATUS: - saa7127_info("Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz"); - saa7127_info("Input: %s\n", state->input_type ? "color bars" : "normal"); - saa7127_info("Output: %s\n", state->video_enable ? + v4l_info(client, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz"); + v4l_info(client, "Input: %s\n", state->input_type ? "color bars" : "normal"); + v4l_info(client, "Output: %s\n", state->video_enable ? output_strs[state->output_type] : "disabled"); - saa7127_info("WSS: %s\n", state->wss_enable ? + v4l_info(client, "WSS: %s\n", state->wss_enable ? wss_strs[state->wss_mode] : "disabled"); - saa7127_info("VPS: %s\n", state->vps_enable ? "enabled" : "disabled"); - saa7127_info("CC: %s\n", state->cc_enable ? "enabled" : "disabled"); + v4l_info(client, "VPS: %s\n", state->vps_enable ? "enabled" : "disabled"); + v4l_info(client, "CC: %s\n", state->cc_enable ? "enabled" : "disabled"); break; #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -723,7 +699,7 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) client->driver = &i2c_driver_saa7127; snprintf(client->name, sizeof(client->name) - 1, "saa7127"); - saa7127_dbg("detecting saa7127 client on address 0x%x\n", address << 1); + v4l_dbg(1, client, "detecting saa7127 client on address 0x%x\n", address << 1); /* First test register 0: Bits 5-7 are a version ID (should be 0), and bit 2 should also be 0. @@ -732,7 +708,7 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) 0x1d after a reset and not expected to ever change. */ if ((saa7127_read(client, 0) & 0xe4) != 0 || (saa7127_read(client, 0x29) & 0x3f) != 0x1d) { - saa7127_dbg("saa7127 not found\n"); + v4l_dbg(1, client, "saa7127 not found\n"); kfree(client); return 0; } @@ -748,7 +724,7 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) /* Configure Encoder */ - saa7127_dbg("Configuring encoder\n"); + v4l_dbg(1, client, "Configuring encoder\n"); saa7127_write_inittab(client, saa7127_init_config_common); saa7127_set_std(client, V4L2_STD_NTSC); saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH); @@ -769,12 +745,12 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2); saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa); if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { - saa7127_info("saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name); saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result); saa7127_write_inittab(client, saa7129_init_config_extra); state->ident = V4L2_IDENT_SAA7129; } else { - saa7127_info("saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name); state->ident = V4L2_IDENT_SAA7127; } @@ -787,11 +763,7 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) static int saa7127_probe(struct i2c_adapter *adapter) { -#ifdef I2C_CLASS_TV_ANALOG if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif return i2c_probe(adapter, &addr_data, saa7127_attach); return 0; } diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 4615a982ac64..ad73c4a60f2b 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -9,7 +9,8 @@ #include <linux/poll.h> #include <linux/i2c.h> #include <linux/types.h> -#include <linux/videodev.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> #include <linux/init.h> #include <linux/crc32.h> @@ -509,7 +510,6 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) { struct saa6752hs_state *h; - printk("saa6752hs: chip found @ 0x%x\n", addr<<1); if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL))) return -ENOMEM; @@ -525,6 +525,8 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) i2c_set_clientdata(&h->client, h); i2c_attach_client(&h->client); + v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1); + return 0; } @@ -598,7 +600,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) static struct i2c_driver driver = { .driver = { - .name = "i2c saa6752hs MPEG encoder", + .name = "saa6752hs", }, .id = I2C_DRIVERID_SAA6752HS, .attach_adapter = saa6752hs_probe, diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index ade05f75fdb0..a7a6ab9298a9 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -20,13 +20,13 @@ * */ -#include <sound/driver.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/time.h> #include <linux/wait.h> #include <linux/moduleparam.h> #include <linux/module.h> +#include <sound/driver.h> #include <sound/core.h> #include <sound/control.h> #include <sound/pcm.h> diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 672fb205959f..77e5be98e4c6 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -25,6 +25,7 @@ #include "saa7134-reg.h" #include "saa7134.h" +#include <media/v4l2-common.h> /* commly used strings */ static char name_mute[] = "mute"; @@ -2555,6 +2556,69 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_CINERGY250PCI] = { + /* remote-control does not work. The signal about a + key press comes in via gpio, but the key code + doesn't. Neither does it have an i2c remote control + interface. */ + .name = "Terratec Cinergy 250 PCI TV", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x80200000, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_svideo, /* NOT tested */ + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE1, + .gpio = 0x0200000, + }, + }, + [SAA7134_BOARD_FLYDVB_TRIO] = { + /* LifeView LR319 FlyDVB Trio */ + /* Peter Missel <peter.missel@onlinehome.de> */ + .name = "LifeView FlyDVB Trio", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x00200000, + .inputs = {{ + .name = name_tv, /* Analog broadcast/cable TV */ + .vmux = 1, + .amux = TV, + .gpio = 0x200000, /* GPIO21=High for TV input */ + .tv = 1, + },{ + .name = name_svideo, /* S-Video signal on S-Video input */ + .vmux = 8, + .amux = LINE2, + },{ + .name = name_comp1, /* Composite signal on S-Video input */ + .vmux = 0, + .amux = LINE2, + },{ + .name = name_comp2, /* Composite input */ + .vmux = 3, + .amux = LINE2, + }}, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2895,6 +2959,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1421, + .subdevice = 0x0351, /* PCI version, new revision */ + .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1421, .subdevice = 0x0370, /* cardbus version */ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, },{ @@ -3002,6 +3072,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x6231, .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x153b, + .subdevice = 0x1160, + .driver_data = SAA7134_BOARD_CINERGY250PCI, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA 7131E */ + .subvendor = 0x5168, + .subdevice = 0x0319, + .driver_data = SAA7134_BOARD_FLYDVB_TRIO, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -3090,6 +3172,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_GO_007_FM: /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ case SAA7134_BOARD_VIDEOMATE_TV_PVR: + case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 21cb3d6be839..accbc32725cf 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -95,77 +95,6 @@ int (*dmasound_exit)(struct saa7134_dev *dev); #define dprintk(fmt, arg...) if (core_debug) \ printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) -/* ------------------------------------------------------------------ */ -/* debug help functions */ - -static const char *v4l1_ioctls[] = { - "0", "GCAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT", - "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ", - "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT", - "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", - "SMICROCODE", "GVBIFMT", "SVBIFMT" }; -#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) - -static const char *v4l2_ioctls[] = { - "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT", - "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF", - "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON", - "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD", - "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER", - "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL", - "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43", - "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT", - "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR", - "S_MODULATOR" -}; -#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) - -static const char *osspcm_ioctls[] = { - "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT", - "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS", - "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER", - "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO", - "SETDUPLEX", "GETODELAY" -}; -#define OSSPCM_IOCTLS ARRAY_SIZE(v4l2_ioctls) - -void saa7134_print_ioctl(char *name, unsigned int cmd) -{ - char *dir; - - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: dir = "--"; break; - case _IOC_READ: dir = "r-"; break; - case _IOC_WRITE: dir = "-w"; break; - case _IOC_READ | _IOC_WRITE: dir = "rw"; break; - default: dir = "??"; break; - } - switch (_IOC_TYPE(cmd)) { - case 'v': - printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n", - name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ? - v4l1_ioctls[_IOC_NR(cmd)] : "???"); - break; - case 'V': - printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n", - name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ? - v4l2_ioctls[_IOC_NR(cmd)] : "???"); - break; - case 'P': - printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n", - name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ? - osspcm_ioctls[_IOC_NR(cmd)] : "???"); - break; - case 'M': - printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n", - name, cmd, dir, _IOC_NR(cmd)); - break; - default: - printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n", - name, cmd, dir, _IOC_NR(cmd)); - } -} - void saa7134_track_gpio(struct saa7134_dev *dev, char *msg) { unsigned long mode,status; @@ -211,7 +140,7 @@ static int pending_call(struct notifier_block *self, unsigned long state, return NOTIFY_DONE; } -static int pending_registered; +static int pending_registered=0; static struct notifier_block pending_notifier = { .notifier_call = pending_call, }; @@ -610,11 +539,38 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) card_has_mpeg(dev)) saa7134_irq_ts_done(dev,status); - if ((report & (SAA7134_IRQ_REPORT_GPIO16 | - SAA7134_IRQ_REPORT_GPIO18)) && - dev->remote) - saa7134_input_irq(dev); + if (report & SAA7134_IRQ_REPORT_GPIO16) { + switch (dev->has_remote) { + case SAA7134_REMOTE_GPIO: + if (dev->remote->mask_keydown & 0x10000) { + saa7134_input_irq(dev); + } + break; + + case SAA7134_REMOTE_I2C: + break; /* FIXME: invoke I2C get_key() */ + default: /* GPIO16 not used by IR remote */ + break; + } + } + + if (report & SAA7134_IRQ_REPORT_GPIO18) { + switch (dev->has_remote) { + case SAA7134_REMOTE_GPIO: + if ((dev->remote->mask_keydown & 0x40000) || + (dev->remote->mask_keyup & 0x40000)) { + saa7134_input_irq(dev); + } + break; + + case SAA7134_REMOTE_I2C: + break; /* FIXME: invoke I2C get_key() */ + + default: /* GPIO18 not used by IR remote */ + break; + } + } } if (10 == loop) { @@ -624,13 +580,16 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) 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 */ + } else if (report & SAA7134_IRQ_REPORT_GPIO16) { + /* disable gpio16 IRQ */ 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)); + "clearing GPIO16 enable bit\n",dev->name); + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16); + } else if (report & SAA7134_IRQ_REPORT_GPIO18) { + /* disable gpio18 IRQs */ + printk(KERN_WARNING "%s/irq: looping -- " + "clearing GPIO18 enable bit\n",dev->name); + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); } else { /* disable all irqs */ printk(KERN_WARNING "%s/irq: looping -- " @@ -711,10 +670,14 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) SAA7134_IRQ2_INTE_PE | SAA7134_IRQ2_INTE_AR; - if (dev->has_remote == SAA7134_REMOTE_GPIO) - irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | - SAA7134_IRQ2_INTE_GPIO18A | - SAA7134_IRQ2_INTE_GPIO16 ); + if (dev->has_remote == SAA7134_REMOTE_GPIO) { + if (dev->remote->mask_keydown & 0x10000) + irq2_mask |= SAA7134_IRQ2_INTE_GPIO16; + else if (dev->remote->mask_keydown & 0x40000) + irq2_mask |= SAA7134_IRQ2_INTE_GPIO18; + else if (dev->remote->mask_keyup & 0x40000) + irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A; + } saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, irq2_mask); @@ -1173,7 +1136,6 @@ module_exit(saa7134_fini); /* ----------------------------------------------------------- */ -EXPORT_SYMBOL(saa7134_print_ioctl); EXPORT_SYMBOL(saa7134_i2c_call_clients); EXPORT_SYMBOL(saa7134_devlist); EXPORT_SYMBOL(saa7134_boards); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index e016480c3468..399f9952596c 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -31,6 +31,7 @@ #include "saa7134-reg.h" #include "saa7134.h" +#include <media/v4l2-common.h> #ifdef HAVE_MT352 # include "mt352.h" diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 575f3e835f91..bd4c389d4c37 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -29,6 +29,7 @@ #include "saa7134.h" #include <media/saa6752hs.h> +#include <media/v4l2-common.h> /* ------------------------------------------------------------------ */ @@ -163,7 +164,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, struct saa7134_dev *dev = file->private_data; if (debug > 1) - saa7134_print_ioctl(dev->name,cmd); + v4l_print_ioctl(dev->name,cmd); switch (cmd) { case VIDIOC_QUERYCAP: { diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 1792d03d621d..6162550c4136 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -30,6 +30,7 @@ #include "saa7134-reg.h" #include "saa7134.h" +#include <media/v4l2-common.h> /* ----------------------------------------------------------- */ @@ -390,9 +391,7 @@ static struct i2c_algorithm saa7134_algo = { static struct i2c_adapter saa7134_adap_template = { .owner = THIS_MODULE, -#ifdef I2C_CLASS_TV_ANALOG .class = I2C_CLASS_TV_ANALOG, -#endif .name = "saa7134", .id = I2C_HW_SAA7134, .algo = &saa7134_algo, diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ab75ca5ac356..82d28cbf289f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -56,23 +56,23 @@ static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = { [ 12 ] = KEY_KP8, [ 13 ] = KEY_KP9, - [ 14 ] = KEY_TUNER, // Air/Cable + [ 14 ] = KEY_MODE, // Air/Cable [ 17 ] = KEY_VIDEO, // Video [ 21 ] = KEY_AUDIO, // Audio - [ 0 ] = KEY_POWER, // Pover + [ 0 ] = KEY_POWER, // Power + [ 24 ] = KEY_TUNER, // AV Source [ 2 ] = KEY_ZOOM, // Fullscreen + [ 26 ] = KEY_LANGUAGE, // Stereo [ 27 ] = KEY_MUTE, // Mute - [ 20 ] = KEY_VOLUMEUP, - [ 23 ] = KEY_VOLUMEDOWN, + [ 20 ] = KEY_VOLUMEUP, // Volume + + [ 23 ] = KEY_VOLUMEDOWN, // Volume - [ 18 ] = KEY_CHANNELUP, // Channel + [ 19 ] = KEY_CHANNELDOWN, // Channel - - [ 6 ] = KEY_AGAIN, // Recal - [ 16 ] = KEY_KPENTER, // Enter - - [ 26 ] = KEY_F22, // Stereo - [ 24 ] = KEY_EDIT, // AV Source + [ 6 ] = KEY_AGAIN, // Recall + [ 16 ] = KEY_ENTER, // Enter }; + static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = { [ 0 ] = KEY_KP0, [ 1 ] = KEY_KP1, @@ -543,12 +543,22 @@ static int build_key(struct saa7134_dev *dev) dprintk("build_key gpio=0x%x mask=0x%x data=%d\n", gpio, ir->mask_keycode, data); - if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || - (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev, &ir->ir, data, data); - } else { - ir_input_nokey(ir->dev, &ir->ir); + if (ir->polling) { + if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || + (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { + ir_input_keydown(ir->dev, &ir->ir, data, data); + } else { + ir_input_nokey(ir->dev, &ir->ir); + } + } + else { /* IRQ driven mode - handle key press and release in one go */ + if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || + (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { + ir_input_keydown(ir->dev, &ir->ir, data, data); + ir_input_nokey(ir->dev, &ir->ir); + } } + return 0; } @@ -686,6 +696,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) polling = 50; // ms break; case SAA7134_BOARD_VIDEOMATE_TV_PVR: + case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: ir_codes = videomate_tv_pvr_codes; mask_keycode = 0x00003F; diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index 8badd2a9cb2f..7448e386a804 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -373,6 +373,42 @@ static ssize_t dsp_write(struct file *file, const char __user *buffer, return -EINVAL; } +static const char *osspcm_ioctls[] = { + "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT", + "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS", + "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER", + "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO", + "SETDUPLEX", "GETODELAY" +}; +#define OSSPCM_IOCTLS ARRAY_SIZE(osspcm_ioctls) + +static void saa7134_oss_print_ioctl(char *name, unsigned int cmd) +{ + char *dir; + + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: dir = "--"; break; + case _IOC_READ: dir = "r-"; break; + case _IOC_WRITE: dir = "-w"; break; + case _IOC_READ | _IOC_WRITE: dir = "rw"; break; + default: dir = "??"; break; + } + switch (_IOC_TYPE(cmd)) { + case 'P': + printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n", + name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ? + osspcm_ioctls[_IOC_NR(cmd)] : "???"); + break; + case 'M': + printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n", + name, cmd, dir, _IOC_NR(cmd)); + break; + default: + printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n", + name, cmd, dir, _IOC_NR(cmd)); + } +} + static int dsp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -382,7 +418,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, int val = 0; if (debug > 1) - saa7134_print_ioctl(dev->name,cmd); + saa7134_oss_print_ioctl(dev->name,cmd); switch (cmd) { case OSS_GETVERSION: return put_user(SOUND_VERSION, p); @@ -678,7 +714,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file, int __user *p = argp; if (debug > 1) - saa7134_print_ioctl(dev->name,cmd); + saa7134_oss_print_ioctl(dev->name,cmd); switch (cmd) { case OSS_GETVERSION: return put_user(SOUND_VERSION, p); diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 45c852df13ed..adfa8fe49a11 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -29,6 +29,7 @@ #include "saa7134-reg.h" #include "saa7134.h" +#include <media/v4l2-common.h> /* Include V4L1 specific functions. Should be removed soon */ #include <linux/videodev.h> @@ -1689,7 +1690,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, int err; if (video_debug > 1) - saa7134_print_ioctl(dev->name,cmd); + v4l_print_ioctl(dev->name,cmd); switch (cmd) { case VIDIOC_S_CTRL: @@ -2142,7 +2143,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, struct saa7134_dev *dev = fh->dev; if (video_debug > 1) - saa7134_print_ioctl(dev->name,cmd); + v4l_print_ioctl(dev->name,cmd); switch (cmd) { case VIDIOC_QUERYCAP: { @@ -2262,6 +2263,7 @@ static struct file_operations video_fops = .poll = video_poll, .mmap = video_mmap, .ioctl = video_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; @@ -2271,6 +2273,7 @@ static struct file_operations radio_fops = .open = video_open, .release = video_release, .ioctl = radio_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index add49db1ad41..e70eae8d29bb 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -37,6 +37,9 @@ #include <media/ir-common.h> #include <media/ir-kbd-i2c.h> #include <media/video-buf.h> +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/pcm.h> #include <media/video-buf-dvb.h> #ifndef TRUE @@ -47,10 +50,6 @@ #endif #define UNSET (-1U) -#include <sound/driver.h> -#include <sound/core.h> -#include <sound/pcm.h> - /* ----------------------------------------------------------- */ /* enums */ @@ -209,6 +208,8 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 #define SAA7134_BOARD_PHILIPS_TIGER 81 #define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82 +#define SAA7134_BOARD_CINERGY250PCI 83 +#define SAA7134_BOARD_FLYDVB_TRIO 84 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 @@ -546,7 +547,6 @@ struct saa7134_dev { extern struct list_head saa7134_devlist; -void saa7134_print_ioctl(char *name, unsigned int cmd); void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); #define SAA7134_PGTABLE_SIZE 4096 diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index d4497dbae05c..6ee54a45411f 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -1974,6 +1974,7 @@ static struct file_operations saa_fops = .open = saa_open, .release = saa_release, .ioctl = saa_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .read = saa_read, .llseek = no_llseek, .write = saa_write, diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 549c9929f107..99261f15e66e 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -50,6 +50,7 @@ #include "bttv.h" #include <media/audiochip.h> +#include <media/v4l2-common.h> #ifndef VIDEO_AUDIO_BALANCE # define VIDEO_AUDIO_BALANCE 32 @@ -90,9 +91,6 @@ struct tda7432 { static struct i2c_driver driver; static struct i2c_client client_template; -#define dprintk if (debug) printk -#define d2printk if (debug > 1) printk - /* The TDA7432 is made by STS-Thompson * http://www.st.com * http://us.st.com/stonline/books/pdf/docs/4056.pdf @@ -229,12 +227,12 @@ static struct i2c_client client_template; static int tda7432_write(struct i2c_client *client, int subaddr, int val) { unsigned char buffer[2]; - d2printk("tda7432: In tda7432_write\n"); - dprintk("tda7432: Writing %d 0x%x\n", subaddr, val); + v4l_dbg(2,client,"In tda7432_write\n"); + v4l_dbg(1,client,"Writing %d 0x%x\n", subaddr, val); buffer[0] = subaddr; buffer[1] = val; if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tda7432: I/O error, trying (write %d 0x%x)\n", + v4l_err(client,"I/O error, trying (write %d 0x%x)\n", subaddr, val); return -1; } @@ -247,9 +245,9 @@ static int tda7432_set(struct i2c_client *client) { struct tda7432 *t = i2c_get_clientdata(client); unsigned char buf[16]; - d2printk("tda7432: In tda7432_set\n"); + v4l_dbg(2,client,"In tda7432_set\n"); - dprintk(KERN_INFO + v4l_dbg(1,client, "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", t->input,t->volume,t->bass,t->treble,t->lf,t->lr,t->rf,t->rr,t->loud); buf[0] = TDA7432_IN; @@ -263,7 +261,7 @@ static int tda7432_set(struct i2c_client *client) buf[8] = t->rr; buf[9] = t->loud; if (10 != i2c_master_send(client,buf,10)) { - printk(KERN_WARNING "tda7432: I/O error, trying tda7432_set\n"); + v4l_err(client,"I/O error, trying tda7432_set\n"); return -1; } @@ -273,7 +271,7 @@ static int tda7432_set(struct i2c_client *client) static void do_tda7432_init(struct i2c_client *client) { struct tda7432 *t = i2c_get_clientdata(client); - d2printk("tda7432: In tda7432_init\n"); + v4l_dbg(2,client,"In tda7432_init\n"); t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ TDA7432_BASS_SYM | /* Symmetric bass cut */ @@ -301,7 +299,6 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind) { struct tda7432 *t; struct i2c_client *client; - d2printk("tda7432: In tda7432_attach\n"); t = kmalloc(sizeof *t,GFP_KERNEL); if (!t) @@ -315,21 +312,16 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind) i2c_set_clientdata(client, t); do_tda7432_init(client); - printk(KERN_INFO "tda7432: init\n"); - i2c_attach_client(client); + + v4l_info(client, "chip found @ 0x%x (%s)\n", addr << 1, adap->name); return 0; } static int tda7432_probe(struct i2c_adapter *adap) { -#ifdef I2C_CLASS_TV_ANALOG if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda7432_attach); -#else - if (adap->id == I2C_HW_B_BT848) - return i2c_probe(adap, &addr_data, tda7432_attach); -#endif return 0; } @@ -348,7 +340,9 @@ static int tda7432_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct tda7432 *t = i2c_get_clientdata(client); - d2printk("tda7432: In tda7432_command\n"); + v4l_dbg(2,client,"In tda7432_command\n"); + if (debug>1) + v4l_i2c_print_ioctl(client,cmd); switch (cmd) { /* --- v4l ioctls --- */ @@ -359,7 +353,6 @@ static int tda7432_command(struct i2c_client *client, case VIDIOCGAUDIO: { struct video_audio *va = arg; - dprintk("tda7432: VIDIOCGAUDIO\n"); va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_BASS | @@ -414,7 +407,6 @@ static int tda7432_command(struct i2c_client *client, case VIDIOCSAUDIO: { struct video_audio *va = arg; - dprintk("tda7432: VIDEOCSAUDIO\n"); if(va->flags & VIDEO_AUDIO_VOLUME){ if(!maxvol){ /* max +20db */ @@ -490,11 +482,6 @@ static int tda7432_command(struct i2c_client *client, } /* end of VIDEOCSAUDIO case */ - default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ - - /* nothing */ - d2printk("tda7432: Default\n"); - } /* end of (cmd) switch */ return 0; @@ -502,7 +489,7 @@ static int tda7432_command(struct i2c_client *client, static struct i2c_driver driver = { .driver = { - .name = "i2c tda7432 driver", + .name = "tda7432", }, .id = I2C_DRIVERID_TDA7432, .attach_adapter = tda7432_probe, @@ -519,7 +506,7 @@ static struct i2c_client client_template = static int __init tda7432_init(void) { if ( (loudness < 0) || (loudness > 15) ) { - printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\n"); + printk(KERN_ERR "loudness parameter must be between 0 and 15\n"); return -EINVAL; } diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 61d94ddaff41..2498b76df429 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -398,14 +398,8 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) return 0; } - /*---------------------------------------------------------------------*/ -#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) { char* mode; diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 9c3ecf7a0fed..299393bf900a 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -257,13 +257,8 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind) static int tda9875_probe(struct i2c_adapter *adap) { -#ifdef I2C_CLASS_TV_ANALOG if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda9875_attach); -#else - if (adap->id == I2C_HW_B_BT848) - return i2c_probe(adap, &addr_data, tda9875_attach); -#endif return 0; } @@ -373,7 +368,7 @@ static int tda9875_command(struct i2c_client *client, static struct i2c_driver driver = { .driver = { - .name = "i2c tda9875 driver", + .name = "tda9875", }, .id = I2C_DRIVERID_TDA9875, .attach_adapter = tda9875_probe, diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 7165a1b9625a..9cf47dc65579 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -9,7 +9,7 @@ #include <linux/slab.h> #include <linux/delay.h> -#include <media/audiochip.h> +#include <media/v4l2-common.h> #include <media/tuner.h> @@ -57,7 +57,6 @@ struct tda9887 { v4l2_std_id std; enum tuner_mode mode; unsigned int config; - unsigned int pinnacle_id; unsigned int using_v4l2; unsigned int radio_mode; unsigned char data[4]; @@ -115,6 +114,9 @@ static struct i2c_client client_template; #define cAudioGain0 0x00 // bit c7 #define cAudioGain6 0x80 // bit c7 +#define cTopMask 0x1f // bit c0:4 +#define cTopPalSecamDefault 0x14 // bit c0:4 +#define cTopNtscRadioDefault 0x10 // bit c0:4 //// third reg (e) #define cAudioIF_4_5 0x00 // bit e0:1 @@ -146,13 +148,15 @@ static struct i2c_client client_template; static struct tvnorm tvnorms[] = { { - .std = V4L2_STD_PAL_BG, - .name = "PAL-BG", + .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N, + .name = "PAL-BGHN", .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), - .e = ( cAudioIF_5_5 | + cDeemphasis50 | + cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_5_5 | cVideoIF_38_90 ), },{ .std = V4L2_STD_PAL_I, @@ -160,8 +164,10 @@ static struct tvnorm tvnorms[] = { .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), - .e = ( cAudioIF_6_0 | + cDeemphasis50 | + cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_6_0 | cVideoIF_38_90 ), },{ .std = V4L2_STD_PAL_DK, @@ -169,52 +175,80 @@ static struct tvnorm tvnorms[] = { .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), - .e = ( cAudioIF_6_5 | - cVideoIF_38_00 ), + cDeemphasis50 | + cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_6_5 | + cVideoIF_38_90 ), },{ - .std = V4L2_STD_PAL_M | V4L2_STD_PAL_N, - .name = "PAL-M/N", + .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc, + .name = "PAL-M/Nc", .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis75 ), - .e = ( cAudioIF_4_5 | + cDeemphasis75 | + cTopNtscRadioDefault), + .e = ( cGating_36 | + cAudioIF_4_5 | cVideoIF_45_75 ), },{ + .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, + .name = "SECAM-BGH", + .b = ( cPositiveAmTV | + cQSS ), + .c = ( cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_5_5 | + cVideoIF_38_90 ), + },{ .std = V4L2_STD_SECAM_L, .name = "SECAM-L", .b = ( cPositiveAmTV | cQSS ), + .c = ( cTopPalSecamDefault), .e = ( cGating_36 | cAudioIF_6_5 | cVideoIF_38_90 ), },{ + .std = V4L2_STD_SECAM_LC, + .name = "SECAM-L'", + .b = ( cOutputPort2Inactive | + cPositiveAmTV | + cQSS ), + .c = ( cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_6_5 | + cVideoIF_33_90 ), + },{ .std = V4L2_STD_SECAM_DK, .name = "SECAM-DK", .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), - .e = ( cAudioIF_6_5 | - cVideoIF_38_00 ), + cDeemphasis50 | + cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_6_5 | + cVideoIF_38_90 ), },{ .std = V4L2_STD_NTSC_M, .name = "NTSC-M", .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis75 ), + cDeemphasis75 | + cTopNtscRadioDefault), .e = ( cGating_36 | cAudioIF_4_5 | cVideoIF_45_75 ), },{ .std = V4L2_STD_NTSC_M_JP, - .name = "NTSC-JP", + .name = "NTSC-M-JP", .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), + cDeemphasis50 | + cTopNtscRadioDefault), .e = ( cGating_36 | cAudioIF_4_5 | cVideoIF_58_75 ), @@ -226,8 +260,10 @@ static struct tvnorm radio_stereo = { .b = ( cFmRadio | cQSS ), .c = ( cDeemphasisOFF | - cAudioGain6 ), - .e = ( cAudioIF_5_5 | + cAudioGain6 | + cTopNtscRadioDefault), + .e = ( cTunerGainLow | + cAudioIF_5_5 | cRadioIF_38_90 ), }; @@ -236,8 +272,10 @@ static struct tvnorm radio_mono = { .b = ( cFmRadio | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50), - .e = ( cAudioIF_5_5 | + cDeemphasis75 | + cTopNtscRadioDefault), + .e = ( cTunerGainLow | + cAudioIF_5_5 | cRadioIF_38_90 ), }; @@ -400,7 +438,8 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) static unsigned int port1 = UNSET; static unsigned int port2 = UNSET; static unsigned int qss = UNSET; -static unsigned int adjust = 0x10; +static unsigned int adjust = UNSET; + module_param(port1, int, 0644); module_param(port2, int, 0644); module_param(qss, int, 0644); @@ -428,8 +467,10 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf) buf[1] &= ~cQSS; } - if (adjust >= 0x00 && adjust < 0x20) + if (adjust >= 0x00 && adjust < 0x20) { + buf[2] &= ~cTopMask; buf[2] |= adjust; + } return 0; } @@ -465,6 +506,10 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) break; } } + if (t->config & TDA9887_TOP_SET) { + buf[2] &= ~cTopMask; + buf[2] |= (t->config >> 8) & cTopMask; + } if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) buf[1] &= ~cQSS; return 0; @@ -472,38 +517,13 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) /* ---------------------------------------------------------------------- */ -static int tda9887_set_pinnacle(struct tda9887 *t, char *buf) -{ - unsigned int bCarrierMode = UNSET; - - if (t->std & V4L2_STD_625_50) { - if ((1 == t->pinnacle_id) || (7 == t->pinnacle_id)) { - bCarrierMode = cIntercarrier; - } else { - bCarrierMode = cQSS; - } - } - if (t->std & V4L2_STD_525_60) { - if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { - bCarrierMode = cIntercarrier; - } else { - bCarrierMode = cQSS; - } - } - - if (bCarrierMode != UNSET) { - buf[1] &= ~0x04; - buf[1] |= bCarrierMode; - } - return 0; -} - -/* ---------------------------------------------------------------------- */ +static char pal[] = "--"; +static char secam[] = "--"; +static char ntsc[] = "-"; -static char pal[] = "-"; module_param_string(pal, pal, sizeof(pal), 0644); -static char secam[] = "-"; module_param_string(secam, secam, sizeof(secam), 0644); +module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); static int tda9887_fixup_std(struct tda9887 *t) { @@ -514,8 +534,17 @@ static int tda9887_fixup_std(struct tda9887 *t) case 'B': case 'g': case 'G': - tda9887_dbg("insmod fixup: PAL => PAL-BG\n"); - t->std = V4L2_STD_PAL_BG; + case 'h': + case 'H': + case 'n': + case 'N': + if (pal[1] == 'c' || pal[1] == 'C') { + tda9887_dbg("insmod fixup: PAL => PAL-Nc\n"); + t->std = V4L2_STD_PAL_Nc; + } else { + tda9887_dbg("insmod fixup: PAL => PAL-BGHN\n"); + t->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N; + } break; case 'i': case 'I': @@ -529,6 +558,11 @@ static int tda9887_fixup_std(struct tda9887 *t) tda9887_dbg("insmod fixup: PAL => PAL-DK\n"); t->std = V4L2_STD_PAL_DK; break; + case 'm': + case 'M': + tda9887_dbg("insmod fixup: PAL => PAL-M\n"); + t->std = V4L2_STD_PAL_M; + break; case '-': /* default parameter, do nothing */ break; @@ -539,6 +573,15 @@ static int tda9887_fixup_std(struct tda9887 *t) } if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { switch (secam[0]) { + case 'b': + case 'B': + case 'g': + case 'G': + case 'h': + case 'H': + tda9887_dbg("insmod fixup: SECAM => SECAM-BGH\n"); + t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; + break; case 'd': case 'D': case 'k': @@ -548,8 +591,13 @@ static int tda9887_fixup_std(struct tda9887 *t) break; case 'l': case 'L': - tda9887_dbg("insmod fixup: SECAM => SECAM-L\n"); - t->std = V4L2_STD_SECAM_L; + if (secam[1] == 'c' || secam[1] == 'C') { + tda9887_dbg("insmod fixup: SECAM => SECAM-L'\n"); + t->std = V4L2_STD_SECAM_LC; + } else { + tda9887_dbg("insmod fixup: SECAM => SECAM-L\n"); + t->std = V4L2_STD_SECAM_L; + } break; case '-': /* default parameter, do nothing */ @@ -559,6 +607,26 @@ static int tda9887_fixup_std(struct tda9887 *t) break; } } + if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) { + switch (ntsc[0]) { + case 'm': + case 'M': + tda9887_dbg("insmod fixup: NTSC => NTSC-M\n"); + t->std = V4L2_STD_NTSC_M; + break; + case 'j': + case 'J': + tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); + t->std = V4L2_STD_NTSC_M_JP; + break; + case '-': + /* default parameter, do nothing */ + break; + default: + tda9887_info("ntsc= argument not recognised\n"); + break; + } + } return 0; } @@ -581,12 +649,22 @@ static int tda9887_configure(struct tda9887 *t) memset(t->data,0,sizeof(t->data)); tda9887_set_tvnorm(t,t->data); + /* A note on the port settings: + These settings tend to depend on the specifics of the board. + By default they are set to inactive (bit value 1) by this driver, + overwriting any changes made by the tvnorm. This means that it + is the responsibility of the module using the tda9887 to set + these values in case of changes in the tvnorm. + In many cases port 2 should be made active (0) when selecting + SECAM-L, and port 2 should remain inactive (1) for SECAM-L'. + + For the other standards the tda9887 application note says that + the ports should be set to active (0), but, again, that may + differ depending on the precise hardware configuration. + */ t->data[1] |= cOutputPort1Inactive; t->data[1] |= cOutputPort2Inactive; - if (UNSET != t->pinnacle_id) { - tda9887_set_pinnacle(t,t->data); - } tda9887_set_config(t,t->data); tda9887_set_insmod(t,t->data); @@ -594,7 +672,6 @@ static int tda9887_configure(struct tda9887 *t) t->data[1] |= cForcedMuteAudioON; } - tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1],t->data[2],t->data[3]); if (debug > 1) @@ -625,7 +702,6 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) t->client = client_template; t->std = 0; - t->pinnacle_id = UNSET; t->radio_mode = V4L2_TUNER_MODE_STEREO; tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); @@ -638,18 +714,8 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) static int tda9887_probe(struct i2c_adapter *adap) { -#ifdef I2C_CLASS_TV_ANALOG if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda9887_attach); -#else - switch (adap->id) { - case I2C_HW_B_BT848: - case I2C_HW_B_RIVA: - case I2C_HW_SAA7134: - return i2c_probe(adap, &addr_data, tda9887_attach); - break; - } -#endif return 0; } @@ -689,14 +755,6 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) tda9887_configure(t); break; } - case AUDC_CONFIG_PINNACLE: - { - int *i = arg; - - t->pinnacle_id = *i; - tda9887_configure(t); - break; - } case TDA9887_SET_CONFIG: { int *i = arg; @@ -787,7 +845,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) } case VIDIOC_LOG_STATUS: { - tda9887_info("Data bytes: b=%02x c=%02x e=%02x\n", t->data[1], t->data[2], t->data[3]); + tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1], t->data[2], t->data[3]); break; } default: @@ -824,7 +882,7 @@ static struct i2c_driver driver = { .detach_client = tda9887_detach, .command = tda9887_command, .driver = { - .name = "i2c tda9887 driver", + .name = "tda9887", .suspend = tda9887_suspend, .resume = tda9887_resume, }, diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index a9375ef05de1..261b7a3c0417 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -17,6 +17,9 @@ #define PREFIX "TEA5767 " +/* from tuner-core.c */ +extern int debug; + /*****************************************************************************/ /****************************** @@ -246,7 +249,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq) if (5 != (rc = i2c_master_send(c, buffer, 5))) tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); - if (tuner_debug) { + if (debug) { if (5 != (rc = i2c_master_recv(c, buffer, 5))) tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); else @@ -264,7 +267,7 @@ static int tea5767_signal(struct i2c_client *c) if (5 != (rc = i2c_master_recv(c, buffer, 5))) tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); - return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << (13 - 4)); + return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8); } static int tea5767_stereo(struct i2c_client *c) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index c13c7b95ef35..57bc585a6955 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -20,10 +20,9 @@ #include <linux/init.h> #include <media/tuner.h> +#include <media/v4l2-common.h> #include <media/audiochip.h> -#include "msp3400.h" - #define UNSET (-1U) /* standard i2c insmod options */ @@ -38,21 +37,30 @@ I2C_CLIENT_INSMOD; /* insmod options used at init time => read/only */ static unsigned int addr = 0; -module_param(addr, int, 0444); - static unsigned int no_autodetect = 0; -module_param(no_autodetect, int, 0444); - static unsigned int show_i2c = 0; -module_param(show_i2c, int, 0444); /* insmod options used at runtime => read/write */ -unsigned int tuner_debug = 0; -module_param(tuner_debug, int, 0644); +static unsigned int tuner_debug = 0; +int debug = 0; static unsigned int tv_range[2] = { 44, 958 }; static unsigned int radio_range[2] = { 65, 108 }; +static char pal[] = "--"; +static char secam[] = "--"; +static char ntsc[] = "-"; + +module_param(addr, int, 0444); +module_param(no_autodetect, int, 0444); +module_param(show_i2c, int, 0444); +/* Note: tuner_debug is deprecated and will be removed in 2.6.17 */ +module_param(tuner_debug, int, 0444); +module_param(debug, int, 0644); + +module_param_string(pal, pal, sizeof(pal), 0644); +module_param_string(secam, secam, sizeof(secam), 0644); +module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); module_param_array(tv_range, int, NULL, 0644); module_param_array(radio_range, int, NULL, 0644); @@ -249,11 +257,6 @@ static inline int check_mode(struct tuner *t, char *cmd) return 0; } -static char pal[] = "-"; -module_param_string(pal, pal, sizeof(pal), 0644); -static char secam[] = "--"; -module_param_string(secam, secam, sizeof(secam), 0644); - /* get more precise norm info from insmod option */ static int tuner_fixup_std(struct tuner *t) { @@ -285,8 +288,13 @@ static int tuner_fixup_std(struct tuner *t) break; case 'N': case 'n': - tuner_dbg ("insmod fixup: PAL => PAL-N\n"); - t->std = V4L2_STD_PAL_N; + if (pal[1] == 'c' || pal[1] == 'C') { + tuner_dbg("insmod fixup: PAL => PAL-Nc\n"); + t->std = V4L2_STD_PAL_Nc; + } else { + tuner_dbg ("insmod fixup: PAL => PAL-N\n"); + t->std = V4L2_STD_PAL_N; + } break; case '-': /* default parameter, do nothing */ @@ -298,6 +306,15 @@ static int tuner_fixup_std(struct tuner *t) } if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { switch (secam[0]) { + case 'b': + case 'B': + case 'g': + case 'G': + case 'h': + case 'H': + tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n"); + t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; + break; case 'd': case 'D': case 'k': @@ -324,9 +341,60 @@ static int tuner_fixup_std(struct tuner *t) } } + if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) { + switch (ntsc[0]) { + case 'm': + case 'M': + tuner_dbg("insmod fixup: NTSC => NTSC-M\n"); + t->std = V4L2_STD_NTSC_M; + break; + case 'j': + case 'J': + tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); + t->std = V4L2_STD_NTSC_M_JP; + break; + case '-': + /* default parameter, do nothing */ + break; + default: + tuner_info("ntsc= argument not recognised\n"); + break; + } + } return 0; } +static void tuner_status(struct i2c_client *client) +{ + struct tuner *t = i2c_get_clientdata(client); + unsigned long freq, freq_fraction; + const char *p; + + switch (t->mode) { + case V4L2_TUNER_RADIO: p = "radio"; break; + case V4L2_TUNER_ANALOG_TV: p = "analog TV"; break; + case V4L2_TUNER_DIGITAL_TV: p = "digital TV"; break; + default: p = "undefined"; break; + } + if (t->mode == V4L2_TUNER_RADIO) { + freq = t->freq / 16000; + freq_fraction = (t->freq % 16000) * 100 / 16000; + } else { + freq = t->freq / 16; + freq_fraction = (t->freq % 16) * 100 / 16; + } + tuner_info("Tuner mode: %s\n", p); + tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); + tuner_info("Standard: 0x%08llx\n", t->std); + if (t->mode == V4L2_TUNER_RADIO) { + if (t->has_signal) { + tuner_info("Signal strength: %d\n", t->has_signal(client)); + } + if (t->is_stereo) { + tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no"); + } + } +} /* ---------------------------------------------------------------------- */ /* static var Used only in tuner_attach and tuner_probe */ @@ -352,6 +420,11 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; + if (tuner_debug) { + debug = tuner_debug; + printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n"); + printk(KERN_ERR "tuner: use the debug option instead.\n"); + } if (show_i2c) { unsigned char buffer[16]; @@ -478,7 +551,9 @@ static inline int check_v4l2(struct tuner *t) 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; + + if (debug>1) + v4l_i2c_print_ioctl(&(t->i2c),cmd); switch (cmd) { /* --- configuration --- */ @@ -501,18 +576,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) t->standby (client); 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; case VIDIOCSAUDIO: if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) return 0; @@ -523,9 +586,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) tuner_dbg("VIDIOCSAUDIO not implemented.\n"); break; - case MSP_SET_MATRIX: - case TDA9887_SET_CONFIG: - break; /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ @@ -708,10 +768,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) } break; } - default: - tuner_dbg("Unimplemented IOCTL 0x%08x(dir=%d,tp='%c',nr=%d,sz=%d)\n", - cmd, _IOC_DIR(cmd), _IOC_TYPE(cmd), - _IOC_NR(cmd), _IOC_SIZE(cmd)); + case VIDIOC_LOG_STATUS: + tuner_status(client); break; } @@ -747,10 +805,10 @@ static struct i2c_driver driver = { .detach_client = tuner_detach, .command = tuner_command, .driver = { - .name = "tuner", - .suspend = tuner_suspend, - .resume = tuner_resume, - }, + .name = "tuner", + .suspend = tuner_suspend, + .resume = tuner_resume, + }, }; static struct i2c_client client_template = { .name = "(tuner unset)", diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index e0c9fdb9914a..e5fb74365836 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -8,6 +8,10 @@ #include <linux/videodev.h> #include <media/tuner.h> +static int offset = 0; +module_param(offset, int, 0666); +MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); + /* ---------------------------------------------------------------------- */ /* tv standard selection for Temic 4046 FM5 @@ -75,24 +79,20 @@ #define TUNER_PLL_LOCKED 0x40 #define TUNER_STEREO_MK3 0x04 +#define TUNER_MAX_RANGES 3 + /* ---------------------------------------------------------------------- */ 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; + + int count; + struct { + unsigned short thresh; + unsigned char cb; + } ranges[TUNER_MAX_RANGES]; 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 */ }; /* @@ -102,158 +102,696 @@ struct tunertype */ static struct tunertype tuners[] = { /* 0-9 */ - { "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}, + [TUNER_TEMIC_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL (4002 FH5)", + .count = 3, + .ranges = { + { 16 * 140.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */ + .name = "Philips PAL_I (FI1246 and compatibles)", + .count = 3, + .ranges = { + { 16 * 140.25 /*MHz*/, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */ + .name = "Philips NTSC (FI1236,FM1236 and compatibles)", + .count = 3, + .ranges = { + { 16 * 157.25 /*MHz*/, 0xa0, }, + { 16 * 451.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */ + .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", + .count = 3, + .ranges = { + { 16 * 168.25 /*MHz*/, 0xa7, }, + { 16 * 447.25 /*MHz*/, 0x97, }, + { 16 * 999.99 , 0x37, }, + }, + .config = 0x8e, + }, + [TUNER_ABSENT] = { /* Tuner Absent */ + .name = "NoTuner", + .count = 1, + .ranges = { + { 0, 0x00, }, + }, + .config = 0x00, + }, + [TUNER_PHILIPS_PAL] = { /* Philips PAL */ + .name = "Philips PAL_BG (FI1216 and compatibles)", + .count = 3, + .ranges = { + { 16 * 168.25 /*MHz*/, 0xa0, }, + { 16 * 447.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4032 FY5)", + .count = 3, + .ranges = { + { 16 * 157.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */ + .name = "Temic PAL_I (4062 FY5)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0x02, }, + { 16 * 450.00 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4036 FY5)", + .count = 3, + .ranges = { + { 16 * 157.25 /*MHz*/, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */ + .name = "Alps HSBH1", + .count = 3, + .ranges = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 385.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, /* 10-19 */ - { "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}, + [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */ + .name = "Alps TSBE1", + .count = 3, + .ranges = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 385.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */ + .name = "Alps TSBB5", + .count = 3, + .ranges = { + { 16 * 133.25 /*MHz*/, 0x01, }, + { 16 * 351.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */ + .name = "Alps TSBE5", + .count = 3, + .ranges = { + { 16 * 133.25 /*MHz*/, 0x01, }, + { 16 * 351.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */ + .name = "Alps TSBC5", + .count = 3, + .ranges = { + { 16 * 133.25 /*MHz*/, 0x01, }, + { 16 * 351.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL_BG (4006FH5)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */ + .name = "Alps TSCH6", + .count = 3, + .ranges = { + { 16 * 137.25 /*MHz*/, 0x14, }, + { 16 * 385.25 /*MHz*/, 0x12, }, + { 16 * 999.99 , 0x11, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */ + .name = "Temic PAL_DK (4016 FY5)", + .count = 3, + .ranges = { + { 16 * 168.25 /*MHz*/, 0xa0, }, + { 16 * 456.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */ + .name = "Philips NTSC_M (MK2)", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */ + .name = "Temic PAL_I (4066 FY5)", + .count = 3, + .ranges = { + { 16 * 169.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL* auto (4006 FN5)", + .count = 3, + .ranges = { + { 16 * 169.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, /* 20-29 */ - { "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}, + [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", + .count = 3, + .ranges = { + { 16 * 141.00 /*MHz*/, 0xa0, }, + { 16 * 464.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4039 FR5)", + .count = 3, + .ranges = { + { 16 * 158.00 /*MHz*/, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */ + .name = "Temic PAL/SECAM multi (4046 FM5)", + .count = 3, + .ranges = { + { 16 * 169.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */ + .name = "Philips PAL_DK (FI1256 and compatibles)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FQ1216ME)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */ + .name = "LG PAL_I+FM (TAPC-I001D)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */ + .name = "LG PAL_I (TAPC-I701D)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC+FM (TPI8NSR01F)", + .count = 3, + .ranges = { + { 16 * 210.00 /*MHz*/, 0xa0, }, + { 16 * 497.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */ + .name = "LG PAL_BG+FM (TPI8PSB01D)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_LG_PAL] = { /* LGINNOTEK PAL */ + .name = "LG PAL_BG (TPI8PSB11D)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, /* 30-39 */ - { "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, + [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */ + .name = "Temic PAL* auto + FM (4009 FN5)", + .count = 3, + .ranges = { + { 16 * 141.00 /*MHz*/, 0xa0, }, + { 16 * 464.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */ + .name = "SHARP NTSC_JP (2U5JF5540)", + .count = 3, + .ranges = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 317.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */ + .name = "Samsung PAL TCPM9091PD27", + .count = 3, + .ranges = { + { 16 * 169 /*MHz*/, 0xa0, }, + { 16 * 464 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_MT2032] = { /* Microtune PAL|NTSC */ + .name = "MT20xx universal", /* 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*158.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}, + [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */ + .name = "Temic PAL_BG (4106 FH5)", + .count = 3, + .ranges = { + { 16 * 141.00 /*MHz*/, 0xa0, }, + { 16 * 464.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */ + .name = "Temic PAL_DK/SECAM_L (4012 FY5)", + .count = 3, + .ranges = { + { 16 * 140.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, + }, + .config = 0x8e, + }, + [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4136 FY5)", + .count = 3, + .ranges = { + { 16 * 158.00 /*MHz*/, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */ + .name = "LG PAL (newer TAPC series)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FM1216ME MK3)", + .count = 3, + .ranges = { + { 16 * 158.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, + [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC (newer TAPC series)", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, /* 40-49 */ - { "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}, + [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */ + .name = "HITACHI V7-J180AT", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */ + .name = "Philips PAL_MK (FI1216 MK)", + .count = 3, + .ranges = { + { 16 * 140.25 /*MHz*/, 0x01, }, + { 16 * 463.25 /*MHz*/, 0xc2, }, + { 16 * 999.99 , 0xcf, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */ + .name = "Philips 1236D ATSC/NTSC dual in", + .count = 3, + .ranges = { + { 16 * 157.25 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */ + .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */ + .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, + [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */ + .name = "Microtune 4049 FM5", + .count = 3, + .ranges = { + { 16 * 141.00 /*MHz*/, 0xa0, }, + { 16 * 464.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */ + .name = "Panasonic VP27s/ENGE4324D", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0xce, + }, + [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC (TAPE series)", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, + [TUNER_TNF_8831BGFF] = { /* Philips PAL */ + .name = "Tenna TNF 8831 BGFF)", + .count = 3, + .ranges = { + { 16 * 161.25 /*MHz*/, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */ + .name = "Microtune 4042 FI5 ATSC/NTSC dual in", + .count = 3, + .ranges = { + { 16 * 162.00 /*MHz*/, 0xa2, }, + { 16 * 457.00 /*MHz*/, 0x94, }, + { 16 * 999.99 , 0x31, }, + }, + .config = 0x8e, + }, /* 50-59 */ - { "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, + [TUNER_TCL_2002N] = { /* TCL NTSC */ + .name = "TCL 2002N", + .count = 3, + .ranges = { + { 16 * 172.00 /*MHz*/, 0x01, }, + { 16 * 448.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */ + .name = "Philips PAL/SECAM_D (FM 1256 I-H3)", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, + [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */ + .name = "Thomson DTT 7610 (ATSC/NTSC)", + .count = 3, + .ranges = { + { 16 * 157.25 /*MHz*/, 0x39, }, + { 16 * 454.00 /*MHz*/, 0x3a, }, + { 16 * 999.99 , 0x3c, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */ + .name = "Philips FQ1286", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x41, }, + { 16 * 454.00 /*MHz*/, 0x42, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */ + .name = "tda8290+75", /* see tda8290.c for details */ }, - { "TCL 2002MB", TCL, 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 }, - { "Ymec TVision TVF-8531MF/8831MF/8731MF", Philips, NTSC, - 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, - { "Ymec TVision TVF-5533MF", Philips, NTSC, - 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, + [TUNER_TCL_2002MB] = { /* TCL PAL */ + .name = "TCL 2002MB", + .count = 3, + .ranges = { + { 16 * 170.00 /*MHz*/, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0xce, + }, + [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FQ1216AME MK4)", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0xce, + }, + [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */ + .name = "Philips FQ1236A MK4", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, + [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */ + .name = "Ymec TVision TVF-8531MF/8831MF/8731MF", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, + }, + .config = 0x8e, + }, + [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */ + .name = "Ymec TVision TVF-5533MF", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, /* 60-69 */ - { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, - 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, - { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, - 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623}, - { "Philips TEA5767HN FM Radio", Philips, RADIO, + [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */ + /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ + .name = "Thomson DTT 761X (ATSC/NTSC)", + .count = 3, + .ranges = { + { 16 * 145.25 /*MHz*/, 0x39, }, + { 16 * 415.25 /*MHz*/, 0x3a, }, + { 16 * 999.99 , 0x3c, }, + }, + .config = 0x8e, + }, + [TUNER_TENA_9533_DI] = { /* Philips PAL */ + .name = "Tena TNF9533-D/IF/TNF9533-B/DF", + .count = 3, + .ranges = { + { 16 * 160.25 /*MHz*/, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, + [TUNER_TEA5767] = { /* Philips RADIO */ + .name = "Philips TEA5767HN FM Radio", /* see tea5767.c for details */}, - { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL, - 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 }, - { "LG TDVS-H062F/TUA6034", LGINNOTEK, ATSC, - 16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732}, - { "Ymec TVF66T5-B/DFF", Philips, PAL, - 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, - { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC, - 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 }, - { "Philips TD1316 Hybrid Tuner", Philips, PAL, - 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, - { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, - 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 }, - { "Tena TNF 5335 MF", Philips, NTSC, - 16*157.25,16*454.00,0x01,0x02,0x04,0x8e,732 }, + [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */ + .name = "Philips FMD1216ME MK3 Hybrid Tuner", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x51, }, + { 16 * 442.00 /*MHz*/, 0x52, }, + { 16 * 999.99 , 0x54, }, + }, + .config = 0x86, + }, + [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */ + .name = "LG TDVS-H062F/TUA6034", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0x01 }, + { 16 * 455.00 /*MHz*/, 0x02 }, + { 16 * 999.99 , 0x04 }, + }, + .config = 0x8e, + }, + [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ + .name = "Ymec TVF66T5-B/DFF", + .count = 3, + .ranges = { + { 16 * 160.25 /*MHz*/, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC (TALN mini series)", + .count = 3, + .ranges = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 373.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, + }, + .config = 0x8e, + }, + [TUNER_PHILIPS_TD1316] = { /* Philips PAL */ + .name = "Philips TD1316 Hybrid Tuner", + .count = 3, + .ranges = { + { 16 * 160.00 /*MHz*/, 0xa1, }, + { 16 * 442.00 /*MHz*/, 0xa2, }, + { 16 * 999.99 , 0xa4, }, + }, + .config = 0xc8, + }, + [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */ + .name = "Philips TUV1236D ATSC/NTSC dual in", + .count = 3, + .ranges = { + { 16 * 157.25 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0xce, + }, + [TUNER_TNF_5335MF] = { /* Philips NTSC */ + .name = "Tena TNF 5335 MF", + .count = 3, + .ranges = { + { 16 * 157.25 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, + }, + .config = 0x8e, + }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); @@ -305,20 +843,19 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) u16 div; struct tunertype *tun; unsigned char buffer[4]; - int rc; + int rc, IFPCoff, i; 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"); + for (i = 0; i < tun->count; i++) { + if (freq > tun->ranges[i].thresh) + continue; + break; } - + config = tun->ranges[i].cb; + /* i == 0 -> VHF_LO */ + /* i == 1 -> VHF_HI */ + /* i == 2 -> UHF */ + tuner_dbg("tv: range %d\n",i); /* tv norm specific stuff for multi-norm tuners */ switch (t->type) { @@ -420,7 +957,37 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) * frequency in case (wanted frequency < current frequency). */ - div=freq + tun->IFPCoff; + /* IFPCoff = Video Intermediate Frequency - Vif: + 940 =16*58.75 NTSC/J (Japan) + 732 =16*45.75 M/N STD + 704 =16*44 ATSC (at DVB code) + 632 =16*39.50 I U.K. + 622.4=16*38.90 B/G D/K I, L STD + 592 =16*37.00 D China + 590 =16.36.875 B Australia + 543.2=16*33.95 L' STD + 171.2=16*10.70 FM Radio (at set_radio_freq) + */ + + if (t->std == V4L2_STD_NTSC_M_JP) { + IFPCoff = 940; + } else if ((t->std & V4L2_STD_MN) && + !(t->std & ~V4L2_STD_MN)) { + IFPCoff = 732; + } else if (t->std == V4L2_STD_SECAM_LC) { + IFPCoff = 543; + } else { + IFPCoff = 623; + } + + div=freq + IFPCoff + offset; + + tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", + freq / 16, freq % 16 * 100 / 16, + IFPCoff / 16, IFPCoff % 16 * 100 / 16, + offset / 16, offset % 16 * 100 / 16, + div); + if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) { buffer[0] = tun->config; buffer[1] = config; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 0292c5abf14a..b582943a0d3e 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -31,6 +31,7 @@ #include <linux/smp_lock.h> #include <media/audiochip.h> +#include <media/v4l2-common.h> #include "tvaudio.h" @@ -46,17 +47,6 @@ MODULE_LICENSE("GPL"); #define UNSET (-1U) -#define tvaudio_info(fmt, arg...) do {\ - printk(KERN_INFO "tvaudio %d-%04x: " fmt, \ - chip->c.adapter->nr, chip->c.addr , ##arg); } while (0) -#define tvaudio_warn(fmt, arg...) do {\ - printk(KERN_WARNING "tvaudio %d-%04x: " fmt, \ - chip->c.adapter->nr, chip->c.addr , ##arg); } while (0) -#define tvaudio_dbg(fmt, arg...) do {\ - if (debug) \ - printk(KERN_INFO "tvaudio %d-%04x: " fmt, \ - chip->c.adapter->nr, chip->c.addr , ##arg); } while (0) - /* ---------------------------------------------------------------------- */ /* our structs */ @@ -131,7 +121,7 @@ struct CHIPSTATE { /* current settings */ __u16 left,right,treble,bass,mode; int prevmode; - int norm; + int radio; /* thread */ pid_t tpid; @@ -142,8 +132,6 @@ struct CHIPSTATE { int watch_stereo; }; -#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */ - /* ---------------------------------------------------------------------- */ /* i2c addresses */ @@ -171,23 +159,23 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) unsigned char buffer[2]; if (-1 == subaddr) { - tvaudio_dbg("%s: chip_write: 0x%x\n", + v4l_dbg(1, &chip->c, "%s: chip_write: 0x%x\n", chip->c.name, val); chip->shadow.bytes[1] = val; buffer[0] = val; if (1 != i2c_master_send(&chip->c,buffer,1)) { - tvaudio_warn("%s: I/O error (write 0x%x)\n", + v4l_warn(&chip->c, "%s: I/O error (write 0x%x)\n", chip->c.name, val); return -1; } } else { - tvaudio_dbg("%s: chip_write: reg%d=0x%x\n", + v4l_dbg(1, &chip->c, "%s: chip_write: reg%d=0x%x\n", chip->c.name, subaddr, val); chip->shadow.bytes[subaddr+1] = val; buffer[0] = subaddr; buffer[1] = val; if (2 != i2c_master_send(&chip->c,buffer,2)) { - tvaudio_warn("%s: I/O error (write reg%d=0x%x)\n", + v4l_warn(&chip->c, "%s: I/O error (write reg%d=0x%x)\n", chip->c.name, subaddr, val); return -1; } @@ -212,11 +200,11 @@ static int chip_read(struct CHIPSTATE *chip) unsigned char buffer; if (1 != i2c_master_recv(&chip->c,&buffer,1)) { - tvaudio_warn("%s: I/O error (read)\n", + v4l_warn(&chip->c, "%s: I/O error (read)\n", chip->c.name); return -1; } - tvaudio_dbg("%s: chip_read: 0x%x\n",chip->c.name, buffer); + v4l_dbg(1, &chip->c, "%s: chip_read: 0x%x\n",chip->c.name, buffer); return buffer; } @@ -231,10 +219,10 @@ static int chip_read2(struct CHIPSTATE *chip, int subaddr) write[0] = subaddr; if (2 != i2c_transfer(chip->c.adapter,msgs,2)) { - tvaudio_warn("%s: I/O error (read2)\n", chip->c.name); + v4l_warn(&chip->c, "%s: I/O error (read2)\n", chip->c.name); return -1; } - tvaudio_dbg("%s: chip_read2: reg%d=0x%x\n", + v4l_dbg(1, &chip->c, "%s: chip_read2: reg%d=0x%x\n", chip->c.name, subaddr,read[0]); return read[0]; } @@ -247,7 +235,7 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) return 0; /* update our shadow register set; print bytes if (debug > 0) */ - tvaudio_dbg("%s: chip_cmd(%s): reg=%d, data:", + v4l_dbg(1, &chip->c, "%s: chip_cmd(%s): reg=%d, data:", chip->c.name, name,cmd->bytes[0]); for (i = 1; i < cmd->count; i++) { if (debug) @@ -259,7 +247,7 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) /* send data to the chip */ if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) { - tvaudio_warn("%s: I/O error (%s)\n", chip->c.name, name); + v4l_warn(&chip->c, "%s: I/O error (%s)\n", chip->c.name, name); return -1; } return 0; @@ -286,7 +274,7 @@ static int chip_thread(void *data) daemonize("%s", chip->c.name); allow_signal(SIGTERM); - tvaudio_dbg("%s: thread started\n", chip->c.name); + v4l_dbg(1, &chip->c, "%s: thread started\n", chip->c.name); for (;;) { add_wait_queue(&chip->wq, &wait); @@ -298,10 +286,10 @@ static int chip_thread(void *data) try_to_freeze(); if (chip->done || signal_pending(current)) break; - tvaudio_dbg("%s: thread wakeup\n", chip->c.name); + v4l_dbg(1, &chip->c, "%s: thread wakeup\n", chip->c.name); /* don't do anything for radio or if mode != auto */ - if (chip->norm == VIDEO_MODE_RADIO || chip->mode != 0) + if (chip->radio || chip->mode != 0) continue; /* have a look what's going on */ @@ -311,7 +299,7 @@ static int chip_thread(void *data) mod_timer(&chip->wt, jiffies+2*HZ); } - tvaudio_dbg("%s: thread exiting\n", chip->c.name); + v4l_dbg(1, &chip->c, "%s: thread exiting\n", chip->c.name); complete_and_exit(&chip->texit, 0); return 0; } @@ -324,7 +312,7 @@ static void generic_checkmode(struct CHIPSTATE *chip) if (mode == chip->prevmode) return; - tvaudio_dbg("%s: thread checkmode\n", chip->c.name); + v4l_dbg(1, &chip->c, "%s: thread checkmode\n", chip->c.name); chip->prevmode = mode; if (mode & VIDEO_SOUND_STEREO) @@ -371,7 +359,7 @@ static int tda9840_getmode(struct CHIPSTATE *chip) if (val & TDA9840_ST_STEREO) mode |= VIDEO_SOUND_STEREO; - tvaudio_dbg ("tda9840_getmode(): raw chip read: %d, return: %d\n", + v4l_dbg(1, &chip->c, "tda9840_getmode(): raw chip read: %d, return: %d\n", val, mode); return mode; } @@ -667,7 +655,7 @@ static int tda9873_getmode(struct CHIPSTATE *chip) mode |= VIDEO_SOUND_STEREO; if (val & TDA9873_DUAL) mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - tvaudio_dbg ("tda9873_getmode(): raw chip read: %d, return: %d\n", + v4l_dbg(1, &chip->c, "tda9873_getmode(): raw chip read: %d, return: %d\n", val, mode); return mode; } @@ -678,12 +666,12 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode) /* int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */ if ((sw_data & TDA9873_INP_MASK) != TDA9873_INTERNAL) { - tvaudio_dbg("tda9873_setmode(): external input\n"); + v4l_dbg(1, &chip->c, "tda9873_setmode(): external input\n"); return; } - tvaudio_dbg("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]); - tvaudio_dbg("tda9873_setmode(): sw_data = %d\n", sw_data); + v4l_dbg(1, &chip->c, "tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]); + v4l_dbg(1, &chip->c, "tda9873_setmode(): sw_data = %d\n", sw_data); switch (mode) { case VIDEO_SOUND_MONO: @@ -704,7 +692,7 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode) } chip_write(chip, TDA9873_SW, sw_data); - tvaudio_dbg("tda9873_setmode(): req. mode %d; chip_write: %d\n", + v4l_dbg(1, &chip->c, "tda9873_setmode(): req. mode %d; chip_write: %d\n", mode, sw_data); } @@ -843,7 +831,7 @@ static int tda9874a_setup(struct CHIPSTATE *chip) chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80); chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */ } - tvaudio_dbg("tda9874a_setup(): %s [0x%02X].\n", + v4l_dbg(1, &chip->c, "tda9874a_setup(): %s [0x%02X].\n", tda9874a_modelist[tda9874a_STD].name,tda9874a_STD); return 1; } @@ -886,7 +874,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip) mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; } - tvaudio_dbg("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n", + v4l_dbg(1, &chip->c, "tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n", dsr, nsr, necr, mode); return mode; } @@ -932,7 +920,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) chip_write(chip, TDA9874A_AOSR, aosr); chip_write(chip, TDA9874A_MDACOSR, mdacosr); - tvaudio_dbg("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n", + v4l_dbg(1, &chip->c, "tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n", mode, aosr, mdacosr); } else { /* dic == 0x07 */ @@ -967,7 +955,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode) chip_write(chip, TDA9874A_FMMR, fmmr); chip_write(chip, TDA9874A_AOSR, aosr); - tvaudio_dbg("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n", + v4l_dbg(1, &chip->c, "tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n", mode, fmmr, aosr); } } @@ -981,10 +969,10 @@ static int tda9874a_checkit(struct CHIPSTATE *chip) if(-1 == (sic = chip_read2(chip,TDA9874A_SIC))) return 0; - tvaudio_dbg("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic); + v4l_dbg(1, &chip->c, "tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic); if((dic == 0x11)||(dic == 0x07)) { - tvaudio_info("found tda9874%s.\n", (dic == 0x11) ? "a":"h"); + v4l_info(&chip->c, "found tda9874%s.\n", (dic == 0x11) ? "a":"h"); tda9874a_dic = dic; /* remember device id. */ return 1; } @@ -1196,7 +1184,7 @@ static int ta8874z_getmode(struct CHIPSTATE *chip) }else if (!(val & TA8874Z_B0)){ mode |= VIDEO_SOUND_STEREO; } - /* tvaudio_dbg ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */ + /* v4l_dbg(1, &chip->c, "ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */ return mode; } @@ -1209,7 +1197,7 @@ static void ta8874z_setmode(struct CHIPSTATE *chip, int mode) { int update = 1; audiocmd *t = NULL; - tvaudio_dbg("ta8874z_setmode(): mode: 0x%02x\n", mode); + v4l_dbg(1, &chip->c, "ta8874z_setmode(): mode: 0x%02x\n", mode); switch(mode){ case VIDEO_SOUND_MONO: @@ -1490,7 +1478,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) i2c_set_clientdata(&chip->c, chip); /* find description for the chip */ - tvaudio_dbg("chip found @ 0x%x\n", addr<<1); + v4l_dbg(1, &chip->c, "chip found @ 0x%x\n", addr<<1); for (desc = chiplist; desc->name != NULL; desc++) { if (0 == *(desc->insmodopt)) continue; @@ -1502,12 +1490,12 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) break; } if (desc->name == NULL) { - tvaudio_dbg("no matching chip description found\n"); + v4l_dbg(1, &chip->c, "no matching chip description found\n"); return -EIO; } - tvaudio_info("%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name); + v4l_info(&chip->c, "%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name); if (desc->flags) { - tvaudio_dbg("matches:%s%s%s.\n", + v4l_dbg(1, &chip->c, "matches:%s%s%s.\n", (desc->flags & CHIP_HAS_VOLUME) ? " volume" : "", (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "", (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : ""); @@ -1550,7 +1538,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) init_completion(&chip->texit); chip->tpid = kernel_thread(chip_thread,(void *)chip,0); if (chip->tpid < 0) - tvaudio_warn("%s: kernel_thread() failed\n", + v4l_warn(&chip->c, "%s: kernel_thread() failed\n", chip->c.name); wake_up_interruptible(&chip->wq); } @@ -1563,17 +1551,8 @@ static int chip_probe(struct i2c_adapter *adap) because dedicated drivers are used */ if ((adap->id == I2C_HW_SAA7146)) return 0; -#ifdef I2C_CLASS_TV_ANALOG if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, chip_attach); -#else - switch (adap->id) { - case I2C_HW_B_BT848: - case I2C_HW_B_RIVA: - case I2C_HW_SAA7134: - return i2c_probe(adap, &addr_data, chip_attach); - } -#endif return 0; } @@ -1604,7 +1583,7 @@ static int chip_command(struct i2c_client *client, struct CHIPSTATE *chip = i2c_get_clientdata(client); struct CHIPDESC *desc = chiplist + chip->type; - tvaudio_dbg("%s: chip_command 0x%x\n", chip->c.name, cmd); + v4l_dbg(1, &chip->c, "%s: chip_command 0x%x\n", chip->c.name, cmd); switch (cmd) { case AUDC_SET_INPUT: @@ -1617,7 +1596,7 @@ static int chip_command(struct i2c_client *client, break; case AUDC_SET_RADIO: - chip->norm = VIDEO_MODE_RADIO; + chip->radio = 1; chip->watch_stereo = 0; /* del_timer(&chip->wt); */ break; @@ -1643,7 +1622,7 @@ static int chip_command(struct i2c_client *client, va->bass = chip->bass; va->treble = chip->treble; } - if (chip->norm != VIDEO_MODE_RADIO) { + if (!chip->radio) { if (desc->getmode) va->mode = desc->getmode(chip); else @@ -1678,15 +1657,80 @@ static int chip_command(struct i2c_client *client, } break; } - case VIDIOCSCHAN: + + case VIDIOC_S_TUNER: { - struct video_channel *vc = arg; + struct v4l2_tuner *vt = arg; + int mode = 0; - chip->norm = vc->norm; + switch (vt->audmode) { + case V4L2_TUNER_MODE_MONO: + mode = VIDEO_SOUND_MONO; + break; + case V4L2_TUNER_MODE_STEREO: + mode = VIDEO_SOUND_STEREO; + break; + case V4L2_TUNER_MODE_LANG1: + mode = VIDEO_SOUND_LANG1; + break; + case V4L2_TUNER_MODE_LANG2: + mode = VIDEO_SOUND_LANG2; + break; + default: + break; + } + + if (desc->setmode && mode) { + chip->watch_stereo = 0; + /* del_timer(&chip->wt); */ + chip->mode = mode; + desc->setmode(chip, mode); + } break; } - case VIDIOCSFREQ: + + case VIDIOC_G_TUNER: { + struct v4l2_tuner *vt = arg; + int mode = VIDEO_SOUND_MONO; + + if (chip->radio) + break; + vt->audmode = 0; + vt->rxsubchans = 0; + vt->capability = V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; + + if (desc->getmode) + mode = desc->getmode(chip); + + if (mode & VIDEO_SOUND_MONO) + vt->rxsubchans |= V4L2_TUNER_SUB_MONO; + if (mode & VIDEO_SOUND_STEREO) + vt->rxsubchans |= V4L2_TUNER_SUB_STEREO; + if (mode & VIDEO_SOUND_LANG1) + vt->rxsubchans |= V4L2_TUNER_SUB_LANG1 | + V4L2_TUNER_SUB_LANG2; + + mode = chip->mode; + if (mode & VIDEO_SOUND_MONO) + vt->audmode = V4L2_TUNER_MODE_MONO; + if (mode & VIDEO_SOUND_STEREO) + vt->audmode = V4L2_TUNER_MODE_STEREO; + if (mode & VIDEO_SOUND_LANG1) + vt->audmode = V4L2_TUNER_MODE_LANG1; + if (mode & VIDEO_SOUND_LANG2) + vt->audmode = V4L2_TUNER_MODE_LANG2; + break; + } + + case VIDIOCSCHAN: + case VIDIOC_S_STD: + chip->radio = 0; + break; + + case VIDIOCSFREQ: + case VIDIOC_S_FREQUENCY: chip->mode = 0; /* automatic */ if (desc->checkmode) { desc->setmode(chip,VIDEO_SOUND_MONO); @@ -1695,15 +1739,14 @@ static int chip_command(struct i2c_client *client, mod_timer(&chip->wt, jiffies+2*HZ); /* the thread will call checkmode() later */ } - } + break; } return 0; } - static struct i2c_driver driver = { .driver = { - .name = "generic i2c audio driver", + .name = "tvaudio", }, .id = I2C_DRIVERID_TVAUDIO, .attach_adapter = chip_probe, diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 8ac4cb82a459..fd0acc5da667 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -40,6 +40,7 @@ #include <media/tuner.h> #include <media/tveeprom.h> +#include <media/v4l2-common.h> #include <media/audiochip.h> MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver"); @@ -52,21 +53,19 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define STRM(array,i) (i < sizeof(array)/sizeof(char*) ? array[i] : "unknown") -#define tveeprom_info(fmt, arg...) do {\ - printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) -#define tveeprom_warn(fmt, arg...) do {\ - printk(KERN_WARNING "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) -#define tveeprom_dbg(fmt, arg...) do {\ +#define tveeprom_info(fmt, arg...) \ + v4l_printk(KERN_INFO, "tveeprom", c->adapter, c->addr, fmt , ## arg) +#define tveeprom_warn(fmt, arg...) \ + v4l_printk(KERN_WARNING, "tveeprom", c->adapter, c->addr, fmt , ## arg) +#define tveeprom_dbg(fmt, arg...) do { \ if (debug) \ - printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) - - -/* ----------------------------------------------------------------------- */ -/* some hauppauge specific stuff */ + v4l_printk(KERN_DEBUG, "tveeprom", c->adapter, c->addr, fmt , ## arg); \ + } while (0) +/* + * The Hauppauge eeprom uses an 8bit field to determine which + * tuner formats the tuner supports. + */ static struct HAUPPAUGE_TUNER_FMT { int id; @@ -74,14 +73,14 @@ static struct HAUPPAUGE_TUNER_FMT } hauppauge_tuner_fmt[] = { - { 0x00000000, " unknown1" }, - { 0x00000000, " unknown2" }, - { 0x00000007, " PAL(B/G)" }, - { 0x00001000, " NTSC(M)" }, - { 0x00000010, " PAL(I)" }, - { 0x00400000, " SECAM(L/L')" }, - { 0x00000e00, " PAL(D/K)" }, - { 0x03000000, " ATSC/DVB Digital" }, + { V4L2_STD_UNKNOWN," UNKNOWN" }, + { V4L2_STD_UNKNOWN," FM" }, + { V4L2_STD_PAL_BG, " PAL(B/G)" }, + { V4L2_STD_NTSC_M, " NTSC(M)" }, + { V4L2_STD_PAL_I, " PAL(I)" }, + { V4L2_STD_SECAM_L," SECAM(L/L')" }, + { V4L2_STD_PAL_DK, " PAL(D/D1/K)" }, + { V4L2_STD_ATSC, " ATSC/DVB Digital" }, }; /* This is the full list of possible tuners. Many thanks to Hauppauge for @@ -387,7 +386,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, if ((eeprom_data[0] == 0x1a) && (eeprom_data[1] == 0xeb) && (eeprom_data[2] == 0x67) && (eeprom_data[3] == 0x95)) start=0xa0; /* Generic em28xx offset */ - else if (((eeprom_data[0] & 0xf0) == 0x10) && + else if (((eeprom_data[0] & 0xe1) == 0x01) && (eeprom_data[1] == 0x00) && (eeprom_data[2] == 0x00) && (eeprom_data[8] == 0x84)) diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index e837f9f7fed6..9e86caeb96a7 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c @@ -227,13 +227,9 @@ static int tvmixer_release(struct inode *inode, struct file *file) } static struct i2c_driver driver = { -#ifdef I2C_PEC .driver = { - .name = "tv card mixer driver", + .name = "tvmixer", }, -#else - .name = "tv card mixer driver", -#endif .id = I2C_DRIVERID_TVMIXER, .detach_adapter = tvmixer_adapters, .attach_adapter = tvmixer_adapters, @@ -267,22 +263,8 @@ static int tvmixer_clients(struct i2c_client *client) struct video_audio va; int i,minor; -#ifdef I2C_CLASS_TV_ANALOG if (!(client->adapter->class & I2C_CLASS_TV_ANALOG)) return -1; -#else - /* TV card ??? */ - switch (client->adapter->id) { - case I2C_HW_SMBUS_VOODOO3: - case I2C_HW_B_BT848: - case I2C_HW_B_RIVA: - /* ok, have a look ... */ - break; - default: - /* ignore that one */ - return -1; - } -#endif /* unregister ?? */ for (i = 0; i < DEV_MAX; i++) { diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index a60442ea4f94..c35b8042eee5 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -9,6 +9,7 @@ #include <linux/videodev.h> #include <linux/delay.h> #include <linux/video_decoder.h> +#include <media/v4l2-common.h> #include "tvp5150_reg.h" @@ -28,33 +29,38 @@ static int debug = 0; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ +#define tvp5150_info(fmt, arg...) do { \ + printk(KERN_INFO "%s %d-%04x: " fmt, c->driver->driver.name, \ + i2c_adapter_id(c->adapter), c->addr , ## arg); } while (0) +#define tvp5150_dbg(num, fmt, arg...) \ do { \ if (debug >= num) \ - printk(format, ##args); \ - } while (0) + printk(KERN_DEBUG "%s debug %d-%04x: " fmt,\ + c->driver->driver.name, \ + i2c_adapter_id(c->adapter), \ + c->addr , ## arg); } while (0) /* supported controls */ static struct v4l2_queryctrl tvp5150_qctrl[] = { { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 0, - .flags = 0, - }, { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = 0x10, - .flags = 0, - }, { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 0x1, + .default_value = 0x10, + .flags = 0, + }, { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Saturation", @@ -63,16 +69,16 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = { .step = 0x1, .default_value = 0x10, .flags = 0, - }, { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = -128, - .maximum = 127, - .step = 0x1, - .default_value = 0x10, - .flags = 0, - } + }, { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = -128, + .maximum = 127, + .step = 0x1, + .default_value = 0x10, + .flags = 0, + } }; struct tvp5150 { @@ -94,12 +100,14 @@ static inline int tvp5150_read(struct i2c_client *c, unsigned char addr) buffer[0] = addr; if (1 != (rc = i2c_master_send(c, buffer, 1))) - dprintk(0, "i2c i/o error: rc == %d (should be 1)\n", rc); + tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 1)\n", rc); msleep(10); if (1 != (rc = i2c_master_recv(c, buffer, 1))) - dprintk(0, "i2c i/o error: rc == %d (should be 1)\n", rc); + tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 1)\n", rc); + + tvp5150_dbg(2, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]); return (buffer[0]); } @@ -109,13 +117,12 @@ static inline void tvp5150_write(struct i2c_client *c, unsigned char addr, { unsigned char buffer[2]; int rc; -/* struct tvp5150 *core = i2c_get_clientdata(c); */ buffer[0] = addr; buffer[1] = value; - dprintk(1, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]); + tvp5150_dbg(2, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]); if (2 != (rc = i2c_master_send(c, buffer, 2))) - dprintk(0, "i2c i/o error: rc == %d (should be 2)\n", rc); + tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 2)\n", rc); } static void dump_reg(struct i2c_client *c) @@ -437,48 +444,346 @@ enum tvp5150_input { static inline void tvp5150_selmux(struct i2c_client *c, enum tvp5150_input input) { + int opmode=0; + struct tvp5150 *decoder = i2c_get_clientdata(c); if (!decoder->enable) input |= TVP5150_BLACK_SCREEN; + switch (input) { + case TVP5150_ANALOG_CH0: + case TVP5150_ANALOG_CH1: + opmode=0x30; /* TV Mode */ + break; + default: + opmode=0; /* Auto Mode */ + break; + } + + tvp5150_write(c, TVP5150_OP_MODE_CTL, opmode); tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, input); }; -static inline void tvp5150_reset(struct i2c_client *c) +struct i2c_reg_value { + unsigned char reg; + unsigned char value; +}; + +/* Default values as sugested at TVP5150AM1 datasheet */ +static const struct i2c_reg_value tvp5150_init_default[] = { + { /* 0x00 */ + TVP5150_VD_IN_SRC_SEL_1,0x00 + }, + { /* 0x01 */ + TVP5150_ANAL_CHL_CTL,0x15 + }, + { /* 0x02 */ + TVP5150_OP_MODE_CTL,0x00 + }, + { /* 0x03 */ + TVP5150_MISC_CTL,0x01 + }, + { /* 0x06 */ + TVP5150_COLOR_KIL_THSH_CTL,0x10 + }, + { /* 0x07 */ + TVP5150_LUMA_PROC_CTL_1,0x60 + }, + { /* 0x08 */ + TVP5150_LUMA_PROC_CTL_2,0x00 + }, + { /* 0x09 */ + TVP5150_BRIGHT_CTL,0x80 + }, + { /* 0x0a */ + TVP5150_SATURATION_CTL,0x80 + }, + { /* 0x0b */ + TVP5150_HUE_CTL,0x00 + }, + { /* 0x0c */ + TVP5150_CONTRAST_CTL,0x80 + }, + { /* 0x0d */ + TVP5150_DATA_RATE_SEL,0x47 + }, + { /* 0x0e */ + TVP5150_LUMA_PROC_CTL_3,0x00 + }, + { /* 0x0f */ + TVP5150_CONF_SHARED_PIN,0x08 + }, + { /* 0x11 */ + TVP5150_ACT_VD_CROP_ST_MSB,0x00 + }, + { /* 0x12 */ + TVP5150_ACT_VD_CROP_ST_LSB,0x00 + }, + { /* 0x13 */ + TVP5150_ACT_VD_CROP_STP_MSB,0x00 + }, + { /* 0x14 */ + TVP5150_ACT_VD_CROP_STP_LSB,0x00 + }, + { /* 0x15 */ + TVP5150_GENLOCK,0x01 + }, + { /* 0x16 */ + TVP5150_HORIZ_SYNC_START,0x80 + }, + { /* 0x18 */ + TVP5150_VERT_BLANKING_START,0x00 + }, + { /* 0x19 */ + TVP5150_VERT_BLANKING_STOP,0x00 + }, + { /* 0x1a */ + TVP5150_CHROMA_PROC_CTL_1,0x0c + }, + { /* 0x1b */ + TVP5150_CHROMA_PROC_CTL_2,0x14 + }, + { /* 0x1c */ + TVP5150_INT_RESET_REG_B,0x00 + }, + { /* 0x1d */ + TVP5150_INT_ENABLE_REG_B,0x00 + }, + { /* 0x1e */ + TVP5150_INTT_CONFIG_REG_B,0x00 + }, + { /* 0x28 */ + TVP5150_VIDEO_STD,0x00 + }, + { /* 0x2e */ + TVP5150_MACROVISION_ON_CTR,0x0f + }, + { /* 0x2f */ + TVP5150_MACROVISION_OFF_CTR,0x01 + }, + { /* 0xbb */ + TVP5150_TELETEXT_FIL_ENA,0x00 + }, + { /* 0xc0 */ + TVP5150_INT_STATUS_REG_A,0x00 + }, + { /* 0xc1 */ + TVP5150_INT_ENABLE_REG_A,0x00 + }, + { /* 0xc2 */ + TVP5150_INT_CONF,0x04 + }, + { /* 0xc8 */ + TVP5150_FIFO_INT_THRESHOLD,0x80 + }, + { /* 0xc9 */ + TVP5150_FIFO_RESET,0x00 + }, + { /* 0xca */ + TVP5150_LINE_NUMBER_INT,0x00 + }, + { /* 0xcb */ + TVP5150_PIX_ALIGN_REG_LOW,0x4e + }, + { /* 0xcc */ + TVP5150_PIX_ALIGN_REG_HIGH,0x00 + }, + { /* 0xcd */ + TVP5150_FIFO_OUT_CTRL,0x01 + }, + { /* 0xcf */ + TVP5150_FULL_FIELD_ENA_1,0x00 + }, + { /* 0xd0 */ + TVP5150_FULL_FIELD_ENA_2,0x00 + }, + { /* 0xfc */ + TVP5150_FULL_FIELD_MODE_REG,0x7f + }, + { /* end of data */ + 0xff,0xff + } +}; + +/* Default values as sugested at TVP5150AM1 datasheet */ +static const struct i2c_reg_value tvp5150_init_enable[] = { + { + TVP5150_CONF_SHARED_PIN, 2 + },{ /* Automatic offset and AGC enabled */ + TVP5150_ANAL_CHL_CTL, 0x15 + },{ /* Activate YCrCb output 0x9 or 0xd ? */ + TVP5150_MISC_CTL, 0x6f + },{ /* Activates video std autodetection for all standards */ + TVP5150_AUTOSW_MSK, 0x0 + },{ /* Default format: 0x47. For 4:2:2: 0x40 */ + TVP5150_DATA_RATE_SEL, 0x47 + },{ + TVP5150_CHROMA_PROC_CTL_1, 0x0c + },{ + TVP5150_CHROMA_PROC_CTL_2, 0x54 + },{ /* Non documented, but initialized on WinTV USB2 */ + 0x27, 0x20 + },{ + 0xff,0xff + } +}; + +struct i2c_vbi_ram_value { + u16 reg; + unsigned char values[26]; +}; + +struct i2c_vbi_ram_value vbi_ram_default[] = { - struct tvp5150 *decoder = i2c_get_clientdata(c); + {0x010, /* WST SECAM 6 */ + { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x26, 0xe6, 0xb4, 0x0e, 0x0, 0x0, 0x0, 0x10, 0x0 } + }, + {0x030, /* WST PAL B 6 */ + { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x2b, 0xa6, 0x72, 0x10, 0x0, 0x0, 0x0, 0x10, 0x0 } + }, + {0x050, /* WST PAL C 6 */ + { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0xa6, 0x98, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } + }, + {0x070, /* WST NTSC 6 */ + { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } + }, + {0x090, /* NABTS, NTSC 6 */ + { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x15, 0x0 } + }, + {0x0b0, /* NABTS, NTSC-J 6 */ + { 0xaa, 0xaa, 0xff, 0xff , 0xa7, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 } + }, + {0x0d0, /* CC, PAL/SECAM 6 */ + { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0xa6, 0x7b, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 } + }, + {0x0f0, /* CC, NTSC 6 */ + { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0x69, 0x8c, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 } + }, + {0x110, /* WSS, PAL/SECAM 6 */ + { 0x5b, 0x55, 0xc5, 0xff , 0x0, 0x71, 0x6e, 0x42, 0xa6, 0xcd, 0x0f, 0x0, 0x0, 0x0, 0x3a, 0x0 } + }, + {0x130, /* WSS, NTSC C */ + { 0x38, 0x00, 0x3f, 0x00 , 0x0, 0x71, 0x6e, 0x43, 0x69, 0x7c, 0x08, 0x0, 0x0, 0x0, 0x39, 0x0 } + }, + {0x150, /* VITC, PAL/SECAM 6 */ + { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0xa6, 0x85, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 } + }, + {0x170, /* VITC, NTSC 6 */ + { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0x69, 0x94, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 } + }, + { (u16)-1 } +}; - tvp5150_write(c, TVP5150_CONF_SHARED_PIN, 2); +static int tvp5150_write_inittab(struct i2c_client *c, + const struct i2c_reg_value *regs) +{ + while (regs->reg != 0xff) { + tvp5150_write(c, regs->reg, regs->value); + regs++; + } + return 0; +} - /* Automatic offset and AGC enabled */ - tvp5150_write(c, TVP5150_ANAL_CHL_CTL, 0x15); +static int tvp5150_vdp_init(struct i2c_client *c, + const struct i2c_vbi_ram_value *regs) +{ + unsigned int i; - /* Normal Operation */ -// tvp5150_write(c, TVP5150_OP_MODE_CTL, 0x00); + /* Disable Full Field */ + tvp5150_write(c, TVP5150_FULL_FIELD_ENA_1, 0); - /* Activate YCrCb output 0x9 or 0xd ? */ - tvp5150_write(c, TVP5150_MISC_CTL, 0x6f); + /* Before programming, Line mode should be at 0xff */ + for (i=TVP5150_FULL_FIELD_ENA_2; i<=TVP5150_LINE_MODE_REG_44; i++) + tvp5150_write(c, i, 0xff); - /* Activates video std autodetection for all standards */ - tvp5150_write(c, TVP5150_AUTOSW_MSK, 0x0); + /* Load Ram Table */ + while (regs->reg != (u16)-1 ) { + tvp5150_write(c, TVP5150_CONF_RAM_ADDR_HIGH,regs->reg>>8); + tvp5150_write(c, TVP5150_CONF_RAM_ADDR_LOW,regs->reg); - /* Default format: 0x47, 4:2:2: 0x40 */ - tvp5150_write(c, TVP5150_DATA_RATE_SEL, 0x47); + for (i=0;i<16;i++) + tvp5150_write(c, TVP5150_VDP_CONF_RAM_DATA,regs->values[i]); - tvp5150_selmux(c, decoder->input); + regs++; + } + return 0; +} + +static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std) +{ + struct tvp5150 *decoder = i2c_get_clientdata(c); + int fmt=0; + + decoder->norm=std; + + /* First tests should be against specific std */ + + if (std == V4L2_STD_ALL) { + fmt=0; /* Autodetect mode */ + } else if (std & V4L2_STD_NTSC_443) { + fmt=0xa; + } else if (std & V4L2_STD_PAL_M) { + fmt=0x6; + } else if (std & (V4L2_STD_PAL_N| V4L2_STD_PAL_Nc)) { + fmt=0x8; + } else { + /* Then, test against generic ones */ + if (std & V4L2_STD_NTSC) { + fmt=0x2; + } else if (std & V4L2_STD_PAL) { + fmt=0x4; + } else if (std & V4L2_STD_SECAM) { + fmt=0xc; + } + } + + tvp5150_dbg(1,"Set video std register to %d.\n",fmt); + tvp5150_write(c, TVP5150_VIDEO_STD, fmt); - tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_1, 0x0c); - tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_2, 0x54); + return 0; +} - tvp5150_write(c, 0x27, 0x20); /* ?????????? */ +static inline void tvp5150_reset(struct i2c_client *c) +{ + u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom; + struct tvp5150 *decoder = i2c_get_clientdata(c); - tvp5150_write(c, TVP5150_VIDEO_STD, 0x0); /* Auto switch */ + type=tvp5150_read(c,TVP5150_AUTOSW_MSK); + msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID); + lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID); + msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER); + lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER); + + if (type==0xdc) { + ver_656=tvp5150_read(c,TVP5150_REV_SELECT); + tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656); + } else if (type==0xfc) { + tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id); + } else { + tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type); + } + tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom); + /* Initializes TVP5150 to its default values */ + tvp5150_write_inittab(c, tvp5150_init_default); + + /* Initializes VDP registers */ + tvp5150_vdp_init(c, vbi_ram_default); + + /* Selects decoder input */ + tvp5150_selmux(c, decoder->input); + + /* Initializes TVP5150 to stream enabled values */ + tvp5150_write_inittab(c, tvp5150_init_enable); + + /* Initialize image preferences */ tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright >> 8); tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast >> 8); tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast >> 8); tvp5150_write(c, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8); + + tvp5150_set_std(c, decoder->norm); }; static int tvp5150_get_ctrl(struct i2c_client *c, struct v4l2_control *ctrl) @@ -498,9 +803,8 @@ static int tvp5150_get_ctrl(struct i2c_client *c, struct v4l2_control *ctrl) case V4L2_CID_HUE: ctrl->value = tvp5150_read(c, TVP5150_HUE_CTL); return 0; - default: - return -EINVAL; } + return -EINVAL; } static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl) @@ -520,28 +824,59 @@ static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl) case V4L2_CID_HUE: tvp5150_write(c, TVP5150_HUE_CTL, ctrl->value); return 0; - default: - return -EINVAL; } + return -EINVAL; } /**************************************************************************** I2C Command ****************************************************************************/ -static int tvp5150_command(struct i2c_client *client, +static int tvp5150_command(struct i2c_client *c, unsigned int cmd, void *arg) { - struct tvp5150 *decoder = i2c_get_clientdata(client); + struct tvp5150 *decoder = i2c_get_clientdata(c); switch (cmd) { case 0: + case VIDIOC_INT_RESET: case DECODER_INIT: - tvp5150_reset(client); + tvp5150_reset(c); + break; + case VIDIOC_S_STD: + if (decoder->norm == *(v4l2_std_id *)arg) + break; + return tvp5150_set_std(c, *(v4l2_std_id *)arg); + case VIDIOC_G_STD: + *(v4l2_std_id *)arg = decoder->norm; + break; + +#ifdef CONFIG_VIDEO_ADV_DEBUG + case VIDIOC_INT_G_REGISTER: + { + struct v4l2_register *reg = arg; + + if (reg->i2c_id != I2C_DRIVERID_TVP5150) + return -EINVAL; + reg->val = tvp5150_read(c, reg->reg & 0xff); + break; + } + + case VIDIOC_INT_S_REGISTER: + { + struct v4l2_register *reg = arg; + + if (reg->i2c_id != I2C_DRIVERID_TVP5150) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff); break; + } +#endif case DECODER_DUMP: - dump_reg(client); + dump_reg(c); break; case DECODER_GET_CAPABILITIES: @@ -600,7 +935,7 @@ static int tvp5150_command(struct i2c_client *client, } decoder->input = *iarg; - tvp5150_selmux(client, decoder->input); + tvp5150_selmux(c, decoder->input); break; } @@ -620,19 +955,18 @@ static int tvp5150_command(struct i2c_client *client, decoder->enable = (*iarg != 0); - tvp5150_selmux(client, decoder->input); + tvp5150_selmux(c, decoder->input); break; } case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; - u8 i, n; + int i; - dprintk(1, KERN_DEBUG "VIDIOC_QUERYCTRL"); + tvp5150_dbg(1, "VIDIOC_QUERYCTRL called\n"); - n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]); - for (i = 0; i < n; i++) + for (i = 0; i < ARRAY_SIZE(tvp5150_qctrl); i++) if (qc->id && qc->id == tvp5150_qctrl[i].id) { memcpy(qc, &(tvp5150_qctrl[i]), sizeof(*qc)); @@ -644,16 +978,14 @@ static int tvp5150_command(struct i2c_client *client, case VIDIOC_G_CTRL: { struct v4l2_control *ctrl = arg; - dprintk(1, KERN_DEBUG "VIDIOC_G_CTRL"); + tvp5150_dbg(1, "VIDIOC_G_CTRL called\n"); - return tvp5150_get_ctrl(client, ctrl); + return tvp5150_get_ctrl(c, ctrl); } - case VIDIOC_S_CTRL_OLD: /* ??? */ case VIDIOC_S_CTRL: { struct v4l2_control *ctrl = arg; u8 i, n; - dprintk(1, KERN_DEBUG "VIDIOC_S_CTRL"); n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]); for (i = 0; i < n; i++) if (ctrl->id == tvp5150_qctrl[i].id) { @@ -662,11 +994,10 @@ static int tvp5150_command(struct i2c_client *client, || ctrl->value > tvp5150_qctrl[i].maximum) return -ERANGE; - dprintk(1, - KERN_DEBUG - "VIDIOC_S_CTRL: id=%d, value=%d", + tvp5150_dbg(1, + "VIDIOC_S_CTRL: id=%d, value=%d\n", ctrl->id, ctrl->value); - return tvp5150_set_ctrl(client, ctrl); + return tvp5150_set_ctrl(c, ctrl); } return -EINVAL; } @@ -677,25 +1008,25 @@ static int tvp5150_command(struct i2c_client *client, if (decoder->bright != pic->brightness) { /* We want 0 to 255 we get 0-65535 */ decoder->bright = pic->brightness; - tvp5150_write(client, TVP5150_BRIGHT_CTL, + tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright >> 8); } if (decoder->contrast != pic->contrast) { /* We want 0 to 255 we get 0-65535 */ decoder->contrast = pic->contrast; - tvp5150_write(client, TVP5150_CONTRAST_CTL, + tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast >> 8); } if (decoder->sat != pic->colour) { /* We want 0 to 255 we get 0-65535 */ decoder->sat = pic->colour; - tvp5150_write(client, TVP5150_SATURATION_CTL, + tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast >> 8); } if (decoder->hue != pic->hue) { /* We want -128 to 127 we get 0-65535 */ decoder->hue = pic->hue; - tvp5150_write(client, TVP5150_HUE_CTL, + tvp5150_write(c, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8); } break; @@ -720,12 +1051,12 @@ static struct i2c_client client_template = { static int tvp5150_detect_client(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_client *client; + struct i2c_client *c; struct tvp5150 *core; int rv; - dprintk(1, - KERN_INFO + if (debug) + printk( KERN_INFO "tvp5150.c: detecting tvp5150 client on address 0x%x\n", address << 1); @@ -738,22 +1069,22 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter, I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return 0; - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) + c = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (c == 0) return -ENOMEM; - memcpy(client, &client_template, sizeof(struct i2c_client)); + memcpy(c, &client_template, sizeof(struct i2c_client)); core = kmalloc(sizeof(struct tvp5150), GFP_KERNEL); if (core == 0) { - kfree(client); + kfree(c); return -ENOMEM; } memset(core, 0, sizeof(struct tvp5150)); - i2c_set_clientdata(client, core); + i2c_set_clientdata(c, core); - rv = i2c_attach_client(client); + rv = i2c_attach_client(c); - core->norm = VIDEO_MODE_AUTO; + core->norm = V4L2_STD_ALL; core->input = 2; core->enable = 1; core->bright = 32768; @@ -762,37 +1093,41 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter, core->sat = 32768; if (rv) { - kfree(client); + kfree(c); kfree(core); return rv; } if (debug > 1) - dump_reg(client); + dump_reg(c); return 0; } static int tvp5150_attach_adapter(struct i2c_adapter *adapter) { - dprintk(1, - KERN_INFO + if (debug) + printk( KERN_INFO "tvp5150.c: starting probe for adapter %s (0x%x)\n", adapter->name, adapter->id); return i2c_probe(adapter, &addr_data, &tvp5150_detect_client); } -static int tvp5150_detach_client(struct i2c_client *client) +static int tvp5150_detach_client(struct i2c_client *c) { - struct tvp5150 *decoder = i2c_get_clientdata(client); + struct tvp5150 *decoder = i2c_get_clientdata(c); int err; - err = i2c_detach_client(client); + tvp5150_dbg(1, + "tvp5150.c: removing tvp5150 adapter on address 0x%x\n", + c->addr << 1); + + err = i2c_detach_client(c); if (err) { return err; } kfree(decoder); - kfree(client); + kfree(c); return 0; } @@ -803,9 +1138,7 @@ static struct i2c_driver driver = { .driver = { .name = "tvp5150", }, - - /* FIXME */ - .id = I2C_DRIVERID_SAA7110, + .id = I2C_DRIVERID_TVP5150, .attach_adapter = tvp5150_attach_adapter, .detach_client = tvp5150_detach_client, diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 4134549d11a8..2ab5b4093800 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -951,6 +951,10 @@ v4l_compat_translate_ioctl(struct inode *inode, dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); break; } + if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { + err = -EINVAL; + break; + } memset(fmt, 0, sizeof(*fmt)); fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line; fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate; @@ -966,6 +970,11 @@ v4l_compat_translate_ioctl(struct inode *inode, { struct vbi_format *fmt = arg; + if (VIDEO_PALETTE_RAW != fmt->sample_format) { + err = -EINVAL; + break; + } + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(fmt2, 0, sizeof(*fmt2)); @@ -986,7 +995,7 @@ v4l_compat_translate_ioctl(struct inode *inode, if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || - VIDEO_PALETTE_RAW != fmt->sample_format || + fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY || fmt2->fmt.vbi.start[0] != fmt->start[0] || fmt2->fmt.vbi.count[0] != fmt->count[0] || fmt2->fmt.vbi.start[1] != fmt->start[1] || diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 62a7d636ef11..5dbd7c1b362a 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -58,6 +58,8 @@ #include <asm/pgtable.h> #include <asm/io.h> #include <asm/div64.h> +#include <linux/video_decoder.h> +#include <media/v4l2-common.h> #ifdef CONFIG_KMOD #include <linux/kmod.h> @@ -190,55 +192,174 @@ char *v4l2_type_names[] = { [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", }; -char *v4l2_ioctl_names[256] = { - [0 ... 255] = "UNKNOWN", - [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", - [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", - [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT", - [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT", - [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT", - [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS", - [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF", - [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF", - [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF", - [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY", - [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF", - [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF", - [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON", - [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF", - [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM", - [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM", - [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD", - [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD", - [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD", - [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT", - [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL", - [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL", - [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER", - [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER", - [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO", - [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO", - [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL", - [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU", - [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT", - [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT", - [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT", - [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT", - [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT", - [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT", - [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT", - [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR", - [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR", - [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY", - [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY", - [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", - [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", - [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", - [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", - [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", - [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", - [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT", +/* ------------------------------------------------------------------ */ +/* debug help functions */ + +#ifdef HAVE_V4L1 +static const char *v4l1_ioctls[] = { + [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP", + [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN", + [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN", + [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER", + [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER", + [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT", + [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT", + [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE", + [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN", + [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN", + [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF", + [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF", + [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY", + [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ", + [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ", + [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO", + [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO", + [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC", + [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE", + [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF", + [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT", + [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE", + [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE", + [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE", + [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE", + [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO", + [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE", + [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT", + [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT" }; +#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) +#endif + +static const char *v4l2_ioctls[] = { + [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", + [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", + [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT", + [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT", + [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT", + [_IOC_NR(VIDIOC_G_MPEGCOMP)] = "VIDIOC_G_MPEGCOMP", + [_IOC_NR(VIDIOC_S_MPEGCOMP)] = "VIDIOC_S_MPEGCOMP", + [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS", + [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF", + [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF", + [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF", + [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY", + [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF", + [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF", + [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON", + [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF", + [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM", + [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM", + [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD", + [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD", + [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD", + [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT", + [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL", + [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL", + [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER", + [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER", + [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO", + [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO", + [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL", + [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU", + [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT", + [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT", + [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT", + [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT", + [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT", + [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT", + [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT", + [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR", + [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR", + [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY", + [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY", + [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", + [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", + [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", + [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", + [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", + [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", + [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT", + [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO", + [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT", + [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY", + [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY", +#if 1 + [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", +#endif + [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS" +}; +#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) + +static const char *v4l2_int_ioctls[] = { +#ifdef HAVE_VIDEO_DECODER + [_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES", + [_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS", + [_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM", + [_IOC_NR(DECODER_SET_INPUT)] = "DECODER_SET_INPUT", + [_IOC_NR(DECODER_SET_OUTPUT)] = "DECODER_SET_OUTPUT", + [_IOC_NR(DECODER_ENABLE_OUTPUT)] = "DECODER_ENABLE_OUTPUT", + [_IOC_NR(DECODER_SET_PICTURE)] = "DECODER_SET_PICTURE", + [_IOC_NR(DECODER_SET_GPIO)] = "DECODER_SET_GPIO", + [_IOC_NR(DECODER_INIT)] = "DECODER_INIT", + [_IOC_NR(DECODER_SET_VBI_BYPASS)] = "DECODER_SET_VBI_BYPASS", + [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP", +#endif + [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", + [_IOC_NR(AUDC_SET_INPUT)] = "AUDC_SET_INPUT", + + [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", + [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", + [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG", + + [_IOC_NR(VIDIOC_INT_S_REGISTER)] = "VIDIOC_INT_S_REGISTER", + [_IOC_NR(VIDIOC_INT_G_REGISTER)] = "VIDIOC_INT_G_REGISTER", + [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", + [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", + [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE", + [_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA", + [_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA", + [_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)] = "VIDIOC_INT_G_CHIP_IDENT", + [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ" +}; +#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) + +/* Common ioctl debug function. This function can be used by + external ioctl messages as well as internal V4L ioctl */ +void v4l_printk_ioctl(unsigned int cmd) +{ + char *dir; + + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: dir = "--"; break; + case _IOC_READ: dir = "r-"; break; + case _IOC_WRITE: dir = "-w"; break; + case _IOC_READ | _IOC_WRITE: dir = "rw"; break; + default: dir = "*ERR*"; break; + } + switch (_IOC_TYPE(cmd)) { + case 'd': + printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n", + (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ? + v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); + break; +#ifdef HAVE_V4L1 + case 'v': + printk("v4l1 ioctl %s, dir=%s (0x%08x)\n", + (_IOC_NR(cmd) < V4L1_IOCTLS) ? + v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); + break; +#endif + case 'V': + printk("v4l2 ioctl %s, dir=%s (0x%08x)\n", + (_IOC_NR(cmd) < V4L2_IOCTLS) ? + v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); + break; + + default: + printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n", + _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); + } +} /* ----------------------------------------------------------------- */ @@ -253,7 +374,7 @@ EXPORT_SYMBOL(v4l2_prio_check); EXPORT_SYMBOL(v4l2_field_names); EXPORT_SYMBOL(v4l2_type_names); -EXPORT_SYMBOL(v4l2_ioctl_names); +EXPORT_SYMBOL(v4l_printk_ioctl); /* * Local variables: diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 6de5b0094b82..9a9902c56ae7 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -68,7 +68,8 @@ static void video_release(struct class_device *cd) { struct video_device *vfd = container_of(cd, struct video_device, class_dev); -#if 1 /* needed until all drivers are fixed */ +#if 1 + /* needed until all drivers are fixed */ if (!vfd->release) return; #endif @@ -338,13 +339,14 @@ int video_register_device(struct video_device *vfd, int type, int nr) if (vfd->dev) vfd->class_dev.dev = vfd->dev; vfd->class_dev.class = &video_class; - vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); + vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); strlcpy(vfd->class_dev.class_id, vfd->devfs_name + 4, BUS_ID_SIZE); class_device_register(&vfd->class_dev); class_device_create_file(&vfd->class_dev, - &class_device_attr_name); + &class_device_attr_name); -#if 1 /* needed until all drivers are fixed */ +#if 1 + /* needed until all drivers are fixed */ if (!vfd->release) printk(KERN_WARNING "videodev: \"%s\" has no release callback. " "Please fix your driver for proper sysfs support, see " diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index c318ba32fbaf..b7b0afffd214 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -187,6 +187,7 @@ static struct file_operations w9966_fops = { .open = video_exclusive_open, .release = video_exclusive_release, .ioctl = w9966_v4l_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .read = w9966_v4l_read, .llseek = no_llseek, }; diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index bbfd55cd9948..c2e6d2e9f5f1 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -25,7 +25,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - #include <linux/module.h> #include <linux/types.h> #include <linux/ioctl.h> @@ -33,20 +32,12 @@ #include <linux/i2c.h> #include <linux/i2c-id.h> #include <linux/videodev.h> -#include <media/audiochip.h> +#include <media/v4l2-common.h> MODULE_DESCRIPTION("wm8775 driver"); MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); MODULE_LICENSE("GPL"); -#define wm8775_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) -#define wm8775_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) - - static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END }; @@ -70,7 +61,7 @@ static int wm8775_write(struct i2c_client *client, int reg, u16 val) int i; if (reg < 0 || reg >= TOT_REGS) { - wm8775_err("Invalid register R%d\n", reg); + v4l_err(client, "Invalid register R%d\n", reg); return -1; } @@ -80,7 +71,7 @@ static int wm8775_write(struct i2c_client *client, int reg, u16 val) return 0; } } - wm8775_err("I2C: cannot write %03x to register R%d\n", val, reg); + v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); return -1; } @@ -88,38 +79,53 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct wm8775_state *state = i2c_get_clientdata(client); - int *input = arg; + struct v4l2_audio *input = arg; + struct v4l2_control *ctrl = arg; switch (cmd) { - case AUDC_SET_INPUT: + case VIDIOC_S_AUDIO: + /* There are 4 inputs and one output. Zero or more inputs + are multiplexed together to the output. Hence there are + 16 combinations. + If only one input is active (the normal case) then the + input values 1, 2, 4 or 8 should be used. */ + if (input->index > 15) { + v4l_err(client, "Invalid input %d.\n", input->index); + return -EINVAL; + } + state->input = input->index; + if (state->muted) + break; wm8775_write(client, R21, 0x0c0); wm8775_write(client, R14, 0x1d4); wm8775_write(client, R15, 0x1d4); + wm8775_write(client, R21, 0x100 + state->input); + break; - if (*input == AUDIO_RADIO) { - wm8775_write(client, R21, 0x108); - state->input = 8; - state->muted = 0; - break; - } - if (*input == AUDIO_MUTE) { - state->muted = 1; - break; - } - if (*input == AUDIO_UNMUTE) { + case VIDIOC_G_AUDIO: + memset(input, 0, sizeof(*input)); + input->index = state->input; + break; + + case VIDIOC_G_CTRL: + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + ctrl->value = state->muted; + break; + + case VIDIOC_S_CTRL: + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + state->muted = ctrl->value; + wm8775_write(client, R21, 0x0c0); + wm8775_write(client, R14, 0x1d4); + wm8775_write(client, R15, 0x1d4); + if (!state->muted) wm8775_write(client, R21, 0x100 + state->input); - state->muted = 0; - break; - } - /* All other inputs... */ - wm8775_write(client, R21, 0x102); - state->input = 2; - state->muted = 0; break; case VIDIOC_LOG_STATUS: - wm8775_info("Input: %s%s\n", - state->input == 8 ? "radio" : "default", + v4l_info(client, "Input: %d%s\n", state->input, state->muted ? " (muted)" : ""); break; @@ -170,7 +176,7 @@ static int wm8775_attach(struct i2c_adapter *adapter, int address, int kind) client->driver = &i2c_driver; snprintf(client->name, sizeof(client->name) - 1, "wm8775"); - wm8775_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name); + v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); state = kmalloc(sizeof(struct wm8775_state), GFP_KERNEL); if (state == NULL) { @@ -206,11 +212,7 @@ static int wm8775_attach(struct i2c_adapter *adapter, int address, int kind) static int wm8775_probe(struct i2c_adapter *adapter) { -#ifdef I2C_CLASS_TV_ANALOG if (adapter->class & I2C_CLASS_TV_ANALOG) -#else - if (adapter->id == I2C_HW_B_BT848) -#endif return i2c_probe(adapter, &addr_data, wm8775_attach); return 0; } @@ -235,12 +237,10 @@ static struct i2c_driver i2c_driver = { .driver = { .name = "wm8775", }, - - .id = I2C_DRIVERID_WM8775, - + .id = I2C_DRIVERID_WM8775, .attach_adapter = wm8775_probe, - .detach_client = wm8775_detach, - .command = wm8775_command, + .detach_client = wm8775_detach, + .command = wm8775_command, }; diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 4034f1b45366..15283f44e79f 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -4678,6 +4678,7 @@ static struct file_operations zoran_fops = { .open = zoran_open, .release = zoran_close, .ioctl = zoran_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, .read = zoran_read, .write = zoran_write, diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c index 07286816d7df..d4c633b8a7f5 100644 --- a/drivers/media/video/zr36120.c +++ b/drivers/media/video/zr36120.c @@ -1490,6 +1490,7 @@ static struct video_device zr36120_template= .write = zoran_write, .poll = zoran_poll, .ioctl = zoran_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .mmap = zoran_mmap, .minor = -1, }; diff --git a/drivers/message/i2o/README.ioctl b/drivers/message/i2o/README.ioctl index 73dd084c0e98..65c0c47aeb79 100644 --- a/drivers/message/i2o/README.ioctl +++ b/drivers/message/i2o/README.ioctl @@ -185,7 +185,7 @@ VII. Getting Parameters ENOMEM Kernel memory allocation error A return value of 0 does not mean that the value was actually - properly retreived. The user should check the result list + properly retrieved. The user should check the result list to determine the specific status of the transaction. VIII. Downloading Software diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 6696f71363b9..bfca5c176e88 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -495,6 +495,7 @@ static void mmc_decode_cid(struct mmc_card *card) case 2: /* MMC v2.0 - v2.2 */ case 3: /* MMC v3.1 - v3.3 */ + case 4: /* MMC v4 */ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index d5f28981596b..f2c42b13945d 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -187,7 +187,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.data.flags |= MMC_DATA_WRITE; brq.data.blocks = 1; } - brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL; + + if (brq.data.blocks > 1) { + brq.data.flags |= MMC_DATA_MULTI; + brq.mrq.stop = &brq.stop; + } else { + brq.mrq.stop = NULL; + } brq.data.sg = mq->sg; brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg); diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 4f13bd2ccf9a..f25757625361 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -90,7 +90,7 @@ static int dma = 2; * Basic functions */ -static inline void wbsd_unlock_config(struct wbsd_host* host) +static inline void wbsd_unlock_config(struct wbsd_host *host) { BUG_ON(host->config == 0); @@ -98,14 +98,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host) outb(host->unlock_code, host->config); } -static inline void wbsd_lock_config(struct wbsd_host* host) +static inline void wbsd_lock_config(struct wbsd_host *host) { BUG_ON(host->config == 0); outb(LOCK_CODE, host->config); } -static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value) +static inline void wbsd_write_config(struct wbsd_host *host, u8 reg, u8 value) { BUG_ON(host->config == 0); @@ -113,7 +113,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value) outb(value, host->config + 1); } -static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg) +static inline u8 wbsd_read_config(struct wbsd_host *host, u8 reg) { BUG_ON(host->config == 0); @@ -121,13 +121,13 @@ static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg) return inb(host->config + 1); } -static inline void wbsd_write_index(struct wbsd_host* host, u8 index, u8 value) +static inline void wbsd_write_index(struct wbsd_host *host, u8 index, u8 value) { outb(index, host->base + WBSD_IDXR); outb(value, host->base + WBSD_DATAR); } -static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index) +static inline u8 wbsd_read_index(struct wbsd_host *host, u8 index) { outb(index, host->base + WBSD_IDXR); return inb(host->base + WBSD_DATAR); @@ -137,7 +137,7 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index) * Common routines */ -static void wbsd_init_device(struct wbsd_host* host) +static void wbsd_init_device(struct wbsd_host *host) { u8 setup, ier; @@ -197,7 +197,7 @@ static void wbsd_init_device(struct wbsd_host* host) inb(host->base + WBSD_ISR); } -static void wbsd_reset(struct wbsd_host* host) +static void wbsd_reset(struct wbsd_host *host) { u8 setup; @@ -211,14 +211,13 @@ static void wbsd_reset(struct wbsd_host* host) wbsd_write_index(host, WBSD_IDX_SETUP, setup); } -static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq) +static void wbsd_request_end(struct wbsd_host *host, struct mmc_request *mrq) { unsigned long dmaflags; DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode); - if (host->dma >= 0) - { + if (host->dma >= 0) { /* * Release ISA DMA controller. */ @@ -247,7 +246,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq) * Scatter/gather functions */ -static inline void wbsd_init_sg(struct wbsd_host* host, struct mmc_data* data) +static inline void wbsd_init_sg(struct wbsd_host *host, struct mmc_data *data) { /* * Get info. about SG list from data structure. @@ -259,7 +258,7 @@ static inline void wbsd_init_sg(struct wbsd_host* host, struct mmc_data* data) host->remain = host->cur_sg->length; } -static inline int wbsd_next_sg(struct wbsd_host* host) +static inline int wbsd_next_sg(struct wbsd_host *host) { /* * Skip to next SG entry. @@ -270,33 +269,32 @@ static inline int wbsd_next_sg(struct wbsd_host* host) /* * Any entries left? */ - if (host->num_sg > 0) - { - host->offset = 0; - host->remain = host->cur_sg->length; - } + if (host->num_sg > 0) { + host->offset = 0; + host->remain = host->cur_sg->length; + } return host->num_sg; } -static inline char* wbsd_kmap_sg(struct wbsd_host* host) +static inline char *wbsd_kmap_sg(struct wbsd_host *host) { host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ) + host->cur_sg->offset; return host->mapped_sg; } -static inline void wbsd_kunmap_sg(struct wbsd_host* host) +static inline void wbsd_kunmap_sg(struct wbsd_host *host) { kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ); } -static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data) +static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) { unsigned int len, i, size; - struct scatterlist* sg; - char* dmabuf = host->dma_buffer; - char* sgbuf; + struct scatterlist *sg; + char *dmabuf = host->dma_buffer; + char *sgbuf; size = host->size; @@ -308,8 +306,7 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data) * be the entire list though so make sure that * we do not transfer too much. */ - for (i = 0;i < len;i++) - { + for (i = 0; i < len; i++) { sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset; if (size < sg[i].length) memcpy(dmabuf, sgbuf, size); @@ -337,12 +334,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data) host->size -= size; } -static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data) +static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) { unsigned int len, i, size; - struct scatterlist* sg; - char* dmabuf = host->dma_buffer; - char* sgbuf; + struct scatterlist *sg; + char *dmabuf = host->dma_buffer; + char *sgbuf; size = host->size; @@ -354,8 +351,7 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data) * be the entire list though so make sure that * we do not transfer too much. */ - for (i = 0;i < len;i++) - { + for (i = 0; i < len; i++) { sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset; if (size < sg[i].length) memcpy(sgbuf, dmabuf, size); @@ -387,46 +383,38 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data) * Command handling */ -static inline void wbsd_get_short_reply(struct wbsd_host* host, - struct mmc_command* cmd) +static inline void wbsd_get_short_reply(struct wbsd_host *host, + struct mmc_command *cmd) { /* * Correct response type? */ - if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_SHORT) - { + if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_SHORT) { cmd->error = MMC_ERR_INVALID; return; } - cmd->resp[0] = - wbsd_read_index(host, WBSD_IDX_RESP12) << 24; - cmd->resp[0] |= - wbsd_read_index(host, WBSD_IDX_RESP13) << 16; - cmd->resp[0] |= - wbsd_read_index(host, WBSD_IDX_RESP14) << 8; - cmd->resp[0] |= - wbsd_read_index(host, WBSD_IDX_RESP15) << 0; - cmd->resp[1] = - wbsd_read_index(host, WBSD_IDX_RESP16) << 24; + cmd->resp[0] = wbsd_read_index(host, WBSD_IDX_RESP12) << 24; + cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP13) << 16; + cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP14) << 8; + cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP15) << 0; + cmd->resp[1] = wbsd_read_index(host, WBSD_IDX_RESP16) << 24; } -static inline void wbsd_get_long_reply(struct wbsd_host* host, - struct mmc_command* cmd) +static inline void wbsd_get_long_reply(struct wbsd_host *host, + struct mmc_command *cmd) { int i; /* * Correct response type? */ - if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_LONG) - { + if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_LONG) { cmd->error = MMC_ERR_INVALID; return; } - for (i = 0;i < 4;i++) - { + for (i = 0; i < 4; i++) { cmd->resp[i] = wbsd_read_index(host, WBSD_IDX_RESP1 + i * 4) << 24; cmd->resp[i] |= @@ -438,7 +426,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host, } } -static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) +static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd) { int i; u8 status, isr; @@ -456,7 +444,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) * Send the command (CRC calculated by host). */ outb(cmd->opcode, host->base + WBSD_CMDR); - for (i = 3;i >= 0;i--) + for (i = 3; i >= 0; i--) outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR); cmd->error = MMC_ERR_NONE; @@ -471,8 +459,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) /* * Do we expect a reply? */ - if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) - { + if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) { /* * Read back status. */ @@ -488,8 +475,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) else if ((cmd->flags & MMC_RSP_CRC) && (isr & WBSD_INT_CRC)) cmd->error = MMC_ERR_BADCRC; /* All ok */ - else - { + else { if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) wbsd_get_short_reply(host, cmd); else @@ -504,10 +490,10 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) * Data functions */ -static void wbsd_empty_fifo(struct wbsd_host* host) +static void wbsd_empty_fifo(struct wbsd_host *host) { - struct mmc_data* data = host->mrq->cmd->data; - char* buffer; + struct mmc_data *data = host->mrq->cmd->data; + char *buffer; int i, fsr, fifo; /* @@ -522,8 +508,7 @@ static void wbsd_empty_fifo(struct wbsd_host* host) * Drain the fifo. This has a tendency to loop longer * than the FIFO length (usually one block). */ - while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_EMPTY)) - { + while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_EMPTY)) { /* * The size field in the FSR is broken so we have to * do some guessing. @@ -535,8 +520,7 @@ static void wbsd_empty_fifo(struct wbsd_host* host) else fifo = 1; - for (i = 0;i < fifo;i++) - { + for (i = 0; i < fifo; i++) { *buffer = inb(host->base + WBSD_DFR); buffer++; host->offset++; @@ -547,8 +531,7 @@ static void wbsd_empty_fifo(struct wbsd_host* host) /* * Transfer done? */ - if (data->bytes_xfered == host->size) - { + if (data->bytes_xfered == host->size) { wbsd_kunmap_sg(host); return; } @@ -556,15 +539,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host) /* * End of scatter list entry? */ - if (host->remain == 0) - { + if (host->remain == 0) { wbsd_kunmap_sg(host); /* * Get next entry. Check if last. */ - if (!wbsd_next_sg(host)) - { + if (!wbsd_next_sg(host)) { /* * We should never reach this point. * It means that we're trying to @@ -594,10 +575,10 @@ static void wbsd_empty_fifo(struct wbsd_host* host) tasklet_schedule(&host->fifo_tasklet); } -static void wbsd_fill_fifo(struct wbsd_host* host) +static void wbsd_fill_fifo(struct wbsd_host *host) { - struct mmc_data* data = host->mrq->cmd->data; - char* buffer; + struct mmc_data *data = host->mrq->cmd->data; + char *buffer; int i, fsr, fifo; /* @@ -613,8 +594,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host) * Fill the fifo. This has a tendency to loop longer * than the FIFO length (usually one block). */ - while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_FULL)) - { + while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_FULL)) { /* * The size field in the FSR is broken so we have to * do some guessing. @@ -626,8 +606,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host) else fifo = 15; - for (i = 16;i > fifo;i--) - { + for (i = 16; i > fifo; i--) { outb(*buffer, host->base + WBSD_DFR); buffer++; host->offset++; @@ -638,8 +617,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host) /* * Transfer done? */ - if (data->bytes_xfered == host->size) - { + if (data->bytes_xfered == host->size) { wbsd_kunmap_sg(host); return; } @@ -647,15 +625,13 @@ static void wbsd_fill_fifo(struct wbsd_host* host) /* * End of scatter list entry? */ - if (host->remain == 0) - { + if (host->remain == 0) { wbsd_kunmap_sg(host); /* * Get next entry. Check if last. */ - if (!wbsd_next_sg(host)) - { + if (!wbsd_next_sg(host)) { /* * We should never reach this point. * It means that we're trying to @@ -684,7 +660,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host) tasklet_schedule(&host->fifo_tasklet); } -static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) +static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data) { u16 blksize; u8 setup; @@ -706,8 +682,10 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) */ if (data->timeout_ns > 127000000) wbsd_write_index(host, WBSD_IDX_TAAC, 127); - else - wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000); + else { + wbsd_write_index(host, WBSD_IDX_TAAC, + data->timeout_ns / 1000000); + } if (data->timeout_clks > 255) wbsd_write_index(host, WBSD_IDX_NSAC, 255); @@ -722,23 +700,18 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) * Space for CRC must be included in the size. * Two bytes are needed for each data line. */ - if (host->bus_width == MMC_BUS_WIDTH_1) - { + if (host->bus_width == MMC_BUS_WIDTH_1) { blksize = (1 << data->blksz_bits) + 2; wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0); wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF); - } - else if (host->bus_width == MMC_BUS_WIDTH_4) - { + } else if (host->bus_width == MMC_BUS_WIDTH_4) { blksize = (1 << data->blksz_bits) + 2 * 4; - wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0) - | WBSD_DATA_WIDTH); + wbsd_write_index(host, WBSD_IDX_PBSMSB, + ((blksize >> 4) & 0xF0) | WBSD_DATA_WIDTH); wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF); - } - else - { + } else { data->error = MMC_ERR_INVALID; return; } @@ -755,14 +728,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) /* * DMA transfer? */ - if (host->dma >= 0) - { + if (host->dma >= 0) { /* * The buffer for DMA is only 64 kB. */ BUG_ON(host->size > 0x10000); - if (host->size > 0x10000) - { + if (host->size > 0x10000) { data->error = MMC_ERR_INVALID; return; } @@ -794,9 +765,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) * Enable DMA on the host. */ wbsd_write_index(host, WBSD_IDX_DMA, WBSD_DMA_ENABLE); - } - else - { + } else { /* * This flag is used to keep printk * output to a minimum. @@ -817,13 +786,10 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) * Set up FIFO threshold levels (and fill * buffer if doing a write). */ - if (data->flags & MMC_DATA_READ) - { + if (data->flags & MMC_DATA_READ) { wbsd_write_index(host, WBSD_IDX_FIFOEN, WBSD_FIFOEN_FULL | 8); - } - else - { + } else { wbsd_write_index(host, WBSD_IDX_FIFOEN, WBSD_FIFOEN_EMPTY | 8); wbsd_fill_fifo(host); @@ -833,7 +799,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) data->error = MMC_ERR_NONE; } -static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) +static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data) { unsigned long dmaflags; int count; @@ -851,16 +817,14 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) * Wait for the controller to leave data * transfer state. */ - do - { + do { status = wbsd_read_index(host, WBSD_IDX_STATUS); } while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE)); /* * DMA transfer? */ - if (host->dma >= 0) - { + if (host->dma >= 0) { /* * Disable DMA on the host. */ @@ -878,16 +842,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) /* * Any leftover data? */ - if (count) - { + if (count) { printk(KERN_ERR "%s: Incomplete DMA transfer. " "%d bytes left.\n", mmc_hostname(host->mmc), count); data->error = MMC_ERR_FAILED; - } - else - { + } else { /* * Transfer data from DMA buffer to * SG list. @@ -910,10 +871,10 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) * * \*****************************************************************************/ -static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) +static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq) { - struct wbsd_host* host = mmc_priv(mmc); - struct mmc_command* cmd; + struct wbsd_host *host = mmc_priv(mmc); + struct mmc_command *cmd; /* * Disable tasklets to avoid a deadlock. @@ -930,8 +891,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) * If there is no card in the slot then * timeout immediatly. */ - if (!(host->flags & WBSD_FCARD_PRESENT)) - { + if (!(host->flags & WBSD_FCARD_PRESENT)) { cmd->error = MMC_ERR_TIMEOUT; goto done; } @@ -939,8 +899,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) /* * Does the request include data? */ - if (cmd->data) - { + if (cmd->data) { wbsd_prepare_data(host, cmd->data); if (cmd->data->error != MMC_ERR_NONE) @@ -954,8 +913,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) * will be finished after the data has * transfered. */ - if (cmd->data && (cmd->error == MMC_ERR_NONE)) - { + if (cmd->data && (cmd->error == MMC_ERR_NONE)) { /* * Dirty fix for hardware bug. */ @@ -973,14 +931,14 @@ done: spin_unlock_bh(&host->lock); } -static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) +static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { - struct wbsd_host* host = mmc_priv(mmc); + struct wbsd_host *host = mmc_priv(mmc); u8 clk, setup, pwr; DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", - ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, - ios->vdd, ios->bus_width); + ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, + ios->vdd, ios->bus_width); spin_lock_bh(&host->lock); @@ -1004,8 +962,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) * Only write to the clock register when * there is an actual change. */ - if (clk != host->clk) - { + if (clk != host->clk) { wbsd_write_index(host, WBSD_IDX_CLK, clk); host->clk = clk; } @@ -1013,8 +970,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) /* * Power up card. */ - if (ios->power_mode != MMC_POWER_OFF) - { + if (ios->power_mode != MMC_POWER_OFF) { pwr = inb(host->base + WBSD_CSR); pwr &= ~WBSD_POWER_N; outb(pwr, host->base + WBSD_CSR); @@ -1026,23 +982,19 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) * that needs to be disabled. */ setup = wbsd_read_index(host, WBSD_IDX_SETUP); - if (ios->chip_select == MMC_CS_HIGH) - { + if (ios->chip_select == MMC_CS_HIGH) { BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1); setup |= WBSD_DAT3_H; host->flags |= WBSD_FIGNORE_DETECT; - } - else - { - if (setup & WBSD_DAT3_H) - { + } else { + if (setup & WBSD_DAT3_H) { setup &= ~WBSD_DAT3_H; /* * We cannot resume card detection immediatly * because of capacitance and delays in the chip. */ - mod_timer(&host->ignore_timer, jiffies + HZ/100); + mod_timer(&host->ignore_timer, jiffies + HZ / 100); } } wbsd_write_index(host, WBSD_IDX_SETUP, setup); @@ -1056,9 +1008,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) spin_unlock_bh(&host->lock); } -static int wbsd_get_ro(struct mmc_host* mmc) +static int wbsd_get_ro(struct mmc_host *mmc) { - struct wbsd_host* host = mmc_priv(mmc); + struct wbsd_host *host = mmc_priv(mmc); u8 csr; spin_lock_bh(&host->lock); @@ -1096,7 +1048,7 @@ static struct mmc_host_ops wbsd_ops = { static void wbsd_reset_ignore(unsigned long data) { - struct wbsd_host *host = (struct wbsd_host*)data; + struct wbsd_host *host = (struct wbsd_host *)data; BUG_ON(host == NULL); @@ -1119,7 +1071,7 @@ static void wbsd_reset_ignore(unsigned long data) * Tasklets */ -static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host) +static inline struct mmc_data *wbsd_get_data(struct wbsd_host *host) { WARN_ON(!host->mrq); if (!host->mrq) @@ -1138,14 +1090,13 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host) static void wbsd_tasklet_card(unsigned long param) { - struct wbsd_host* host = (struct wbsd_host*)param; + struct wbsd_host *host = (struct wbsd_host *)param; u8 csr; int delay = -1; spin_lock(&host->lock); - if (host->flags & WBSD_FIGNORE_DETECT) - { + if (host->flags & WBSD_FIGNORE_DETECT) { spin_unlock(&host->lock); return; } @@ -1153,23 +1104,18 @@ static void wbsd_tasklet_card(unsigned long param) csr = inb(host->base + WBSD_CSR); WARN_ON(csr == 0xff); - if (csr & WBSD_CARDPRESENT) - { - if (!(host->flags & WBSD_FCARD_PRESENT)) - { + if (csr & WBSD_CARDPRESENT) { + if (!(host->flags & WBSD_FCARD_PRESENT)) { DBG("Card inserted\n"); host->flags |= WBSD_FCARD_PRESENT; delay = 500; } - } - else if (host->flags & WBSD_FCARD_PRESENT) - { + } else if (host->flags & WBSD_FCARD_PRESENT) { DBG("Card removed\n"); host->flags &= ~WBSD_FCARD_PRESENT; - if (host->mrq) - { + if (host->mrq) { printk(KERN_ERR "%s: Card removed during transfer!\n", mmc_hostname(host->mmc)); wbsd_reset(host); @@ -1193,8 +1139,8 @@ static void wbsd_tasklet_card(unsigned long param) static void wbsd_tasklet_fifo(unsigned long param) { - struct wbsd_host* host = (struct wbsd_host*)param; - struct mmc_data* data; + struct wbsd_host *host = (struct wbsd_host *)param; + struct mmc_data *data; spin_lock(&host->lock); @@ -1213,8 +1159,7 @@ static void wbsd_tasklet_fifo(unsigned long param) /* * Done? */ - if (host->size == data->bytes_xfered) - { + if (host->size == data->bytes_xfered) { wbsd_write_index(host, WBSD_IDX_FIFOEN, 0); tasklet_schedule(&host->finish_tasklet); } @@ -1225,8 +1170,8 @@ end: static void wbsd_tasklet_crc(unsigned long param) { - struct wbsd_host* host = (struct wbsd_host*)param; - struct mmc_data* data; + struct wbsd_host *host = (struct wbsd_host *)param; + struct mmc_data *data; spin_lock(&host->lock); @@ -1249,8 +1194,8 @@ end: static void wbsd_tasklet_timeout(unsigned long param) { - struct wbsd_host* host = (struct wbsd_host*)param; - struct mmc_data* data; + struct wbsd_host *host = (struct wbsd_host *)param; + struct mmc_data *data; spin_lock(&host->lock); @@ -1273,8 +1218,8 @@ end: static void wbsd_tasklet_finish(unsigned long param) { - struct wbsd_host* host = (struct wbsd_host*)param; - struct mmc_data* data; + struct wbsd_host *host = (struct wbsd_host *)param; + struct mmc_data *data; spin_lock(&host->lock); @@ -1294,14 +1239,13 @@ end: static void wbsd_tasklet_block(unsigned long param) { - struct wbsd_host* host = (struct wbsd_host*)param; - struct mmc_data* data; + struct wbsd_host *host = (struct wbsd_host *)param; + struct mmc_data *data; spin_lock(&host->lock); if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) != - WBSD_CRC_OK) - { + WBSD_CRC_OK) { data = wbsd_get_data(host); if (!data) goto end; @@ -1323,7 +1267,7 @@ end: static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs) { - struct wbsd_host* host = dev_id; + struct wbsd_host *host = dev_id; int isr; isr = inb(host->base + WBSD_ISR); @@ -1365,10 +1309,10 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs) * Allocate/free MMC structure. */ -static int __devinit wbsd_alloc_mmc(struct device* dev) +static int __devinit wbsd_alloc_mmc(struct device *dev) { - struct mmc_host* mmc; - struct wbsd_host* host; + struct mmc_host *mmc; + struct wbsd_host *host; /* * Allocate MMC structure. @@ -1388,7 +1332,7 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) mmc->ops = &wbsd_ops; mmc->f_min = 375000; mmc->f_max = 24000000; - mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->caps = MMC_CAP_4_BIT_DATA; spin_lock_init(&host->lock); @@ -1424,10 +1368,10 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) return 0; } -static void __devexit wbsd_free_mmc(struct device* dev) +static void __devexit wbsd_free_mmc(struct device *dev) { - struct mmc_host* mmc; - struct wbsd_host* host; + struct mmc_host *mmc; + struct wbsd_host *host; mmc = dev_get_drvdata(dev); if (!mmc) @@ -1447,7 +1391,7 @@ static void __devexit wbsd_free_mmc(struct device* dev) * Scan for known chip id:s */ -static int __devinit wbsd_scan(struct wbsd_host* host) +static int __devinit wbsd_scan(struct wbsd_host *host) { int i, j, k; int id; @@ -1477,16 +1421,14 @@ static int __devinit wbsd_scan(struct wbsd_host* host) wbsd_lock_config(host); for (k = 0; k < ARRAY_SIZE(valid_ids); k++) { - if (id == valid_ids[k]) - { + if (id == valid_ids[k]) { host->chip_id = id; return 0; } } - if (id != 0xFFFF) - { + if (id != 0xFFFF) { DBG("Unknown hardware (id %x) found at %x\n", id, config_ports[i]); } @@ -1505,7 +1447,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host) * Allocate/free io port ranges */ -static int __devinit wbsd_request_region(struct wbsd_host* host, int base) +static int __devinit wbsd_request_region(struct wbsd_host *host, int base) { if (io & 0x7) return -EINVAL; @@ -1518,7 +1460,7 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base) return 0; } -static void __devexit wbsd_release_regions(struct wbsd_host* host) +static void __devexit wbsd_release_regions(struct wbsd_host *host) { if (host->base) release_region(host->base, 8); @@ -1535,7 +1477,7 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host) * Allocate/free DMA port and buffer */ -static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) +static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma) { if (dma < 0) return; @@ -1579,8 +1521,8 @@ kfree: */ BUG_ON(1); - dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE, - DMA_BIDIRECTIONAL); + dma_unmap_single(host->mmc->dev, host->dma_addr, + WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); host->dma_addr = (dma_addr_t)NULL; kfree(host->dma_buffer); @@ -1594,11 +1536,12 @@ err: "Falling back on FIFO.\n", dma); } -static void __devexit wbsd_release_dma(struct wbsd_host* host) +static void __devexit wbsd_release_dma(struct wbsd_host *host) { - if (host->dma_addr) - dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE, - DMA_BIDIRECTIONAL); + if (host->dma_addr) { + dma_unmap_single(host->mmc->dev, host->dma_addr, + WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); + } kfree(host->dma_buffer); if (host->dma >= 0) free_dma(host->dma); @@ -1612,7 +1555,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host) * Allocate/free IRQ. */ -static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq) +static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq) { int ret; @@ -1629,17 +1572,23 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq) /* * Set up tasklets. */ - tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host); - tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned long)host); - tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host); - tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host); - tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host); - tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host); + tasklet_init(&host->card_tasklet, wbsd_tasklet_card, + (unsigned long)host); + tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, + (unsigned long)host); + tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, + (unsigned long)host); + tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, + (unsigned long)host); + tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, + (unsigned long)host); + tasklet_init(&host->block_tasklet, wbsd_tasklet_block, + (unsigned long)host); return 0; } -static void __devexit wbsd_release_irq(struct wbsd_host* host) +static void __devexit wbsd_release_irq(struct wbsd_host *host) { if (!host->irq) return; @@ -1660,7 +1609,7 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host) * Allocate all resources for the host. */ -static int __devinit wbsd_request_resources(struct wbsd_host* host, +static int __devinit wbsd_request_resources(struct wbsd_host *host, int base, int irq, int dma) { int ret; @@ -1691,7 +1640,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host, * Release all resources for the host. */ -static void __devexit wbsd_release_resources(struct wbsd_host* host) +static void __devexit wbsd_release_resources(struct wbsd_host *host) { wbsd_release_dma(host); wbsd_release_irq(host); @@ -1702,7 +1651,7 @@ static void __devexit wbsd_release_resources(struct wbsd_host* host) * Configure the resources the chip should use. */ -static void wbsd_chip_config(struct wbsd_host* host) +static void wbsd_chip_config(struct wbsd_host *host) { wbsd_unlock_config(host); @@ -1746,7 +1695,7 @@ static void wbsd_chip_config(struct wbsd_host* host) * Check that configured resources are correct. */ -static int wbsd_chip_validate(struct wbsd_host* host) +static int wbsd_chip_validate(struct wbsd_host *host) { int base, irq, dma; @@ -1786,7 +1735,7 @@ static int wbsd_chip_validate(struct wbsd_host* host) * Powers down the SD function */ -static void wbsd_chip_poweroff(struct wbsd_host* host) +static void wbsd_chip_poweroff(struct wbsd_host *host) { wbsd_unlock_config(host); @@ -1802,11 +1751,11 @@ static void wbsd_chip_poweroff(struct wbsd_host* host) * * \*****************************************************************************/ -static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, +static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma, int pnp) { - struct wbsd_host* host = NULL; - struct mmc_host* mmc = NULL; + struct wbsd_host *host = NULL; + struct mmc_host *mmc = NULL; int ret; ret = wbsd_alloc_mmc(dev); @@ -1820,16 +1769,12 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, * Scan for hardware. */ ret = wbsd_scan(host); - if (ret) - { - if (pnp && (ret == -ENODEV)) - { + if (ret) { + if (pnp && (ret == -ENODEV)) { printk(KERN_WARNING DRIVER_NAME ": Unable to confirm device presence. You may " "experience lock-ups.\n"); - } - else - { + } else { wbsd_free_mmc(dev); return ret; } @@ -1839,8 +1784,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, * Request resources. */ ret = wbsd_request_resources(host, io, irq, dma); - if (ret) - { + if (ret) { wbsd_release_resources(host); wbsd_free_mmc(dev); return ret; @@ -1849,18 +1793,15 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, /* * See if chip needs to be configured. */ - if (pnp) - { - if ((host->config != 0) && !wbsd_chip_validate(host)) - { + if (pnp) { + if ((host->config != 0) && !wbsd_chip_validate(host)) { printk(KERN_WARNING DRIVER_NAME ": PnP active but chip not configured! " "You probably have a buggy BIOS. " "Configuring chip manually.\n"); wbsd_chip_config(host); } - } - else + } else wbsd_chip_config(host); /* @@ -1868,8 +1809,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, * Not tested. */ #ifdef CONFIG_PM - if (host->config) - { + if (host->config) { wbsd_unlock_config(host); wbsd_write_config(host, WBSD_CONF_PME, 0xA0); wbsd_lock_config(host); @@ -1902,10 +1842,10 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, return 0; } -static void __devexit wbsd_shutdown(struct device* dev, int pnp) +static void __devexit wbsd_shutdown(struct device *dev, int pnp) { - struct mmc_host* mmc = dev_get_drvdata(dev); - struct wbsd_host* host; + struct mmc_host *mmc = dev_get_drvdata(dev); + struct wbsd_host *host; if (!mmc) return; @@ -1929,12 +1869,12 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp) * Non-PnP */ -static int __devinit wbsd_probe(struct platform_device* dev) +static int __devinit wbsd_probe(struct platform_device *dev) { return wbsd_init(&dev->dev, io, irq, dma, 0); } -static int __devexit wbsd_remove(struct platform_device* dev) +static int __devexit wbsd_remove(struct platform_device *dev) { wbsd_shutdown(&dev->dev, 0); @@ -1948,7 +1888,7 @@ static int __devexit wbsd_remove(struct platform_device* dev) #ifdef CONFIG_PNP static int __devinit -wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id) +wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id) { int io, irq, dma; @@ -1967,7 +1907,7 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id) return wbsd_init(&pnpdev->dev, io, irq, dma, 1); } -static void __devexit wbsd_pnp_remove(struct pnp_dev * dev) +static void __devexit wbsd_pnp_remove(struct pnp_dev *dev) { wbsd_shutdown(&dev->dev, 1); } @@ -1980,37 +1920,54 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev * dev) #ifdef CONFIG_PM -static int wbsd_suspend(struct platform_device *dev, pm_message_t state) +static int wbsd_suspend(struct wbsd_host *host, pm_message_t state) +{ + BUG_ON(host == NULL); + + return mmc_suspend_host(host->mmc, state); +} + +static int wbsd_resume(struct wbsd_host *host) +{ + BUG_ON(host == NULL); + + wbsd_init_device(host); + + return mmc_resume_host(host->mmc); +} + +static int wbsd_platform_suspend(struct platform_device *dev, + pm_message_t state) { struct mmc_host *mmc = platform_get_drvdata(dev); struct wbsd_host *host; int ret; - if (!mmc) + if (mmc == NULL) return 0; - DBG("Suspending...\n"); - - ret = mmc_suspend_host(mmc, state); - if (!ret) - return ret; + DBGF("Suspending...\n"); host = mmc_priv(mmc); + ret = wbsd_suspend(host, state); + if (ret) + return ret; + wbsd_chip_poweroff(host); return 0; } -static int wbsd_resume(struct platform_device *dev) +static int wbsd_platform_resume(struct platform_device *dev) { struct mmc_host *mmc = platform_get_drvdata(dev); struct wbsd_host *host; - if (!mmc) + if (mmc == NULL) return 0; - DBG("Resuming...\n"); + DBGF("Resuming...\n"); host = mmc_priv(mmc); @@ -2021,15 +1978,68 @@ static int wbsd_resume(struct platform_device *dev) */ mdelay(5); - wbsd_init_device(host); + return wbsd_resume(host); +} + +#ifdef CONFIG_PNP + +static int wbsd_pnp_suspend(struct pnp_dev *pnp_dev, pm_message_t state) +{ + struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev); + struct wbsd_host *host; + + if (mmc == NULL) + return 0; + + DBGF("Suspending...\n"); + + host = mmc_priv(mmc); + + return wbsd_suspend(host, state); +} + +static int wbsd_pnp_resume(struct pnp_dev *pnp_dev) +{ + struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev); + struct wbsd_host *host; + + if (mmc == NULL) + return 0; + + DBGF("Resuming...\n"); - return mmc_resume_host(mmc); + host = mmc_priv(mmc); + + /* + * See if chip needs to be configured. + */ + if (host->config != 0) { + if (!wbsd_chip_validate(host)) { + printk(KERN_WARNING DRIVER_NAME + ": PnP active but chip not configured! " + "You probably have a buggy BIOS. " + "Configuring chip manually.\n"); + wbsd_chip_config(host); + } + } + + /* + * Allow device to initialise itself properly. + */ + mdelay(5); + + return wbsd_resume(host); } +#endif /* CONFIG_PNP */ + #else /* CONFIG_PM */ -#define wbsd_suspend NULL -#define wbsd_resume NULL +#define wbsd_platform_suspend NULL +#define wbsd_platform_resume NULL + +#define wbsd_pnp_suspend NULL +#define wbsd_pnp_resume NULL #endif /* CONFIG_PM */ @@ -2039,8 +2049,8 @@ static struct platform_driver wbsd_driver = { .probe = wbsd_probe, .remove = __devexit_p(wbsd_remove), - .suspend = wbsd_suspend, - .resume = wbsd_resume, + .suspend = wbsd_platform_suspend, + .resume = wbsd_platform_resume, .driver = { .name = DRIVER_NAME, }, @@ -2053,6 +2063,9 @@ static struct pnp_driver wbsd_pnp_driver = { .id_table = pnp_dev_table, .probe = wbsd_pnp_probe, .remove = __devexit_p(wbsd_pnp_remove), + + .suspend = wbsd_pnp_suspend, + .resume = wbsd_pnp_resume, }; #endif /* CONFIG_PNP */ @@ -2072,31 +2085,26 @@ static int __init wbsd_drv_init(void) #ifdef CONFIG_PNP - if (!nopnp) - { + if (!nopnp) { result = pnp_register_driver(&wbsd_pnp_driver); if (result < 0) return result; } - #endif /* CONFIG_PNP */ - if (nopnp) - { + if (nopnp) { result = platform_driver_register(&wbsd_driver); if (result < 0) return result; wbsd_device = platform_device_alloc(DRIVER_NAME, -1); - if (!wbsd_device) - { + if (!wbsd_device) { platform_driver_unregister(&wbsd_driver); return -ENOMEM; } result = platform_device_add(wbsd_device); - if (result) - { + if (result) { platform_device_put(wbsd_device); platform_driver_unregister(&wbsd_driver); return result; @@ -2115,8 +2123,7 @@ static void __exit wbsd_drv_exit(void) #endif /* CONFIG_PNP */ - if (nopnp) - { + if (nopnp) { platform_device_unregister(wbsd_device); platform_driver_unregister(&wbsd_driver); diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index b9b77cf39a18..7abd7fee0dda 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -473,14 +473,6 @@ config MTD_IXP2000 IXDP425 and Coyote. If you have an IXP2000 based board and would like to use the flash chips on it, say 'Y'. -config MTD_EPXA10DB - tristate "CFI Flash device mapped on Epxa10db" - depends on MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT - help - This enables support for the flash devices on the Altera - Excalibur XA10 Development Board. If you are building a kernel - for on of these boards then you should say 'Y' otherwise say 'N'. - config MTD_FORTUNET tristate "CFI Flash device mapped on the FortuNet board" depends on MTD_CFI && MTD_PARTITIONS && SA1100_FORTUNET diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 2f7e254912f0..ab71f172eb77 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o obj-$(CONFIG_MTD_DC21285) += dc21285.o obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o -obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o obj-$(CONFIG_MTD_IQ80310) += iq80310.o obj-$(CONFIG_MTD_L440GX) += l440gx.o obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c deleted file mode 100644 index 265b079fe934..000000000000 --- a/drivers/mtd/maps/epxa10db-flash.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Flash memory access on EPXA based devices - * - * (C) 2000 Nicolas Pitre <nico@cam.org> - * Copyright (C) 2001 Altera Corporation - * Copyright (C) 2001 Red Hat, Inc. - * - * $Id: epxa10db-flash.c,v 1.15 2005/11/07 11:14:27 gleixner Exp $ - * - * 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/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> - -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#include <linux/mtd/partitions.h> - -#include <asm/io.h> -#include <asm/hardware.h> - -#ifdef CONFIG_EPXA10DB -#define BOARD_NAME "EPXA10DB" -#else -#define BOARD_NAME "EPXA1DB" -#endif - -static int nr_parts = 0; -static struct mtd_partition *parts; - -static struct mtd_info *mymtd; - -static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts); - - -static struct map_info epxa_map = { - .name = "EPXA flash", - .size = FLASH_SIZE, - .bankwidth = 2, - .phys = FLASH_START, -}; - -static const char *probes[] = { "RedBoot", "afs", NULL }; - -static int __init epxa_mtd_init(void) -{ - int i; - - printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START); - - epxa_map.virt = ioremap(FLASH_START, FLASH_SIZE); - if (!epxa_map.virt) { - printk("Failed to ioremap %s flash\n",BOARD_NAME); - return -EIO; - } - simple_map_init(&epxa_map); - - mymtd = do_map_probe("cfi_probe", &epxa_map); - if (!mymtd) { - iounmap((void *)epxa_map.virt); - return -ENXIO; - } - - mymtd->owner = THIS_MODULE; - - /* Unlock the flash device. */ - if(mymtd->unlock){ - for (i=0; i<mymtd->numeraseregions;i++){ - int j; - for(j=0;j<mymtd->eraseregions[i].numblocks;j++){ - mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize); - } - } - } - -#ifdef CONFIG_MTD_PARTITIONS - nr_parts = parse_mtd_partitions(mymtd, probes, &parts, 0); - - if (nr_parts > 0) { - add_mtd_partitions(mymtd, parts, nr_parts); - return 0; - } -#endif - /* No recognised partitioning schemes found - use defaults */ - nr_parts = epxa_default_partitions(mymtd, &parts); - if (nr_parts > 0) { - add_mtd_partitions(mymtd, parts, nr_parts); - return 0; - } - - /* If all else fails... */ - add_mtd_device(mymtd); - return 0; -} - -static void __exit epxa_mtd_cleanup(void) -{ - if (mymtd) { - if (nr_parts) - del_mtd_partitions(mymtd); - else - del_mtd_device(mymtd); - map_destroy(mymtd); - } - if (epxa_map.virt) { - iounmap((void *)epxa_map.virt); - epxa_map.virt = 0; - } -} - - -/* - * This will do for now, once we decide which bootldr we're finally - * going to use then we'll remove this function and do it properly - * - * Partions are currently (as offsets from base of flash): - * 0x00000000 - 0x003FFFFF - bootloader (!) - * 0x00400000 - 0x00FFFFFF - Flashdisk - */ - -static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts) -{ - struct mtd_partition *parts; - int ret, i; - int npartitions = 0; - char *names; - const char *name = "jffs"; - - printk("Using default partitions for %s\n",BOARD_NAME); - npartitions=1; - parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL); - memzero(parts,npartitions*sizeof(*parts)+strlen(name)); - if (!parts) { - ret = -ENOMEM; - goto out; - } - i=0; - names = (char *)&parts[npartitions]; - parts[i].name = names; - names += strlen(name) + 1; - strcpy(parts[i].name, name); - -#ifdef CONFIG_EPXA10DB - parts[i].size = FLASH_SIZE-0x00400000; - parts[i].offset = 0x00400000; -#else - parts[i].size = FLASH_SIZE-0x00180000; - parts[i].offset = 0x00180000; -#endif - - out: - *pparts = parts; - return npartitions; -} - - -module_init(epxa_mtd_init); -module_exit(epxa_mtd_cleanup); - -MODULE_AUTHOR("Clive Davies"); -MODULE_DESCRIPTION("Altera epxa mtd flash map"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 733bc25b2bf9..4959800a18d7 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -27,6 +27,19 @@ config NETDEVICES # that for each of the symbols. if NETDEVICES +config IFB + tristate "Intermediate Functional Block support" + depends on NET_CLS_ACT + ---help--- + This is an intermidiate driver that allows sharing of + resources. + To compile this driver as a module, choose M here: the module + will be called ifb. If you want to use more than one ifb + device at a time, you need to compile this driver as a module. + Instead of 'ifb', the devices will then be called 'ifb0', + 'ifb1' etc. + Look at the iproute2 documentation directory for usage etc + config DUMMY tristate "Dummy net driver support" ---help--- diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b74a7cb5bae6..00e72b12fb92 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -125,6 +125,7 @@ ifeq ($(CONFIG_SLIP_COMPRESSED),y) endif obj-$(CONFIG_DUMMY) += dummy.o +obj-$(CONFIG_IFB) += ifb.o obj-$(CONFIG_DE600) += de600.o obj-$(CONFIG_DE620) += de620.o obj-$(CONFIG_LANCE) += lance.o diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig index 470364deded0..625184b65e38 100644 --- a/drivers/net/arm/Kconfig +++ b/drivers/net/arm/Kconfig @@ -31,16 +31,3 @@ config ARM_ETHERH help If you have an Acorn system with one of these network cards, you should say Y to this option if you wish to use it with Linux. - -config ARM_ETHER00 - tristate "Altera Ether00 support" - depends on NET_ETHERNET && ARM && ARCH_CAMELOT - help - This is the driver for Altera's ether00 ethernet mac IP core. Say - Y here if you want to build support for this into the kernel. It - is also available as a module (say M here) that can be inserted/ - removed from the kernel at the same time as the PLD is configured. - If this driver is running on an epxa10 development board then it - will generate a suitable hw address based on the board serial - number (MTD support is required for this). Otherwise you will - need to set a suitable hw address using ifconfig. diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile index b0d706834d89..bc263edf06a7 100644 --- a/drivers/net/arm/Makefile +++ b/drivers/net/arm/Makefile @@ -4,7 +4,6 @@ # obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o -obj-$(CONFIG_ARM_ETHER00) += ether00.o obj-$(CONFIG_ARM_ETHERH) += etherh.o obj-$(CONFIG_ARM_ETHER3) += ether3.o obj-$(CONFIG_ARM_ETHER1) += ether1.o diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 877891a29aaa..53e3afc1b7b7 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -668,9 +668,8 @@ static void __init am79c961_banner(void) printk(KERN_INFO "%s", version); } -static int __init am79c961_probe(struct device *_dev) +static int __init am79c961_probe(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(_dev); struct resource *res; struct net_device *dev; struct dev_priv *priv; @@ -758,15 +757,16 @@ out: return ret; } -static struct device_driver am79c961_driver = { - .name = "am79c961", - .bus = &platform_bus_type, +static struct platform_driver am79c961_driver = { .probe = am79c961_probe, + .driver = { + .name = "am79c961", + }, }; static int __init am79c961_init(void) { - return driver_register(&am79c961_driver); + return platform_driver_register(&am79c961_driver); } __initcall(am79c961_init); diff --git a/drivers/net/arm/ether00.c b/drivers/net/arm/ether00.c deleted file mode 100644 index 4f1f4e31bda5..000000000000 --- a/drivers/net/arm/ether00.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * drivers/net/ether00.c - * - * Copyright (C) 2001 Altera Corporation - * - * 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 - */ - -/* includes */ -#include <linux/config.h> -#include <linux/pci.h> -#include <linux/sched.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <linux/etherdevice.h> -#include <linux/module.h> -#include <linux/tqueue.h> -#include <linux/mtd/mtd.h> -#include <linux/pld/pld_hotswap.h> -#include <asm/arch/excalibur.h> -#include <asm/arch/hardware.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/sizes.h> - -#include <asm/arch/ether00.h> -#include <asm/arch/tdkphy.h> - - -MODULE_AUTHOR("Clive Davies"); -MODULE_DESCRIPTION("Altera Ether00 IP core driver"); -MODULE_LICENSE("GPL"); - -#define PKT_BUF_SZ 1540 /* Size of each rx buffer */ -#define ETH_NR 4 /* Number of MACs this driver supports */ - -#define DEBUG(x) - -#define __dma_va(x) (unsigned int)((unsigned int)priv->dma_data+(((unsigned int)(x))&(EXC_SPSRAM_BLOCK0_SIZE-1))) -#define __dma_pa(x) (unsigned int)(EXC_SPSRAM_BLOCK0_BASE+(((unsigned int)(x))-(unsigned int)priv->dma_data)) - -#define ETHER00_BASE 0 -#define ETHER00_TYPE -#define ETHER00_NAME "ether00" -#define MAC_REG_SIZE 0x400 /* size of MAC register area */ - - - -/* typedefs */ - -/* The definition of the driver control structure */ - -#define RX_NUM_BUFF 10 -#define RX_NUM_FDESC 10 -#define TX_NUM_FDESC 10 - -struct tx_fda_ent{ - FDA_DESC fd; - BUF_DESC bd; - BUF_DESC pad; -}; -struct rx_fda_ent{ - FDA_DESC fd; - BUF_DESC bd; - BUF_DESC pad; -}; -struct rx_blist_ent{ - FDA_DESC fd; - BUF_DESC bd; - BUF_DESC pad; -}; -struct net_priv -{ - struct net_device_stats stats; - struct sk_buff* skb; - void* dma_data; - struct rx_blist_ent* rx_blist_vp; - struct rx_fda_ent* rx_fda_ptr; - struct tx_fda_ent* tx_fdalist_vp; - struct tq_struct tq_memupdate; - unsigned char memupdate_scheduled; - unsigned char rx_disabled; - unsigned char queue_stopped; - spinlock_t rx_lock; -}; - -static const char vendor_id[2]={0x07,0xed}; - -#ifdef ETHER00_DEBUG - -/* Dump (most) registers for debugging puposes */ - -static void dump_regs(struct net_device *dev){ - struct net_priv* priv=dev->priv; - unsigned int* i; - - printk("\n RX free descriptor area:\n"); - - for(i=(unsigned int*)priv->rx_fda_ptr; - i<((unsigned int*)(priv->rx_fda_ptr+RX_NUM_FDESC));){ - printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3)); - i+=4; - } - - printk("\n RX buffer list:\n"); - - for(i=(unsigned int*)priv->rx_blist_vp; - i<((unsigned int*)(priv->rx_blist_vp+RX_NUM_BUFF));){ - printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3)); - i+=4; - } - - printk("\n TX frame descriptor list:\n"); - - for(i=(unsigned int*)priv->tx_fdalist_vp; - i<((unsigned int*)(priv->tx_fdalist_vp+TX_NUM_FDESC));){ - printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3)); - i+=4; - } - - printk("\ndma ctl=%#x\n",readw(ETHER_DMA_CTL(dev->base_addr))); - printk("txfrmptr=%#x\n",readw(ETHER_TXFRMPTR(dev->base_addr))); - printk("txthrsh=%#x\n",readw(ETHER_TXTHRSH(dev->base_addr))); - printk("txpollctr=%#x\n",readw(ETHER_TXPOLLCTR(dev->base_addr))); - printk("blfrmptr=%#x\n",readw(ETHER_BLFRMPTR(dev->base_addr))); - printk("rxfragsize=%#x\n",readw(ETHER_RXFRAGSIZE(dev->base_addr))); - printk("tx_int_en=%#x\n",readw(ETHER_INT_EN(dev->base_addr))); - printk("fda_bas=%#x\n",readw(ETHER_FDA_BAS(dev->base_addr))); - printk("fda_lim=%#x\n",readw(ETHER_FDA_LIM(dev->base_addr))); - printk("int_src=%#x\n",readw(ETHER_INT_SRC(dev->base_addr))); - printk("pausecnt=%#x\n",readw(ETHER_PAUSECNT(dev->base_addr))); - printk("rempaucnt=%#x\n",readw(ETHER_REMPAUCNT(dev->base_addr))); - printk("txconfrmstat=%#x\n",readw(ETHER_TXCONFRMSTAT(dev->base_addr))); - printk("mac_ctl=%#x\n",readw(ETHER_MAC_CTL(dev->base_addr))); - printk("arc_ctl=%#x\n",readw(ETHER_ARC_CTL(dev->base_addr))); - printk("tx_ctl=%#x\n",readw(ETHER_TX_CTL(dev->base_addr))); -} -#endif /* ETHER00_DEBUG */ - - -static int ether00_write_phy(struct net_device *dev, short address, short value) -{ - volatile int count = 1024; - writew(value,ETHER_MD_DATA(dev->base_addr)); - writew( ETHER_MD_CA_BUSY_MSK | - ETHER_MD_CA_WR_MSK | - (address & ETHER_MD_CA_ADDR_MSK), - ETHER_MD_CA(dev->base_addr)); - - /* Wait for the command to complete */ - while((readw(ETHER_MD_CA(dev->base_addr)) & ETHER_MD_CA_BUSY_MSK)&&count){ - count--; - } - if (!count){ - printk("Write to phy failed, addr=%#x, data=%#x\n",address, value); - return -EIO; - } - return 0; -} - -static int ether00_read_phy(struct net_device *dev, short address) -{ - volatile int count = 1024; - writew( ETHER_MD_CA_BUSY_MSK | - (address & ETHER_MD_CA_ADDR_MSK), - ETHER_MD_CA(dev->base_addr)); - - /* Wait for the command to complete */ - while((readw(ETHER_MD_CA(dev->base_addr)) & ETHER_MD_CA_BUSY_MSK)&&count){ - count--; - } - if (!count){ - printk(KERN_WARNING "Read from phy timed out\n"); - return -EIO; - } - return readw(ETHER_MD_DATA(dev->base_addr)); -} - -static void ether00_phy_int(int irq_num, void* dev_id, struct pt_regs* regs) -{ - struct net_device* dev=dev_id; - int irq_status; - - irq_status=ether00_read_phy(dev, PHY_IRQ_CONTROL); - - if(irq_status & PHY_IRQ_CONTROL_ANEG_COMP_INT_MSK){ - /* - * Autonegotiation complete on epxa10db. The mac doesn't - * twig if we're in full duplex so we need to check the - * phy status register and configure the mac accordingly - */ - if(ether00_read_phy(dev, PHY_STATUS)&(PHY_STATUS_10T_F_MSK|PHY_STATUS_100_X_F_MSK)){ - int tmp; - tmp=readl(ETHER_MAC_CTL(dev->base_addr)); - writel(tmp|ETHER_MAC_CTL_FULLDUP_MSK,ETHER_MAC_CTL(dev->base_addr)); - } - } - - if(irq_status&PHY_IRQ_CONTROL_LS_CHG_INT_MSK){ - - if(ether00_read_phy(dev, PHY_STATUS)& PHY_STATUS_LINK_MSK){ - /* Link is up */ - netif_carrier_on(dev); - //printk("Carrier on\n"); - }else{ - netif_carrier_off(dev); - //printk("Carrier off\n"); - - } - } - -} - -static void setup_blist_entry(struct sk_buff* skb,struct rx_blist_ent* blist_ent_ptr){ - /* Make the buffer consistent with the cache as the mac is going to write - * directly into it*/ - blist_ent_ptr->fd.FDSystem=(unsigned int)skb; - blist_ent_ptr->bd.BuffData=(char*)__pa(skb->data); - consistent_sync(skb->data,PKT_BUF_SZ,PCI_DMA_FROMDEVICE); - /* align IP on 16 Byte (DMA_CTL set to skip 2 bytes) */ - skb_reserve(skb,2); - blist_ent_ptr->bd.BuffLength=PKT_BUF_SZ-2; - blist_ent_ptr->fd.FDLength=1; - blist_ent_ptr->fd.FDCtl=FDCTL_COWNSFD_MSK; - blist_ent_ptr->bd.BDCtl=BDCTL_COWNSBD_MSK; -} - - -static int ether00_mem_init(struct net_device* dev) -{ - struct net_priv* priv=dev->priv; - struct tx_fda_ent *tx_fd_ptr,*tx_end_ptr; - struct rx_blist_ent* blist_ent_ptr; - int i; - - /* - * Grab a block of on chip SRAM to contain the control stuctures for - * the ethernet MAC. This uncached becuase it needs to be accesses by both - * bus masters (cpu + mac). However, it shouldn't matter too much in terms - * of speed as its on chip memory - */ - priv->dma_data=ioremap_nocache(EXC_SPSRAM_BLOCK0_BASE,EXC_SPSRAM_BLOCK0_SIZE ); - if (!priv->dma_data) - return -ENOMEM; - - priv->rx_fda_ptr=(struct rx_fda_ent*)priv->dma_data; - /* - * Now share it out amongst the Frame descriptors and the buffer list - */ - priv->rx_blist_vp=(struct rx_blist_ent*)((unsigned int)priv->dma_data+RX_NUM_FDESC*sizeof(struct rx_fda_ent)); - - /* - *Initalise the FDA list - */ - /* set ownership to the controller */ - memset(priv->rx_fda_ptr,0x80,RX_NUM_FDESC*sizeof(struct rx_fda_ent)); - - /* - *Initialise the buffer list - */ - blist_ent_ptr=priv->rx_blist_vp; - i=0; - while(blist_ent_ptr<(priv->rx_blist_vp+RX_NUM_BUFF)){ - struct sk_buff *skb; - blist_ent_ptr->fd.FDLength=1; - skb=dev_alloc_skb(PKT_BUF_SZ); - if(skb){ - setup_blist_entry(skb,blist_ent_ptr); - blist_ent_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(blist_ent_ptr+1); - blist_ent_ptr->bd.BDStat=i++; - blist_ent_ptr++; - } - else - { - printk("Failed to initalise buffer list\n"); - } - - } - blist_ent_ptr--; - blist_ent_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(priv->rx_blist_vp); - - priv->tx_fdalist_vp=(struct tx_fda_ent*)(priv->rx_blist_vp+RX_NUM_BUFF); - - /* Initialise the buffers to be a circular list. The mac will then go poll - * the list until it finds a frame ready to transmit */ - tx_end_ptr=priv->tx_fdalist_vp+TX_NUM_FDESC; - for(tx_fd_ptr=priv->tx_fdalist_vp;tx_fd_ptr<tx_end_ptr;tx_fd_ptr++){ - tx_fd_ptr->fd.FDNext=(FDA_DESC*)__dma_pa((tx_fd_ptr+1)); - tx_fd_ptr->fd.FDCtl=1; - tx_fd_ptr->fd.FDStat=0; - tx_fd_ptr->fd.FDLength=1; - - } - /* Change the last FDNext pointer to make a circular list */ - tx_fd_ptr--; - tx_fd_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(priv->tx_fdalist_vp); - - /* Point the device at the chain of Rx and Tx Buffers */ - writel((unsigned int)__dma_pa(priv->rx_fda_ptr),ETHER_FDA_BAS(dev->base_addr)); - writel((RX_NUM_FDESC-1)*sizeof(struct rx_fda_ent),ETHER_FDA_LIM(dev->base_addr)); - writel((unsigned int)__dma_pa(priv->rx_blist_vp),ETHER_BLFRMPTR(dev->base_addr)); - - writel((unsigned int)__dma_pa(priv->tx_fdalist_vp),ETHER_TXFRMPTR(dev->base_addr)); - - return 0; -} - - -void ether00_mem_update(void* dev_id) -{ - struct net_device* dev=dev_id; - struct net_priv* priv=dev->priv; - struct sk_buff* skb; - struct tx_fda_ent *fda_ptr=priv->tx_fdalist_vp; - struct rx_blist_ent* blist_ent_ptr; - unsigned long flags; - - priv->tq_memupdate.sync=0; - //priv->tq_memupdate.list= - priv->memupdate_scheduled=0; - - /* Transmit interrupt */ - while(fda_ptr<(priv->tx_fdalist_vp+TX_NUM_FDESC)){ - if(!(FDCTL_COWNSFD_MSK&fda_ptr->fd.FDCtl) && (ETHER_TX_STAT_COMP_MSK&fda_ptr->fd.FDStat)){ - priv->stats.tx_packets++; - priv->stats.tx_bytes+=fda_ptr->bd.BuffLength; - skb=(struct sk_buff*)fda_ptr->fd.FDSystem; - //printk("%d:txcln:fda=%#x skb=%#x\n",jiffies,fda_ptr,skb); - dev_kfree_skb(skb); - fda_ptr->fd.FDSystem=0; - fda_ptr->fd.FDStat=0; - fda_ptr->fd.FDCtl=0; - } - fda_ptr++; - } - /* Fill in any missing buffers from the received queue */ - spin_lock_irqsave(&priv->rx_lock,flags); - blist_ent_ptr=priv->rx_blist_vp; - while(blist_ent_ptr<(priv->rx_blist_vp+RX_NUM_BUFF)){ - /* fd.FDSystem of 0 indicates we failed to allocate the buffer in the ISR */ - if(!blist_ent_ptr->fd.FDSystem){ - struct sk_buff *skb; - skb=dev_alloc_skb(PKT_BUF_SZ); - blist_ent_ptr->fd.FDSystem=(unsigned int)skb; - if(skb){ - setup_blist_entry(skb,blist_ent_ptr); - } - else - { - break; - } - } - blist_ent_ptr++; - } - spin_unlock_irqrestore(&priv->rx_lock,flags); - if(priv->queue_stopped){ - //printk("%d:cln:start q\n",jiffies); - netif_start_queue(dev); - } - if(priv->rx_disabled){ - //printk("%d:enable_irq\n",jiffies); - priv->rx_disabled=0; - writel(ETHER_RX_CTL_RXEN_MSK,ETHER_RX_CTL(dev->base_addr)); - - } -} - - -static void ether00_int( int irq_num, void* dev_id, struct pt_regs* regs) -{ - struct net_device* dev=dev_id; - struct net_priv* priv=dev->priv; - - unsigned int interruptValue; - - interruptValue=readl(ETHER_INT_SRC(dev->base_addr)); - - //printk("INT_SRC=%x\n",interruptValue); - - if(!(readl(ETHER_INT_SRC(dev->base_addr)) & ETHER_INT_SRC_IRQ_MSK)) - { - return; /* Interrupt wasn't caused by us!! */ - } - - if(readl(ETHER_INT_SRC(dev->base_addr))& - (ETHER_INT_SRC_INTMACRX_MSK | - ETHER_INT_SRC_FDAEX_MSK | - ETHER_INT_SRC_BLEX_MSK)) { - struct rx_blist_ent* blist_ent_ptr; - struct rx_fda_ent* fda_ent_ptr; - struct sk_buff* skb; - - fda_ent_ptr=priv->rx_fda_ptr; - spin_lock(&priv->rx_lock); - while(fda_ent_ptr<(priv->rx_fda_ptr+RX_NUM_FDESC)){ - int result; - - if(!(fda_ent_ptr->fd.FDCtl&FDCTL_COWNSFD_MSK)) - { - /* This frame is ready for processing */ - /*find the corresponding buffer in the bufferlist */ - blist_ent_ptr=priv->rx_blist_vp+fda_ent_ptr->bd.BDStat; - skb=(struct sk_buff*)blist_ent_ptr->fd.FDSystem; - - /* Pass this skb up the stack */ - skb->dev=dev; - skb_put(skb,fda_ent_ptr->fd.FDLength); - skb->protocol=eth_type_trans(skb,dev); - skb->ip_summed=CHECKSUM_UNNECESSARY; - result=netif_rx(skb); - /* Update statistics */ - priv->stats.rx_packets++; - priv->stats.rx_bytes+=fda_ent_ptr->fd.FDLength; - - /* Free the FDA entry */ - fda_ent_ptr->bd.BDStat=0xff; - fda_ent_ptr->fd.FDCtl=FDCTL_COWNSFD_MSK; - - /* Allocate a new skb and point the bd entry to it */ - blist_ent_ptr->fd.FDSystem=0; - skb=dev_alloc_skb(PKT_BUF_SZ); - //printk("allocskb=%#x\n",skb); - if(skb){ - setup_blist_entry(skb,blist_ent_ptr); - - } - else if(!priv->memupdate_scheduled){ - int tmp; - /* There are no buffers at the moment, so schedule */ - /* the background task to sort this out */ - schedule_task(&priv->tq_memupdate); - priv->memupdate_scheduled=1; - printk(KERN_DEBUG "%s:No buffers",dev->name); - /* If this interrupt was due to a lack of buffers then - * we'd better stop the receiver too */ - if(interruptValueÐER_INT_SRC_BLEX_MSK){ - priv->rx_disabled=1; - tmp=readl(ETHER_INT_SRC(dev->base_addr)); - writel(tmp&~ETHER_RX_CTL_RXEN_MSK,ETHER_RX_CTL(dev->base_addr)); - printk(KERN_DEBUG "%s:Halting rx",dev->name); - } - - } - - } - fda_ent_ptr++; - } - spin_unlock(&priv->rx_lock); - - /* Clear the interrupts */ - writel(ETHER_INT_SRC_INTMACRX_MSK | ETHER_INT_SRC_FDAEX_MSK - | ETHER_INT_SRC_BLEX_MSK,ETHER_INT_SRC(dev->base_addr)); - - } - - if(readl(ETHER_INT_SRC(dev->base_addr))ÐER_INT_SRC_INTMACTX_MSK){ - - if(!priv->memupdate_scheduled){ - schedule_task(&priv->tq_memupdate); - priv->memupdate_scheduled=1; - } - /* Clear the interrupt */ - writel(ETHER_INT_SRC_INTMACTX_MSK,ETHER_INT_SRC(dev->base_addr)); - } - - if (readl(ETHER_INT_SRC(dev->base_addr)) & (ETHER_INT_SRC_SWINT_MSK| - ETHER_INT_SRC_INTEARNOT_MSK| - ETHER_INT_SRC_INTLINK_MSK| - ETHER_INT_SRC_INTEXBD_MSK| - ETHER_INT_SRC_INTTXCTLCMP_MSK)) - { - /* - * Not using any of these so they shouldn't happen - * - * In the cased of INTEXBD - if you allocate more - * than 28 decsriptors you may need to think about this - */ - printk("Not using this interrupt\n"); - } - - if (readl(ETHER_INT_SRC(dev->base_addr)) & - (ETHER_INT_SRC_INTSBUS_MSK | - ETHER_INT_SRC_INTNRABT_MSK - |ETHER_INT_SRC_DMPARERR_MSK)) - { - /* - * Hardware errors, we can either ignore them and hope they go away - *or reset the device, I'll try the first for now to see if they happen - */ - printk("Hardware error\n"); - } -} - -static void ether00_setup_ethernet_address(struct net_device* dev) -{ - int tmp; - - dev->addr_len=6; - writew(0,ETHER_ARC_ADR(dev->base_addr)); - writel((dev->dev_addr[0]<<24) | - (dev->dev_addr[1]<<16) | - (dev->dev_addr[2]<<8) | - dev->dev_addr[3], - ETHER_ARC_DATA(dev->base_addr)); - - writew(4,ETHER_ARC_ADR(dev->base_addr)); - tmp=readl(ETHER_ARC_DATA(dev->base_addr)); - tmp&=0xffff; - tmp|=(dev->dev_addr[4]<<24) | (dev->dev_addr[5]<<16); - writel(tmp, ETHER_ARC_DATA(dev->base_addr)); - /* Enable this entry in the ARC */ - - writel(1,ETHER_ARC_ENA(dev->base_addr)); - - return; -} - - -static void ether00_reset(struct net_device *dev) -{ - /* reset the controller */ - writew(ETHER_MAC_CTL_RESET_MSK,ETHER_MAC_CTL(dev->base_addr)); - - /* - * Make sure we're not going to send anything - */ - - writew(ETHER_TX_CTL_TXHALT_MSK,ETHER_TX_CTL(dev->base_addr)); - - /* - * Make sure we're not going to receive anything - */ - writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr)); - - /* - * Disable Interrupts for now, and set the burst size to 8 bytes - */ - - writel(ETHER_DMA_CTL_INTMASK_MSK | - ((8 << ETHER_DMA_CTL_DMBURST_OFST) & ETHER_DMA_CTL_DMBURST_MSK) - |(2<<ETHER_DMA_CTL_RXALIGN_OFST), - ETHER_DMA_CTL(dev->base_addr)); - - - /* - * Set TxThrsh - start transmitting a packet after 1514 - * bytes or when a packet is complete, whichever comes first - */ - writew(1514,ETHER_TXTHRSH(dev->base_addr)); - - /* - * Set TxPollCtr. Each cycle is - * 61.44 microseconds with a 33 MHz bus - */ - writew(1,ETHER_TXPOLLCTR(dev->base_addr)); - - /* - * Set Rx_Ctl - Turn off reception and let RxData turn it - * on later - */ - writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr)); - -} - - -static void ether00_set_multicast(struct net_device* dev) -{ - int count=dev->mc_count; - - /* Set promiscuous mode if it's asked for. */ - - if (dev->flags&IFF_PROMISC){ - - writew( ETHER_ARC_CTL_COMPEN_MSK | - ETHER_ARC_CTL_BROADACC_MSK | - ETHER_ARC_CTL_GROUPACC_MSK | - ETHER_ARC_CTL_STATIONACC_MSK, - ETHER_ARC_CTL(dev->base_addr)); - return; - } - - /* - * Get all multicast packets if required, or if there are too - * many addresses to fit in hardware - */ - if (dev->flags & IFF_ALLMULTI){ - writew( ETHER_ARC_CTL_COMPEN_MSK | - ETHER_ARC_CTL_GROUPACC_MSK | - ETHER_ARC_CTL_BROADACC_MSK, - ETHER_ARC_CTL(dev->base_addr)); - return; - } - if (dev->mc_count > (ETHER_ARC_SIZE - 1)){ - - printk(KERN_WARNING "Too many multicast addresses for hardware to filter - receiving all multicast packets\n"); - writew( ETHER_ARC_CTL_COMPEN_MSK | - ETHER_ARC_CTL_GROUPACC_MSK | - ETHER_ARC_CTL_BROADACC_MSK, - ETHER_ARC_CTL(dev->base_addr)); - return; - } - - if(dev->mc_count){ - struct dev_mc_list *mc_list_ent=dev->mc_list; - unsigned int temp,i; - DEBUG(printk("mc_count=%d mc_list=%#x\n",dev-> mc_count, dev->mc_list)); - DEBUG(printk("mc addr=%02#x%02x%02x%02x%02x%02x\n", - mc_list_ent->dmi_addr[5], - mc_list_ent->dmi_addr[4], - mc_list_ent->dmi_addr[3], - mc_list_ent->dmi_addr[2], - mc_list_ent->dmi_addr[1], - mc_list_ent->dmi_addr[0]);) - - /* - * The first 6 bytes are the MAC address, so - * don't change them! - */ - writew(4,ETHER_ARC_ADR(dev->base_addr)); - temp=readl(ETHER_ARC_DATA(dev->base_addr)); - temp&=0xffff0000; - - /* Disable the current multicast stuff */ - writel(1,ETHER_ARC_ENA(dev->base_addr)); - - for(;;){ - temp|=mc_list_ent->dmi_addr[1] | - mc_list_ent->dmi_addr[0]<<8; - writel(temp,ETHER_ARC_DATA(dev->base_addr)); - - i=readl(ETHER_ARC_ADR(dev->base_addr)); - writew(i+4,ETHER_ARC_ADR(dev->base_addr)); - - temp=mc_list_ent->dmi_addr[5]| - mc_list_ent->dmi_addr[4]<<8 | - mc_list_ent->dmi_addr[3]<<16 | - mc_list_ent->dmi_addr[2]<<24; - writel(temp,ETHER_ARC_DATA(dev->base_addr)); - - count--; - if(!mc_list_ent->next || !count){ - break; - } - DEBUG(printk("mc_list_next=%#x\n",mc_list_ent->next);) - mc_list_ent=mc_list_ent->next; - - - i=readl(ETHER_ARC_ADR(dev->base_addr)); - writel(i+4,ETHER_ARC_ADR(dev->base_addr)); - - temp=mc_list_ent->dmi_addr[3]| - mc_list_ent->dmi_addr[2]<<8 | - mc_list_ent->dmi_addr[1]<<16 | - mc_list_ent->dmi_addr[0]<<24; - writel(temp,ETHER_ARC_DATA(dev->base_addr)); - - i=readl(ETHER_ARC_ADR(dev->base_addr)); - writel(i+4,ETHER_ARC_ADR(dev->base_addr)); - - temp=mc_list_ent->dmi_addr[4]<<16 | - mc_list_ent->dmi_addr[5]<<24; - - writel(temp,ETHER_ARC_DATA(dev->base_addr)); - - count--; - if(!mc_list_ent->next || !count){ - break; - } - mc_list_ent=mc_list_ent->next; - } - - - if(count) - printk(KERN_WARNING "Multicast list size error\n"); - - - writew( ETHER_ARC_CTL_BROADACC_MSK| - ETHER_ARC_CTL_COMPEN_MSK, - ETHER_ARC_CTL(dev->base_addr)); - - } - - /* enable the active ARC enties */ - writew((1<<(count+2))-1,ETHER_ARC_ENA(dev->base_addr)); -} - - -static int ether00_open(struct net_device* dev) -{ - int result,tmp; - struct net_priv* priv; - - if (!is_valid_ether_addr(dev->dev_addr)) - return -EINVAL; - - /* Install interrupt handlers */ - result=request_irq(dev->irq,ether00_int,0,"ether00",dev); - if(result) - goto open_err1; - - result=request_irq(2,ether00_phy_int,0,"ether00_phy",dev); - if(result) - goto open_err2; - - ether00_reset(dev); - result=ether00_mem_init(dev); - if(result) - goto open_err3; - - - ether00_setup_ethernet_address(dev); - - ether00_set_multicast(dev); - - result=ether00_write_phy(dev,PHY_CONTROL, PHY_CONTROL_ANEGEN_MSK | PHY_CONTROL_RANEG_MSK); - if(result) - goto open_err4; - result=ether00_write_phy(dev,PHY_IRQ_CONTROL, PHY_IRQ_CONTROL_LS_CHG_IE_MSK | - PHY_IRQ_CONTROL_ANEG_COMP_IE_MSK); - if(result) - goto open_err4; - - /* Start the device enable interrupts */ - writew(ETHER_RX_CTL_RXEN_MSK -// | ETHER_RX_CTL_STRIPCRC_MSK - | ETHER_RX_CTL_ENGOOD_MSK - | ETHER_RX_CTL_ENRXPAR_MSK| ETHER_RX_CTL_ENLONGERR_MSK - | ETHER_RX_CTL_ENOVER_MSK| ETHER_RX_CTL_ENCRCERR_MSK, - ETHER_RX_CTL(dev->base_addr)); - - writew(ETHER_TX_CTL_TXEN_MSK| - ETHER_TX_CTL_ENEXDEFER_MSK| - ETHER_TX_CTL_ENLCARR_MSK| - ETHER_TX_CTL_ENEXCOLL_MSK| - ETHER_TX_CTL_ENLATECOLL_MSK| - ETHER_TX_CTL_ENTXPAR_MSK| - ETHER_TX_CTL_ENCOMP_MSK, - ETHER_TX_CTL(dev->base_addr)); - - tmp=readl(ETHER_DMA_CTL(dev->base_addr)); - writel(tmp&~ETHER_DMA_CTL_INTMASK_MSK,ETHER_DMA_CTL(dev->base_addr)); - - return 0; - - open_err4: - ether00_reset(dev); - open_err3: - free_irq(2,dev); - open_err2: - free_irq(dev->irq,dev); - open_err1: - return result; - -} - - -static int ether00_tx(struct sk_buff* skb, struct net_device* dev) -{ - struct net_priv *priv=dev->priv; - struct tx_fda_ent *fda_ptr; - int i; - - - /* - * Find an empty slot in which to stick the frame - */ - fda_ptr=(struct tx_fda_ent*)__dma_va(readl(ETHER_TXFRMPTR(dev->base_addr))); - i=0; - while(i<TX_NUM_FDESC){ - if (fda_ptr->fd.FDStat||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){ - fda_ptr =(struct tx_fda_ent*) __dma_va((struct tx_fda_ent*)fda_ptr->fd.FDNext); - } - else { - break; - } - i++; - } - - /* Write the skb data from the cache*/ - consistent_sync(skb->data,skb->len,PCI_DMA_TODEVICE); - fda_ptr->bd.BuffData=(char*)__pa(skb->data); - fda_ptr->bd.BuffLength=(unsigned short)skb->len; - /* Save the pointer to the skb for freeing later */ - fda_ptr->fd.FDSystem=(unsigned int)skb; - fda_ptr->fd.FDStat=0; - /* Pass ownership of the buffers to the controller */ - fda_ptr->fd.FDCtl=1; - fda_ptr->fd.FDCtl|=FDCTL_COWNSFD_MSK; - - /* If the next buffer in the list is full, stop the queue */ - fda_ptr=(struct tx_fda_ent*)__dma_va(fda_ptr->fd.FDNext); - if ((fda_ptr->fd.FDStat)||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){ - netif_stop_queue(dev); - priv->queue_stopped=1; - } - - return 0; -} - -static struct net_device_stats *ether00_stats(struct net_device* dev) -{ - struct net_priv *priv=dev->priv; - return &priv->stats; -} - - -static int ether00_stop(struct net_device* dev) -{ - struct net_priv *priv=dev->priv; - int tmp; - - /* Stop/disable the device. */ - tmp=readw(ETHER_RX_CTL(dev->base_addr)); - tmp&=~(ETHER_RX_CTL_RXEN_MSK | ETHER_RX_CTL_ENGOOD_MSK); - tmp|=ETHER_RX_CTL_RXHALT_MSK; - writew(tmp,ETHER_RX_CTL(dev->base_addr)); - - tmp=readl(ETHER_TX_CTL(dev->base_addr)); - tmp&=~ETHER_TX_CTL_TXEN_MSK; - tmp|=ETHER_TX_CTL_TXHALT_MSK; - writel(tmp,ETHER_TX_CTL(dev->base_addr)); - - /* Free up system resources */ - free_irq(dev->irq,dev); - free_irq(2,dev); - iounmap(priv->dma_data); - - return 0; -} - - -static void ether00_get_ethernet_address(struct net_device* dev) -{ - struct mtd_info *mymtd=NULL; - int i; - size_t retlen; - - /* - * For the Epxa10 dev board (camelot), the ethernet MAC - * address is of the form 00:aa:aa:00:xx:xx where - * 00:aa:aa is the Altera vendor ID and xx:xx is the - * last 2 bytes of the board serial number, as programmed - * into the OTP area of the flash device on EBI1. If this - * isn't an expa10 dev board, or there's no mtd support to - * read the serial number from flash then we'll force the - * use to set their own mac address using ifconfig. - */ - -#ifdef CONFIG_ARCH_CAMELOT -#ifdef CONFIG_MTD - /* get the mtd_info structure for the first mtd device*/ - for(i=0;i<MAX_MTD_DEVICES;i++){ - mymtd=get_mtd_device(NULL,i); - if(!mymtd||!strcmp(mymtd->name,"EPXA10DB flash")) - break; - } - - if(!mymtd || !mymtd->read_user_prot_reg){ - printk(KERN_WARNING "%s: Failed to read MAC address from flash\n",dev->name); - }else{ - mymtd->read_user_prot_reg(mymtd,2,1,&retlen,&dev->dev_addr[5]); - mymtd->read_user_prot_reg(mymtd,3,1,&retlen,&dev->dev_addr[4]); - dev->dev_addr[3]=0; - dev->dev_addr[2]=vendor_id[1]; - dev->dev_addr[1]=vendor_id[0]; - dev->dev_addr[0]=0; - } -#else - printk(KERN_WARNING "%s: MTD support required to read MAC address from EPXA10 dev board\n", dev->name); -#endif -#endif - - if (!is_valid_ether_addr(dev->dev_addr)) - printk("%s: Invalid ethernet MAC address. Please set using " - "ifconfig\n", dev->name); - -} - -/* - * Keep a mapping of dev_info addresses -> port lines to use when - * removing ports dev==NULL indicates unused entry - */ - - -static struct net_device* dev_list[ETH_NR]; - -static int ether00_add_device(struct pldhs_dev_info* dev_info,void* dev_ps_data) -{ - struct net_device *dev; - struct net_priv *priv; - void *map_addr; - int result; - int i; - - i=0; - while(dev_list[i] && i < ETH_NR) - i++; - - if(i==ETH_NR){ - printk(KERN_WARNING "ether00: Maximum number of ports reached\n"); - return 0; - } - - - if (!request_mem_region(dev_info->base_addr, MAC_REG_SIZE, "ether00")) - return -EBUSY; - - dev = alloc_etherdev(sizeof(struct net_priv)); - if(!dev) { - result = -ENOMEM; - goto out_release; - } - priv = dev->priv; - - priv->tq_memupdate.routine=ether00_mem_update; - priv->tq_memupdate.data=(void*) dev; - - spin_lock_init(&priv->rx_lock); - - map_addr=ioremap_nocache(dev_info->base_addr,SZ_4K); - if(!map_addr){ - result = -ENOMEM; - out_kfree; - } - - dev->open=ether00_open; - dev->stop=ether00_stop; - dev->set_multicast_list=ether00_set_multicast; - dev->hard_start_xmit=ether00_tx; - dev->get_stats=ether00_stats; - - ether00_get_ethernet_address(dev); - - SET_MODULE_OWNER(dev); - - dev->base_addr=(unsigned int)map_addr; - dev->irq=dev_info->irq; - dev->features=NETIF_F_DYNALLOC | NETIF_F_HW_CSUM; - - result=register_netdev(dev); - if(result){ - printk("Ether00: Error %i registering driver\n",result); - goto out_unmap; - } - printk("registered ether00 device at %#x\n",dev_info->base_addr); - - dev_list[i]=dev; - - return result; - - out_unmap: - iounmap(map_addr); - out_kfree: - free_netdev(dev); - out_release: - release_mem_region(dev_info->base_addr, MAC_REG_SIZE); - return result; -} - - -static int ether00_remove_devices(void) -{ - int i; - - for(i=0;i<ETH_NR;i++){ - if(dev_list[i]){ - netif_device_detach(dev_list[i]); - unregister_netdev(dev_list[i]); - iounmap((void*)dev_list[i]->base_addr); - release_mem_region(dev_list[i]->base_addr, MAC_REG_SIZE); - free_netdev(dev_list[i]); - dev_list[i]=0; - } - } - return 0; -} - -static struct pld_hotswap_ops ether00_pldhs_ops={ - .name = ETHER00_NAME, - .add_device = ether00_add_device, - .remove_devices = ether00_remove_devices, -}; - - -static void __exit ether00_cleanup_module(void) -{ - int result; - result=ether00_remove_devices(); - if(result) - printk(KERN_WARNING "ether00: failed to remove all devices\n"); - - pldhs_unregister_driver(ETHER00_NAME); -} -module_exit(ether00_cleanup_module); - - -static int __init ether00_mod_init(void) -{ - printk("mod init\n"); - return pldhs_register_driver(ðer00_pldhs_ops); - -} - -module_init(ether00_mod_init); - diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index 1cc53abc3a39..f1d5b1027ff7 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -69,7 +69,6 @@ #include <asm/system.h> #include <asm/ecard.h> #include <asm/io.h> -#include <asm/irq.h> static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 942a2819576c..6a93b666eb72 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -50,7 +50,6 @@ #include <asm/system.h> #include <asm/ecard.h> #include <asm/io.h> -#include <asm/irq.h> #include "../8390.h" diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 41b3d83c2ab8..f4424cf886c5 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -515,6 +515,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) count = kiss_esc(p, (unsigned char *)ax->xbuff, len); } } + spin_unlock_bh(&ax->buflock); set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags); actual = ax->tty->driver->write(ax->tty, ax->xbuff, count); @@ -524,7 +525,6 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) ax->dev->trans_start = jiffies; ax->xleft = count - actual; ax->xhead = ax->xbuff + actual; - spin_unlock_bh(&ax->buflock); } /* Encapsulate an AX.25 packet and kick it into a TTY queue. */ diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index e92c17f6931c..55c7ed608391 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -276,7 +276,7 @@ static void hp100_RegisterDump(struct net_device *dev); * Convert an address in a kernel buffer to a bus/phys/dma address. * This work *only* for memory fragments part of lp->page_vaddr, * because it was properly DMA allocated via pci_alloc_consistent(), - * so we just need to "retreive" the original mapping to bus/phys/dma + * so we just need to "retrieve" the original mapping to bus/phys/dma * address - Jean II */ static inline dma_addr_t virt_to_whatever(struct net_device *dev, u32 * ptr) { diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c new file mode 100644 index 000000000000..1b699259b4ec --- /dev/null +++ b/drivers/net/ifb.c @@ -0,0 +1,294 @@ +/* drivers/net/ifb.c: + + The purpose of this driver is to provide a device that allows + for sharing of resources: + + 1) qdiscs/policies that are per device as opposed to system wide. + ifb allows for a device which can be redirected to thus providing + an impression of sharing. + + 2) Allows for queueing incoming traffic for shaping instead of + dropping. + + The original concept is based on what is known as the IMQ + driver initially written by Martin Devera, later rewritten + by Patrick McHardy and then maintained by Andre Correa. + + You need the tc action mirror or redirect to feed this device + packets. + + 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. + + Authors: Jamal Hadi Salim (2005) + +*/ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/init.h> +#include <linux/moduleparam.h> +#include <net/pkt_sched.h> + +#define TX_TIMEOUT (2*HZ) + +#define TX_Q_LIMIT 32 +struct ifb_private { + struct net_device_stats stats; + struct tasklet_struct ifb_tasklet; + int tasklet_pending; + /* mostly debug stats leave in for now */ + unsigned long st_task_enter; /* tasklet entered */ + unsigned long st_txq_refl_try; /* transmit queue refill attempt */ + unsigned long st_rxq_enter; /* receive queue entered */ + unsigned long st_rx2tx_tran; /* receive to trasmit transfers */ + unsigned long st_rxq_notenter; /*receiveQ not entered, resched */ + unsigned long st_rx_frm_egr; /* received from egress path */ + unsigned long st_rx_frm_ing; /* received from ingress path */ + unsigned long st_rxq_check; + unsigned long st_rxq_rsch; + struct sk_buff_head rq; + struct sk_buff_head tq; +}; + +static int numifbs = 1; + +static void ri_tasklet(unsigned long dev); +static int ifb_xmit(struct sk_buff *skb, struct net_device *dev); +static struct net_device_stats *ifb_get_stats(struct net_device *dev); +static int ifb_open(struct net_device *dev); +static int ifb_close(struct net_device *dev); + +static void ri_tasklet(unsigned long dev) +{ + + struct net_device *_dev = (struct net_device *)dev; + struct ifb_private *dp = netdev_priv(_dev); + struct net_device_stats *stats = &dp->stats; + struct sk_buff *skb; + + dp->st_task_enter++; + if ((skb = skb_peek(&dp->tq)) == NULL) { + dp->st_txq_refl_try++; + if (spin_trylock(&_dev->xmit_lock)) { + dp->st_rxq_enter++; + while ((skb = skb_dequeue(&dp->rq)) != NULL) { + skb_queue_tail(&dp->tq, skb); + dp->st_rx2tx_tran++; + } + spin_unlock(&_dev->xmit_lock); + } else { + /* reschedule */ + dp->st_rxq_notenter++; + goto resched; + } + } + + while ((skb = skb_dequeue(&dp->tq)) != NULL) { + u32 from = G_TC_FROM(skb->tc_verd); + + skb->tc_verd = 0; + skb->tc_verd = SET_TC_NCLS(skb->tc_verd); + stats->tx_packets++; + stats->tx_bytes +=skb->len; + if (from & AT_EGRESS) { + dp->st_rx_frm_egr++; + dev_queue_xmit(skb); + } else if (from & AT_INGRESS) { + + dp->st_rx_frm_ing++; + netif_rx(skb); + } else { + dev_kfree_skb(skb); + stats->tx_dropped++; + } + } + + if (spin_trylock(&_dev->xmit_lock)) { + dp->st_rxq_check++; + if ((skb = skb_peek(&dp->rq)) == NULL) { + dp->tasklet_pending = 0; + if (netif_queue_stopped(_dev)) + netif_wake_queue(_dev); + } else { + dp->st_rxq_rsch++; + spin_unlock(&_dev->xmit_lock); + goto resched; + } + spin_unlock(&_dev->xmit_lock); + } else { +resched: + dp->tasklet_pending = 1; + tasklet_schedule(&dp->ifb_tasklet); + } + +} + +static void __init ifb_setup(struct net_device *dev) +{ + /* Initialize the device structure. */ + dev->get_stats = ifb_get_stats; + dev->hard_start_xmit = ifb_xmit; + dev->open = &ifb_open; + dev->stop = &ifb_close; + + /* Fill in device structure with ethernet-generic values. */ + ether_setup(dev); + dev->tx_queue_len = TX_Q_LIMIT; + dev->change_mtu = NULL; + dev->flags |= IFF_NOARP; + dev->flags &= ~IFF_MULTICAST; + SET_MODULE_OWNER(dev); + random_ether_addr(dev->dev_addr); +} + +static int ifb_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ifb_private *dp = netdev_priv(dev); + struct net_device_stats *stats = &dp->stats; + int ret = 0; + u32 from = G_TC_FROM(skb->tc_verd); + + stats->tx_packets++; + stats->tx_bytes+=skb->len; + + if (!from || !skb->input_dev) { +dropped: + dev_kfree_skb(skb); + stats->rx_dropped++; + return ret; + } else { + /* + * note we could be going + * ingress -> egress or + * egress -> ingress + */ + skb->dev = skb->input_dev; + skb->input_dev = dev; + if (from & AT_INGRESS) { + skb_pull(skb, skb->dev->hard_header_len); + } else { + if (!(from & AT_EGRESS)) { + goto dropped; + } + } + } + + if (skb_queue_len(&dp->rq) >= dev->tx_queue_len) { + netif_stop_queue(dev); + } + + dev->trans_start = jiffies; + skb_queue_tail(&dp->rq, skb); + if (!dp->tasklet_pending) { + dp->tasklet_pending = 1; + tasklet_schedule(&dp->ifb_tasklet); + } + + return ret; +} + +static struct net_device_stats *ifb_get_stats(struct net_device *dev) +{ + struct ifb_private *dp = netdev_priv(dev); + struct net_device_stats *stats = &dp->stats; + + pr_debug("tasklets stats %ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld \n", + dp->st_task_enter, dp->st_txq_refl_try, dp->st_rxq_enter, + dp->st_rx2tx_tran dp->st_rxq_notenter, dp->st_rx_frm_egr, + dp->st_rx_frm_ing, dp->st_rxq_check, dp->st_rxq_rsch ); + + return stats; +} + +static struct net_device **ifbs; + +/* Number of ifb devices to be set up by this module. */ +module_param(numifbs, int, 0); +MODULE_PARM_DESC(numifbs, "Number of ifb devices"); + +static int ifb_close(struct net_device *dev) +{ + struct ifb_private *dp = netdev_priv(dev); + + tasklet_kill(&dp->ifb_tasklet); + netif_stop_queue(dev); + skb_queue_purge(&dp->rq); + skb_queue_purge(&dp->tq); + return 0; +} + +static int ifb_open(struct net_device *dev) +{ + struct ifb_private *dp = netdev_priv(dev); + + tasklet_init(&dp->ifb_tasklet, ri_tasklet, (unsigned long)dev); + skb_queue_head_init(&dp->rq); + skb_queue_head_init(&dp->tq); + netif_start_queue(dev); + + return 0; +} + +static int __init ifb_init_one(int index) +{ + struct net_device *dev_ifb; + int err; + + dev_ifb = alloc_netdev(sizeof(struct ifb_private), + "ifb%d", ifb_setup); + + if (!dev_ifb) + return -ENOMEM; + + if ((err = register_netdev(dev_ifb))) { + free_netdev(dev_ifb); + dev_ifb = NULL; + } else { + ifbs[index] = dev_ifb; + } + + return err; +} + +static void ifb_free_one(int index) +{ + unregister_netdev(ifbs[index]); + free_netdev(ifbs[index]); +} + +static int __init ifb_init_module(void) +{ + int i, err = 0; + ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL); + if (!ifbs) + return -ENOMEM; + for (i = 0; i < numifbs && !err; i++) + err = ifb_init_one(i); + if (err) { + while (--i >= 0) + ifb_free_one(i); + } + + return err; +} + +static void __exit ifb_cleanup_module(void) +{ + int i; + + for (i = 0; i < numifbs; i++) + ifb_free_one(i); + kfree(ifbs); +} + +module_init(ifb_init_module); +module_exit(ifb_cleanup_module); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jamal Hadi Salim"); diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 049c34b37067..593d8adee891 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1598,7 +1598,7 @@ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch(cmd) { case SIOCGMIIPHY: /* Get the address of the PHY in use. */ data[0] = 0; /* we have only this address */ - /* fall trough */ + /* fall through */ case SIOCGMIIREG: /* Read the specified MII register. */ data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f); break; diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c index 0fddf61047b4..07c1b4c8699d 100644 --- a/drivers/net/sk98lin/skdim.c +++ b/drivers/net/sk98lin/skdim.c @@ -180,7 +180,7 @@ SkDimModerate(SK_AC *pAC) { /* ** The number of interrupts per sec is the same as expected. ** Evalulate the descriptor-ratio. If it has changed, a resize - ** in the moderation timer might be usefull + ** in the moderation timer might be useful */ if (M_DIMINFO.AutoSizing) { ResizeDimTimerDuration(pAC); diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 197edd74fbb5..a5f2b1ee0752 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -2851,7 +2851,7 @@ unsigned long Flags; /* for spin lock */ * Description: * This function is called if an ioctl is issued on the device. * There are three subfunction for reading, writing and test-writing - * the private MIB data structure (usefull for SysKonnect-internal tools). + * the private MIB data structure (useful for SysKonnect-internal tools). * * Returns: * 0, if everything is ok diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c index 58e1a5be913f..a386172107e8 100644 --- a/drivers/net/sk98lin/skgepnmi.c +++ b/drivers/net/sk98lin/skgepnmi.c @@ -611,7 +611,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ * Description: * Calls a general sub-function for all this stuff. The preset does * the same as a set, but returns just before finally setting the - * new value. This is usefull to check if a set might be successfull. + * new value. This is useful to check if a set might be successfull. * If the instance -1 is passed, an array of values is supposed and * all instances of the OID will be set. * @@ -654,7 +654,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ * Description: * Calls a general sub-function for all this stuff. The preset does * the same as a set, but returns just before finally setting the - * new value. This is usefull to check if a set might be successfull. + * new value. This is useful to check if a set might be successfull. * If the instance -1 is passed, an array of values is supposed and * all instances of the OID will be set. * @@ -870,7 +870,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ * Description: * Calls a general sub-function for all this set stuff. The preset does * the same as a set, but returns just before finally setting the - * new value. This is usefull to check if a set might be successfull. + * new value. This is useful to check if a set might be successfull. * The sub-function runs through the IdTable, checks which OIDs are able * to set, and calls the handler function of the OID to perform the * preset. The return value of the function will also be stored in @@ -6473,7 +6473,7 @@ unsigned int PhysPortIndex) /* Physical port index */ * * Description: * The COMMON module only tells us if the mode is half or full duplex. - * But in the decade of auto sensing it is usefull for the user to + * But in the decade of auto sensing it is useful for the user to * know if the mode was negotiated or forced. Therefore we have a * look to the mode, which was last used by the negotiation process. * diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 95bd07b8b61b..315be4770d3e 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -347,7 +347,7 @@ static void led_LCD_driver(unsigned char leds) ** ** led_get_net_activity() ** - ** calculate if there was TX- or RX-troughput on the network interfaces + ** calculate if there was TX- or RX-throughput on the network interfaces ** (analog to dev_get_info() from net/core/dev.c) ** */ diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index d21894c63f8e..92a885760832 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -25,7 +25,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence) loff_t new = -1; struct inode *inode = file->f_dentry->d_inode; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); switch (whence) { case 0: new = off; @@ -41,7 +41,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence) new = -EINVAL; else file->f_pos = new; - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return new; } diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 09ed05727bcb..dda5a5f79c53 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -146,7 +146,6 @@ #include <asm/system.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/ecard.h> #include "../scsi.h" diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c index 804125e35fc3..a28940156703 100644 --- a/drivers/scsi/arm/arxescsi.c +++ b/drivers/scsi/arm/arxescsi.c @@ -33,7 +33,6 @@ #include <asm/dma.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/ecard.h> #include "../scsi.h" diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 81e266be26d0..e6c9491dc5c0 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -13,7 +13,6 @@ #include <asm/ecard.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/system.h> #include "../scsi.h" diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index 3a7a46b0dc41..583d2d8c8335 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -31,7 +31,6 @@ #include <asm/dma.h> #include <asm/ecard.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/pgtable.h> #include "../scsi.h" diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index 4d1e8f52c924..3ffec7efc9d5 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -35,7 +35,6 @@ #include <linux/dma-mapping.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/dma.h> #include <asm/ecard.h> #include <asm/pgtable.h> diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index 3333d7b39139..3113bdcedb13 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -22,7 +22,6 @@ #include <asm/dma.h> #include <asm/ecard.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/pgtable.h> #include "../scsi.h" diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 221e96e2620a..78aad9582bcf 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -2493,7 +2493,7 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp) } if (resp) { if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - memset(resp, 0, resSz); + memset(page_address(resp), 0, resSz); if (retSzp) *retSzp = resSz; } diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 1891cf5bdeef..e8454611cb65 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -54,6 +54,8 @@ */ static unsigned int share_irqs = SERIAL8250_SHARE_IRQS; +static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; + /* * Debugging. */ @@ -2118,7 +2120,7 @@ static void __init serial8250_isa_init_ports(void) return; first = 0; - for (i = 0; i < UART_NR; i++) { + for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; up->port.line = i; @@ -2137,7 +2139,7 @@ static void __init serial8250_isa_init_ports(void) } for (i = 0, up = serial8250_ports; - i < ARRAY_SIZE(old_serial_port) && i < UART_NR; + i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; i++, up++) { up->port.iobase = old_serial_port[i].port; up->port.irq = irq_canonicalize(old_serial_port[i].irq); @@ -2159,7 +2161,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) serial8250_isa_init_ports(); - for (i = 0; i < UART_NR; i++) { + for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; up->port.dev = dev; @@ -2262,7 +2264,7 @@ static int serial8250_console_setup(struct console *co, char *options) * if so, search for the first available port that does have * console support. */ - if (co->index >= UART_NR) + if (co->index >= nr_uarts) co->index = 0; port = &serial8250_ports[co->index].port; if (!port->iobase && !port->membase) @@ -2298,7 +2300,7 @@ static int __init find_port(struct uart_port *p) int line; struct uart_port *port; - for (line = 0; line < UART_NR; line++) { + for (line = 0; line < nr_uarts; line++) { port = &serial8250_ports[line].port; if (uart_match_port(p, port)) return line; @@ -2420,7 +2422,7 @@ static int __devexit serial8250_remove(struct platform_device *dev) { int i; - for (i = 0; i < UART_NR; i++) { + for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; if (up->port.dev == &dev->dev) @@ -2487,7 +2489,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * /* * First, find a port entry which matches. */ - for (i = 0; i < UART_NR; i++) + for (i = 0; i < nr_uarts; i++) if (uart_match_port(&serial8250_ports[i].port, port)) return &serial8250_ports[i]; @@ -2496,7 +2498,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * * free entry. We look for one which hasn't been previously * used (indicated by zero iobase). */ - for (i = 0; i < UART_NR; i++) + for (i = 0; i < nr_uarts; i++) if (serial8250_ports[i].port.type == PORT_UNKNOWN && serial8250_ports[i].port.iobase == 0) return &serial8250_ports[i]; @@ -2505,7 +2507,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * * That also failed. Last resort is to find any entry which * doesn't have a real port associated with it. */ - for (i = 0; i < UART_NR; i++) + for (i = 0; i < nr_uarts; i++) if (serial8250_ports[i].port.type == PORT_UNKNOWN) return &serial8250_ports[i]; @@ -2590,8 +2592,11 @@ static int __init serial8250_init(void) { int ret, i; + if (nr_uarts > UART_NR) + nr_uarts = UART_NR; + printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ " - "%d ports, IRQ sharing %sabled\n", (int) UART_NR, + "%d ports, IRQ sharing %sabled\n", nr_uarts, share_irqs ? "en" : "dis"); for (i = 0; i < NR_IRQS; i++) @@ -2651,6 +2656,9 @@ module_param(share_irqs, uint, 0644); MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" " (unsafe)"); +module_param(nr_uarts, uint, 0644); +MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")"); + #ifdef CONFIG_SERIAL_8250_RSA module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444); MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 812bae62c8ec..1bae26a8a503 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -95,6 +95,16 @@ config SERIAL_8250_NR_UARTS PCI enumeration and any ports that may be added at run-time via hot-plug, or any ISA multi-port serial cards. +config SERIAL_8250_RUNTIME_UARTS + int "Number of 8250/16550 serial ports to register at runtime" + depends on SERIAL_8250 + default "4" + help + Set this to the maximum number of serial ports you want + the kernel to register at boot time. This can be overriden + with the module parameter "nr_uarts", or boot-time parameter + 8250.nr_uarts + config SERIAL_8250_EXTENDED bool "Extended 8250/16550 serial driver options" depends on SERIAL_8250 @@ -359,29 +369,6 @@ config SERIAL_21285_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) -config SERIAL_UART00 - bool "Excalibur serial port (uart00) support" - depends on ARM && ARCH_CAMELOT - select SERIAL_CORE - help - Say Y here if you want to use the hard logic uart on Excalibur. This - driver also supports soft logic implementations of this uart core. - -config SERIAL_UART00_CONSOLE - bool "Support for console on Excalibur serial port" - depends on SERIAL_UART00 - select SERIAL_CORE_CONSOLE - help - Say Y here if you want to support a serial console on an Excalibur - hard logic uart or uart00 IP core. - - Even if you say Y here, the currently visible virtual console - (/dev/tty0) will still be used as the system console by default, but - you can alter that using a kernel command line option such as - "console=ttyS1". (Try "man bootparam" or see the documentation of - your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time.) - config SERIAL_MPSC bool "Marvell MPSC serial port support" depends on PPC32 && MV64X60 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index d7c7c7180e33..137148bba4fa 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -29,7 +29,6 @@ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o obj-$(CONFIG_SERIAL_PXA) += pxa.o obj-$(CONFIG_SERIAL_SA1100) += sa1100.o obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o -obj-$(CONFIG_SERIAL_UART00) += uart00.o obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 34c576dfad8d..9589509fc5bd 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1440,6 +1440,7 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) * modem is ready for us. */ spin_lock_irq(&port->lock); + port->ops->enable_ms(port); mctrl = port->ops->get_mctrl(port); spin_unlock_irq(&port->lock); if (mctrl & TIOCM_CAR) diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c deleted file mode 100644 index 47b504ff38b2..000000000000 --- a/drivers/serial/uart00.c +++ /dev/null @@ -1,782 +0,0 @@ -/* - * linux/drivers/serial/uart00.c - * - * Driver for UART00 serial ports - * - * Based on drivers/char/serial_amba.c, by ARM Limited & - * Deep Blue Solutions Ltd. - * Copyright 2001 Altera Corporation - * - * Update for 2.6.4 by Dirk Behme <dirk.behme@de.bosch.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: uart00.c,v 1.35 2002/07/28 10:03:28 rmk Exp $ - * - */ -#include <linux/config.h> - -#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial_core.h> -#include <linux/serial.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/sizes.h> - -#include <asm/arch/excalibur.h> -#define UART00_TYPE (volatile unsigned int*) -#include <asm/arch/uart00.h> -#include <asm/arch/int_ctrl00.h> - -#define UART_NR 2 - -#define SERIAL_UART00_NAME "ttyUA" -#define SERIAL_UART00_MAJOR 204 -#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */ -#define SERIAL_UART00_NR UART_NR -#define UART_PORT_SIZE 0x50 - -#define UART00_ISR_PASS_LIMIT 256 - -/* - * Access macros for the UART00 UARTs - */ -#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase)) -#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase)) -#define UART_GET_IES(p) inl(UART_IES((p)->membase)) -#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase)) -#define UART_GET_IEC(p) inl(UART_IEC((p)->membase)) -#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase)) -#define UART_GET_CHAR(p) inl(UART_RD((p)->membase)) -#define UART_GET_RSR(p) inl(UART_RSR((p)->membase)) -#define UART_GET_RDS(p) inl(UART_RDS((p)->membase)) -#define UART_GET_MSR(p) inl(UART_MSR((p)->membase)) -#define UART_GET_MCR(p) inl(UART_MCR((p)->membase)) -#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase)) -#define UART_GET_MC(p) inl(UART_MC((p)->membase)) -#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase)) -#define UART_GET_TSR(p) inl(UART_TSR((p)->membase)) -#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase)) -#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase)) -#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase)) -#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase)) -#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK) -#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15) -//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0) - -static void uart00_stop_tx(struct uart_port *port) -{ - UART_PUT_IEC(port, UART_IEC_TIE_MSK); -} - -static void uart00_stop_rx(struct uart_port *port) -{ - UART_PUT_IEC(port, UART_IEC_RE_MSK); -} - -static void uart00_enable_ms(struct uart_port *port) -{ - UART_PUT_IES(port, UART_IES_ME_MSK); -} - -static void -uart00_rx_chars(struct uart_port *port, struct pt_regs *regs) -{ - struct tty_struct *tty = port->info->tty; - unsigned int status, ch, rds, flg, ignored = 0; - - status = UART_GET_RSR(port); - while (UART_RX_DATA(status)) { - /* - * We need to read rds before reading the - * character from the fifo - */ - rds = UART_GET_RDS(port); - ch = UART_GET_CHAR(port); - port->icount.rx++; - - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; - - flg = TTY_NORMAL; - - /* - * Note that the error handling code is - * out of the main execution path - */ - if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK| - UART_RDS_PE_MSK |UART_RDS_PE_MSK)) - goto handle_error; - if (uart_handle_sysrq_char(port, ch, regs)) - goto ignore_char; - - error_return: - tty_insert_flip_char(tty, ch, flg); - - ignore_char: - status = UART_GET_RSR(port); - } - out: - tty_flip_buffer_push(tty); - return; - - handle_error: - if (rds & UART_RDS_BI_MSK) { - status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK); - port->icount.brk++; - if (uart_handle_break(port)) - goto ignore_char; - } else if (rds & UART_RDS_PE_MSK) - port->icount.parity++; - else if (rds & UART_RDS_FE_MSK) - port->icount.frame++; - if (rds & UART_RDS_OE_MSK) - port->icount.overrun++; - - if (rds & port->ignore_status_mask) { - if (++ignored > 100) - goto out; - goto ignore_char; - } - rds &= port->read_status_mask; - - if (rds & UART_RDS_BI_MSK) - flg = TTY_BREAK; - else if (rds & UART_RDS_PE_MSK) - flg = TTY_PARITY; - else if (rds & UART_RDS_FE_MSK) - flg = TTY_FRAME; - - if (rds & UART_RDS_OE_MSK) { - /* - * CHECK: does overrun affect the current character? - * ASSUMPTION: it does not. - */ - tty_insert_flip_char(tty, ch, flg); - ch = 0; - flg = TTY_OVERRUN; - } -#ifdef SUPPORT_SYSRQ - port->sysrq = 0; -#endif - goto error_return; -} - -static void uart00_tx_chars(struct uart_port *port) -{ - struct circ_buf *xmit = &port->info->xmit; - int count; - - if (port->x_char) { - while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15) - barrier(); - UART_PUT_CHAR(port, port->x_char); - port->icount.tx++; - port->x_char = 0; - return; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - uart00_stop_tx(port); - return; - } - - count = port->fifosize >> 1; - do { - while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15) - barrier(); - UART_PUT_CHAR(port, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - if (uart_circ_empty(xmit)) - break; - } while (--count > 0); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - - if (uart_circ_empty(xmit)) - uart00_stop_tx(port); -} - -static void uart00_start_tx(struct uart_port *port) -{ - UART_PUT_IES(port, UART_IES_TIE_MSK); - uart00_tx_chars(port); -} - -static void uart00_modem_status(struct uart_port *port) -{ - unsigned int status; - - status = UART_GET_MSR(port); - - if (!(status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK | - UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK))) - return; - - if (status & UART_MSR_DDCD_MSK) - uart_handle_dcd_change(port, status & UART_MSR_DCD_MSK); - - if (status & UART_MSR_DDSR_MSK) - port->icount.dsr++; - - if (status & UART_MSR_DCTS_MSK) - uart_handle_cts_change(port, status & UART_MSR_CTS_MSK); - - wake_up_interruptible(&port->info->delta_msr_wait); -} - -static irqreturn_t uart00_int(int irq, void *dev_id, struct pt_regs *regs) -{ - struct uart_port *port = dev_id; - unsigned int status, pass_counter = 0; - - status = UART_GET_INT_STATUS(port); - do { - if (status & UART_ISR_RI_MSK) - uart00_rx_chars(port, regs); - if (status & UART_ISR_MI_MSK) - uart00_modem_status(port); - if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK)) - uart00_tx_chars(port); - if (pass_counter++ > UART00_ISR_PASS_LIMIT) - break; - - status = UART_GET_INT_STATUS(port); - } while (status); - - return IRQ_HANDLED; -} - -static unsigned int uart00_tx_empty(struct uart_port *port) -{ - return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT; -} - -static unsigned int uart00_get_mctrl(struct uart_port *port) -{ - unsigned int result = 0; - unsigned int status; - - status = UART_GET_MSR(port); - if (status & UART_MSR_DCD_MSK) - result |= TIOCM_CAR; - if (status & UART_MSR_DSR_MSK) - result |= TIOCM_DSR; - if (status & UART_MSR_CTS_MSK) - result |= TIOCM_CTS; - if (status & UART_MSR_RI_MSK) - result |= TIOCM_RI; - - return result; -} - -static void uart00_set_mctrl_null(struct uart_port *port, unsigned int mctrl) -{ -} - -static void uart00_break_ctl(struct uart_port *port, int break_state) -{ - unsigned long flags; - unsigned int mcr; - - spin_lock_irqsave(&port->lock, flags); - mcr = UART_GET_MCR(port); - if (break_state == -1) - mcr |= UART_MCR_BR_MSK; - else - mcr &= ~UART_MCR_BR_MSK; - UART_PUT_MCR(port, mcr); - spin_unlock_irqrestore(&port->lock, flags); -} - -static void -uart00_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) -{ - unsigned int uart_mc, old_ies, baud, quot; - unsigned long flags; - - /* - * We don't support CREAD (yet) - */ - termios->c_cflag |= CREAD; - - /* - * Ask the core to calculate the divisor for us. - */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - quot = uart_get_divisor(port, baud); - - /* byte size and parity */ - switch (termios->c_cflag & CSIZE) { - case CS5: - uart_mc = UART_MC_CLS_CHARLEN_5; - break; - case CS6: - uart_mc = UART_MC_CLS_CHARLEN_6; - break; - case CS7: - uart_mc = UART_MC_CLS_CHARLEN_7; - break; - default: // CS8 - uart_mc = UART_MC_CLS_CHARLEN_8; - break; - } - if (termios->c_cflag & CSTOPB) - uart_mc|= UART_MC_ST_TWO; - if (termios->c_cflag & PARENB) { - uart_mc |= UART_MC_PE_MSK; - if (!(termios->c_cflag & PARODD)) - uart_mc |= UART_MC_EP_MSK; - } - - spin_lock_irqsave(&port->lock, flags); - - /* - * Update the per-port timeout. - */ - uart_update_timeout(port, termios->c_cflag, baud); - - port->read_status_mask = UART_RDS_OE_MSK; - if (termios->c_iflag & INPCK) - port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK; - if (termios->c_iflag & (BRKINT | PARMRK)) - port->read_status_mask |= UART_RDS_BI_MSK; - - /* - * Characters to ignore - */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK; - if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= UART_RDS_BI_MSK; - /* - * If we're ignoring parity and break indicators, - * ignore overruns to (for real raw support). - */ - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= UART_RDS_OE_MSK; - } - - /* first, disable everything */ - old_ies = UART_GET_IES(port); - - if (UART_ENABLE_MS(port, termios->c_cflag)) - old_ies |= UART_IES_ME_MSK; - - /* Set baud rate */ - UART_PUT_DIV_LO(port, (quot & 0xff)); - UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8)); - - UART_PUT_MC(port, uart_mc); - UART_PUT_IES(port, old_ies); - - spin_unlock_irqrestore(&port->lock, flags); -} - -static int uart00_startup(struct uart_port *port) -{ - int result; - - /* - * Allocate the IRQ - */ - result = request_irq(port->irq, uart00_int, 0, "uart00", port); - if (result) { - printk(KERN_ERR "Request of irq %d failed\n", port->irq); - return result; - } - - /* - * Finally, enable interrupts. Use the TII interrupt to minimise - * the number of interrupts generated. If higher performance is - * needed, consider using the TI interrupt with a suitable FIFO - * threshold - */ - UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK); - - return 0; -} - -static void uart00_shutdown(struct uart_port *port) -{ - /* - * disable all interrupts, disable the port - */ - UART_PUT_IEC(port, 0xff); - - /* disable break condition and fifos */ - UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK); - - /* - * Free the interrupt - */ - free_irq(port->irq, port); -} - -static const char *uart00_type(struct uart_port *port) -{ - return port->type == PORT_UART00 ? "Altera UART00" : NULL; -} - -/* - * Release the memory region(s) being used by 'port' - */ -static void uart00_release_port(struct uart_port *port) -{ - release_mem_region(port->mapbase, UART_PORT_SIZE); - -#ifdef CONFIG_ARCH_CAMELOT - if (port->membase != (void*)IO_ADDRESS(EXC_UART00_BASE)) { - iounmap(port->membase); - } -#endif -} - -/* - * Request the memory region(s) being used by 'port' - */ -static int uart00_request_port(struct uart_port *port) -{ - return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_uart00") - != NULL ? 0 : -EBUSY; -} - -/* - * Configure/autoconfigure the port. - */ -static void uart00_config_port(struct uart_port *port, int flags) -{ - - /* - * Map the io memory if this is a soft uart - */ - if (!port->membase) - port->membase = ioremap_nocache(port->mapbase,SZ_4K); - - if (!port->membase) - printk(KERN_ERR "serial00: cannot map io memory\n"); - else - port->type = PORT_UART00; - -} - -/* - * verify the new serial_struct (for TIOCSSERIAL). - */ -static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - int ret = 0; - if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00) - ret = -EINVAL; - if (ser->irq < 0 || ser->irq >= NR_IRQS) - ret = -EINVAL; - if (ser->baud_base < 9600) - ret = -EINVAL; - return ret; -} - -static struct uart_ops uart00_pops = { - .tx_empty = uart00_tx_empty, - .set_mctrl = uart00_set_mctrl_null, - .get_mctrl = uart00_get_mctrl, - .stop_tx = uart00_stop_tx, - .start_tx = uart00_start_tx, - .stop_rx = uart00_stop_rx, - .enable_ms = uart00_enable_ms, - .break_ctl = uart00_break_ctl, - .startup = uart00_startup, - .shutdown = uart00_shutdown, - .set_termios = uart00_set_termios, - .type = uart00_type, - .release_port = uart00_release_port, - .request_port = uart00_request_port, - .config_port = uart00_config_port, - .verify_port = uart00_verify_port, -}; - - -#ifdef CONFIG_ARCH_CAMELOT -static struct uart_port epxa10db_port = { - .membase = (void*)IO_ADDRESS(EXC_UART00_BASE), - .mapbase = EXC_UART00_BASE, - .iotype = SERIAL_IO_MEM, - .irq = IRQ_UART, - .uartclk = EXC_AHB2_CLK_FREQUENCY, - .fifosize = 16, - .ops = &uart00_pops, - .flags = ASYNC_BOOT_AUTOCONF, -}; -#endif - - -#ifdef CONFIG_SERIAL_UART00_CONSOLE -static void uart00_console_write(struct console *co, const char *s, unsigned count) -{ -#ifdef CONFIG_ARCH_CAMELOT - struct uart_port *port = &epxa10db_port; - unsigned int status, old_ies; - int i; - - /* - * First save the CR then disable the interrupts - */ - old_ies = UART_GET_IES(port); - UART_PUT_IEC(port,0xff); - - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_TSR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_TSR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, '\r'); - } - } - - /* - * Finally, wait for transmitter to become empty - * and restore the IES - */ - do { - status = UART_GET_TSR(port); - } while (status & UART_TSR_TX_LEVEL_MSK); - UART_PUT_IES(port, old_ies); -#endif -} - -static void __init -uart00_console_get_options(struct uart_port *port, int *baud, - int *parity, int *bits) -{ - unsigned int uart_mc, quot; - - uart_mc = UART_GET_MC(port); - - *parity = 'n'; - if (uart_mc & UART_MC_PE_MSK) { - if (uart_mc & UART_MC_EP_MSK) - *parity = 'e'; - else - *parity = 'o'; - } - - switch (uart_mc & UART_MC_CLS_MSK) { - case UART_MC_CLS_CHARLEN_5: - *bits = 5; - break; - case UART_MC_CLS_CHARLEN_6: - *bits = 6; - break; - case UART_MC_CLS_CHARLEN_7: - *bits = 7; - break; - case UART_MC_CLS_CHARLEN_8: - *bits = 8; - break; - } - quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8); - *baud = port->uartclk / (16 *quot ); -} - -static int __init uart00_console_setup(struct console *co, char *options) -{ - struct uart_port *port; - int baud = 115200; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - -#ifdef CONFIG_ARCH_CAMELOT - port = &epxa10db_port; ; -#else - return -ENODEV; -#endif - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - else - uart00_console_get_options(port, &baud, &parity, &bits); - - return uart_set_options(port, co, baud, parity, bits, flow); -} - -extern struct uart_driver uart00_reg; -static struct console uart00_console = { - .name = SERIAL_UART00_NAME, - .write = uart00_console_write, - .device = uart_console_device, - .setup = uart00_console_setup, - .flags = CON_PRINTBUFFER, - .index = 0, - .data = &uart00_reg, -}; - -static int __init uart00_console_init(void) -{ - register_console(&uart00_console); - return 0; -} -console_initcall(uart00_console_init); - -#define UART00_CONSOLE &uart00_console -#else -#define UART00_CONSOLE NULL -#endif - -static struct uart_driver uart00_reg = { - .owner = NULL, - .driver_name = SERIAL_UART00_NAME, - .dev_name = SERIAL_UART00_NAME, - .major = SERIAL_UART00_MAJOR, - .minor = SERIAL_UART00_MINOR, - .nr = UART_NR, - .cons = UART00_CONSOLE, -}; - -struct dev_port_entry{ - unsigned int base_addr; - struct uart_port *port; -}; - -#ifdef CONFIG_PLD_HOTSWAP - -static struct dev_port_entry dev_port_map[UART_NR]; - -/* - * Keep a mapping of dev_info addresses -> port lines to use when - * removing ports dev==NULL indicates unused entry - */ - -struct uart00_ps_data{ - unsigned int clk; - unsigned int fifosize; -}; - -int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data) -{ - struct uart00_ps_data* dev_ps=dev_ps_data; - struct uart_port * port; - int i,result; - - i=0; - while(dev_port_map[i].port) - i++; - - if(i==UART_NR){ - printk(KERN_WARNING "uart00: Maximum number of ports reached\n"); - return 0; - } - - port=kmalloc(sizeof(struct uart_port),GFP_KERNEL); - if(!port) - return -ENOMEM; - - printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize); - port->membase=0; - port->mapbase=dev_info->base_addr; - port->iotype=SERIAL_IO_MEM; - port->irq=dev_info->irq; - port->uartclk=dev_ps->clk; - port->fifosize=dev_ps->fifosize; - port->ops=&uart00_pops; - port->line=i; - port->flags=ASYNC_BOOT_AUTOCONF; - - result=uart_add_one_port(&uart00_reg, port); - if(result){ - printk("uart_add_one_port returned %d\n",result); - return result; - } - dev_port_map[i].base_addr=dev_info->base_addr; - dev_port_map[i].port=port; - printk("uart00: added device at %x as ttyUA%d\n",dev_port_map[i].base_addr,i); - return 0; - -} - -int uart00_remove_devices(void) -{ - int i,result; - - - result=0; - for(i=1;i<UART_NR;i++){ - if(dev_port_map[i].base_addr){ - result=uart_remove_one_port(&uart00_reg, dev_port_map[i].port); - if(result) - return result; - - /* port removed sucessfully, so now tidy up */ - kfree(dev_port_map[i].port); - dev_port_map[i].base_addr=0; - dev_port_map[i].port=NULL; - } - } - return 0; - -} - -struct pld_hotswap_ops uart00_pldhs_ops={ - .name = "uart00", - .add_device = uart00_add_device, - .remove_devices = uart00_remove_devices, -}; - -#endif - -static int __init uart00_init(void) -{ - int result; - - printk(KERN_INFO "Serial: UART00 driver $Revision: 1.35 $\n"); - - printk(KERN_WARNING "serial_uart00:Using temporary major/minor pairs" - " - these WILL change in the future\n"); - - result = uart_register_driver(&uart00_reg); - if (result) - return result; -#ifdef CONFIG_ARCH_CAMELOT - result = uart_add_one_port(&uart00_reg,&epxa10db_port); -#endif - if (result) - uart_unregister_driver(&uart00_reg); - -#ifdef CONFIG_PLD_HOTSWAP - pldhs_register_driver(&uart00_pldhs_ops); -#endif - return result; -} - -__initcall(uart00_init); diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 4ddc453023a2..3cf945cc5b9a 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -184,13 +184,13 @@ static void update_bus(struct dentry *bus) bus->d_inode->i_gid = busgid; bus->d_inode->i_mode = S_IFDIR | busmode; - down(&bus->d_inode->i_sem); + mutex_lock(&bus->d_inode->i_mutex); list_for_each_entry(dev, &bus->d_subdirs, d_u.d_child) if (dev->d_inode) update_dev(dev); - up(&bus->d_inode->i_sem); + mutex_unlock(&bus->d_inode->i_mutex); } static void update_sb(struct super_block *sb) @@ -201,7 +201,7 @@ static void update_sb(struct super_block *sb) if (!root) return; - down(&root->d_inode->i_sem); + mutex_lock(&root->d_inode->i_mutex); list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) { if (bus->d_inode) { @@ -219,7 +219,7 @@ static void update_sb(struct super_block *sb) } } - up(&root->d_inode->i_sem); + mutex_unlock(&root->d_inode->i_mutex); } static int remount(struct super_block *sb, int *flags, char *data) @@ -333,10 +333,10 @@ static int usbfs_empty (struct dentry *dentry) static int usbfs_unlink (struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); dentry->d_inode->i_nlink--; dput(dentry); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); d_delete(dentry); return 0; } @@ -346,7 +346,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) int error = -ENOTEMPTY; struct inode * inode = dentry->d_inode; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); dentry_unhash(dentry); if (usbfs_empty(dentry)) { dentry->d_inode->i_nlink -= 2; @@ -355,7 +355,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) dir->i_nlink--; error = 0; } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); if (!error) d_delete(dentry); dput(dentry); @@ -380,7 +380,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) { loff_t retval = -EINVAL; - down(&file->f_dentry->d_inode->i_sem); + mutex_lock(&file->f_dentry->d_inode->i_mutex); switch(orig) { case 0: if (offset > 0) { @@ -397,7 +397,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) default: break; } - up(&file->f_dentry->d_inode->i_sem); + mutex_unlock(&file->f_dentry->d_inode->i_mutex); return retval; } @@ -480,7 +480,7 @@ static int fs_create_by_name (const char *name, mode_t mode, } *dentry = NULL; - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); *dentry = lookup_one_len(name, parent, strlen(name)); if (!IS_ERR(dentry)) { if ((mode & S_IFMT) == S_IFDIR) @@ -489,7 +489,7 @@ static int fs_create_by_name (const char *name, mode_t mode, error = usbfs_create (parent->d_inode, *dentry, mode); } else error = PTR_ERR(dentry); - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); return error; } @@ -528,7 +528,7 @@ static void fs_remove_file (struct dentry *dentry) if (!parent || !parent->d_inode) return; - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); if (usbfs_positive(dentry)) { if (dentry->d_inode) { if (S_ISDIR(dentry->d_inode->i_mode)) @@ -538,7 +538,7 @@ static void fs_remove_file (struct dentry *dentry) dput(dentry); } } - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); } /* --------------------------------------------------------------------- */ diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 0cea9782d7d4..de59c58896d6 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -1891,7 +1891,7 @@ static int fsync_sub(struct lun *curlun) return -EINVAL; inode = filp->f_dentry->d_inode; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); current->flags |= PF_SYNCWRITE; rc = filemap_fdatawrite(inode->i_mapping); err = filp->f_op->fsync(filp, filp->f_dentry, 1); @@ -1901,7 +1901,7 @@ static int fsync_sub(struct lun *curlun) if (!rc) rc = err; current->flags &= ~PF_SYNCWRITE; - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); VLDBG(curlun, "fdatasync -> %d\n", rc); return rc; } diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 5c40980a5bd9..c6c279de832e 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1562,10 +1562,10 @@ restart: spin_unlock_irq (&dev->lock); /* break link to dcache */ - down (&parent->i_sem); + mutex_lock (&parent->i_mutex); d_delete (dentry); dput (dentry); - up (&parent->i_sem); + mutex_unlock (&parent->i_mutex); /* fds may still be open */ goto restart; diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index ed1899d307db..be3fd9bce573 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -11,14 +11,14 @@ config USB_EHCI_HCD The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. If your USB host controller supports USB 2.0, you will likely want to - configure this Host Controller Driver. At this writing, the primary - implementation of EHCI is a chip from NEC, widely available in add-on - PCI cards, but implementations are in the works from other vendors - including Intel and Philips. Motherboard support is appearing. + configure this Host Controller Driver. At the time of this writing, + the primary implementation of EHCI is a chip from NEC, widely available + in add-on PCI cards, but implementations are in the works from other + vendors including Intel and Philips. Motherboard support is appearing. EHCI controllers are packaged with "companion" host controllers (OHCI or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports - will connect to EHCI if it the device is high speed, otherwise they + will connect to EHCI if the device is high speed, otherwise they connect to a companion controller. If you configure EHCI, you should probably configure the OHCI (for NEC and some other vendors) USB Host Controller Driver or UHCI (for Via motherboards) Host Controller diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c index 6a5700e9d428..25646804d5be 100644 --- a/drivers/usb/media/dsbr100.c +++ b/drivers/usb/media/dsbr100.c @@ -127,6 +127,7 @@ static struct file_operations usb_dsbr100_fops = { .open = usb_dsbr100_open, .release = usb_dsbr100_close, .ioctl = usb_dsbr100_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c index 3a0e8ce67ebe..8af665bbe330 100644 --- a/drivers/usb/media/ov511.c +++ b/drivers/usb/media/ov511.c @@ -4774,6 +4774,7 @@ static struct file_operations ov511_fops = { .read = ov51x_v4l1_read, .mmap = ov51x_v4l1_mmap, .ioctl = ov51x_v4l1_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c index 09ca6128ac20..4f9b0dc6fd7b 100644 --- a/drivers/usb/media/pwc/pwc-if.c +++ b/drivers/usb/media/pwc/pwc-if.c @@ -154,6 +154,7 @@ static struct file_operations pwc_fops = { .poll = pwc_video_poll, .mmap = pwc_video_mmap, .ioctl = pwc_video_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static struct video_device pwc_template = { diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c index b2ae29af5940..2ba562285fda 100644 --- a/drivers/usb/media/se401.c +++ b/drivers/usb/media/se401.c @@ -1193,6 +1193,7 @@ static struct file_operations se401_fops = { .read = se401_read, .mmap = se401_mmap, .ioctl = se401_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static struct video_device se401_template = { diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c index 774038b352cd..b497a6a0a206 100644 --- a/drivers/usb/media/stv680.c +++ b/drivers/usb/media/stv680.c @@ -1343,6 +1343,7 @@ static struct file_operations stv680_fops = { .read = stv680_read, .mmap = stv680_mmap, .ioctl = stv680_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static struct video_device stv680_template = { diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c index 4bd113325ef9..63a72e550a1b 100644 --- a/drivers/usb/media/usbvideo.c +++ b/drivers/usb/media/usbvideo.c @@ -953,6 +953,7 @@ static struct file_operations usbvideo_fops = { .read = usbvideo_v4l_read, .mmap = usbvideo_v4l_mmap, .ioctl = usbvideo_v4l_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static const struct video_device usbvideo_template = { diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c index 1c73155c8d77..5df144073871 100644 --- a/drivers/usb/media/vicam.c +++ b/drivers/usb/media/vicam.c @@ -1236,6 +1236,7 @@ static struct file_operations vicam_fops = { .read = vicam_read, .mmap = vicam_mmap, .ioctl = vicam_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index 3605a6f3067b..bff9434c8e55 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -3490,6 +3490,7 @@ static struct file_operations w9968cf_fops = { .release = w9968cf_release, .read = w9968cf_read, .ioctl = w9968cf_ioctl, + .compat_ioctl = v4l_compat_ioctl32, .mmap = w9968cf_mmap, .llseek = no_llseek, }; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index af18355e94cc..4e9637eb6137 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -357,7 +357,7 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m } while (retval != 5 && retval != ENODEV); if (retval != 5) { - err("%s - failed to retreive serial line settings - %d", __FUNCTION__, retval); + err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval); return retval; } else { spin_lock_irqsave(&priv->lock, flags); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 8bc8337c99c4..4dd6865d32b0 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -584,7 +584,7 @@ static struct usb_serial_driver *search_serial_device(struct usb_interface *ifac const struct usb_device_id *id; struct usb_serial_driver *t; - /* List trough know devices and see if the usb id matches */ + /* Check if the usb id matches a known device */ list_for_each(p, &usb_serial_driver_list) { t = list_entry(p, struct usb_serial_driver, driver_list); id = usb_match_id(iface, t->id_table); diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c index ea7c86306918..7f9838dceab5 100644 --- a/drivers/video/aty/radeon_monitor.c +++ b/drivers/video/aty/radeon_monitor.c @@ -423,7 +423,7 @@ static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo, /* * Probe display on both primary and secondary card's connector (if any) * by various available techniques (i2c, OF device tree, BIOS, ...) and - * try to retreive EDID. The algorithm here comes from XFree's radeon + * try to retrieve EDID. The algorithm here comes from XFree's radeon * driver */ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo, diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index a9300f930ef2..55a3514157ed 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -50,7 +50,6 @@ #include <linux/init.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/pgtable.h> #include <asm/system.h> #include <asm/uaccess.h> diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile index d0244c04af5a..4ef5cd19609d 100644 --- a/drivers/video/logo/Makefile +++ b/drivers/video/logo/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_LOGO_M32R_CLUT224) += logo_m32r_clut224.o # How to generate logo's -# Use logo-cfiles to retreive list of .c files to be built +# Use logo-cfiles to retrieve list of .c files to be built logo-cfiles = $(notdir $(patsubst %.$(2), %.c, \ $(wildcard $(srctree)/$(src)/*$(1).$(2)))) diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 2ea1354e439f..087e58689e4c 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -178,7 +178,6 @@ #include <asm/hardware.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/mach-types.h> #include <asm/uaccess.h> #include <asm/arch/assabet.h> @@ -1455,7 +1454,11 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) static int __init sa1100fb_probe(struct platform_device *pdev) { struct sa1100fb_info *fbi; - int ret; + int ret, irq; + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) + return -EINVAL; if (!request_mem_region(0xb0100000, 0x10000, "LCD")) return -EBUSY; @@ -1470,7 +1473,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev) if (ret) goto failed; - ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT, + ret = request_irq(irq, sa1100fb_handle_irq, SA_INTERRUPT, "LCD", fbi); if (ret) { printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); @@ -1492,7 +1495,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev) ret = register_framebuffer(&fbi->fb); if (ret < 0) - goto failed; + goto err_free_irq; #ifdef CONFIG_CPU_FREQ fbi->freq_transition.notifier_call = sa1100fb_freq_transition; @@ -1504,7 +1507,9 @@ static int __init sa1100fb_probe(struct platform_device *pdev) /* This driver cannot be unloaded at the moment */ return 0; -failed: + err_free_irq: + free_irq(irq, fbi); + failed: platform_set_drvdata(pdev, NULL); kfree(fbi); release_mem_region(0xb0100000, 0x10000); diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index 9a1e00dd3e02..4baf61a22327 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -3,7 +3,7 @@ menu "Dallas's 1-wire bus" config W1 tristate "Dallas's 1-wire support" ---help--- - Dallas's 1-wire bus is usefull to connect slow 1-pin devices + Dallas's 1-wire bus is useful to connect slow 1-pin devices such as iButtons and thermal sensors. If you want W1 support, you should say Y here. diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index d933ef1fbd8a..a17b28854288 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -663,7 +663,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, } /** - * v9fs_vfs_getattr - retreive file metadata + * v9fs_vfs_getattr - retrieve file metadata * @mnt - mount information * @dentry - file to get attributes on * @stat - metadata structure to populate diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 9ebe881c6786..44d439cb69f4 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -244,10 +244,10 @@ affs_put_inode(struct inode *inode) pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); affs_free_prealloc(inode); if (atomic_read(&inode->i_count) == 1) { - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (inode->i_size != AFFS_I(inode)->mmu_private) affs_truncate(inode); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } } diff --git a/fs/autofs/root.c b/fs/autofs/root.c index a1ab1c0ed215..808134a5a2fa 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -229,9 +229,9 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr dentry->d_flags |= DCACHE_AUTOFS_PENDING; d_add(dentry, NULL); - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); autofs_revalidate(dentry, nd); - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); /* * If we are still pending, check if we had to handle diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 2241405ffc41..541b19e6fec9 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -489,9 +489,9 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s d_add(dentry, NULL); if (dentry->d_op && dentry->d_op->d_revalidate) { - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); (dentry->d_op->d_revalidate)(dentry, nd); - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); } /* diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 2568eb41cb3a..9ccc7d8275b8 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -588,11 +588,11 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer, case 2: set_bit(Enabled, &e->flags); break; case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root); - down(&root->d_inode->i_sem); + mutex_lock(&root->d_inode->i_mutex); kill_node(e); - up(&root->d_inode->i_sem); + mutex_unlock(&root->d_inode->i_mutex); dput(root); break; default: return res; @@ -622,7 +622,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer, return PTR_ERR(e); root = dget(sb->s_root); - down(&root->d_inode->i_sem); + mutex_lock(&root->d_inode->i_mutex); dentry = lookup_one_len(e->name, root, strlen(e->name)); err = PTR_ERR(dentry); if (IS_ERR(dentry)) @@ -658,7 +658,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer, out2: dput(dentry); out: - up(&root->d_inode->i_sem); + mutex_unlock(&root->d_inode->i_mutex); dput(root); if (err) { @@ -703,12 +703,12 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer, case 1: enabled = 0; break; case 2: enabled = 1; break; case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root); - down(&root->d_inode->i_sem); + mutex_lock(&root->d_inode->i_mutex); while (!list_empty(&entries)) kill_node(list_entry(entries.next, Node, list)); - up(&root->d_inode->i_sem); + mutex_unlock(&root->d_inode->i_mutex); dput(root); default: return res; } diff --git a/fs/block_dev.c b/fs/block_dev.c index e0df94c37b7e..6e50346fb1ee 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -202,7 +202,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin) loff_t size; loff_t retval; - down(&bd_inode->i_sem); + mutex_lock(&bd_inode->i_mutex); size = i_size_read(bd_inode); switch (origin) { @@ -219,7 +219,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin) } retval = offset; } - up(&bd_inode->i_sem); + mutex_unlock(&bd_inode->i_mutex); return retval; } diff --git a/fs/buffer.c b/fs/buffer.c index 55f0975a9b15..6466bc8a3dc7 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -352,11 +352,11 @@ static long do_fsync(unsigned int fd, int datasync) * We need to protect against concurrent writers, * which could cause livelocks in fsync_buffers_list */ - down(&mapping->host->i_sem); + mutex_lock(&mapping->host->i_mutex); err = file->f_op->fsync(file, file->f_dentry, datasync); if (!ret) ret = err; - up(&mapping->host->i_sem); + mutex_unlock(&mapping->host->i_mutex); err = filemap_fdatawait(mapping); if (!ret) ret = err; @@ -2338,7 +2338,7 @@ int generic_commit_write(struct file *file, struct page *page, __block_commit_write(inode,page,from,to); /* * No need to use i_size_read() here, the i_size - * cannot change under us because we hold i_sem. + * cannot change under us because we hold i_mutex. */ if (pos > inode->i_size) { i_size_write(inode, pos); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2a13a2bac8f1..e10213b7541e 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -860,9 +860,9 @@ static int cifs_oplock_thread(void * dummyarg) DeleteOplockQEntry(oplock_item); /* can not grab inode sem here since it would deadlock when oplock received on delete - since vfs_unlink holds the i_sem across + since vfs_unlink holds the i_mutex across the call */ - /* down(&inode->i_sem);*/ + /* mutex_lock(&inode->i_mutex);*/ if (S_ISREG(inode->i_mode)) { rc = filemap_fdatawrite(inode->i_mapping); if(CIFS_I(inode)->clientCanCacheRead == 0) { @@ -871,7 +871,7 @@ static int cifs_oplock_thread(void * dummyarg) } } else rc = 0; - /* up(&inode->i_sem);*/ + /* mutex_unlock(&inode->i_mutex);*/ if (rc) CIFS_I(inode)->write_behind_rc = rc; cFYI(1,("Oplock flush inode %p rc %d",inode,rc)); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9558f51bca55..3ebce9430f4a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1040,9 +1040,9 @@ int cifs_revalidate(struct dentry *direntry) } /* can not grab this sem since kernel filesys locking documentation - indicates i_sem may be taken by the kernel on lookup and rename - which could deadlock if we grab the i_sem here as well */ -/* down(&direntry->d_inode->i_sem);*/ + indicates i_mutex may be taken by the kernel on lookup and rename + which could deadlock if we grab the i_mutex here as well */ +/* mutex_lock(&direntry->d_inode->i_mutex);*/ /* need to write out dirty pages here */ if (direntry->d_inode->i_mapping) { /* do we need to lock inode until after invalidate completes @@ -1066,7 +1066,7 @@ int cifs_revalidate(struct dentry *direntry) } } } -/* up(&direntry->d_inode->i_sem); */ +/* mutex_unlock(&direntry->d_inode->i_mutex); */ kfree(full_path); FreeXid(xid); diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 2391766e9c7c..8f1a517f8b4e 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -453,7 +453,7 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir) coda_vfs_stat.readdir++; host_inode = host_file->f_dentry->d_inode; - down(&host_inode->i_sem); + mutex_lock(&host_inode->i_mutex); host_file->f_pos = coda_file->f_pos; if (!host_file->f_op->readdir) { @@ -475,7 +475,7 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir) } out: coda_file->f_pos = host_file->f_pos; - up(&host_inode->i_sem); + mutex_unlock(&host_inode->i_mutex); return ret; } diff --git a/fs/coda/file.c b/fs/coda/file.c index e6bc022568f3..30b4630bd735 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -77,14 +77,14 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo return -EINVAL; host_inode = host_file->f_dentry->d_inode; - down(&coda_inode->i_sem); + mutex_lock(&coda_inode->i_mutex); ret = host_file->f_op->write(host_file, buf, count, ppos); coda_inode->i_size = host_inode->i_size; coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9; coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME_SEC; - up(&coda_inode->i_sem); + mutex_unlock(&coda_inode->i_mutex); return ret; } @@ -272,9 +272,9 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) if (host_file->f_op && host_file->f_op->fsync) { host_dentry = host_file->f_dentry; host_inode = host_dentry->d_inode; - down(&host_inode->i_sem); + mutex_lock(&host_inode->i_mutex); err = host_file->f_op->fsync(host_file, host_dentry, datasync); - up(&host_inode->i_sem); + mutex_unlock(&host_inode->i_mutex); } if ( !err && !datasync ) { diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 43a2508ac696..55d9a3a954cf 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -207,244 +207,6 @@ static int do_ext3_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg)); } -struct video_tuner32 { - compat_int_t tuner; - char name[32]; - compat_ulong_t rangelow, rangehigh; - u32 flags; /* It is really u32 in videodev.h */ - u16 mode, signal; -}; - -static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) -{ - int i; - - if(get_user(kp->tuner, &up->tuner)) - return -EFAULT; - for(i = 0; i < 32; i++) - __get_user(kp->name[i], &up->name[i]); - __get_user(kp->rangelow, &up->rangelow); - __get_user(kp->rangehigh, &up->rangehigh); - __get_user(kp->flags, &up->flags); - __get_user(kp->mode, &up->mode); - __get_user(kp->signal, &up->signal); - return 0; -} - -static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) -{ - int i; - - if(put_user(kp->tuner, &up->tuner)) - return -EFAULT; - for(i = 0; i < 32; i++) - __put_user(kp->name[i], &up->name[i]); - __put_user(kp->rangelow, &up->rangelow); - __put_user(kp->rangehigh, &up->rangehigh); - __put_user(kp->flags, &up->flags); - __put_user(kp->mode, &up->mode); - __put_user(kp->signal, &up->signal); - return 0; -} - -struct video_buffer32 { - compat_caddr_t base; - compat_int_t height, width, depth, bytesperline; -}; - -static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) -{ - u32 tmp; - - if (get_user(tmp, &up->base)) - return -EFAULT; - - /* This is actually a physical address stored - * as a void pointer. - */ - kp->base = (void *)(unsigned long) tmp; - - __get_user(kp->height, &up->height); - __get_user(kp->width, &up->width); - __get_user(kp->depth, &up->depth); - __get_user(kp->bytesperline, &up->bytesperline); - return 0; -} - -static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) -{ - u32 tmp = (u32)((unsigned long)kp->base); - - if(put_user(tmp, &up->base)) - return -EFAULT; - __put_user(kp->height, &up->height); - __put_user(kp->width, &up->width); - __put_user(kp->depth, &up->depth); - __put_user(kp->bytesperline, &up->bytesperline); - return 0; -} - -struct video_clip32 { - s32 x, y, width, height; /* Its really s32 in videodev.h */ - compat_caddr_t next; -}; - -struct video_window32 { - u32 x, y, width, height, chromakey, flags; - compat_caddr_t clips; - compat_int_t clipcount; -}; - -/* You get back everything except the clips... */ -static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) -{ - if(put_user(kp->x, &up->x)) - return -EFAULT; - __put_user(kp->y, &up->y); - __put_user(kp->width, &up->width); - __put_user(kp->height, &up->height); - __put_user(kp->chromakey, &up->chromakey); - __put_user(kp->flags, &up->flags); - __put_user(kp->clipcount, &up->clipcount); - return 0; -} - -#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) -#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) -#define VIDIOCGWIN32 _IOR('v',9, struct video_window32) -#define VIDIOCSWIN32 _IOW('v',10, struct video_window32) -#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32) -#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32) -#define VIDIOCGFREQ32 _IOR('v',14, u32) -#define VIDIOCSFREQ32 _IOW('v',15, u32) - -enum { - MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip) -}; - -static int do_set_window(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct video_window32 __user *up = compat_ptr(arg); - struct video_window __user *vw; - struct video_clip __user *p; - int nclips; - u32 n; - - if (get_user(nclips, &up->clipcount)) - return -EFAULT; - - /* Peculiar interface... */ - if (nclips < 0) - nclips = VIDEO_CLIPMAP_SIZE; - - if (nclips > MaxClips) - return -ENOMEM; - - vw = compat_alloc_user_space(sizeof(struct video_window) + - nclips * sizeof(struct video_clip)); - - p = nclips ? (struct video_clip __user *)(vw + 1) : NULL; - - if (get_user(n, &up->x) || put_user(n, &vw->x) || - get_user(n, &up->y) || put_user(n, &vw->y) || - get_user(n, &up->width) || put_user(n, &vw->width) || - get_user(n, &up->height) || put_user(n, &vw->height) || - get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) || - get_user(n, &up->flags) || put_user(n, &vw->flags) || - get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) || - get_user(n, &up->clips) || put_user(p, &vw->clips)) - return -EFAULT; - - if (nclips) { - struct video_clip32 __user *u = compat_ptr(n); - int i; - if (!u) - return -EINVAL; - for (i = 0; i < nclips; i++, u++, p++) { - s32 v; - if (get_user(v, &u->x) || - put_user(v, &p->x) || - get_user(v, &u->y) || - put_user(v, &p->y) || - get_user(v, &u->width) || - put_user(v, &p->width) || - get_user(v, &u->height) || - put_user(v, &p->height) || - put_user(NULL, &p->next)) - return -EFAULT; - } - } - - return sys_ioctl(fd, VIDIOCSWIN, (unsigned long)p); -} - -static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - union { - struct video_tuner vt; - struct video_buffer vb; - struct video_window vw; - unsigned long vx; - } karg; - mm_segment_t old_fs = get_fs(); - void __user *up = compat_ptr(arg); - int err = 0; - - /* First, convert the command. */ - switch(cmd) { - case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; - case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; - case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; - case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; - case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; - case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; - case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; - }; - - switch(cmd) { - case VIDIOCSTUNER: - case VIDIOCGTUNER: - err = get_video_tuner32(&karg.vt, up); - break; - - case VIDIOCSFBUF: - err = get_video_buffer32(&karg.vb, up); - break; - - case VIDIOCSFREQ: - err = get_user(karg.vx, (u32 __user *)up); - break; - }; - if(err) - goto out; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&karg); - set_fs(old_fs); - - if(err == 0) { - switch(cmd) { - case VIDIOCGTUNER: - err = put_video_tuner32(&karg.vt, up); - break; - - case VIDIOCGWIN: - err = put_video_window32(&karg.vw, up); - break; - - case VIDIOCGFBUF: - err = put_video_buffer32(&karg.vb, up); - break; - - case VIDIOCGFREQ: - err = put_user(((u32)karg.vx), (u32 __user *)up); - break; - }; - } -out: - return err; -} - struct compat_dmx_event { dmx_event_t event; compat_time_t timeStamp; @@ -3015,14 +2777,6 @@ COMPATIBLE_IOCTL(EXT3_IOC_GROUP_ADD) #ifdef CONFIG_JBD_DEBUG HANDLE_IOCTL(EXT3_IOC32_WAIT_FOR_READONLY, do_ext3_ioctl) #endif -HANDLE_IOCTL(VIDIOCGTUNER32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSTUNER32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGWIN32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSWIN32, do_set_window) -HANDLE_IOCTL(VIDIOCGFBUF32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl) /* One SMB ioctl needs translations. */ #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid) diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index e48b539243a1..b668ec61527e 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -288,10 +288,10 @@ static struct dentry * configfs_lookup(struct inode *dir, /* * Only subdirectories count here. Files (CONFIGFS_NOT_PINNED) are - * attributes and are removed by rmdir(). We recurse, taking i_sem + * attributes and are removed by rmdir(). We recurse, taking i_mutex * on all children that are candidates for default detach. If the * result is clean, then configfs_detach_group() will handle dropping - * i_sem. If there is an error, the caller will clean up the i_sem + * i_mutex. If there is an error, the caller will clean up the i_mutex * holders via configfs_detach_rollback(). */ static int configfs_detach_prep(struct dentry *dentry) @@ -309,8 +309,8 @@ static int configfs_detach_prep(struct dentry *dentry) if (sd->s_type & CONFIGFS_NOT_PINNED) continue; if (sd->s_type & CONFIGFS_USET_DEFAULT) { - down(&sd->s_dentry->d_inode->i_sem); - /* Mark that we've taken i_sem */ + mutex_lock(&sd->s_dentry->d_inode->i_mutex); + /* Mark that we've taken i_mutex */ sd->s_type |= CONFIGFS_USET_DROPPING; ret = configfs_detach_prep(sd->s_dentry); @@ -327,7 +327,7 @@ out: } /* - * Walk the tree, dropping i_sem wherever CONFIGFS_USET_DROPPING is + * Walk the tree, dropping i_mutex wherever CONFIGFS_USET_DROPPING is * set. */ static void configfs_detach_rollback(struct dentry *dentry) @@ -341,7 +341,7 @@ static void configfs_detach_rollback(struct dentry *dentry) if (sd->s_type & CONFIGFS_USET_DROPPING) { sd->s_type &= ~CONFIGFS_USET_DROPPING; - up(&sd->s_dentry->d_inode->i_sem); + mutex_unlock(&sd->s_dentry->d_inode->i_mutex); } } } @@ -424,11 +424,11 @@ static void detach_groups(struct config_group *group) /* * From rmdir/unregister, a configfs_detach_prep() pass - * has taken our i_sem for us. Drop it. + * has taken our i_mutex for us. Drop it. * From mkdir/register cleanup, there is no sem held. */ if (sd->s_type & CONFIGFS_USET_DROPPING) - up(&child->d_inode->i_sem); + mutex_unlock(&child->d_inode->i_mutex); d_delete(child); dput(child); @@ -493,11 +493,11 @@ static int populate_groups(struct config_group *group) /* FYI, we're faking mkdir here * I'm not sure we need this semaphore, as we're called * from our parent's mkdir. That holds our parent's - * i_sem, so afaik lookup cannot continue through our + * i_mutex, so afaik lookup cannot continue through our * parent to find us, let alone mess with our tree. - * That said, taking our i_sem is closer to mkdir + * That said, taking our i_mutex is closer to mkdir * emulation, and shouldn't hurt. */ - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); for (i = 0; group->default_groups[i]; i++) { new_group = group->default_groups[i]; @@ -507,7 +507,7 @@ static int populate_groups(struct config_group *group) break; } - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); } if (ret) @@ -856,7 +856,7 @@ int configfs_rename_dir(struct config_item * item, const char *new_name) down_write(&configfs_rename_sem); parent = item->parent->dentry; - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); if (!IS_ERR(new_dentry)) { @@ -872,7 +872,7 @@ int configfs_rename_dir(struct config_item * item, const char *new_name) error = -EEXIST; dput(new_dentry); } - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); up_write(&configfs_rename_sem); return error; @@ -884,9 +884,9 @@ static int configfs_dir_open(struct inode *inode, struct file *file) struct dentry * dentry = file->f_dentry; struct configfs_dirent * parent_sd = dentry->d_fsdata; - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); file->private_data = configfs_new_dirent(parent_sd, NULL); - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); return file->private_data ? 0 : -ENOMEM; @@ -897,9 +897,9 @@ static int configfs_dir_close(struct inode *inode, struct file *file) struct dentry * dentry = file->f_dentry; struct configfs_dirent * cursor = file->private_data; - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); list_del_init(&cursor->s_sibling); - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); release_configfs_dirent(cursor); @@ -975,7 +975,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) { struct dentry * dentry = file->f_dentry; - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); switch (origin) { case 1: offset += file->f_pos; @@ -983,7 +983,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) if (offset >= 0) break; default: - up(&file->f_dentry->d_inode->i_sem); + mutex_unlock(&file->f_dentry->d_inode->i_mutex); return -EINVAL; } if (offset != file->f_pos) { @@ -1007,7 +1007,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) list_add_tail(&cursor->s_sibling, p); } } - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); return offset; } @@ -1037,7 +1037,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) sd = configfs_sb->s_root->d_fsdata; link_group(to_config_group(sd->s_element), group); - down(&configfs_sb->s_root->d_inode->i_sem); + mutex_lock(&configfs_sb->s_root->d_inode->i_mutex); name.name = group->cg_item.ci_name; name.len = strlen(name.name); @@ -1057,7 +1057,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) else d_delete(dentry); - up(&configfs_sb->s_root->d_inode->i_sem); + mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex); if (dentry) { dput(dentry); @@ -1079,18 +1079,18 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys) return; } - down(&configfs_sb->s_root->d_inode->i_sem); - down(&dentry->d_inode->i_sem); + mutex_lock(&configfs_sb->s_root->d_inode->i_mutex); + mutex_lock(&dentry->d_inode->i_mutex); if (configfs_detach_prep(dentry)) { printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n"); } configfs_detach_group(&group->cg_item); dentry->d_inode->i_flags |= S_DEAD; - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); d_delete(dentry); - up(&configfs_sb->s_root->d_inode->i_sem); + mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex); dput(dentry); diff --git a/fs/configfs/file.c b/fs/configfs/file.c index af1ffc9a15c0..c26cd61f13af 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c @@ -336,9 +336,9 @@ int configfs_add_file(struct dentry * dir, const struct configfs_attribute * att umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG; int error = 0; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type); - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); return error; } diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index 6b274c6d428f..6577c588de9d 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c @@ -122,7 +122,7 @@ const unsigned char * configfs_get_name(struct configfs_dirent *sd) /* * Unhashes the dentry corresponding to given configfs_dirent - * Called with parent inode's i_sem held. + * Called with parent inode's i_mutex held. */ void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent) { @@ -145,7 +145,7 @@ void configfs_hash_and_remove(struct dentry * dir, const char * name) struct configfs_dirent * sd; struct configfs_dirent * parent_sd = dir->d_fsdata; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { if (!sd->s_element) continue; @@ -156,7 +156,7 @@ void configfs_hash_and_remove(struct dentry * dir, const char * name) break; } } - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); } diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index a86ac4aeaedb..d4f1a2cddd47 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -146,7 +146,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode, } *dentry = NULL; - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); *dentry = lookup_one_len(name, parent, strlen(name)); if (!IS_ERR(dentry)) { if ((mode & S_IFMT) == S_IFDIR) @@ -155,7 +155,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode, error = debugfs_create(parent->d_inode, *dentry, mode); } else error = PTR_ERR(dentry); - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); return error; } @@ -273,7 +273,7 @@ void debugfs_remove(struct dentry *dentry) if (!parent || !parent->d_inode) return; - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); if (debugfs_positive(dentry)) { if (dentry->d_inode) { if (S_ISDIR(dentry->d_inode->i_mode)) @@ -283,7 +283,7 @@ void debugfs_remove(struct dentry *dentry) dput(dentry); } } - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); simple_release_fs(&debugfs_mount, &debugfs_mount_count); } EXPORT_SYMBOL_GPL(debugfs_remove); diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 1274422a5384..b621521e09d4 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2162,27 +2162,27 @@ static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd) * * make sure that * d_instantiate always runs under lock - * we release i_sem lock before going to sleep + * we release i_mutex lock before going to sleep * * unfortunately sometimes d_revalidate is called with - * and sometimes without i_sem lock held. The following checks + * and sometimes without i_mutex lock held. The following checks * attempt to deduce when we need to add (and drop resp.) lock * here. This relies on current (2.6.2) calling coventions: * - * lookup_hash is always run under i_sem and is passing NULL + * lookup_hash is always run under i_mutex and is passing NULL * as nd * - * open(...,O_CREATE,...) calls _lookup_hash under i_sem + * open(...,O_CREATE,...) calls _lookup_hash under i_mutex * and sets flags to LOOKUP_OPEN|LOOKUP_CREATE * * all other invocations of ->d_revalidate seem to happen - * outside of i_sem + * outside of i_mutex */ need_lock = nd && (!(nd->flags & LOOKUP_CREATE) || (nd->flags & LOOKUP_PARENT)); if (need_lock) - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); if (is_devfsd_or_child(fs_info)) { devfs_handle_t de = lookup_info->de; @@ -2221,9 +2221,9 @@ static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd) add_wait_queue(&lookup_info->wait_queue, &wait); read_unlock(&parent->u.dir.lock); /* at this point it is always (hopefully) locked */ - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); schedule(); - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); /* * This does not need nor should remove wait from wait_queue. * Wait queue head is never reused - nothing is ever added to it @@ -2238,7 +2238,7 @@ static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd) out: if (need_lock) - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); return 1; } /* End Function devfs_d_revalidate_wait */ @@ -2284,9 +2284,9 @@ static struct dentry *devfs_lookup(struct inode *dir, struct dentry *dentry, /* Unlock directory semaphore, which will release any waiters. They will get the hashed dentry, and may be forced to wait for revalidation */ - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); wait_for_devfsd_finished(fs_info); /* If I'm not devfsd, must wait */ - down(&dir->i_sem); /* Grab it again because them's the rules */ + mutex_lock(&dir->i_mutex); /* Grab it again because them's the rules */ de = lookup_info.de; /* If someone else has been so kind as to make the inode, we go home early */ diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index f2be44d4491f..bfb8a230bac9 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -130,7 +130,7 @@ static struct dentry *get_node(int num) { char s[12]; struct dentry *root = devpts_root; - down(&root->d_inode->i_sem); + mutex_lock(&root->d_inode->i_mutex); return lookup_one_len(s, root, sprintf(s, "%d", num)); } @@ -161,7 +161,7 @@ int devpts_pty_new(struct tty_struct *tty) if (!IS_ERR(dentry) && !dentry->d_inode) d_instantiate(dentry, inode); - up(&devpts_root->d_inode->i_sem); + mutex_unlock(&devpts_root->d_inode->i_mutex); return 0; } @@ -178,7 +178,7 @@ struct tty_struct *devpts_get_tty(int number) dput(dentry); } - up(&devpts_root->d_inode->i_sem); + mutex_unlock(&devpts_root->d_inode->i_mutex); return tty; } @@ -196,7 +196,7 @@ void devpts_pty_kill(int number) } dput(dentry); } - up(&devpts_root->d_inode->i_sem); + mutex_unlock(&devpts_root->d_inode->i_mutex); } static int __init init_devpts_fs(void) diff --git a/fs/direct-io.c b/fs/direct-io.c index 3931e7f1e6bf..30dbbd1df511 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -56,7 +56,7 @@ * lock_type is DIO_LOCKING for regular files on direct-IO-naive filesystems. * This determines whether we need to do the fancy locking which prevents * direct-IO from being able to read uninitialised disk blocks. If its zero - * (blockdev) this locking is not done, and if it is DIO_OWN_LOCKING i_sem is + * (blockdev) this locking is not done, and if it is DIO_OWN_LOCKING i_mutex is * not held for the entire direct write (taken briefly, initially, during a * direct read though, but its never held for the duration of a direct-IO). */ @@ -930,7 +930,7 @@ out: } /* - * Releases both i_sem and i_alloc_sem + * Releases both i_mutex and i_alloc_sem */ static ssize_t direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, @@ -1062,11 +1062,11 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, /* * All block lookups have been performed. For READ requests - * we can let i_sem go now that its achieved its purpose + * we can let i_mutex go now that its achieved its purpose * of protecting us from looking up uninitialized blocks. */ if ((rw == READ) && (dio->lock_type == DIO_LOCKING)) - up(&dio->inode->i_sem); + mutex_unlock(&dio->inode->i_mutex); /* * OK, all BIOs are submitted, so we can decrement bio_count to truly @@ -1145,18 +1145,18 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, * The locking rules are governed by the dio_lock_type parameter. * * DIO_NO_LOCKING (no locking, for raw block device access) - * For writes, i_sem is not held on entry; it is never taken. + * For writes, i_mutex is not held on entry; it is never taken. * * DIO_LOCKING (simple locking for regular files) - * For writes we are called under i_sem and return with i_sem held, even though + * For writes we are called under i_mutex and return with i_mutex held, even though * it is internally dropped. - * For reads, i_sem is not held on entry, but it is taken and dropped before + * For reads, i_mutex is not held on entry, but it is taken and dropped before * returning. * * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of * uninitialised data, allowing parallel direct readers and writers) - * For writes we are called without i_sem, return without it, never touch it. - * For reads, i_sem is held on entry and will be released before returning. + * For writes we are called without i_mutex, return without it, never touch it. + * For reads, i_mutex is held on entry and will be released before returning. * * Additional i_alloc_sem locking requirements described inline below. */ @@ -1214,11 +1214,11 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, * For block device access DIO_NO_LOCKING is used, * neither readers nor writers do any locking at all * For regular files using DIO_LOCKING, - * readers need to grab i_sem and i_alloc_sem - * writers need to grab i_alloc_sem only (i_sem is already held) + * readers need to grab i_mutex and i_alloc_sem + * writers need to grab i_alloc_sem only (i_mutex is already held) * For regular files using DIO_OWN_LOCKING, * neither readers nor writers take any locks here - * (i_sem is already held and release for writers here) + * (i_mutex is already held and release for writers here) */ dio->lock_type = dio_lock_type; if (dio_lock_type != DIO_NO_LOCKING) { @@ -1228,7 +1228,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, mapping = iocb->ki_filp->f_mapping; if (dio_lock_type != DIO_OWN_LOCKING) { - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); reader_with_isem = 1; } @@ -1240,7 +1240,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, } if (dio_lock_type == DIO_OWN_LOCKING) { - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); reader_with_isem = 0; } } @@ -1266,7 +1266,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, out: if (reader_with_isem) - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); if (rw & WRITE) current->flags &= ~PF_SYNCWRITE; return retval; diff --git a/fs/dquot.c b/fs/dquot.c index 2a62b3dc20ec..cb6d5bfbdfd5 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -100,7 +100,7 @@ * operation is just reading pointers from inode (or not using them at all) the * read lock is enough. If pointers are altered function must hold write lock * (these locking rules also apply for S_NOQUOTA flag in the inode - note that - * for altering the flag i_sem is also needed). If operation is holding + * for altering the flag i_mutex is also needed). If operation is holding * reference to dquot in other way (e.g. quotactl ops) it must be guarded by * dqonoff_sem. * This locking assures that: @@ -117,9 +117,9 @@ * spinlock to internal buffers before writing. * * Lock ordering (including related VFS locks) is the following: - * i_sem > dqonoff_sem > iprune_sem > journal_lock > dqptr_sem > + * i_mutex > dqonoff_sem > iprune_sem > journal_lock > dqptr_sem > * > dquot->dq_lock > dqio_sem - * i_sem on quota files is special (it's below dqio_sem) + * i_mutex on quota files is special (it's below dqio_sem) */ static DEFINE_SPINLOCK(dq_list_lock); @@ -1369,11 +1369,11 @@ int vfs_quota_off(struct super_block *sb, int type) /* If quota was reenabled in the meantime, we have * nothing to do */ if (!sb_has_quota_enabled(sb, cnt)) { - down(&toputinode[cnt]->i_sem); + mutex_lock(&toputinode[cnt]->i_mutex); toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | S_NOATIME | S_NOQUOTA); truncate_inode_pages(&toputinode[cnt]->i_data, 0); - up(&toputinode[cnt]->i_sem); + mutex_unlock(&toputinode[cnt]->i_mutex); mark_inode_dirty(toputinode[cnt]); iput(toputinode[cnt]); } @@ -1417,7 +1417,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) write_inode_now(inode, 1); /* And now flush the block cache so that kernel sees the changes */ invalidate_bdev(sb->s_bdev, 0); - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); down(&dqopt->dqonoff_sem); if (sb_has_quota_enabled(sb, type)) { error = -EBUSY; @@ -1449,7 +1449,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) goto out_file_init; } up(&dqopt->dqio_sem); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); set_enable_flags(dqopt, type); add_dquot_ref(sb, type); @@ -1470,7 +1470,7 @@ out_lock: inode->i_flags |= oldflags; up_write(&dqopt->dqptr_sem); } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); out_fmt: put_quota_format(fmt); diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index c49d6254379a..5bfe40085fbc 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -177,9 +177,9 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, struct dentry *ppd; struct dentry *npd; - down(&pd->d_inode->i_sem); + mutex_lock(&pd->d_inode->i_mutex); ppd = CALL(nops,get_parent)(pd); - up(&pd->d_inode->i_sem); + mutex_unlock(&pd->d_inode->i_mutex); if (IS_ERR(ppd)) { err = PTR_ERR(ppd); @@ -201,9 +201,9 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, break; } dprintk("find_exported_dentry: found name: %s\n", nbuf); - down(&ppd->d_inode->i_sem); + mutex_lock(&ppd->d_inode->i_mutex); npd = lookup_one_len(nbuf, ppd, strlen(nbuf)); - up(&ppd->d_inode->i_sem); + mutex_unlock(&ppd->d_inode->i_mutex); if (IS_ERR(npd)) { err = PTR_ERR(npd); dprintk("find_exported_dentry: lookup failed: %d\n", err); @@ -242,9 +242,9 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, struct dentry *nresult; err = CALL(nops,get_name)(target_dir, nbuf, result); if (!err) { - down(&target_dir->d_inode->i_sem); + mutex_lock(&target_dir->d_inode->i_mutex); nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf)); - up(&target_dir->d_inode->i_sem); + mutex_unlock(&target_dir->d_inode->i_mutex); if (!IS_ERR(nresult)) { if (nresult->d_inode) { dput(result); diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 6af2f4130290..239133d01d91 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -149,7 +149,7 @@ ext2_iset_acl(struct inode *inode, struct posix_acl **i_acl, } /* - * inode->i_sem: don't care + * inode->i_mutex: don't care */ static struct posix_acl * ext2_get_acl(struct inode *inode, int type) @@ -211,7 +211,7 @@ ext2_get_acl(struct inode *inode, int type) } /* - * inode->i_sem: down + * inode->i_mutex: down */ static int ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) @@ -301,8 +301,8 @@ ext2_permission(struct inode *inode, int mask, struct nameidata *nd) /* * Initialize the ACLs of a new inode. Called from ext2_new_inode. * - * dir->i_sem: down - * inode->i_sem: up (access to inode is still exclusive) + * dir->i_mutex: down + * inode->i_mutex: up (access to inode is still exclusive) */ int ext2_init_acl(struct inode *inode, struct inode *dir) @@ -361,7 +361,7 @@ cleanup: * for directories) are added. There are no more bits available in the * file mode. * - * inode->i_sem: down + * inode->i_mutex: down */ int ext2_acl_chmod(struct inode *inode) diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index e977f8566d14..00de0a7312a2 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -53,7 +53,7 @@ struct ext2_inode_info { #ifdef CONFIG_EXT2_FS_XATTR /* * Extended attributes can be read independently of the main file - * data. Taking i_sem even when reading would cause contention + * data. Taking i_mutex even when reading would cause contention * between readers of EAs and writers of regular file data, so * instead we synchronize on xattr_sem when reading or changing * EAs. diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 522fa70dd8ea..8d6819846fc9 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -1152,7 +1152,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type, struct buffer_head tmp_bh; struct buffer_head *bh; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); while (towrite > 0) { tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; @@ -1189,7 +1189,7 @@ out: inode->i_version++; inode->i_mtime = inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return len - towrite; } diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 0099462d4271..f7a3b5fee274 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -325,7 +325,7 @@ cleanup: /* * Inode operation listxattr() * - * dentry->d_inode->i_sem: don't care + * dentry->d_inode->i_mutex: don't care */ ssize_t ext2_listxattr(struct dentry *dentry, char *buffer, size_t size) diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index 3ac38266fc9e..9ed132c96034 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -152,7 +152,7 @@ ext3_iset_acl(struct inode *inode, struct posix_acl **i_acl, /* * Inode operation get_posix_acl(). * - * inode->i_sem: don't care + * inode->i_mutex: don't care */ static struct posix_acl * ext3_get_acl(struct inode *inode, int type) @@ -216,7 +216,7 @@ ext3_get_acl(struct inode *inode, int type) /* * Set the access or default ACL of an inode. * - * inode->i_sem: down unless called from ext3_new_inode + * inode->i_mutex: down unless called from ext3_new_inode */ static int ext3_set_acl(handle_t *handle, struct inode *inode, int type, @@ -306,8 +306,8 @@ ext3_permission(struct inode *inode, int mask, struct nameidata *nd) /* * Initialize the ACLs of a new inode. Called from ext3_new_inode. * - * dir->i_sem: down - * inode->i_sem: up (access to inode is still exclusive) + * dir->i_mutex: down + * inode->i_mutex: up (access to inode is still exclusive) */ int ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) @@ -368,7 +368,7 @@ cleanup: * for directories) are added. There are no more bits available in the * file mode. * - * inode->i_sem: down + * inode->i_mutex: down */ int ext3_acl_chmod(struct inode *inode) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 7c45acf94589..56bf76586019 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2150,7 +2150,7 @@ int ext3_force_commit(struct super_block *sb) static void ext3_write_super (struct super_block * sb) { - if (down_trylock(&sb->s_lock) == 0) + if (mutex_trylock(&sb->s_lock) != 0) BUG(); sb->s_dirt = 0; } @@ -2601,7 +2601,7 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type, struct buffer_head *bh; handle_t *handle = journal_current_handle(); - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); while (towrite > 0) { tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; @@ -2644,7 +2644,7 @@ out: inode->i_version++; inode->i_mtime = inode->i_ctime = CURRENT_TIME; ext3_mark_inode_dirty(handle, inode); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return len - towrite; } diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 430de9f63be3..238199d82ce5 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -140,7 +140,7 @@ ext3_xattr_handler(int name_index) /* * Inode operation listxattr() * - * dentry->d_inode->i_sem: don't care + * dentry->d_inode->i_mutex: don't care */ ssize_t ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) diff --git a/fs/fat/dir.c b/fs/fat/dir.c index eef1b81aa294..db0de5c621c7 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -729,13 +729,13 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp, buf.dirent = d1; buf.result = 0; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); ret = -ENOENT; if (!IS_DEADDIR(inode)) { ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir, short_only, both); } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); if (ret >= 0) ret = buf.result; return ret; diff --git a/fs/fat/file.c b/fs/fat/file.c index 9b07c328a6fc..d30876cf35f5 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -41,7 +41,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, if (err) return err; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (IS_RDONLY(inode)) { err = -EROFS; @@ -103,7 +103,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED; mark_inode_dirty(inode); up: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return err; } default: diff --git a/fs/fifo.c b/fs/fifo.c index 5455916241f0..923371b753ab 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -35,7 +35,7 @@ static int fifo_open(struct inode *inode, struct file *filp) int ret; ret = -ERESTARTSYS; - if (down_interruptible(PIPE_SEM(*inode))) + if (mutex_lock_interruptible(PIPE_MUTEX(*inode))) goto err_nolock_nocleanup; if (!inode->i_pipe) { @@ -119,7 +119,7 @@ static int fifo_open(struct inode *inode, struct file *filp) } /* Ok! */ - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); return 0; err_rd: @@ -139,7 +139,7 @@ err: free_pipe_info(inode); err_nocleanup: - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); err_nolock_nocleanup: return ret; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 05dedddf4289..63d2980df5c9 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -560,9 +560,9 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, struct inode *inode = file->f_dentry->d_inode; ssize_t res; /* Don't allow parallel writes to the same file */ - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); res = fuse_direct_io(file, buf, count, ppos, 1); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return res; } diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index d499393a8ae7..050a49276499 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -547,13 +547,13 @@ static int hfs_file_release(struct inode *inode, struct file *file) if (atomic_read(&file->f_count) != 0) return 0; if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) { - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); hfs_file_truncate(inode); //if (inode->i_flags & S_DEAD) { // hfs_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); // hfs_delete_inode(inode); //} - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } return 0; } diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c index c7d316455fa0..9fb51632303c 100644 --- a/fs/hfsplus/bitmap.c +++ b/fs/hfsplus/bitmap.c @@ -29,7 +29,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma return size; dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); - down(&HFSPLUS_SB(sb).alloc_file->i_sem); + mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, (filler_t *)mapping->a_ops->readpage, NULL); @@ -143,7 +143,7 @@ done: sb->s_dirt = 1; dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); out: - up(&HFSPLUS_SB(sb).alloc_file->i_sem); + mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); return start; } @@ -164,7 +164,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) if ((offset + count) > HFSPLUS_SB(sb).total_blocks) return -2; - down(&HFSPLUS_SB(sb).alloc_file->i_sem); + mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; pnr = offset / PAGE_CACHE_BITS; page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL); @@ -215,7 +215,7 @@ out: kunmap(page); HFSPLUS_SB(sb).free_blocks += len; sb->s_dirt = 1; - up(&HFSPLUS_SB(sb).alloc_file->i_sem); + mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); return 0; } diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index fc98583cf045..983bcd02ac1c 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -276,13 +276,13 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) if (atomic_read(&file->f_count) != 0) return 0; if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); hfsplus_file_truncate(inode); if (inode->i_flags & S_DEAD) { hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); hfsplus_delete_inode(inode); } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } return 0; } diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 0217c3a04441..5591f9623aa2 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c @@ -32,19 +32,19 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence) /*printk("dir lseek\n");*/ if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok; - down(&i->i_sem); + mutex_lock(&i->i_mutex); pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1; while (pos != new_off) { if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh); else goto fail; if (pos == 12) goto fail; } - up(&i->i_sem); + mutex_unlock(&i->i_mutex); ok: unlock_kernel(); return filp->f_pos = new_off; fail: - up(&i->i_sem); + mutex_unlock(&i->i_mutex); /*printk("illegal lseek: %016llx\n", new_off);*/ unlock_kernel(); return -ESPIPE; diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index 52930915bad8..a44dc5897399 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -171,12 +171,12 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, err = -ENOMEM; parent = HPPFS_I(ino)->proc_dentry; - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); proc_dentry = d_lookup(parent, &dentry->d_name); if(proc_dentry == NULL){ proc_dentry = d_alloc(parent, &dentry->d_name); if(proc_dentry == NULL){ - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); goto out; } new = (*parent->d_inode->i_op->lookup)(parent->d_inode, @@ -186,7 +186,7 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, proc_dentry = new; } } - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); if(IS_ERR(proc_dentry)) return(proc_dentry); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 8c41315a6e42..ff1b7d108bd0 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -118,7 +118,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) vma_len = (loff_t)(vma->vm_end - vma->vm_start); - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); file_accessed(file); vma->vm_flags |= VM_HUGETLB | VM_RESERVED; vma->vm_ops = &hugetlb_vm_ops; @@ -133,7 +133,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) if (inode->i_size < len) inode->i_size = len; out: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return ret; } diff --git a/fs/inode.c b/fs/inode.c index fd568caf7f74..e08767fd57b0 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -192,7 +192,7 @@ void inode_init_once(struct inode *inode) INIT_HLIST_NODE(&inode->i_hash); INIT_LIST_HEAD(&inode->i_dentry); INIT_LIST_HEAD(&inode->i_devices); - sema_init(&inode->i_sem, 1); + mutex_init(&inode->i_mutex); init_rwsem(&inode->i_alloc_sem); INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC); rwlock_init(&inode->i_data.tree_lock); diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 2559ee10beda..fc3855a1aef3 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -1415,7 +1415,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, * This will never trigger with sane page sizes. leave it in * anyway, since I'm thinking about how to merge larger writes * (the current idea is to poke a thread that does the actual - * I/O and starts by doing a down(&inode->i_sem). then we + * I/O and starts by doing a mutex_lock(&inode->i_mutex). then we * would need to get the page cache pages and have a list of * I/O requests and do write-merging here. * -- prumpf diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h index c0fd7b3eadc6..dc21a5bd54d4 100644 --- a/fs/jfs/jfs_incore.h +++ b/fs/jfs/jfs_incore.h @@ -58,7 +58,7 @@ struct jfs_inode_info { /* * rdwrlock serializes xtree between reads & writes and synchronizes * changes to special inodes. It's use would be redundant on - * directories since the i_sem taken in the VFS is sufficient. + * directories since the i_mutex taken in the VFS is sufficient. */ struct rw_semaphore rdwrlock; /* @@ -68,7 +68,7 @@ struct jfs_inode_info { * inode is blocked in txBegin or TxBeginAnon */ struct semaphore commit_sem; - /* xattr_sem allows us to access the xattrs without taking i_sem */ + /* xattr_sem allows us to access the xattrs without taking i_mutex */ struct rw_semaphore xattr_sem; lid_t xtlid; /* lid of xtree lock on directory */ #ifdef CONFIG_JFS_POSIX_ACL diff --git a/fs/libfs.c b/fs/libfs.c index 9c50523382e7..63c020e6589e 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -74,7 +74,7 @@ int dcache_dir_close(struct inode *inode, struct file *file) loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) { - down(&file->f_dentry->d_inode->i_sem); + mutex_lock(&file->f_dentry->d_inode->i_mutex); switch (origin) { case 1: offset += file->f_pos; @@ -82,7 +82,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) if (offset >= 0) break; default: - up(&file->f_dentry->d_inode->i_sem); + mutex_unlock(&file->f_dentry->d_inode->i_mutex); return -EINVAL; } if (offset != file->f_pos) { @@ -106,7 +106,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) spin_unlock(&dcache_lock); } } - up(&file->f_dentry->d_inode->i_sem); + mutex_unlock(&file->f_dentry->d_inode->i_mutex); return offset; } @@ -356,7 +356,7 @@ int simple_commit_write(struct file *file, struct page *page, /* * No need to use i_size_read() here, the i_size - * cannot change under us because we hold the i_sem. + * cannot change under us because we hold the i_mutex. */ if (pos > inode->i_size) i_size_write(inode, pos); diff --git a/fs/namei.c b/fs/namei.c index 300eae088d5f..0a8f073435af 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -438,7 +438,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s struct dentry * result; struct inode *dir = parent->d_inode; - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); /* * First re-do the cached lookup just in case it was created * while we waited for the directory semaphore.. @@ -464,7 +464,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s else result = dentry; } - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); return result; } @@ -472,7 +472,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s * Uhhuh! Nasty case: the cache was re-populated while * we waited on the semaphore. Need to revalidate. */ - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); if (result->d_op && result->d_op->d_revalidate) { if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) { dput(result); @@ -1366,7 +1366,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) struct dentry *p; if (p1 == p2) { - down(&p1->d_inode->i_sem); + mutex_lock(&p1->d_inode->i_mutex); return NULL; } @@ -1374,30 +1374,30 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) for (p = p1; p->d_parent != p; p = p->d_parent) { if (p->d_parent == p2) { - down(&p2->d_inode->i_sem); - down(&p1->d_inode->i_sem); + mutex_lock(&p2->d_inode->i_mutex); + mutex_lock(&p1->d_inode->i_mutex); return p; } } for (p = p2; p->d_parent != p; p = p->d_parent) { if (p->d_parent == p1) { - down(&p1->d_inode->i_sem); - down(&p2->d_inode->i_sem); + mutex_lock(&p1->d_inode->i_mutex); + mutex_lock(&p2->d_inode->i_mutex); return p; } } - down(&p1->d_inode->i_sem); - down(&p2->d_inode->i_sem); + mutex_lock(&p1->d_inode->i_mutex); + mutex_lock(&p2->d_inode->i_mutex); return NULL; } void unlock_rename(struct dentry *p1, struct dentry *p2) { - up(&p1->d_inode->i_sem); + mutex_unlock(&p1->d_inode->i_mutex); if (p1 != p2) { - up(&p2->d_inode->i_sem); + mutex_unlock(&p2->d_inode->i_mutex); up(&p1->d_inode->i_sb->s_vfs_rename_sem); } } @@ -1563,14 +1563,14 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) dir = nd->dentry; nd->flags &= ~LOOKUP_PARENT; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); path.dentry = lookup_hash(nd); path.mnt = nd->mnt; do_last: error = PTR_ERR(path.dentry); if (IS_ERR(path.dentry)) { - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); goto exit; } @@ -1579,7 +1579,7 @@ do_last: if (!IS_POSIXACL(dir->d_inode)) mode &= ~current->fs->umask; error = vfs_create(dir->d_inode, path.dentry, mode, nd); - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); dput(nd->dentry); nd->dentry = path.dentry; if (error) @@ -1593,7 +1593,7 @@ do_last: /* * It already exists. */ - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); error = -EEXIST; if (flag & O_EXCL) @@ -1665,7 +1665,7 @@ do_link: goto exit; } dir = nd->dentry; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); path.dentry = lookup_hash(nd); path.mnt = nd->mnt; __putname(nd->last.name); @@ -1680,13 +1680,13 @@ do_link: * Simple function to lookup and return a dentry and create it * if it doesn't exist. Is SMP-safe. * - * Returns with nd->dentry->d_inode->i_sem locked. + * Returns with nd->dentry->d_inode->i_mutex locked. */ struct dentry *lookup_create(struct nameidata *nd, int is_dir) { struct dentry *dentry = ERR_PTR(-EEXIST); - down(&nd->dentry->d_inode->i_sem); + mutex_lock(&nd->dentry->d_inode->i_mutex); /* * Yucky last component or no last component at all? * (foo/., foo/.., /////) @@ -1784,7 +1784,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev) } dput(dentry); } - up(&nd.dentry->d_inode->i_sem); + mutex_unlock(&nd.dentry->d_inode->i_mutex); path_release(&nd); out: putname(tmp); @@ -1836,7 +1836,7 @@ asmlinkage long sys_mkdir(const char __user * pathname, int mode) error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); dput(dentry); } - up(&nd.dentry->d_inode->i_sem); + mutex_unlock(&nd.dentry->d_inode->i_mutex); path_release(&nd); out: putname(tmp); @@ -1885,7 +1885,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) DQUOT_INIT(dir); - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); dentry_unhash(dentry); if (d_mountpoint(dentry)) error = -EBUSY; @@ -1897,7 +1897,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) dentry->d_inode->i_flags |= S_DEAD; } } - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); if (!error) { d_delete(dentry); } @@ -1932,14 +1932,14 @@ asmlinkage long sys_rmdir(const char __user * pathname) error = -EBUSY; goto exit1; } - down(&nd.dentry->d_inode->i_sem); + mutex_lock(&nd.dentry->d_inode->i_mutex); dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_rmdir(nd.dentry->d_inode, dentry); dput(dentry); } - up(&nd.dentry->d_inode->i_sem); + mutex_unlock(&nd.dentry->d_inode->i_mutex); exit1: path_release(&nd); exit: @@ -1959,7 +1959,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) DQUOT_INIT(dir); - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); if (d_mountpoint(dentry)) error = -EBUSY; else { @@ -1967,7 +1967,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) if (!error) error = dir->i_op->unlink(dir, dentry); } - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); /* We don't d_delete() NFS sillyrenamed files--they still exist. */ if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { @@ -1979,7 +1979,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) /* * Make sure that the actual truncation of the file will occur outside its - * directory's i_sem. Truncate can take a long time if there is a lot of + * directory's i_mutex. Truncate can take a long time if there is a lot of * writeout happening, and we don't want to prevent access to the directory * while waiting on the I/O. */ @@ -2001,7 +2001,7 @@ asmlinkage long sys_unlink(const char __user * pathname) error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; - down(&nd.dentry->d_inode->i_sem); + mutex_lock(&nd.dentry->d_inode->i_mutex); dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { @@ -2015,7 +2015,7 @@ asmlinkage long sys_unlink(const char __user * pathname) exit2: dput(dentry); } - up(&nd.dentry->d_inode->i_sem); + mutex_unlock(&nd.dentry->d_inode->i_mutex); if (inode) iput(inode); /* truncate the inode here */ exit1: @@ -2075,7 +2075,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); dput(dentry); } - up(&nd.dentry->d_inode->i_sem); + mutex_unlock(&nd.dentry->d_inode->i_mutex); path_release(&nd); out: putname(to); @@ -2113,10 +2113,10 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de if (error) return error; - down(&old_dentry->d_inode->i_sem); + mutex_lock(&old_dentry->d_inode->i_mutex); DQUOT_INIT(dir); error = dir->i_op->link(old_dentry, dir, new_dentry); - up(&old_dentry->d_inode->i_sem); + mutex_unlock(&old_dentry->d_inode->i_mutex); if (!error) fsnotify_create(dir, new_dentry->d_name.name); return error; @@ -2157,7 +2157,7 @@ asmlinkage long sys_link(const char __user * oldname, const char __user * newnam error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); dput(new_dentry); } - up(&nd.dentry->d_inode->i_sem); + mutex_unlock(&nd.dentry->d_inode->i_mutex); out_release: path_release(&nd); out: @@ -2178,7 +2178,7 @@ exit: * sb->s_vfs_rename_sem. We might be more accurate, but that's another * story. * c) we have to lock _three_ objects - parents and victim (if it exists). - * And that - after we got ->i_sem on parents (until then we don't know + * And that - after we got ->i_mutex on parents (until then we don't know * whether the target exists). Solution: try to be smart with locking * order for inodes. We rely on the fact that tree topology may change * only under ->s_vfs_rename_sem _and_ that parent of the object we @@ -2195,9 +2195,9 @@ exit: * stuff into VFS), but the former is not going away. Solution: the same * trick as in rmdir(). * e) conversion from fhandle to dentry may come in the wrong moment - when - * we are removing the target. Solution: we will have to grab ->i_sem + * we are removing the target. Solution: we will have to grab ->i_mutex * in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on - * ->i_sem on parents, which works but leads to some truely excessive + * ->i_mutex on parents, which works but leads to some truely excessive * locking]. */ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, @@ -2222,7 +2222,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, target = new_dentry->d_inode; if (target) { - down(&target->i_sem); + mutex_lock(&target->i_mutex); dentry_unhash(new_dentry); } if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) @@ -2232,7 +2232,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, if (target) { if (!error) target->i_flags |= S_DEAD; - up(&target->i_sem); + mutex_unlock(&target->i_mutex); if (d_unhashed(new_dentry)) d_rehash(new_dentry); dput(new_dentry); @@ -2255,7 +2255,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, dget(new_dentry); target = new_dentry->d_inode; if (target) - down(&target->i_sem); + mutex_lock(&target->i_mutex); if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) error = -EBUSY; else @@ -2266,7 +2266,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, d_move(old_dentry, new_dentry); } if (target) - up(&target->i_sem); + mutex_unlock(&target->i_mutex); dput(new_dentry); return error; } diff --git a/fs/namespace.c b/fs/namespace.c index 3e8fb61ad597..f0e353f5bc30 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -814,7 +814,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) return -ENOTDIR; err = -ENOENT; - down(&nd->dentry->d_inode->i_sem); + mutex_lock(&nd->dentry->d_inode->i_mutex); if (IS_DEADDIR(nd->dentry->d_inode)) goto out_unlock; @@ -826,7 +826,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) err = attach_recursive_mnt(mnt, nd, NULL); out_unlock: - up(&nd->dentry->d_inode->i_sem); + mutex_unlock(&nd->dentry->d_inode->i_mutex); if (!err) security_sb_post_addmount(mnt, nd); return err; @@ -962,7 +962,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) goto out; err = -ENOENT; - down(&nd->dentry->d_inode->i_sem); + mutex_lock(&nd->dentry->d_inode->i_mutex); if (IS_DEADDIR(nd->dentry->d_inode)) goto out1; @@ -1004,7 +1004,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) list_del_init(&old_nd.mnt->mnt_expire); spin_unlock(&vfsmount_lock); out1: - up(&nd->dentry->d_inode->i_sem); + mutex_unlock(&nd->dentry->d_inode->i_mutex); out: up_write(&namespace_sem); if (!err) @@ -1573,7 +1573,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, user_nd.dentry = dget(current->fs->root); read_unlock(¤t->fs->lock); down_write(&namespace_sem); - down(&old_nd.dentry->d_inode->i_sem); + mutex_lock(&old_nd.dentry->d_inode->i_mutex); error = -EINVAL; if (IS_MNT_SHARED(old_nd.mnt) || IS_MNT_SHARED(new_nd.mnt->mnt_parent) || @@ -1626,7 +1626,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, path_release(&root_parent); path_release(&parent_nd); out2: - up(&old_nd.dentry->d_inode->i_sem); + mutex_unlock(&old_nd.dentry->d_inode->i_mutex); up_write(&namespace_sem); path_release(&user_nd); path_release(&old_nd); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e9255198f767..a1554bead692 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -194,7 +194,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) spin_unlock(&inode->i_lock); /* Ensure consistent page alignment of the data. * Note: assumes we have exclusive access to this mapping either - * through inode->i_sem or some other mechanism. + * through inode->i_mutex or some other mechanism. */ if (page->index == 0) invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1); @@ -573,7 +573,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) { - down(&filp->f_dentry->d_inode->i_sem); + mutex_lock(&filp->f_dentry->d_inode->i_mutex); switch (origin) { case 1: offset += filp->f_pos; @@ -589,7 +589,7 @@ loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) ((struct nfs_open_context *)filp->private_data)->dir_cookie = 0; } out: - up(&filp->f_dentry->d_inode->i_sem); + mutex_unlock(&filp->f_dentry->d_inode->i_mutex); return offset; } @@ -1001,7 +1001,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) openflags &= ~(O_CREAT|O_TRUNC); /* - * Note: we're not holding inode->i_sem and so may be racing with + * Note: we're not holding inode->i_mutex and so may be racing with * operations that change the directory. We therefore save the * change attribute *before* we do the RPC call. */ @@ -1051,7 +1051,7 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) return dentry; if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) return NULL; - /* Note: caller is already holding the dir->i_sem! */ + /* Note: caller is already holding the dir->i_mutex! */ dentry = d_alloc(parent, &name); if (dentry == NULL) return NULL; diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 954cf893d50c..be963a133aaa 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -121,9 +121,9 @@ out: static void nfsd4_sync_rec_dir(void) { - down(&rec_dir.dentry->d_inode->i_sem); + mutex_lock(&rec_dir.dentry->d_inode->i_mutex); nfsd_sync_dir(rec_dir.dentry); - up(&rec_dir.dentry->d_inode->i_sem); + mutex_unlock(&rec_dir.dentry->d_inode->i_mutex); } int @@ -143,7 +143,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) nfs4_save_user(&uid, &gid); /* lock the parent */ - down(&rec_dir.dentry->d_inode->i_sem); + mutex_lock(&rec_dir.dentry->d_inode->i_mutex); dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1); if (IS_ERR(dentry)) { @@ -159,7 +159,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) out_put: dput(dentry); out_unlock: - up(&rec_dir.dentry->d_inode->i_sem); + mutex_unlock(&rec_dir.dentry->d_inode->i_mutex); if (status == 0) { clp->cl_firststate = 1; nfsd4_sync_rec_dir(); @@ -259,9 +259,9 @@ nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry) printk("nfsd4: non-file found in client recovery directory\n"); return -EINVAL; } - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); status = vfs_unlink(dir->d_inode, dentry); - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); return status; } @@ -274,9 +274,9 @@ nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry) * any regular files anyway, just in case the directory was created by * a kernel from the future.... */ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); status = vfs_rmdir(dir->d_inode, dentry); - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); return status; } @@ -288,9 +288,9 @@ nfsd4_unlink_clid_dir(char *name, int namlen) dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); - down(&rec_dir.dentry->d_inode->i_sem); + mutex_lock(&rec_dir.dentry->d_inode->i_mutex); dentry = lookup_one_len(name, rec_dir.dentry, namlen); - up(&rec_dir.dentry->d_inode->i_sem); + mutex_unlock(&rec_dir.dentry->d_inode->i_mutex); if (IS_ERR(dentry)) { status = PTR_ERR(dentry); return status; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index df4019f04560..bb36b4304491 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -390,12 +390,12 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key) error = -EOPNOTSUPP; if (inode->i_op && inode->i_op->setxattr) { - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); security_inode_setxattr(dentry, key, buf, len, 0); error = inode->i_op->setxattr(dentry, key, buf, len, 0); if (!error) security_inode_post_setxattr(dentry, key, buf, len, 0); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } out: kfree(buf); @@ -739,9 +739,9 @@ nfsd_sync(struct file *filp) int err; struct inode *inode = filp->f_dentry->d_inode; dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name); - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); err=nfsd_dosync(filp, filp->f_dentry, filp->f_op); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return err; } @@ -885,9 +885,9 @@ static void kill_suid(struct dentry *dentry) struct iattr ia; ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID; - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &ia); - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); } static inline int diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index eda056bac256..9480a0526cd3 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1532,7 +1532,7 @@ int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a, * NOTE to self: No changes in the attribute list are required to move from * a resident to a non-resident attribute. * - * Locking: - The caller must hold i_sem on the inode. + * Locking: - The caller must hold i_mutex on the inode. */ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) { @@ -1728,7 +1728,7 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) /* * This needs to be last since the address space operations ->readpage * and ->writepage can run concurrently with us as they are not - * serialized on i_sem. Note, we are not allowed to fail once we flip + * serialized on i_mutex. Note, we are not allowed to fail once we flip * this switch, which is another reason to do this last. */ NInoSetNonResident(ni); diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 795c3d1930f5..b0690d4c8906 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -69,7 +69,7 @@ ntfschar I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'), * work but we don't care for how quickly one can access them. This also fixes * the dcache aliasing issues. * - * Locking: - Caller must hold i_sem on the directory. + * Locking: - Caller must hold i_mutex on the directory. * - Each page cache page in the index allocation mapping must be * locked whilst being accessed otherwise we may find a corrupt * page due to it being under ->writepage at the moment which @@ -1085,11 +1085,11 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, * While this will return the names in random order this doesn't matter for * ->readdir but OTOH results in a faster ->readdir. * - * VFS calls ->readdir without BKL but with i_sem held. This protects the VFS + * VFS calls ->readdir without BKL but with i_mutex held. This protects the VFS * parts (e.g. ->f_pos and ->i_size, and it also protects against directory * modifications). * - * Locking: - Caller must hold i_sem on the directory. + * Locking: - Caller must hold i_mutex on the directory. * - Each page cache page in the index allocation mapping must be * locked whilst being accessed otherwise we may find a corrupt * page due to it being under ->writepage at the moment which @@ -1520,7 +1520,7 @@ static int ntfs_dir_open(struct inode *vi, struct file *filp) * Note: In the past @filp could be NULL so we ignore it as we don't need it * anyway. * - * Locking: Caller must hold i_sem on the inode. + * Locking: Caller must hold i_mutex on the inode. * * TODO: We should probably also write all attribute/index inodes associated * with this inode but since we have no simple way of getting to them we ignore diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 727533891813..30f71acdc1cb 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -106,7 +106,7 @@ static int ntfs_file_open(struct inode *vi, struct file *filp) * this is the case, the necessary zeroing will also have happened and that all * metadata is self-consistent. * - * Locking: i_sem on the vfs inode corrseponsind to the ntfs inode @ni must be + * Locking: i_mutex on the vfs inode corrseponsind to the ntfs inode @ni must be * held by the caller. */ static int ntfs_attr_extend_initialized(ntfs_inode *ni, const s64 new_init_size, @@ -473,7 +473,7 @@ static inline int ntfs_submit_bh_for_read(struct buffer_head *bh) * @bytes: number of bytes to be written * * This is called for non-resident attributes from ntfs_file_buffered_write() - * with i_sem held on the inode (@pages[0]->mapping->host). There are + * with i_mutex held on the inode (@pages[0]->mapping->host). There are * @nr_pages pages in @pages which are locked but not kmap()ped. The source * data has not yet been copied into the @pages. * @@ -1637,7 +1637,7 @@ err_out: * @pos: byte position in file at which the write begins * @bytes: number of bytes to be written * - * This is called from ntfs_file_buffered_write() with i_sem held on the inode + * This is called from ntfs_file_buffered_write() with i_mutex held on the inode * (@pages[0]->mapping->host). There are @nr_pages pages in @pages which are * locked but not kmap()ped. The source data has already been copied into the * @page. ntfs_prepare_pages_for_non_resident_write() has been called before @@ -1814,7 +1814,7 @@ err_out: /** * ntfs_file_buffered_write - * - * Locking: The vfs is holding ->i_sem on the inode. + * Locking: The vfs is holding ->i_mutex on the inode. */ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, @@ -2196,9 +2196,9 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const char __user *buf, BUG_ON(iocb->ki_pos != pos); - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); ret = ntfs_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { int err = sync_page_range(inode, mapping, pos, ret); if (err < 0) @@ -2221,12 +2221,12 @@ static ssize_t ntfs_file_writev(struct file *file, const struct iovec *iov, struct kiocb kiocb; ssize_t ret; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); init_sync_kiocb(&kiocb, file); ret = ntfs_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos); if (ret == -EIOCBQUEUED) ret = wait_on_sync_kiocb(&kiocb); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { int err = sync_page_range(inode, mapping, *ppos - ret, ret); if (err < 0) @@ -2269,7 +2269,7 @@ static ssize_t ntfs_file_write(struct file *file, const char __user *buf, * Note: In the past @filp could be NULL so we ignore it as we don't need it * anyway. * - * Locking: Caller must hold i_sem on the inode. + * Locking: Caller must hold i_mutex on the inode. * * TODO: We should probably also write all attribute/index inodes associated * with this inode but since we have no simple way of getting to them we ignore diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c index 8f2d5727546f..9f5427c2d105 100644 --- a/fs/ntfs/index.c +++ b/fs/ntfs/index.c @@ -32,7 +32,7 @@ * Allocate a new index context, initialize it with @idx_ni and return it. * Return NULL if allocation failed. * - * Locking: Caller must hold i_sem on the index inode. + * Locking: Caller must hold i_mutex on the index inode. */ ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *idx_ni) { @@ -50,7 +50,7 @@ ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *idx_ni) * * Release the index context @ictx, releasing all associated resources. * - * Locking: Caller must hold i_sem on the index inode. + * Locking: Caller must hold i_mutex on the index inode. */ void ntfs_index_ctx_put(ntfs_index_context *ictx) { @@ -106,7 +106,7 @@ void ntfs_index_ctx_put(ntfs_index_context *ictx) * or ntfs_index_entry_write() before the call to ntfs_index_ctx_put() to * ensure that the changes are written to disk. * - * Locking: - Caller must hold i_sem on the index inode. + * Locking: - Caller must hold i_mutex on the index inode. * - Each page cache page in the index allocation mapping must be * locked whilst being accessed otherwise we may find a corrupt * page due to it being under ->writepage at the moment which diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index b24f4c4b2c5c..bda7a08911a5 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -2125,13 +2125,13 @@ void ntfs_put_inode(struct inode *vi) ntfs_inode *ni = NTFS_I(vi); if (NInoIndexAllocPresent(ni)) { struct inode *bvi = NULL; - down(&vi->i_sem); + mutex_lock(&vi->i_mutex); if (atomic_read(&vi->i_count) == 2) { bvi = ni->itype.index.bmp_ino; if (bvi) ni->itype.index.bmp_ino = NULL; } - up(&vi->i_sem); + mutex_unlock(&vi->i_mutex); if (bvi) iput(bvi); } @@ -2311,7 +2311,7 @@ static const char *es = " Leaving inconsistent metadata. Unmount and run " * * Returns 0 on success or -errno on error. * - * Called with ->i_sem held. In all but one case ->i_alloc_sem is held for + * Called with ->i_mutex held. In all but one case ->i_alloc_sem is held for * writing. The only case in the kernel where ->i_alloc_sem is not held is * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called * with the current i_size as the offset. The analogous place in NTFS is in @@ -2831,7 +2831,7 @@ void ntfs_truncate_vfs(struct inode *vi) { * We also abort all changes of user, group, and mode as we do not implement * the NTFS ACLs yet. * - * Called with ->i_sem held. For the ATTR_SIZE (i.e. ->truncate) case, also + * Called with ->i_mutex held. For the ATTR_SIZE (i.e. ->truncate) case, also * called with ->i_alloc_sem held for writing. * * Basically this is a copy of generic notify_change() and inode_setattr() diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index 351dbc3b6e40..5ea9eb93af62 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -96,7 +96,7 @@ * name. We then convert the name to the current NLS code page, and proceed * searching for a dentry with this name, etc, as in case 2), above. * - * Locking: Caller must hold i_sem on the directory. + * Locking: Caller must hold i_mutex on the directory. */ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, struct nameidata *nd) @@ -254,7 +254,7 @@ handle_name: nls_name.hash = full_name_hash(nls_name.name, nls_name.len); /* - * Note: No need for dent->d_lock lock as i_sem is held on the + * Note: No need for dent->d_lock lock as i_mutex is held on the * parent inode. */ @@ -374,7 +374,7 @@ struct inode_operations ntfs_dir_inode_ops = { * The code is based on the ext3 ->get_parent() implementation found in * fs/ext3/namei.c::ext3_get_parent(). * - * Note: ntfs_get_parent() is called with @child_dent->d_inode->i_sem down. + * Note: ntfs_get_parent() is called with @child_dent->d_inode->i_mutex down. * * Return the dentry of the parent directory on success or the error code on * error (IS_ERR() is true). diff --git a/fs/ntfs/quota.c b/fs/ntfs/quota.c index 833df2a4e9fb..d0ef4182147b 100644 --- a/fs/ntfs/quota.c +++ b/fs/ntfs/quota.c @@ -48,7 +48,7 @@ BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol) ntfs_error(vol->sb, "Quota inodes are not open."); return FALSE; } - down(&vol->quota_q_ino->i_sem); + mutex_lock(&vol->quota_q_ino->i_mutex); ictx = ntfs_index_ctx_get(NTFS_I(vol->quota_q_ino)); if (!ictx) { ntfs_error(vol->sb, "Failed to get index context."); @@ -98,7 +98,7 @@ BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol) ntfs_index_entry_mark_dirty(ictx); set_done: ntfs_index_ctx_put(ictx); - up(&vol->quota_q_ino->i_sem); + mutex_unlock(&vol->quota_q_ino->i_mutex); /* * We set the flag so we do not try to mark the quotas out of date * again on remount. @@ -110,7 +110,7 @@ done: err_out: if (ictx) ntfs_index_ctx_put(ictx); - up(&vol->quota_q_ino->i_sem); + mutex_unlock(&vol->quota_q_ino->i_mutex); return FALSE; } diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 6c16db9e1a8a..280e383fc84e 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -1213,10 +1213,10 @@ static int check_windows_hibernation_status(ntfs_volume *vol) * Find the inode number for the hibernation file by looking up the * filename hiberfil.sys in the root directory. */ - down(&vol->root_ino->i_sem); + mutex_lock(&vol->root_ino->i_mutex); mref = ntfs_lookup_inode_by_name(NTFS_I(vol->root_ino), hiberfil, 12, &name); - up(&vol->root_ino->i_sem); + mutex_unlock(&vol->root_ino->i_mutex); if (IS_ERR_MREF(mref)) { ret = MREF_ERR(mref); /* If the file does not exist, Windows is not hibernated. */ @@ -1307,10 +1307,10 @@ static BOOL load_and_init_quota(ntfs_volume *vol) * Find the inode number for the quota file by looking up the filename * $Quota in the extended system files directory $Extend. */ - down(&vol->extend_ino->i_sem); + mutex_lock(&vol->extend_ino->i_mutex); mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), Quota, 6, &name); - up(&vol->extend_ino->i_sem); + mutex_unlock(&vol->extend_ino->i_mutex); if (IS_ERR_MREF(mref)) { /* * If the file does not exist, quotas are disabled and have @@ -1390,10 +1390,10 @@ static BOOL load_and_init_usnjrnl(ntfs_volume *vol) * Find the inode number for the transaction log file by looking up the * filename $UsnJrnl in the extended system files directory $Extend. */ - down(&vol->extend_ino->i_sem); + mutex_lock(&vol->extend_ino->i_mutex); mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), UsnJrnl, 8, &name); - up(&vol->extend_ino->i_sem); + mutex_unlock(&vol->extend_ino->i_mutex); if (IS_ERR_MREF(mref)) { /* * If the file does not exist, transaction logging is disabled, @@ -2312,9 +2312,9 @@ static void ntfs_put_super(struct super_block *sb) if (!list_empty(&sb->s_dirty)) { const char *s1, *s2; - down(&vol->mft_ino->i_sem); + mutex_lock(&vol->mft_ino->i_mutex); truncate_inode_pages(vol->mft_ino->i_mapping, 0); - up(&vol->mft_ino->i_sem); + mutex_unlock(&vol->mft_ino->i_mutex); write_inode_now(vol->mft_ino, 1); if (!list_empty(&sb->s_dirty)) { static const char *_s1 = "inodes"; diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 465f797451ee..6b9812db3779 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -966,7 +966,7 @@ static int ocfs2_truncate_log_append(struct ocfs2_super *osb, mlog_entry("start_blk = %"MLFu64", num_clusters = %u\n", start_blk, num_clusters); - BUG_ON(!down_trylock(&tl_inode->i_sem)); + BUG_ON(mutex_trylock(&tl_inode->i_mutex)); start_cluster = ocfs2_blocks_to_clusters(osb->sb, start_blk); @@ -1108,7 +1108,7 @@ bail: return status; } -/* Expects you to already be holding tl_inode->i_sem */ +/* Expects you to already be holding tl_inode->i_mutex */ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) { int status; @@ -1123,7 +1123,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) mlog_entry_void(); - BUG_ON(!down_trylock(&tl_inode->i_sem)); + BUG_ON(mutex_trylock(&tl_inode->i_mutex)); di = (struct ocfs2_dinode *) tl_bh->b_data; tl = &di->id2.i_dealloc; @@ -1198,9 +1198,9 @@ int ocfs2_flush_truncate_log(struct ocfs2_super *osb) int status; struct inode *tl_inode = osb->osb_tl_inode; - down(&tl_inode->i_sem); + mutex_lock(&tl_inode->i_mutex); status = __ocfs2_flush_truncate_log(osb); - up(&tl_inode->i_sem); + mutex_unlock(&tl_inode->i_mutex); return status; } @@ -1363,7 +1363,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, mlog(0, "cleanup %u records from %"MLFu64"\n", num_recs, tl_copy->i_blkno); - down(&tl_inode->i_sem); + mutex_lock(&tl_inode->i_mutex); for(i = 0; i < num_recs; i++) { if (ocfs2_truncate_log_needs_flush(osb)) { status = __ocfs2_flush_truncate_log(osb); @@ -1395,7 +1395,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, } bail_up: - up(&tl_inode->i_sem); + mutex_unlock(&tl_inode->i_mutex); mlog_exit(status); return status; @@ -1840,7 +1840,7 @@ start: mlog(0, "clusters_to_del = %u in this pass\n", clusters_to_del); - down(&tl_inode->i_sem); + mutex_lock(&tl_inode->i_mutex); tl_sem = 1; /* ocfs2_truncate_log_needs_flush guarantees us at least one * record is free for use. If there isn't any, we flush to get @@ -1875,7 +1875,7 @@ start: goto bail; } - up(&tl_inode->i_sem); + mutex_unlock(&tl_inode->i_mutex); tl_sem = 0; ocfs2_commit_trans(handle); @@ -1890,7 +1890,7 @@ bail: ocfs2_schedule_truncate_log_flush(osb, 1); if (tl_sem) - up(&tl_inode->i_sem); + mutex_unlock(&tl_inode->i_mutex); if (handle) ocfs2_commit_trans(handle); @@ -1994,7 +1994,7 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb, goto bail; } - down(&ext_alloc_inode->i_sem); + mutex_lock(&ext_alloc_inode->i_mutex); (*tc)->tc_ext_alloc_inode = ext_alloc_inode; status = ocfs2_meta_lock(ext_alloc_inode, @@ -2026,7 +2026,7 @@ static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc) if (tc->tc_ext_alloc_locked) ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1); - up(&tc->tc_ext_alloc_inode->i_sem); + mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex); iput(tc->tc_ext_alloc_inode); } diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c index 5fd60c105913..cf7828f23361 100644 --- a/fs/ocfs2/cluster/nodemanager.c +++ b/fs/ocfs2/cluster/nodemanager.c @@ -653,7 +653,7 @@ static struct config_group *o2nm_cluster_group_make_group(struct config_group *g struct config_group *o2hb_group = NULL, *ret = NULL; void *defs = NULL; - /* this runs under the parent dir's i_sem; there can be only + /* this runs under the parent dir's i_mutex; there can be only * one caller in here at a time */ if (o2nm_single_cluster) goto out; /* ENOSPC */ diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 856e20ae8263..57158fa75d91 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -202,7 +202,7 @@ bail: } /* - * NOTE: this should always be called with parent dir i_sem taken. + * NOTE: this should always be called with parent dir i_mutex taken. */ int ocfs2_find_files_on_disk(const char *name, int namelen, @@ -245,7 +245,7 @@ leave: * Return 0 if the name does not exist * Return -EEXIST if the directory contains the name * - * Callers should have i_sem + a cluster lock on dir + * Callers should have i_mutex + a cluster lock on dir */ int ocfs2_check_dir_for_entry(struct inode *dir, const char *name, diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 72ae9e3306f4..ca5f9f90d794 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -492,7 +492,7 @@ restart_all: } /* blocks peope in read/write from reading our allocation - * until we're done changing it. We depend on i_sem to block + * until we're done changing it. We depend on i_mutex to block * other extend/truncate calls while we're here. Ordering wrt * start_trans is important here -- always do it before! */ down_write(&OCFS2_I(inode)->ip_alloc_sem); @@ -958,8 +958,8 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, filp->f_flags &= ~O_DIRECT; #endif - down(&inode->i_sem); - /* to match setattr's i_sem -> i_alloc_sem -> rw_lock ordering */ + mutex_lock(&inode->i_mutex); + /* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */ if (filp->f_flags & O_DIRECT) { have_alloc_sem = 1; down_read(&inode->i_alloc_sem); @@ -1123,7 +1123,7 @@ out: up_read(&inode->i_alloc_sem); if (rw_level != -1) ocfs2_rw_unlock(inode, rw_level); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); mlog_exit(ret); return ret; diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index a91ba4dec936..d4ecc0627716 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -485,10 +485,10 @@ static int ocfs2_remove_inode(struct inode *inode, goto bail; } - down(&inode_alloc_inode->i_sem); + mutex_lock(&inode_alloc_inode->i_mutex); status = ocfs2_meta_lock(inode_alloc_inode, NULL, &inode_alloc_bh, 1); if (status < 0) { - up(&inode_alloc_inode->i_sem); + mutex_unlock(&inode_alloc_inode->i_mutex); mlog_errno(status); goto bail; @@ -536,7 +536,7 @@ bail_commit: ocfs2_commit_trans(handle); bail_unlock: ocfs2_meta_unlock(inode_alloc_inode, 1); - up(&inode_alloc_inode->i_sem); + mutex_unlock(&inode_alloc_inode->i_mutex); brelse(inode_alloc_bh); bail: iput(inode_alloc_inode); @@ -567,10 +567,10 @@ static int ocfs2_wipe_inode(struct inode *inode, /* Lock the orphan dir. The lock will be held for the entire * delete_inode operation. We do this now to avoid races with * recovery completion on other nodes. */ - down(&orphan_dir_inode->i_sem); + mutex_lock(&orphan_dir_inode->i_mutex); status = ocfs2_meta_lock(orphan_dir_inode, NULL, &orphan_dir_bh, 1); if (status < 0) { - up(&orphan_dir_inode->i_sem); + mutex_unlock(&orphan_dir_inode->i_mutex); mlog_errno(status); goto bail; @@ -593,7 +593,7 @@ static int ocfs2_wipe_inode(struct inode *inode, bail_unlock_dir: ocfs2_meta_unlock(orphan_dir_inode, 1); - up(&orphan_dir_inode->i_sem); + mutex_unlock(&orphan_dir_inode->i_mutex); brelse(orphan_dir_bh); bail: iput(orphan_dir_inode); diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 04428042e5e5..303c8d96457f 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -216,7 +216,7 @@ void ocfs2_handle_add_inode(struct ocfs2_journal_handle *handle, atomic_inc(&inode->i_count); /* we're obviously changing it... */ - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); /* sanity check */ BUG_ON(OCFS2_I(inode)->ip_handle); @@ -241,7 +241,7 @@ static void ocfs2_handle_unlock_inodes(struct ocfs2_journal_handle *handle) OCFS2_I(inode)->ip_handle = NULL; list_del_init(&OCFS2_I(inode)->ip_handle_list); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); iput(inode); } } @@ -1433,10 +1433,10 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, goto out; } - down(&orphan_dir_inode->i_sem); + mutex_lock(&orphan_dir_inode->i_mutex); status = ocfs2_meta_lock(orphan_dir_inode, NULL, NULL, 0); if (status < 0) { - up(&orphan_dir_inode->i_sem); + mutex_unlock(&orphan_dir_inode->i_mutex); mlog_errno(status); goto out; } @@ -1451,7 +1451,7 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, if (!bh) status = -EINVAL; if (status < 0) { - up(&orphan_dir_inode->i_sem); + mutex_unlock(&orphan_dir_inode->i_mutex); if (bh) brelse(bh); mlog_errno(status); @@ -1465,7 +1465,7 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, if (!ocfs2_check_dir_entry(orphan_dir_inode, de, bh, local)) { - up(&orphan_dir_inode->i_sem); + mutex_unlock(&orphan_dir_inode->i_mutex); status = -EINVAL; mlog_errno(status); brelse(bh); @@ -1509,7 +1509,7 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, } brelse(bh); } - up(&orphan_dir_inode->i_sem); + mutex_unlock(&orphan_dir_inode->i_mutex); ocfs2_meta_unlock(orphan_dir_inode, 0); have_disk_lock = 0; diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index fe373a2101d9..149b35181666 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -334,7 +334,7 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb, goto bail; } - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &alloc_bh, 0, inode); @@ -367,7 +367,7 @@ bail: brelse(alloc_bh); if (inode) { - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); iput(inode); } @@ -446,7 +446,7 @@ bail: /* * make sure we've got at least bitswanted contiguous bits in the - * local alloc. You lose them when you drop i_sem. + * local alloc. You lose them when you drop i_mutex. * * We will add ourselves to the transaction passed in, but may start * our own in order to shift windows. diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 48bf7f0ce544..364d64bd5f10 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -169,7 +169,7 @@ static match_table_t tokens = { */ static void ocfs2_write_super(struct super_block *sb) { - if (down_trylock(&sb->s_lock) == 0) + if (mutex_trylock(&sb->s_lock) != 0) BUG(); sb->s_dirt = 0; } diff --git a/fs/open.c b/fs/open.c index 75f3329e8a67..a3b3a9b5c2ff 100644 --- a/fs/open.c +++ b/fs/open.c @@ -211,9 +211,9 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, newattrs.ia_valid |= ATTR_FILE; } - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); err = notify_change(dentry, &newattrs); - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); return err; } @@ -398,9 +398,9 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) (error = vfs_permission(&nd, MAY_WRITE)) != 0) goto dput_and_out; } - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); error = notify_change(nd.dentry, &newattrs); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); dput_and_out: path_release(&nd); out: @@ -451,9 +451,9 @@ long do_utimes(char __user * filename, struct timeval * times) (error = vfs_permission(&nd, MAY_WRITE)) != 0) goto dput_and_out; } - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); error = notify_change(nd.dentry, &newattrs); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); dput_and_out: path_release(&nd); out: @@ -620,13 +620,13 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) err = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out_putf; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); out_putf: fput(file); @@ -654,13 +654,13 @@ asmlinkage long sys_chmod(const char __user * filename, mode_t mode) if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto dput_and_out; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; error = notify_change(nd.dentry, &newattrs); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); dput_and_out: path_release(&nd); @@ -696,9 +696,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) } if (!S_ISDIR(inode->i_mode)) newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); error = notify_change(dentry, &newattrs); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); out: return error; } diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig index e227a04261ab..7490cc9208b3 100644 --- a/fs/partitions/Kconfig +++ b/fs/partitions/Kconfig @@ -21,26 +21,30 @@ config ACORN_PARTITION Support hard disks partitioned under Acorn operating systems. config ACORN_PARTITION_CUMANA - bool "Cumana partition support" if PARTITION_ADVANCED && ACORN_PARTITION + bool "Cumana partition support" if PARTITION_ADVANCED default y if ARCH_ACORN + depends on ACORN_PARTITION help Say Y here if you would like to use hard disks under Linux which were partitioned using the Cumana interface on Acorn machines. config ACORN_PARTITION_EESOX - bool "EESOX partition support" if PARTITION_ADVANCED && ACORN_PARTITION + bool "EESOX partition support" if PARTITION_ADVANCED default y if ARCH_ACORN + depends on ACORN_PARTITION config ACORN_PARTITION_ICS - bool "ICS partition support" if PARTITION_ADVANCED && ACORN_PARTITION + bool "ICS partition support" if PARTITION_ADVANCED default y if ARCH_ACORN + depends on ACORN_PARTITION help Say Y here if you would like to use hard disks under Linux which were partitioned using the ICS interface on Acorn machines. config ACORN_PARTITION_ADFS - bool "Native filecore partition support" if PARTITION_ADVANCED && ACORN_PARTITION + bool "Native filecore partition support" if PARTITION_ADVANCED default y if ARCH_ACORN + depends on ACORN_PARTITION help The Acorn Disc Filing System is the standard file system of the RiscOS operating system which runs on Acorn's ARM-based Risc PC @@ -48,15 +52,17 @@ config ACORN_PARTITION_ADFS `Y' here, Linux will support disk partitions created under ADFS. config ACORN_PARTITION_POWERTEC - bool "PowerTec partition support" if PARTITION_ADVANCED && ACORN_PARTITION + bool "PowerTec partition support" if PARTITION_ADVANCED default y if ARCH_ACORN + depends on ACORN_PARTITION help Support reading partition tables created on Acorn machines using the PowerTec SCSI drive. config ACORN_PARTITION_RISCIX - bool "RISCiX partition support" if PARTITION_ADVANCED && ACORN_PARTITION + bool "RISCiX partition support" if PARTITION_ADVANCED default y if ARCH_ACORN + depends on ACORN_PARTITION help Once upon a time, there was a native Unix port for the Acorn series of machines called RISCiX. If you say 'Y' here, Linux will be able @@ -224,5 +230,3 @@ config EFI_PARTITION Say Y here if you would like to use hard disks under Linux which were partitioned using EFI GPT. Presently only useful on the IA-64 platform. - -# define_bool CONFIG_ACORN_PARTITION_CUMANA y diff --git a/fs/pipe.c b/fs/pipe.c index 66aa0b938d6a..acb030b61fb0 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -44,10 +44,10 @@ void pipe_wait(struct inode * inode) * is considered a noninteractive wait: */ prepare_to_wait(PIPE_WAIT(*inode), &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE); - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); schedule(); finish_wait(PIPE_WAIT(*inode), &wait); - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); } static inline int @@ -136,7 +136,7 @@ pipe_readv(struct file *filp, const struct iovec *_iov, do_wakeup = 0; ret = 0; - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); info = inode->i_pipe; for (;;) { int bufs = info->nrbufs; @@ -200,7 +200,7 @@ pipe_readv(struct file *filp, const struct iovec *_iov, } pipe_wait(inode); } - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); /* Signal writers asynchronously that there is more room. */ if (do_wakeup) { wake_up_interruptible(PIPE_WAIT(*inode)); @@ -237,7 +237,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov, do_wakeup = 0; ret = 0; - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); info = inode->i_pipe; if (!PIPE_READERS(*inode)) { @@ -341,7 +341,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov, PIPE_WAITING_WRITERS(*inode)--; } out: - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); if (do_wakeup) { wake_up_interruptible(PIPE_WAIT(*inode)); kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); @@ -381,7 +381,7 @@ pipe_ioctl(struct inode *pino, struct file *filp, switch (cmd) { case FIONREAD: - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); info = inode->i_pipe; count = 0; buf = info->curbuf; @@ -390,7 +390,7 @@ pipe_ioctl(struct inode *pino, struct file *filp, count += info->bufs[buf].len; buf = (buf+1) & (PIPE_BUFFERS-1); } - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); return put_user(count, (int __user *)arg); default: return -EINVAL; @@ -433,7 +433,7 @@ pipe_poll(struct file *filp, poll_table *wait) static int pipe_release(struct inode *inode, int decr, int decw) { - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); PIPE_READERS(*inode) -= decr; PIPE_WRITERS(*inode) -= decw; if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) { @@ -443,7 +443,7 @@ pipe_release(struct inode *inode, int decr, int decw) kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); } - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); return 0; } @@ -454,9 +454,9 @@ pipe_read_fasync(int fd, struct file *filp, int on) struct inode *inode = filp->f_dentry->d_inode; int retval; - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode)); - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); if (retval < 0) return retval; @@ -471,9 +471,9 @@ pipe_write_fasync(int fd, struct file *filp, int on) struct inode *inode = filp->f_dentry->d_inode; int retval; - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode)); - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); if (retval < 0) return retval; @@ -488,14 +488,14 @@ pipe_rdwr_fasync(int fd, struct file *filp, int on) struct inode *inode = filp->f_dentry->d_inode; int retval; - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode)); if (retval >= 0) retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode)); - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); if (retval < 0) return retval; @@ -534,9 +534,9 @@ pipe_read_open(struct inode *inode, struct file *filp) { /* We could have perhaps used atomic_t, but this and friends below are the only places. So it doesn't seem worthwhile. */ - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); PIPE_READERS(*inode)++; - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); return 0; } @@ -544,9 +544,9 @@ pipe_read_open(struct inode *inode, struct file *filp) static int pipe_write_open(struct inode *inode, struct file *filp) { - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); PIPE_WRITERS(*inode)++; - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); return 0; } @@ -554,12 +554,12 @@ pipe_write_open(struct inode *inode, struct file *filp) static int pipe_rdwr_open(struct inode *inode, struct file *filp) { - down(PIPE_SEM(*inode)); + mutex_lock(PIPE_MUTEX(*inode)); if (filp->f_mode & FMODE_READ) PIPE_READERS(*inode)++; if (filp->f_mode & FMODE_WRITE) PIPE_WRITERS(*inode)++; - up(PIPE_SEM(*inode)); + mutex_unlock(PIPE_MUTEX(*inode)); return 0; } diff --git a/fs/quota.c b/fs/quota.c index 612e04db4b93..d14d872646d4 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -168,7 +168,7 @@ static void quota_sync_sb(struct super_block *sb, int type) sync_blockdev(sb->s_bdev); /* Now when everything is written we can discard the pagecache so - * that userspace sees the changes. We need i_sem and so we could + * that userspace sees the changes. We need i_mutex and so we could * not do it inside dqonoff_sem. Moreover we need to be carefull * about races with quotaoff() (that is the reason why we have own * reference to inode). */ @@ -184,9 +184,9 @@ static void quota_sync_sb(struct super_block *sb, int type) up(&sb_dqopt(sb)->dqonoff_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (discard[cnt]) { - down(&discard[cnt]->i_sem); + mutex_lock(&discard[cnt]->i_mutex); truncate_inode_pages(&discard[cnt]->i_data, 0); - up(&discard[cnt]->i_sem); + mutex_unlock(&discard[cnt]->i_mutex); iput(discard[cnt]); } } diff --git a/fs/read_write.c b/fs/read_write.c index df3468a22fea..3f7a1a62165f 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -33,7 +33,7 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) long long retval; struct inode *inode = file->f_mapping->host; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); switch (origin) { case 2: offset += inode->i_size; @@ -49,7 +49,7 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) } retval = offset; } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return retval; } diff --git a/fs/readdir.c b/fs/readdir.c index b03579bc0210..b6109329b607 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -30,13 +30,13 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf) if (res) goto out; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); res = -ENOENT; if (!IS_DEADDIR(inode)) { res = file->f_op->readdir(file, buf, filler); file_accessed(file); } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); out: return res; } diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 7892a865b58a..127e7d2cabdd 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -49,7 +49,7 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) } reiserfs_write_lock(inode->i_sb); - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); /* freeing preallocation only involves relogging blocks that * are already in the current transaction. preallocation gets * freed at the end of each transaction, so it is impossible for @@ -100,7 +100,7 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) err = reiserfs_truncate_file(inode, 0); } out: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); reiserfs_write_unlock(inode->i_sb); return err; } @@ -1342,7 +1342,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t if (unlikely(!access_ok(VERIFY_READ, buf, count))) return -EFAULT; - down(&inode->i_sem); // locks the entire file for just us + mutex_lock(&inode->i_mutex); // locks the entire file for just us pos = *ppos; @@ -1532,12 +1532,12 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t generic_osync_inode(inode, file->f_mapping, OSYNC_METADATA | OSYNC_DATA); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); reiserfs_async_progress_wait(inode->i_sb); return (already_written != 0) ? already_written : res; out: - up(&inode->i_sem); // unlock the file on exit. + mutex_unlock(&inode->i_mutex); // unlock the file on exit. return res; } diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index a5e3a0ddbe53..ffa34b861bdb 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -40,12 +40,12 @@ void reiserfs_delete_inode(struct inode *inode) /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */ if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */ - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); reiserfs_delete_xattrs(inode); if (journal_begin(&th, inode->i_sb, jbegin_count)) { - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); goto out; } reiserfs_update_inode_transaction(inode); @@ -59,11 +59,11 @@ void reiserfs_delete_inode(struct inode *inode) DQUOT_FREE_INODE(inode); if (journal_end(&th, inode->i_sb, jbegin_count)) { - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); goto out; } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); /* check return value from reiserfs_delete_object after * ending the transaction @@ -551,7 +551,7 @@ static int convert_tail_for_hole(struct inode *inode, /* we don't have to make sure the conversion did not happen while ** we were locking the page because anyone that could convert - ** must first take i_sem. + ** must first take i_mutex. ** ** We must fix the tail page for writing because it might have buffers ** that are mapped, but have a block number of 0. This indicates tail @@ -586,7 +586,7 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th, BUG_ON(!th->t_trans_id); #ifdef REISERFS_PREALLOCATE - if (!(flags & GET_BLOCK_NO_ISEM)) { + if (!(flags & GET_BLOCK_NO_IMUX)) { return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr, path, block); } @@ -2318,7 +2318,7 @@ static int map_block_for_writepage(struct inode *inode, /* this is where we fill in holes in the file. */ if (use_get_block) { retval = reiserfs_get_block(inode, block, bh_result, - GET_BLOCK_CREATE | GET_BLOCK_NO_ISEM + GET_BLOCK_CREATE | GET_BLOCK_NO_IMUX | GET_BLOCK_NO_DANGLE); if (!retval) { if (!buffer_mapped(bh_result) diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 81fc00285f60..ba8bf8df6dc7 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c @@ -120,7 +120,7 @@ static int reiserfs_unpack(struct inode *inode, struct file *filp) /* we need to make sure nobody is changing the file size beneath ** us */ - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); write_from = inode->i_size & (blocksize - 1); /* if we are on a block boundary, we are already unpacked. */ @@ -156,7 +156,7 @@ static int reiserfs_unpack(struct inode *inode, struct file *filp) page_cache_release(page); out: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); reiserfs_write_unlock(inode->i_sb); return retval; } diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 42afb5bef111..397d9590c8f2 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -2211,7 +2211,7 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, size_t towrite = len; struct buffer_head tmp_bh, *bh; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); while (towrite > 0) { tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; @@ -2250,7 +2250,7 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, inode->i_version++; inode->i_mtime = inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return len - towrite; } diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c index c92e124f628e..196e971c03c9 100644 --- a/fs/reiserfs/tail_conversion.c +++ b/fs/reiserfs/tail_conversion.c @@ -205,7 +205,7 @@ int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_in 1) * p_s_sb->s_blocksize; pos1 = pos; - // we are protected by i_sem. The tail can not disapper, not + // we are protected by i_mutex. The tail can not disapper, not // append can be done either // we are in truncate or packing tail in file_release diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 02091eaac0b4..f1895f0a278e 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -67,11 +67,11 @@ static struct dentry *create_xa_root(struct super_block *sb) goto out; } else if (!xaroot->d_inode) { int err; - down(&privroot->d_inode->i_sem); + mutex_lock(&privroot->d_inode->i_mutex); err = privroot->d_inode->i_op->mkdir(privroot->d_inode, xaroot, 0700); - up(&privroot->d_inode->i_sem); + mutex_unlock(&privroot->d_inode->i_mutex); if (err) { dput(xaroot); @@ -219,7 +219,7 @@ static struct dentry *get_xa_file_dentry(const struct inode *inode, } else if (flags & XATTR_REPLACE || flags & FL_READONLY) { goto out; } else { - /* inode->i_sem is down, so nothing else can try to create + /* inode->i_mutex is down, so nothing else can try to create * the same xattr */ err = xadir->d_inode->i_op->create(xadir->d_inode, xafile, 0700 | S_IFREG, NULL); @@ -268,7 +268,7 @@ static struct file *open_xa_file(const struct inode *inode, const char *name, * and don't mess with f->f_pos, but the idea is the same. Do some * action on each and every entry in the directory. * - * we're called with i_sem held, so there are no worries about the directory + * we're called with i_mutex held, so there are no worries about the directory * changing underneath us. */ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) @@ -426,7 +426,7 @@ int xattr_readdir(struct file *file, filldir_t filler, void *buf) int res = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) goto out; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); // down(&inode->i_zombie); res = -ENOENT; if (!IS_DEADDIR(inode)) { @@ -435,7 +435,7 @@ int xattr_readdir(struct file *file, filldir_t filler, void *buf) unlock_kernel(); } // up(&inode->i_zombie); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); out: return res; } @@ -480,7 +480,7 @@ static inline __u32 xattr_hash(const char *msg, int len) /* Generic extended attribute operations that can be used by xa plugins */ /* - * inode->i_sem: down + * inode->i_mutex: down */ int reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, @@ -535,7 +535,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, /* Resize it so we're ok to write there */ newattrs.ia_size = buffer_size; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; - down(&xinode->i_sem); + mutex_lock(&xinode->i_mutex); err = notify_change(fp->f_dentry, &newattrs); if (err) goto out_filp; @@ -598,7 +598,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, } out_filp: - up(&xinode->i_sem); + mutex_unlock(&xinode->i_mutex); fput(fp); out: @@ -606,7 +606,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, } /* - * inode->i_sem: down + * inode->i_mutex: down */ int reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, @@ -793,7 +793,7 @@ reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen, } -/* This is called w/ inode->i_sem downed */ +/* This is called w/ inode->i_mutex downed */ int reiserfs_delete_xattrs(struct inode *inode) { struct file *fp; @@ -946,7 +946,7 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) /* * Inode operation getxattr() - * Preliminary locking: we down dentry->d_inode->i_sem + * Preliminary locking: we down dentry->d_inode->i_mutex */ ssize_t reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, @@ -970,7 +970,7 @@ reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, /* * Inode operation setxattr() * - * dentry->d_inode->i_sem down + * dentry->d_inode->i_mutex down */ int reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, @@ -1008,7 +1008,7 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, /* * Inode operation removexattr() * - * dentry->d_inode->i_sem down + * dentry->d_inode->i_mutex down */ int reiserfs_removexattr(struct dentry *dentry, const char *name) { @@ -1091,7 +1091,7 @@ reiserfs_listxattr_filler(void *buf, const char *name, int namelen, /* * Inode operation listxattr() * - * Preliminary locking: we down dentry->d_inode->i_sem + * Preliminary locking: we down dentry->d_inode->i_mutex */ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) { @@ -1289,9 +1289,9 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) if (!IS_ERR(dentry)) { if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) { struct inode *inode = dentry->d_parent->d_inode; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); err = inode->i_op->mkdir(inode, dentry, 0700); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); if (err) { dput(dentry); dentry = NULL; diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index a47ac9aac8b2..2dc953504cc0 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -174,7 +174,7 @@ static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size) /* * Inode operation get_posix_acl(). * - * inode->i_sem: down + * inode->i_mutex: down * BKL held [before 2.5.x] */ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) @@ -237,7 +237,7 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) /* * Inode operation set_posix_acl(). * - * inode->i_sem: down + * inode->i_mutex: down * BKL held [before 2.5.x] */ static int @@ -312,7 +312,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) return error; } -/* dir->i_sem: down, +/* dir->i_mutex: locked, * inode is new and not released into the wild yet */ int reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry, diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c index 7b7f2cb5f0e1..383523011aad 100644 --- a/fs/relayfs/inode.c +++ b/fs/relayfs/inode.c @@ -109,7 +109,7 @@ static struct dentry *relayfs_create_entry(const char *name, } parent = dget(parent); - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); d = lookup_one_len(name, parent, strlen(name)); if (IS_ERR(d)) { d = NULL; @@ -139,7 +139,7 @@ release_mount: simple_release_fs(&relayfs_mount, &relayfs_mount_count); exit: - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); dput(parent); return d; } @@ -204,7 +204,7 @@ int relayfs_remove(struct dentry *dentry) return -EINVAL; parent = dget(parent); - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); if (dentry->d_inode) { if (S_ISDIR(dentry->d_inode->i_mode)) error = simple_rmdir(parent->d_inode, dentry); @@ -215,7 +215,7 @@ int relayfs_remove(struct dentry *dentry) } if (!error) dput(dentry); - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); dput(parent); if (!error) @@ -476,7 +476,7 @@ static ssize_t relay_file_read(struct file *filp, ssize_t ret = 0; void *from; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if(!relay_file_read_avail(buf, *ppos)) goto out; @@ -494,7 +494,7 @@ static ssize_t relay_file_read(struct file *filp, relay_file_read_consume(buf, read_start, count); *ppos = relay_file_read_end_pos(buf, read_start, count); out: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return ret; } diff --git a/fs/super.c b/fs/super.c index 0a30e51692cf..c177b92419c5 100644 --- a/fs/super.c +++ b/fs/super.c @@ -72,7 +72,7 @@ static struct super_block *alloc_super(void) INIT_HLIST_HEAD(&s->s_anon); INIT_LIST_HEAD(&s->s_inodes); init_rwsem(&s->s_umount); - sema_init(&s->s_lock, 1); + mutex_init(&s->s_lock); down_write(&s->s_umount); s->s_count = S_BIAS; atomic_set(&s->s_active, 1); diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index d36780382176..49bd219275db 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -99,7 +99,7 @@ static int create_dir(struct kobject * k, struct dentry * p, int error; umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; - down(&p->d_inode->i_sem); + mutex_lock(&p->d_inode->i_mutex); *d = lookup_one_len(n, p, strlen(n)); if (!IS_ERR(*d)) { error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR); @@ -122,7 +122,7 @@ static int create_dir(struct kobject * k, struct dentry * p, dput(*d); } else error = PTR_ERR(*d); - up(&p->d_inode->i_sem); + mutex_unlock(&p->d_inode->i_mutex); return error; } @@ -246,7 +246,7 @@ static void remove_dir(struct dentry * d) struct dentry * parent = dget(d->d_parent); struct sysfs_dirent * sd; - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); d_delete(d); sd = d->d_fsdata; list_del_init(&sd->s_sibling); @@ -257,7 +257,7 @@ static void remove_dir(struct dentry * d) pr_debug(" o %s removing done (%d)\n",d->d_name.name, atomic_read(&d->d_count)); - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); dput(parent); } @@ -286,7 +286,7 @@ void sysfs_remove_dir(struct kobject * kobj) return; pr_debug("sysfs %s: removing dir\n",dentry->d_name.name); - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); parent_sd = dentry->d_fsdata; list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED)) @@ -295,7 +295,7 @@ void sysfs_remove_dir(struct kobject * kobj) sysfs_drop_dentry(sd, dentry); sysfs_put(sd); } - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); remove_dir(dentry); /** @@ -318,7 +318,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) down_write(&sysfs_rename_sem); parent = kobj->parent->dentry; - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); if (!IS_ERR(new_dentry)) { @@ -334,7 +334,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) error = -EEXIST; dput(new_dentry); } - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); up_write(&sysfs_rename_sem); return error; @@ -345,9 +345,9 @@ static int sysfs_dir_open(struct inode *inode, struct file *file) struct dentry * dentry = file->f_dentry; struct sysfs_dirent * parent_sd = dentry->d_fsdata; - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); file->private_data = sysfs_new_dirent(parent_sd, NULL); - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); return file->private_data ? 0 : -ENOMEM; @@ -358,9 +358,9 @@ static int sysfs_dir_close(struct inode *inode, struct file *file) struct dentry * dentry = file->f_dentry; struct sysfs_dirent * cursor = file->private_data; - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); list_del_init(&cursor->s_sibling); - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); release_sysfs_dirent(cursor); @@ -436,7 +436,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) { struct dentry * dentry = file->f_dentry; - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); switch (origin) { case 1: offset += file->f_pos; @@ -444,7 +444,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) if (offset >= 0) break; default: - up(&file->f_dentry->d_inode->i_sem); + mutex_unlock(&file->f_dentry->d_inode->i_mutex); return -EINVAL; } if (offset != file->f_pos) { @@ -468,7 +468,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) list_add_tail(&cursor->s_sibling, p); } } - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); return offset; } @@ -483,4 +483,3 @@ struct file_operations sysfs_dir_operations = { EXPORT_SYMBOL_GPL(sysfs_create_dir); EXPORT_SYMBOL_GPL(sysfs_remove_dir); EXPORT_SYMBOL_GPL(sysfs_rename_dir); - diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 4013d7905e84..d0e3d8495165 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -364,9 +364,9 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; int error = 0; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); error = sysfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type); - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); return error; } @@ -398,7 +398,7 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) struct dentry * victim; int res = -ENOENT; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); victim = lookup_one_len(attr->name, dir, strlen(attr->name)); if (!IS_ERR(victim)) { /* make sure dentry is really there */ @@ -420,7 +420,7 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) */ dput(victim); } - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); return res; } @@ -441,22 +441,22 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) struct iattr newattrs; int res = -ENOENT; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); victim = lookup_one_len(attr->name, dir, strlen(attr->name)); if (!IS_ERR(victim)) { if (victim->d_inode && (victim->d_parent->d_inode == dir->d_inode)) { inode = victim->d_inode; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; res = notify_change(victim, &newattrs); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } dput(victim); } - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); return res; } @@ -480,4 +480,3 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) EXPORT_SYMBOL_GPL(sysfs_create_file); EXPORT_SYMBOL_GPL(sysfs_remove_file); EXPORT_SYMBOL_GPL(sysfs_update_file); - diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 970a33f03299..c3133219941c 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -201,7 +201,7 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd) /* * Unhashes the dentry corresponding to given sysfs_dirent - * Called with parent inode's i_sem held. + * Called with parent inode's i_mutex held. */ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) { @@ -232,7 +232,7 @@ void sysfs_hash_and_remove(struct dentry * dir, const char * name) /* no inode means this hasn't been made visible yet */ return; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { if (!sd->s_element) continue; @@ -243,7 +243,5 @@ void sysfs_hash_and_remove(struct dentry * dir, const char * name) break; } } - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); } - - diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index de402fa915f2..e38d6338a20d 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -86,9 +86,9 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char BUG_ON(!kobj || !kobj->dentry || !name); - down(&dentry->d_inode->i_sem); + mutex_lock(&dentry->d_inode->i_mutex); error = sysfs_add_link(dentry, name, target); - up(&dentry->d_inode->i_sem); + mutex_unlock(&dentry->d_inode->i_mutex); return error; } @@ -177,4 +177,3 @@ struct inode_operations sysfs_symlink_inode_operations = { EXPORT_SYMBOL_GPL(sysfs_create_link); EXPORT_SYMBOL_GPL(sysfs_remove_link); - diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 2ba11a9aa995..e9a42c711a9e 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1275,7 +1275,7 @@ static ssize_t ufs_quota_write(struct super_block *sb, int type, size_t towrite = len; struct buffer_head *bh; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); while (towrite > 0) { tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; @@ -1297,7 +1297,7 @@ static ssize_t ufs_quota_write(struct super_block *sb, int type, } out: if (len == towrite) { - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return err; } if (inode->i_size < off+len-towrite) @@ -1305,7 +1305,7 @@ out: inode->i_version++; inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return len - towrite; } diff --git a/fs/xattr.c b/fs/xattr.c index bcc2156d4d28..386a532ee5a9 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -51,7 +51,7 @@ setxattr(struct dentry *d, char __user *name, void __user *value, } } - down(&d->d_inode->i_sem); + mutex_lock(&d->d_inode->i_mutex); error = security_inode_setxattr(d, kname, kvalue, size, flags); if (error) goto out; @@ -73,7 +73,7 @@ setxattr(struct dentry *d, char __user *name, void __user *value, fsnotify_xattr(d); } out: - up(&d->d_inode->i_sem); + mutex_unlock(&d->d_inode->i_mutex); kfree(kvalue); return error; } @@ -323,9 +323,9 @@ removexattr(struct dentry *d, char __user *name) error = security_inode_removexattr(d, kname); if (error) goto out; - down(&d->d_inode->i_sem); + mutex_lock(&d->d_inode->i_mutex); error = d->d_inode->i_op->removexattr(d, kname); - up(&d->d_inode->i_sem); + mutex_unlock(&d->d_inode->i_mutex); if (!error) fsnotify_xattr(d); } diff --git a/fs/xfs/linux-2.6/mutex.h b/fs/xfs/linux-2.6/mutex.h index ce773d89a923..d3369b6ca168 100644 --- a/fs/xfs/linux-2.6/mutex.h +++ b/fs/xfs/linux-2.6/mutex.h @@ -19,7 +19,7 @@ #define __XFS_SUPPORT_MUTEX_H__ #include <linux/spinlock.h> -#include <asm/semaphore.h> +#include <linux/mutex.h> /* * Map the mutex'es from IRIX to Linux semaphores. @@ -28,12 +28,8 @@ * callers. */ #define MUTEX_DEFAULT 0x0 -typedef struct semaphore mutex_t; -#define mutex_init(lock, type, name) sema_init(lock, 1) -#define mutex_destroy(lock) sema_init(lock, -99) -#define mutex_lock(lock, num) down(lock) -#define mutex_trylock(lock) (down_trylock(lock) ? 0 : 1) -#define mutex_unlock(lock) up(lock) +typedef struct mutex mutex_t; +//#define mutex_destroy(lock) do{}while(0) #endif /* __XFS_SUPPORT_MUTEX_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 14215a7db59f..41c478bb1ffc 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -203,7 +203,7 @@ validate_fields( ip->i_nlink = va.va_nlink; ip->i_blocks = va.va_nblocks; - /* we're under i_sem so i_size can't change under us */ + /* we're under i_mutex so i_size can't change under us */ if (i_size_read(ip) != va.va_size) i_size_write(ip, va.va_size); } diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 279e9bc92aba..5675117ef227 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -254,7 +254,7 @@ xfs_read( } if (unlikely(ioflags & IO_ISDIRECT)) - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); xfs_ilock(ip, XFS_IOLOCK_SHARED); if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && @@ -286,7 +286,7 @@ xfs_read( unlock_isem: if (unlikely(ioflags & IO_ISDIRECT)) - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return ret; } @@ -655,7 +655,7 @@ relock: iolock = XFS_IOLOCK_EXCL; locktype = VRWLOCK_WRITE; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); } else { iolock = XFS_IOLOCK_SHARED; locktype = VRWLOCK_WRITE_DIRECT; @@ -686,7 +686,7 @@ start: int dmflags = FILP_DELAY_FLAG(file); if (need_isem) - dmflags |= DM_FLAGS_ISEM; + dmflags |= DM_FLAGS_IMUX; xfs_iunlock(xip, XFS_ILOCK_EXCL); error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp, @@ -772,7 +772,7 @@ retry: if (need_isem) { /* demote the lock now the cached pages are gone */ XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); iolock = XFS_IOLOCK_SHARED; locktype = VRWLOCK_WRITE_DIRECT; @@ -817,14 +817,14 @@ retry: xfs_rwunlock(bdp, locktype); if (need_isem) - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp, DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL, 0, 0, 0); /* Delay flag intentionally unused */ if (error) goto out_nounlocks; if (need_isem) - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); xfs_rwlock(bdp, locktype); pos = xip->i_d.di_size; ret = 0; @@ -926,7 +926,7 @@ retry: xfs_rwunlock(bdp, locktype); if (need_isem) - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); error = sync_page_range(inode, mapping, pos, ret); if (!error) @@ -938,7 +938,7 @@ retry: xfs_rwunlock(bdp, locktype); out_unlock_isem: if (need_isem) - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); out_nounlocks: return -error; } diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 00b5043dfa5a..772ac48329ea 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -104,7 +104,7 @@ xfs_qm_dqinit( */ if (brandnewdquot) { dqp->dq_flnext = dqp->dq_flprev = dqp; - mutex_init(&dqp->q_qlock, MUTEX_DEFAULT, "xdq"); + mutex_init(&dqp->q_qlock); initnsema(&dqp->q_flock, 1, "fdq"); sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq"); @@ -1382,7 +1382,7 @@ void xfs_dqlock( xfs_dquot_t *dqp) { - mutex_lock(&(dqp->q_qlock), PINOD); + mutex_lock(&(dqp->q_qlock)); } void diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 5328a2937127..bb6991a7a617 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -167,7 +167,7 @@ xfs_Gqm_init(void) xqm->qm_dqfree_ratio = XFS_QM_DQFREE_RATIO; xqm->qm_nrefs = 0; #ifdef DEBUG - mutex_init(&qcheck_lock, MUTEX_DEFAULT, "qchk"); + xfs_mutex_init(&qcheck_lock, MUTEX_DEFAULT, "qchk"); #endif return xqm; } @@ -1166,7 +1166,7 @@ xfs_qm_init_quotainfo( qinf->qi_dqreclaims = 0; /* mutex used to serialize quotaoffs */ - mutex_init(&qinf->qi_quotaofflock, MUTEX_DEFAULT, "qoff"); + mutex_init(&qinf->qi_quotaofflock); /* Precalc some constants */ qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB); @@ -1285,7 +1285,7 @@ xfs_qm_list_init( char *str, int n) { - mutex_init(&list->qh_lock, MUTEX_DEFAULT, str); + mutex_init(&list->qh_lock); list->qh_next = NULL; list->qh_version = 0; list->qh_nelems = 0; @@ -2762,7 +2762,7 @@ STATIC void xfs_qm_freelist_init(xfs_frlist_t *ql) { ql->qh_next = ql->qh_prev = (xfs_dquot_t *) ql; - mutex_init(&ql->qh_lock, MUTEX_DEFAULT, "dqf"); + mutex_init(&ql->qh_lock); ql->qh_version = 0; ql->qh_nelems = 0; } @@ -2772,7 +2772,7 @@ xfs_qm_freelist_destroy(xfs_frlist_t *ql) { xfs_dquot_t *dqp, *nextdqp; - mutex_lock(&ql->qh_lock, PINOD); + mutex_lock(&ql->qh_lock); for (dqp = ql->qh_next; dqp != (xfs_dquot_t *)ql; ) { xfs_dqlock(dqp); diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h index 12da259f2fcb..4568deb6da86 100644 --- a/fs/xfs/quota/xfs_qm.h +++ b/fs/xfs/quota/xfs_qm.h @@ -165,7 +165,7 @@ typedef struct xfs_dquot_acct { #define XFS_QM_IWARNLIMIT 5 #define XFS_QM_RTBWARNLIMIT 5 -#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock, PINOD)) +#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock)) #define XFS_QM_UNLOCK(xqm) (mutex_unlock(&xqm##_lock)) #define XFS_QM_HOLD(xqm) ((xqm)->qm_nrefs++) #define XFS_QM_RELE(xqm) ((xqm)->qm_nrefs--) diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index d9d2993de435..90402a1c3983 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -363,7 +363,7 @@ xfs_qm_init(void) KERN_INFO "SGI XFS Quota Management subsystem\n"; printk(message); - mutex_init(&xfs_Gqm_lock, MUTEX_DEFAULT, "xfs_qmlock"); + mutex_init(&xfs_Gqm_lock); vfs_bhv_set_custom(&xfs_qmops, &xfs_qmcore_xfs); xfs_qm_init_procfs(); } diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 24690e1af659..86a1d09f48d5 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -233,7 +233,7 @@ xfs_qm_scall_quotaoff( */ ASSERT(mp->m_quotainfo); if (mp->m_quotainfo) - mutex_lock(&(XFS_QI_QOFFLOCK(mp)), PINOD); + mutex_lock(&(XFS_QI_QOFFLOCK(mp))); ASSERT(mp->m_quotainfo); @@ -508,7 +508,7 @@ xfs_qm_scall_quotaon( /* * Switch on quota enforcement in core. */ - mutex_lock(&(XFS_QI_QOFFLOCK(mp)), PINOD); + mutex_lock(&(XFS_QI_QOFFLOCK(mp))); mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD); mutex_unlock(&(XFS_QI_QOFFLOCK(mp))); @@ -617,7 +617,7 @@ xfs_qm_scall_setqlim( * a quotaoff from happening). (XXXThis doesn't currently happen * because we take the vfslock before calling xfs_qm_sysent). */ - mutex_lock(&(XFS_QI_QOFFLOCK(mp)), PINOD); + mutex_lock(&(XFS_QI_QOFFLOCK(mp))); /* * Get the dquot (locked), and join it to the transaction. @@ -1426,7 +1426,7 @@ xfs_qm_internalqcheck( xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC); XFS_bflush(mp->m_ddev_targp); - mutex_lock(&qcheck_lock, PINOD); + mutex_lock(&qcheck_lock); /* There should be absolutely no quota activity while this is going on. */ qmtest_udqtab = kmem_zalloc(qmtest_hashmask * diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h index 7a9f3beb818c..b7ddd04aae32 100644 --- a/fs/xfs/quota/xfs_quota_priv.h +++ b/fs/xfs/quota/xfs_quota_priv.h @@ -51,7 +51,7 @@ #define XFS_QI_MPLNEXT(mp) ((mp)->m_quotainfo->qi_dqlist.qh_next) #define XFS_QI_MPLNDQUOTS(mp) ((mp)->m_quotainfo->qi_dqlist.qh_nelems) -#define XQMLCK(h) (mutex_lock(&((h)->qh_lock), PINOD)) +#define XQMLCK(h) (mutex_lock(&((h)->qh_lock))) #define XQMUNLCK(h) (mutex_unlock(&((h)->qh_lock))) #ifdef DEBUG struct xfs_dqhash; diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c index 70ce40914c8a..69ec4f540c3a 100644 --- a/fs/xfs/support/uuid.c +++ b/fs/xfs/support/uuid.c @@ -24,7 +24,7 @@ static uuid_t *uuid_table; void uuid_init(void) { - mutex_init(&uuid_monitor, MUTEX_DEFAULT, "uuid_monitor"); + mutex_init(&uuid_monitor); } /* @@ -94,7 +94,7 @@ uuid_table_insert(uuid_t *uuid) { int i, hole; - mutex_lock(&uuid_monitor, PVFS); + mutex_lock(&uuid_monitor); for (i = 0, hole = -1; i < uuid_table_size; i++) { if (uuid_is_nil(&uuid_table[i])) { hole = i; @@ -122,7 +122,7 @@ uuid_table_remove(uuid_t *uuid) { int i; - mutex_lock(&uuid_monitor, PVFS); + mutex_lock(&uuid_monitor); for (i = 0; i < uuid_table_size; i++) { if (uuid_is_nil(&uuid_table[i])) continue; diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 864bf6955689..b4c7f2bc55a0 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -152,7 +152,7 @@ typedef enum { #define DM_FLAGS_NDELAY 0x001 /* return EAGAIN after dm_pending() */ #define DM_FLAGS_UNWANTED 0x002 /* event not in fsys dm_eventset_t */ -#define DM_FLAGS_ISEM 0x004 /* thread holds i_sem */ +#define DM_FLAGS_IMUX 0x004 /* thread holds i_mutex */ #define DM_FLAGS_IALLOCSEM_RD 0x010 /* thread holds i_alloc_sem rd */ #define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ @@ -161,21 +161,21 @@ typedef enum { */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ - DM_FLAGS_ISEM : 0) -#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM) + DM_FLAGS_IMUX : 0) +#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \ (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)) #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ - DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM) -#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM) + DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_IMUX) +#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) #endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ - 0 : DM_FLAGS_ISEM) -#define DM_SEM_FLAG_WR (DM_FLAGS_ISEM) + 0 : DM_FLAGS_IMUX) +#define DM_SEM_FLAG_WR (DM_FLAGS_IMUX) #endif diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 541d5dd474be..303af86739bf 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -117,7 +117,7 @@ xfs_mount_init(void) AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail"); spinlock_init(&mp->m_sb_lock, "xfs_sb"); - mutex_init(&mp->m_ilock, MUTEX_DEFAULT, "xfs_ilock"); + mutex_init(&mp->m_ilock); initnsema(&mp->m_growlock, 1, "xfs_grow"); /* * Initialize the AIL. diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 08b2e0a5d807..3432fd5a3986 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -533,7 +533,7 @@ typedef struct xfs_mod_sb { int msb_delta; /* Change to make to specified field */ } xfs_mod_sb_t; -#define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock), PINOD) +#define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock)) #define XFS_MOUNT_IUNLOCK(mp) mutex_unlock(&((mp)->m_ilock)) #define XFS_SB_LOCK(mp) mutex_spinlock(&(mp)->m_sb_lock) #define XFS_SB_UNLOCK(mp,s) mutex_spinunlock(&(mp)->m_sb_lock,(s)) diff --git a/include/asm-alpha/atomic.h b/include/asm-alpha/atomic.h index cb03bbe92cdf..fc77f7413083 100644 --- a/include/asm-alpha/atomic.h +++ b/include/asm-alpha/atomic.h @@ -176,6 +176,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) } #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) #define atomic_add_unless(v, a, u) \ ({ \ diff --git a/include/asm-alpha/mutex.h b/include/asm-alpha/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-alpha/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200.h b/include/asm-arm/arch-at91rm9200/at91rm9200.h new file mode 100644 index 000000000000..58f40931a5c1 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200.h @@ -0,0 +1,261 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Common definitions. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91RM9200_H +#define AT91RM9200_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */ +#define AT91_ID_SYS 1 /* System Peripheral */ +#define AT91_ID_PIOA 2 /* Parallel IO Controller A */ +#define AT91_ID_PIOB 3 /* Parallel IO Controller B */ +#define AT91_ID_PIOC 4 /* Parallel IO Controller C */ +#define AT91_ID_PIOD 5 /* Parallel IO Controller D */ +#define AT91_ID_US0 6 /* USART 0 */ +#define AT91_ID_US1 7 /* USART 1 */ +#define AT91_ID_US2 8 /* USART 2 */ +#define AT91_ID_US3 9 /* USART 3 */ +#define AT91_ID_MCI 10 /* Multimedia Card Interface */ +#define AT91_ID_UDP 11 /* USB Device Port */ +#define AT91_ID_TWI 12 /* Two-Wire Interface */ +#define AT91_ID_SPI 13 /* Serial Peripheral Interface */ +#define AT91_ID_SSC0 14 /* Serial Synchronous Controller 0 */ +#define AT91_ID_SSC1 15 /* Serial Synchronous Controller 1 */ +#define AT91_ID_SSC2 16 /* Serial Synchronous Controller 2 */ +#define AT91_ID_TC0 17 /* Timer Counter 0 */ +#define AT91_ID_TC1 18 /* Timer Counter 1 */ +#define AT91_ID_TC2 19 /* Timer Counter 2 */ +#define AT91_ID_TC3 20 /* Timer Counter 3 */ +#define AT91_ID_TC4 21 /* Timer Counter 4 */ +#define AT91_ID_TC5 22 /* Timer Counter 5 */ +#define AT91_ID_UHP 23 /* USB Host port */ +#define AT91_ID_EMAC 24 /* Ethernet MAC */ +#define AT91_ID_IRQ0 25 /* Advanced Interrupt Controller (IRQ0) */ +#define AT91_ID_IRQ1 26 /* Advanced Interrupt Controller (IRQ1) */ +#define AT91_ID_IRQ2 27 /* Advanced Interrupt Controller (IRQ2) */ +#define AT91_ID_IRQ3 28 /* Advanced Interrupt Controller (IRQ3) */ +#define AT91_ID_IRQ4 29 /* Advanced Interrupt Controller (IRQ4) */ +#define AT91_ID_IRQ5 30 /* Advanced Interrupt Controller (IRQ5) */ +#define AT91_ID_IRQ6 31 /* Advanced Interrupt Controller (IRQ6) */ + + +/* + * Peripheral physical base addresses. + */ +#define AT91_BASE_TCB0 0xfffa0000 +#define AT91_BASE_TC0 0xfffa0000 +#define AT91_BASE_TC1 0xfffa0040 +#define AT91_BASE_TC2 0xfffa0080 +#define AT91_BASE_TCB1 0xfffa4000 +#define AT91_BASE_TC3 0xfffa4000 +#define AT91_BASE_TC4 0xfffa4040 +#define AT91_BASE_TC5 0xfffa4080 +#define AT91_BASE_UDP 0xfffb0000 +#define AT91_BASE_MCI 0xfffb4000 +#define AT91_BASE_TWI 0xfffb8000 +#define AT91_BASE_EMAC 0xfffbc000 +#define AT91_BASE_US0 0xfffc0000 +#define AT91_BASE_US1 0xfffc4000 +#define AT91_BASE_US2 0xfffc8000 +#define AT91_BASE_US3 0xfffcc000 +#define AT91_BASE_SSC0 0xfffd0000 +#define AT91_BASE_SSC1 0xfffd4000 +#define AT91_BASE_SSC2 0xfffd8000 +#define AT91_BASE_SPI 0xfffe0000 +#define AT91_BASE_SYS 0xfffff000 + + +/* + * PIO pin definitions (peripheral A/B multiplexing). + */ +#define AT91_PA0_MISO (1 << 0) /* A: SPI Master-In Slave-Out */ +#define AT91_PA0_PCK3 (1 << 0) /* B: PMC Programmable Clock Output 3 */ +#define AT91_PA1_MOSI (1 << 1) /* A: SPI Master-Out Slave-In */ +#define AT91_PA1_PCK0 (1 << 1) /* B: PMC Programmable Clock Output 0 */ +#define AT91_PA2_SPCK (1 << 2) /* A: SPI Serial Clock */ +#define AT91_PA2_IRQ4 (1 << 2) /* B: External Interrupt 4 */ +#define AT91_PA3_NPCS0 (1 << 3) /* A: SPI Peripheral Chip Select 0 */ +#define AT91_PA3_IRQ5 (1 << 3) /* B: External Interrupt 5 */ +#define AT91_PA4_NPCS1 (1 << 4) /* A: SPI Peripheral Chip Select 1 */ +#define AT91_PA4_PCK1 (1 << 4) /* B: PMC Programmable Clock Output 1 */ +#define AT91_PA5_NPCS2 (1 << 5) /* A: SPI Peripheral Chip Select 2 */ +#define AT91_PA5_TXD3 (1 << 5) /* B: USART Transmit Data 3 */ +#define AT91_PA6_NPCS3 (1 << 6) /* A: SPI Peripheral Chip Select 3 */ +#define AT91_PA6_RXD3 (1 << 6) /* B: USART Receive Data 3 */ +#define AT91_PA7_ETXCK_EREFCK (1 << 7) /* A: Ethernet Reference Clock / Transmit Clock */ +#define AT91_PA7_PCK2 (1 << 7) /* B: PMC Programmable Clock Output 2 */ +#define AT91_PA8_ETXEN (1 << 8) /* A: Ethernet Transmit Enable */ +#define AT91_PA8_MCCDB (1 << 8) /* B: MMC Multimedia Card B Command */ +#define AT91_PA9_ETX0 (1 << 9) /* A: Ethernet Transmit Data 0 */ +#define AT91_PA9_MCDB0 (1 << 9) /* B: MMC Multimedia Card B Data 0 */ +#define AT91_PA10_ETX1 (1 << 10) /* A: Ethernet Transmit Data 1 */ +#define AT91_PA10_MCDB1 (1 << 10) /* B: MMC Multimedia Card B Data 1 */ +#define AT91_PA11_ECRS_ECRSDV (1 << 11) /* A: Ethernet Carrier Sense / Data Valid */ +#define AT91_PA11_MCDB2 (1 << 11) /* B: MMC Multimedia Card B Data 2 */ +#define AT91_PA12_ERX0 (1 << 12) /* A: Ethernet Receive Data 0 */ +#define AT91_PA12_MCDB3 (1 << 12) /* B: MMC Multimedia Card B Data 3 */ +#define AT91_PA13_ERX1 (1 << 13) /* A: Ethernet Receive Data 1 */ +#define AT91_PA13_TCLK0 (1 << 13) /* B: TC External Clock Input 0 */ +#define AT91_PA14_ERXER (1 << 14) /* A: Ethernet Receive Error */ +#define AT91_PA14_TCLK1 (1 << 14) /* B: TC External Clock Input 1 */ +#define AT91_PA15_EMDC (1 << 15) /* A: Ethernet Management Data Clock */ +#define AT91_PA15_TCLK2 (1 << 15) /* B: TC External Clock Input 2 */ +#define AT91_PA16_EMDIO (1 << 16) /* A: Ethernet Management Data I/O */ +#define AT91_PA16_IRQ6 (1 << 16) /* B: External Interrupt 6 */ +#define AT91_PA17_TXD0 (1 << 17) /* A: USART Transmit Data 0 */ +#define AT91_PA17_TIOA0 (1 << 17) /* B: TC I/O Line A 0 */ +#define AT91_PA18_RXD0 (1 << 18) /* A: USART Receive Data 0 */ +#define AT91_PA18_TIOB0 (1 << 18) /* B: TC I/O Line B 0 */ +#define AT91_PA19_SCK0 (1 << 19) /* A: USART Serial Clock 0 */ +#define AT91_PA19_TIOA1 (1 << 19) /* B: TC I/O Line A 1 */ +#define AT91_PA20_CTS0 (1 << 20) /* A: USART Clear To Send 0 */ +#define AT91_PA20_TIOB1 (1 << 20) /* B: TC I/O Line B 1 */ +#define AT91_PA21_RTS0 (1 << 21) /* A: USART Ready To Send 0 */ +#define AT91_PA21_TIOA2 (1 << 21) /* B: TC I/O Line A 2 */ +#define AT91_PA22_RXD2 (1 << 22) /* A: USART Receive Data 2 */ +#define AT91_PA22_TIOB2 (1 << 22) /* B: TC I/O Line B 2 */ +#define AT91_PA23_TXD2 (1 << 23) /* A: USART Transmit Data 2 */ +#define AT91_PA23_IRQ3 (1 << 23) /* B: External Interrupt 3 */ +#define AT91_PA24_SCK2 (1 << 24) /* A: USART Serial Clock 2 */ +#define AT91_PA24_PCK1 (1 << 24) /* B: PMC Programmable Clock Output 1 */ +#define AT91_PA25_TWD (1 << 25) /* A: TWI Two-wire Serial Data */ +#define AT91_PA25_IRQ2 (1 << 25) /* B: External Interrupt 2 */ +#define AT91_PA26_TWCK (1 << 26) /* A: TWI Two-wire Serial Clock */ +#define AT91_PA26_IRQ1 (1 << 26) /* B: External Interrupt 1 */ +#define AT91_PA27_MCCK (1 << 27) /* A: MMC Multimedia Card Clock */ +#define AT91_PA27_TCLK3 (1 << 27) /* B: TC External Clock Input 3 */ +#define AT91_PA28_MCCDA (1 << 28) /* A: MMC Multimedia Card A Command */ +#define AT91_PA28_TCLK4 (1 << 28) /* B: TC External Clock Input 4 */ +#define AT91_PA29_MCDA0 (1 << 29) /* A: MMC Multimedia Card A Data 0 */ +#define AT91_PA29_TCLK5 (1 << 29) /* B: TC External Clock Input 5 */ +#define AT91_PA30_DRXD (1 << 30) /* A: DBGU Receive Data */ +#define AT91_PA30_CTS2 (1 << 30) /* B: USART Clear To Send 2 */ +#define AT91_PA31_DTXD (1 << 31) /* A: DBGU Transmit Data */ +#define AT91_PA31_RTS2 (1 << 31) /* B: USART Ready To Send 2 */ + +#define AT91_PB0_TF0 (1 << 0) /* A: SSC Transmit Frame Sync 0 */ +#define AT91_PB0_RTS3 (1 << 0) /* B: USART Ready To Send 3 */ +#define AT91_PB1_TK0 (1 << 1) /* A: SSC Transmit Clock 0 */ +#define AT91_PB1_CTS3 (1 << 1) /* B: USART Clear To Send 3 */ +#define AT91_PB2_TD0 (1 << 2) /* A: SSC Transmit Data 0 */ +#define AT91_PB2_SCK3 (1 << 2) /* B: USART Serial Clock 3 */ +#define AT91_PB3_RD0 (1 << 3) /* A: SSC Receive Data 0 */ +#define AT91_PB3_MCDA1 (1 << 3) /* B: MMC Multimedia Card A Data 1 */ +#define AT91_PB4_RK0 (1 << 4) /* A: SSC Receive Clock 0 */ +#define AT91_PB4_MCDA2 (1 << 4) /* B: MMC Multimedia Card A Data 2 */ +#define AT91_PB5_RF0 (1 << 5) /* A: SSC Receive Frame Sync 0 */ +#define AT91_PB5_MCDA3 (1 << 5) /* B: MMC Multimedia Card A Data 3 */ +#define AT91_PB6_TF1 (1 << 6) /* A: SSC Transmit Frame Sync 1 */ +#define AT91_PB6_TIOA3 (1 << 6) /* B: TC I/O Line A 3 */ +#define AT91_PB7_TK1 (1 << 7) /* A: SSC Transmit Clock 1 */ +#define AT91_PB7_TIOB3 (1 << 7) /* B: TC I/O Line B 3 */ +#define AT91_PB8_TD1 (1 << 8) /* A: SSC Transmit Data 1 */ +#define AT91_PB8_TIOA4 (1 << 8) /* B: TC I/O Line A 4 */ +#define AT91_PB9_RD1 (1 << 9) /* A: SSC Receive Data 1 */ +#define AT91_PB9_TIOB4 (1 << 9) /* B: TC I/O Line B 4 */ +#define AT91_PB10_RK1 (1 << 10) /* A: SSC Receive Clock 1 */ +#define AT91_PB10_TIOA5 (1 << 10) /* B: TC I/O Line A 5 */ +#define AT91_PB11_RF1 (1 << 11) /* A: SSC Receive Frame Sync 1 */ +#define AT91_PB11_TIOB5 (1 << 11) /* B: TC I/O Line B 5 */ +#define AT91_PB12_TF2 (1 << 12) /* A: SSC Transmit Frame Sync 2 */ +#define AT91_PB12_ETX2 (1 << 12) /* B: Ethernet Transmit Data 2 */ +#define AT91_PB13_TK2 (1 << 13) /* A: SSC Transmit Clock 3 */ +#define AT91_PB13_ETX3 (1 << 13) /* B: Ethernet Transmit Data 3 */ +#define AT91_PB14_TD2 (1 << 14) /* A: SSC Transmit Data 2 */ +#define AT91_PB14_ETXER (1 << 14) /* B: Ethernet Transmit Coding Error */ +#define AT91_PB15_RD2 (1 << 15) /* A: SSC Receive Data 2 */ +#define AT91_PB15_ERX2 (1 << 15) /* B: Ethernet Receive Data 2 */ +#define AT91_PB16_RK2 (1 << 16) /* A: SSC Receive Clock 2 */ +#define AT91_PB16_ERX3 (1 << 16) /* B: Ethernet Receive Data 3 */ +#define AT91_PB17_RF2 (1 << 17) /* A: SSC Receive Frame Sync 2 */ +#define AT91_PB17_ERXDV (1 << 17) /* B: Ethernet Receive Data Valid */ +#define AT91_PB18_RI1 (1 << 18) /* A: USART Ring Indicator 1 */ +#define AT91_PB18_ECOL (1 << 18) /* B: Ethernet Collision Detected */ +#define AT91_PB19_DTR1 (1 << 19) /* A: USART Data Terminal Ready 1 */ +#define AT91_PB19_ERXCK (1 << 19) /* B: Ethernet Receive Clock */ +#define AT91_PB20_TXD1 (1 << 20) /* A: USART Transmit Data 1 */ +#define AT91_PB21_RXD1 (1 << 21) /* A: USART Receive Data 1 */ +#define AT91_PB22_SCK1 (1 << 22) /* A: USART Serial Clock 1 */ +#define AT91_PB23_DCD1 (1 << 23) /* A: USART Data Carrier Detect 1 */ +#define AT91_PB24_CTS1 (1 << 24) /* A: USART Clear To Send 1 */ +#define AT91_PB25_DSR1 (1 << 25) /* A: USART Data Set Ready 1 */ +#define AT91_PB25_EF100 (1 << 25) /* B: Ethernet Force 100 Mbit */ +#define AT91_PB26_RTS1 (1 << 26) /* A: USART Ready To Send 1 */ +#define AT91_PB27_PCK0 (1 << 27) /* B: PMC Programmable Clock Output 0 */ +#define AT91_PB28_FIQ (1 << 28) /* A: Fast Interrupt */ +#define AT91_PB29_IRQ0 (1 << 29) /* A: External Interrupt 0 */ + +#define AT91_PC0_BFCK (1 << 0) /* A: Burst Flash Clock */ +#define AT91_PC1_BFRDY_SMOE (1 << 1) /* A: Burst Flash Ready / SmartMedia Output Enable */ +#define AT91_PC2_BFAVD (1 << 2) /* A: Burst Flash Address Valid */ +#define AT91_PC3_BFBAA_SMWE (1 << 3) /* A: Burst Flash Address Advance / SmartMedia Write Enable */ +#define AT91_PC4_BFOE (1 << 4) /* A: Burst Flash Output Enable */ +#define AT91_PC5_BFWE (1 << 5) /* A: Burst Flash Write Enable */ +#define AT91_PC6_NWAIT (1 << 6) /* A: SMC Wait Signal */ +#define AT91_PC7_A23 (1 << 7) /* A: Address Bus 23 */ +#define AT91_PC8_A24 (1 << 8) /* A: Address Bus 24 */ +#define AT91_PC9_A25_CFRNW (1 << 9) /* A: Address Bus 25 / Compact Flash Read Not Write */ +#define AT91_PC10_NCS4_CFCS (1 << 10) /* A: SMC Chip Select 4 / Compact Flash Chip Select */ +#define AT91_PC11_NCS5_CFCE1 (1 << 11) /* A: SMC Chip Select 5 / Compact Flash Chip Enable 1 */ +#define AT91_PC12_NCS6_CFCE2 (1 << 12) /* A: SMC Chip Select 6 / Compact Flash Chip Enable 2 */ +#define AT91_PC13_NCS7 (1 << 13) /* A: Chip Select 7 */ + +#define AT91_PD0_ETX0 (1 << 0) /* A: Ethernet Transmit Data 0 */ +#define AT91_PD1_ETX1 (1 << 1) /* A: Ethernet Transmit Data 1 */ +#define AT91_PD2_ETX2 (1 << 2) /* A: Ethernet Transmit Data 2 */ +#define AT91_PD3_ETX3 (1 << 3) /* A: Ethernet Transmit Data 3 */ +#define AT91_PD4_ETXEN (1 << 4) /* A: Ethernet Transmit Enable */ +#define AT91_PD5_ETXER (1 << 5) /* A: Ethernet Transmit Coding Error */ +#define AT91_PD6_DTXD (1 << 6) /* A: DBGU Transmit Data */ +#define AT91_PD7_PCK0 (1 << 7) /* A: PMC Programmable Clock Output 0 */ +#define AT91_PD7_TSYNC (1 << 7) /* B: ETM Trace Synchronization Signal */ +#define AT91_PD8_PCK1 (1 << 8) /* A: PMC Programmable Clock Output 1 */ +#define AT91_PD8_TCLK (1 << 8) /* B: ETM Trace Clock */ +#define AT91_PD9_PCK2 (1 << 9) /* A: PMC Programmable Clock Output 2 */ +#define AT91_PD9_TPS0 (1 << 9) /* B: ETM Trace ARM Pipeline Status 0 */ +#define AT91_PD10_PCK3 (1 << 10) /* A: PMC Programmable Clock Output 3 */ +#define AT91_PD10_TPS1 (1 << 10) /* B: ETM Trace ARM Pipeline Status 1 */ +#define AT91_PD11_TPS2 (1 << 11) /* B: ETM Trace ARM Pipeline Status 2 */ +#define AT91_PD12_TPK0 (1 << 12) /* B: ETM Trace Packet Port 0 */ +#define AT91_PD13_TPK1 (1 << 13) /* B: ETM Trace Packet Port 1 */ +#define AT91_PD14_TPK2 (1 << 14) /* B: ETM Trace Packet Port 2 */ +#define AT91_PD15_TD0 (1 << 15) /* A: SSC Transmit Data 0 */ +#define AT91_PD15_TPK3 (1 << 15) /* B: ETM Trace Packet Port 3 */ +#define AT91_PD16_TD1 (1 << 16) /* A: SSC Transmit Data 1 */ +#define AT91_PD16_TPK4 (1 << 16) /* B: ETM Trace Packet Port 4 */ +#define AT91_PD17_TD2 (1 << 17) /* A: SSC Transmit Data 2 */ +#define AT91_PD17_TPK5 (1 << 17) /* B: ETM Trace Packet Port 5 */ +#define AT91_PD18_NPCS1 (1 << 18) /* A: SPI Peripheral Chip Select 1 */ +#define AT91_PD18_TPK6 (1 << 18) /* B: ETM Trace Packet Port 6 */ +#define AT91_PD19_NPCS2 (1 << 19) /* A: SPI Peripheral Chip Select 2 */ +#define AT91_PD19_TPK7 (1 << 19) /* B: ETM Trace Packet Port 7 */ +#define AT91_PD20_NPCS3 (1 << 20) /* A: SPI Peripheral Chip Select 3 */ +#define AT91_PD20_TPK8 (1 << 20) /* B: ETM Trace Packet Port 8 */ +#define AT91_PD21_RTS0 (1 << 21) /* A: USART Ready To Send 0 */ +#define AT91_PD21_TPK9 (1 << 21) /* B: ETM Trace Packet Port 9 */ +#define AT91_PD22_RTS1 (1 << 22) /* A: USART Ready To Send 1 */ +#define AT91_PD22_TPK10 (1 << 22) /* B: ETM Trace Packet Port 10 */ +#define AT91_PD23_RTS2 (1 << 23) /* A: USART Ready To Send 2 */ +#define AT91_PD23_TPK11 (1 << 23) /* B: ETM Trace Packet Port 11 */ +#define AT91_PD24_RTS3 (1 << 24) /* A: USART Ready To Send 3 */ +#define AT91_PD24_TPK12 (1 << 24) /* B: ETM Trace Packet Port 12 */ +#define AT91_PD25_DTR1 (1 << 25) /* A: USART Data Terminal Ready 1 */ +#define AT91_PD25_TPK13 (1 << 25) /* B: ETM Trace Packet Port 13 */ +#define AT91_PD26_TPK14 (1 << 26) /* B: ETM Trace Packet Port 14 */ +#define AT91_PD27_TPK15 (1 << 27) /* B: ETM Trace Packet Port 15 */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h new file mode 100644 index 000000000000..9bfffdbf1e0b --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h @@ -0,0 +1,328 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_sys.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef AT91RM9200_SYS_H +#define AT91RM9200_SYS_H + +/* + * Advanced Interrupt Controller. + */ +#define AT91_AIC 0x000 + +#define AT91_AIC_SMR(n) (AT91_AIC + ((n) * 4)) /* Source Mode Registers 0-31 */ +#define AT91_AIC_PRIOR (7 << 0) /* Priority Level */ +#define AT91_AIC_SRCTYPE (3 << 5) /* Interrupt Source Type */ +#define AT91_AIC_SRCTYPE_LOW (0 << 5) +#define AT91_AIC_SRCTYPE_FALLING (1 << 5) +#define AT91_AIC_SRCTYPE_HIGH (2 << 5) +#define AT91_AIC_SRCTYPE_RISING (3 << 5) + +#define AT91_AIC_SVR(n) (AT91_AIC + 0x80 + ((n) * 4)) /* Source Vector Registers 0-31 */ +#define AT91_AIC_IVR (AT91_AIC + 0x100) /* Interrupt Vector Register */ +#define AT91_AIC_FVR (AT91_AIC + 0x104) /* Fast Interrupt Vector Register */ +#define AT91_AIC_ISR (AT91_AIC + 0x108) /* Interrupt Status Register */ +#define AT91_AIC_IRQID (0x1f << 0) /* Current Interrupt Identifier */ + +#define AT91_AIC_IPR (AT91_AIC + 0x10c) /* Interrupt Pending Register */ +#define AT91_AIC_IMR (AT91_AIC + 0x110) /* Interrupt Mask Register */ +#define AT91_AIC_CISR (AT91_AIC + 0x114) /* Core Interrupt Status Register */ +#define AT91_AIC_NFIQ (1 << 0) /* nFIQ Status */ +#define AT91_AIC_NIRQ (1 << 1) /* nIRQ Status */ + +#define AT91_AIC_IECR (AT91_AIC + 0x120) /* Interrupt Enable Command Register */ +#define AT91_AIC_IDCR (AT91_AIC + 0x124) /* Interrupt Disable Command Register */ +#define AT91_AIC_ICCR (AT91_AIC + 0x128) /* Interrupt Clear Command Register */ +#define AT91_AIC_ISCR (AT91_AIC + 0x12c) /* Interrupt Set Command Register */ +#define AT91_AIC_EOICR (AT91_AIC + 0x130) /* End of Interrupt Command Register */ +#define AT91_AIC_SPU (AT91_AIC + 0x134) /* Spurious Interrupt Vector Register */ +#define AT91_AIC_DCR (AT91_AIC + 0x138) /* Debug Control Register */ +#define AT91_AIC_DCR_PROT (1 << 0) /* Protection Mode */ +#define AT91_AIC_DCR_GMSK (1 << 1) /* General Mask */ + + +/* + * Debug Unit. + */ +#define AT91_DBGU 0x200 + +#define AT91_DBGU_CR (AT91_DBGU + 0x00) /* Control Register */ +#define AT91_DBGU_MR (AT91_DBGU + 0x04) /* Mode Register */ +#define AT91_DBGU_IER (AT91_DBGU + 0x08) /* Interrupt Enable Register */ +#define AT91_DBGU_TXRDY (1 << 1) /* Transmitter Ready */ +#define AT91_DBGU_TXEMPTY (1 << 9) /* Transmitter Empty */ +#define AT91_DBGU_IDR (AT91_DBGU + 0x0c) /* Interrupt Disable Register */ +#define AT91_DBGU_IMR (AT91_DBGU + 0x10) /* Interrupt Mask Register */ +#define AT91_DBGU_SR (AT91_DBGU + 0x14) /* Status Register */ +#define AT91_DBGU_RHR (AT91_DBGU + 0x18) /* Receiver Holding Register */ +#define AT91_DBGU_THR (AT91_DBGU + 0x1c) /* Transmitter Holding Register */ +#define AT91_DBGU_BRGR (AT91_DBGU + 0x20) /* Baud Rate Generator Register */ +#define AT91_DBGU_CIDR (AT91_DBGU + 0x40) /* Chip ID Register */ +#define AT91_DBGU_EXID (AT91_DBGU + 0x44) /* Chip ID Extension Register */ + + +/* + * PIO Controllers. + */ +#define AT91_PIOA 0x400 +#define AT91_PIOB 0x600 +#define AT91_PIOC 0x800 +#define AT91_PIOD 0xa00 + +#define PIO_PER 0x00 /* Enable Register */ +#define PIO_PDR 0x04 /* Disable Register */ +#define PIO_PSR 0x08 /* Status Register */ +#define PIO_OER 0x10 /* Output Enable Register */ +#define PIO_ODR 0x14 /* Output Disable Register */ +#define PIO_OSR 0x18 /* Output Status Register */ +#define PIO_IFER 0x20 /* Glitch Input Filter Enable */ +#define PIO_IFDR 0x24 /* Glitch Input Filter Disable */ +#define PIO_IFSR 0x28 /* Glitch Input Filter Status */ +#define PIO_SODR 0x30 /* Set Output Data Register */ +#define PIO_CODR 0x34 /* Clear Output Data Register */ +#define PIO_ODSR 0x38 /* Output Data Status Register */ +#define PIO_PDSR 0x3c /* Pin Data Status Register */ +#define PIO_IER 0x40 /* Interrupt Enable Register */ +#define PIO_IDR 0x44 /* Interrupt Disable Register */ +#define PIO_IMR 0x48 /* Interrupt Mask Register */ +#define PIO_ISR 0x4c /* Interrupt Status Register */ +#define PIO_MDER 0x50 /* Multi-driver Enable Register */ +#define PIO_MDDR 0x54 /* Multi-driver Disable Register */ +#define PIO_MDSR 0x58 /* Multi-driver Status Register */ +#define PIO_PUDR 0x60 /* Pull-up Disable Register */ +#define PIO_PUER 0x64 /* Pull-up Enable Register */ +#define PIO_PUSR 0x68 /* Pull-up Status Register */ +#define PIO_ASR 0x70 /* Peripheral A Select Register */ +#define PIO_BSR 0x74 /* Peripheral B Select Register */ +#define PIO_ABSR 0x78 /* AB Status Register */ +#define PIO_OWER 0xa0 /* Output Write Enable Register */ +#define PIO_OWDR 0xa4 /* Output Write Disable Register */ +#define PIO_OWSR 0xa8 /* Output Write Status Register */ + +#define AT91_PIO_P(n) (1 << (n)) + + +/* + * Power Management Controller. + */ +#define AT91_PMC 0xc00 + +#define AT91_PMC_SCER (AT91_PMC + 0x00) /* System Clock Enable Register */ +#define AT91_PMC_SCDR (AT91_PMC + 0x04) /* System Clock Disable Register */ + +#define AT91_PMC_SCSR (AT91_PMC + 0x08) /* System Clock Status Register */ +#define AT91_PMC_PCK (1 << 0) /* Processor Clock */ +#define AT91_PMC_UDP (1 << 1) /* USB Devcice Port Clock */ +#define AT91_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend */ +#define AT91_PMC_UHP (1 << 4) /* USB Host Port Clock */ +#define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */ +#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */ +#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */ +#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */ + +#define AT91_PMC_PCER (AT91_PMC + 0x10) /* Peripheral Clock Enable Register */ +#define AT91_PMC_PCDR (AT91_PMC + 0x14) /* Peripheral Clock Disable Register */ +#define AT91_PMC_PCSR (AT91_PMC + 0x18) /* Peripheral Clock Status Register */ + +#define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register */ +#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */ +#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */ + +#define AT91_CKGR_MCFR (AT91_PMC + 0x24) /* Main Clock Frequency Register */ +#define AT91_PMC_MAINF (0xffff << 0) /* Main Clock Frequency */ +#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ + +#define AT91_CKGR_PLLAR (AT91_PMC + 0x28) /* PLL A Register */ +#define AT91_CKGR_PLLBR (AT91_PMC + 0x2c) /* PLL B Register */ +#define AT91_PMC_DIV (0xff << 0) /* Divider */ +#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */ +#define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */ +#define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */ +#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */ + +#define AT91_PMC_MCKR (AT91_PMC + 0x30) /* Master Clock Register */ +#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */ +#define AT91_PMC_CSS_SLOW (0 << 0) +#define AT91_PMC_CSS_MAIN (1 << 0) +#define AT91_PMC_CSS_PLLA (2 << 0) +#define AT91_PMC_CSS_PLLB (3 << 0) +#define AT91_PMC_PRES (7 << 2) /* Master Clock Prescaler */ +#define AT91_PMC_PRES_1 (0 << 2) +#define AT91_PMC_PRES_2 (1 << 2) +#define AT91_PMC_PRES_4 (2 << 2) +#define AT91_PMC_PRES_8 (3 << 2) +#define AT91_PMC_PRES_16 (4 << 2) +#define AT91_PMC_PRES_32 (5 << 2) +#define AT91_PMC_PRES_64 (6 << 2) +#define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */ +#define AT91_PMC_MDIV_1 (0 << 8) +#define AT91_PMC_MDIV_2 (1 << 8) +#define AT91_PMC_MDIV_3 (2 << 8) +#define AT91_PMC_MDIV_4 (3 << 8) + +#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-3 Registers */ +#define AT91_PMC_IER (AT91_PMC + 0x60) /* Interrupt Enable Register */ +#define AT91_PMC_IDR (AT91_PMC + 0x64) /* Interrupt Disable Register */ +#define AT91_PMC_SR (AT91_PMC + 0x68) /* Status Register */ +#define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */ +#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */ +#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */ +#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */ +#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */ +#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */ +#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */ +#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */ +#define AT91_PMC_IMR (AT91_PMC + 0x6c) /* Interrupt Mask Register */ + + +/* + * System Timer. + */ +#define AT91_ST 0xd00 + +#define AT91_ST_CR (AT91_ST + 0x00) /* Control Register */ +#define AT91_ST_WDRST (1 << 0) /* Watchdog Timer Restart */ +#define AT91_ST_PIMR (AT91_ST + 0x04) /* Period Interval Mode Register */ +#define AT91_ST_PIV (0xffff << 0) /* Period Interval Value */ +#define AT91_ST_WDMR (AT91_ST + 0x08) /* Watchdog Mode Register */ +#define AT91_ST_WDV (0xffff << 0) /* Watchdog Counter Value */ +#define AT91_ST_RSTEN (1 << 16) /* Reset Enable */ +#define AT91_ST_EXTEN (1 << 17) /* External Signal Assertion Enable */ +#define AT91_ST_RTMR (AT91_ST + 0x0c) /* Real-time Mode Register */ +#define AT91_ST_RTPRES (0xffff << 0) /* Real-time Prescalar Value */ +#define AT91_ST_SR (AT91_ST + 0x10) /* Status Register */ +#define AT91_ST_PITS (1 << 0) /* Period Interval Timer Status */ +#define AT91_ST_WDOVF (1 << 1) /* Watchdog Overflow */ +#define AT91_ST_RTTINC (1 << 2) /* Real-time Timer Increment */ +#define AT91_ST_ALMS (1 << 3) /* Alarm Status */ +#define AT91_ST_IER (AT91_ST + 0x14) /* Interrupt Enable Register */ +#define AT91_ST_IDR (AT91_ST + 0x18) /* Interrupt Disable Register */ +#define AT91_ST_IMR (AT91_ST + 0x1c) /* Interrupt Mask Register */ +#define AT91_ST_RTAR (AT91_ST + 0x20) /* Real-time Alarm Register */ +#define AT91_ST_ALMV (0xfffff << 0) /* Alarm Value */ +#define AT91_ST_CRTR (AT91_ST + 0x24) /* Current Real-time Register */ +#define AT91_ST_CRTV (0xfffff << 0) /* Current Real-Time Value */ + + +/* + * Real-time Clock. + */ +#define AT91_RTC 0xe00 + +#define AT91_RTC_CR (AT91_RTC + 0x00) /* Control Register */ +#define AT91_RTC_UPDTIM (1 << 0) /* Update Request Time Register */ +#define AT91_RTC_UPDCAL (1 << 1) /* Update Request Calendar Register */ +#define AT91_RTC_TIMEVSEL (3 << 8) /* Time Event Selection */ +#define AT91_RTC_TIMEVSEL_MINUTE (0 << 8) +#define AT91_RTC_TIMEVSEL_HOUR (1 << 8) +#define AT91_RTC_TIMEVSEL_DAY24 (2 << 8) +#define AT91_RTC_TIMEVSEL_DAY12 (3 << 8) +#define AT91_RTC_CALEVSEL (3 << 16) /* Calendar Event Selection */ +#define AT91_RTC_CALEVSEL_WEEK (0 << 16) +#define AT91_RTC_CALEVSEL_MONTH (1 << 16) +#define AT91_RTC_CALEVSEL_YEAR (2 << 16) + +#define AT91_RTC_MR (AT91_RTC + 0x04) /* Mode Register */ +#define AT91_RTC_HRMOD (1 << 0) /* 12/24 Hour Mode */ + +#define AT91_RTC_TIMR (AT91_RTC + 0x08) /* Time Register */ +#define AT91_RTC_SEC (0x7f << 0) /* Current Second */ +#define AT91_RTC_MIN (0x7f << 8) /* Current Minute */ +#define AT91_RTC_HOUR (0x3f << 16) /* Current Hour */ +#define At91_RTC_AMPM (1 << 22) /* Ante Meridiem Post Meridiem Indicator */ + +#define AT91_RTC_CALR (AT91_RTC + 0x0c) /* Calendar Register */ +#define AT91_RTC_CENT (0x7f << 0) /* Current Century */ +#define AT91_RTC_YEAR (0xff << 8) /* Current Year */ +#define AT91_RTC_MONTH (0x1f << 16) /* Current Month */ +#define AT91_RTC_DAY (7 << 21) /* Current Day */ +#define AT91_RTC_DATE (0x3f << 24) /* Current Date */ + +#define AT91_RTC_TIMALR (AT91_RTC + 0x10) /* Time Alarm Register */ +#define AT91_RTC_SECEN (1 << 7) /* Second Alarm Enable */ +#define AT91_RTC_MINEN (1 << 15) /* Minute Alarm Enable */ +#define AT91_RTC_HOUREN (1 << 23) /* Hour Alarm Enable */ + +#define AT91_RTC_CALALR (AT91_RTC + 0x14) /* Calendar Alarm Register */ +#define AT91_RTC_MTHEN (1 << 23) /* Month Alarm Enable */ +#define AT91_RTC_DATEEN (1 << 31) /* Date Alarm Enable */ + +#define AT91_RTC_SR (AT91_RTC + 0x18) /* Status Register */ +#define AT91_RTC_ACKUPD (1 << 0) /* Acknowledge for Update */ +#define AT91_RTC_ALARM (1 << 1) /* Alarm Flag */ +#define AT91_RTC_SECEV (1 << 2) /* Second Event */ +#define AT91_RTC_TIMEV (1 << 3) /* Time Event */ +#define AT91_RTC_CALEV (1 << 4) /* Calendar Event */ + +#define AT91_RTC_SCCR (AT91_RTC + 0x1c) /* Status Clear Command Register */ +#define AT91_RTC_IER (AT91_RTC + 0x20) /* Interrupt Enable Register */ +#define AT91_RTC_IDR (AT91_RTC + 0x24) /* Interrupt Disable Register */ +#define AT91_RTC_IMR (AT91_RTC + 0x28) /* Interrupt Mask Register */ + +#define AT91_RTC_VER (AT91_RTC + 0x2c) /* Valid Entry Register */ +#define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */ +#define AT91_RTC_NVCAL (1 << 1) /* Non valid Calendar */ +#define AT91_RTC_NVTIMALR (1 << 2) /* Non valid Time Alarm */ +#define AT91_RTC_NVCALALR (1 << 3) /* Non valid Calendar Alarm */ + + +/* + * Memory Controller. + */ +#define AT91_MC 0xf00 + +#define AT91_MC_RCR (AT91_MC + 0x00) /* MC Remap Control Register */ +#define AT91_MC_RCB (1 << 0) /* Remap Command Bit */ + +#define AT91_MC_ASR (AT91_MC + 0x04) /* MC Abort Status Register */ +#define AT91_MC_AASR (AT91_MC + 0x08) /* MC Abort Address Status Register */ +#define AT91_MC_MPR (AT91_MC + 0x0c) /* MC Master Priority Register */ + +/* External Bus Interface (EBI) registers */ +#define AT91_EBI_CSA (AT91_MC + 0x60) /* Chip Select Assignment Register */ +#define AT91_EBI_CS0A (1 << 0) /* Chip Select 0 Assignment */ +#define AT91_EBI_CS0A_SMC (0 << 0) +#define AT91_EBI_CS0A_BFC (1 << 0) +#define AT91_EBI_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_EBI_CS1A_SMC (0 << 1) +#define AT91_EBI_CS1A_SDRAMC (1 << 1) +#define AT91_EBI_CS3A (1 << 3) /* Chip Select 2 Assignment */ +#define AT91_EBI_CS3A_SMC (0 << 3) +#define AT91_EBI_CS3A_SMC_SMARTMEDIA (1 << 3) +#define AT91_EBI_CS4A (1 << 4) /* Chip Select 3 Assignment */ +#define AT91_EBI_CS4A_SMC (0 << 4) +#define AT91_EBI_CS4A_SMC_COMPACTFLASH (1 << 4) +#define AT91_EBI_CFGR (AT91_MC + 0x64) /* Configuration Register */ +#define AT91_EBI_DBPUC (1 << 0) /* Data Bus Pull-Up Configuration */ + +/* Static Memory Controller (SMC) registers */ +#define AT91_SMC_CSR(n) (AT91_MC + 0x70 + ((n) * 4))/* SMC Chip Select Register */ +#define AT91_SMC_NWS (0x7f << 0) /* Number of Wait States */ +#define AT91_SMC_WSEN (1 << 7) /* Wait State Enable */ +#define AT91_SMC_TDF (0xf << 8) /* Data Float Time */ +#define AT91_SMC_BAT (1 << 12) /* Byte Access Type */ +#define AT91_SMC_DBW (3 << 13) /* Data Bus Width */ +#define AT91_SMC_DBW_16 (1 << 13) +#define AT91_SMC_DBW_8 (2 << 13) +#define AT91_SMC_DPR (1 << 15) /* Data Read Protocol */ +#define AT91_SMC_ACSS (3 << 16) /* Address to Chip Select Setup */ +#define AT91_SMC_ACSS_STD (0 << 16) +#define AT91_SMC_ACSS_1 (1 << 16) +#define AT91_SMC_ACSS_2 (2 << 16) +#define AT91_SMC_ACSS_3 (3 << 16) +#define AT91_SMC_RWSETUP (7 << 24) /* Read & Write Signal Time Setup */ +#define AT91_SMC_RWHOLD (7 << 28) /* Read & Write Signal Hold Time */ + + +#endif diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h new file mode 100644 index 000000000000..2e7d1139a799 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/board.h @@ -0,0 +1,80 @@ +/* + * include/asm-arm/arch-at91rm9200/board.h + * + * Copyright (C) 2005 HP 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * These are data structures found in platform_device.dev.platform_data, + * and describing board-specfic data needed by drivers. For example, + * which pin is used for a given GPIO role. + * + * In 2.6, drivers should strongly avoid board-specific knowledge so + * that supporting new boards normally won't require driver patches. + * Most board-specific knowledge should be in arch/.../board-*.c files. + */ + +#ifndef __ASM_ARCH_BOARD_H +#define __ASM_ARCH_BOARD_H + + /* Clocks */ +extern unsigned long at91_master_clock; + + /* Serial Port */ +extern int at91_serial_map[AT91_NR_UART]; +extern int at91_console_port; + + /* USB Device */ +struct at91_udc_data { + u8 vbus_pin; /* high == host powering us */ + u8 pullup_pin; /* high == D+ pulled up */ +}; +extern void __init at91_add_device_udc(struct at91_udc_data *data); + + /* Compact Flash */ +struct at91_cf_data { + u8 irq_pin; /* I/O IRQ */ + u8 det_pin; /* Card detect */ + u8 vcc_pin; /* power switching */ + u8 rst_pin; /* card reset */ +}; +extern void __init at91_add_device_cf(struct at91_cf_data *data); + + /* MMC / SD */ +struct at91_mmc_data { + u8 det_pin; /* card detect IRQ */ + unsigned is_b:1; /* uses B side (vs A) */ + unsigned wire4:1; /* (SD) supports DAT0..DAT3 */ + u8 wp_pin; /* (SD) writeprotect detect */ + u8 vcc_pin; /* power switching (high == on) */ +}; +extern void __init at91_add_device_mmc(struct at91_mmc_data *data); + + /* Ethernet */ +struct at91_eth_data { + u8 phy_irq_pin; /* PHY IRQ */ + u8 is_rmii; /* using RMII interface? */ +}; +extern void __init at91_add_device_eth(struct at91_eth_data *data); + + /* USB Host */ +struct at91_usbh_data { + u8 ports; /* number of ports on root hub */ +}; +extern void __init at91_add_device_usbh(struct at91_usbh_data *data); + +#endif diff --git a/include/asm-arm/arch-at91rm9200/debug-macro.S b/include/asm-arm/arch-at91rm9200/debug-macro.S new file mode 100644 index 000000000000..f496b54c4c3e --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/debug-macro.S @@ -0,0 +1,38 @@ +/* + * include/asm-arm/arch-at91rm9200/debug-macro.S + * + * Copyright (C) 2003-2005 SAN People + * + * Debugging macro include header + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <asm/hardware.h> + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + ldreq \rx, =AT91_BASE_SYS @ System peripherals (phys address) + ldrne \rx, =AT91_VA_BASE_SYS @ System peripherals (virt address) + .endm + + .macro senduart,rd,rx + strb \rd, [\rx, #AT91_DBGU_THR] @ Write to Transmitter Holding Register + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #AT91_DBGU_SR] @ Read Status Register + tst \rd, #AT91_DBGU_TXRDY @ DBGU_TXRDY = 1 when ready to transmit + beq 1001b + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #AT91_DBGU_SR] @ Read Status Register + tst \rd, #AT91_DBGU_TXEMPTY @ DBGU_TXEMPTY = 1 when transmission complete + beq 1001b + .endm + diff --git a/include/asm-arm/arch-epxa10db/dma.h b/include/asm-arm/arch-at91rm9200/dma.h index de20ec8e74b1..22c1dfdd8da3 100644 --- a/include/asm-arm/arch-epxa10db/dma.h +++ b/include/asm-arm/arch-at91rm9200/dma.h @@ -1,7 +1,7 @@ /* - * linux/include/asm-arm/arch-camelot/dma.h + * include/asm-arm/arch-at91rm9200/dma.h * - * Copyright (C) 1997,1998 Russell King + * Copyright (C) 2003 SAN People * * 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 diff --git a/include/asm-arm/arch-at91rm9200/entry-macro.S b/include/asm-arm/arch-at91rm9200/entry-macro.S new file mode 100644 index 000000000000..61a326e94909 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/entry-macro.S @@ -0,0 +1,25 @@ +/* + * include/asm-arm/arch-at91rm9200/entry-macro.S + * + * Copyright (C) 2003-2005 SAN People + * + * Low-level IRQ helper macros for AT91RM9200 platforms + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <asm/hardware.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, =(AT91_VA_BASE_SYS) @ base virtual address of SYS peripherals + ldr \irqnr, [\base, #AT91_AIC_IVR] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt) + ldr \irqstat, [\base, #AT91_AIC_ISR] @ read interrupt source number + teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt + streq \tmp, [\base, #AT91_AIC_EOICR] @ not going to be handled further, then ACK it now. + .endm + diff --git a/include/asm-arm/arch-at91rm9200/gpio.h b/include/asm-arm/arch-at91rm9200/gpio.h new file mode 100644 index 000000000000..0f0a61e2f129 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/gpio.h @@ -0,0 +1,193 @@ +/* + * include/asm-arm/arch-at91rm9200/gpio.h + * + * Copyright (C) 2005 HP 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. + * + */ + +#ifndef __ASM_ARCH_AT91RM9200_GPIO_H +#define __ASM_ARCH_AT91RM9200_GPIO_H + +#define PIN_BASE NR_AIC_IRQS + +#define PQFP_GPIO_BANKS 3 /* PQFP package has 3 banks */ +#define BGA_GPIO_BANKS 4 /* BGA package has 4 banks */ + +/* these pin numbers double as IRQ numbers, like AT91_ID_* values */ + +#define AT91_PIN_PA0 (PIN_BASE + 0x00 + 0) +#define AT91_PIN_PA1 (PIN_BASE + 0x00 + 1) +#define AT91_PIN_PA2 (PIN_BASE + 0x00 + 2) +#define AT91_PIN_PA3 (PIN_BASE + 0x00 + 3) +#define AT91_PIN_PA4 (PIN_BASE + 0x00 + 4) + +#define AT91_PIN_PA5 (PIN_BASE + 0x00 + 5) +#define AT91_PIN_PA6 (PIN_BASE + 0x00 + 6) +#define AT91_PIN_PA7 (PIN_BASE + 0x00 + 7) +#define AT91_PIN_PA8 (PIN_BASE + 0x00 + 8) +#define AT91_PIN_PA9 (PIN_BASE + 0x00 + 9) + +#define AT91_PIN_PA10 (PIN_BASE + 0x00 + 10) +#define AT91_PIN_PA11 (PIN_BASE + 0x00 + 11) +#define AT91_PIN_PA12 (PIN_BASE + 0x00 + 12) +#define AT91_PIN_PA13 (PIN_BASE + 0x00 + 13) +#define AT91_PIN_PA14 (PIN_BASE + 0x00 + 14) + +#define AT91_PIN_PA15 (PIN_BASE + 0x00 + 15) +#define AT91_PIN_PA16 (PIN_BASE + 0x00 + 16) +#define AT91_PIN_PA17 (PIN_BASE + 0x00 + 17) +#define AT91_PIN_PA18 (PIN_BASE + 0x00 + 18) +#define AT91_PIN_PA19 (PIN_BASE + 0x00 + 19) + +#define AT91_PIN_PA20 (PIN_BASE + 0x00 + 20) +#define AT91_PIN_PA21 (PIN_BASE + 0x00 + 21) +#define AT91_PIN_PA22 (PIN_BASE + 0x00 + 22) +#define AT91_PIN_PA23 (PIN_BASE + 0x00 + 23) +#define AT91_PIN_PA24 (PIN_BASE + 0x00 + 24) + +#define AT91_PIN_PA25 (PIN_BASE + 0x00 + 25) +#define AT91_PIN_PA26 (PIN_BASE + 0x00 + 26) +#define AT91_PIN_PA27 (PIN_BASE + 0x00 + 27) +#define AT91_PIN_PA28 (PIN_BASE + 0x00 + 28) +#define AT91_PIN_PA29 (PIN_BASE + 0x00 + 29) + +#define AT91_PIN_PA30 (PIN_BASE + 0x00 + 30) +#define AT91_PIN_PA31 (PIN_BASE + 0x00 + 31) + +#define AT91_PIN_PB0 (PIN_BASE + 0x20 + 0) +#define AT91_PIN_PB1 (PIN_BASE + 0x20 + 1) +#define AT91_PIN_PB2 (PIN_BASE + 0x20 + 2) +#define AT91_PIN_PB3 (PIN_BASE + 0x20 + 3) +#define AT91_PIN_PB4 (PIN_BASE + 0x20 + 4) + +#define AT91_PIN_PB5 (PIN_BASE + 0x20 + 5) +#define AT91_PIN_PB6 (PIN_BASE + 0x20 + 6) +#define AT91_PIN_PB7 (PIN_BASE + 0x20 + 7) +#define AT91_PIN_PB8 (PIN_BASE + 0x20 + 8) +#define AT91_PIN_PB9 (PIN_BASE + 0x20 + 9) + +#define AT91_PIN_PB10 (PIN_BASE + 0x20 + 10) +#define AT91_PIN_PB11 (PIN_BASE + 0x20 + 11) +#define AT91_PIN_PB12 (PIN_BASE + 0x20 + 12) +#define AT91_PIN_PB13 (PIN_BASE + 0x20 + 13) +#define AT91_PIN_PB14 (PIN_BASE + 0x20 + 14) + +#define AT91_PIN_PB15 (PIN_BASE + 0x20 + 15) +#define AT91_PIN_PB16 (PIN_BASE + 0x20 + 16) +#define AT91_PIN_PB17 (PIN_BASE + 0x20 + 17) +#define AT91_PIN_PB18 (PIN_BASE + 0x20 + 18) +#define AT91_PIN_PB19 (PIN_BASE + 0x20 + 19) + +#define AT91_PIN_PB20 (PIN_BASE + 0x20 + 20) +#define AT91_PIN_PB21 (PIN_BASE + 0x20 + 21) +#define AT91_PIN_PB22 (PIN_BASE + 0x20 + 22) +#define AT91_PIN_PB23 (PIN_BASE + 0x20 + 23) +#define AT91_PIN_PB24 (PIN_BASE + 0x20 + 24) + +#define AT91_PIN_PB25 (PIN_BASE + 0x20 + 25) +#define AT91_PIN_PB26 (PIN_BASE + 0x20 + 26) +#define AT91_PIN_PB27 (PIN_BASE + 0x20 + 27) +#define AT91_PIN_PB28 (PIN_BASE + 0x20 + 28) +#define AT91_PIN_PB29 (PIN_BASE + 0x20 + 29) + +#define AT91_PIN_PB30 (PIN_BASE + 0x20 + 30) +#define AT91_PIN_PB31 (PIN_BASE + 0x20 + 31) + +#define AT91_PIN_PC0 (PIN_BASE + 0x40 + 0) +#define AT91_PIN_PC1 (PIN_BASE + 0x40 + 1) +#define AT91_PIN_PC2 (PIN_BASE + 0x40 + 2) +#define AT91_PIN_PC3 (PIN_BASE + 0x40 + 3) +#define AT91_PIN_PC4 (PIN_BASE + 0x40 + 4) + +#define AT91_PIN_PC5 (PIN_BASE + 0x40 + 5) +#define AT91_PIN_PC6 (PIN_BASE + 0x40 + 6) +#define AT91_PIN_PC7 (PIN_BASE + 0x40 + 7) +#define AT91_PIN_PC8 (PIN_BASE + 0x40 + 8) +#define AT91_PIN_PC9 (PIN_BASE + 0x40 + 9) + +#define AT91_PIN_PC10 (PIN_BASE + 0x40 + 10) +#define AT91_PIN_PC11 (PIN_BASE + 0x40 + 11) +#define AT91_PIN_PC12 (PIN_BASE + 0x40 + 12) +#define AT91_PIN_PC13 (PIN_BASE + 0x40 + 13) +#define AT91_PIN_PC14 (PIN_BASE + 0x40 + 14) + +#define AT91_PIN_PC15 (PIN_BASE + 0x40 + 15) +#define AT91_PIN_PC16 (PIN_BASE + 0x40 + 16) +#define AT91_PIN_PC17 (PIN_BASE + 0x40 + 17) +#define AT91_PIN_PC18 (PIN_BASE + 0x40 + 18) +#define AT91_PIN_PC19 (PIN_BASE + 0x40 + 19) + +#define AT91_PIN_PC20 (PIN_BASE + 0x40 + 20) +#define AT91_PIN_PC21 (PIN_BASE + 0x40 + 21) +#define AT91_PIN_PC22 (PIN_BASE + 0x40 + 22) +#define AT91_PIN_PC23 (PIN_BASE + 0x40 + 23) +#define AT91_PIN_PC24 (PIN_BASE + 0x40 + 24) + +#define AT91_PIN_PC25 (PIN_BASE + 0x40 + 25) +#define AT91_PIN_PC26 (PIN_BASE + 0x40 + 26) +#define AT91_PIN_PC27 (PIN_BASE + 0x40 + 27) +#define AT91_PIN_PC28 (PIN_BASE + 0x40 + 28) +#define AT91_PIN_PC29 (PIN_BASE + 0x40 + 29) + +#define AT91_PIN_PC30 (PIN_BASE + 0x40 + 30) +#define AT91_PIN_PC31 (PIN_BASE + 0x40 + 31) + +#define AT91_PIN_PD0 (PIN_BASE + 0x60 + 0) +#define AT91_PIN_PD1 (PIN_BASE + 0x60 + 1) +#define AT91_PIN_PD2 (PIN_BASE + 0x60 + 2) +#define AT91_PIN_PD3 (PIN_BASE + 0x60 + 3) +#define AT91_PIN_PD4 (PIN_BASE + 0x60 + 4) + +#define AT91_PIN_PD5 (PIN_BASE + 0x60 + 5) +#define AT91_PIN_PD6 (PIN_BASE + 0x60 + 6) +#define AT91_PIN_PD7 (PIN_BASE + 0x60 + 7) +#define AT91_PIN_PD8 (PIN_BASE + 0x60 + 8) +#define AT91_PIN_PD9 (PIN_BASE + 0x60 + 9) + +#define AT91_PIN_PD10 (PIN_BASE + 0x60 + 10) +#define AT91_PIN_PD11 (PIN_BASE + 0x60 + 11) +#define AT91_PIN_PD12 (PIN_BASE + 0x60 + 12) +#define AT91_PIN_PD13 (PIN_BASE + 0x60 + 13) +#define AT91_PIN_PD14 (PIN_BASE + 0x60 + 14) + +#define AT91_PIN_PD15 (PIN_BASE + 0x60 + 15) +#define AT91_PIN_PD16 (PIN_BASE + 0x60 + 16) +#define AT91_PIN_PD17 (PIN_BASE + 0x60 + 17) +#define AT91_PIN_PD18 (PIN_BASE + 0x60 + 18) +#define AT91_PIN_PD19 (PIN_BASE + 0x60 + 19) + +#define AT91_PIN_PD20 (PIN_BASE + 0x60 + 20) +#define AT91_PIN_PD21 (PIN_BASE + 0x60 + 21) +#define AT91_PIN_PD22 (PIN_BASE + 0x60 + 22) +#define AT91_PIN_PD23 (PIN_BASE + 0x60 + 23) +#define AT91_PIN_PD24 (PIN_BASE + 0x60 + 24) + +#define AT91_PIN_PD25 (PIN_BASE + 0x60 + 25) +#define AT91_PIN_PD26 (PIN_BASE + 0x60 + 26) +#define AT91_PIN_PD27 (PIN_BASE + 0x60 + 27) +#define AT91_PIN_PD28 (PIN_BASE + 0x60 + 28) +#define AT91_PIN_PD29 (PIN_BASE + 0x60 + 29) + +#define AT91_PIN_PD30 (PIN_BASE + 0x60 + 30) +#define AT91_PIN_PD31 (PIN_BASE + 0x60 + 31) + +#ifndef __ASSEMBLY__ +/* setup setup routines, called from board init or driver probe() */ +extern int at91_set_A_periph(unsigned pin, int use_pullup); +extern int at91_set_B_periph(unsigned pin, int use_pullup); +extern int at91_set_gpio_input(unsigned pin, int use_pullup); +extern int at91_set_gpio_output(unsigned pin, int value); +extern int at91_set_deglitch(unsigned pin, int is_on); + +/* callable at any time */ +extern int at91_set_gpio_value(unsigned pin, int value); +extern int at91_get_gpio_value(unsigned pin); +#endif + +#endif + diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h new file mode 100644 index 000000000000..2646c01f8e97 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/hardware.h @@ -0,0 +1,92 @@ +/* + * include/asm-arm/arch-at91rm9200/hardware.h + * + * Copyright (C) 2003 SAN People + * Copyright (C) 2003 ATMEL + * + * 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. + * + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include <asm/sizes.h> + +#include <asm/arch/at91rm9200.h> +#include <asm/arch/at91rm9200_sys.h> + +/* + * Remap the peripherals from address 0xFFFA0000 .. 0xFFFFFFFF + * to 0xFEFA0000 .. 0xFF000000. (384Kb) + */ +#define AT91_IO_PHYS_BASE 0xFFFA0000 +#define AT91_IO_SIZE (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1) +#define AT91_IO_VIRT_BASE (0xFF000000 - AT91_IO_SIZE) + + /* Convert a physical IO address to virtual IO address */ +#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE) + +/* + * Virtual to Physical Address mapping for IO devices. + */ +#define AT91_VA_BASE_SYS AT91_IO_P2V(AT91_BASE_SYS) +#define AT91_VA_BASE_SPI AT91_IO_P2V(AT91_BASE_SPI) +#define AT91_VA_BASE_SSC2 AT91_IO_P2V(AT91_BASE_SSC2) +#define AT91_VA_BASE_SSC1 AT91_IO_P2V(AT91_BASE_SSC1) +#define AT91_VA_BASE_SSC0 AT91_IO_P2V(AT91_BASE_SSC0) +#define AT91_VA_BASE_US3 AT91_IO_P2V(AT91_BASE_US3) +#define AT91_VA_BASE_US2 AT91_IO_P2V(AT91_BASE_US2) +#define AT91_VA_BASE_US1 AT91_IO_P2V(AT91_BASE_US1) +#define AT91_VA_BASE_US0 AT91_IO_P2V(AT91_BASE_US0) +#define AT91_VA_BASE_EMAC AT91_IO_P2V(AT91_BASE_EMAC) +#define AT91_VA_BASE_TWI AT91_IO_P2V(AT91_BASE_TWI) +#define AT91_VA_BASE_MCI AT91_IO_P2V(AT91_BASE_MCI) +#define AT91_VA_BASE_UDP AT91_IO_P2V(AT91_BASE_UDP) +#define AT91_VA_BASE_TCB1 AT91_IO_P2V(AT91_BASE_TCB1) +#define AT91_VA_BASE_TCB0 AT91_IO_P2V(AT91_BASE_TCB0) + +/* Internal SRAM */ +#define AT91_BASE_SRAM 0x00200000 /* Internal SRAM base address */ +#define AT91_SRAM_SIZE 0x00004000 /* Internal SRAM SIZE (16Kb) */ + +/* Serial ports */ +#define AT91_NR_UART 5 /* 4 USART3's and one DBGU port */ + +/* FLASH */ +#define AT91_FLASH_BASE 0x10000000 /* NCS0: Flash physical base address */ + +/* SDRAM */ +#define AT91_SDRAM_BASE 0x20000000 /* NCS1: SDRAM physical base address */ + +/* SmartMedia */ +#define AT91_SMARTMEDIA_BASE 0x40000000 /* NCS3: Smartmedia physical base address */ + +/* Multi-Master Memory controller */ +#define AT91_UHP_BASE 0x00300000 /* USB Host controller */ + +/* Clocks */ +#define AT91_SLOW_CLOCK 32768 /* slow clock */ + +#ifndef __ASSEMBLY__ +#include <asm/io.h> + +static inline unsigned int at91_sys_read(unsigned int reg_offset) +{ + void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS; + + return readl(addr + reg_offset); +} + +static inline void at91_sys_write(unsigned int reg_offset, unsigned long value) +{ + void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS; + + writel(value, addr + reg_offset); +} +#endif + +#endif diff --git a/include/asm-arm/arch-epxa10db/io.h b/include/asm-arm/arch-at91rm9200/io.h index 9fe100c9d6be..23e670d85c9d 100644 --- a/include/asm-arm/arch-epxa10db/io.h +++ b/include/asm-arm/arch-at91rm9200/io.h @@ -1,7 +1,7 @@ /* - * linux/include/asm-arm/arch-epxa10db/io.h + * include/asm-arm/arch-at91rm9200/io.h * - * Copyright (C) 1999 ARM Limited + * Copyright (C) 2003 SAN People * * 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 @@ -17,25 +17,17 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __ASM_ARM_ARCH_IO_H -#define __ASM_ARM_ARCH_IO_H -#include <asm/hardware.h> +#ifndef __ASM_ARCH_IO_H +#define __ASM_ARCH_IO_H -#define IO_SPACE_LIMIT 0xffff +#include <asm/arch/at91rm9200.h> +#include <asm/io.h> - -/* - * Generic virtual read/write - */ -/*#define outsw __arch_writesw -#define outsl __arch_writesl -#define outsb __arch_writesb -#define insb __arch_readsb -#define insw __arch_readsw -#define insl __arch_readsl*/ +#define IO_SPACE_LIMIT 0xFFFFFFFF #define __io(a) ((void __iomem *)(a)) -#define __mem_pci(a) (a) +#define __mem_pci(a) (a) + #endif diff --git a/include/asm-arm/arch-at91rm9200/irqs.h b/include/asm-arm/arch-at91rm9200/irqs.h new file mode 100644 index 000000000000..27b0497f1b36 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/irqs.h @@ -0,0 +1,52 @@ +/* + * include/asm-arm/arch-at91rm9200/irqs.h + * + * Copyright (C) 2004 SAN People + * + * 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 + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +#define NR_AIC_IRQS 32 + + +/* + * Acknowledge interrupt with AIC after interrupt has been handled. + * (by kernel/irq.c) + */ +#define irq_finish(irq) do { at91_sys_write(AT91_AIC_EOICR, 0); } while (0) + + +/* + * IRQ interrupt symbols are the AT91_ID_* symbols in at91rm9200.h + * for IRQs handled directly through the AIC, or else the AT91_PIN_* + * symbols in gpio.h for ones handled indirectly as GPIOs. + * We make provision for 4 banks of GPIO. + */ +#include <asm/arch/gpio.h> + +#define NR_IRQS (NR_AIC_IRQS + (4 * 32)) + + +#ifndef __ASSEMBLY__ +/* + * Initialize the IRQ controller. + */ +extern void at91rm9200_init_irq(unsigned int priority[]); +#endif + +#endif diff --git a/include/asm-arm/arch-epxa10db/memory.h b/include/asm-arm/arch-at91rm9200/memory.h index 999541b6a9f5..462f1f0ad67c 100644 --- a/include/asm-arm/arch-epxa10db/memory.h +++ b/include/asm-arm/arch-at91rm9200/memory.h @@ -1,7 +1,7 @@ /* - * linux/include/asm-arm/arch-epxa10/memory.h + * include/asm-arm/arch-at91rm9200/memory.h * - * Copyright (C) 2001 Altera Corporation + * Copyright (C) 2004 SAN People * * 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 @@ -17,13 +17,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -/* - * Physical DRAM offset. - */ -#define PHYS_OFFSET UL(0x00000000) +#include <asm/arch/hardware.h> + +#define PHYS_OFFSET (AT91_SDRAM_BASE) + /* * Virtual view <-> DMA view memory address translations @@ -32,7 +33,9 @@ * bus_to_virt: Used to convert an address for DMA operations * to an address that the kernel can use. */ -#define __virt_to_bus(x) (x - PAGE_OFFSET + /*SDRAM_BASE*/0) -#define __bus_to_virt(x) (x - /*SDRAM_BASE*/0 + PAGE_OFFSET) +#define __virt_to_bus__is_a_macro +#define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt__is_a_macro +#define __bus_to_virt(x) __phys_to_virt(x) #endif diff --git a/include/asm-arm/arch-epxa10db/param.h b/include/asm-arm/arch-at91rm9200/param.h index 783dedd71c8f..9480f8446852 100644 --- a/include/asm-arm/arch-epxa10db/param.h +++ b/include/asm-arm/arch-at91rm9200/param.h @@ -1,7 +1,7 @@ /* - * linux/include/asm-arm/arch-epxa10db/param.h + * include/asm-arm/arch-at91rm9200/param.h * - * Copyright (C) 1999 ARM Limited + * Copyright (C) 2003 SAN People * * 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 @@ -17,3 +17,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef __ASM_ARCH_PARAM_H +#define __ASM_ARCH_PARAM_H + +/* + * We use default params + */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/pio.h b/include/asm-arm/arch-at91rm9200/pio.h new file mode 100644 index 000000000000..a89501b4a703 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/pio.h @@ -0,0 +1,115 @@ +/* + * include/asm-arm/arch-at91rm9200/pio.h + * + * Copyright (C) 2003 SAN People + * + * 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. + * + */ + +#ifndef __ASM_ARCH_PIO_H +#define __ASM_ARCH_PIO_H + +#include <asm/arch/hardware.h> + +static inline void AT91_CfgPIO_USART0(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA17_TXD0 | AT91_PA18_RXD0 | AT91_PA20_CTS0); + + /* + * Errata #39 - RTS0 is not internally connected to PA21. We need to drive + * the pin manually. Default is off (RTS is active low). + */ + at91_sys_write(AT91_PIOA + PIO_PER, AT91_PA21_RTS0); + at91_sys_write(AT91_PIOA + PIO_OER, AT91_PA21_RTS0); + at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0); +} + +static inline void AT91_CfgPIO_USART1(void) { + at91_sys_write(AT91_PIOB + PIO_PDR, AT91_PB18_RI1 | AT91_PB19_DTR1 + | AT91_PB20_TXD1 | AT91_PB21_RXD1 | AT91_PB23_DCD1 + | AT91_PB24_CTS1 | AT91_PB25_DSR1 | AT91_PB26_RTS1); +} + +static inline void AT91_CfgPIO_USART2(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA22_RXD2 | AT91_PA23_TXD2); +} + +static inline void AT91_CfgPIO_USART3(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA5_TXD3 | AT91_PA6_RXD3); + at91_sys_write(AT91_PIOA + PIO_BSR, AT91_PA5_TXD3 | AT91_PA6_RXD3); +} + +static inline void AT91_CfgPIO_DBGU(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA31_DTXD | AT91_PA30_DRXD); +} + +/* + * Enable the Two-Wire interface. + */ +static inline void AT91_CfgPIO_TWI(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA25_TWD | AT91_PA26_TWCK); + at91_sys_write(AT91_PIOA + PIO_ASR, AT91_PA25_TWD | AT91_PA26_TWCK); + at91_sys_write(AT91_PIOA + PIO_MDER, AT91_PA25_TWD | AT91_PA26_TWCK); /* open drain */ +} + +/* + * Enable the Serial Peripheral Interface. + */ +static inline void AT91_CfgPIO_SPI(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA0_MISO | AT91_PA1_MOSI | AT91_PA2_SPCK); +} + +static inline void AT91_CfgPIO_SPI_CS0(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA3_NPCS0); +} + +static inline void AT91_CfgPIO_SPI_CS1(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA4_NPCS1); +} + +static inline void AT91_CfgPIO_SPI_CS2(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA5_NPCS2); +} + +static inline void AT91_CfgPIO_SPI_CS3(void) { + at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA6_NPCS3); +} + +/* + * Select the DataFlash card. + */ +static inline void AT91_CfgPIO_DataFlashCard(void) { + at91_sys_write(AT91_PIOB + PIO_PER, AT91_PIO_P(7)); + at91_sys_write(AT91_PIOB + PIO_OER, AT91_PIO_P(7)); + at91_sys_write(AT91_PIOB + PIO_CODR, AT91_PIO_P(7)); +} + +/* + * Enable NAND Flash (SmartMedia) interface. + */ +static inline void AT91_CfgPIO_SmartMedia(void) { + /* enable PC0=SMCE, PC1=SMOE, PC3=SMWE, A21=CLE, A22=ALE */ + at91_sys_write(AT91_PIOC + PIO_ASR, AT91_PC0_BFCK | AT91_PC1_BFRDY_SMOE | AT91_PC3_BFBAA_SMWE); + at91_sys_write(AT91_PIOC + PIO_PDR, AT91_PC0_BFCK | AT91_PC1_BFRDY_SMOE | AT91_PC3_BFBAA_SMWE); + + /* Configure PC2 as input (signal READY of the SmartMedia) */ + at91_sys_write(AT91_PIOC + PIO_PER, AT91_PC2_BFAVD); /* enable direct output enable */ + at91_sys_write(AT91_PIOC + PIO_ODR, AT91_PC2_BFAVD); /* disable output */ + + /* Configure PB1 as input (signal Card Detect of the SmartMedia) */ + at91_sys_write(AT91_PIOB + PIO_PER, AT91_PIO_P(1)); /* enable direct output enable */ + at91_sys_write(AT91_PIOB + PIO_ODR, AT91_PIO_P(1)); /* disable output */ +} + +static inline int AT91_PIO_SmartMedia_RDY(void) { + return (at91_sys_read(AT91_PIOC + PIO_PDSR) & AT91_PIO_P(2)) ? 1 : 0; +} + +static inline int AT91_PIO_SmartMedia_CardDetect(void) { + return (at91_sys_read(AT91_PIOB + PIO_PDSR) & AT91_PIO_P(1)) ? 1 : 0; +} + +#endif diff --git a/include/asm-arm/arch-epxa10db/system.h b/include/asm-arm/arch-at91rm9200/system.h index 345b092a1ed5..29c42655f05c 100644 --- a/include/asm-arm/arch-epxa10db/system.h +++ b/include/asm-arm/arch-at91rm9200/system.h @@ -1,9 +1,7 @@ /* - * linux/include/asm-arm/arch-epxa10db/system.h + * include/asm-arm/arch-at91rm9200/system.h * - * Copyright (C) 1999 ARM Limited - * Copyright (C) 2000 Deep Blue Solutions Ltd - * Copyright (C) 2001 Altera Corporation + * Copyright (C) 2003 SAN People * * 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 @@ -19,23 +17,35 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H -#include <asm/arch/platform.h> +#include <asm/arch/hardware.h> static inline void arch_idle(void) { /* - * This should do all the clock switching - * and wait for interrupt tricks + * Disable the processor clock. The processor will be automatically + * re-enabled by an interrupt or by a reset. + */ +// at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK); + + /* + * Set the processor (CP15) into 'Wait for Interrupt' mode. + * Unlike disabling the processor clock via the PMC (above) + * this allows the processor to be woken via JTAG. */ cpu_do_idle(); } -extern __inline__ void arch_reset(char mode) +static inline void arch_reset(char mode) { - /* Hmm... We can probably do something with the watchdog... */ + /* + * Perform a hardware reset with the use of the Watchdog timer. + */ + at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1); + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); } #endif diff --git a/include/asm-arm/arch-epxa10db/timex.h b/include/asm-arm/arch-at91rm9200/timex.h index b87a75fc9589..3f112dd12587 100644 --- a/include/asm-arm/arch-epxa10db/timex.h +++ b/include/asm-arm/arch-at91rm9200/timex.h @@ -1,9 +1,7 @@ /* - * linux/include/asm-arm/arch-epxa10db/timex.h + * include/asm-arm/arch-at91rm9200/timex.h * - * Excalibur timex specifications - * - * Copyright (C) 2001 Altera Corporation + * Copyright (C) 2003 SAN People * * 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 @@ -20,7 +18,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - * ?? - */ -#define CLOCK_TICK_RATE (50000000 / 16) +#ifndef __ASM_ARCH_TIMEX_H +#define __ASM_ARCH_TIMEX_H + +#include <asm/arch/hardware.h> + +#define CLOCK_TICK_RATE (AT91_SLOW_CLOCK) + +#endif diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h new file mode 100644 index 000000000000..b30dd5520713 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/uncompress.h @@ -0,0 +1,55 @@ +/* + * include/asm-arm/arch-at91rm9200/uncompress.h + * + * Copyright (C) 2003 SAN People + * + * 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 + */ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#include <asm/arch/hardware.h> + +/* + * The following code assumes the serial port has already been + * initialized by the bootloader. We search for the first enabled + * port in the most probable order. If you didn't setup a port in + * your bootloader then nothing will appear (which might be desired). + * + * This does not append a newline + */ +static void putstr(const char *s) +{ + void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */ + + while (*s) { + while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); } + __raw_writel(*s, sys + AT91_DBGU_THR); + if (*s == '\n') { + while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); } + __raw_writel('\r', sys + AT91_DBGU_THR); + } + s++; + } + /* wait for transmission to complete */ + while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY)) { barrier(); } +} + +#define arch_decomp_setup() + +#define arch_decomp_wdog() + +#endif diff --git a/include/asm-arm/arch-epxa10db/vmalloc.h b/include/asm-arm/arch-at91rm9200/vmalloc.h index 546fb7d2b6ad..34d9718feb90 100644 --- a/include/asm-arm/arch-epxa10db/vmalloc.h +++ b/include/asm-arm/arch-at91rm9200/vmalloc.h @@ -1,7 +1,7 @@ /* - * linux/include/asm-arm/arch-epxa10db/vmalloc.h + * include/asm-arm/arch-at91rm9200/vmalloc.h * - * Copyright (C) 2000 Russell King. + * Copyright (C) 2003 SAN People * * 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 @@ -17,4 +17,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) + +#ifndef __ASM_ARCH_VMALLOC_H +#define __ASM_ARCH_VMALLOC_H + +#define VMALLOC_END (AT91_IO_VIRT_BASE & PGDIR_MASK) + +#endif diff --git a/include/asm-arm/arch-epxa10db/debug-macro.S b/include/asm-arm/arch-epxa10db/debug-macro.S deleted file mode 100644 index 1d11c51f498f..000000000000 --- a/include/asm-arm/arch-epxa10db/debug-macro.S +++ /dev/null @@ -1,41 +0,0 @@ -/* linux/include/asm-arm/arch-epxa10db/debug-macro.S - * - * Debugging macro include header - * - * Copyright (C) 1994-1999 Russell King - * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * -*/ - -#include <asm/arch/excalibur.h> -#define UART00_TYPE -#include <asm/arch/uart00.h> - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - ldr \rx, =EXC_UART00_BASE @ physical base address - orrne \rx, \rx, #0xff000000 @ virtual base - orrne \rx, \rx, #0x00f00000 - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #UART_TD(0)] - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #UART_TSR(0)] - and \rd, \rd, #UART_TSR_TX_LEVEL_MSK - cmp \rd, #15 - beq 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #UART_TSR(0)] - ands \rd, \rd, #UART_TSR_TX_LEVEL_MSK - bne 1001b - .endm diff --git a/include/asm-arm/arch-epxa10db/entry-macro.S b/include/asm-arm/arch-epxa10db/entry-macro.S deleted file mode 100644 index de6ae08334e2..000000000000 --- a/include/asm-arm/arch-epxa10db/entry-macro.S +++ /dev/null @@ -1,25 +0,0 @@ -/* - * include/asm-arm/arch-epxa10db/entry-macro.S - * - * Low-level IRQ helper macros for epxa10db platform - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ -#include <asm/arch/platform.h> -#undef IRQ_MODE /* same name defined in asm/proc/ptrace.h */ -#include <asm/arch/int_ctrl00.h> - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - ldr \irqstat, =INT_ID(IO_ADDRESS(EXC_INT_CTRL00_BASE)) - ldr \irqnr,[\irqstat] - cmp \irqnr,#0 - subne \irqnr,\irqnr,#1 - - .endm - diff --git a/include/asm-arm/arch-epxa10db/ether00.h b/include/asm-arm/arch-epxa10db/ether00.h deleted file mode 100644 index b737b8aabe2f..000000000000 --- a/include/asm-arm/arch-epxa10db/ether00.h +++ /dev/null @@ -1,482 +0,0 @@ -#ifndef __ETHER00_H -#define __ETHER00_H - - - -/* - * Register definitions for the Ethernet MAC - */ - -/* - * Copyright (c) Altera Corporation 2000. - * All rights reserved. - */ - -/* -* Structures for the DMA controller -*/ -typedef struct fda_desc - { - struct fda_desc * FDNext; - long FDSystem; - long FDStat; - short FDLength; - short FDCtl; - }FDA_DESC; - -typedef struct buf_desc - { - char * BuffData; - short BuffLength; - char BDStat; - char BDCtl; - }BUF_DESC; - -/* -* Control masks for the DMA controller -*/ -#define FDCTL_BDCOUNT_MSK (0x1F) -#define FDCTL_BDCOUNT_OFST (0) -#define FDCTL_FRMOPT_MSK (0x7C00) -#define FDCTL_FRMOPT_OFST (10) -#define FDCTL_COWNSFD_MSK (0x8000) -#define FDCTL_COWNSFD_OFST (15) - -#define BDCTL_RXBDSEQN_MSK (0x7F) -#define BDCTL_RXBDSEQN_OFST (0) -#define BDCTL_COWNSBD_MSK (0x80) -#define BDCTL_COWNSBD_OFST (7) - -#define FDNEXT_EOL_MSK (0x1) -#define FDNEXT_EOL_OFST (0) -#define FDNEXT_EOL_POINTER_MSK (0xFFFFFFF0) -#define FDNEXT_EOL_POINTER_OFST (4) - -#define ETHER_ARC_SIZE (21) - -/* -* Register definitions and masks -*/ -#define ETHER_DMA_CTL(base) (ETHER00_TYPE (base + 0x100)) -#define ETHER_DMA_CTL_DMBURST_OFST (2) -#define ETHER_DMA_CTL_DMBURST_MSK (0x1FC) -#define ETHER_DMA_CTL_POWRMGMNT_OFST (11) -#define ETHER_DMA_CTL_POWRMGMNT_MSK (0x1000) -#define ETHER_DMA_CTL_TXBIGE_OFST (14) -#define ETHER_DMA_CTL_TXBIGE_MSK (0x4000) -#define ETHER_DMA_CTL_RXBIGE_OFST (15) -#define ETHER_DMA_CTL_RXBIGE_MSK (0x8000) -#define ETHER_DMA_CTL_TXWAKEUP_OFST (16) -#define ETHER_DMA_CTL_TXWAKEUP_MSK (0x10000) -#define ETHER_DMA_CTL_SWINTREQ_OFST (17) -#define ETHER_DMA_CTL_SWINTREQ_MSK (0x20000) -#define ETHER_DMA_CTL_INTMASK_OFST (18) -#define ETHER_DMA_CTL_INTMASK_MSK (0x40000) -#define ETHER_DMA_CTL_M66ENSTAT_OFST (19) -#define ETHER_DMA_CTL_M66ENSTAT_MSK (0x80000) -#define ETHER_DMA_CTL_RMTXINIT_OFST (20) -#define ETHER_DMA_CTL_RMTXINIT_MSK (0x100000) -#define ETHER_DMA_CTL_RMRXINIT_OFST (21) -#define ETHER_DMA_CTL_RMRXINIT_MSK (0x200000) -#define ETHER_DMA_CTL_RXALIGN_OFST (22) -#define ETHER_DMA_CTL_RXALIGN_MSK (0xC00000) -#define ETHER_DMA_CTL_RMSWRQ_OFST (24) -#define ETHER_DMA_CTL_RMSWRQ_MSK (0x1000000) -#define ETHER_DMA_CTL_RMEMBANK_OFST (25) -#define ETHER_DMA_CTL_RMEMBANK_MSK (0x2000000) - -#define ETHER_TXFRMPTR(base) (ETHER00_TYPE (base + 0x104)) - -#define ETHER_TXTHRSH(base) (ETHER00_TYPE (base + 0x308)) - -#define ETHER_TXPOLLCTR(base) (ETHER00_TYPE (base + 0x30c)) - -#define ETHER_BLFRMPTR(base) (ETHER00_TYPE (base + 0x110)) -#define ETHER_BLFFRMPTR_EOL_OFST (0) -#define ETHER_BLFFRMPTR_EOL_MSK (0x1) -#define ETHER_BLFFRMPTR_ADDRESS_OFST (4) -#define ETHER_BLFFRMPTR_ADDRESS_MSK (0xFFFFFFF0) - -#define ETHER_RXFRAGSIZE(base) (ETHER00_TYPE (base + 0x114)) -#define ETHER_RXFRAGSIZE_MINFRAG_OFST (2) -#define ETHER_RXFRAGSIZE_MINFRAG_MSK (0xFFC) -#define ETHER_RXFRAGSIZE_ENPACK_OFST (15) -#define ETHER_RXFRAGSIZE_ENPACK_MSK (0x8000) - -#define ETHER_INT_EN(base) (ETHER00_TYPE (base + 0x118)) -#define ETHER_INT_EN_FDAEXEN_OFST (0) -#define ETHER_INT_EN_FDAEXEN_MSK (0x1) -#define ETHER_INT_EN_BLEXEN_OFST (1) -#define ETHER_INT_EN_BLEXN_MSK (0x2) -#define ETHER_INT_EN_STARGABTEN_OFST (2) -#define ETHER_INT_EN_STARGABTEN_MSK (0x4) -#define ETHER_INT_EN_RTARGABTEN_OFST (3) -#define ETHER_INT_EN_RTARGABTEN_MSK (0x8) -#define ETHER_INT_EN_RMASABTEN_OFST (4) -#define ETHER_INT_EN_RMASABTEN_MSK (0x10) -#define ETHER_INT_EN_SSYSERREN_OFST (5) -#define ETHER_INT_EN_SSYSERREN_MSK (0x20) -#define ETHER_INT_EN_DPARERREN_OFST (6) -#define ETHER_INT_EN_DPARERREN_MSK (0x40) -#define ETHER_INT_EN_EARNOTEN_OFST (7) -#define ETHER_INT_EN_EARNOTEN_MSK (0x80) -#define ETHER_INT_EN_DPARDEN_OFST (8) -#define ETHER_INT_EN_DPARDEN_MSK (0x100) -#define ETHER_INT_EN_DMPARERREN_OFST (9) -#define ETHER_INT_EN_DMPARERREN_MSK (0x200) -#define ETHER_INT_EN_TXCTLCMPEN_OFST (10) -#define ETHER_INT_EN_TXCTLCMPEN_MSK (0x400) -#define ETHER_INT_EN_NRABTEN_OFST (11) -#define ETHER_INT_EN_NRABTEN_MSK (0x800) - -#define ETHER_FDA_BAS(base) (ETHER00_TYPE (base + 0x11C)) -#define ETHER_FDA_BAS_ADDRESS_OFST (4) -#define ETHER_FDA_BAS_ADDRESS_MSK (0xFFFFFFF0) - -#define ETHER_FDA_LIM(base) (ETHER00_TYPE (base + 0x120)) -#define ETHER_FDA_LIM_COUNT_OFST (4) -#define ETHER_FDA_LIM_COUNT_MSK (0xFFF0) - -#define ETHER_INT_SRC(base) (ETHER00_TYPE (base + 0x124)) -#define ETHER_INT_SRC_INTMACTX_OFST (0) -#define ETHER_INT_SRC_INTMACTX_MSK (0x1) -#define ETHER_INT_SRC_INTMACRX_OFST (1) -#define ETHER_INT_SRC_INTMACRX_MSK (0x2) -#define ETHER_INT_SRC_INTSBUS_OFST (2) -#define ETHER_INT_SRC_INTSBUS_MSK (0x4) -#define ETHER_INT_SRC_INTFDAEX_OFST (3) -#define ETHER_INT_SRC_INTFDAEX_MSK (0x8) -#define ETHER_INT_SRC_INTBLEX_OFST (4) -#define ETHER_INT_SRC_INTBLEX_MSK (0x10) -#define ETHER_INT_SRC_SWINT_OFST (5) -#define ETHER_INT_SRC_SWINT_MSK (0x20) -#define ETHER_INT_SRC_INTEARNOT_OFST (6) -#define ETHER_INT_SRC_INTEARNOT_MSK (0x40) -#define ETHER_INT_SRC_DMPARERR_OFST (7) -#define ETHER_INT_SRC_DMPARERR_MSK (0x80) -#define ETHER_INT_SRC_INTEXBD_OFST (8) -#define ETHER_INT_SRC_INTEXBD_MSK (0x100) -#define ETHER_INT_SRC_INTTXCTLCMP_OFST (9) -#define ETHER_INT_SRC_INTTXCTLCMP_MSK (0x200) -#define ETHER_INT_SRC_INTNRABT_OFST (10) -#define ETHER_INT_SRC_INTNRABT_MSK (0x400) -#define ETHER_INT_SRC_FDAEX_OFST (11) -#define ETHER_INT_SRC_FDAEX_MSK (0x800) -#define ETHER_INT_SRC_BLEX_OFST (12) -#define ETHER_INT_SRC_BLEX_MSK (0x1000) -#define ETHER_INT_SRC_DMPARERRSTAT_OFST (13) -#define ETHER_INT_SRC_DMPARERRSTAT_MSK (0x2000) -#define ETHER_INT_SRC_NRABT_OFST (14) -#define ETHER_INT_SRC_NRABT_MSK (0x4000) -#define ETHER_INT_SRC_INTLINK_OFST (15) -#define ETHER_INT_SRC_INTLINK_MSK (0x8000) -#define ETHER_INT_SRC_INTEXDEFER_OFST (16) -#define ETHER_INT_SRC_INTEXDEFER_MSK (0x10000) -#define ETHER_INT_SRC_INTRMON_OFST (17) -#define ETHER_INT_SRC_INTRMON_MSK (0x20000) -#define ETHER_INT_SRC_IRQ_MSK (0x83FF) - -#define ETHER_PAUSECNT(base) (ETHER00_TYPE (base + 0x40)) -#define ETHER_PAUSECNT_COUNT_OFST (0) -#define ETHER_PAUSECNT_COUNT_MSK (0xFFFF) - -#define ETHER_REMPAUCNT(base) (ETHER00_TYPE (base + 0x44)) -#define ETHER_REMPAUCNT_COUNT_OFST (0) -#define ETHER_REMPAUCNT_COUNT_MSK (0xFFFF) - -#define ETHER_TXCONFRMSTAT(base) (ETHER00_TYPE (base + 0x348)) -#define ETHER_TXCONFRMSTAT_TS_STAT_VALUE_OFST (0) -#define ETHER_TXCONFRMSTAT_TS_STAT_VALUE_MSK (0x3FFFFF) - -#define ETHER_MAC_CTL(base) (ETHER00_TYPE (base + 0)) -#define ETHER_MAC_CTL_HALTREQ_OFST (0) -#define ETHER_MAC_CTL_HALTREQ_MSK (0x1) -#define ETHER_MAC_CTL_HALTIMM_OFST (1) -#define ETHER_MAC_CTL_HALTIMM_MSK (0x2) -#define ETHER_MAC_CTL_RESET_OFST (2) -#define ETHER_MAC_CTL_RESET_MSK (0x4) -#define ETHER_MAC_CTL_FULLDUP_OFST (3) -#define ETHER_MAC_CTL_FULLDUP_MSK (0x8) -#define ETHER_MAC_CTL_MACLOOP_OFST (4) -#define ETHER_MAC_CTL_MACLOOP_MSK (0x10) -#define ETHER_MAC_CTL_CONN_OFST (5) -#define ETHER_MAC_CTL_CONN_MSK (0x60) -#define ETHER_MAC_CTL_LOOP10_OFST (7) -#define ETHER_MAC_CTL_LOOP10_MSK (0x80) -#define ETHER_MAC_CTL_LNKCHG_OFST (8) -#define ETHER_MAC_CTL_LNKCHG_MSK (0x100) -#define ETHER_MAC_CTL_MISSROLL_OFST (10) -#define ETHER_MAC_CTL_MISSROLL_MSK (0x400) -#define ETHER_MAC_CTL_ENMISSROLL_OFST (13) -#define ETHER_MAC_CTL_ENMISSROLL_MSK (0x2000) -#define ETHER_MAC_CTL_LINK10_OFST (15) -#define ETHER_MAC_CTL_LINK10_MSK (0x8000) - -#define ETHER_ARC_CTL(base) (ETHER00_TYPE (base + 0x4)) -#define ETHER_ARC_CTL_STATIONACC_OFST (0) -#define ETHER_ARC_CTL_STATIONACC_MSK (0x1) -#define ETHER_ARC_CTL_GROUPACC_OFST (1) -#define ETHER_ARC_CTL_GROUPACC_MSK (0x2) -#define ETHER_ARC_CTL_BROADACC_OFST (2) -#define ETHER_ARC_CTL_BROADACC_MSK (0x4) -#define ETHER_ARC_CTL_NEGARC_OFST (3) -#define ETHER_ARC_CTL_NEGARC_MSK (0x8) -#define ETHER_ARC_CTL_COMPEN_OFST (4) -#define ETHER_ARC_CTL_COMPEN_MSK (0x10) - -#define ETHER_TX_CTL(base) (ETHER00_TYPE (base + 0x8)) -#define ETHER_TX_CTL_TXEN_OFST (0) -#define ETHER_TX_CTL_TXEN_MSK (0x1) -#define ETHER_TX_CTL_TXHALT_OFST (1) -#define ETHER_TX_CTL_TXHALT_MSK (0x2) -#define ETHER_TX_CTL_NOPAD_OFST (2) -#define ETHER_TX_CTL_NOPAD_MSK (0x4) -#define ETHER_TX_CTL_NOCRC_OFST (3) -#define ETHER_TX_CTL_NOCRC_MSK (0x8) -#define ETHER_TX_CTL_FBACK_OFST (4) -#define ETHER_TX_CTL_FBACK_MSK (0x10) -#define ETHER_TX_CTL_NOEXDEF_OFST (5) -#define ETHER_TX_CTL_NOEXDEF_MSK (0x20) -#define ETHER_TX_CTL_SDPAUSE_OFST (6) -#define ETHER_TX_CTL_SDPAUSE_MSK (0x40) -#define ETHER_TX_CTL_MII10_OFST (7) -#define ETHER_TX_CTL_MII10_MSK (0x80) -#define ETHER_TX_CTL_ENUNDER_OFST (8) -#define ETHER_TX_CTL_ENUNDER_MSK (0x100) -#define ETHER_TX_CTL_ENEXDEFER_OFST (9) -#define ETHER_TX_CTL_ENEXDEFER_MSK (0x200) -#define ETHER_TX_CTL_ENLCARR_OFST (10) -#define ETHER_TX_CTL_ENLCARR_MSK (0x400) -#define ETHER_TX_CTL_ENEXCOLL_OFST (11) -#define ETHER_TX_CTL_ENEXCOLL_MSK (0x800) -#define ETHER_TX_CTL_ENLATECOLL_OFST (12) -#define ETHER_TX_CTL_ENLATECOLL_MSK (0x1000) -#define ETHER_TX_CTL_ENTXPAR_OFST (13) -#define ETHER_TX_CTL_ENTXPAR_MSK (0x2000) -#define ETHER_TX_CTL_ENCOMP_OFST (14) -#define ETHER_TX_CTL_ENCOMP_MSK (0x4000) - -#define ETHER_TX_STAT(base) (ETHER00_TYPE (base + 0xc)) -#define ETHER_TX_STAT_TXCOLL_OFST (0) -#define ETHER_TX_STAT_TXCOLL_MSK (0xF) -#define ETHER_TX_STAT_EXCOLL_OFST (4) -#define ETHER_TX_STAT_EXCOLL_MSK (0x10) -#define ETHER_TX_STAT_TXDEFER_OFST (5) -#define ETHER_TX_STAT_TXDEFER_MSK (0x20) -#define ETHER_TX_STAT_PAUSED_OFST (6) -#define ETHER_TX_STAT_PAUSED_MSK (0x40) -#define ETHER_TX_STAT_INTTX_OFST (7) -#define ETHER_TX_STAT_INTTX_MSK (0x80) -#define ETHER_TX_STAT_UNDER_OFST (8) -#define ETHER_TX_STAT_UNDER_MSK (0x100) -#define ETHER_TX_STAT_EXDEFER_OFST (9) -#define ETHER_TX_STAT_EXDEFER_MSK (0x200) -#define ETHER_TX_STAT_LCARR_OFST (10) -#define ETHER_TX_STAT_LCARR_MSK (0x400) -#define ETHER_TX_STAT_TX10STAT_OFST (11) -#define ETHER_TX_STAT_TX10STAT_MSK (0x800) -#define ETHER_TX_STAT_LATECOLL_OFST (12) -#define ETHER_TX_STAT_LATECOLL_MSK (0x1000) -#define ETHER_TX_STAT_TXPAR_OFST (13) -#define ETHER_TX_STAT_TXPAR_MSK (0x2000) -#define ETHER_TX_STAT_COMP_OFST (14) -#define ETHER_TX_STAT_COMP_MSK (0x4000) -#define ETHER_TX_STAT_TXHALTED_OFST (15) -#define ETHER_TX_STAT_TXHALTED_MSK (0x8000) -#define ETHER_TX_STAT_SQERR_OFST (16) -#define ETHER_TX_STAT_SQERR_MSK (0x10000) -#define ETHER_TX_STAT_TXMCAST_OFST (17) -#define ETHER_TX_STAT_TXMCAST_MSK (0x20000) -#define ETHER_TX_STAT_TXBCAST_OFST (18) -#define ETHER_TX_STAT_TXBCAST_MSK (0x40000) -#define ETHER_TX_STAT_VLAN_OFST (19) -#define ETHER_TX_STAT_VLAN_MSK (0x80000) -#define ETHER_TX_STAT_MACC_OFST (20) -#define ETHER_TX_STAT_MACC_MSK (0x100000) -#define ETHER_TX_STAT_TXPAUSE_OFST (21) -#define ETHER_TX_STAT_TXPAUSE_MSK (0x200000) - -#define ETHER_RX_CTL(base) (ETHER00_TYPE (base + 0x10)) -#define ETHER_RX_CTL_RXEN_OFST (0) -#define ETHER_RX_CTL_RXEN_MSK (0x1) -#define ETHER_RX_CTL_RXHALT_OFST (1) -#define ETHER_RX_CTL_RXHALT_MSK (0x2) -#define ETHER_RX_CTL_LONGEN_OFST (2) -#define ETHER_RX_CTL_LONGEN_MSK (0x4) -#define ETHER_RX_CTL_SHORTEN_OFST (3) -#define ETHER_RX_CTL_SHORTEN_MSK (0x8) -#define ETHER_RX_CTL_STRIPCRC_OFST (4) -#define ETHER_RX_CTL_STRIPCRC_MSK (0x10) -#define ETHER_RX_CTL_PASSCTL_OFST (5) -#define ETHER_RX_CTL_PASSCTL_MSK (0x20) -#define ETHER_RX_CTL_IGNORECRC_OFST (6) -#define ETHER_RX_CTL_IGNORECRC_MSK (0x40) -#define ETHER_RX_CTL_ENALIGN_OFST (8) -#define ETHER_RX_CTL_ENALIGN_MSK (0x100) -#define ETHER_RX_CTL_ENCRCERR_OFST (9) -#define ETHER_RX_CTL_ENCRCERR_MSK (0x200) -#define ETHER_RX_CTL_ENOVER_OFST (10) -#define ETHER_RX_CTL_ENOVER_MSK (0x400) -#define ETHER_RX_CTL_ENLONGERR_OFST (11) -#define ETHER_RX_CTL_ENLONGERR_MSK (0x800) -#define ETHER_RX_CTL_ENRXPAR_OFST (13) -#define ETHER_RX_CTL_ENRXPAR_MSK (0x2000) -#define ETHER_RX_CTL_ENGOOD_OFST (14) -#define ETHER_RX_CTL_ENGOOD_MSK (0x4000) - -#define ETHER_RX_STAT(base) (ETHER00_TYPE (base + 0x14)) -#define ETHER_RX_STAT_LENERR_OFST (4) -#define ETHER_RX_STAT_LENERR_MSK (0x10) -#define ETHER_RX_STAT_CTLRECD_OFST (5) -#define ETHER_RX_STAT_CTLRECD_MSK (0x20) -#define ETHER_RX_STAT_INTRX_OFST (6) -#define ETHER_RX_STAT_INTRX_MSK (0x40) -#define ETHER_RX_STAT_RX10STAT_OFST (7) -#define ETHER_RX_STAT_RX10STAT_MSK (0x80) -#define ETHER_RX_STAT_ALIGNERR_OFST (8) -#define ETHER_RX_STAT_ALIGNERR_MSK (0x100) -#define ETHER_RX_STAT_CRCERR_OFST (9) -#define ETHER_RX_STAT_CRCERR_MSK (0x200) -#define ETHER_RX_STAT_OVERFLOW_OFST (10) -#define ETHER_RX_STAT_OVERFLOW_MSK (0x400) -#define ETHER_RX_STAT_LONGERR_OFST (11) -#define ETHER_RX_STAT_LONGERR_MSK (0x800) -#define ETHER_RX_STAT_RXPAR_OFST (13) -#define ETHER_RX_STAT_RXPAR_MSK (0x2000) -#define ETHER_RX_STAT_GOOD_OFST (14) -#define ETHER_RX_STAT_GOOD_MSK (0x4000) -#define ETHER_RX_STAT_RXHALTED_OFST (15) -#define ETHER_RX_STAT_RXHALTED_MSK (0x8000) -#define ETHER_RX_STAT_RXMCAST_OFST (17) -#define ETHER_RX_STAT_RXMCAST_MSK (0x10000) -#define ETHER_RX_STAT_RXBCAST_OFST (18) -#define ETHER_RX_STAT_RXBCAST_MSK (0x20000) -#define ETHER_RX_STAT_RXVLAN_OFST (19) -#define ETHER_RX_STAT_RXVLAN_MSK (0x40000) -#define ETHER_RX_STAT_RXPAUSE_OFST (20) -#define ETHER_RX_STAT_RXPAUSE_MSK (0x80000) -#define ETHER_RX_STAT_ARCSTATUS_OFST (21) -#define ETHER_RX_STAT_ARCSTATUS_MSK (0xF00000) -#define ETHER_RX_STAT_ARCENT_OFST (25) -#define ETHER_RX_STAT_ARCENT_MSK (0x1F000000) - -#define ETHER_MD_DATA(base) (ETHER00_TYPE (base + 0x18)) - -#define ETHER_MD_CA(base) (ETHER00_TYPE (base + 0x1c)) -#define ETHER_MD_CA_ADDR_OFST (0) -#define ETHER_MD_CA_ADDR_MSK (0x1F) -#define ETHER_MD_CA_PHY_OFST (5) -#define ETHER_MD_CA_PHY_MSK (0x3E0) -#define ETHER_MD_CA_WR_OFST (10) -#define ETHER_MD_CA_WR_MSK (0x400) -#define ETHER_MD_CA_BUSY_OFST (11) -#define ETHER_MD_CA_BUSY_MSK (0x800) -#define ETHER_MD_CA_PRESUPP_OFST (12) -#define ETHER_MD_CA_PRESUPP_MSK (0x1000) - -#define ETHER_ARC_ADR(base) (ETHER00_TYPE (base + 0x160)) -#define ETHER_ARC_ADR_ARC_LOC_OFST (2) -#define ETHER_ARC_ADR_ARC_LOC_MSK (0xFFC) - -#define ETHER_ARC_DATA(base) (ETHER00_TYPE (base + 0x364)) - -#define ETHER_ARC_ENA(base) (ETHER00_TYPE (base + 0x28)) -#define ETHER_ARC_ENA_MSK (0x1FFFFF) - -#define ETHER_PROM_CTL(base) (ETHER00_TYPE (base + 0x2c)) -#define ETHER_PROM_CTL_PROM_ADDR_OFST (0) -#define ETHER_PROM_CTL_PROM_ADDR_MSK (0x3F) -#define ETHER_PROM_CTL_OPCODE_OFST (13) -#define ETHER_PROM_CTL_OPCODE_MSK (0x6000) -#define ETHER_PROM_CTL_OPCODE_READ_MSK (0x4000) -#define ETHER_PROM_CTL_OPCODE_WRITE_MSK (0x2000) -#define ETHER_PROM_CTL_OPCODE_ERASE_MSK (0x6000) -#define ETHER_PROM_CTL_ENABLE_MSK (0x0030) -#define ETHER_PROM_CTL_DISABLE_MSK (0x0000) -#define ETHER_PROM_CTL_BUSY_OFST (15) -#define ETHER_PROM_CTL_BUSY_MSK (0x8000) - -#define ETHER_PROM_DATA(base) (ETHER00_TYPE (base + 0x30)) - -#define ETHER_MISS_CNT(base) (ETHER00_TYPE (base + 0x3c)) -#define ETHER_MISS_CNT_COUNT_OFST (0) -#define ETHER_MISS_CNT_COUNT_MSK (0xFFFF) - -#define ETHER_CNTDATA(base) (ETHER00_TYPE (base + 0x80)) - -#define ETHER_CNTACC(base) (ETHER00_TYPE (base + 0x84)) -#define ETHER_CNTACC_ADDR_OFST (0) -#define ETHER_CNTACC_ADDR_MSK (0xFF) -#define ETHER_CNTACC_WRRDN_OFST (8) -#define ETHER_CNTACC_WRRDN_MSK (0x100) -#define ETHER_CNTACC_CLEAR_OFST (9) -#define ETHER_CNTACC_CLEAR_MSK (0x200) - -#define ETHER_TXRMINTEN(base) (ETHER00_TYPE (base + 0x88)) -#define ETHER_TXRMINTEN_MSK (0x3FFFFFFF) - -#define ETHER_RXRMINTEN(base) (ETHER00_TYPE (base + 0x8C)) -#define ETHER_RXRMINTEN_MSK (0xFFFFFF) - -/* -* RMON Registers -*/ -#define RMON_COLLISION0 0x0 -#define RMON_COLLISION1 0x1 -#define RMON_COLLISION2 0x2 -#define RMON_COLLISION3 0x3 -#define RMON_COLLISION4 0x4 -#define RMON_COLLISION5 0x5 -#define RMON_COLLISION6 0x6 -#define RMON_COLLISION7 0x7 -#define RMON_COLLISION8 0x8 -#define RMON_COLLISION9 0x9 -#define RMON_COLLISION10 0xa -#define RMON_COLLISION11 0xb -#define RMON_COLLISION12 0xc -#define RMON_COLLISION13 0xd -#define RMON_COLLISION14 0xe -#define RMON_COLLISION15 0xf -#define RMON_COLLISION16 0x10 -#define RMON_FRAMES_WITH_DEFERRED_XMISSIONS 0x11 -#define RMON_LATE_COLLISIONS 0x12 -#define RMON_FRAMES_LOST_DUE_TO_MAC_XMIT 0x13 -#define RMON_CARRIER_SENSE_ERRORS 0x14 -#define RMON_FRAMES_WITH_EXCESSIVE_DEFERAL 0x15 -#define RMON_UNICAST_FRAMES_TRANSMITTED_OK 0x16 -#define RMON_MULTICAST_FRAMES_XMITTED_OK 0x17 -#define RMON_BROADCAST_FRAMES_XMITTED_OK 0x18 -#define RMON_SQE_TEST_ERRORS 0x19 -#define RMON_PAUSE_MACCTRL_FRAMES_XMITTED 0x1A -#define RMON_MACCTRL_FRAMES_XMITTED 0x1B -#define RMON_VLAN_FRAMES_XMITTED 0x1C -#define RMON_OCTETS_XMITTED_OK 0x1D -#define RMON_OCTETS_XMITTED_OK_HI 0x1E - -#define RMON_RX_PACKET_SIZES0 0x40 -#define RMON_RX_PACKET_SIZES1 0x41 -#define RMON_RX_PACKET_SIZES2 0x42 -#define RMON_RX_PACKET_SIZES3 0x43 -#define RMON_RX_PACKET_SIZES4 0x44 -#define RMON_RX_PACKET_SIZES5 0x45 -#define RMON_RX_PACKET_SIZES6 0x46 -#define RMON_RX_PACKET_SIZES7 0x47 -#define RMON_FRAME_CHECK_SEQUENCE_ERRORS 0x48 -#define RMON_ALIGNMENT_ERRORS 0x49 -#define RMON_FRAGMENTS 0x4A -#define RMON_JABBERS 0x4B -#define RMON_FRAMES_LOST_TO_INTMACRCVERR 0x4C -#define RMON_UNICAST_FRAMES_RCVD_OK 0x4D -#define RMON_MULTICAST_FRAMES_RCVD_OK 0x4E -#define RMON_BROADCAST_FRAMES_RCVD_OK 0x4F -#define RMON_IN_RANGE_LENGTH_ERRORS 0x50 -#define RMON_OUT_OF_RANGE_LENGTH_ERRORS 0x51 -#define RMON_VLAN_FRAMES_RCVD 0x52 -#define RMON_PAUSE_MAC_CTRL_FRAMES_RCVD 0x53 -#define RMON_MAC_CTRL_FRAMES_RCVD 0x54 -#define RMON_OCTETS_RCVD_OK 0x55 -#define RMON_OCTETS_RCVD_OK_HI 0x56 -#define RMON_OCTETS_RCVD_OTHER 0x57 -#define RMON_OCTETS_RCVD_OTHER_HI 0x58 - -#endif /* __ETHER00_H */ diff --git a/include/asm-arm/arch-epxa10db/excalibur.h b/include/asm-arm/arch-epxa10db/excalibur.h deleted file mode 100644 index 5c91dd6d7822..000000000000 --- a/include/asm-arm/arch-epxa10db/excalibur.h +++ /dev/null @@ -1,91 +0,0 @@ -/* megafunction wizard: %ARM-Based Excalibur% - GENERATION: STANDARD - VERSION: WM1.0 - MODULE: ARM-Based Excalibur - PROJECT: excalibur - ============================================================ - File Name: v:\embedded\linux\bootldr\excalibur.h - Megafunction Name(s): ARM-Based Excalibur - ============================================================ - - ************************************************************ - THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! - ************************************************************/ - -#ifndef EXCALIBUR_H_INCLUDED -#define EXCALIBUR_H_INCLUDED - -#define EXC_DEFINE_PROCESSOR_LITTLE_ENDIAN -#define EXC_DEFINE_BOOT_FROM_FLASH - -#define EXC_INPUT_CLK_FREQUENCY (50000000) -#define EXC_AHB1_CLK_FREQUENCY (150000000) -#define EXC_AHB2_CLK_FREQUENCY (75000000) -#define EXC_SDRAM_CLK_FREQUENCY (75000000) - -/* Registers Block */ -#define EXC_REGISTERS_BASE (0x7fffc000) -#define EXC_MODE_CTRL00_BASE (EXC_REGISTERS_BASE + 0x000) -#define EXC_IO_CTRL00_BASE (EXC_REGISTERS_BASE + 0x040) -#define EXC_MMAP00_BASE (EXC_REGISTERS_BASE + 0x080) -#define EXC_PLD_CONFIG00_BASE (EXC_REGISTERS_BASE + 0x140) -#define EXC_TIMER00_BASE (EXC_REGISTERS_BASE + 0x200) -#define EXC_INT_CTRL00_BASE (EXC_REGISTERS_BASE + 0xc00) -#define EXC_CLOCK_CTRL00_BASE (EXC_REGISTERS_BASE + 0x300) -#define EXC_WATCHDOG00_BASE (EXC_REGISTERS_BASE + 0xa00) -#define EXC_UART00_BASE (EXC_REGISTERS_BASE + 0x280) -#define EXC_EBI00_BASE (EXC_REGISTERS_BASE + 0x380) -#define EXC_SDRAM00_BASE (EXC_REGISTERS_BASE + 0x400) -#define EXC_AHB12_BRIDGE_CTRL00_BASE (EXC_REGISTERS_BASE + 0x800) -#define EXC_PLD_STRIPE_BRIDGE_CTRL00_BASE (EXC_REGISTERS_BASE + 0x100) -#define EXC_STRIPE_PLD_BRIDGE_CTRL00_BASE (EXC_REGISTERS_BASE + 0x100) - -#define EXC_REGISTERS_SIZE (0x00004000) - -/* EBI Block(s) */ -#define EXC_EBI_BLOCK0_BASE (0x40000000) -#define EXC_EBI_BLOCK0_SIZE (0x00400000) -#define EXC_EBI_BLOCK0_WIDTH (8) -#define EXC_EBI_BLOCK0_NON_CACHEABLE -#define EXC_EBI_BLOCK1_BASE (0x40400000) -#define EXC_EBI_BLOCK1_SIZE (0x00400000) -#define EXC_EBI_BLOCK1_WIDTH (16) -#define EXC_EBI_BLOCK1_NON_CACHEABLE -#define EXC_EBI_BLOCK2_BASE (0x40800000) -#define EXC_EBI_BLOCK2_SIZE (0x00400000) -#define EXC_EBI_BLOCK2_WIDTH (16) -#define EXC_EBI_BLOCK2_NON_CACHEABLE -#define EXC_EBI_BLOCK3_BASE (0x40c00000) -#define EXC_EBI_BLOCK3_SIZE (0x00400000) -#define EXC_EBI_BLOCK3_WIDTH (16) -#define EXC_EBI_BLOCK3_NON_CACHEABLE - -/* SDRAM Block(s) */ -#define EXC_SDRAM_BLOCK0_BASE (0x00000000) -#define EXC_SDRAM_BLOCK0_SIZE (0x04000000) -#define EXC_SDRAM_BLOCK0_WIDTH (32) -#define EXC_SDRAM_BLOCK1_BASE (0x04000000) -#define EXC_SDRAM_BLOCK1_SIZE (0x04000000) -#define EXC_SDRAM_BLOCK1_WIDTH (32) - -/* Single Port SRAM Block(s) */ -#define EXC_SPSRAM_BLOCK0_BASE (0x08000000) -#define EXC_SPSRAM_BLOCK0_SIZE (0x00020000) -#define EXC_SPSRAM_BLOCK1_BASE (0x08020000) -#define EXC_SPSRAM_BLOCK1_SIZE (0x00020000) - -/* PLD Block(s) */ -#define EXC_PLD_BLOCK0_BASE (0x80000000) -#define EXC_PLD_BLOCK0_SIZE (0x00004000) -#define EXC_PLD_BLOCK0_NON_CACHEABLE -#define EXC_PLD_BLOCK1_BASE (0xf000000) -#define EXC_PLD_BLOCK1_SIZE (0x00004000) -#define EXC_PLD_BLOCK1_NON_CACHEABLE -#define EXC_PLD_BLOCK2_BASE (0x80008000) -#define EXC_PLD_BLOCK2_SIZE (0x00004000) -#define EXC_PLD_BLOCK2_NON_CACHEABLE -#define EXC_PLD_BLOCK3_BASE (0x8000c000) -#define EXC_PLD_BLOCK3_SIZE (0x00004000) -#define EXC_PLD_BLOCK3_NON_CACHEABLE - -#endif diff --git a/include/asm-arm/arch-epxa10db/hardware.h b/include/asm-arm/arch-epxa10db/hardware.h deleted file mode 100644 index b992c2924a77..000000000000 --- a/include/asm-arm/arch-epxa10db/hardware.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * linux/include/asm-arm/arch-epxa10/hardware.h - * - * This file contains the hardware definitions of the Integrator. - * - * Copyright (C) 1999 ARM Limited. - * Copyright (C) 2001 Altera Corporation - * - * 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 - */ -#ifndef __ASM_ARCH_HARDWARE_H -#define __ASM_ARCH_HARDWARE_H - -#include <asm/arch/platform.h> - -/* - * Where in virtual memory the IO devices (timers, system controllers - * and so on) - */ -#define IO_BASE 0xf0000000 // VA of IO -#define IO_SIZE 0x10000000 // How much? -#define IO_START EXC_REGISTERS_BASE // PA of IO -/* macro to get at IO space when running virtually */ -#define IO_ADDRESS(x) ((x) | 0xf0000000) - -#define FLASH_VBASE 0xFE000000 -#define FLASH_SIZE 0x01000000 -#define FLASH_START EXC_EBI_BLOCK0_BASE -#define FLASH_VADDR(x) ((x)|0xFE000000) -/* - * Similar to above, but for PCI addresses (memory, IO, Config and the - * V3 chip itself). WARNING: this has to mirror definitions in platform.h - */ -#if 0 -#define PCI_MEMORY_VADDR 0xe8000000 -#define PCI_CONFIG_VADDR 0xec000000 -#define PCI_V3_VADDR 0xed000000 -#define PCI_IO_VADDR 0xee000000 - -#define PCIO_BASE PCI_IO_VADDR -#define PCIMEM_BASE PCI_MEMORY_VADDR - - -#define pcibios_assign_all_busses() 1 - -#define PCIBIOS_MIN_IO 0x6000 -#define PCIBIOS_MIN_MEM 0x00100000 -#endif - - -#endif - diff --git a/include/asm-arm/arch-epxa10db/int_ctrl00.h b/include/asm-arm/arch-epxa10db/int_ctrl00.h deleted file mode 100644 index 23ec864c40bb..000000000000 --- a/include/asm-arm/arch-epxa10db/int_ctrl00.h +++ /dev/null @@ -1,288 +0,0 @@ -/* - * - * This file contains the register definitions for the Excalibur - * Timer TIMER00. - * - * Copyright (C) 2001 Altera Corporation - * - * 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 - */ - -#ifndef __INT_CTRL00_H -#define __INT_CTRL00_H - -#define INT_MS(base_addr) (INT_CTRL00_TYPE (base_addr + 0x00 )) -#define INT_MS_FC_MSK (0x10000) -#define INT_MS_FC_OFST (16) -#define INT_MS_M1_MSK (0x8000) -#define INT_MS_M1_OFST (15) -#define INT_MS_M0_MSK (0x4000) -#define INT_MS_M0_OFST (14) -#define INT_MS_AE_MSK (0x2000) -#define INT_MS_AE_OFST (13) -#define INT_MS_PE_MSK (0x1000) -#define INT_MS_PE_OFST (12) -#define INT_MS_EE_MSK (0x0800) -#define INT_MS_EE_OFST (11) -#define INT_MS_PS_MSK (0x0400) -#define INT_MS_PS_OFST (10) -#define INT_MS_T1_MSK (0x0200) -#define INT_MS_T1_OFST (9) -#define INT_MS_T0_MSK (0x0100) -#define INT_MS_T0_OFST (8) -#define INT_MS_UA_MSK (0x0080) -#define INT_MS_UA_OFST (7) -#define INT_MS_IP_MSK (0x0040) -#define INT_MS_IP_OFST (6) -#define INT_MS_P5_MSK (0x0020) -#define INT_MS_P5_OFST (5) -#define INT_MS_P4_MSK (0x0010) -#define INT_MS_P4_OFST (4) -#define INT_MS_P3_MSK (0x0008) -#define INT_MS_P3_OFST (3) -#define INT_MS_P2_MSK (0x0004) -#define INT_MS_P2_OFST (2) -#define INT_MS_P1_MSK (0x0002) -#define INT_MS_P1_OFST (1) -#define INT_MS_P0_MSK (0x0001) -#define INT_MS_P0_OFST (0) - -#define INT_MC(base_addr) (INT_CTRL00_TYPE (base_addr + 0x04 )) -#define INT_MC_FC_MSK (0x10000) -#define INT_MC_FC_OFST (16) -#define INT_MC_M1_MSK (0x8000) -#define INT_MC_M1_OFST (15) -#define INT_MC_M0_MSK (0x4000) -#define INT_MC_M0_OFST (14) -#define INT_MC_AE_MSK (0x2000) -#define INT_MC_AE_OFST (13) -#define INT_MC_PE_MSK (0x1000) -#define INT_MC_PE_OFST (12) -#define INT_MC_EE_MSK (0x0800) -#define INT_MC_EE_OFST (11) -#define INT_MC_PS_MSK (0x0400) -#define INT_MC_PS_OFST (10) -#define INT_MC_T1_MSK (0x0200) -#define INT_MC_T1_OFST (9) -#define INT_MC_T0_MSK (0x0100) -#define INT_MC_T0_OFST (8) -#define INT_MC_UA_MSK (0x0080) -#define INT_MC_UA_OFST (7) -#define INT_MC_IP_MSK (0x0040) -#define INT_MC_IP_OFST (6) -#define INT_MC_P5_MSK (0x0020) -#define INT_MC_P5_OFST (5) -#define INT_MC_P4_MSK (0x0010) -#define INT_MC_P4_OFST (4) -#define INT_MC_P3_MSK (0x0008) -#define INT_MC_P3_OFST (3) -#define INT_MC_P2_MSK (0x0004) -#define INT_MC_P2_OFST (2) -#define INT_MC_P1_MSK (0x0002) -#define INT_MC_P1_OFST (1) -#define INT_MC_P0_MSK (0x0001) -#define INT_MC_P0_OFST (0) - -#define INT_SS(base_addr) (INT_CTRL00_TYPE (base_addr + 0x08 )) -#define INT_SS_FC_SSK (0x8000) -#define INT_SS_FC_OFST (15) -#define INT_SS_M1_SSK (0x8000) -#define INT_SS_M1_OFST (15) -#define INT_SS_M0_SSK (0x4000) -#define INT_SS_M0_OFST (14) -#define INT_SS_AE_SSK (0x2000) -#define INT_SS_AE_OFST (13) -#define INT_SS_PE_SSK (0x1000) -#define INT_SS_PE_OFST (12) -#define INT_SS_EE_SSK (0x0800) -#define INT_SS_EE_OFST (11) -#define INT_SS_PS_SSK (0x0400) -#define INT_SS_PS_OFST (10) -#define INT_SS_T1_SSK (0x0200) -#define INT_SS_T1_OFST (9) -#define INT_SS_T0_SSK (0x0100) -#define INT_SS_T0_OFST (8) -#define INT_SS_UA_SSK (0x0080) -#define INT_SS_UA_OFST (7) -#define INT_SS_IP_SSK (0x0040) -#define INT_SS_IP_OFST (6) -#define INT_SS_P5_SSK (0x0020) -#define INT_SS_P5_OFST (5) -#define INT_SS_P4_SSK (0x0010) -#define INT_SS_P4_OFST (4) -#define INT_SS_P3_SSK (0x0008) -#define INT_SS_P3_OFST (3) -#define INT_SS_P2_SSK (0x0004) -#define INT_SS_P2_OFST (2) -#define INT_SS_P1_SSK (0x0002) -#define INT_SS_P1_OFST (1) -#define INT_SS_P0_SSK (0x0001) -#define INT_SS_P0_OFST (0) - -#define INT_RS(base_addr) (INT_CTRL00_TYPE (base_addr + 0x0C )) -#define INT_RS_FC_RSK (0x10000) -#define INT_RS_FC_OFST (16) -#define INT_RS_M1_RSK (0x8000) -#define INT_RS_M1_OFST (15) -#define INT_RS_M0_RSK (0x4000) -#define INT_RS_M0_OFST (14) -#define INT_RS_AE_RSK (0x2000) -#define INT_RS_AE_OFST (13) -#define INT_RS_PE_RSK (0x1000) -#define INT_RS_PE_OFST (12) -#define INT_RS_EE_RSK (0x0800) -#define INT_RS_EE_OFST (11) -#define INT_RS_PS_RSK (0x0400) -#define INT_RS_PS_OFST (10) -#define INT_RS_T1_RSK (0x0200) -#define INT_RS_T1_OFST (9) -#define INT_RS_T0_RSK (0x0100) -#define INT_RS_T0_OFST (8) -#define INT_RS_UA_RSK (0x0080) -#define INT_RS_UA_OFST (7) -#define INT_RS_IP_RSK (0x0040) -#define INT_RS_IP_OFST (6) -#define INT_RS_P5_RSK (0x0020) -#define INT_RS_P5_OFST (5) -#define INT_RS_P4_RSK (0x0010) -#define INT_RS_P4_OFST (4) -#define INT_RS_P3_RSK (0x0008) -#define INT_RS_P3_OFST (3) -#define INT_RS_P2_RSK (0x0004) -#define INT_RS_P2_OFST (2) -#define INT_RS_P1_RSK (0x0002) -#define INT_RS_P1_OFST (1) -#define INT_RS_P0_RSK (0x0001) -#define INT_RS_P0_OFST (0) - -#define INT_ID(base_addr) (INT_CTRL00_TYPE (base_addr + 0x10 )) -#define INT_ID_ID_MSK (0x3F) -#define INT_ID_ID_OFST (0) - -#define INT_PLD_PRIORITY(base_addr) (INT_CTRL00_TYPE (base_addr + 0x14 )) -#define INT_PLD_PRIORITY_PRI_MSK (0x3F) -#define INT_PLD_PRIORITY_PRI_OFST (0) -#define INT_PLD_PRIORITY_GA_MSK (0x40) -#define INT_PLD_PRIORITY_GA_OFST (6) - -#define INT_MODE(base_addr) (INT_CTRL00_TYPE (base_addr + 0x18 )) -#define INT_MODE_MODE_MSK (0x3) -#define INT_MODE_MODE_OFST (0) - -#define INT_PRIORITY_P0(base_addr) (INT_CTRL00_TYPE (base_addr + 0x80 )) -#define INT_PRIORITY_P0_PRI_MSK (0x3F) -#define INT_PRIORITY_P0_PRI_OFST (0) -#define INT_PRIORITY_P0_FQ_MSK (0x40) -#define INT_PRIORITY_P0_FQ_OFST (6) - -#define INT_PRIORITY_P1(base_addr) (INT_CTRL00_TYPE (base_addr + 0x84 )) -#define INT_PRIORITY_P1_PRI_MSK (0x3F) -#define INT_PRIORITY_P1_PRI_OFST (0) -#define INT_PRIORITY_P1_FQ_MSK (0x40) -#define INT_PRIORITY_P1_FQ_OFST (6) - -#define INT_PRIORITY_P2(base_addr) (INT_CTRL00_TYPE (base_addr + 0x88 )) -#define INT_PRIORITY_P2_PRI_MSK (0x3F) -#define INT_PRIORITY_P2_PRI_OFST (0) -#define INT_PRIORITY_P2_FQ_MSK (0x40) -#define INT_PRIORITY_P2_FQ_OFST (6) - -#define INT_PRIORITY_P3(base_addr) (INT_CTRL00_TYPE (base_addr + 0x8C )) -#define INT_PRIORITY_P3_PRI_MSK (0x3F) -#define INT_PRIORITY_P3_PRI_OFST (0) -#define INT_PRIORITY_P3_FQ_MSK (0x40) -#define INT_PRIORITY_P3_FQ_OFST (6) - -#define INT_PRIORITY_P4(base_addr) (INT_CTRL00_TYPE (base_addr + 0x90 )) -#define INT_PRIORITY_P4_PRI_MSK (0x3F) -#define INT_PRIORITY_P4_PRI_OFST (0) -#define INT_PRIORITY_P4_FQ_MSK (0x40) -#define INT_PRIORITY_P4_FQ_OFST (6) - -#define INT_PRIORITY_P5(base_addr) (INT_CTRL00_TYPE (base_addr + 0x94 )) -#define INT_PRIORITY_P5_PRI_MSK (0x3F) -#define INT_PRIORITY_P5_PRI_OFST (0) -#define INT_PRIORITY_P5_FQ_MSK (0x40) -#define INT_PRIORITY_P5_FQ_OFST (6) - -#define INT_PRIORITY_IP(base_addr) (INT_CTRL00_TYPE (base_addr + 0x94 )) -#define INT_PRIORITY_IP_PRI_MSK (0x3F) -#define INT_PRIORITY_IP_PRI_OFST (0) -#define INT_PRIORITY_IP_FQ_MSK (0x40) -#define INT_PRIORITY_IP_FQ_OFST (6) - -#define INT_PRIORITY_UA(base_addr) (INT_CTRL00_TYPE (base_addr + 0x9C )) -#define INT_PRIORITY_UA_PRI_MSK (0x3F) -#define INT_PRIORITY_UA_PRI_OFST (0) -#define INT_PRIORITY_UA_FQ_MSK (0x40) -#define INT_PRIORITY_UA_FQ_OFST (6) - -#define INT_PRIORITY_T0(base_addr) (INT_CTRL00_TYPE (base_addr + 0xA0 )) -#define INT_PRIORITY_T0_PRI_MSK (0x3F) -#define INT_PRIORITY_T0_PRI_OFST (0) -#define INT_PRIORITY_T0_FQ_MSK (0x40) -#define INT_PRIORITY_T0_FQ_OFST (6) - -#define INT_PRIORITY_T1(base_addr) (INT_CTRL00_TYPE (base_addr + 0xA4 )) -#define INT_PRIORITY_T1_PRI_MSK (0x3F) -#define INT_PRIORITY_T1_PRI_OFST (0) -#define INT_PRIORITY_T1_FQ_MSK (0x40) -#define INT_PRIORITY_T1_FQ_OFST (6) - -#define INT_PRIORITY_PS(base_addr) (INT_CTRL00_TYPE (base_addr + 0xA8 )) -#define INT_PRIORITY_PS_PRI_MSK (0x3F) -#define INT_PRIORITY_PS_PRI_OFST (0) -#define INT_PRIORITY_PS_FQ_MSK (0x40) -#define INT_PRIORITY_PS_FQ_OFST (6) - -#define INT_PRIORITY_EE(base_addr) (INT_CTRL00_TYPE (base_addr + 0xAC )) -#define INT_PRIORITY_EE_PRI_MSK (0x3F) -#define INT_PRIORITY_EE_PRI_OFST (0) -#define INT_PRIORITY_EE_FQ_MSK (0x40) -#define INT_PRIORITY_EE_FQ_OFST (6) - -#define INT_PRIORITY_PE(base_addr) (INT_CTRL00_TYPE (base_addr + 0xB0 )) -#define INT_PRIORITY_PE_PRI_MSK (0x3F) -#define INT_PRIORITY_PE_PRI_OFST (0) -#define INT_PRIORITY_PE_FQ_MSK (0x40) -#define INT_PRIORITY_PE_FQ_OFST (6) - -#define INT_PRIORITY_AE(base_addr) (INT_CTRL00_TYPE (base_addr + 0xB4 )) -#define INT_PRIORITY_AE_PRI_MSK (0x3F) -#define INT_PRIORITY_AE_PRI_OFST (0) -#define INT_PRIORITY_AE_FQ_MSK (0x40) -#define INT_PRIORITY_AE_FQ_OFST (6) - -#define INT_PRIORITY_M0(base_addr) (INT_CTRL00_TYPE (base_addr + 0xB8 )) -#define INT_PRIORITY_M0_PRI_MSK (0x3F) -#define INT_PRIORITY_M0_PRI_OFST (0) -#define INT_PRIORITY_M0_FQ_MSK (0x40) -#define INT_PRIORITY_M0_FQ_OFST (6) - -#define INT_PRIORITY_M1(base_addr) (INT_CTRL00_TYPE (base_addr + 0xBC )) -#define INT_PRIORITY_M1_PRI_MSK (0x3F) -#define INT_PRIORITY_M1_PRI_OFST (0) -#define INT_PRIORITY_M1_FQ_MSK (0x40) -#define INT_PRIORITY_M1_FQ_OFST (6) - -#define INT_PRIORITY_FC(base_addr) (INT_CTRL00_TYPE (base_addr + 0xC0 )) -#define INT_PRIORITY_FC_PRI_MSK (0x3F) -#define INT_PRIORITY_FC_PRI_OFST (0) -#define INT_PRIORITY_FC_FQ_MSK (0x40) -#define INT_PRIORITY_FC_FQ_OFST (6) - -#endif /* __INT_CTRL00_H */ - - diff --git a/include/asm-arm/arch-epxa10db/irqs.h b/include/asm-arm/arch-epxa10db/irqs.h deleted file mode 100644 index c3758a3b5d9d..000000000000 --- a/include/asm-arm/arch-epxa10db/irqs.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * linux/include/asm-arm/arch-camelot/irqs.h - * - * Copyright (C) 2001 Altera Corporation - * - * 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 - */ - -/* Use the Excalibur chip definitions */ -#define INT_CTRL00_TYPE -#include "asm/arch/int_ctrl00.h" - - -#define IRQ_PLD0 INT_MS_P0_OFST -#define IRQ_PLD1 INT_MS_P1_OFST -#define IRQ_PLD2 INT_MS_P2_OFST -#define IRQ_PLD3 INT_MS_P3_OFST -#define IRQ_PLD4 INT_MS_P4_OFST -#define IRQ_PLD5 INT_MS_P5_OFST -#define IRQ_EXT INT_MS_IP_OFST -#define IRQ_UART INT_MS_UA_OFST -#define IRQ_TIMER0 INT_MS_T0_OFST -#define IRQ_TIMER1 INT_MS_T1_OFST -#define IRQ_PLL INT_MS_PLL_OFST -#define IRQ_EBI INT_MS_EBI_OFST -#define IRQ_STRIPE_BRIDGE INT_MS_PLL_OFST -#define IRQ_AHB_BRIDGE INT_MS_PLL_OFST -#define IRQ_COMMRX INT_MS_CR_OFST -#define IRQ_COMMTX INT_MS_CT_OFST -#define IRQ_FAST_COMM INT_MS_FC_OFST - -#define NR_IRQS (INT_MS_FC_OFST + 1) - diff --git a/include/asm-arm/arch-epxa10db/mode_ctrl00.h b/include/asm-arm/arch-epxa10db/mode_ctrl00.h deleted file mode 100644 index d8a7efa12e19..000000000000 --- a/include/asm-arm/arch-epxa10db/mode_ctrl00.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef __MODE_CTRL00_H -#define __MODE_CTRL00_H - -/* - * Register definitions for the reset and mode control - */ - -/* - * Copyright (C) 2001 Altera Corporation - * - * 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 - */ - - - -#define BOOT_CR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR )) -#define BOOT_CR_BF_MSK (0x1) -#define BOOT_CR_BF_OFST (0) -#define BOOT_CR_HM_MSK (0x2) -#define BOOT_CR_HM_OFST (1) -#define BOOT_CR_RE_MSK (0x4) -#define BOOT_CR_RE_OFST (2) - -#define RESET_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x4 )) -#define RESET_SR_WR_MSK (0x1) -#define RESET_SR_WR_OFST (0) -#define RESET_SR_CR_MSK (0x2) -#define RESET_SR_CR_OFST (1) -#define RESET_SR_JT_MSK (0x4) -#define RESET_SR_JT_OFST (2) -#define RESET_SR_ER_MSK (0x8) -#define RESET_SR_ER_OFST (3) - -#define ID_CODE(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x08 )) - -#define SRAM0_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x20 )) -#define SRAM0_SR_SIZE_MSK (0xFFFFF000) -#define SRAM0_SR_SIZE_OFST (12) - -#define SRAM1_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x24 )) -#define SRAM1_SR_SIZE_MSK (0xFFFFF000) -#define SRAM1_SR_SIZE_OFST (12) - -#define DPSRAM0_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x30 )) - -#define DPSRAM0_SR_MODE_MSK (0xF) -#define DPSRAM0_SR_MODE_OFST (0) -#define DPSRAM0_SR_GLBL_MSK (0x30) -#define DPSRAM0_SR_SIZE_MSK (0xFFFFF000) -#define DPSRAM0_SR_SIZE_OFST (12) - -#define DPSRAM0_LCR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x34 )) -#define DPSRAM0_LCR_LCKADDR_MSK (0x1FFE0) -#define DPSRAM0_LCR_LCKADDR_OFST (4) - -#define DPSRAM1_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x38 )) -#define DPSRAM1_SR_MODE_MSK (0xF) -#define DPSRAM1_SR_MODE_OFST (0) -#define DPSRAM1_SR_GLBL_MSK (0x30) -#define DPSRAM1_SR_GLBL_OFST (4) -#define DPSRAM1_SR_SIZE_MSK (0xFFFFF000) -#define DPSRAM1_SR_SIZE_OFST (12) - -#define DPSRAM1_LCR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x3C )) -#define DPSRAM1_LCR_LCKADDR_MSK (0x1FFE0) -#define DPSRAM1_LCR_LCKADDR_OFST (4) - -#endif /* __MODE_CTRL00_H */ diff --git a/include/asm-arm/arch-epxa10db/platform.h b/include/asm-arm/arch-epxa10db/platform.h deleted file mode 100644 index 129bb0f212a0..000000000000 --- a/include/asm-arm/arch-epxa10db/platform.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef PLATFORM_H -#define PLATFORM_H -#include "excalibur.h" - -#define MAXIRQNUM 15 -#endif - diff --git a/include/asm-arm/arch-epxa10db/pld_conf00.h b/include/asm-arm/arch-epxa10db/pld_conf00.h deleted file mode 100644 index 7af2c38dacc6..000000000000 --- a/include/asm-arm/arch-epxa10db/pld_conf00.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef __PLD_CONF00_H -#define __PLD_CONF00_H - -/* - * Register definitions for the PLD Configuration Logic - */ - -/* - * - * This file contains the register definitions for the Excalibur - * Interrupt controller INT_CTRL00. - * - * Copyright (C) 2001 Altera Corporation - * - * 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 - */ - -#define CONFIG_CONTROL(BASE_ADDR) (PLD_CONF00_TYPE (BASE_ADDR)) -#define CONFIG_CONTROL_LK_MSK (0x1) -#define CONFIG_CONTROL_LK_OFST (0) -#define CONFIG_CONTROL_CO_MSK (0x2) -#define CONFIG_CONTROL_CO_OFST (1) -#define CONFIG_CONTROL_B_MSK (0x4) -#define CONFIG_CONTROL_B_OFST (2) -#define CONFIG_CONTROL_PC_MSK (0x8) -#define CONFIG_CONTROL_PC_OFST (3) -#define CONFIG_CONTROL_E_MSK (0x10) -#define CONFIG_CONTROL_E_OFST (4) -#define CONFIG_CONTROL_ES_MSK (0xE0) -#define CONFIG_CONTROL_ES_OFST (5) -#define CONFIG_CONTROL_ES_0_MSK (0x20) -#define CONFIG_CONTROL_ES_1_MSK (0x40) -#define CONFIG_CONTROL_ES_2_MSK (0x80) - -#define CONFIG_CONTROL_CLOCK(BASE_ADDR) (PLD_CONF00_TYPE (BASE_ADDR + 0x4 )) -#define CONFIG_CONTROL_CLOCK_RATIO_MSK (0xFFFF) -#define CONFIG_CONTROL_CLOCK_RATIO_OFST (0) - -#define CONFIG_CONTROL_DATA(BASE_ADDR) (PLD_CONF00_TYPE (BASE_ADDR + 0x8 )) -#define CONFIG_CONTROL_DATA_MSK (0xFFFFFFFF) -#define CONFIG_CONTROL_DATA_OFST (0) - -#define CONFIG_UNLOCK(BASE_ADDR) (PLD_CONF00_TYPE (BASE_ADDR + 0xC )) -#define CONFIG_UNLOCK_MSK (0xFFFFFFFF) -#define CONFIG_UNLOCK_OFST (0) - -#define CONFIG_UNLOCK_MAGIC (0x554E4C4B) - -#endif /* __PLD_CONF00_H */ - - - - - - - - - - - - diff --git a/include/asm-arm/arch-epxa10db/tdkphy.h b/include/asm-arm/arch-epxa10db/tdkphy.h deleted file mode 100644 index 5e107bd4e109..000000000000 --- a/include/asm-arm/arch-epxa10db/tdkphy.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * linux/drivers/tdkphy.h - * - * Copyright (C) 2001 Altera Corporation - * - * 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 - */ - -#ifndef __TDKPHY_H -#define __TDKPHY_H - -/* - * Register definitions for the TDK 78Q2120 PHY - * which is on the Camelot board - */ - -/* - * Copyright (c) Altera Corporation 2000. - * All rights reserved. - */ -#define PHY_CONTROL (0) -#define PHY_CONTROL_COLT_MSK (0x80) -#define PHY_CONTROL_COLT_OFST (7) -#define PHY_CONTROL_DUPLEX_MSK (0x100) -#define PHY_CONTROL_DUPLEX_OFST (8) -#define PHY_CONTROL_RANEG_MSK (0x200) -#define PHY_CONTROL_RANEG_OFST (9) -#define PHY_CONTROL_ISO_MSK (0x400) -#define PHY_CONTROL_ISO_OFST (10) -#define PHY_CONTROL_PWRDN_MSK (0x800) -#define PHY_CONTROL_PWRDN_OFST (11) -#define PHY_CONTROL_ANEGEN_MSK (0x1000) -#define PHY_CONTROL_ANEGEN_OFST (12) -#define PHY_CONTROL_SPEEDSL_MSK (0x2000) -#define PHY_CONTROL_SPEEDSL_OFST (13) -#define PHY_CONTROL_LOOPBK_MSK (0x4000) -#define PHY_CONTROL_LOOPBK_OFST (14) -#define PHY_CONTROL_RESET_MSK (0x8000) -#define PHY_CONTROL_RESET_OFST (15) - -#define PHY_STATUS (1) -#define PHY_STATUS_ETXD_MSK (0x1) -#define PHY_STATUS_EXTD_OFST (0) -#define PHY_STATUS_JAB_MSK (0x2) -#define PHY_STATUS_JAB_OFST (1) -#define PHY_STATUS_LINK_MSK (0x4) -#define PHY_STATUS_LINK_OFST (2) -#define PHY_STATUS_ANEGA_MSK (0x8) -#define PHY_STATUS_ANEGA_OFST (3) -#define PHY_STATUS_RFAULT_MSK (0x10) -#define PHY_STATUS_RFAULT_OFST (4) -#define PHY_STATUS_ANEGC_MSK (0x20) -#define PHY_STATUS_ANEGC_OFST (5) -#define PHY_STATUS_10T_H_MSK (0x800) -#define PHY_STATUS_10T_H_OFST (11) -#define PHY_STATUS_10T_F_MSK (0x1000) -#define PHY_STATUS_10T_F_OFST (12) -#define PHY_STATUS_100_X_H_MSK (0x2000) -#define PHY_STATUS_100_X_H_OFST (13) -#define PHY_STATUS_100_X_F_MSK (0x4000) -#define PHY_STATUS_100_X_F_OFST (14) -#define PHY_STATUS_100T4_MSK (0x8000) -#define PHY_STATUS_100T4_OFST (15) - -#define PHY_ID1 (2) -#define PHY_ID1_OUI_MSK (0xFFFF) -#define PHY_ID1_OUI_OFST (0) - -#define PHY_ID2 (3) -#define PHY_ID2_RN_MSK (0xF) -#define PHY_ID2_RN_OFST (0) -#define PHY_ID2_MN_MSK (0x3F0) -#define PHY_ID2_MN_OFST (4) -#define PHY_ID2_OUI_MSK (0xFC00) -#define PHY_ID2_OUI_OFST (10) - -#define PHY_AUTO_NEG_ADVERTISEMENT (4) -#define PHY_AUTO_NEG_ADVERTISEMENT_SELECTOR_MSK (0x1F) -#define PHY_AUTO_NEG_ADVERTISEMENT_SELECTOR_OFST (0) -#define PHY_AUTO_NEG_ADVERTISEMENT_A0_MSK (0x20) -#define PHY_AUTO_NEG_ADVERTISEMENT_A0_OFST (5) -#define PHY_AUTO_NEG_ADVERTISEMENT_A1_MSK (0x40) -#define PHY_AUTO_NEG_ADVERTISEMENT_A1_OFST (6) -#define PHY_AUTO_NEG_ADVERTISEMENT_A2_MSK (0x80) -#define PHY_AUTO_NEG_ADVERTISEMENT_A2_OFST (7) -#define PHY_AUTO_NEG_ADVERTISEMENT_A3_MSK (0x100) -#define PHY_AUTO_NEG_ADVERTISEMENT_A3_OFST (8) -#define PHY_AUTO_NEG_ADVERTISEMENT_A4_MSK (0x200) -#define PHY_AUTO_NEG_ADVERTISEMENT_A4_OFST (9) -#define PHY_AUTO_NEG_ADVERTISEMENT_TAF_MSK (0x1FE0) -#define PHY_AUTO_NEG_ADVERTISEMENT_TAF_OFST (5) -#define PHY_AUTO_NEG_ADVERTISEMENT_RF_MSK (0x2000) -#define PHY_AUTO_NEG_ADVERTISEMENT_RF_OFST (13) -#define PHY_AUTO_NEG_ADVERTISEMENT_RSVD_MSK (0x4000) -#define PHY_AUTO_NEG_ADVERTISEMENT_RVSD_OFST (14) -#define PHY_AUTO_NEG_ADVERTISEMENT_NP_MSK (0x8000) -#define PHY_AUTO_NEG_ADVERTISEMENT_NP_OFST (15) - -#define PHY_AUTO_NEG_LINK_PARTNER (5) -#define PHY_AUTO_NEG_LINK_PARTNER_S4_MSK (0x1F) -#define PHY_AUTO_NEG_LINK_PARTNER_S4_OFST (0) -#define PHY_AUTO_NEG_LINK_PARTNER_A7_MSK (0x1FE0) -#define PHY_AUTO_NEG_LINK_PARTNER_A7_OFST (5) -#define PHY_AUTO_NEG_LINK_PARTNER_RF_MSK (0x2000) -#define PHY_AUTO_NEG_LINK_PARTNER_RF_OFST (13) -#define PHY_AUTO_NEG_LINK_PARTNER_ACK_MSK (0x4000) -#define PHY_AUTO_NEG_LINK_PARTNER_ACK_OFST (14) -#define PHY_AUTO_NEG_LINK_PARTNER_NP_MSK (0x8000) -#define PHY_AUTO_NEG_LINK_PARTNER_NP_OFST (15) - -#define PHY_AUTO_NEG_EXPANSION (6) -#define PHY_AUTO_NEG_EXPANSION_LPANEGA_MSK (0x1) -#define PHY_AUTO_NEG_EXPANSION_LPANEGA_OFST (0) -#define PHY_AUTO_NEG_EXPANSION_PRX_MSK (0x2) -#define PHY_AUTO_NEG_EXPANSION_PRX_OFST (1) -#define PHY_AUTO_NEG_EXPANSION_NPA_MSK (0x4) -#define PHY_AUTO_NEG_EXPANSION_NPA_OFST (2) -#define PHY_AUTO_NEG_EXPANSION_LPNPA_MSK (0x8) -#define PHY_AUTO_NEG_EXPANSION_LPNPA_OFST (3) -#define PHY_AUTO_NEG_EXPANSION_PDF_MSK (0x10) -#define PHY_AUTO_NEG_EXPANSION_PDF_OFST (4) - -#define PHY_VENDOR_SPECIFIC (16) -#define PHY_VENDOR_SPECIFIC_RXCC_MSK (0x1) -#define PHY_VENDOR_SPECIFIC_RXCC_OFST (0) -#define PHY_VENDOR_SPECIFIC_PCSBP_MSK (0x2) -#define PHY_VENDOR_SPECIFIC_PCSBP_OFST (1) -#define PHY_VENDOR_SPECIFIC_RVSPOL_MSK (0x10) -#define PHY_VENDOR_SPECIFIC_RVSPOL_OFST (4) -#define PHY_VENDOR_SPECIFIC_APOL_MSK (0x20) -#define PHY_VENDOR_SPECIFIC_APOL_OFST (5) -#define PHY_VENDOR_SPECIFIC_GPIO0_DIR_MSK (0x40) -#define PHY_VENDOR_SPECIFIC_GPIO0_DIR_OFST (6) -#define PHY_VENDOR_SPECIFIC_GPIO0_DAT_MSK (0x80) -#define PHY_VENDOR_SPECIFIC_GPIO0_DAT_OFST (7) -#define PHY_VENDOR_SPECIFIC_GPIO1_DIR_MSK (0x100) -#define PHY_VENDOR_SPECIFIC_GPIO1_DIR_OFST (8) -#define PHY_VENDOR_SPECIFIC_GPIO1_DAT_MSK (0x200) -#define PHY_VENDOR_SPECIFIC_GPIO1_DAT_OFST (9) -#define PHY_VENDOR_SPECIFIC_10BT_NATURAL_LOOPBACK_DAT_MSK (0x400) -#define PHY_VENDOR_SPECIFIC_10BT_NATURAL_LOOPBACK_DAT_OFST (10) -#define PHY_VENDOR_SPECIFIC_10BT_SQE_TEST_INHIBIT_MSK (0x800) -#define PHY_VENDOR_SPECIFIC_10BT_SQE_TEST_INHIBIT_OFST (11) -#define PHY_VENDOR_SPECIFIC_TXHIM_MSK (0x1000) -#define PHY_VENDOR_SPECIFIC_TXHIM_OFST (12) -#define PHY_VENDOR_SPECIFIC_INT_LEVEL_MSK (0x4000) -#define PHY_VENDOR_SPECIFIC_INT_LEVEL_OFST (14) -#define PHY_VENDOR_SPECIFIC_RPTR_MSK (0x8000) -#define PHY_VENDOR_SPECIFIC_RPTR_OFST (15) - -#define PHY_IRQ_CONTROL (17) -#define PHY_IRQ_CONTROL_ANEG_COMP_INT_MSK (0x1) -#define PHY_IRQ_CONTROL_ANEG_COMP_INT_OFST (0) -#define PHY_IRQ_CONTROL_RFAULT_INT_MSK (0x2) -#define PHY_IRQ_CONTROL_RFAULT_INT_OFST (1) -#define PHY_IRQ_CONTROL_LS_CHG_INT_MSK (0x4) -#define PHY_IRQ_CONTROL_LS_CHG_INT_OFST (2) -#define PHY_IRQ_CONTROL_LP_ACK_INT_MSK (0x8) -#define PHY_IRQ_CONTROL_LP_ACK_INT_OFST (3) -#define PHY_IRQ_CONTROL_PDF_INT_MSK (0x10) -#define PHY_IRQ_CONTROL_PDF_INT_OFST (4) -#define PHY_IRQ_CONTROL_PRX_INT_MSK (0x20) -#define PHY_IRQ_CONTROL_PRX_INT_OFST (5) -#define PHY_IRQ_CONTROL_RXER_INT_MSK (0x40) -#define PHY_IRQ_CONTROL_RXER_INT_OFST (6) -#define PHY_IRQ_CONTROL_JABBER_INT_MSK (0x80) -#define PHY_IRQ_CONTROL_JABBER_INT_OFST (7) -#define PHY_IRQ_CONTROL_ANEG_COMP_IE_MSK (0x100) -#define PHY_IRQ_CONTROL_ANEG_COMP_IE_OFST (8) -#define PHY_IRQ_CONTROL_RFAULT_IE_MSK (0x200) -#define PHY_IRQ_CONTROL_RFAULT_IE_OFST (9) -#define PHY_IRQ_CONTROL_LS_CHG_IE_MSK (0x400) -#define PHY_IRQ_CONTROL_LS_CHG_IE_OFST (10) -#define PHY_IRQ_CONTROL_LP_ACK_IE_MSK (0x800) -#define PHY_IRQ_CONTROL_LP_ACK_IE_OFST (11) -#define PHY_IRQ_CONTROL_PDF_IE_MSK (0x1000) -#define PHY_IRQ_CONTROL_PDF_IE_OFST (12) -#define PHY_IRQ_CONTROL_PRX_IE_MSK (0x2000) -#define PHY_IRQ_CONTROL_PRX_IE_OFST (13) -#define PHY_IRQ_CONTROL_RXER_IE_MSK (0x4000) -#define PHY_IRQ_CONTROL_RXER_IE_OFST (14) -#define PHY_IRQ_CONTROL_JABBER_IE_MSK (0x8000) -#define PHY_IRQ_CONTROL_JABBER_IE_OFST (15) - -#define PHY_DIAGNOSTIC (18) -#define PHY_DIAGNOSTIC_RX_LOCK_MSK (0x100) -#define PHY_DIAGNOSTIC_RX_LOCK_OFST (8) -#define PHY_DIAGNOSTIC_RX_PASS_MSK (0x200) -#define PHY_DIAGNOSTIC_RX_PASS_OFST (9) -#define PHY_DIAGNOSTIC_RATE_MSK (0x400) -#define PHY_DIAGNOSTIC_RATE_OFST (10) -#define PHY_DIAGNOSTIC_DPLX_MSK (0x800) -#define PHY_DIAGNOSTIC_DPLX_OFST (11) -#define PHY_DIAGNOSTIC_ANEGF_MSK (0x1000) -#define PHY_DIAGNOSTIC_ANEGF_OFST (12) - -#endif /* __TDKPHY_H */ diff --git a/include/asm-arm/arch-epxa10db/timer00.h b/include/asm-arm/arch-epxa10db/timer00.h deleted file mode 100644 index 52a3fb58b59d..000000000000 --- a/include/asm-arm/arch-epxa10db/timer00.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * This file contains the register definitions for the Excalibur - * Timer TIMER00. - * - * Copyright (C) 2001 Altera Corporation - * - * 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 - */ -#ifndef __TIMER00_H -#define __TIMER00_H - -/* - * Register definitions for the timers - */ - - -#define TIMER0_CR(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x00 )) -#define TIMER0_CR_B_MSK (0x20) -#define TIMER0_CR_B_OFST (0x5) -#define TIMER0_CR_S_MSK (0x10) -#define TIMER0_CR_S_OFST (0x4) -#define TIMER0_CR_CI_MSK (0x08) -#define TIMER0_CR_CI_OFST (0x3) -#define TIMER0_CR_IE_MSK (0x04) -#define TIMER0_CR_IE_OFST (0x2) -#define TIMER0_CR_MODE_MSK (0x3) -#define TIMER0_CR_MODE_OFST (0) -#define TIMER0_CR_MODE_FREE (0) -#define TIMER0_CR_MODE_ONE (1) -#define TIMER0_CR_MODE_INTVL (2) - -#define TIMER0_SR(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x00 )) -#define TIMER0_SR_B_MSK (0x20) -#define TIMER0_SR_B_OFST (0x5) -#define TIMER0_SR_S_MSK (0x10) -#define TIMER0_SR_S_OFST (0x4) -#define TIMER0_SR_CI_MSK (0x08) -#define TIMER0_SR_CI_OFST (0x3) -#define TIMER0_SR_IE_MSK (0x04) -#define TIMER0_SR_IE_OFST (0x2) -#define TIMER0_SR_MODE_MSK (0x3) -#define TIMER0_SR_MODE_OFST (0) -#define TIMER0_SR_MODE_FREE (0) -#define TIMER0_SR_MODE_ONE (1) -#define TIMER0_SR_MODE_INTVL (2) - -#define TIMER0_PRESCALE(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x010 )) -#define TIMER0_LIMIT(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x020 )) -#define TIMER0_READ(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x030 )) - -#define TIMER1_CR(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x40 )) -#define TIMER1_CR_B_MSK (0x20) -#define TIMER1_CR_B_OFST (0x5) -#define TIMER1_CR_S_MSK (0x10) -#define TIMER1_CR_S_OFST (0x4) -#define TIMER1_CR_CI_MSK (0x08) -#define TIMER1_CR_CI_OFST (0x3) -#define TIMER1_CR_IE_MSK (0x04) -#define TIMER1_CR_IE_OFST (0x2) -#define TIMER1_CR_MODE_MSK (0x3) -#define TIMER1_CR_MODE_OFST (0) -#define TIMER1_CR_MODE_FREE (0) -#define TIMER1_CR_MODE_ONE (1) -#define TIMER1_CR_MODE_INTVL (2) - -#define TIMER1_SR(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x40 )) -#define TIMER1_SR_B_MSK (0x20) -#define TIMER1_SR_B_OFST (0x5) -#define TIMER1_SR_S_MSK (0x10) -#define TIMER1_SR_S_OFST (0x4) -#define TIMER1_SR_CI_MSK (0x08) -#define TIMER1_SR_CI_OFST (0x3) -#define TIMER1_SR_IE_MSK (0x04) -#define TIMER1_SR_IE_OFST (0x2) -#define TIMER1_SR_MODE_MSK (0x3) -#define TIMER1_SR_MODE_OFST (0) -#define TIMER1_SR_MODE_FREE (0) -#define TIMER1_SR_MODE_ONE (1) -#define TIMER1_SR_MODE_INTVL (2) - -#define TIMER1_PRESCALE(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x050 )) -#define TIMER1_LIMIT(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x060 )) -#define TIMER1_READ(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x070 )) - -#endif /* __TIMER00_H */ diff --git a/include/asm-arm/arch-epxa10db/uart00.h b/include/asm-arm/arch-epxa10db/uart00.h deleted file mode 100644 index 5abd8914d68b..000000000000 --- a/include/asm-arm/arch-epxa10db/uart00.h +++ /dev/null @@ -1,181 +0,0 @@ -/* * - * Copyright (C) 2001 Altera Corporation - * - * 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 - */ -#ifndef __UART00_H -#define __UART00_H - -/* - * Register definitions for the UART - */ - -#define UART_TX_FIFO_SIZE (15) - -#define UART_RSR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x00 )) -#define UART_RSR_RX_LEVEL_MSK (0x1f) -#define UART_RSR_RX_LEVEL_OFST (0) -#define UART_RSR_RE_MSK (0x80) -#define UART_RSR_RE_OFST (7) - -#define UART_RDS(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x04 )) -#define UART_RDS_BI_MSK (0x8) -#define UART_RDS_BI_OFST (4) -#define UART_RDS_FE_MSK (0x4) -#define UART_RDS_FE_OFST (2) -#define UART_RDS_PE_MSK (0x2) -#define UART_RDS_PE_OFST (1) -#define UART_RDS_OE_MSK (0x1) -#define UART_RDS_OE_OFST (0) - -#define UART_RD(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x08 )) -#define UART_RD_RX_DATA_MSK (0xff) -#define UART_RD_RX_DATA_OFST (0) - -#define UART_TSR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x0c )) -#define UART_TSR_TX_LEVEL_MSK (0x1f) -#define UART_TSR_TX_LEVEL_OFST (0) -#define UART_TSR_TXI_MSK (0x80) -#define UART_TSR_TXI_OFST (7) - -#define UART_TD(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x10 )) -#define UART_TD_TX_DATA_MSK (0xff) -#define UART_TD_TX_DATA_OFST (0) - -#define UART_FCR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x14 )) -#define UART_FCR_RX_THR_MSK (0xd0) -#define UART_FCR_RX_THR_OFST (5) -#define UART_FCR_RX_THR_1 (0x00) -#define UART_FCR_RX_THR_2 (0x20) -#define UART_FCR_RX_THR_4 (0x40) -#define UART_FCR_RX_THR_6 (0x60) -#define UART_FCR_RX_THR_8 (0x80) -#define UART_FCR_RX_THR_10 (0xa0) -#define UART_FCR_RX_THR_12 (0xc0) -#define UART_FCR_RX_THR_14 (0xd0) -#define UART_FCR_TX_THR_MSK (0x1c) -#define UART_FCR_TX_THR_OFST (2) -#define UART_FCR_TX_THR_0 (0x00) -#define UART_FCR_TX_THR_2 (0x04) -#define UART_FCR_TX_THR_4 (0x08) -#define UART_FCR_TX_THR_8 (0x0c) -#define UART_FCR_TX_THR_10 (0x10) -#define UART_FCR_TX_THR_12 (0x14) -#define UART_FCR_TX_THR_14 (0x18) -#define UART_FCR_TX_THR_15 (0x1c) -#define UART_FCR_RC_MSK (0x02) -#define UART_FCR_RC_OFST (1) -#define UART_FCR_TC_MSK (0x01) -#define UART_FCR_TC_OFST (0) - -#define UART_IES(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x18 )) -#define UART_IES_ME_MSK (0x8) -#define UART_IES_ME_OFST (3) -#define UART_IES_TIE_MSK (0x4) -#define UART_IES_TIE_OFST (2) -#define UART_IES_TE_MSK (0x2) -#define UART_IES_TE_OFST (1) -#define UART_IES_RE_MSK (0x1) -#define UART_IES_RE_OFST (0) - -#define UART_IEC(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x1c )) -#define UART_IEC_ME_MSK (0x8) -#define UART_IEC_ME_OFST (3) -#define UART_IEC_TIE_MSK (0x4) -#define UART_IEC_TIE_OFST (2) -#define UART_IEC_TE_MSK (0x2) -#define UART_IEC_TE_OFST (1) -#define UART_IEC_RE_MSK (0x1) -#define UART_IEC_RE_OFST (0) - -#define UART_ISR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x20 )) -#define UART_ISR_MI_MSK (0x8) -#define UART_ISR_MI_OFST (3) -#define UART_ISR_TII_MSK (0x4) -#define UART_ISR_TII_OFST (2) -#define UART_ISR_TI_MSK (0x2) -#define UART_ISR_TI_OFST (1) -#define UART_ISR_RI_MSK (0x1) -#define UART_ISR_RI_OFST (0) - -#define UART_IID(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x24 )) -#define UART_IID_IID_MSK (0x7) -#define UART_IID_IID_OFST (0) - -#define UART_MC(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x28 )) -#define UART_MC_OE_MSK (0x40) -#define UART_MC_OE_OFST (6) -#define UART_MC_SP_MSK (0x20) -#define UART_MC_SP_OFST (5) -#define UART_MC_EP_MSK (0x10) -#define UART_MC_EP_OFST (4) -#define UART_MC_PE_MSK (0x08) -#define UART_MC_PE_OFST (3) -#define UART_MC_ST_MSK (0x04) -#define UART_MC_ST_ONE (0x0) -#define UART_MC_ST_TWO (0x04) -#define UART_MC_ST_OFST (2) -#define UART_MC_CLS_MSK (0x03) -#define UART_MC_CLS_OFST (0) -#define UART_MC_CLS_CHARLEN_5 (0) -#define UART_MC_CLS_CHARLEN_6 (1) -#define UART_MC_CLS_CHARLEN_7 (2) -#define UART_MC_CLS_CHARLEN_8 (3) - -#define UART_MCR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x2c )) -#define UART_MCR_AC_MSK (0x80) -#define UART_MCR_AC_OFST (7) -#define UART_MCR_AR_MSK (0x40) -#define UART_MCR_AR_OFST (6) -#define UART_MCR_BR_MSK (0x20) -#define UART_MCR_BR_OFST (5) -#define UART_MCR_LB_MSK (0x10) -#define UART_MCR_LB_OFST (4) -#define UART_MCR_DCD_MSK (0x08) -#define UART_MCR_DCD_OFST (3) -#define UART_MCR_RI_MSK (0x04) -#define UART_MCR_RI_OFST (2) -#define UART_MCR_DTR_MSK (0x02) -#define UART_MCR_DTR_OFST (1) -#define UART_MCR_RTS_MSK (0x01) -#define UART_MCR_RTS_OFST (0) - -#define UART_MSR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x30 )) -#define UART_MSR_DCD_MSK (0x80) -#define UART_MSR_DCD_OFST (7) -#define UART_MSR_RI_MSK (0x40) -#define UART_MSR_RI_OFST (6) -#define UART_MSR_DSR_MSK (0x20) -#define UART_MSR_DSR_OFST (5) -#define UART_MSR_CTS_MSK (0x10) -#define UART_MSR_CTS_OFST (4) -#define UART_MSR_DDCD_MSK (0x08) -#define UART_MSR_DDCD_OFST (3) -#define UART_MSR_TERI_MSK (0x04) -#define UART_MSR_TERI_OFST (2) -#define UART_MSR_DDSR_MSK (0x02) -#define UART_MSR_DDSR_OFST (1) -#define UART_MSR_DCTS_MSK (0x01) -#define UART_MSR_DCTS_OFST (0) - -#define UART_DIV_LO(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x34 )) -#define UART_DIV_LO_DIV_MSK (0xff) -#define UART_DIV_LO_DIV_OFST (0) - -#define UART_DIV_HI(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x38 )) -#define UART_DIV_HI_DIV_MSK (0xff) -#define UART_DIV_HI_DIV_OFST (0) - -#endif /* __UART00_H */ diff --git a/include/asm-arm/arch-epxa10db/uncompress.h b/include/asm-arm/arch-epxa10db/uncompress.h deleted file mode 100644 index fdfe0e6848f8..000000000000 --- a/include/asm-arm/arch-epxa10db/uncompress.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * linux/include/asm-arm/arch-epxa10db/uncompress.h - * - * Copyright (C) 1999 ARM Limited - * Copyright (C) 2001 Altera Corporation - * - * 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 "asm/arch/platform.h" -#include "asm/hardware.h" -#define UART00_TYPE (volatile unsigned int*) -#include "asm/arch/uart00.h" - -/* - * This does not append a newline - */ -static void putstr(const char *s) -{ - while (*s) { - while ((*UART_TSR(EXC_UART00_BASE) & - UART_TSR_TX_LEVEL_MSK)==15) - barrier(); - - *UART_TD(EXC_UART00_BASE) = *s; - - if (*s == '\n') { - while ((*UART_TSR(EXC_UART00_BASE) & - UART_TSR_TX_LEVEL_MSK)==15) - barrier(); - - *UART_TD(EXC_UART00_BASE) = '\r'; - } - s++; - } -} - -/* - * nothing to do - */ -#define arch_decomp_setup() - -#define arch_decomp_wdog() diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h index f72b63309bc5..3d7283d84405 100644 --- a/include/asm-arm/atomic.h +++ b/include/asm-arm/atomic.h @@ -175,6 +175,8 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) #endif /* __LINUX_ARM_ARCH__ */ +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + static inline int atomic_add_unless(atomic_t *v, int a, int u) { int c, old; diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index 0cf4d4f99600..fd0147e52dbb 100644 --- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h @@ -56,7 +56,12 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); /* * Architecture ioremap implementation. + * + * __ioremap takes CPU physical address. + * + * __ioremap_pfn takes a Page Frame Number and an offset into that page */ +extern void __iomem * __ioremap_pfn(unsigned long, unsigned long, size_t, unsigned long); extern void __iomem * __ioremap(unsigned long, size_t, unsigned long); extern void __iounmap(void __iomem *addr); @@ -261,6 +266,7 @@ out: * * ioremap takes a PCI memory address, as specified in * Documentation/IO-mapping.txt. + * */ #ifndef __arch_ioremap #define ioremap(cookie,size) __ioremap(cookie,size,0) diff --git a/include/asm-arm/mach/map.h b/include/asm-arm/mach/map.h index b338936bde4f..3351b77fab36 100644 --- a/include/asm-arm/mach/map.h +++ b/include/asm-arm/mach/map.h @@ -27,9 +27,6 @@ struct meminfo; #define MT_ROM 6 #define MT_IXP2000_DEVICE 7 -#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT) -#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) - extern void create_memmap_holes(struct meminfo *); extern void memtable_init(struct meminfo *); extern void iotable_init(struct map_desc *, int); diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index 3e572364ee73..3d7f08bd9030 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h @@ -58,6 +58,12 @@ #endif /* + * Convert a physical address to a Page Frame Number and back + */ +#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT) +#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) + +/* * The module space lives between the addresses given by TASK_SIZE * and PAGE_OFFSET - it must be within 32MB of the kernel text. */ diff --git a/include/asm-arm/mutex.h b/include/asm-arm/mutex.h new file mode 100644 index 000000000000..6caa59f1f595 --- /dev/null +++ b/include/asm-arm/mutex.h @@ -0,0 +1,128 @@ +/* + * include/asm-arm/mutex.h + * + * ARM optimized mutex locking primitives + * + * Please look into asm-generic/mutex-xchg.h for a formal definition. + */ +#ifndef _ASM_MUTEX_H +#define _ASM_MUTEX_H + +#if __LINUX_ARM_ARCH__ < 6 +/* On pre-ARMv6 hardware the swp based implementation is the most efficient. */ +# include <asm-generic/mutex-xchg.h> +#else + +/* + * Attempting to lock a mutex on ARMv6+ can be done with a bastardized + * atomic decrement (it is not a reliable atomic decrement but it satisfies + * the defined semantics for our purpose, while being smaller and faster + * than a real atomic decrement or atomic swap. The idea is to attempt + * decrementing the lock value only once. If once decremented it isn't zero, + * or if its store-back fails due to a dispute on the exclusive store, we + * simply bail out immediately through the slow path where the lock will be + * reattempted until it succeeds. + */ +#define __mutex_fastpath_lock(count, fail_fn) \ +do { \ + int __ex_flag, __res; \ + \ + typecheck(atomic_t *, count); \ + typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ + \ + __asm__ ( \ + "ldrex %0, [%2] \n" \ + "sub %0, %0, #1 \n" \ + "strex %1, %0, [%2] \n" \ + \ + : "=&r" (__res), "=&r" (__ex_flag) \ + : "r" (&(count)->counter) \ + : "cc","memory" ); \ + \ + if (unlikely(__res || __ex_flag)) \ + fail_fn(count); \ +} while (0) + +#define __mutex_fastpath_lock_retval(count, fail_fn) \ +({ \ + int __ex_flag, __res; \ + \ + typecheck(atomic_t *, count); \ + typecheck_fn(fastcall int (*)(atomic_t *), fail_fn); \ + \ + __asm__ ( \ + "ldrex %0, [%2] \n" \ + "sub %0, %0, #1 \n" \ + "strex %1, %0, [%2] \n" \ + \ + : "=&r" (__res), "=&r" (__ex_flag) \ + : "r" (&(count)->counter) \ + : "cc","memory" ); \ + \ + __res |= __ex_flag; \ + if (unlikely(__res != 0)) \ + __res = fail_fn(count); \ + __res; \ +}) + +/* + * Same trick is used for the unlock fast path. However the original value, + * rather than the result, is used to test for success in order to have + * better generated assembly. + */ +#define __mutex_fastpath_unlock(count, fail_fn) \ +do { \ + int __ex_flag, __res, __orig; \ + \ + typecheck(atomic_t *, count); \ + typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ + \ + __asm__ ( \ + "ldrex %0, [%3] \n" \ + "add %1, %0, #1 \n" \ + "strex %2, %1, [%3] \n" \ + \ + : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) \ + : "r" (&(count)->counter) \ + : "cc","memory" ); \ + \ + if (unlikely(__orig || __ex_flag)) \ + fail_fn(count); \ +} while (0) + +/* + * If the unlock was done on a contended lock, or if the unlock simply fails + * then the mutex remains locked. + */ +#define __mutex_slowpath_needs_to_unlock() 1 + +/* + * For __mutex_fastpath_trylock we use another construct which could be + * described as a "single value cmpxchg". + * + * This provides the needed trylock semantics like cmpxchg would, but it is + * lighter and less generic than a true cmpxchg implementation. + */ +static inline int +__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) +{ + int __ex_flag, __res, __orig; + + __asm__ ( + + "1: ldrex %0, [%3] \n" + "subs %1, %0, #1 \n" + "strexeq %2, %1, [%3] \n" + "movlt %0, #0 \n" + "cmpeq %2, #0 \n" + "bgt 1b \n" + + : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) + : "r" (&count->counter) + : "cc", "memory" ); + + return __orig; +} + +#endif +#endif diff --git a/include/asm-arm26/atomic.h b/include/asm-arm26/atomic.h index 3074b0e76343..1552c8653990 100644 --- a/include/asm-arm26/atomic.h +++ b/include/asm-arm26/atomic.h @@ -76,6 +76,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new) return ret; } +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + static inline int atomic_add_unless(atomic_t *v, int a, int u) { int ret; diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h index 2df2c7aa19b7..0b51a87e5532 100644 --- a/include/asm-cris/atomic.h +++ b/include/asm-cris/atomic.h @@ -136,6 +136,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new) return ret; } +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + static inline int atomic_add_unless(atomic_t *v, int a, int u) { int ret; diff --git a/include/asm-cris/mutex.h b/include/asm-cris/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-cris/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-frv/atomic.h b/include/asm-frv/atomic.h index 9c9e9499cfd8..a59f684b4f33 100644 --- a/include/asm-frv/atomic.h +++ b/include/asm-frv/atomic.h @@ -328,6 +328,7 @@ extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new); #endif #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new)) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) #define atomic_add_unless(v, a, u) \ ({ \ diff --git a/include/asm-frv/mutex.h b/include/asm-frv/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-frv/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-generic/mutex-dec.h b/include/asm-generic/mutex-dec.h new file mode 100644 index 000000000000..74b18cda169f --- /dev/null +++ b/include/asm-generic/mutex-dec.h @@ -0,0 +1,110 @@ +/* + * asm-generic/mutex-dec.h + * + * Generic implementation of the mutex fastpath, based on atomic + * decrement/increment. + */ +#ifndef _ASM_GENERIC_MUTEX_DEC_H +#define _ASM_GENERIC_MUTEX_DEC_H + +/** + * __mutex_fastpath_lock - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if + * it wasn't 1 originally. This function MUST leave the value lower than + * 1 even when the "1" assertion wasn't true. + */ +#define __mutex_fastpath_lock(count, fail_fn) \ +do { \ + if (unlikely(atomic_dec_return(count) < 0)) \ + fail_fn(count); \ + else \ + smp_mb(); \ +} while (0) + +/** + * __mutex_fastpath_lock_retval - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if + * it wasn't 1 originally. This function returns 0 if the fastpath succeeds, + * or anything the slow path function returns. + */ +static inline int +__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) +{ + if (unlikely(atomic_dec_return(count) < 0)) + return fail_fn(count); + else { + smp_mb(); + return 0; + } +} + +/** + * __mutex_fastpath_unlock - try to promote the count from 0 to 1 + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 0 + * + * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>. + * In the failure case, this function is allowed to either set the value to + * 1, or to set it to a value lower than 1. + * + * If the implementation sets it to a value of lower than 1, then the + * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs + * to return 0 otherwise. + */ +#define __mutex_fastpath_unlock(count, fail_fn) \ +do { \ + smp_mb(); \ + if (unlikely(atomic_inc_return(count) <= 0)) \ + fail_fn(count); \ +} while (0) + +#define __mutex_slowpath_needs_to_unlock() 1 + +/** + * __mutex_fastpath_trylock - try to acquire the mutex, without waiting + * + * @count: pointer of type atomic_t + * @fail_fn: fallback function + * + * Change the count from 1 to a value lower than 1, and return 0 (failure) + * if it wasn't 1 originally, or return 1 (success) otherwise. This function + * MUST leave the value lower than 1 even when the "1" assertion wasn't true. + * Additionally, if the value was < 0 originally, this function must not leave + * it to 0 on failure. + * + * If the architecture has no effective trylock variant, it should call the + * <fail_fn> spinlock-based trylock variant unconditionally. + */ +static inline int +__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) +{ + /* + * We have two variants here. The cmpxchg based one is the best one + * because it never induce a false contention state. It is included + * here because architectures using the inc/dec algorithms over the + * xchg ones are much more likely to support cmpxchg natively. + * + * If not we fall back to the spinlock based variant - that is + * just as efficient (and simpler) as a 'destructive' probing of + * the mutex state would be. + */ +#ifdef __HAVE_ARCH_CMPXCHG + if (likely(atomic_cmpxchg(count, 1, 0)) == 1) { + smp_mb(); + return 1; + } + return 0; +#else + return fail_fn(count); +#endif +} + +#endif diff --git a/include/asm-generic/mutex-null.h b/include/asm-generic/mutex-null.h new file mode 100644 index 000000000000..5cf8b7ce0c45 --- /dev/null +++ b/include/asm-generic/mutex-null.h @@ -0,0 +1,24 @@ +/* + * asm-generic/mutex-null.h + * + * Generic implementation of the mutex fastpath, based on NOP :-) + * + * This is used by the mutex-debugging infrastructure, but it can also + * be used by architectures that (for whatever reason) want to use the + * spinlock based slowpath. + */ +#ifndef _ASM_GENERIC_MUTEX_NULL_H +#define _ASM_GENERIC_MUTEX_NULL_H + +/* extra parameter only needed for mutex debugging: */ +#ifndef __IP__ +# define __IP__ +#endif + +#define __mutex_fastpath_lock(count, fail_fn) fail_fn(count __RET_IP__) +#define __mutex_fastpath_lock_retval(count, fail_fn) fail_fn(count __RET_IP__) +#define __mutex_fastpath_unlock(count, fail_fn) fail_fn(count __RET_IP__) +#define __mutex_fastpath_trylock(count, fail_fn) fail_fn(count) +#define __mutex_slowpath_needs_to_unlock() 1 + +#endif diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h new file mode 100644 index 000000000000..1d24f47e6c48 --- /dev/null +++ b/include/asm-generic/mutex-xchg.h @@ -0,0 +1,117 @@ +/* + * asm-generic/mutex-xchg.h + * + * Generic implementation of the mutex fastpath, based on xchg(). + * + * NOTE: An xchg based implementation is less optimal than an atomic + * decrement/increment based implementation. If your architecture + * has a reasonable atomic dec/inc then you should probably use + * asm-generic/mutex-dec.h instead, or you could open-code an + * optimized version in asm/mutex.h. + */ +#ifndef _ASM_GENERIC_MUTEX_XCHG_H +#define _ASM_GENERIC_MUTEX_XCHG_H + +/** + * __mutex_fastpath_lock - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if it + * wasn't 1 originally. This function MUST leave the value lower than 1 + * even when the "1" assertion wasn't true. + */ +#define __mutex_fastpath_lock(count, fail_fn) \ +do { \ + if (unlikely(atomic_xchg(count, 0) != 1)) \ + fail_fn(count); \ + else \ + smp_mb(); \ +} while (0) + + +/** + * __mutex_fastpath_lock_retval - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if it + * wasn't 1 originally. This function returns 0 if the fastpath succeeds, + * or anything the slow path function returns + */ +static inline int +__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) +{ + if (unlikely(atomic_xchg(count, 0) != 1)) + return fail_fn(count); + else { + smp_mb(); + return 0; + } +} + +/** + * __mutex_fastpath_unlock - try to promote the mutex from 0 to 1 + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 0 + * + * try to promote the mutex from 0 to 1. if it wasn't 0, call <function> + * In the failure case, this function is allowed to either set the value to + * 1, or to set it to a value lower than one. + * If the implementation sets it to a value of lower than one, the + * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs + * to return 0 otherwise. + */ +#define __mutex_fastpath_unlock(count, fail_fn) \ +do { \ + smp_mb(); \ + if (unlikely(atomic_xchg(count, 1) != 0)) \ + fail_fn(count); \ +} while (0) + +#define __mutex_slowpath_needs_to_unlock() 0 + +/** + * __mutex_fastpath_trylock - try to acquire the mutex, without waiting + * + * @count: pointer of type atomic_t + * @fail_fn: spinlock based trylock implementation + * + * Change the count from 1 to a value lower than 1, and return 0 (failure) + * if it wasn't 1 originally, or return 1 (success) otherwise. This function + * MUST leave the value lower than 1 even when the "1" assertion wasn't true. + * Additionally, if the value was < 0 originally, this function must not leave + * it to 0 on failure. + * + * If the architecture has no effective trylock variant, it should call the + * <fail_fn> spinlock-based trylock variant unconditionally. + */ +static inline int +__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) +{ + int prev = atomic_xchg(count, 0); + + if (unlikely(prev < 0)) { + /* + * The lock was marked contended so we must restore that + * state. If while doing so we get back a prev value of 1 + * then we just own it. + * + * [ In the rare case of the mutex going to 1, to 0, to -1 + * and then back to 0 in this few-instructions window, + * this has the potential to trigger the slowpath for the + * owner's unlock path needlessly, but that's not a problem + * in practice. ] + */ + prev = atomic_xchg(count, prev); + if (prev < 0) + prev = 0; + } + smp_mb(); + + return prev; +} + +#endif diff --git a/include/asm-h8300/atomic.h b/include/asm-h8300/atomic.h index d891541e89c3..21f54428c86b 100644 --- a/include/asm-h8300/atomic.h +++ b/include/asm-h8300/atomic.h @@ -95,6 +95,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new) return ret; } +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + static inline int atomic_add_unless(atomic_t *v, int a, int u) { int ret; diff --git a/include/asm-h8300/mutex.h b/include/asm-h8300/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-h8300/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h index 7a5472d77091..de649d3aa2d4 100644 --- a/include/asm-i386/atomic.h +++ b/include/asm-i386/atomic.h @@ -216,6 +216,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) } #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) /** * atomic_add_unless - add unless the number is a given value diff --git a/include/asm-i386/mutex.h b/include/asm-i386/mutex.h new file mode 100644 index 000000000000..4e5e3de1b9a6 --- /dev/null +++ b/include/asm-i386/mutex.h @@ -0,0 +1,124 @@ +/* + * Assembly implementation of the mutex fastpath, based on atomic + * decrement/increment. + * + * started by Ingo Molnar: + * + * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + */ +#ifndef _ASM_MUTEX_H +#define _ASM_MUTEX_H + +/** + * __mutex_fastpath_lock - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fn: function to call if the original value was not 1 + * + * Change the count from 1 to a value lower than 1, and call <fn> if it + * wasn't 1 originally. This function MUST leave the value lower than 1 + * even when the "1" assertion wasn't true. + */ +#define __mutex_fastpath_lock(count, fail_fn) \ +do { \ + unsigned int dummy; \ + \ + typecheck(atomic_t *, count); \ + typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ + \ + __asm__ __volatile__( \ + LOCK " decl (%%eax) \n" \ + " js "#fail_fn" \n" \ + \ + :"=a" (dummy) \ + : "a" (count) \ + : "memory", "ecx", "edx"); \ +} while (0) + + +/** + * __mutex_fastpath_lock_retval - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if it + * wasn't 1 originally. This function returns 0 if the fastpath succeeds, + * or anything the slow path function returns + */ +static inline int +__mutex_fastpath_lock_retval(atomic_t *count, + int fastcall (*fail_fn)(atomic_t *)) +{ + if (unlikely(atomic_dec_return(count) < 0)) + return fail_fn(count); + else + return 0; +} + +/** + * __mutex_fastpath_unlock - try to promote the mutex from 0 to 1 + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 0 + * + * try to promote the mutex from 0 to 1. if it wasn't 0, call <fail_fn>. + * In the failure case, this function is allowed to either set the value + * to 1, or to set it to a value lower than 1. + * + * If the implementation sets it to a value of lower than 1, the + * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs + * to return 0 otherwise. + */ +#define __mutex_fastpath_unlock(count, fail_fn) \ +do { \ + unsigned int dummy; \ + \ + typecheck(atomic_t *, count); \ + typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ + \ + __asm__ __volatile__( \ + LOCK " incl (%%eax) \n" \ + " jle "#fail_fn" \n" \ + \ + :"=a" (dummy) \ + : "a" (count) \ + : "memory", "ecx", "edx"); \ +} while (0) + +#define __mutex_slowpath_needs_to_unlock() 1 + +/** + * __mutex_fastpath_trylock - try to acquire the mutex, without waiting + * + * @count: pointer of type atomic_t + * @fail_fn: fallback function + * + * Change the count from 1 to a value lower than 1, and return 0 (failure) + * if it wasn't 1 originally, or return 1 (success) otherwise. This function + * MUST leave the value lower than 1 even when the "1" assertion wasn't true. + * Additionally, if the value was < 0 originally, this function must not leave + * it to 0 on failure. + */ +static inline int +__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) +{ + /* + * We have two variants here. The cmpxchg based one is the best one + * because it never induce a false contention state. It is included + * here because architectures using the inc/dec algorithms over the + * xchg ones are much more likely to support cmpxchg natively. + * + * If not we fall back to the spinlock based variant - that is + * just as efficient (and simpler) as a 'destructive' probing of + * the mutex state would be. + */ +#ifdef __HAVE_ARCH_CMPXCHG + if (likely(atomic_cmpxchg(count, 1, 0)) == 1) + return 1; + return 0; +#else + return fail_fn(count); +#endif +} + +#endif diff --git a/include/asm-ia64/atomic.h b/include/asm-ia64/atomic.h index 15cf7984c48e..d3e0dfa99e1f 100644 --- a/include/asm-ia64/atomic.h +++ b/include/asm-ia64/atomic.h @@ -89,6 +89,7 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v) } #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) #define atomic_add_unless(v, a, u) \ ({ \ diff --git a/include/asm-ia64/mutex.h b/include/asm-ia64/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-ia64/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-m32r/atomic.h b/include/asm-m32r/atomic.h index 70761278b6cb..3122fe106f05 100644 --- a/include/asm-m32r/atomic.h +++ b/include/asm-m32r/atomic.h @@ -243,6 +243,7 @@ static __inline__ int atomic_dec_return(atomic_t *v) #define atomic_add_negative(i,v) (atomic_add_return((i), (v)) < 0) #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) /** * atomic_add_unless - add unless the number is a given value diff --git a/include/asm-m32r/mutex.h b/include/asm-m32r/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-m32r/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-m68k/atomic.h b/include/asm-m68k/atomic.h index b8a4e75d679d..a4a84d5c65d5 100644 --- a/include/asm-m68k/atomic.h +++ b/include/asm-m68k/atomic.h @@ -140,6 +140,7 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v) } #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) #define atomic_add_unless(v, a, u) \ ({ \ diff --git a/include/asm-m68k/mutex.h b/include/asm-m68k/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-m68k/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-m68knommu/atomic.h b/include/asm-m68knommu/atomic.h index 1702dbe9318c..6c4e4b63e454 100644 --- a/include/asm-m68knommu/atomic.h +++ b/include/asm-m68knommu/atomic.h @@ -129,6 +129,7 @@ static inline int atomic_sub_return(int i, atomic_t * v) } #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) #define atomic_add_unless(v, a, u) \ ({ \ diff --git a/include/asm-m68knommu/mutex.h b/include/asm-m68knommu/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-m68knommu/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h index 92256e43a938..94a95872d727 100644 --- a/include/asm-mips/atomic.h +++ b/include/asm-mips/atomic.h @@ -289,6 +289,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) } #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) /** * atomic_add_unless - add unless the number is a given value diff --git a/include/asm-mips/mutex.h b/include/asm-mips/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-mips/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h index 64ebd086c40d..2ca56d34aaad 100644 --- a/include/asm-parisc/atomic.h +++ b/include/asm-parisc/atomic.h @@ -165,6 +165,7 @@ static __inline__ int atomic_read(const atomic_t *v) /* exported interface */ #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) /** * atomic_add_unless - add unless the number is a given value diff --git a/include/asm-parisc/mutex.h b/include/asm-parisc/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-parisc/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index ae395a0632a6..248f9aec959c 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h @@ -165,6 +165,7 @@ static __inline__ int atomic_dec_return(atomic_t *v) } #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) /** * atomic_add_unless - add unless the number is a given value diff --git a/include/asm-powerpc/mutex.h b/include/asm-powerpc/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-powerpc/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h index 134c2b5be0f2..82ce47607774 100644 --- a/include/asm-powerpc/smu.h +++ b/include/asm-powerpc/smu.h @@ -22,7 +22,7 @@ /* * Partition info commands * - * These commands are used to retreive the sdb-partition-XX datas from + * These commands are used to retrieve the sdb-partition-XX datas from * the SMU. The lenght is always 2. First byte is the subcommand code * and second byte is the partition ID. * @@ -225,7 +225,7 @@ * * SMU_CMD_MISC_ee_GET_DATABLOCK_REC is used, among others, to * transfer blocks of data from the SMU. So far, I've decrypted it's - * usage to retreive partition data. In order to do that, you have to + * usage to retrieve partition data. In order to do that, you have to * break your transfer in "chunks" since that command cannot transfer * more than a chunk at a time. The chunk size used by OF is 0xe bytes, * but it seems that the darwin driver will let you do 0x1e bytes if @@ -556,7 +556,7 @@ struct smu_user_cmd_hdr __u32 cmdtype; #define SMU_CMDTYPE_SMU 0 /* SMU command */ #define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ -#define SMU_CMDTYPE_GET_PARTITION 2 /* retreive an sdb partition */ +#define SMU_CMDTYPE_GET_PARTITION 2 /* retrieve an sdb partition */ __u8 cmd; /* SMU command byte */ __u8 pad[3]; /* padding */ diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h index d82aedf616fe..be6fefe223d6 100644 --- a/include/asm-s390/atomic.h +++ b/include/asm-s390/atomic.h @@ -75,6 +75,8 @@ static __inline__ void atomic_set_mask(unsigned long mask, atomic_t * v) __CS_LOOP(v, mask, "or"); } +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + static __inline__ int atomic_cmpxchg(atomic_t *v, int old, int new) { __asm__ __volatile__(" cs %0,%3,0(%2)\n" diff --git a/include/asm-s390/mutex.h b/include/asm-s390/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-s390/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-sh/atomic.h b/include/asm-sh/atomic.h index 618d8e0de348..fb627de217f2 100644 --- a/include/asm-sh/atomic.h +++ b/include/asm-sh/atomic.h @@ -101,6 +101,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new) return ret; } +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + static inline int atomic_add_unless(atomic_t *v, int a, int u) { int ret; diff --git a/include/asm-sh/mutex.h b/include/asm-sh/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-sh/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-sh64/atomic.h b/include/asm-sh64/atomic.h index f3ce5c0df13a..28f2ea9b567b 100644 --- a/include/asm-sh64/atomic.h +++ b/include/asm-sh64/atomic.h @@ -113,6 +113,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new) return ret; } +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + static inline int atomic_add_unless(atomic_t *v, int a, int u) { int ret; diff --git a/include/asm-sh64/mutex.h b/include/asm-sh64/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-sh64/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h index accb4967e9d2..e1033170bd3a 100644 --- a/include/asm-sparc/atomic.h +++ b/include/asm-sparc/atomic.h @@ -20,6 +20,7 @@ typedef struct { volatile int counter; } atomic_t; extern int __atomic_add_return(int, atomic_t *); extern int atomic_cmpxchg(atomic_t *, int, int); +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) extern int atomic_add_unless(atomic_t *, int, int); extern void atomic_set(atomic_t *, int); diff --git a/include/asm-sparc/mutex.h b/include/asm-sparc/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-sparc/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h index 11f5aa5d108c..25256bdc8aae 100644 --- a/include/asm-sparc64/atomic.h +++ b/include/asm-sparc64/atomic.h @@ -72,6 +72,7 @@ extern int atomic64_sub_ret(int, atomic64_t *); #define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0) #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) #define atomic_add_unless(v, a, u) \ ({ \ diff --git a/include/asm-sparc64/mutex.h b/include/asm-sparc64/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-sparc64/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-um/mutex.h b/include/asm-um/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-um/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h index f5b9ab6f4e70..166df00457ea 100644 --- a/include/asm-v850/atomic.h +++ b/include/asm-v850/atomic.h @@ -104,6 +104,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new) return ret; } +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + static inline int atomic_add_unless(atomic_t *v, int a, int u) { int ret; diff --git a/include/asm-v850/mutex.h b/include/asm-v850/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-v850/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h index 72eb071488c7..6b540237a2f8 100644 --- a/include/asm-x86_64/atomic.h +++ b/include/asm-x86_64/atomic.h @@ -389,6 +389,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t *v) #define atomic64_dec_return(v) (atomic64_sub_return(1,v)) #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) /** * atomic_add_unless - add unless the number is a given value diff --git a/include/asm-x86_64/mutex.h b/include/asm-x86_64/mutex.h new file mode 100644 index 000000000000..818abfd262d1 --- /dev/null +++ b/include/asm-x86_64/mutex.h @@ -0,0 +1,113 @@ +/* + * Assembly implementation of the mutex fastpath, based on atomic + * decrement/increment. + * + * started by Ingo Molnar: + * + * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + */ +#ifndef _ASM_MUTEX_H +#define _ASM_MUTEX_H + +/** + * __mutex_fastpath_lock - decrement and call function if negative + * @v: pointer of type atomic_t + * @fail_fn: function to call if the result is negative + * + * Atomically decrements @v and calls <fail_fn> if the result is negative. + */ +#define __mutex_fastpath_lock(v, fail_fn) \ +do { \ + unsigned long dummy; \ + \ + typecheck(atomic_t *, v); \ + typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ + \ + __asm__ __volatile__( \ + LOCK " decl (%%rdi) \n" \ + " js 2f \n" \ + "1: \n" \ + \ + LOCK_SECTION_START("") \ + "2: call "#fail_fn" \n" \ + " jmp 1b \n" \ + LOCK_SECTION_END \ + \ + :"=D" (dummy) \ + : "D" (v) \ + : "rax", "rsi", "rdx", "rcx", \ + "r8", "r9", "r10", "r11", "memory"); \ +} while (0) + +/** + * __mutex_fastpath_lock_retval - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if + * it wasn't 1 originally. This function returns 0 if the fastpath succeeds, + * or anything the slow path function returns + */ +static inline int +__mutex_fastpath_lock_retval(atomic_t *count, + int fastcall (*fail_fn)(atomic_t *)) +{ + if (unlikely(atomic_dec_return(count) < 0)) + return fail_fn(count); + else + return 0; +} + +/** + * __mutex_fastpath_unlock - increment and call function if nonpositive + * @v: pointer of type atomic_t + * @fail_fn: function to call if the result is nonpositive + * + * Atomically increments @v and calls <fail_fn> if the result is nonpositive. + */ +#define __mutex_fastpath_unlock(v, fail_fn) \ +do { \ + unsigned long dummy; \ + \ + typecheck(atomic_t *, v); \ + typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ + \ + __asm__ __volatile__( \ + LOCK " incl (%%rdi) \n" \ + " jle 2f \n" \ + "1: \n" \ + \ + LOCK_SECTION_START("") \ + "2: call "#fail_fn" \n" \ + " jmp 1b \n" \ + LOCK_SECTION_END \ + \ + :"=D" (dummy) \ + : "D" (v) \ + : "rax", "rsi", "rdx", "rcx", \ + "r8", "r9", "r10", "r11", "memory"); \ +} while (0) + +#define __mutex_slowpath_needs_to_unlock() 1 + +/** + * __mutex_fastpath_trylock - try to acquire the mutex, without waiting + * + * @count: pointer of type atomic_t + * @fail_fn: fallback function + * + * Change the count from 1 to 0 and return 1 (success), or return 0 (failure) + * if it wasn't 1 originally. [the fallback function is never used on + * x86_64, because all x86_64 CPUs have a CMPXCHG instruction.] + */ +static inline int +__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) +{ + if (likely(atomic_cmpxchg(count, 1, 0)) == 1) + return 1; + else + return 0; +} + +#endif diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h index e2ce06b101ad..fe105a123924 100644 --- a/include/asm-xtensa/atomic.h +++ b/include/asm-xtensa/atomic.h @@ -224,6 +224,7 @@ static inline int atomic_sub_return(int i, atomic_t * v) #define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0) #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) /** * atomic_add_unless - add unless the number is a given value diff --git a/include/asm-xtensa/mutex.h b/include/asm-xtensa/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-xtensa/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index 119f9d064cc6..339878952f12 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -218,32 +218,6 @@ COMPATIBLE_IOCTL(VT_RESIZE) COMPATIBLE_IOCTL(VT_RESIZEX) COMPATIBLE_IOCTL(VT_LOCKSWITCH) COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) -/* Little v */ -/* Little v, the video4linux ioctls (conflict?) */ -COMPATIBLE_IOCTL(VIDIOCGCAP) -COMPATIBLE_IOCTL(VIDIOCGCHAN) -COMPATIBLE_IOCTL(VIDIOCSCHAN) -COMPATIBLE_IOCTL(VIDIOCGPICT) -COMPATIBLE_IOCTL(VIDIOCSPICT) -COMPATIBLE_IOCTL(VIDIOCCAPTURE) -COMPATIBLE_IOCTL(VIDIOCKEY) -COMPATIBLE_IOCTL(VIDIOCGAUDIO) -COMPATIBLE_IOCTL(VIDIOCSAUDIO) -COMPATIBLE_IOCTL(VIDIOCSYNC) -COMPATIBLE_IOCTL(VIDIOCMCAPTURE) -COMPATIBLE_IOCTL(VIDIOCGMBUF) -COMPATIBLE_IOCTL(VIDIOCGUNIT) -COMPATIBLE_IOCTL(VIDIOCGCAPTURE) -COMPATIBLE_IOCTL(VIDIOCSCAPTURE) -/* BTTV specific... */ -COMPATIBLE_IOCTL(_IOW('v', BASE_VIDIOCPRIVATE+0, char [256])) -COMPATIBLE_IOCTL(_IOR('v', BASE_VIDIOCPRIVATE+1, char [256])) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)) -COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */ -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int)) /* Little p (/dev/rtc, /dev/envctrl, etc.) */ COMPATIBLE_IOCTL(RTC_AIE_ON) COMPATIBLE_IOCTL(RTC_AIE_OFF) diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 3c89df6e7768..d88bf8aa8b47 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -3,6 +3,7 @@ * * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> * * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> * and Nettle, by Niels Möller. @@ -126,7 +127,11 @@ struct crypto_alg { unsigned int cra_blocksize; unsigned int cra_ctxsize; unsigned int cra_alignmask; + + int cra_priority; + const char cra_name[CRYPTO_MAX_ALG_NAME]; + const char cra_driver_name[CRYPTO_MAX_ALG_NAME]; union { struct cipher_alg cipher; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index d41df7047ed7..c8cbd90ba375 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -240,6 +240,15 @@ struct dvb_frontend_event { }; +/** + * When set, this flag will disable any zigzagging or other "normal" tuning + * behaviour. Additionally, there will be no automatic monitoring of the lock + * status, and hence no frontend events will be generated. If a frontend device + * is closed, this flag will be automatically turned off when the device is + * reopened read-write. + */ +#define FE_TUNE_MODE_ONESHOT 0x01 + #define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info) @@ -260,6 +269,7 @@ struct dvb_frontend_event { #define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters) #define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters) +#define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81) /* unsigned int */ #define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event) #define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */ diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 4a6f50e31c73..23fe746a1d51 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -66,7 +66,7 @@ struct elevator_type }; /* - * each queue has an elevator_queue assoicated with it + * each queue has an elevator_queue associated with it */ struct elevator_queue { diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h index 2914f7b07156..e71dd98dbcae 100644 --- a/include/linux/ext3_fs_i.h +++ b/include/linux/ext3_fs_i.h @@ -87,7 +87,7 @@ struct ext3_inode_info { #ifdef CONFIG_EXT3_FS_XATTR /* * Extended attributes can be read independently of the main file - * data. Taking i_sem even when reading would cause contention + * data. Taking i_mutex even when reading would cause contention * between readers of EAs and writers of regular file data, so * instead we synchronize on xattr_sem when reading or changing * EAs. diff --git a/include/linux/fs.h b/include/linux/fs.h index 4c82219b0fae..92ae3e2067b0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -219,6 +219,7 @@ extern int dir_notify_enable; #include <linux/prio_tree.h> #include <linux/init.h> #include <linux/sched.h> +#include <linux/mutex.h> #include <asm/atomic.h> #include <asm/semaphore.h> @@ -484,7 +485,7 @@ struct inode { unsigned long i_blocks; unsigned short i_bytes; spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ - struct semaphore i_sem; + struct mutex i_mutex; struct rw_semaphore i_alloc_sem; struct inode_operations *i_op; struct file_operations *i_fop; /* former ->i_op->default_file_ops */ @@ -820,7 +821,7 @@ struct super_block { unsigned long s_magic; struct dentry *s_root; struct rw_semaphore s_umount; - struct semaphore s_lock; + struct mutex s_lock; int s_count; int s_syncing; int s_need_sync_fs; @@ -892,13 +893,13 @@ static inline int has_fs_excl(void) static inline void lock_super(struct super_block * sb) { get_fs_excl(); - down(&sb->s_lock); + mutex_lock(&sb->s_lock); } static inline void unlock_super(struct super_block * sb) { put_fs_excl(); - up(&sb->s_lock); + mutex_unlock(&sb->s_lock); } /* @@ -1191,7 +1192,7 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc); * directory. The name should be stored in the @name (with the * understanding that it is already pointing to a a %NAME_MAX+1 sized * buffer. get_name() should return %0 on success, a negative error code - * or error. @get_name will be called without @parent->i_sem held. + * or error. @get_name will be called without @parent->i_mutex held. * * get_parent: * @get_parent should find the parent directory for the given @child which @@ -1213,7 +1214,7 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc); * nfsd_find_fh_dentry() in either the @obj or @parent parameters. * * Locking rules: - * get_parent is called with child->d_inode->i_sem down + * get_parent is called with child->d_inode->i_mutex down * get_name is not (which is possibly inconsistent) */ diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index fb46f8d56999..6ff2d365895f 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -103,6 +103,7 @@ #define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */ #define I2C_DRIVERID_AKITAIOEXP 74 /* IO Expander on Sharp SL-C1000 */ #define I2C_DRIVERID_INFRARED 75 /* I2C InfraRed on Video boards */ +#define I2C_DRIVERID_TVP5150 76 /* TVP5150 video decoder */ #define I2C_DRIVERID_I2CDEV 900 #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ diff --git a/include/linux/ide.h b/include/linux/ide.h index ef8d0cbb832f..9a8c05dbe4f3 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -18,6 +18,7 @@ #include <linux/bio.h> #include <linux/device.h> #include <linux/pci.h> +#include <linux/completion.h> #include <asm/byteorder.h> #include <asm/system.h> #include <asm/io.h> @@ -638,7 +639,7 @@ typedef struct ide_drive_s { int crc_count; /* crc counter to reduce drive speed */ struct list_head list; struct device gendev; - struct semaphore gendev_rel_sem; /* to deal with device release() */ + struct completion gendev_rel_comp; /* to deal with device release() */ } ide_drive_t; #define to_ide_device(dev)container_of(dev, ide_drive_t, gendev) @@ -794,7 +795,7 @@ typedef struct hwif_s { unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */ struct device gendev; - struct semaphore gendev_rel_sem; /* To deal with device release() */ + struct completion gendev_rel_comp; /* To deal with device release() */ void *hwif_data; /* extra hwif data */ diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h index ef85ab56302b..ad565bf9dcc1 100644 --- a/include/linux/jffs2_fs_i.h +++ b/include/linux/jffs2_fs_i.h @@ -8,11 +8,11 @@ #include <asm/semaphore.h> struct jffs2_inode_info { - /* We need an internal semaphore similar to inode->i_sem. + /* We need an internal mutex similar to inode->i_mutex. Unfortunately, we can't used the existing one, because either the GC would deadlock, or we'd have to release it before letting GC proceed. Or we'd have to put ugliness - into the GC code so it didn't attempt to obtain the i_sem + into the GC code so it didn't attempt to obtain the i_mutex for the inode(s) which are already locked */ struct semaphore sem; diff --git a/include/linux/kernel.h b/include/linux/kernel.h index ca7ff8fdd090..d0e6ca3b00ef 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -286,6 +286,15 @@ extern void dump_stack(void); 1; \ }) +/* + * Check at compile time that 'function' is a certain type, or is a pointer + * to that type (needs to use typedef for the function type.) + */ +#define typecheck_fn(type,function) \ +({ typeof(type) __tmp = function; \ + (void)__tmp; \ +}) + #endif /* __KERNEL__ */ #define SI_LOAD_SHIFT 16 diff --git a/include/linux/loop.h b/include/linux/loop.h index 40f63c9879d2..f96506782ebe 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h @@ -58,9 +58,9 @@ struct loop_device { struct bio *lo_bio; struct bio *lo_biotail; int lo_state; - struct semaphore lo_sem; + struct completion lo_done; + struct completion lo_bh_done; struct semaphore lo_ctl_mutex; - struct semaphore lo_bh_mutex; int lo_pending; request_queue_t *lo_queue; diff --git a/include/linux/mm.h b/include/linux/mm.h index df80e63903b5..3f1fafc0245e 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -13,6 +13,7 @@ #include <linux/rbtree.h> #include <linux/prio_tree.h> #include <linux/fs.h> +#include <linux/mutex.h> struct mempolicy; struct anon_vma; @@ -1024,6 +1025,9 @@ static inline void vm_stat_account(struct mm_struct *mm, static inline void kernel_map_pages(struct page *page, int numpages, int enable) { + if (!PageHighMem(page) && !enable) + mutex_debug_check_no_locks_freed(page_address(page), + page_address(page + numpages)); } #endif diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index aef6042f8f0b..ccd3e13de1e8 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -27,14 +27,15 @@ struct mmc_command { #define MMC_RSP_MASK (3 << 0) #define MMC_RSP_CRC (1 << 3) /* expect valid crc */ #define MMC_RSP_BUSY (1 << 4) /* card may send busy */ +#define MMC_RSP_OPCODE (1 << 5) /* response contains opcode */ /* * These are the response types, and correspond to valid bit * patterns of the above flags. One additional valid pattern * is all zeros, which means we don't expect a response. */ -#define MMC_RSP_R1 (MMC_RSP_SHORT|MMC_RSP_CRC) -#define MMC_RSP_R1B (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_BUSY) +#define MMC_RSP_R1 (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_OPCODE) +#define MMC_RSP_R1B (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY) #define MMC_RSP_R2 (MMC_RSP_LONG|MMC_RSP_CRC) #define MMC_RSP_R3 (MMC_RSP_SHORT) #define MMC_RSP_R6 (MMC_RSP_SHORT|MMC_RSP_CRC) @@ -64,6 +65,7 @@ struct mmc_data { #define MMC_DATA_WRITE (1 << 8) #define MMC_DATA_READ (1 << 9) #define MMC_DATA_STREAM (1 << 10) +#define MMC_DATA_MULTI (1 << 11) unsigned int bytes_xfered; diff --git a/include/linux/mutex-debug.h b/include/linux/mutex-debug.h new file mode 100644 index 000000000000..0ccd8f983b50 --- /dev/null +++ b/include/linux/mutex-debug.h @@ -0,0 +1,21 @@ +#ifndef __LINUX_MUTEX_DEBUG_H +#define __LINUX_MUTEX_DEBUG_H + +/* + * Mutexes - debugging helpers: + */ + +#define __DEBUG_MUTEX_INITIALIZER(lockname) \ + , .held_list = LIST_HEAD_INIT(lockname.held_list), \ + .name = #lockname , .magic = &lockname + +#define mutex_init(sem) __mutex_init(sem, __FUNCTION__) + +extern void FASTCALL(mutex_destroy(struct mutex *lock)); + +extern void mutex_debug_show_all_locks(void); +extern void mutex_debug_show_held_locks(struct task_struct *filter); +extern void mutex_debug_check_no_locks_held(struct task_struct *task); +extern void mutex_debug_check_no_locks_freed(const void *from, const void *to); + +#endif diff --git a/include/linux/mutex.h b/include/linux/mutex.h new file mode 100644 index 000000000000..9bce0fee68d4 --- /dev/null +++ b/include/linux/mutex.h @@ -0,0 +1,119 @@ +/* + * Mutexes: blocking mutual exclusion locks + * + * started by Ingo Molnar: + * + * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * + * This file contains the main data structure and API definitions. + */ +#ifndef __LINUX_MUTEX_H +#define __LINUX_MUTEX_H + +#include <linux/list.h> +#include <linux/spinlock_types.h> + +#include <asm/atomic.h> + +/* + * Simple, straightforward mutexes with strict semantics: + * + * - only one task can hold the mutex at a time + * - only the owner can unlock the mutex + * - multiple unlocks are not permitted + * - recursive locking is not permitted + * - a mutex object must be initialized via the API + * - a mutex object must not be initialized via memset or copying + * - task may not exit with mutex held + * - memory areas where held locks reside must not be freed + * - held mutexes must not be reinitialized + * - mutexes may not be used in irq contexts + * + * These semantics are fully enforced when DEBUG_MUTEXES is + * enabled. Furthermore, besides enforcing the above rules, the mutex + * debugging code also implements a number of additional features + * that make lock debugging easier and faster: + * + * - uses symbolic names of mutexes, whenever they are printed in debug output + * - point-of-acquire tracking, symbolic lookup of function names + * - list of all locks held in the system, printout of them + * - owner tracking + * - detects self-recursing locks and prints out all relevant info + * - detects multi-task circular deadlocks and prints out all affected + * locks and tasks (and only those tasks) + */ +struct mutex { + /* 1: unlocked, 0: locked, negative: locked, possible waiters */ + atomic_t count; + spinlock_t wait_lock; + struct list_head wait_list; +#ifdef CONFIG_DEBUG_MUTEXES + struct thread_info *owner; + struct list_head held_list; + unsigned long acquire_ip; + const char *name; + void *magic; +#endif +}; + +/* + * This is the control structure for tasks blocked on mutex, + * which resides on the blocked task's kernel stack: + */ +struct mutex_waiter { + struct list_head list; + struct task_struct *task; +#ifdef CONFIG_DEBUG_MUTEXES + struct mutex *lock; + void *magic; +#endif +}; + +#ifdef CONFIG_DEBUG_MUTEXES +# include <linux/mutex-debug.h> +#else +# define __DEBUG_MUTEX_INITIALIZER(lockname) +# define mutex_init(mutex) __mutex_init(mutex, NULL) +# define mutex_destroy(mutex) do { } while (0) +# define mutex_debug_show_all_locks() do { } while (0) +# define mutex_debug_show_held_locks(p) do { } while (0) +# define mutex_debug_check_no_locks_held(task) do { } while (0) +# define mutex_debug_check_no_locks_freed(from, to) do { } while (0) +#endif + +#define __MUTEX_INITIALIZER(lockname) \ + { .count = ATOMIC_INIT(1) \ + , .wait_lock = SPIN_LOCK_UNLOCKED \ + , .wait_list = LIST_HEAD_INIT(lockname.wait_list) \ + __DEBUG_MUTEX_INITIALIZER(lockname) } + +#define DEFINE_MUTEX(mutexname) \ + struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) + +extern void fastcall __mutex_init(struct mutex *lock, const char *name); + +/*** + * mutex_is_locked - is the mutex locked + * @lock: the mutex to be queried + * + * Returns 1 if the mutex is locked, 0 if unlocked. + */ +static inline int fastcall mutex_is_locked(struct mutex *lock) +{ + return atomic_read(&lock->count) != 1; +} + +/* + * See kernel/mutex.c for detailed documentation of these APIs. + * Also see Documentation/mutex-design.txt. + */ +extern void fastcall mutex_lock(struct mutex *lock); +extern int fastcall mutex_lock_interruptible(struct mutex *lock); +/* + * NOTE: mutex_trylock() follows the spin_trylock() convention, + * not the down_trylock() convention! + */ +extern int fastcall mutex_trylock(struct mutex *lock); +extern void fastcall mutex_unlock(struct mutex *lock); + +#endif diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index bb842ea41033..0798b7781a6e 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h @@ -294,7 +294,7 @@ fill_post_wcc(struct svc_fh *fhp) /* * Lock a file handle/inode * NOTE: both fh_lock and fh_unlock are done "by hand" in - * vfs.c:nfsd_rename as it needs to grab 2 i_sem's at once + * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once * so, any changes here should be reflected there. */ static inline void @@ -317,7 +317,7 @@ fh_lock(struct svc_fh *fhp) } inode = dentry->d_inode; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); fill_pre_wcc(fhp); fhp->fh_locked = 1; } @@ -333,7 +333,7 @@ fh_unlock(struct svc_fh *fhp) if (fhp->fh_locked) { fill_post_wcc(fhp); - up(&fhp->fh_dentry->d_inode->i_sem); + mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex); fhp->fh_locked = 0; } } diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 1767073df26f..b12e59c75752 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -37,7 +37,7 @@ struct pipe_inode_info { memory allocation, whereas PIPE_BUF makes atomicity guarantees. */ #define PIPE_SIZE PAGE_SIZE -#define PIPE_SEM(inode) (&(inode).i_sem) +#define PIPE_MUTEX(inode) (&(inode).i_mutex) #define PIPE_WAIT(inode) (&(inode).i_pipe->wait) #define PIPE_READERS(inode) ((inode).i_pipe->readers) #define PIPE_WRITERS(inode) ((inode).i_pipe->writers) diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 001ab82df051..e276c5ba2bb7 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1857,7 +1857,7 @@ void padd_item(char *item, int total_length, int length); #define GET_BLOCK_CREATE 1 /* add anything you need to find block */ #define GET_BLOCK_NO_HOLE 2 /* return -ENOENT for file holes */ #define GET_BLOCK_READ_DIRECT 4 /* read the tail if indirect item not found */ -#define GET_BLOCK_NO_ISEM 8 /* i_sem is not held, don't preallocate */ +#define GET_BLOCK_NO_IMUX 8 /* i_mutex is not held, don't preallocate */ #define GET_BLOCK_NO_DANGLE 16 /* don't leave any transactions running */ int restart_transaction(struct reiserfs_transaction_handle *th, diff --git a/include/linux/sched.h b/include/linux/sched.h index 78eb92ae4d94..85b53f87c703 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -817,6 +817,11 @@ struct task_struct { /* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */ spinlock_t proc_lock; +#ifdef CONFIG_DEBUG_MUTEXES + /* mutex deadlock detection */ + struct mutex_waiter *blocked_on; +#endif + /* journalling filesystem info */ void *journal_info; diff --git a/include/linux/video_decoder.h b/include/linux/video_decoder.h index 0e9e48b83e3b..121e26da2c18 100644 --- a/include/linux/video_decoder.h +++ b/include/linux/video_decoder.h @@ -1,6 +1,8 @@ #ifndef _LINUX_VIDEO_DECODER_H #define _LINUX_VIDEO_DECODER_H +#define HAVE_VIDEO_DECODER 1 + struct video_decoder_capability { /* this name is too long */ __u32 flags; #define VIDEO_DECODER_PAL 1 /* can decode PAL signal */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 1cded681eb6d..ce40675324bd 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -642,6 +642,12 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) #define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000) +/* some merged standards */ +#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) + /* some common needed stuff */ #define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\ V4L2_STD_PAL_B1 |\ @@ -662,7 +668,8 @@ typedef __u64 v4l2_std_id; V4L2_STD_SECAM_G |\ V4L2_STD_SECAM_H |\ V4L2_STD_SECAM_DK |\ - V4L2_STD_SECAM_L) + V4L2_STD_SECAM_L |\ + V4L2_STD_SECAM_LC) #define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ V4L2_STD_PAL_60 |\ @@ -888,7 +895,6 @@ struct v4l2_audio /* Flags for the 'mode' field */ #define V4L2_AUDMODE_AVL 0x00001 -#define V4L2_AUDMODE_32BITS 0x00002 struct v4l2_audioout { @@ -1110,7 +1116,6 @@ int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local); /* names for fancy debug output */ extern char *v4l2_field_names[]; extern char *v4l2_type_names[]; -extern char *v4l2_ioctl_names[]; /* Compatibility layer interface -- v4l1-compat module */ typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file, @@ -1118,6 +1123,11 @@ typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file, int v4l_compat_translate_ioctl(struct inode *inode, struct file *file, int cmd, void *arg, v4l2_kioctl driver_ioctl); +/* 32 Bits compatibility layer for 64 bits processors */ +extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, + unsigned long arg); + + #endif /* __KERNEL__ */ #endif /* __LINUX_VIDEODEV2_H */ diff --git a/include/media/audiochip.h b/include/media/audiochip.h index b7d4b0930408..295d256ee811 100644 --- a/include/media/audiochip.h +++ b/include/media/audiochip.h @@ -23,11 +23,6 @@ enum audiochip { /* ---------------------------------------------------------------------- */ -/* v4l device was opened in Radio mode */ -#define AUDC_SET_RADIO _IO('m',2) -/* select from TV,radio,extern,MUTE */ -#define AUDC_SET_INPUT _IOW('m',17,int) - /* audio inputs */ #define AUDIO_TUNER 0x00 #define AUDIO_RADIO 0x01 @@ -40,15 +35,4 @@ enum audiochip { #define AUDIO_MUTE 0x80 #define AUDIO_UNMUTE 0x81 -/* all the stuff below is obsolete and just here for reference. I'll - * remove it once the driver is tested and works fine. - * - * Instead creating alot of tiny API's for all kinds of different - * chips, we'll just pass throuth the v4l ioctl structs (v4l2 not - * yet...). It is a bit less flexible, but most/all used i2c chips - * make sense in v4l context only. So I think that's acceptable... - */ - -/* misc stuff to pass around config info to i2c chips */ -#define AUDC_CONFIG_PINNACLE _IOW('m',32,int) #endif /* AUDIOCHIP_H */ diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index 16af9299315f..e5e749e984ee 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -178,6 +178,8 @@ struct saa7146_ext_vv struct saa7146_extension_ioctls *ioctls; int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg); + + struct file_operations vbi_fops; }; struct saa7146_use_ops { diff --git a/include/media/tuner.h b/include/media/tuner.h index b37cde606692..7674b121ce8b 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -82,9 +82,9 @@ #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 */ +/* Microtune merged with Temic 12/31/1999 partially financed by Alps - these may be similar to Temic */ #define TUNER_MICROTUNE_4049FM5 45 -#define TUNER_MICROTUNE_4042_FI5 46 +#define TUNER_PANASONIC_VP27 46 #define TUNER_LG_NTSC_TAPE 47 #define TUNER_TNF_8831BGFF 48 @@ -102,7 +102,7 @@ #define TUNER_YMEC_TVF_8531MF 58 #define TUNER_YMEC_TVF_5533MF 59 /* Pixelview Pro Ultra NTSC */ -#define TUNER_THOMSON_DTT7611 60 /* DViCO FusionHDTV 3 Gold-T */ +#define TUNER_THOMSON_DTT761X 60 /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ #define TUNER_TENA_9533_DI 61 #define TUNER_TEA5767 62 /* Only FM Radio Tuner */ #define TUNER_PHILIPS_FMD1216ME_MK3 63 @@ -115,47 +115,26 @@ #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ #define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */ -#define NOTUNER 0 -#define PAL 1 /* PAL_BG */ -#define PAL_I 2 -#define NTSC 3 -#define SECAM 4 -#define ATSC 5 -#define RADIO 6 - -#define NoTuner 0 -#define Philips 1 -#define TEMIC 2 -#define Sony 3 -#define Alps 4 -#define LGINNOTEK 5 -#define SHARP 6 -#define Samsung 7 -#define Microtune 8 -#define HITACHI 9 -#define Panasonic 10 -#define TCL 11 -#define THOMSON 12 - -#define TUNER_SET_TYPE_ADDR _IOW('T',3,int) -#define TUNER_SET_STANDBY _IOW('T',4,int) -#define TDA9887_SET_CONFIG _IOW('t',5,int) - /* tv card specific */ -# define TDA9887_PRESENT (1<<0) -# define TDA9887_PORT1_INACTIVE (1<<1) -# define TDA9887_PORT2_INACTIVE (1<<2) -# define TDA9887_QSS (1<<3) -# define TDA9887_INTERCARRIER (1<<4) -# define TDA9887_PORT1_ACTIVE (1<<5) -# define TDA9887_PORT2_ACTIVE (1<<6) -# define TDA9887_INTERCARRIER_NTSC (1<<7) +#define TDA9887_PRESENT (1<<0) +#define TDA9887_PORT1_INACTIVE (1<<1) +#define TDA9887_PORT2_INACTIVE (1<<2) +#define TDA9887_QSS (1<<3) +#define TDA9887_INTERCARRIER (1<<4) +#define TDA9887_PORT1_ACTIVE (1<<5) +#define TDA9887_PORT2_ACTIVE (1<<6) +#define TDA9887_INTERCARRIER_NTSC (1<<7) +/* Tuner takeover point adjustment, in dB, -16 <= top <= 15 */ +#define TDA9887_TOP_MASK (0x3f << 8) +#define TDA9887_TOP_SET (1 << 13) +#define TDA9887_TOP(top) (TDA9887_TOP_SET | (((16 + (top)) & 0x1f) << 8)) + /* config options */ -# define TDA9887_DEEMPHASIS_MASK (3<<16) -# define TDA9887_DEEMPHASIS_NONE (1<<16) -# define TDA9887_DEEMPHASIS_50 (2<<16) -# define TDA9887_DEEMPHASIS_75 (3<<16) -# define TDA9887_AUTOMUTE (1<<18) +#define TDA9887_DEEMPHASIS_MASK (3<<16) +#define TDA9887_DEEMPHASIS_NONE (1<<16) +#define TDA9887_DEEMPHASIS_50 (2<<16) +#define TDA9887_DEEMPHASIS_75 (3<<16) +#define TDA9887_AUTOMUTE (1<<18) #ifdef __KERNEL__ @@ -167,10 +146,26 @@ enum tuner_mode { T_STANDBY = 1 << 31 }; +/* Older boards only had a single tuner device. Nowadays multiple tuner + devices may be present on a single board. Using TUNER_SET_TYPE_ADDR + to pass the tuner_setup structure it is possible to setup each tuner + device in turn. + + Since multiple devices may be present it is no longer sufficient to + send a command to a single i2c device. Instead you should broadcast + the command to all i2c devices. + + By setting the mode_mask correctly you can select which commands are + accepted by a specific tuner device. For example, set mode_mask to + T_RADIO if the device is a radio-only tuner. That specific tuner will + only accept commands when the tuner is in radio mode and ignore them + when the tuner is set to TV mode. + */ + struct tuner_setup { - unsigned short addr; - unsigned int type; - unsigned int mode_mask; + unsigned short addr; /* I2C address */ + unsigned int type; /* Tuner type */ + unsigned int mode_mask; /* Allowed tuner modes */ }; struct tuner { @@ -207,7 +202,6 @@ struct tuner { void (*standby)(struct i2c_client *c); }; -extern unsigned int tuner_debug; extern unsigned const int tuner_count; extern int microtune_init(struct i2c_client *c); @@ -219,15 +213,15 @@ extern int tea5767_autodetection(struct i2c_client *c); #define tuner_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ - if (tuner_debug) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, \ - t->i2c.driver->driver.name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + extern int debug; \ + if (debug) \ + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) #endif /* __KERNEL__ */ diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index d3fd48157eb8..3cc3132f391e 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -26,12 +26,57 @@ #ifndef V4L2_COMMON_H_ #define V4L2_COMMON_H_ -/* VIDIOC_INT_AUDIO_CLOCK_FREQ */ -enum v4l2_audio_clock_freq { - V4L2_AUDCLK_32_KHZ = 32000, - V4L2_AUDCLK_441_KHZ = 44100, - V4L2_AUDCLK_48_KHZ = 48000, -}; +/* v4l debugging and diagnostics */ + +/* Common printk constucts for v4l-i2c drivers. These macros create a unique + prefix consisting of the driver name, the adapter number and the i2c + address. */ +#define v4l_printk(level, name, adapter, addr, fmt, arg...) \ + printk(level "%s %d-%04x: " fmt, name, i2c_adapter_id(adapter), addr , ## arg) + +#define v4l_client_printk(level, client, fmt, arg...) \ + v4l_printk(level, (client)->driver->driver.name, (client)->adapter, \ + (client)->addr, fmt , ## arg) + +#define v4l_err(client, fmt, arg...) \ + v4l_client_printk(KERN_ERR, client, fmt , ## arg) + +#define v4l_warn(client, fmt, arg...) \ + v4l_client_printk(KERN_WARNING, client, fmt , ## arg) + +#define v4l_info(client, fmt, arg...) \ + v4l_client_printk(KERN_INFO, client, fmt , ## arg) + +/* These three macros assume that the debug level is set with a module + parameter called 'debug'. */ +#define v4l_dbg(level, client, fmt, arg...) \ + do { \ + extern int debug; \ + if (debug >= (level)) \ + v4l_client_printk(KERN_DEBUG, client, fmt , ## arg); \ + } while (0) + +/* Prints the ioctl in a human-readable format */ +extern void v4l_printk_ioctl(unsigned int cmd); + +/* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */ +#define v4l_print_ioctl(name, cmd) \ + do { \ + printk(KERN_DEBUG "%s: ", name); \ + v4l_printk_ioctl(cmd); \ + } while (0) + +/* Use this macro in I2C drivers where 'client' is the struct i2c_client + pointer */ +#define v4l_i2c_print_ioctl(client, cmd) \ + do { \ + v4l_client_printk(KERN_DEBUG, client, ""); \ + v4l_printk_ioctl(cmd); \ + } while (0) + +/* ------------------------------------------------------------------------- */ + +/* Internal ioctls */ /* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */ struct v4l2_register { @@ -70,6 +115,20 @@ enum v4l2_chip_ident { V4L2_IDENT_CX25843 = 243, }; +/* audio ioctls */ +/* v4l device was opened in Radio mode */ +#define AUDC_SET_RADIO _IO('d',88) +/* select from TV,radio,extern,MUTE */ +#define AUDC_SET_INPUT _IOW('d',89,int) + +/* tuner ioctls */ +/* Sets tuner type and its I2C addr */ +#define TUNER_SET_TYPE_ADDR _IOW('d',90,int) +/* Puts tuner on powersaving state, disabling it, except for i2c */ +#define TUNER_SET_STANDBY _IOW('d',91,int) +/* Sets tda9887 specific stuff, like port1, port2 and qss */ +#define TDA9887_SET_CONFIG _IOW('d',92,int) + /* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ #define VIDIOC_INT_S_REGISTER _IOR ('d', 100, struct v4l2_register) #define VIDIOC_INT_G_REGISTER _IOWR('d', 101, struct v4l2_register) @@ -77,10 +136,12 @@ enum v4l2_chip_ident { /* Reset the I2C chip */ #define VIDIOC_INT_RESET _IO ('d', 102) -/* Set the frequency of the audio clock output. +/* Set the frequency (in Hz) of the audio clock output. Used to slave an audio processor to the video decoder, ensuring that audio - and video remain synchronized. */ -#define VIDIOC_INT_AUDIO_CLOCK_FREQ _IOR ('d', 103, enum v4l2_audio_clock_freq) + and video remain synchronized. + Usual values for the frequency are 48000, 44100 or 32000 Hz. + If the frequency is not supported, then -EINVAL is returned. */ +#define VIDIOC_INT_AUDIO_CLOCK_FREQ _IOW ('d', 103, u32) /* Video decoders that support sliced VBI need to implement this ioctl. Field p of the v4l2_sliced_vbi_line struct is set to the start of the VBI @@ -107,4 +168,10 @@ enum v4l2_chip_ident { be made. */ #define VIDIOC_INT_G_CHIP_IDENT _IOR ('d', 107, enum v4l2_chip_ident *) +/* Sets I2S speed in bps. This is used to provide a standard way to select I2S + clock used by driving digital audio streams at some board designs. + Usual values for the frequency are 1024000 and 2048000. + If the frequency is not supported, then -EINVAL is returned. */ +#define VIDIOC_INT_I2S_CLOCK_FREQ _IOW ('d', 108, u32) + #endif /* V4L2_COMMON_H_ */ diff --git a/include/net/act_api.h b/include/net/act_api.h index b55eb7c7f033..11e9eaf79f5a 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -63,7 +63,7 @@ struct tc_action_ops __u32 type; /* TBD to match kind */ __u32 capab; /* capabilities includes 4 bit version */ struct module *owner; - int (*act)(struct sk_buff **, struct tc_action *, struct tcf_result *); + int (*act)(struct sk_buff *, struct tc_action *, struct tcf_result *); int (*get_stats)(struct sk_buff *, struct tc_action *); int (*dump)(struct sk_buff *, struct tc_action *,int , int); int (*cleanup)(struct tc_action *, int bind); diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 6492e7363d84..b94d1ad92c4d 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -1,6 +1,7 @@ #ifndef __NET_PKT_SCHED_H #define __NET_PKT_SCHED_H +#include <linux/jiffies.h> #include <net/sch_generic.h> struct qdisc_walker @@ -59,8 +60,8 @@ typedef struct timeval psched_time_t; typedef long psched_tdiff_t; #define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp)) -#define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ)) -#define PSCHED_JIFFIE2US(delay) ((delay)*(1000000/HZ)) +#define PSCHED_US2JIFFIE(usecs) usecs_to_jiffies(usecs) +#define PSCHED_JIFFIE2US(delay) jiffies_to_usecs(delay) #else /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */ @@ -123,9 +124,9 @@ do { \ default: \ __delta = 0; \ case 2: \ - __delta += 1000000; \ + __delta += USEC_PER_SEC; \ case 1: \ - __delta += 1000000; \ + __delta += USEC_PER_SEC; \ } \ } \ __delta; \ @@ -136,9 +137,9 @@ psched_tod_diff(int delta_sec, int bound) { int delta; - if (bound <= 1000000 || delta_sec > (0x7FFFFFFF/1000000)-1) + if (bound <= USEC_PER_SEC || delta_sec > (0x7FFFFFFF/USEC_PER_SEC)-1) return bound; - delta = delta_sec * 1000000; + delta = delta_sec * USEC_PER_SEC; if (delta > bound || delta < 0) delta = bound; return delta; @@ -152,9 +153,9 @@ psched_tod_diff(int delta_sec, int bound) default: \ __delta = psched_tod_diff(__delta_sec, bound); break; \ case 2: \ - __delta += 1000000; \ + __delta += USEC_PER_SEC; \ case 1: \ - __delta += 1000000; \ + __delta += USEC_PER_SEC; \ case 0: \ if (__delta > bound || __delta < 0) \ __delta = bound; \ @@ -170,15 +171,15 @@ psched_tod_diff(int delta_sec, int bound) ({ \ int __delta = (tv).tv_usec + (delta); \ (tv_res).tv_sec = (tv).tv_sec; \ - if (__delta > 1000000) { (tv_res).tv_sec++; __delta -= 1000000; } \ + if (__delta > USEC_PER_SEC) { (tv_res).tv_sec++; __delta -= USEC_PER_SEC; } \ (tv_res).tv_usec = __delta; \ }) #define PSCHED_TADD(tv, delta) \ ({ \ (tv).tv_usec += (delta); \ - if ((tv).tv_usec > 1000000) { (tv).tv_sec++; \ - (tv).tv_usec -= 1000000; } \ + if ((tv).tv_usec > USEC_PER_SEC) { (tv).tv_sec++; \ + (tv).tv_usec -= USEC_PER_SEC; } \ }) /* Set/check that time is in the "past perfect"; diff --git a/ipc/mqueue.c b/ipc/mqueue.c index c8943b53d8e6..a8aa6152eea6 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -660,7 +660,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, if (fd < 0) goto out_putname; - down(&mqueue_mnt->mnt_root->d_inode->i_sem); + mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex); dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); @@ -697,7 +697,7 @@ out_putfd: out_err: fd = error; out_upsem: - up(&mqueue_mnt->mnt_root->d_inode->i_sem); + mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex); out_putname: putname(name); return fd; @@ -714,7 +714,7 @@ asmlinkage long sys_mq_unlink(const char __user *u_name) if (IS_ERR(name)) return PTR_ERR(name); - down(&mqueue_mnt->mnt_root->d_inode->i_sem); + mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex); dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); @@ -735,7 +735,7 @@ out_err: dput(dentry); out_unlock: - up(&mqueue_mnt->mnt_root->d_inode->i_sem); + mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex); putname(name); if (inode) iput(inode); diff --git a/kernel/Makefile b/kernel/Makefile index 4f5a1453093a..a940bac02837 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -7,8 +7,9 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ sysctl.o capability.o ptrace.o timer.o user.o \ signal.o sys.o kmod.o workqueue.o pid.o \ rcupdate.o intermodule.o extable.o params.o posix-timers.o \ - kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o + kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o +obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o obj-$(CONFIG_FUTEX) += futex.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += cpu.o spinlock.o diff --git a/kernel/cpuset.c b/kernel/cpuset.c index eab64e23bcae..2a75e44e1a41 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1513,7 +1513,7 @@ static int cpuset_add_file(struct dentry *dir, const struct cftype *cft) struct dentry *dentry; int error; - down(&dir->d_inode->i_sem); + mutex_lock(&dir->d_inode->i_mutex); dentry = cpuset_get_dentry(dir, cft->name); if (!IS_ERR(dentry)) { error = cpuset_create_file(dentry, 0644 | S_IFREG); @@ -1522,7 +1522,7 @@ static int cpuset_add_file(struct dentry *dir, const struct cftype *cft) dput(dentry); } else error = PTR_ERR(dentry); - up(&dir->d_inode->i_sem); + mutex_unlock(&dir->d_inode->i_mutex); return error; } @@ -1793,7 +1793,7 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode) /* * Release manage_sem before cpuset_populate_dir() because it - * will down() this new directory's i_sem and if we race with + * will down() this new directory's i_mutex and if we race with * another mkdir, we might deadlock. */ up(&manage_sem); @@ -1812,7 +1812,7 @@ static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode) { struct cpuset *c_parent = dentry->d_parent->d_fsdata; - /* the vfs holds inode->i_sem already */ + /* the vfs holds inode->i_mutex already */ return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR); } @@ -1823,7 +1823,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) struct cpuset *parent; char *pathbuf = NULL; - /* the vfs holds both inode->i_sem already */ + /* the vfs holds both inode->i_mutex already */ down(&manage_sem); cpuset_update_task_memory_state(); diff --git a/kernel/exit.c b/kernel/exit.c index caceabf3f230..309a46fa16f8 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -29,6 +29,7 @@ #include <linux/syscalls.h> #include <linux/signal.h> #include <linux/cn_proc.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <asm/unistd.h> @@ -869,6 +870,10 @@ fastcall NORET_TYPE void do_exit(long code) mpol_free(tsk->mempolicy); tsk->mempolicy = NULL; #endif + /* + * If DEBUG_MUTEXES is on, make sure we are holding no locks: + */ + mutex_debug_check_no_locks_held(tsk); /* PF_DEAD causes final put_task_struct after we schedule. */ preempt_disable(); diff --git a/kernel/fork.c b/kernel/fork.c index 72e3252c6763..b18d64554feb 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -979,6 +979,10 @@ static task_t *copy_process(unsigned long clone_flags, } #endif +#ifdef CONFIG_DEBUG_MUTEXES + p->blocked_on = NULL; /* not blocked yet */ +#endif + p->tgid = p->pid; if (clone_flags & CLONE_THREAD) p->tgid = current->tgid; diff --git a/kernel/mutex-debug.c b/kernel/mutex-debug.c new file mode 100644 index 000000000000..4fcb051a8b9e --- /dev/null +++ b/kernel/mutex-debug.c @@ -0,0 +1,464 @@ +/* + * kernel/mutex-debug.c + * + * Debugging code for mutexes + * + * Started by Ingo Molnar: + * + * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * + * lock debugging, locking tree, deadlock detection started by: + * + * Copyright (C) 2004, LynuxWorks, Inc., Igor Manyilov, Bill Huey + * Released under the General Public License (GPL). + */ +#include <linux/mutex.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/kallsyms.h> +#include <linux/interrupt.h> + +#include <asm/mutex.h> + +#include "mutex-debug.h" + +/* + * We need a global lock when we walk through the multi-process + * lock tree. Only used in the deadlock-debugging case. + */ +DEFINE_SPINLOCK(debug_mutex_lock); + +/* + * All locks held by all tasks, in a single global list: + */ +LIST_HEAD(debug_mutex_held_locks); + +/* + * In the debug case we carry the caller's instruction pointer into + * other functions, but we dont want the function argument overhead + * in the nondebug case - hence these macros: + */ +#define __IP_DECL__ , unsigned long ip +#define __IP__ , ip +#define __RET_IP__ , (unsigned long)__builtin_return_address(0) + +/* + * "mutex debugging enabled" flag. We turn it off when we detect + * the first problem because we dont want to recurse back + * into the tracing code when doing error printk or + * executing a BUG(): + */ +int debug_mutex_on = 1; + +static void printk_task(struct task_struct *p) +{ + if (p) + printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio); + else + printk("<none>"); +} + +static void printk_ti(struct thread_info *ti) +{ + if (ti) + printk_task(ti->task); + else + printk("<none>"); +} + +static void printk_task_short(struct task_struct *p) +{ + if (p) + printk("%s/%d [%p, %3d]", p->comm, p->pid, p, p->prio); + else + printk("<none>"); +} + +static void printk_lock(struct mutex *lock, int print_owner) +{ + printk(" [%p] {%s}\n", lock, lock->name); + + if (print_owner && lock->owner) { + printk(".. held by: "); + printk_ti(lock->owner); + printk("\n"); + } + if (lock->owner) { + printk("... acquired at: "); + print_symbol("%s\n", lock->acquire_ip); + } +} + +/* + * printk locks held by a task: + */ +static void show_task_locks(struct task_struct *p) +{ + switch (p->state) { + case TASK_RUNNING: printk("R"); break; + case TASK_INTERRUPTIBLE: printk("S"); break; + case TASK_UNINTERRUPTIBLE: printk("D"); break; + case TASK_STOPPED: printk("T"); break; + case EXIT_ZOMBIE: printk("Z"); break; + case EXIT_DEAD: printk("X"); break; + default: printk("?"); break; + } + printk_task(p); + if (p->blocked_on) { + struct mutex *lock = p->blocked_on->lock; + + printk(" blocked on mutex:"); + printk_lock(lock, 1); + } else + printk(" (not blocked on mutex)\n"); +} + +/* + * printk all locks held in the system (if filter == NULL), + * or all locks belonging to a single task (if filter != NULL): + */ +void show_held_locks(struct task_struct *filter) +{ + struct list_head *curr, *cursor = NULL; + struct mutex *lock; + struct thread_info *t; + unsigned long flags; + int count = 0; + + if (filter) { + printk("------------------------------\n"); + printk("| showing all locks held by: | ("); + printk_task_short(filter); + printk("):\n"); + printk("------------------------------\n"); + } else { + printk("---------------------------\n"); + printk("| showing all locks held: |\n"); + printk("---------------------------\n"); + } + + /* + * Play safe and acquire the global trace lock. We + * cannot printk with that lock held so we iterate + * very carefully: + */ +next: + debug_spin_lock_save(&debug_mutex_lock, flags); + list_for_each(curr, &debug_mutex_held_locks) { + if (cursor && curr != cursor) + continue; + lock = list_entry(curr, struct mutex, held_list); + t = lock->owner; + if (filter && (t != filter->thread_info)) + continue; + count++; + cursor = curr->next; + debug_spin_lock_restore(&debug_mutex_lock, flags); + + printk("\n#%03d: ", count); + printk_lock(lock, filter ? 0 : 1); + goto next; + } + debug_spin_lock_restore(&debug_mutex_lock, flags); + printk("\n"); +} + +void mutex_debug_show_all_locks(void) +{ + struct task_struct *g, *p; + int count = 10; + int unlock = 1; + + printk("\nShowing all blocking locks in the system:\n"); + + /* + * Here we try to get the tasklist_lock as hard as possible, + * if not successful after 2 seconds we ignore it (but keep + * trying). This is to enable a debug printout even if a + * tasklist_lock-holding task deadlocks or crashes. + */ +retry: + if (!read_trylock(&tasklist_lock)) { + if (count == 10) + printk("hm, tasklist_lock locked, retrying... "); + if (count) { + count--; + printk(" #%d", 10-count); + mdelay(200); + goto retry; + } + printk(" ignoring it.\n"); + unlock = 0; + } + if (count != 10) + printk(" locked it.\n"); + + do_each_thread(g, p) { + show_task_locks(p); + if (!unlock) + if (read_trylock(&tasklist_lock)) + unlock = 1; + } while_each_thread(g, p); + + printk("\n"); + show_held_locks(NULL); + printk("=============================================\n\n"); + + if (unlock) + read_unlock(&tasklist_lock); +} + +static void report_deadlock(struct task_struct *task, struct mutex *lock, + struct mutex *lockblk, unsigned long ip) +{ + printk("\n%s/%d is trying to acquire this lock:\n", + current->comm, current->pid); + printk_lock(lock, 1); + printk("... trying at: "); + print_symbol("%s\n", ip); + show_held_locks(current); + + if (lockblk) { + printk("but %s/%d is deadlocking current task %s/%d!\n\n", + task->comm, task->pid, current->comm, current->pid); + printk("\n%s/%d is blocked on this lock:\n", + task->comm, task->pid); + printk_lock(lockblk, 1); + + show_held_locks(task); + + printk("\n%s/%d's [blocked] stackdump:\n\n", + task->comm, task->pid); + show_stack(task, NULL); + } + + printk("\n%s/%d's [current] stackdump:\n\n", + current->comm, current->pid); + dump_stack(); + mutex_debug_show_all_locks(); + printk("[ turning off deadlock detection. Please report this. ]\n\n"); + local_irq_disable(); +} + +/* + * Recursively check for mutex deadlocks: + */ +static int check_deadlock(struct mutex *lock, int depth, + struct thread_info *ti, unsigned long ip) +{ + struct mutex *lockblk; + struct task_struct *task; + + if (!debug_mutex_on) + return 0; + + ti = lock->owner; + if (!ti) + return 0; + + task = ti->task; + lockblk = NULL; + if (task->blocked_on) + lockblk = task->blocked_on->lock; + + /* Self-deadlock: */ + if (current == task) { + DEBUG_OFF(); + if (depth) + return 1; + printk("\n==========================================\n"); + printk( "[ BUG: lock recursion deadlock detected! |\n"); + printk( "------------------------------------------\n"); + report_deadlock(task, lock, NULL, ip); + return 0; + } + + /* Ugh, something corrupted the lock data structure? */ + if (depth > 20) { + DEBUG_OFF(); + printk("\n===========================================\n"); + printk( "[ BUG: infinite lock dependency detected!? |\n"); + printk( "-------------------------------------------\n"); + report_deadlock(task, lock, lockblk, ip); + return 0; + } + + /* Recursively check for dependencies: */ + if (lockblk && check_deadlock(lockblk, depth+1, ti, ip)) { + printk("\n============================================\n"); + printk( "[ BUG: circular locking deadlock detected! ]\n"); + printk( "--------------------------------------------\n"); + report_deadlock(task, lock, lockblk, ip); + return 0; + } + return 0; +} + +/* + * Called when a task exits, this function checks whether the + * task is holding any locks, and reports the first one if so: + */ +void mutex_debug_check_no_locks_held(struct task_struct *task) +{ + struct list_head *curr, *next; + struct thread_info *t; + unsigned long flags; + struct mutex *lock; + + if (!debug_mutex_on) + return; + + debug_spin_lock_save(&debug_mutex_lock, flags); + list_for_each_safe(curr, next, &debug_mutex_held_locks) { + lock = list_entry(curr, struct mutex, held_list); + t = lock->owner; + if (t != task->thread_info) + continue; + list_del_init(curr); + DEBUG_OFF(); + debug_spin_lock_restore(&debug_mutex_lock, flags); + + printk("BUG: %s/%d, lock held at task exit time!\n", + task->comm, task->pid); + printk_lock(lock, 1); + if (lock->owner != task->thread_info) + printk("exiting task is not even the owner??\n"); + return; + } + debug_spin_lock_restore(&debug_mutex_lock, flags); +} + +/* + * Called when kernel memory is freed (or unmapped), or if a mutex + * is destroyed or reinitialized - this code checks whether there is + * any held lock in the memory range of <from> to <to>: + */ +void mutex_debug_check_no_locks_freed(const void *from, const void *to) +{ + struct list_head *curr, *next; + unsigned long flags; + struct mutex *lock; + void *lock_addr; + + if (!debug_mutex_on) + return; + + debug_spin_lock_save(&debug_mutex_lock, flags); + list_for_each_safe(curr, next, &debug_mutex_held_locks) { + lock = list_entry(curr, struct mutex, held_list); + lock_addr = lock; + if (lock_addr < from || lock_addr >= to) + continue; + list_del_init(curr); + DEBUG_OFF(); + debug_spin_lock_restore(&debug_mutex_lock, flags); + + printk("BUG: %s/%d, active lock [%p(%p-%p)] freed!\n", + current->comm, current->pid, lock, from, to); + dump_stack(); + printk_lock(lock, 1); + if (lock->owner != current_thread_info()) + printk("freeing task is not even the owner??\n"); + return; + } + debug_spin_lock_restore(&debug_mutex_lock, flags); +} + +/* + * Must be called with lock->wait_lock held. + */ +void debug_mutex_set_owner(struct mutex *lock, + struct thread_info *new_owner __IP_DECL__) +{ + lock->owner = new_owner; + DEBUG_WARN_ON(!list_empty(&lock->held_list)); + if (debug_mutex_on) { + list_add_tail(&lock->held_list, &debug_mutex_held_locks); + lock->acquire_ip = ip; + } +} + +void debug_mutex_init_waiter(struct mutex_waiter *waiter) +{ + memset(waiter, 0x11, sizeof(*waiter)); + waiter->magic = waiter; + INIT_LIST_HEAD(&waiter->list); +} + +void debug_mutex_wake_waiter(struct mutex *lock, struct mutex_waiter *waiter) +{ + SMP_DEBUG_WARN_ON(!spin_is_locked(&lock->wait_lock)); + DEBUG_WARN_ON(list_empty(&lock->wait_list)); + DEBUG_WARN_ON(waiter->magic != waiter); + DEBUG_WARN_ON(list_empty(&waiter->list)); +} + +void debug_mutex_free_waiter(struct mutex_waiter *waiter) +{ + DEBUG_WARN_ON(!list_empty(&waiter->list)); + memset(waiter, 0x22, sizeof(*waiter)); +} + +void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter, + struct thread_info *ti __IP_DECL__) +{ + SMP_DEBUG_WARN_ON(!spin_is_locked(&lock->wait_lock)); + check_deadlock(lock, 0, ti, ip); + /* Mark the current thread as blocked on the lock: */ + ti->task->blocked_on = waiter; + waiter->lock = lock; +} + +void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, + struct thread_info *ti) +{ + DEBUG_WARN_ON(list_empty(&waiter->list)); + DEBUG_WARN_ON(waiter->task != ti->task); + DEBUG_WARN_ON(ti->task->blocked_on != waiter); + ti->task->blocked_on = NULL; + + list_del_init(&waiter->list); + waiter->task = NULL; +} + +void debug_mutex_unlock(struct mutex *lock) +{ + DEBUG_WARN_ON(lock->magic != lock); + DEBUG_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next); + DEBUG_WARN_ON(lock->owner != current_thread_info()); + if (debug_mutex_on) { + DEBUG_WARN_ON(list_empty(&lock->held_list)); + list_del_init(&lock->held_list); + } +} + +void debug_mutex_init(struct mutex *lock, const char *name) +{ + /* + * Make sure we are not reinitializing a held lock: + */ + mutex_debug_check_no_locks_freed((void *)lock, (void *)(lock + 1)); + lock->owner = NULL; + INIT_LIST_HEAD(&lock->held_list); + lock->name = name; + lock->magic = lock; +} + +/*** + * mutex_destroy - mark a mutex unusable + * @lock: the mutex to be destroyed + * + * This function marks the mutex uninitialized, and any subsequent + * use of the mutex is forbidden. The mutex must not be locked when + * this function is called. + */ +void fastcall mutex_destroy(struct mutex *lock) +{ + DEBUG_WARN_ON(mutex_is_locked(lock)); + lock->magic = NULL; +} + +EXPORT_SYMBOL_GPL(mutex_destroy); + diff --git a/kernel/mutex-debug.h b/kernel/mutex-debug.h new file mode 100644 index 000000000000..fd384050acb1 --- /dev/null +++ b/kernel/mutex-debug.h @@ -0,0 +1,134 @@ +/* + * Mutexes: blocking mutual exclusion locks + * + * started by Ingo Molnar: + * + * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * + * This file contains mutex debugging related internal declarations, + * prototypes and inline functions, for the CONFIG_DEBUG_MUTEXES case. + * More details are in kernel/mutex-debug.c. + */ + +extern spinlock_t debug_mutex_lock; +extern struct list_head debug_mutex_held_locks; +extern int debug_mutex_on; + +/* + * In the debug case we carry the caller's instruction pointer into + * other functions, but we dont want the function argument overhead + * in the nondebug case - hence these macros: + */ +#define __IP_DECL__ , unsigned long ip +#define __IP__ , ip +#define __RET_IP__ , (unsigned long)__builtin_return_address(0) + +/* + * This must be called with lock->wait_lock held. + */ +extern void debug_mutex_set_owner(struct mutex *lock, + struct thread_info *new_owner __IP_DECL__); + +static inline void debug_mutex_clear_owner(struct mutex *lock) +{ + lock->owner = NULL; +} + +extern void debug_mutex_init_waiter(struct mutex_waiter *waiter); +extern void debug_mutex_wake_waiter(struct mutex *lock, + struct mutex_waiter *waiter); +extern void debug_mutex_free_waiter(struct mutex_waiter *waiter); +extern void debug_mutex_add_waiter(struct mutex *lock, + struct mutex_waiter *waiter, + struct thread_info *ti __IP_DECL__); +extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, + struct thread_info *ti); +extern void debug_mutex_unlock(struct mutex *lock); +extern void debug_mutex_init(struct mutex *lock, const char *name); + +#define debug_spin_lock(lock) \ + do { \ + local_irq_disable(); \ + if (debug_mutex_on) \ + spin_lock(lock); \ + } while (0) + +#define debug_spin_unlock(lock) \ + do { \ + if (debug_mutex_on) \ + spin_unlock(lock); \ + local_irq_enable(); \ + preempt_check_resched(); \ + } while (0) + +#define debug_spin_lock_save(lock, flags) \ + do { \ + local_irq_save(flags); \ + if (debug_mutex_on) \ + spin_lock(lock); \ + } while (0) + +#define debug_spin_lock_restore(lock, flags) \ + do { \ + if (debug_mutex_on) \ + spin_unlock(lock); \ + local_irq_restore(flags); \ + preempt_check_resched(); \ + } while (0) + +#define spin_lock_mutex(lock) \ + do { \ + struct mutex *l = container_of(lock, struct mutex, wait_lock); \ + \ + DEBUG_WARN_ON(in_interrupt()); \ + debug_spin_lock(&debug_mutex_lock); \ + spin_lock(lock); \ + DEBUG_WARN_ON(l->magic != l); \ + } while (0) + +#define spin_unlock_mutex(lock) \ + do { \ + spin_unlock(lock); \ + debug_spin_unlock(&debug_mutex_lock); \ + } while (0) + +#define DEBUG_OFF() \ +do { \ + if (debug_mutex_on) { \ + debug_mutex_on = 0; \ + console_verbose(); \ + if (spin_is_locked(&debug_mutex_lock)) \ + spin_unlock(&debug_mutex_lock); \ + } \ +} while (0) + +#define DEBUG_BUG() \ +do { \ + if (debug_mutex_on) { \ + DEBUG_OFF(); \ + BUG(); \ + } \ +} while (0) + +#define DEBUG_WARN_ON(c) \ +do { \ + if (unlikely(c && debug_mutex_on)) { \ + DEBUG_OFF(); \ + WARN_ON(1); \ + } \ +} while (0) + +# define DEBUG_BUG_ON(c) \ +do { \ + if (unlikely(c)) \ + DEBUG_BUG(); \ +} while (0) + +#ifdef CONFIG_SMP +# define SMP_DEBUG_WARN_ON(c) DEBUG_WARN_ON(c) +# define SMP_DEBUG_BUG_ON(c) DEBUG_BUG_ON(c) +#else +# define SMP_DEBUG_WARN_ON(c) do { } while (0) +# define SMP_DEBUG_BUG_ON(c) do { } while (0) +#endif + diff --git a/kernel/mutex.c b/kernel/mutex.c new file mode 100644 index 000000000000..7eb960661441 --- /dev/null +++ b/kernel/mutex.c @@ -0,0 +1,325 @@ +/* + * kernel/mutex.c + * + * Mutexes: blocking mutual exclusion locks + * + * Started by Ingo Molnar: + * + * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * + * Many thanks to Arjan van de Ven, Thomas Gleixner, Steven Rostedt and + * David Howells for suggestions and improvements. + * + * Also see Documentation/mutex-design.txt. + */ +#include <linux/mutex.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> + +/* + * In the DEBUG case we are using the "NULL fastpath" for mutexes, + * which forces all calls into the slowpath: + */ +#ifdef CONFIG_DEBUG_MUTEXES +# include "mutex-debug.h" +# include <asm-generic/mutex-null.h> +#else +# include "mutex.h" +# include <asm/mutex.h> +#endif + +/*** + * mutex_init - initialize the mutex + * @lock: the mutex to be initialized + * + * Initialize the mutex to unlocked state. + * + * It is not allowed to initialize an already locked mutex. + */ +void fastcall __mutex_init(struct mutex *lock, const char *name) +{ + atomic_set(&lock->count, 1); + spin_lock_init(&lock->wait_lock); + INIT_LIST_HEAD(&lock->wait_list); + + debug_mutex_init(lock, name); +} + +EXPORT_SYMBOL(__mutex_init); + +/* + * We split the mutex lock/unlock logic into separate fastpath and + * slowpath functions, to reduce the register pressure on the fastpath. + * We also put the fastpath first in the kernel image, to make sure the + * branch is predicted by the CPU as default-untaken. + */ +static void fastcall noinline __sched +__mutex_lock_slowpath(atomic_t *lock_count __IP_DECL__); + +/*** + * mutex_lock - acquire the mutex + * @lock: the mutex to be acquired + * + * Lock the mutex exclusively for this task. If the mutex is not + * available right now, it will sleep until it can get it. + * + * The mutex must later on be released by the same task that + * acquired it. Recursive locking is not allowed. The task + * may not exit without first unlocking the mutex. Also, kernel + * memory where the mutex resides mutex must not be freed with + * the mutex still locked. The mutex must first be initialized + * (or statically defined) before it can be locked. memset()-ing + * the mutex to 0 is not allowed. + * + * ( The CONFIG_DEBUG_MUTEXES .config option turns on debugging + * checks that will enforce the restrictions and will also do + * deadlock debugging. ) + * + * This function is similar to (but not equivalent to) down(). + */ +void fastcall __sched mutex_lock(struct mutex *lock) +{ + /* + * The locking fastpath is the 1->0 transition from + * 'unlocked' into 'locked' state. + * + * NOTE: if asm/mutex.h is included, then some architectures + * rely on mutex_lock() having _no other code_ here but this + * fastpath. That allows the assembly fastpath to do + * tail-merging optimizations. (If you want to put testcode + * here, do it under #ifndef CONFIG_MUTEX_DEBUG.) + */ + __mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath); +} + +EXPORT_SYMBOL(mutex_lock); + +static void fastcall noinline __sched +__mutex_unlock_slowpath(atomic_t *lock_count __IP_DECL__); + +/*** + * mutex_unlock - release the mutex + * @lock: the mutex to be released + * + * Unlock a mutex that has been locked by this task previously. + * + * This function must not be used in interrupt context. Unlocking + * of a not locked mutex is not allowed. + * + * This function is similar to (but not equivalent to) up(). + */ +void fastcall __sched mutex_unlock(struct mutex *lock) +{ + /* + * The unlocking fastpath is the 0->1 transition from 'locked' + * into 'unlocked' state: + * + * NOTE: no other code must be here - see mutex_lock() . + */ + __mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath); +} + +EXPORT_SYMBOL(mutex_unlock); + +/* + * Lock a mutex (possibly interruptible), slowpath: + */ +static inline int __sched +__mutex_lock_common(struct mutex *lock, long state __IP_DECL__) +{ + struct task_struct *task = current; + struct mutex_waiter waiter; + unsigned int old_val; + + debug_mutex_init_waiter(&waiter); + + spin_lock_mutex(&lock->wait_lock); + + debug_mutex_add_waiter(lock, &waiter, task->thread_info, ip); + + /* add waiting tasks to the end of the waitqueue (FIFO): */ + list_add_tail(&waiter.list, &lock->wait_list); + waiter.task = task; + + for (;;) { + /* + * Lets try to take the lock again - this is needed even if + * we get here for the first time (shortly after failing to + * acquire the lock), to make sure that we get a wakeup once + * it's unlocked. Later on, if we sleep, this is the + * operation that gives us the lock. We xchg it to -1, so + * that when we release the lock, we properly wake up the + * other waiters: + */ + old_val = atomic_xchg(&lock->count, -1); + if (old_val == 1) + break; + + /* + * got a signal? (This code gets eliminated in the + * TASK_UNINTERRUPTIBLE case.) + */ + if (unlikely(state == TASK_INTERRUPTIBLE && + signal_pending(task))) { + mutex_remove_waiter(lock, &waiter, task->thread_info); + spin_unlock_mutex(&lock->wait_lock); + + debug_mutex_free_waiter(&waiter); + return -EINTR; + } + __set_task_state(task, state); + + /* didnt get the lock, go to sleep: */ + spin_unlock_mutex(&lock->wait_lock); + schedule(); + spin_lock_mutex(&lock->wait_lock); + } + + /* got the lock - rejoice! */ + mutex_remove_waiter(lock, &waiter, task->thread_info); + debug_mutex_set_owner(lock, task->thread_info __IP__); + + /* set it to 0 if there are no waiters left: */ + if (likely(list_empty(&lock->wait_list))) + atomic_set(&lock->count, 0); + + spin_unlock_mutex(&lock->wait_lock); + + debug_mutex_free_waiter(&waiter); + + DEBUG_WARN_ON(list_empty(&lock->held_list)); + DEBUG_WARN_ON(lock->owner != task->thread_info); + + return 0; +} + +static void fastcall noinline __sched +__mutex_lock_slowpath(atomic_t *lock_count __IP_DECL__) +{ + struct mutex *lock = container_of(lock_count, struct mutex, count); + + __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE __IP__); +} + +/* + * Release the lock, slowpath: + */ +static fastcall noinline void +__mutex_unlock_slowpath(atomic_t *lock_count __IP_DECL__) +{ + struct mutex *lock = container_of(lock_count, struct mutex, count); + + DEBUG_WARN_ON(lock->owner != current_thread_info()); + + spin_lock_mutex(&lock->wait_lock); + + /* + * some architectures leave the lock unlocked in the fastpath failure + * case, others need to leave it locked. In the later case we have to + * unlock it here + */ + if (__mutex_slowpath_needs_to_unlock()) + atomic_set(&lock->count, 1); + + debug_mutex_unlock(lock); + + if (!list_empty(&lock->wait_list)) { + /* get the first entry from the wait-list: */ + struct mutex_waiter *waiter = + list_entry(lock->wait_list.next, + struct mutex_waiter, list); + + debug_mutex_wake_waiter(lock, waiter); + + wake_up_process(waiter->task); + } + + debug_mutex_clear_owner(lock); + + spin_unlock_mutex(&lock->wait_lock); +} + +/* + * Here come the less common (and hence less performance-critical) APIs: + * mutex_lock_interruptible() and mutex_trylock(). + */ +static int fastcall noinline __sched +__mutex_lock_interruptible_slowpath(atomic_t *lock_count __IP_DECL__); + +/*** + * mutex_lock_interruptible - acquire the mutex, interruptable + * @lock: the mutex to be acquired + * + * Lock the mutex like mutex_lock(), and return 0 if the mutex has + * been acquired or sleep until the mutex becomes available. If a + * signal arrives while waiting for the lock then this function + * returns -EINTR. + * + * This function is similar to (but not equivalent to) down_interruptible(). + */ +int fastcall __sched mutex_lock_interruptible(struct mutex *lock) +{ + /* NOTE: no other code must be here - see mutex_lock() */ + return __mutex_fastpath_lock_retval + (&lock->count, __mutex_lock_interruptible_slowpath); +} + +EXPORT_SYMBOL(mutex_lock_interruptible); + +static int fastcall noinline __sched +__mutex_lock_interruptible_slowpath(atomic_t *lock_count __IP_DECL__) +{ + struct mutex *lock = container_of(lock_count, struct mutex, count); + + return __mutex_lock_common(lock, TASK_INTERRUPTIBLE __IP__); +} + +/* + * Spinlock based trylock, we take the spinlock and check whether we + * can get the lock: + */ +static inline int __mutex_trylock_slowpath(atomic_t *lock_count) +{ + struct mutex *lock = container_of(lock_count, struct mutex, count); + int prev; + + spin_lock_mutex(&lock->wait_lock); + + prev = atomic_xchg(&lock->count, -1); + if (likely(prev == 1)) + debug_mutex_set_owner(lock, current_thread_info() __RET_IP__); + /* Set it back to 0 if there are no waiters: */ + if (likely(list_empty(&lock->wait_list))) + atomic_set(&lock->count, 0); + + spin_unlock_mutex(&lock->wait_lock); + + return prev == 1; +} + +/*** + * mutex_trylock - try acquire the mutex, without waiting + * @lock: the mutex to be acquired + * + * Try to acquire the mutex atomically. Returns 1 if the mutex + * has been acquired successfully, and 0 on contention. + * + * NOTE: this function follows the spin_trylock() convention, so + * it is negated to the down_trylock() return values! Be careful + * about this when converting semaphore users to mutexes. + * + * This function must not be used in interrupt context. The + * mutex must be released by the same task that acquired it. + */ +int fastcall mutex_trylock(struct mutex *lock) +{ + return __mutex_fastpath_trylock(&lock->count, + __mutex_trylock_slowpath); +} + +EXPORT_SYMBOL(mutex_trylock); + + + diff --git a/kernel/mutex.h b/kernel/mutex.h new file mode 100644 index 000000000000..00fe84e7b672 --- /dev/null +++ b/kernel/mutex.h @@ -0,0 +1,35 @@ +/* + * Mutexes: blocking mutual exclusion locks + * + * started by Ingo Molnar: + * + * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * + * This file contains mutex debugging related internal prototypes, for the + * !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs: + */ + +#define spin_lock_mutex(lock) spin_lock(lock) +#define spin_unlock_mutex(lock) spin_unlock(lock) +#define mutex_remove_waiter(lock, waiter, ti) \ + __list_del((waiter)->list.prev, (waiter)->list.next) + +#define DEBUG_WARN_ON(c) do { } while (0) +#define debug_mutex_set_owner(lock, new_owner) do { } while (0) +#define debug_mutex_clear_owner(lock) do { } while (0) +#define debug_mutex_init_waiter(waiter) do { } while (0) +#define debug_mutex_wake_waiter(lock, waiter) do { } while (0) +#define debug_mutex_free_waiter(waiter) do { } while (0) +#define debug_mutex_add_waiter(lock, waiter, ti, ip) do { } while (0) +#define debug_mutex_unlock(lock) do { } while (0) +#define debug_mutex_init(lock, name) do { } while (0) + +/* + * Return-address parameters/declarations. They are very useful for + * debugging, but add overhead in the !DEBUG case - so we go the + * trouble of using this not too elegant but zero-cost solution: + */ +#define __IP_DECL__ +#define __IP__ +#define __RET_IP__ + diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index ccc45d49ce71..05ee48316f70 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -236,12 +236,8 @@ static void rcu_do_batch(struct rcu_data *rdp) * active batch and the batch to be registered has not already occurred. * Caller must hold rcu_state.lock. */ -static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp, - int next_pending) +static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp) { - if (next_pending) - rcp->next_pending = 1; - if (rcp->next_pending && rcp->completed == rcp->cur) { rcp->next_pending = 0; @@ -275,7 +271,7 @@ static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp) if (cpus_empty(rsp->cpumask)) { /* batch completed ! */ rcp->completed = rcp->cur; - rcu_start_batch(rcp, rsp, 0); + rcu_start_batch(rcp, rsp); } } @@ -410,7 +406,8 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, if (!rcp->next_pending) { /* and start it/schedule start if it's a new batch */ spin_lock(&rsp->lock); - rcu_start_batch(rcp, rsp, 1); + rcp->next_pending = 1; + rcu_start_batch(rcp, rsp); spin_unlock(&rsp->lock); } } else { diff --git a/kernel/sched.c b/kernel/sched.c index 92733091154c..34a945bcc022 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4386,6 +4386,7 @@ void show_state(void) } while_each_thread(g, p); read_unlock(&tasklist_lock); + mutex_debug_show_all_locks(); } /** diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c48260fb8fd9..1fcd856edec1 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -95,6 +95,14 @@ config DEBUG_PREEMPT if kernel code uses it in a preemption-unsafe way. Also, the kernel will detect preemption count underflows. +config DEBUG_MUTEXES + bool "Mutex debugging, deadlock detection" + default y + depends on DEBUG_KERNEL + help + This allows mutex semantics violations and mutex related deadlocks + (lockups) to be detected and reported automatically. + config DEBUG_SPINLOCK bool "Spinlock debugging" depends on DEBUG_KERNEL diff --git a/mm/filemap.c b/mm/filemap.c index 478f4c74cc31..5fca2737c971 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -61,7 +61,7 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, * ->swap_lock (exclusive_swap_page, others) * ->mapping->tree_lock * - * ->i_sem + * ->i_mutex * ->i_mmap_lock (truncate->unmap_mapping_range) * * ->mmap_sem @@ -73,9 +73,9 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, * ->lock_page (access_process_vm) * * ->mmap_sem - * ->i_sem (msync) + * ->i_mutex (msync) * - * ->i_sem + * ->i_mutex * ->i_alloc_sem (various) * * ->inode_lock @@ -276,7 +276,7 @@ static int wait_on_page_writeback_range(struct address_space *mapping, * integrity" operation. It waits upon in-flight writeout before starting and * waiting upon new writeout. If there was an IO error, return it. * - * We need to re-take i_sem during the generic_osync_inode list walk because + * We need to re-take i_mutex during the generic_osync_inode list walk because * it is otherwise livelockable. */ int sync_page_range(struct inode *inode, struct address_space *mapping, @@ -290,9 +290,9 @@ int sync_page_range(struct inode *inode, struct address_space *mapping, return 0; ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1); if (ret == 0) { - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); ret = generic_osync_inode(inode, mapping, OSYNC_METADATA); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } if (ret == 0) ret = wait_on_page_writeback_range(mapping, start, end); @@ -301,7 +301,7 @@ int sync_page_range(struct inode *inode, struct address_space *mapping, EXPORT_SYMBOL(sync_page_range); /* - * Note: Holding i_sem across sync_page_range_nolock is not a good idea + * Note: Holding i_mutex across sync_page_range_nolock is not a good idea * as it forces O_SYNC writers to different parts of the same file * to be serialised right until io completion. */ @@ -1892,7 +1892,7 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov, /* * Sync the fs metadata but not the minor inode changes and * of course not the data as we did direct DMA for the IO. - * i_sem is held, which protects generic_osync_inode() from + * i_mutex is held, which protects generic_osync_inode() from * livelocking. */ if (written >= 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { @@ -2195,10 +2195,10 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf, BUG_ON(iocb->ki_pos != pos); - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); ret = __generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { ssize_t err; @@ -2220,9 +2220,9 @@ ssize_t generic_file_write(struct file *file, const char __user *buf, struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count }; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); ret = __generic_file_write_nolock(file, &local_iov, 1, ppos); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { ssize_t err; @@ -2256,9 +2256,9 @@ ssize_t generic_file_writev(struct file *file, const struct iovec *iov, struct inode *inode = mapping->host; ssize_t ret; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); ret = __generic_file_write_nolock(file, iov, nr_segs, ppos); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { int err; @@ -2272,7 +2272,7 @@ ssize_t generic_file_writev(struct file *file, const struct iovec *iov, EXPORT_SYMBOL(generic_file_writev); /* - * Called under i_sem for writes to S_ISREG files. Returns -EIO if something + * Called under i_mutex for writes to S_ISREG files. Returns -EIO if something * went wrong during pagecache shootdown. */ static ssize_t diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index 9cf687e4a29a..e2b34e95913e 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c @@ -338,7 +338,7 @@ __xip_file_write(struct file *filp, const char __user *buf, *ppos = pos; /* * No need to use i_size_read() here, the i_size - * cannot change under us because we hold i_sem. + * cannot change under us because we hold i_mutex. */ if (pos > inode->i_size) { i_size_write(inode, pos); @@ -358,7 +358,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, loff_t pos; ssize_t ret; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (!access_ok(VERIFY_READ, buf, len)) { ret=-EFAULT; @@ -390,7 +390,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, out_backing: current->backing_dev_info = NULL; out_up: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return ret; } EXPORT_SYMBOL_GPL(xip_file_write); diff --git a/mm/memory.c b/mm/memory.c index 3944fec38012..7a11ddd5060f 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1784,13 +1784,13 @@ int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) if (!inode->i_op || !inode->i_op->truncate_range) return -ENOSYS; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); down_write(&inode->i_alloc_sem); unmap_mapping_range(mapping, offset, (end - offset), 1); truncate_inode_pages_range(mapping, offset, end); inode->i_op->truncate_range(inode, offset, end); up_write(&inode->i_alloc_sem); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return 0; } diff --git a/mm/msync.c b/mm/msync.c index 1b5b6f662dcf..3563a56e1a51 100644 --- a/mm/msync.c +++ b/mm/msync.c @@ -137,7 +137,7 @@ static int msync_interval(struct vm_area_struct *vma, ret = filemap_fdatawrite(mapping); if (file->f_op && file->f_op->fsync) { /* - * We don't take i_sem here because mmap_sem + * We don't take i_mutex here because mmap_sem * is already held. */ err = file->f_op->fsync(file,file->f_dentry,1); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e0e84924171b..a5e6891f7bb6 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -415,6 +415,9 @@ static void __free_pages_ok(struct page *page, unsigned int order) int reserved = 0; arch_free_page(page, order); + if (!PageHighMem(page)) + mutex_debug_check_no_locks_freed(page_address(page), + page_address(page+(1<<order))); #ifndef CONFIG_MMU for (i = 1 ; i < (1 << order) ; ++i) diff --git a/mm/rmap.c b/mm/rmap.c index 66ec43053a4d..dfbb89f99a15 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -20,13 +20,13 @@ /* * Lock ordering in mm: * - * inode->i_sem (while writing or truncating, not reading or faulting) + * inode->i_mutex (while writing or truncating, not reading or faulting) * inode->i_alloc_sem * * When a page fault occurs in writing from user to file, down_read - * of mmap_sem nests within i_sem; in sys_msync, i_sem nests within - * down_read of mmap_sem; i_sem and down_write of mmap_sem are never - * taken together; in truncation, i_sem is taken outermost. + * of mmap_sem nests within i_mutex; in sys_msync, i_mutex nests within + * down_read of mmap_sem; i_mutex and down_write of mmap_sem are never + * taken together; in truncation, i_mutex is taken outermost. * * mm->mmap_sem * page->flags PG_locked (lock_page) diff --git a/mm/shmem.c b/mm/shmem.c index a1f2f02af724..343b3c0937e5 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1370,7 +1370,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t if (!access_ok(VERIFY_READ, buf, count)) return -EFAULT; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); pos = *ppos; written = 0; @@ -1455,7 +1455,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t if (written) err = written; out: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return err; } @@ -1491,7 +1491,7 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ /* * We must evaluate after, since reads (unlike writes) - * are called without i_sem protection against truncate + * are called without i_mutex protection against truncate */ nr = PAGE_CACHE_SIZE; i_size = i_size_read(inode); diff --git a/mm/slab.c b/mm/slab.c index 1c46c6383552..33aab345cd4a 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3071,6 +3071,7 @@ void kfree(const void *objp) local_irq_save(flags); kfree_debugcheck(objp); c = page_get_cache(virt_to_page(objp)); + mutex_debug_check_no_locks_freed(objp, objp+obj_reallen(c)); __cache_free(c, (void *)objp); local_irq_restore(flags); } diff --git a/mm/swapfile.c b/mm/swapfile.c index 80f948a2028b..6544565a7c0f 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1187,9 +1187,9 @@ asmlinkage long sys_swapoff(const char __user * specialfile) set_blocksize(bdev, p->old_block_size); bd_release(bdev); } else { - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); inode->i_flags &= ~S_SWAPFILE; - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } filp_close(swap_file, NULL); err = 0; @@ -1406,7 +1406,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) p->bdev = bdev; } else if (S_ISREG(inode->i_mode)) { p->bdev = inode->i_sb->s_bdev; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); did_down = 1; if (IS_SWAPFILE(inode)) { error = -EBUSY; @@ -1596,7 +1596,7 @@ out: if (did_down) { if (!error) inode->i_flags |= S_SWAPFILE; - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } return error; } diff --git a/mm/truncate.c b/mm/truncate.c index b1a463d0fe71..6cb3fff25f67 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -196,7 +196,7 @@ EXPORT_SYMBOL(truncate_inode_pages_range); * @mapping: mapping to truncate * @lstart: offset from which to truncate * - * Called under (and serialised by) inode->i_sem. + * Called under (and serialised by) inode->i_mutex. */ void truncate_inode_pages(struct address_space *mapping, loff_t lstart) { diff --git a/net/core/dev.c b/net/core/dev.c index 5081287923d5..bf66b114d3c2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1092,15 +1092,12 @@ int skb_checksum_help(struct sk_buff *skb, int inward) goto out; } - if (offset > (int)skb->len) - BUG(); + BUG_ON(offset > (int)skb->len); csum = skb_checksum(skb, offset, skb->len-offset, 0); offset = skb->tail - skb->h.raw; - if (offset <= 0) - BUG(); - if (skb->csum + 2 > offset) - BUG(); + BUG_ON(offset <= 0); + BUG_ON(skb->csum + 2 > offset); *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum); skb->ip_summed = CHECKSUM_NONE; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 070f91cfde59..d0732e9c8560 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -791,8 +791,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc) int end = offset + skb_shinfo(skb)->frags[i].size; if (end > len) { if (skb_cloned(skb)) { - if (!realloc) - BUG(); + BUG_ON(!realloc); if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) return -ENOMEM; } @@ -894,8 +893,7 @@ unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta) struct sk_buff *insp = NULL; do { - if (!list) - BUG(); + BUG_ON(!list); if (list->len <= eat) { /* Eaten as whole. */ @@ -1199,8 +1197,7 @@ unsigned int skb_checksum(const struct sk_buff *skb, int offset, start = end; } } - if (len) - BUG(); + BUG_ON(len); return csum; } @@ -1282,8 +1279,7 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, start = end; } } - if (len) - BUG(); + BUG_ON(len); return csum; } @@ -1297,8 +1293,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) else csstart = skb_headlen(skb); - if (csstart > skb_headlen(skb)) - BUG(); + BUG_ON(csstart > skb_headlen(skb)); memcpy(to, skb->data, csstart); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index be5a519cd2f8..105039eb7629 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -899,8 +899,7 @@ static void icmp_address_reply(struct sk_buff *skb) u32 _mask, *mp; mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask); - if (mp == NULL) - BUG(); + BUG_ON(mp == NULL); for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { if (*mp == ifa->ifa_mask && inet_ifa_match(rt->rt_src, ifa)) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index c49908192047..457db99c76df 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -50,9 +50,10 @@ static struct sock *idiagnl; #define INET_DIAG_PUT(skb, attrtype, attrlen) \ RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) -static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, - int ext, u32 pid, u32 seq, u16 nlmsg_flags, - const struct nlmsghdr *unlh) +static int inet_csk_diag_fill(struct sock *sk, + struct sk_buff *skb, + int ext, u32 pid, u32 seq, u16 nlmsg_flags, + const struct nlmsghdr *unlh) { const struct inet_sock *inet = inet_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); @@ -70,20 +71,22 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, nlh->nlmsg_flags = nlmsg_flags; r = NLMSG_DATA(nlh); - if (sk->sk_state != TCP_TIME_WAIT) { - if (ext & (1 << (INET_DIAG_MEMINFO - 1))) - minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, - sizeof(*minfo)); - if (ext & (1 << (INET_DIAG_INFO - 1))) - info = INET_DIAG_PUT(skb, INET_DIAG_INFO, - handler->idiag_info_size); - - if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { - size_t len = strlen(icsk->icsk_ca_ops->name); - strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), - icsk->icsk_ca_ops->name); - } + BUG_ON(sk->sk_state == TCP_TIME_WAIT); + + if (ext & (1 << (INET_DIAG_MEMINFO - 1))) + minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, sizeof(*minfo)); + + if (ext & (1 << (INET_DIAG_INFO - 1))) + info = INET_DIAG_PUT(skb, INET_DIAG_INFO, + handler->idiag_info_size); + + if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { + const size_t len = strlen(icsk->icsk_ca_ops->name); + + strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), + icsk->icsk_ca_ops->name); } + r->idiag_family = sk->sk_family; r->idiag_state = sk->sk_state; r->idiag_timer = 0; @@ -93,37 +96,6 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, r->id.idiag_cookie[0] = (u32)(unsigned long)sk; r->id.idiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1); - if (r->idiag_state == TCP_TIME_WAIT) { - const struct inet_timewait_sock *tw = inet_twsk(sk); - long tmo = tw->tw_ttd - jiffies; - if (tmo < 0) - tmo = 0; - - r->id.idiag_sport = tw->tw_sport; - r->id.idiag_dport = tw->tw_dport; - r->id.idiag_src[0] = tw->tw_rcv_saddr; - r->id.idiag_dst[0] = tw->tw_daddr; - r->idiag_state = tw->tw_substate; - r->idiag_timer = 3; - r->idiag_expires = (tmo * 1000 + HZ - 1) / HZ; - r->idiag_rqueue = 0; - r->idiag_wqueue = 0; - r->idiag_uid = 0; - r->idiag_inode = 0; -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) - if (r->idiag_family == AF_INET6) { - const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); - - ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, - &tw6->tw_v6_rcv_saddr); - ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, - &tw6->tw_v6_daddr); - } -#endif - nlh->nlmsg_len = skb->tail - b; - return skb->len; - } - r->id.idiag_sport = inet->sport; r->id.idiag_dport = inet->dport; r->id.idiag_src[0] = inet->rcv_saddr; @@ -185,7 +157,75 @@ nlmsg_failure: return -1; } -static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) +static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, + struct sk_buff *skb, int ext, u32 pid, + u32 seq, u16 nlmsg_flags, + const struct nlmsghdr *unlh) +{ + long tmo; + struct inet_diag_msg *r; + const unsigned char *previous_tail = skb->tail; + struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, + unlh->nlmsg_type, sizeof(*r)); + + r = NLMSG_DATA(nlh); + BUG_ON(tw->tw_state != TCP_TIME_WAIT); + + nlh->nlmsg_flags = nlmsg_flags; + + tmo = tw->tw_ttd - jiffies; + if (tmo < 0) + tmo = 0; + + r->idiag_family = tw->tw_family; + r->idiag_state = tw->tw_state; + r->idiag_timer = 0; + r->idiag_retrans = 0; + r->id.idiag_if = tw->tw_bound_dev_if; + r->id.idiag_cookie[0] = (u32)(unsigned long)tw; + r->id.idiag_cookie[1] = (u32)(((unsigned long)tw >> 31) >> 1); + r->id.idiag_sport = tw->tw_sport; + r->id.idiag_dport = tw->tw_dport; + r->id.idiag_src[0] = tw->tw_rcv_saddr; + r->id.idiag_dst[0] = tw->tw_daddr; + r->idiag_state = tw->tw_substate; + r->idiag_timer = 3; + r->idiag_expires = (tmo * 1000 + HZ - 1) / HZ; + r->idiag_rqueue = 0; + r->idiag_wqueue = 0; + r->idiag_uid = 0; + r->idiag_inode = 0; +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + if (tw->tw_family == AF_INET6) { + const struct inet6_timewait_sock *tw6 = + inet6_twsk((struct sock *)tw); + + ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, + &tw6->tw_v6_rcv_saddr); + ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, + &tw6->tw_v6_daddr); + } +#endif + nlh->nlmsg_len = skb->tail - previous_tail; + return skb->len; +nlmsg_failure: + skb_trim(skb, previous_tail - skb->data); + return -1; +} + +static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, + int ext, u32 pid, u32 seq, u16 nlmsg_flags, + const struct nlmsghdr *unlh) +{ + if (sk->sk_state == TCP_TIME_WAIT) + return inet_twsk_diag_fill((struct inet_timewait_sock *)sk, + skb, ext, pid, seq, nlmsg_flags, + unlh); + return inet_csk_diag_fill(sk, skb, ext, pid, seq, nlmsg_flags, unlh); +} + +static int inet_diag_get_exact(struct sk_buff *in_skb, + const struct nlmsghdr *nlh) { int err; struct sock *sk; @@ -235,7 +275,7 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nl if (!rep) goto out; - if (inet_diag_fill(rep, sk, req->idiag_ext, + if (sk_diag_fill(sk, rep, req->idiag_ext, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, 0, nlh) <= 0) BUG(); @@ -283,7 +323,7 @@ static int bitstring_match(const u32 *a1, const u32 *a2, int bits) static int inet_diag_bc_run(const void *bc, int len, - const struct inet_diag_entry *entry) + const struct inet_diag_entry *entry) { while (len > 0) { int yes = 1; @@ -322,7 +362,7 @@ static int inet_diag_bc_run(const void *bc, int len, yes = 0; break; } - + if (cond->prefix_len == 0) break; @@ -331,7 +371,8 @@ static int inet_diag_bc_run(const void *bc, int len, else addr = entry->daddr; - if (bitstring_match(addr, cond->addr, cond->prefix_len)) + if (bitstring_match(addr, cond->addr, + cond->prefix_len)) break; if (entry->family == AF_INET6 && cond->family == AF_INET) { @@ -346,7 +387,7 @@ static int inet_diag_bc_run(const void *bc, int len, } } - if (yes) { + if (yes) { len -= op->yes; bc += op->yes; } else { @@ -407,14 +448,15 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) default: return -EINVAL; } - bc += op->yes; + bc += op->yes; len -= op->yes; } return len == 0 ? 0 : -EINVAL; } -static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, - struct netlink_callback *cb) +static int inet_csk_diag_dump(struct sock *sk, + struct sk_buff *skb, + struct netlink_callback *cb) { struct inet_diag_req *r = NLMSG_DATA(cb->nlh); @@ -444,14 +486,50 @@ static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, return 0; } - return inet_diag_fill(skb, sk, r->idiag_ext, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); + return inet_csk_diag_fill(sk, skb, r->idiag_ext, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); +} + +static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, + struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct inet_diag_req *r = NLMSG_DATA(cb->nlh); + + if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { + struct inet_diag_entry entry; + struct rtattr *bc = (struct rtattr *)(r + 1); + + entry.family = tw->tw_family; +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + if (tw->tw_family == AF_INET6) { + struct inet6_timewait_sock *tw6 = + inet6_twsk((struct sock *)tw); + entry.saddr = tw6->tw_v6_rcv_saddr.s6_addr32; + entry.daddr = tw6->tw_v6_daddr.s6_addr32; + } else +#endif + { + entry.saddr = &tw->tw_rcv_saddr; + entry.daddr = &tw->tw_daddr; + } + entry.sport = tw->tw_num; + entry.dport = ntohs(tw->tw_dport); + entry.userlocks = 0; + + if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) + return 0; + } + + return inet_twsk_diag_fill(tw, skb, r->idiag_ext, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, - struct request_sock *req, - u32 pid, u32 seq, - const struct nlmsghdr *unlh) + struct request_sock *req, u32 pid, u32 seq, + const struct nlmsghdr *unlh) { const struct inet_request_sock *ireq = inet_rsk(req); struct inet_sock *inet = inet_sk(sk); @@ -504,7 +582,7 @@ nlmsg_failure: } static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, - struct netlink_callback *cb) + struct netlink_callback *cb) { struct inet_diag_entry entry; struct inet_diag_req *r = NLMSG_DATA(cb->nlh); @@ -556,7 +634,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, inet6_rsk(req)->loc_addr.s6_addr32 : #endif &ireq->loc_addr; - entry.daddr = + entry.daddr = #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) (entry.family == AF_INET6) ? inet6_rsk(req)->rmt_addr.s6_addr32 : @@ -599,7 +677,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) handler = inet_diag_table[cb->nlh->nlmsg_type]; BUG_ON(handler == NULL); hashinfo = handler->idiag_hashinfo; - + s_i = cb->args[1]; s_num = num = cb->args[2]; @@ -630,7 +708,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) cb->args[3] > 0) goto syn_recv; - if (inet_diag_dump_sock(skb, sk, cb) < 0) { + if (inet_csk_diag_dump(sk, skb, cb) < 0) { inet_listen_unlock(hashinfo); goto done; } @@ -672,7 +750,6 @@ skip_listen_ht: s_num = 0; read_lock_bh(&head->lock); - num = 0; sk_for_each(sk, node, &head->chain) { struct inet_sock *inet = inet_sk(sk); @@ -684,9 +761,10 @@ skip_listen_ht: if (r->id.idiag_sport != inet->sport && r->id.idiag_sport) goto next_normal; - if (r->id.idiag_dport != inet->dport && r->id.idiag_dport) + if (r->id.idiag_dport != inet->dport && + r->id.idiag_dport) goto next_normal; - if (inet_diag_dump_sock(skb, sk, cb) < 0) { + if (inet_csk_diag_dump(sk, skb, cb) < 0) { read_unlock_bh(&head->lock); goto done; } @@ -695,19 +773,20 @@ next_normal: } if (r->idiag_states & TCPF_TIME_WAIT) { - sk_for_each(sk, node, + struct inet_timewait_sock *tw; + + inet_twsk_for_each(tw, node, &hashinfo->ehash[i + hashinfo->ehash_size].chain) { - struct inet_sock *inet = inet_sk(sk); if (num < s_num) goto next_dying; - if (r->id.idiag_sport != inet->sport && + if (r->id.idiag_sport != tw->tw_sport && r->id.idiag_sport) goto next_dying; - if (r->id.idiag_dport != inet->dport && + if (r->id.idiag_dport != tw->tw_dport && r->id.idiag_dport) goto next_dying; - if (inet_diag_dump_sock(skb, sk, cb) < 0) { + if (inet_twsk_diag_dump(tw, skb, cb) < 0) { read_unlock_bh(&head->lock); goto done; } @@ -724,8 +803,7 @@ done: return skb->len; } -static __inline__ int -inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) +static inline int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { if (!(nlh->nlmsg_flags&NLM_F_REQUEST)) return 0; @@ -755,9 +833,8 @@ inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) } return netlink_dump_start(idiagnl, skb, nlh, inet_diag_dump, NULL); - } else { + } else return inet_diag_get_exact(skb, nlh); - } err_inval: return -EINVAL; @@ -766,15 +843,15 @@ err_inval: static inline void inet_diag_rcv_skb(struct sk_buff *skb) { - int err; - struct nlmsghdr * nlh; - if (skb->len >= NLMSG_SPACE(0)) { - nlh = (struct nlmsghdr *)skb->data; - if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) + int err; + struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data; + + if (nlh->nlmsg_len < sizeof(*nlh) || + skb->len < nlh->nlmsg_len) return; err = inet_diag_rcv_msg(skb, nlh); - if (err || nlh->nlmsg_flags & NLM_F_ACK) + if (err || nlh->nlmsg_flags & NLM_F_ACK) netlink_ack(skb, nlh, err); } } diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index ce5fe3f74a3d..2160874ce7aa 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -304,8 +304,7 @@ static void unlink_from_pool(struct inet_peer *p) /* look for a node to insert instead of p */ struct inet_peer *t; t = lookup_rightempty(p); - if (*stackptr[-1] != t) - BUG(); + BUG_ON(*stackptr[-1] != t); **--stackptr = t->avl_left; /* t is removed, t->v4daddr > x->v4daddr for any * x in p->avl_left subtree. @@ -314,8 +313,7 @@ static void unlink_from_pool(struct inet_peer *p) t->avl_left = p->avl_left; t->avl_right = p->avl_right; t->avl_height = p->avl_height; - if (delp[1] != &p->avl_left) - BUG(); + BUG_ON(delp[1] != &p->avl_left); delp[1] = &t->avl_left; /* was &p->avl_left */ } peer_avl_rebalance(stack, stackptr); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index de16e944777f..1e93eafa7af1 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -188,7 +188,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key) } if (ipgre_fb_tunnel_dev->flags&IFF_UP) - return ipgre_fb_tunnel_dev->priv; + return netdev_priv(ipgre_fb_tunnel_dev); return NULL; } @@ -278,7 +278,7 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int return NULL; dev->init = ipgre_tunnel_init; - nt = dev->priv; + nt = netdev_priv(dev); nt->parms = *parms; if (register_netdevice(dev) < 0) { @@ -286,9 +286,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int goto failed; } - nt = dev->priv; - nt->parms = *parms; - dev_hold(dev); ipgre_tunnel_link(nt); return nt; @@ -299,7 +296,7 @@ failed: static void ipgre_tunnel_uninit(struct net_device *dev) { - ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv); + ipgre_tunnel_unlink(netdev_priv(dev)); dev_put(dev); } @@ -518,7 +515,7 @@ out: skb2->dst->ops->update_pmtu(skb2->dst, rel_info); rel_info = htonl(rel_info); } else if (type == ICMP_TIME_EXCEEDED) { - struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv; + struct ip_tunnel *t = netdev_priv(skb2->dev); if (t->parms.iph.ttl) { rel_type = ICMP_DEST_UNREACH; rel_code = ICMP_HOST_UNREACH; @@ -669,7 +666,7 @@ drop_nolock: static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct net_device_stats *stats = &tunnel->stat; struct iphdr *old_iph = skb->nh.iph; struct iphdr *tiph; @@ -915,7 +912,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t = ipgre_tunnel_locate(&p, 0); } if (t == NULL) - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); memcpy(&p, &t->parms, sizeof(p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) err = -EFAULT; @@ -955,7 +952,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) } else { unsigned nflags=0; - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); if (MULTICAST(p.iph.daddr)) nflags = IFF_BROADCAST; @@ -1004,7 +1001,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if ((t = ipgre_tunnel_locate(&p, 0)) == NULL) goto done; err = -EPERM; - if (t == ipgre_fb_tunnel_dev->priv) + if (t == netdev_priv(ipgre_fb_tunnel_dev)) goto done; dev = t->dev; } @@ -1021,12 +1018,12 @@ done: static struct net_device_stats *ipgre_tunnel_get_stats(struct net_device *dev) { - return &(((struct ip_tunnel*)dev->priv)->stat); + return &(((struct ip_tunnel*)netdev_priv(dev))->stat); } static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); if (new_mtu < 68 || new_mtu > 0xFFF8 - tunnel->hlen) return -EINVAL; dev->mtu = new_mtu; @@ -1066,7 +1063,7 @@ static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { - struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *t = netdev_priv(dev); struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen); u16 *p = (u16*)(iph+1); @@ -1093,7 +1090,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned sh static int ipgre_open(struct net_device *dev) { - struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *t = netdev_priv(dev); if (MULTICAST(t->parms.iph.daddr)) { struct flowi fl = { .oif = t->parms.link, @@ -1117,7 +1114,7 @@ static int ipgre_open(struct net_device *dev) static int ipgre_close(struct net_device *dev) { - struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *t = netdev_priv(dev); if (MULTICAST(t->parms.iph.daddr) && t->mlink) { struct in_device *in_dev = inetdev_by_index(t->mlink); if (in_dev) { @@ -1157,7 +1154,7 @@ static int ipgre_tunnel_init(struct net_device *dev) int mtu = ETH_DATA_LEN; int addend = sizeof(struct iphdr) + 4; - tunnel = (struct ip_tunnel*)dev->priv; + tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; tunnel->dev = dev; @@ -1221,7 +1218,7 @@ static int ipgre_tunnel_init(struct net_device *dev) static int __init ipgre_fb_tunnel_init(struct net_device *dev) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; tunnel->dev = dev; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index c2169b47ddfd..3324fbfe528a 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -69,6 +69,7 @@ #include <net/ip.h> #include <net/protocol.h> #include <net/route.h> +#include <net/xfrm.h> #include <linux/skbuff.h> #include <net/sock.h> #include <net/arp.h> diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index bbd85f5ec985..bc5ca23b2646 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -244,7 +244,7 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c if (dev == NULL) return NULL; - nt = dev->priv; + nt = netdev_priv(dev); SET_MODULE_OWNER(dev); dev->init = ipip_tunnel_init; nt->parms = *parms; @@ -269,7 +269,7 @@ static void ipip_tunnel_uninit(struct net_device *dev) tunnels_wc[0] = NULL; write_unlock_bh(&ipip_lock); } else - ipip_tunnel_unlink((struct ip_tunnel*)dev->priv); + ipip_tunnel_unlink(netdev_priv(dev)); dev_put(dev); } @@ -443,7 +443,7 @@ out: skb2->dst->ops->update_pmtu(skb2->dst, rel_info); rel_info = htonl(rel_info); } else if (type == ICMP_TIME_EXCEEDED) { - struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv; + struct ip_tunnel *t = netdev_priv(skb2->dev); if (t->parms.iph.ttl) { rel_type = ICMP_DEST_UNREACH; rel_code = ICMP_HOST_UNREACH; @@ -514,7 +514,7 @@ out: static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct net_device_stats *stats = &tunnel->stat; struct iphdr *tiph = &tunnel->parms.iph; u8 tos = tunnel->parms.iph.tos; @@ -674,7 +674,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t = ipip_tunnel_locate(&p, 0); } if (t == NULL) - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); memcpy(&p, &t->parms, sizeof(p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) err = -EFAULT; @@ -711,7 +711,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EINVAL; break; } - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); ipip_tunnel_unlink(t); t->parms.iph.saddr = p.iph.saddr; t->parms.iph.daddr = p.iph.daddr; @@ -765,7 +765,7 @@ done: static struct net_device_stats *ipip_tunnel_get_stats(struct net_device *dev) { - return &(((struct ip_tunnel*)dev->priv)->stat); + return &(((struct ip_tunnel*)netdev_priv(dev))->stat); } static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu) @@ -800,7 +800,7 @@ static int ipip_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel; struct iphdr *iph; - tunnel = (struct ip_tunnel*)dev->priv; + tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; tunnel->dev = dev; @@ -838,7 +838,7 @@ static int ipip_tunnel_init(struct net_device *dev) static int __init ipip_fb_tunnel_init(struct net_device *dev) { - struct ip_tunnel *tunnel = dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; tunnel->dev = dev; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 9a5c0ce7ff35..f58ac9854c3f 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -178,8 +178,8 @@ static int reg_vif_num = -1; static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) { read_lock(&mrt_lock); - ((struct net_device_stats*)dev->priv)->tx_bytes += skb->len; - ((struct net_device_stats*)dev->priv)->tx_packets++; + ((struct net_device_stats*)netdev_priv(dev))->tx_bytes += skb->len; + ((struct net_device_stats*)netdev_priv(dev))->tx_packets++; ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT); read_unlock(&mrt_lock); kfree_skb(skb); @@ -188,7 +188,7 @@ static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) static struct net_device_stats *reg_vif_get_stats(struct net_device *dev) { - return (struct net_device_stats*)dev->priv; + return (struct net_device_stats*)netdev_priv(dev); } static void reg_vif_setup(struct net_device *dev) @@ -1149,8 +1149,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) if (vif->flags & VIFF_REGISTER) { vif->pkt_out++; vif->bytes_out+=skb->len; - ((struct net_device_stats*)vif->dev->priv)->tx_bytes += skb->len; - ((struct net_device_stats*)vif->dev->priv)->tx_packets++; + ((struct net_device_stats*)netdev_priv(vif->dev))->tx_bytes += skb->len; + ((struct net_device_stats*)netdev_priv(vif->dev))->tx_packets++; ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT); kfree_skb(skb); return; @@ -1210,8 +1210,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) if (vif->flags & VIFF_TUNNEL) { ip_encap(skb, vif->local, vif->remote); /* FIXME: extra output firewall step used to be here. --RR */ - ((struct ip_tunnel *)vif->dev->priv)->stat.tx_packets++; - ((struct ip_tunnel *)vif->dev->priv)->stat.tx_bytes+=skb->len; + ((struct ip_tunnel *)netdev_priv(vif->dev))->stat.tx_packets++; + ((struct ip_tunnel *)netdev_priv(vif->dev))->stat.tx_bytes+=skb->len; } IPCB(skb)->flags |= IPSKB_FORWARDED; @@ -1467,8 +1467,8 @@ int pim_rcv_v1(struct sk_buff * skb) skb->pkt_type = PACKET_HOST; dst_release(skb->dst); skb->dst = NULL; - ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len; - ((struct net_device_stats*)reg_dev->priv)->rx_packets++; + ((struct net_device_stats*)netdev_priv(reg_dev))->rx_bytes += skb->len; + ((struct net_device_stats*)netdev_priv(reg_dev))->rx_packets++; nf_reset(skb); netif_rx(skb); dev_put(reg_dev); @@ -1522,8 +1522,8 @@ static int pim_rcv(struct sk_buff * skb) skb->ip_summed = 0; skb->pkt_type = PACKET_HOST; dst_release(skb->dst); - ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len; - ((struct net_device_stats*)reg_dev->priv)->rx_packets++; + ((struct net_device_stats*)netdev_priv(reg_dev))->rx_bytes += skb->len; + ((struct net_device_stats*)netdev_priv(reg_dev))->rx_packets++; skb->dst = NULL; nf_reset(skb); netif_rx(skb); diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index e7fa29e576dc..77f304680d86 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -995,7 +995,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, || (!test_bit(IPS_ASSURED_BIT, &conntrack->status) && conntrack->proto.tcp.last_index == TCP_ACK_SET)) && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) { - /* RST sent to invalid SYN or ACK we had let trough + /* RST sent to invalid SYN or ACK we had let through * at a) and c) above: * * a) SYN was in window then @@ -1006,7 +1006,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, * segments we ignored. */ goto in_window; } - /* Just fall trough */ + /* Just fall through */ default: /* Keep compilers happy. */ break; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0a461232329f..a97ed5416c28 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3347,7 +3347,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, int offset = start - TCP_SKB_CB(skb)->seq; int size = TCP_SKB_CB(skb)->end_seq - start; - if (offset < 0) BUG(); + BUG_ON(offset < 0); if (size > 0) { size = min(copy, size); if (skb_copy_bits(skb, offset, skb_put(nskb, size), size)) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index b4c4beba0ede..efa3e72cfcfa 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -226,6 +226,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); ipv6_addr_copy(&hdr->daddr, first_hop); + skb->priority = sk->sk_priority; + mtu = dst_mtu(dst); if ((skb->len <= mtu) || ipfragok) { IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); @@ -1182,6 +1184,8 @@ int ip6_push_pending_frames(struct sock *sk) ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); ipv6_addr_copy(&hdr->daddr, final_dst); + skb->priority = sk->sk_priority; + skb->dst = dst_clone(&rt->u.dst); IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index f079621c8b67..c3c2bf699a67 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -243,7 +243,7 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) if (dev == NULL) return -ENOMEM; - t = dev->priv; + t = netdev_priv(dev); dev->init = ip6ip6_tnl_dev_init; t->parms = *p; @@ -308,7 +308,7 @@ ip6ip6_tnl_locate(struct ip6_tnl_parm *p, struct ip6_tnl **pt, int create) static void ip6ip6_tnl_dev_uninit(struct net_device *dev) { - struct ip6_tnl *t = dev->priv; + struct ip6_tnl *t = netdev_priv(dev); if (dev == ip6ip6_fb_tnl_dev) { write_lock_bh(&ip6ip6_lock); @@ -623,7 +623,7 @@ ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) static int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; + struct ip6_tnl *t = netdev_priv(dev); struct net_device_stats *stats = &t->stat; struct ipv6hdr *ipv6h = skb->nh.ipv6h; struct ipv6_txoptions *opt = NULL; @@ -933,11 +933,11 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; } if ((err = ip6ip6_tnl_locate(&p, &t, 0)) == -ENODEV) - t = (struct ip6_tnl *) dev->priv; + t = netdev_priv(dev); else if (err) break; } else - t = (struct ip6_tnl *) dev->priv; + t = netdev_priv(dev); memcpy(&p, &t->parms, sizeof (p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { @@ -955,7 +955,7 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; } if (!create && dev != ip6ip6_fb_tnl_dev) { - t = (struct ip6_tnl *) dev->priv; + t = netdev_priv(dev); } if (!t && (err = ip6ip6_tnl_locate(&p, &t, create))) { break; @@ -991,12 +991,12 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) err = ip6ip6_tnl_locate(&p, &t, 0); if (err) break; - if (t == ip6ip6_fb_tnl_dev->priv) { + if (t == netdev_priv(ip6ip6_fb_tnl_dev)) { err = -EPERM; break; } } else { - t = (struct ip6_tnl *) dev->priv; + t = netdev_priv(dev); } err = unregister_netdevice(t->dev); break; @@ -1016,7 +1016,7 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static struct net_device_stats * ip6ip6_tnl_get_stats(struct net_device *dev) { - return &(((struct ip6_tnl *) dev->priv)->stat); + return &(((struct ip6_tnl *)netdev_priv(dev))->stat); } /** @@ -1073,7 +1073,7 @@ static void ip6ip6_tnl_dev_setup(struct net_device *dev) static inline void ip6ip6_tnl_dev_init_gen(struct net_device *dev) { - struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; + struct ip6_tnl *t = netdev_priv(dev); t->fl.proto = IPPROTO_IPV6; t->dev = dev; strcpy(t->parms.name, dev->name); @@ -1087,7 +1087,7 @@ ip6ip6_tnl_dev_init_gen(struct net_device *dev) static int ip6ip6_tnl_dev_init(struct net_device *dev) { - struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; + struct ip6_tnl *t = netdev_priv(dev); ip6ip6_tnl_dev_init_gen(dev); ip6ip6_tnl_link_config(t); return 0; @@ -1103,7 +1103,7 @@ ip6ip6_tnl_dev_init(struct net_device *dev) static int ip6ip6_fb_tnl_dev_init(struct net_device *dev) { - struct ip6_tnl *t = dev->priv; + struct ip6_tnl *t = netdev_priv(dev); ip6ip6_tnl_dev_init_gen(dev); dev_hold(dev); tnls_wc[0] = t; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 02872ae8a439..0dae48aa1cec 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -184,7 +184,7 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int if (dev == NULL) return NULL; - nt = dev->priv; + nt = netdev_priv(dev); dev->init = ipip6_tunnel_init; nt->parms = *parms; @@ -210,7 +210,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) write_unlock_bh(&ipip6_lock); dev_put(dev); } else { - ipip6_tunnel_unlink((struct ip_tunnel*)dev->priv); + ipip6_tunnel_unlink(netdev_priv(dev)); dev_put(dev); } } @@ -346,7 +346,7 @@ out: rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0); if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { - struct ip_tunnel * t = (struct ip_tunnel*)rt6i->rt6i_dev->priv; + struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) { rel_type = ICMPV6_DEST_UNREACH; rel_code = ICMPV6_ADDR_UNREACH; @@ -424,7 +424,7 @@ static inline u32 try_6to4(struct in6_addr *v6dst) static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct net_device_stats *stats = &tunnel->stat; struct iphdr *tiph = &tunnel->parms.iph; struct ipv6hdr *iph6 = skb->nh.ipv6h; @@ -610,7 +610,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t = ipip6_tunnel_locate(&p, 0); } if (t == NULL) - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); memcpy(&p, &t->parms, sizeof(p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) err = -EFAULT; @@ -647,7 +647,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EINVAL; break; } - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); ipip6_tunnel_unlink(t); t->parms.iph.saddr = p.iph.saddr; t->parms.iph.daddr = p.iph.daddr; @@ -683,7 +683,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if ((t = ipip6_tunnel_locate(&p, 0)) == NULL) goto done; err = -EPERM; - if (t == ipip6_fb_tunnel_dev->priv) + if (t == netdev_priv(ipip6_fb_tunnel_dev)) goto done; dev = t->dev; } @@ -700,7 +700,7 @@ done: static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev) { - return &(((struct ip_tunnel*)dev->priv)->stat); + return &(((struct ip_tunnel*)netdev_priv(dev))->stat); } static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) @@ -735,7 +735,7 @@ static int ipip6_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel; struct iphdr *iph; - tunnel = (struct ip_tunnel*)dev->priv; + tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; tunnel->dev = dev; @@ -775,7 +775,7 @@ static int ipip6_tunnel_init(struct net_device *dev) static int __init ipip6_fb_tunnel_init(struct net_device *dev) { - struct ip_tunnel *tunnel = dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; tunnel->dev = dev; diff --git a/net/key/af_key.c b/net/key/af_key.c index 52efd04cbedb..4c2f6d694f88 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -297,8 +297,7 @@ static int pfkey_error(struct sadb_msg *orig, int err, struct sock *sk) err = EINTR; if (err >= 512) err = EINVAL; - if (err <= 0 || err >= 256) - BUG(); + BUG_ON(err <= 0 || err >= 256); hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg)); pfkey_hdr_dup(hdr, orig); diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 6167137a5cb5..9a1348a51a0d 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -988,7 +988,7 @@ static int tcp_packet(struct nf_conn *conntrack, || (!test_bit(IPS_ASSURED_BIT, &conntrack->status) && conntrack->proto.tcp.last_index == TCP_ACK_SET)) && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) { - /* RST sent to invalid SYN or ACK we had let trough + /* RST sent to invalid SYN or ACK we had let through * at a) and c) above: * * a) SYN was in window then @@ -999,7 +999,7 @@ static int tcp_packet(struct nf_conn *conntrack, * segments we ignored. */ goto in_window; } - /* Just fall trough */ + /* Just fall through */ default: /* Keep compilers happy. */ break; diff --git a/net/sched/Makefile b/net/sched/Makefile index e48d0d456b3e..0f06aec66094 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -7,13 +7,13 @@ obj-y := sch_generic.o obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o sch_blackhole.o obj-$(CONFIG_NET_CLS) += cls_api.o obj-$(CONFIG_NET_CLS_ACT) += act_api.o -obj-$(CONFIG_NET_ACT_POLICE) += police.o -obj-$(CONFIG_NET_CLS_POLICE) += police.o -obj-$(CONFIG_NET_ACT_GACT) += gact.o -obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o -obj-$(CONFIG_NET_ACT_IPT) += ipt.o -obj-$(CONFIG_NET_ACT_PEDIT) += pedit.o -obj-$(CONFIG_NET_ACT_SIMP) += simple.o +obj-$(CONFIG_NET_ACT_POLICE) += act_police.o +obj-$(CONFIG_NET_CLS_POLICE) += act_police.o +obj-$(CONFIG_NET_ACT_GACT) += act_gact.o +obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o +obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o +obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o +obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 2ce1cb2aa2ed..792ce59940ec 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -165,7 +165,7 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action *act, while ((a = act) != NULL) { repeat: if (a->ops && a->ops->act) { - ret = a->ops->act(&skb, a, res); + ret = a->ops->act(skb, a, res); if (TC_MUNGED & skb->tc_verd) { /* copied already, allow trampling */ skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd); @@ -290,7 +290,7 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est, if (a_o == NULL) { #ifdef CONFIG_KMOD rtnl_unlock(); - request_module(act_name); + request_module("act_%s", act_name); rtnl_lock(); a_o = tc_lookup_action_n(act_name); diff --git a/net/sched/gact.c b/net/sched/act_gact.c index d1c6d542912a..a1e68f78dcc2 100644 --- a/net/sched/gact.c +++ b/net/sched/act_gact.c @@ -135,10 +135,9 @@ tcf_gact_cleanup(struct tc_action *a, int bind) } static int -tcf_gact(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { struct tcf_gact *p = PRIV(a, gact); - struct sk_buff *skb = *pskb; int action = TC_ACT_SHOT; spin_lock(&p->lock); diff --git a/net/sched/ipt.c b/net/sched/act_ipt.c index f50136eed211..b5001939b74b 100644 --- a/net/sched/ipt.c +++ b/net/sched/act_ipt.c @@ -201,11 +201,10 @@ tcf_ipt_cleanup(struct tc_action *a, int bind) } static int -tcf_ipt(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { int ret = 0, result = 0; struct tcf_ipt *p = PRIV(a, ipt); - struct sk_buff *skb = *pskb; if (skb_cloned(skb)) { if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) @@ -222,6 +221,9 @@ tcf_ipt(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) worry later - danger - this API seems to have changed from earlier kernels */ + /* iptables targets take a double skb pointer in case the skb + * needs to be replaced. We don't own the skb, so this must not + * happen. The pskb_expand_head above should make sure of this */ ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, p->hook, p->t->data, NULL); switch (ret) { diff --git a/net/sched/mirred.c b/net/sched/act_mirred.c index 20d06916dc0b..4fcccbd50885 100644 --- a/net/sched/mirred.c +++ b/net/sched/act_mirred.c @@ -158,12 +158,11 @@ tcf_mirred_cleanup(struct tc_action *a, int bind) } static int -tcf_mirred(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { struct tcf_mirred *p = PRIV(a, mirred); struct net_device *dev; struct sk_buff *skb2 = NULL; - struct sk_buff *skb = *pskb; u32 at = G_TC_AT(skb->tc_verd); spin_lock(&p->lock); diff --git a/net/sched/pedit.c b/net/sched/act_pedit.c index 767d24f4610e..1742a68e0122 100644 --- a/net/sched/pedit.c +++ b/net/sched/act_pedit.c @@ -130,10 +130,9 @@ tcf_pedit_cleanup(struct tc_action *a, int bind) } static int -tcf_pedit(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { struct tcf_pedit *p = PRIV(a, pedit); - struct sk_buff *skb = *pskb; int i, munged = 0; u8 *pptr; @@ -246,10 +245,12 @@ tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref) t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); t.expires = jiffies_to_clock_t(p->tm.expires); RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t); + kfree(opt); return skb->len; rtattr_failure: skb_trim(skb, b - skb->data); + kfree(opt); return -1; } diff --git a/net/sched/police.c b/net/sched/act_police.c index eb39fb2f39b6..fa877f8f652c 100644 --- a/net/sched/police.c +++ b/net/sched/act_police.c @@ -284,11 +284,10 @@ static int tcf_act_police_cleanup(struct tc_action *a, int bind) return 0; } -static int tcf_act_police(struct sk_buff **pskb, struct tc_action *a, +static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { psched_time_t now; - struct sk_buff *skb = *pskb; struct tcf_police *p = PRIV(a); long toks; long ptoks = 0; @@ -408,7 +407,7 @@ police_cleanup_module(void) module_init(police_init_module); module_exit(police_cleanup_module); -#endif +#else /* CONFIG_NET_CLS_ACT */ struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est) { @@ -545,6 +544,7 @@ int tcf_police(struct sk_buff *skb, struct tcf_police *p) spin_unlock(&p->lock); return p->action; } +EXPORT_SYMBOL(tcf_police); int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p) { @@ -601,13 +601,4 @@ errout: return -1; } - -EXPORT_SYMBOL(tcf_police); -EXPORT_SYMBOL(tcf_police_destroy); -EXPORT_SYMBOL(tcf_police_dump); -EXPORT_SYMBOL(tcf_police_dump_stats); -EXPORT_SYMBOL(tcf_police_hash); -EXPORT_SYMBOL(tcf_police_ht); -EXPORT_SYMBOL(tcf_police_locate); -EXPORT_SYMBOL(tcf_police_lookup); -EXPORT_SYMBOL(tcf_police_new_index); +#endif /* CONFIG_NET_CLS_ACT */ diff --git a/net/sched/simple.c b/net/sched/act_simple.c index 8a6ae4f491e8..e5f2e1f431e2 100644 --- a/net/sched/simple.c +++ b/net/sched/act_simple.c @@ -44,9 +44,8 @@ static DEFINE_RWLOCK(simp_lock); #include <net/pkt_act.h> #include <net/act_generic.h> -static int tcf_simp(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { - struct sk_buff *skb = *pskb; struct tcf_defact *p = PRIV(a, defact); spin_lock(&p->lock); diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 09453f997d8c..6cd81708bf71 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -257,7 +257,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) (cl = cbq_class_lookup(q, prio)) != NULL) return cl; - *qerr = NET_XMIT_DROP; + *qerr = NET_XMIT_BYPASS; for (;;) { int result = 0; defmap = head->defaults; @@ -413,7 +413,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->rx_class = cl; #endif if (cl == NULL) { - if (ret == NET_XMIT_DROP) + if (ret == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index c26764bc4103..91132f6871d7 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -208,7 +208,7 @@ struct hfsc_sched do { \ struct timeval tv; \ do_gettimeofday(&tv); \ - (stamp) = 1000000ULL * tv.tv_sec + tv.tv_usec; \ + (stamp) = 1ULL * USEC_PER_SEC * tv.tv_sec + tv.tv_usec; \ } while (0) #endif @@ -502,8 +502,8 @@ d2dx(u32 d) u64 dx; dx = ((u64)d * PSCHED_JIFFIE2US(HZ)); - dx += 1000000 - 1; - do_div(dx, 1000000); + dx += USEC_PER_SEC - 1; + do_div(dx, USEC_PER_SEC); return dx; } @@ -523,7 +523,7 @@ dx2d(u64 dx) { u64 d; - d = dx * 1000000; + d = dx * USEC_PER_SEC; do_div(d, PSCHED_JIFFIE2US(HZ)); return (u32)d; } @@ -1227,7 +1227,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) if (cl->level == 0) return cl; - *qerr = NET_XMIT_DROP; + *qerr = NET_XMIT_BYPASS; tcf = q->root.filter_list; while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) { #ifdef CONFIG_NET_CLS_ACT @@ -1643,7 +1643,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch) cl = hfsc_classify(skb, sch, &err); if (cl == NULL) { - if (err == NET_XMIT_DROP) + if (err == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return err; diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 558cc087e602..3ec95df4a85e 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -321,7 +321,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, in if ((cl = htb_find(skb->priority,sch)) != NULL && cl->level == 0) return cl; - *qerr = NET_XMIT_DROP; + *qerr = NET_XMIT_BYPASS; tcf = q->filter_list; while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) { #ifdef CONFIG_NET_CLS_ACT @@ -724,7 +724,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) } #ifdef CONFIG_NET_CLS_ACT } else if (!cl) { - if (ret == NET_XMIT_DROP) + if (ret == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb (skb); return ret; diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 3ac0f495bad0..5b3a3e48ed92 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -54,7 +54,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) u32 band = skb->priority; struct tcf_result res; - *qerr = NET_XMIT_DROP; + *qerr = NET_XMIT_BYPASS; if (TC_H_MAJ(skb->priority) != sch->handle) { #ifdef CONFIG_NET_CLS_ACT switch (tc_classify(skb, q->filter_list, &res)) { @@ -91,7 +91,8 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch) qdisc = prio_classify(skb, sch, &ret); #ifdef CONFIG_NET_CLS_ACT if (qdisc == NULL) { - if (ret == NET_XMIT_DROP) + + if (ret == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; @@ -118,7 +119,7 @@ prio_requeue(struct sk_buff *skb, struct Qdisc* sch) qdisc = prio_classify(skb, sch, &ret); #ifdef CONFIG_NET_CLS_ACT if (qdisc == NULL) { - if (ret == NET_XMIT_DROP) + if (ret == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index c4a2a8c4c339..79b8ef34c6e4 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -274,7 +274,7 @@ teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *de static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) { - struct teql_master *master = (void*)dev->priv; + struct teql_master *master = netdev_priv(dev); struct Qdisc *start, *q; int busy; int nores; @@ -350,7 +350,7 @@ drop: static int teql_master_open(struct net_device *dev) { struct Qdisc * q; - struct teql_master *m = (void*)dev->priv; + struct teql_master *m = netdev_priv(dev); int mtu = 0xFFFE; unsigned flags = IFF_NOARP|IFF_MULTICAST; @@ -397,13 +397,13 @@ static int teql_master_close(struct net_device *dev) static struct net_device_stats *teql_master_stats(struct net_device *dev) { - struct teql_master *m = (void*)dev->priv; + struct teql_master *m = netdev_priv(dev); return &m->stats; } static int teql_master_mtu(struct net_device *dev, int new_mtu) { - struct teql_master *m = (void*)dev->priv; + struct teql_master *m = netdev_priv(dev); struct Qdisc *q; if (new_mtu < 68) @@ -423,7 +423,7 @@ static int teql_master_mtu(struct net_device *dev, int new_mtu) static __init void teql_master_setup(struct net_device *dev) { - struct teql_master *master = dev->priv; + struct teql_master *master = netdev_priv(dev); struct Qdisc_ops *ops = &master->qops; master->dev = dev; @@ -476,7 +476,7 @@ static int __init teql_init(void) break; } - master = dev->priv; + master = netdev_priv(dev); strlcpy(master->qops.id, dev->name, IFNAMSIZ); err = register_qdisc(&master->qops); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 2d7d8a5db2ac..b8b38aba92b3 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1250,8 +1250,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, case SCTP_CMD_TIMER_START: timer = &asoc->timers[cmd->obj.to]; timeout = asoc->timeouts[cmd->obj.to]; - if (!timeout) - BUG(); + BUG_ON(!timeout); timer->expires = jiffies + timeout; sctp_association_hold(asoc); diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index f509e9992767..dcaa0c4453ff 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -575,12 +575,11 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) if (rp->q.list.next == &cd->queue) { spin_unlock(&queue_lock); up(&queue_io_sem); - if (rp->offset) - BUG(); + BUG_ON(rp->offset); return 0; } rq = container_of(rp->q.list.next, struct cache_request, q.list); - if (rq->q.reader) BUG(); + BUG_ON(rq->q.reader); if (rp->offset == 0) rq->readers++; spin_unlock(&queue_lock); diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index e14c1cae7460..9764c80ab0b2 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -69,13 +69,13 @@ rpc_timeout_upcall_queue(void *data) struct rpc_inode *rpci = (struct rpc_inode *)data; struct inode *inode = &rpci->vfs_inode; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (rpci->ops == NULL) goto out; if (rpci->nreaders == 0 && !list_empty(&rpci->pipe)) __rpc_purge_upcall(inode, -ETIMEDOUT); out: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } int @@ -84,7 +84,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) struct rpc_inode *rpci = RPC_I(inode); int res = -EPIPE; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (rpci->ops == NULL) goto out; if (rpci->nreaders) { @@ -100,7 +100,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) res = 0; } out: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); wake_up(&rpci->waitq); return res; } @@ -116,7 +116,7 @@ rpc_close_pipes(struct inode *inode) { struct rpc_inode *rpci = RPC_I(inode); - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (rpci->ops != NULL) { rpci->nreaders = 0; __rpc_purge_list(rpci, &rpci->in_upcall, -EPIPE); @@ -127,7 +127,7 @@ rpc_close_pipes(struct inode *inode) rpci->ops = NULL; } rpc_inode_setowner(inode, NULL); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); cancel_delayed_work(&rpci->queue_timeout); flush_scheduled_work(); } @@ -154,7 +154,7 @@ rpc_pipe_open(struct inode *inode, struct file *filp) struct rpc_inode *rpci = RPC_I(inode); int res = -ENXIO; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (rpci->ops != NULL) { if (filp->f_mode & FMODE_READ) rpci->nreaders ++; @@ -162,7 +162,7 @@ rpc_pipe_open(struct inode *inode, struct file *filp) rpci->nwriters ++; res = 0; } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return res; } @@ -172,7 +172,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) struct rpc_inode *rpci = RPC_I(inode); struct rpc_pipe_msg *msg; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (rpci->ops == NULL) goto out; msg = (struct rpc_pipe_msg *)filp->private_data; @@ -190,7 +190,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) if (rpci->ops->release_pipe) rpci->ops->release_pipe(inode); out: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return 0; } @@ -202,7 +202,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) struct rpc_pipe_msg *msg; int res = 0; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); if (rpci->ops == NULL) { res = -EPIPE; goto out_unlock; @@ -229,7 +229,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) rpci->ops->destroy_msg(msg); } out_unlock: - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return res; } @@ -240,11 +240,11 @@ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *of struct rpc_inode *rpci = RPC_I(inode); int res; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); res = -EPIPE; if (rpci->ops != NULL) res = rpci->ops->downcall(filp, buf, len); - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); return res; } @@ -322,7 +322,7 @@ rpc_info_open(struct inode *inode, struct file *file) if (!ret) { struct seq_file *m = file->private_data; - down(&inode->i_sem); + mutex_lock(&inode->i_mutex); clnt = RPC_I(inode)->private; if (clnt) { atomic_inc(&clnt->cl_users); @@ -331,7 +331,7 @@ rpc_info_open(struct inode *inode, struct file *file) single_release(inode, file); ret = -EINVAL; } - up(&inode->i_sem); + mutex_unlock(&inode->i_mutex); } return ret; } @@ -491,7 +491,7 @@ rpc_depopulate(struct dentry *parent) struct dentry *dentry, *dvec[10]; int n = 0; - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); repeat: spin_lock(&dcache_lock); list_for_each_safe(pos, next, &parent->d_subdirs) { @@ -519,7 +519,7 @@ repeat: } while (n); goto repeat; } - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); } static int @@ -532,7 +532,7 @@ rpc_populate(struct dentry *parent, struct dentry *dentry; int mode, i; - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); for (i = start; i < eof; i++) { dentry = d_alloc_name(parent, files[i].name); if (!dentry) @@ -552,10 +552,10 @@ rpc_populate(struct dentry *parent, dir->i_nlink++; d_add(dentry, inode); } - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); return 0; out_bad: - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); printk(KERN_WARNING "%s: %s failed to populate directory %s\n", __FILE__, __FUNCTION__, parent->d_name.name); return -ENOMEM; @@ -609,7 +609,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) if ((error = rpc_lookup_parent(path, nd)) != 0) return ERR_PTR(error); dir = nd->dentry->d_inode; - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); dentry = lookup_hash(nd); if (IS_ERR(dentry)) goto out_err; @@ -620,7 +620,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) } return dentry; out_err: - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); rpc_release_path(nd); return dentry; } @@ -646,7 +646,7 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client) if (error) goto err_depopulate; out: - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); rpc_release_path(&nd); return dentry; err_depopulate: @@ -671,7 +671,7 @@ rpc_rmdir(char *path) if ((error = rpc_lookup_parent(path, &nd)) != 0) return error; dir = nd.dentry->d_inode; - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); dentry = lookup_hash(&nd); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); @@ -681,7 +681,7 @@ rpc_rmdir(char *path) error = __rpc_rmdir(dir, dentry); dput(dentry); out_release: - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); rpc_release_path(&nd); return error; } @@ -710,7 +710,7 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags) rpci->ops = ops; inode_dir_notify(dir, DN_CREATE); out: - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); rpc_release_path(&nd); return dentry; err_dput: @@ -732,7 +732,7 @@ rpc_unlink(char *path) if ((error = rpc_lookup_parent(path, &nd)) != 0) return error; dir = nd.dentry->d_inode; - down(&dir->i_sem); + mutex_lock(&dir->i_mutex); dentry = lookup_hash(&nd); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); @@ -746,7 +746,7 @@ rpc_unlink(char *path) dput(dentry); inode_dir_notify(dir, DN_DELETE); out_release: - up(&dir->i_sem); + mutex_unlock(&dir->i_mutex); rpc_release_path(&nd); return error; } diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e4296c8b861e..b19cc26fa9c2 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -122,8 +122,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) rqstp->rq_argused = 0; rqstp->rq_resused = 0; arghi = 0; - if (pages > RPCSVC_MAXPAGES) - BUG(); + BUG_ON(pages > RPCSVC_MAXPAGES); while (pages) { struct page *p = alloc_page(GFP_KERNEL); if (!p) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 5f6ae79b8b16..1b5989b1b670 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -784,7 +784,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0); if (err) goto out_mknod_dput; - up(&nd.dentry->d_inode->i_sem); + mutex_unlock(&nd.dentry->d_inode->i_mutex); dput(nd.dentry); nd.dentry = dentry; @@ -823,7 +823,7 @@ out: out_mknod_dput: dput(dentry); out_mknod_unlock: - up(&nd.dentry->d_inode->i_sem); + mutex_unlock(&nd.dentry->d_inode->i_mutex); path_release(&nd); out_mknod_parent: if (err==-EEXIST) diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 2f4531fcaca2..6ed3302312fb 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -540,8 +540,7 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, start = end; } } - if (len) - BUG(); + BUG_ON(len); } EXPORT_SYMBOL_GPL(skb_icv_walk); @@ -610,8 +609,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) start = end; } } - if (len) - BUG(); + BUG_ON(len); return elt; } EXPORT_SYMBOL_GPL(skb_to_sgvec); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 59614a994b4e..077bbf9fb9b7 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -248,11 +248,9 @@ EXPORT_SYMBOL(xfrm_policy_alloc); void __xfrm_policy_destroy(struct xfrm_policy *policy) { - if (!policy->dead) - BUG(); + BUG_ON(!policy->dead); - if (policy->bundles) - BUG(); + BUG_ON(policy->bundles); if (del_timer(&policy->timer)) BUG(); diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 0c4f3a9f2ea9..bf96a61d4b86 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -30,7 +30,7 @@ # - See include/linux/module.h for more details # Step 4 is solely used to allow module versioning in external modules, -# where the CRC of each module is retreived from the Module.symers file. +# where the CRC of each module is retrieved from the Module.symers file. .PHONY: _modpost _modpost: __modpost diff --git a/scripts/mksysmap b/scripts/mksysmap index a6430e05972d..4390fab9f5bd 100644 --- a/scripts/mksysmap +++ b/scripts/mksysmap @@ -1,7 +1,7 @@ #!/bin/sh -x # Based on the vmlinux file create the System.map file # System.map is used by module-init tools and some debugging -# tools to retreive the actual addresses of symbols in the kernel. +# tools to retrieve the actual addresses of symbols in the kernel. # # Usage # mksysmap vmlinux System.map diff --git a/security/inode.c b/security/inode.c index a5964502ae30..0f77b0223662 100644 --- a/security/inode.c +++ b/security/inode.c @@ -172,7 +172,7 @@ static int create_by_name(const char *name, mode_t mode, return -EFAULT; } - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); *dentry = lookup_one_len(name, parent, strlen(name)); if (!IS_ERR(dentry)) { if ((mode & S_IFMT) == S_IFDIR) @@ -181,7 +181,7 @@ static int create_by_name(const char *name, mode_t mode, error = create(parent->d_inode, *dentry, mode); } else error = PTR_ERR(dentry); - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); return error; } @@ -302,7 +302,7 @@ void securityfs_remove(struct dentry *dentry) if (!parent || !parent->d_inode) return; - down(&parent->d_inode->i_sem); + mutex_lock(&parent->d_inode->i_mutex); if (positive(dentry)) { if (dentry->d_inode) { if (S_ISDIR(dentry->d_inode->i_mode)) @@ -312,7 +312,7 @@ void securityfs_remove(struct dentry *dentry) dput(dentry); } } - up(&parent->d_inode->i_sem); + mutex_unlock(&parent->d_inode->i_mutex); simple_release_fs(&mount, &mount_count); } EXPORT_SYMBOL_GPL(securityfs_remove); diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 16df1246a131..7fd072392c7e 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2135,9 +2135,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream == NULL) return -ENXIO; - up(&file->f_dentry->d_inode->i_sem); result = snd_pcm_oss_write1(substream, buf, count); - down(&file->f_dentry->d_inode->i_sem); #ifdef OSS_DEBUG printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); #endif diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 9ee6c177db0c..40b4f679c80e 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -32,10 +32,6 @@ #include "seq_info.h" #include "seq_lock.h" -/* semaphore in struct file record */ -#define semaphore_of(fp) ((fp)->f_dentry->d_inode->i_sem) - - static inline int snd_seq_pool_available(struct snd_seq_pool *pool) { return pool->total_elements - atomic_read(&pool->counter); diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 09cb250d5827..962e6d525564 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -209,7 +209,7 @@ static int pdacf_pcm_prepare(struct snd_pcm_substream *subs) case SNDRV_PCM_FORMAT_S24_3LE: case SNDRV_PCM_FORMAT_S24_3BE: chip->pcm_sample = 3; - /* fall trough */ + /* fall through */ default: /* 24-bit */ aval = AK4117_DIF_24R; chip->pcm_frame = 3; |