summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-05-18 20:37:46 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-05-18 20:37:46 -0700
commitbf4928ae50a0da6a0c8a88131ba6601bc33f2cad (patch)
tree1a3feebb5fd461e4677d46f7ae24b88c84797847
parent1d8c72f0ac214e4f315c10b5ff02f899a085c53f (diff)
parent2685d1377e3c7eb569f6b34d7bb304850fba3fcf (diff)
Merge bk://kernel.bkbits.net/davem/net-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--Documentation/networking/3c509.txt2
-rw-r--r--Documentation/video4linux/bttv/CARDLIST22
-rw-r--r--Documentation/video4linux/bttv/Cards106
-rw-r--r--Documentation/video4linux/bttv/Sound-FAQ9
-rw-r--r--arch/i386/kernel/Makefile3
-rw-r--r--arch/i386/kernel/smpboot.c7
-rw-r--r--arch/i386/kernel/suspend.c3
-rw-r--r--arch/i386/kernel/suspend_asm.S6
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c2
-rw-r--r--drivers/block/DAC960.c2
-rw-r--r--drivers/ieee1394/ohci1394.c2
-rw-r--r--drivers/isdn/hardware/eicon/maintidi.c2
-rw-r--r--drivers/md/dm-ioctl.c1
-rw-r--r--drivers/media/video/msp3400.c241
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c202
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c217
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c9
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c188
-rw-r--r--drivers/media/video/saa7134/saa7134-reg.h13
-rw-r--r--drivers/media/video/saa7134/saa7134-ts.c18
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c591
-rw-r--r--drivers/media/video/saa7134/saa7134-vbi.c9
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c237
-rw-r--r--drivers/media/video/saa7134/saa7134.h170
-rw-r--r--drivers/media/video/tda7432.c13
-rw-r--r--drivers/media/video/tda9875.c16
-rw-r--r--drivers/media/video/tda9887.c8
-rw-r--r--drivers/media/video/tuner.c151
-rw-r--r--drivers/media/video/tvaudio.c212
-rw-r--r--drivers/media/video/tvaudio.h2
-rw-r--r--drivers/media/video/tvmixer.c51
-rw-r--r--drivers/media/video/v4l1-compat.c504
-rw-r--r--drivers/media/video/video-buf.c43
-rw-r--r--drivers/net/3c59x.c21
-rw-r--r--drivers/net/ppp_generic.c2
-rw-r--r--drivers/net/wan/sdla_chdlc.c2
-rw-r--r--drivers/net/wireless/airo.c2
-rw-r--r--drivers/pci/pci.ids1
-rw-r--r--drivers/scsi/megaraid.c8
-rw-r--r--drivers/video/radeonfb.c6
-rw-r--r--fs/cifs/md5.c2
-rw-r--r--fs/open.c2
-rw-r--r--fs/reiserfs/bitmap.c21
-rw-r--r--fs/reiserfs/do_balan.c104
-rw-r--r--fs/reiserfs/file.c1013
-rw-r--r--fs/reiserfs/inode.c54
-rw-r--r--fs/reiserfs/super.c11
-rw-r--r--fs/reiserfs/tail_conversion.c5
-rw-r--r--fs/sysfs/symlink.c2
-rw-r--r--include/asm-i386/genapic.h2
-rw-r--r--include/asm-i386/mach-bigsmp/mach_apic.h17
-rw-r--r--include/asm-i386/mach-generic/mach_apic.h1
-rw-r--r--include/asm-i386/mach-summit/mach_apic.h17
-rw-r--r--include/asm-i386/mmu_context.h4
-rw-r--r--include/asm-i386/spinlock.h23
-rw-r--r--include/asm-i386/types.h2
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/mm.h2
-rw-r--r--include/linux/reiserfs_fs.h4
-rw-r--r--include/linux/reiserfs_fs_sb.h1
-rw-r--r--include/media/audiochip.h9
-rw-r--r--include/media/tuner.h3
-rw-r--r--include/media/video-buf.h1
-rw-r--r--kernel/ksyms.c3
-rw-r--r--mm/memory.c11
-rw-r--r--mm/truncate.c8
-rw-r--r--net/netrom/nr_route.c5
-rw-r--r--sound/oss/cs4281/cs4281m.c71
-rw-r--r--sound/oss/cs4281/cs4281pm-24.c4
-rw-r--r--sound/pci/emu10k1/emufx.c2
70 files changed, 3306 insertions, 1204 deletions
diff --git a/Documentation/networking/3c509.txt b/Documentation/networking/3c509.txt
index 92b60517c8d3..867a99f88c68 100644
--- a/Documentation/networking/3c509.txt
+++ b/Documentation/networking/3c509.txt
@@ -52,7 +52,7 @@ loaded as a module, only the IRQ and transceiver setting may be overridden.
For example, setting two cards to 10base2/IRQ10 and AUI/IRQ11 is done by using
the xcvr and irq module options:
- options 3c509 xcvr=3,3 irq=10,11
+ options 3c509 xcvr=3,1 irq=10,11
(2) Full-duplex mode
diff --git a/Documentation/video4linux/bttv/CARDLIST b/Documentation/video4linux/bttv/CARDLIST
index 2e03c0bd77b4..2131a12bf143 100644
--- a/Documentation/video4linux/bttv/CARDLIST
+++ b/Documentation/video4linux/bttv/CARDLIST
@@ -22,7 +22,7 @@ bttv.o
card=20 - CEI Raffles Card
card=21 - Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50
card=22 - Askey CPH050/ Phoebe Tv Master + FM
- card=23 - Modular Technology MM205 PCTV, bt878
+ card=23 - Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878
card=24 - Askey CPH05X/06X (bt878) [many vendors]
card=25 - Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar
card=26 - Hauppauge WinCam newer (bt878)
@@ -39,7 +39,7 @@ bttv.o
card=37 - Prolink PixelView PlayTV pro
card=38 - Askey CPH06X TView99
card=39 - Pinnacle PCTV Studio/Rave
- card=40 - STB TV PCI FM, Gateway P/N 6000704 (bt878)
+ card=40 - STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100
card=41 - AVerMedia TVPhone 98
card=42 - ProVideo PV951
card=43 - Little OnAir TV
@@ -81,11 +81,27 @@ bttv.o
card=79 - DSP Design TCVIDEO
card=80 - Hauppauge WinTV PVR
card=81 - GV-BCTV5/PCI
+ card=82 - Osprey 100/150 (878)
+ card=83 - Osprey 100/150 (848)
+ card=84 - Osprey 101 (848)
+ card=85 - Osprey 101/151
+ card=86 - Osprey 101/151 w/ svid
+ card=87 - Osprey 200/201/250/251
+ card=88 - Osprey 200/250
+ card=89 - Osprey 210/220
+ card=90 - Osprey 500
+ card=91 - Osprey 540
+ card=92 - Osprey 2000
+ card=93 - IDS Eagle
+ card=94 - Pinnacle PCTV Sat
+ card=95 - Formac ProTV II
+ card=96 - MachTV
+ card=97 - Euresys Picolo
tuner.o
type=0 - Temic PAL (4002 FH5)
type=1 - Philips PAL_I (FI1246 and compatibles)
- type=2 - Philips NTSC (FI1236 and compatibles)
+ type=2 - Philips NTSC (FI1236,FM1236 and compatibles)
type=3 - Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)
type=4 - NoTuner
type=5 - Philips PAL_BG (FI1216 and compatibles)
diff --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards
index 60077f3b4633..7865e56c5d2c 100644
--- a/Documentation/video4linux/bttv/Cards
+++ b/Documentation/video4linux/bttv/Cards
@@ -179,7 +179,8 @@ Lifeview Flyvideo Series:
has not yet been seen (perhaps it was the german name for LR90 [stereo]).
These cards are sold by many OEMs too.
- FlyVideo A2 = LR90 Rev.F (w/Remote, w/o FM, stereo TV by tda9821) {Germany}
+ FlyVideo A2 (Elta 8680)= LR90 Rev.F (w/Remote, w/o FM, stereo TV by tda9821) {Germany}
+ Lifeview 3000 (Elta 8681) as sold by Plus(April 2002), Germany = LR138 w/ saa7134
Typhoon TV card series:
@@ -397,6 +398,8 @@ AVerMedia
AVerTV98 mit Fernbedienung (BT-878 chip)
AVerTV/FM98 (BT-878 chip)
+ VDOmate (www.averm.com.cn) = M168U ?
+
Aimslab
-------
Video Highway or "Video Highway TR200" (ISA)
@@ -413,7 +416,8 @@ Lifetec/Medion/Tevion/Aldi
LT9306/MD9306 = CPH061
LT9415/MD9415 = LR90 Rev.F or Rev.G
MD9592 = Avermedia TVphone98 (PCI_ID=1461:0003), PCB-Rev=M168II-B (w/TDA9873H)
- MD9717 = KNC One (Rev D4, saa7134)
+ MD9717 = KNC One (Rev D4, saa7134, FM1216 MK2 tuner)
+ MD5044 = KNC One (Rev D4, saa7134, FM1216ME MK3 tuner)
Modular Technologies (www.modulartech.com) UK
---------------------------------------------
@@ -481,7 +485,8 @@ Pinnacle
Studio PCTV Pro (Bt878 stereo w/ FM)
Pinnacle PCTV (Bt878, MT2032)
Pinnacle PCTV Pro (Bt878, MT2032)
- Pinncale PCTV Sat (bt878a, HM1821/1221)
+ Pinncale PCTV Sat (bt878a, HM1821/1221) ["Conexant CX24110 with CX24108 tuner, aka HM1221/HM1811"]
+ Pinnacle PCTV Sat XE
M(J)PEG capture and playback:
DC1+ (ISA)
@@ -654,9 +659,9 @@ Hauppauge
WinTV PVR 450
US models
- 990 WinTV-PVR-350 (249USD)
- 980 WinTV-PVR-250 (149USD)
- 880 WinTV-PVR-PCI (199USD)
+ 990 WinTV-PVR-350 (249USD) (iTVC15 chipset + radio)
+ 980 WinTV-PVR-250 (149USD) (iTVC15 chipset)
+ 880 WinTV-PVR-PCI (199USD) (KFIR chipset + bt878)
881 WinTV-PVR-USB
190 WinTV-GO
191 WinTV-GO-FM
@@ -697,11 +702,40 @@ Hauppauge
566 WinTV USB (UK)
573 WinTV USB FM
429 Impact VCB (bt848)
- 600 USB Libe (Video-In 1x Comp, 1xSVHS)
+ 600 USB Live (Video-In 1x Comp, 1xSVHS)
542 WinTV Nova
717 WinTV DVB-S
909 Nova-t PCI
893 Nova-t USB (Duplicate entry)
+ 802 MyTV
+ 804 MyView
+ 809 MyVideo
+ 872 MyTV2Go FM
+
+
+ 546 WinTV Nova-S CI
+ 543 WinTV Nova
+ 907 Nova-S USB
+ 908 Nova-T USB
+ 717 WinTV Nexus-S
+ 157 DEC3000-s Standalone + USB
+
+ Spain
+ 685 WinTV-Go
+ 690 WinTV-PrimioFM
+ 416 WinTV-PCI Nicam Estereo
+ 677 WinTV-PCI-FM
+ 699 WinTV-Theater
+ 683 WinTV-USB
+ 678 WinTV-USB-FM
+ 983 WinTV-PVR-250
+ 883 WinTV-PVR-PCI
+ 993 WinTV-PVR-350
+ 893 WinTV-PVR-USB
+ 728 WinTV-DVB-C PCI
+ 832 MyTV2Go
+ 869 MyTV2Go-FM
+ 805 MyVideo (USB)
Matrix-Vision
@@ -713,6 +747,7 @@ Matrix-Vision
Conceptronic (.net)
------------
TVCON FM, TV card w/ FM = CPH05x
+ TVCON = CPH06x
BestData
--------
@@ -747,11 +782,22 @@ Teppro (www.itcteppro.com.tw)
Kworld (www.kworld.com.tw)
--------------------------
- KWORLD KW-TV878RF-Pro TV Capture with FM Radio
- KWORLD KW-TV878R-Pro TV
- KWORLD KW-TVL878RF (low profile)
- KWORLD KW-TV878R TV Capture (No FM Radio)
- KWORLD KW-TV878RF TV
+ PC TV Station
+ KWORLD KW-TV878R TV (no radio)
+ KWORLD KW-TV878RF TV (w/ radio)
+
+ KWORLD KW-TVL878RF (low profile)
+
+ KWORLD KW-TV713XRF (saa7134)
+
+
+ MPEG TV Station (same cards as above plus WinDVR Software MPEG en/decoder)
+ KWORLD KW-TV878R -Pro TV (no Radio)
+ KWORLD KW-TV878RF-Pro TV (w/ Radio)
+ KWORLD KW-TV878R -Ultra TV (no Radio)
+ KWORLD KW-TV878RF-Ultra TV (w/ Radio)
+
+
JTT/ Justy Corp.http://www.justy.co.jp/ (www.jtt.com.jp website down)
---------------------------------------------------------------------
@@ -793,7 +839,7 @@ Satelco www.citycom-gmbh.de, www.satelco.de
TV-FM =KNC1 saa7134
Standard PCI (DVB-S) = Technotrend Budget
Standard PCI (DVB-S) w/ CI
- Satelco Hoghend PCI (DVB-S) = Technotrend Premium
+ Satelco Highend PCI (DVB-S) = Technotrend Premium
Sensoray www.sensoray.com
@@ -879,3 +925,37 @@ www.pacecom.co.uk website closed
Mercury www.kobian.com (UK and FR)
LR50
LR138RBG-Rx == LR138
+
+TEC sound (package and manuals don't have any other manufacturer info) TecSound
+ Though educated googling found: www.techmakers.com
+ TV-Mate = Zoltrix VP-8482
+
+Lorenzen www.lorenzen.de
+--------
+ SL DVB-S PCI = Technotrend Budget PCI (su1278 or bsru version)
+
+Origo (.uk) www.origo2000.com
+ PC TV Card = LR50
+
+I/O Magic www.iomagic.com
+---------
+ PC PVR - Desktop TV Personal Video Recorder DR-PCTV100 = Pinnacle ROB2D-51009464 4.0 + Cyberlink PowerVCR II
+
+Arowana
+-------
+ TV-Karte / Poso Power TV (?) = Zoltrix VP-8482 (?)
+
+iTVC15 boards:
+-------------
+kuroutoshikou.com ITVC15
+yuan.com MPG160 PCI TV (Internal PCI MPEG2 encoder card plus TV-tuner)
+
+Asus www.asuscom.com
+ Asus TV Tuner Card 880 NTSC (low profile, cx23880)
+ Asus TV (saa7134)
+
+Hoontech
+--------
+http://www.hoontech.com/korean/download/down_driver_list03.html
+ HART Vision 848 (H-ART Vision 848)
+ HART Vision 878 (H-Art Vision 878)
diff --git a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ
index a1d7f229e1ec..b8c9c2605ce2 100644
--- a/Documentation/video4linux/bttv/Sound-FAQ
+++ b/Documentation/video4linux/bttv/Sound-FAQ
@@ -79,10 +79,11 @@ mux.
What you have to do is figure out the correct values for gpiomask and
the audiomux array. If you have Windows and the drivers four your
card installed, you might to check out if you can read these registers
-values used by the windows driver. A tool to do this is available from
-ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil, but it does'nt
-work with bt878 boards according to some reports I received. Another
-one is available from http://www.kki.net.pl/~borgx/bTV.html.
+values used by the windows driver. A tool to do this is available
+from ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil, but it
+does'nt work with bt878 boards according to some reports I received.
+Another one with bt878 suport is available from
+http://btwincap.sourceforge.net/Files/btspy2.00.zip
You might also dig around in the *.ini files of the Windows applications.
You can have a look at the board to see which of the gpio pins are
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 5a7b466bf7b9..4eb9d727da25 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -17,7 +17,8 @@ obj-$(CONFIG_MCA) += mca.o
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_MICROCODE) += microcode.o
-obj-$(CONFIG_APM) += apm.o suspend.o
+obj-$(CONFIG_PM) += suspend.o
+obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_X86_SMP) += smp.o smpboot.o
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 3118dd068cb6..1e415baf29cc 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -935,7 +935,7 @@ int cpu_sibling_map[NR_CPUS] __cacheline_aligned;
static void __init smp_boot_cpus(unsigned int max_cpus)
{
- int apicid, cpu, bit;
+ int apicid, cpu, bit, kicked;
/*
* Setup boot CPU information
@@ -1018,7 +1018,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
*/
Dprintk("CPU present map: %lx\n", phys_cpu_present_map);
- for (bit = 0; bit < NR_CPUS; bit++) {
+ kicked = 1;
+ for (bit = 0; kicked < NR_CPUS && bit < BITS_PER_LONG; bit++) {
apicid = cpu_present_to_apicid(bit);
/*
* Don't even attempt to start the boot CPU!
@@ -1034,6 +1035,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
if (do_boot_cpu(apicid))
printk("CPU #%d not responding - cannot use it.\n",
apicid);
+ else
+ ++kicked;
}
/*
diff --git a/arch/i386/kernel/suspend.c b/arch/i386/kernel/suspend.c
index 1848fd29cfe3..97aed5dd6a27 100644
--- a/arch/i386/kernel/suspend.c
+++ b/arch/i386/kernel/suspend.c
@@ -130,3 +130,6 @@ static void fix_processor_context(void)
}
}
+
+EXPORT_SYMBOL(save_processor_state);
+EXPORT_SYMBOL(restore_processor_state);
diff --git a/arch/i386/kernel/suspend_asm.S b/arch/i386/kernel/suspend_asm.S
index a75350512af7..d15967b07cef 100644
--- a/arch/i386/kernel/suspend_asm.S
+++ b/arch/i386/kernel/suspend_asm.S
@@ -7,6 +7,12 @@
#include <asm/page.h>
.data
+ .align 4
+ .globl saved_context_eax, saved_context_ebx
+ .globl saved_context_ecx, saved_context_edx
+ .globl saved_context_esp, saved_context_ebp
+ .globl saved_context_esi, saved_context_edi
+ .globl saved_context_eflags
saved_context_eax:
.long 0
saved_context_ebx:
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index f373b65bcb42..c3bb1eed0e45 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -247,7 +247,7 @@ static unsigned long smp_commenced_mask = 0;
/* This is for the new dynamic CPU boot code */
volatile unsigned long cpu_callin_map = 0;
-unsigned long cpu_callout_map = 0;
+volatile unsigned long cpu_callout_map = 0;
/* The per processor IRQ masks (these are usually kept in sync) */
static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 09cc1c127849..8ea1e8252d69 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -102,7 +102,7 @@ static int DAC960_ioctl(struct inode *inode, struct file *file,
int drive_nr = (int)disk->private_data;
struct hd_geometry g, *loc = (struct hd_geometry *)arg;
- if (file->f_flags & O_NONBLOCK)
+ if (file && (file->f_flags & O_NONBLOCK))
return DAC960_UserIOCTL(inode, file, cmd, arg);
if (cmd != HDIO_GETGEO || !loc)
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index bd3a58c0273a..2c8ff17ef591 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -3165,7 +3165,7 @@ static void ohci_init_config_rom(struct ti_ohci *ohci)
struct config_rom_ptr cr;
memset(&cr, 0, sizeof(cr));
- memset(ohci->csr_config_rom_cpu, 0, sizeof (ohci->csr_config_rom_cpu));
+ memset(ohci->csr_config_rom_cpu, 0, sizeof(*ohci->csr_config_rom_cpu));
cr.data = ohci->csr_config_rom_cpu;
diff --git a/drivers/isdn/hardware/eicon/maintidi.c b/drivers/isdn/hardware/eicon/maintidi.c
index a32ff89a86d3..29850cf198ae 100644
--- a/drivers/isdn/hardware/eicon/maintidi.c
+++ b/drivers/isdn/hardware/eicon/maintidi.c
@@ -116,7 +116,7 @@ diva_strace_library_interface_t* DivaSTraceLibraryCreateInstance (int Adapter,
}
pmem += sizeof(*pLib);
- memset (pLib, 0x00, sizeof(pLib));
+ memset(pLib, 0x00, sizeof(*pLib));
pLib->Adapter = Adapter;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 3bc04ee7cb08..a6fa7d31e43a 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1115,7 +1115,6 @@ int __init dm_interface_init(void)
DM_DRIVER_EMAIL);
return 0;
- failed:
if (misc_deregister(&_dm_misc) < 0)
DMERR("misc_deregister failed for control device");
dm_hash_exit();
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 65403235f802..9c4887b0dbc4 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -45,13 +45,11 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/videodev.h>
-#include <asm/semaphore.h>
#include <linux/init.h>
-
-#ifdef CONFIG_SMP
-#include <asm/pgtable.h>
#include <linux/smp_lock.h>
-#endif
+#include <asm/semaphore.h>
+#include <asm/pgtable.h>
+
/* kernel_thread */
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
@@ -59,18 +57,13 @@
#include <media/audiochip.h>
#include "msp3400.h"
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {0x40,0x40,I2C_CLIENT_END};
-I2C_CLIENT_INSMOD;
-
/* insmod parameters */
-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),
+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 simple = -1; /* use short programming (>= msp3410 only) */
-static int dolby = 0;
+static int simple = -1; /* use short programming (>= msp3410 only) */
+static int dolby = 0;
#define DFP_COUNT 0x41
static const int bl_dfp[] = {
@@ -79,8 +72,9 @@ static const int bl_dfp[] = {
};
struct msp3400c {
+ int rev1,rev2;
+
int simple;
- int nicam;
int mode;
int norm;
int stereo;
@@ -107,6 +101,10 @@ struct msp3400c {
struct timer_list wake_stereo;
};
+#define HAVE_NICAM(msp) (((msp->rev2>>8) & 0xff) != 00)
+#define HAVE_SIMPLE(msp) ((msp->rev1 & 0xff) >= 'D'-'@')
+#define HAVE_RADIO(msp) ((msp->rev1 & 0xff) >= 'G'-'@')
+
#define MSP3400_MAX 4
static struct i2c_client *msps[MSP3400_MAX];
@@ -124,14 +122,25 @@ MODULE_PARM(dolby,"i");
MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
MODULE_AUTHOR("Gerd Knorr");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL"); /* FreeBSD uses this too */
/* ---------------------------------------------------------------------- */
#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
+};
+static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
+I2C_CLIENT_INSMOD;
+
/* ----------------------------------------------------------------------- */
/* functions for talking to the MSP3400C Sound processor */
@@ -354,7 +363,8 @@ msp3400c_set_scart(struct i2c_client *client, int in, int out)
if (-1 == scarts[out][in])
return;
- dprintk("msp34xx: scart switch: %s => %d\n",scart_names[in],out);
+ dprintk(KERN_DEBUG
+ "msp34xx: scart switch: %s => %d\n",scart_names[in],out);
msp->acb &= ~scarts[out][SCART_MASK];
msp->acb |= scarts[out][in];
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, msp->acb);
@@ -384,7 +394,8 @@ static void msp3400c_setvolume(struct i2c_client *client,
balance = ((right-left) * 127) / vol;
}
- dprintk("msp34xx: setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n",
+ dprintk(KERN_DEBUG
+ "msp34xx: 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 */
@@ -397,7 +408,7 @@ static void msp3400c_setbass(struct i2c_client *client, int bass)
{
int val = ((bass-32768) * 0x60 / 65535) << 8;
- dprintk("msp34xx: setbass: %d 0x%02x\n",bass, val>>8);
+ dprintk(KERN_DEBUG "msp34xx: setbass: %d 0x%02x\n",bass, val>>8);
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0002, val); /* loudspeaker */
}
@@ -405,7 +416,7 @@ static void msp3400c_settreble(struct i2c_client *client, int treble)
{
int val = ((treble-32768) * 0x60 / 65535) << 8;
- dprintk("msp34xx: settreble: %d 0x%02x\n",treble, val>>8);
+ dprintk(KERN_DEBUG "msp34xx: settreble: %d 0x%02x\n",treble, val>>8);
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0003, val); /* loudspeaker */
}
@@ -414,7 +425,7 @@ static void msp3400c_setmode(struct i2c_client *client, int type)
struct msp3400c *msp = i2c_get_clientdata(client);
int i;
- dprintk("msp3400: setmode: %d\n",type);
+ dprintk(KERN_DEBUG "msp3400: setmode: %d\n",type);
msp->mode = type;
msp->stereo = VIDEO_SOUND_MONO;
@@ -460,7 +471,7 @@ static void msp3400c_setmode(struct i2c_client *client, int type)
msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e,
msp_init_data[type].dfp_matrix);
- if (msp->nicam) {
+ if (HAVE_NICAM(msp)) {
/* nicam prescale */
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0010, 0x5a00); /* was: 0x3000 */
}
@@ -469,8 +480,15 @@ static void msp3400c_setmode(struct i2c_client *client, int type)
/* 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" };
+ static char *strmode[16] = {
+#if __GNUC__ >= 3
+ [ 0 ... 15 ] = "invalid",
+#endif
+ [ VIDEO_SOUND_MONO ] = "mono",
+ [ VIDEO_SOUND_STEREO ] = "stereo",
+ [ VIDEO_SOUND_LANG1 ] = "lang1",
+ [ VIDEO_SOUND_LANG2 ] = "lang2",
+ };
struct msp3400c *msp = i2c_get_clientdata(client);
int nicam=0; /* channel source: FM/AM or nicam */
int src=0;
@@ -478,7 +496,7 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode)
/* switch demodulator */
switch (msp->mode) {
case MSP_MODE_FM_TERRA:
- dprintk("msp3400: FM setstereo: %s\n",strmode[mode]);
+ dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n",strmode[mode]);
msp3400c_setcarrier(client,msp->second,msp->main);
switch (mode) {
case VIDEO_SOUND_STEREO:
@@ -492,7 +510,7 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode)
}
break;
case MSP_MODE_FM_SAT:
- dprintk("msp3400: SAT setstereo: %s\n",strmode[mode]);
+ dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n",strmode[mode]);
switch (mode) {
case VIDEO_SOUND_MONO:
msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
@@ -511,24 +529,24 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode)
case MSP_MODE_FM_NICAM1:
case MSP_MODE_FM_NICAM2:
case MSP_MODE_AM_NICAM:
- dprintk("msp3400: NICAM setstereo: %s\n",strmode[mode]);
+ dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n",strmode[mode]);
msp3400c_setcarrier(client,msp->second,msp->main);
if (msp->nicam_on)
nicam=0x0100;
break;
case MSP_MODE_BTSC:
- dprintk("msp3400: BTSC setstereo: %s\n",strmode[mode]);
+ dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n",strmode[mode]);
nicam=0x0300;
break;
case MSP_MODE_EXTERN:
- dprintk("msp3400: extern setstereo: %s\n",strmode[mode]);
+ dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n",strmode[mode]);
nicam = 0x0200;
break;
case MSP_MODE_FM_RADIO:
- dprintk("msp3400: FM-Radio setstereo: %s\n",strmode[mode]);
+ dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n",strmode[mode]);
break;
default:
- dprintk("msp3400: mono setstereo\n");
+ dprintk(KERN_DEBUG "msp3400: mono setstereo\n");
return;
}
@@ -557,7 +575,8 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode)
src = 0x0010 | nicam;
break;
}
- dprintk("msp3400: setstereo final source/matrix = 0x%x\n", src);
+ dprintk(KERN_DEBUG
+ "msp3400: setstereo final source/matrix = 0x%x\n", src);
if (dolby) {
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,0x0520);
@@ -576,22 +595,22 @@ static void
msp3400c_print_mode(struct msp3400c *msp)
{
if (msp->main == msp->second) {
- printk("msp3400: mono sound carrier: %d.%03d MHz\n",
+ printk(KERN_DEBUG "msp3400: mono sound carrier: %d.%03d MHz\n",
msp->main/910000,(msp->main/910)%1000);
} else {
- printk("msp3400: main sound carrier: %d.%03d MHz\n",
+ printk(KERN_DEBUG "msp3400: 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)
- printk("msp3400: NICAM/FM carrier : %d.%03d MHz\n",
+ printk(KERN_DEBUG "msp3400: NICAM/FM carrier : %d.%03d MHz\n",
msp->second/910000,(msp->second/910)%1000);
if (msp->mode == MSP_MODE_AM_NICAM)
- printk("msp3400: NICAM/AM carrier : %d.%03d MHz\n",
+ printk(KERN_DEBUG "msp3400: 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) {
- printk("msp3400: FM-stereo carrier : %d.%03d MHz\n",
+ printk(KERN_DEBUG "msp3400: FM-stereo carrier : %d.%03d MHz\n",
msp->second/910000,(msp->second/910)%1000);
}
}
@@ -638,8 +657,8 @@ autodetect_stereo(struct i2c_client *client)
val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x18);
if (val > 32767)
val -= 65536;
- dprintk("msp34xx: stereo detect register: %d\n",val);
-
+ dprintk(KERN_DEBUG
+ "msp34xx: stereo detect register: %d\n",val);
if (val > 4096) {
newstereo = VIDEO_SOUND_STEREO | VIDEO_SOUND_MONO;
} else if (val < -4096) {
@@ -653,7 +672,9 @@ autodetect_stereo(struct i2c_client *client)
case MSP_MODE_FM_NICAM2:
case MSP_MODE_AM_NICAM:
val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x23);
- dprintk("msp34xx: nicam sync=%d, mode=%d\n",val & 1, (val & 0x1e) >> 1);
+ dprintk(KERN_DEBUG
+ "msp34xx: nicam sync=%d, mode=%d\n",
+ val & 1, (val & 0x1e) >> 1);
if (val & 1) {
/* nicam synced */
@@ -685,7 +706,8 @@ autodetect_stereo(struct i2c_client *client)
break;
case MSP_MODE_BTSC:
val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200);
- dprintk("msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n",
+ dprintk(KERN_DEBUG
+ "msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n",
val,
(val & 0x0002) ? "no" : "yes",
(val & 0x0004) ? "no" : "yes",
@@ -699,13 +721,13 @@ autodetect_stereo(struct i2c_client *client)
}
if (newstereo != msp->stereo) {
update = 1;
- dprintk("msp34xx: watch: stereo %d => %d\n",
+ dprintk(KERN_DEBUG "msp34xx: watch: stereo %d => %d\n",
msp->stereo,newstereo);
msp->stereo = newstereo;
}
if (newnicam != msp->nicam_on) {
update = 1;
- dprintk("msp34xx: watch: nicam %d => %d\n",
+ dprintk(KERN_DEBUG "msp34xx: watch: nicam %d => %d\n",
msp->nicam_on,newnicam);
msp->nicam_on = newnicam;
}
@@ -734,6 +756,8 @@ static void watch_stereo(struct i2c_client *client)
msp3400c_setstereo(client,VIDEO_SOUND_STEREO);
else if (msp->stereo & VIDEO_SOUND_LANG1)
msp3400c_setstereo(client,VIDEO_SOUND_LANG1);
+ else if (msp->stereo & VIDEO_SOUND_LANG2)
+ msp3400c_setstereo(client,VIDEO_SOUND_LANG2);
else
msp3400c_setstereo(client,VIDEO_SOUND_MONO);
}
@@ -751,17 +775,10 @@ static int msp3400c_thread(void *data)
struct CARRIER_DETECT *cd;
int count, max1,max2,val1,val2, val,this;
-#ifdef CONFIG_SMP
lock_kernel();
-#endif
-
daemonize("msp3400");
-
msp->thread = current;
-
-#ifdef CONFIG_SMP
unlock_kernel();
-#endif
printk("msp3400: daemon started\n");
if(msp->notify != NULL)
@@ -778,10 +795,6 @@ static int msp3400c_thread(void *data)
if (msp->rmmod || signal_pending(current))
goto done;
- if (VIDEO_MODE_RADIO == msp->norm ||
- MSP_MODE_EXTERN == msp->mode)
- continue; /* nothing to do */
-
msp->active = 1;
if (msp->watch_stereo) {
@@ -798,8 +811,13 @@ static int msp3400c_thread(void *data)
restart:
if (VIDEO_MODE_RADIO == msp->norm ||
- MSP_MODE_EXTERN == msp->mode)
- continue; /* nothing to do */
+ MSP_MODE_EXTERN == msp->mode) {
+ /* no carrier scan, just unmute */
+ printk("msp3400: thread: no carrier scan\n");
+ msp3400c_setvolume(client, msp->muted,
+ msp->left, msp->right);
+ continue;
+ }
msp->restart = 0;
msp3400c_setvolume(client, msp->muted, 0, 0);
msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
@@ -884,7 +902,7 @@ static int msp3400c_thread(void *data)
msp->nicam_on = 0;
msp3400c_setstereo(client, VIDEO_SOUND_MONO);
msp->watch_stereo = 1;
- } else if (max2 == 1 && msp->nicam) {
+ } else if (max2 == 1 && HAVE_NICAM(msp)) {
/* B/G NICAM */
msp->second = carrier_detect_55[max2].cdo;
msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
@@ -922,7 +940,7 @@ static int msp3400c_thread(void *data)
/* volume prescale for SCART (AM mono input) */
msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900);
msp->watch_stereo = 1;
- } else if (max2 == 0 && msp->nicam) {
+ } else if (max2 == 0 && HAVE_NICAM(msp)) {
/* D/K NICAM */
msp->second = carrier_detect_65[max2].cdo;
msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
@@ -959,7 +977,7 @@ static int msp3400c_thread(void *data)
}
done:
- dprintk("msp3400: thread: exit\n");
+ dprintk(KERN_DEBUG "msp3400: thread: exit\n");
msp->active = 0;
msp->thread = NULL;
@@ -1005,17 +1023,10 @@ static int msp3410d_thread(void *data)
struct msp3400c *msp = i2c_get_clientdata(client);
int mode,val,i,std;
-#ifdef CONFIG_SMP
lock_kernel();
-#endif
-
daemonize("msp3410 [auto]");
-
msp->thread = current;
-
-#ifdef CONFIG_SMP
unlock_kernel();
-#endif
printk("msp3410: daemon started\n");
if(msp->notify != NULL)
@@ -1025,16 +1036,13 @@ static int msp3410d_thread(void *data)
if (msp->rmmod)
goto done;
if (debug > 1)
- printk("msp3410: thread: sleep\n");
+ printk(KERN_DEBUG "msp3410: thread: sleep\n");
interruptible_sleep_on(&msp->wq);
if (debug > 1)
- printk("msp3410: thread: wakeup\n");
+ printk(KERN_DEBUG "msp3410: thread: wakeup\n");
if (msp->rmmod || signal_pending(current))
goto done;
- if (msp->mode == MSP_MODE_EXTERN)
- continue;
-
msp->active = 1;
if (msp->watch_stereo) {
@@ -1050,8 +1058,13 @@ static int msp3410d_thread(void *data)
goto done;
restart:
- if (msp->mode == MSP_MODE_EXTERN)
+ if (msp->mode == MSP_MODE_EXTERN) {
+ /* no carrier scan needed, just unmute */
+ dprintk(KERN_DEBUG "msp3410: thread: no carrier scan\n");
+ msp3400c_setvolume(client, msp->muted,
+ msp->left, msp->right);
continue;
+ }
msp->restart = 0;
del_timer(&msp->wake_stereo);
msp->watch_stereo = 0;
@@ -1073,7 +1086,7 @@ static int msp3410d_thread(void *data)
mode = 0x0003;
std = 1;
break;
- case VIDEO_MODE_RADIO:
+ case VIDEO_MODE_RADIO:
mode = 0x0003;
std = 0x0040;
break;
@@ -1090,7 +1103,7 @@ static int msp3410d_thread(void *data)
for (i = 0; modelist[i].name != NULL; i++)
if (modelist[i].retval == std)
break;
- printk("msp3410: setting mode: %s (0x%04x)\n",
+ printk(KERN_DEBUG "msp3410: setting mode: %s (0x%04x)\n",
modelist[i].name ? modelist[i].name : "unknown",std);
}
@@ -1111,13 +1124,13 @@ static int msp3410d_thread(void *data)
val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e);
if (val < 0x07ff)
break;
- dprintk("msp3410: detection still in progress\n");
+ dprintk(KERN_DEBUG "msp3410: detection still in progress\n");
}
}
for (i = 0; modelist[i].name != NULL; i++)
if (modelist[i].retval == val)
break;
- dprintk("msp3410: current mode: %s (0x%04x)\n",
+ dprintk(KERN_DEBUG "msp3410: current mode: %s (0x%04x)\n",
modelist[i].name ? modelist[i].name : "unknown",
val);
msp->main = modelist[i].main;
@@ -1125,7 +1138,8 @@ static int msp3410d_thread(void *data)
if (amsound && (msp->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) {
/* autodetection has failed, let backup */
- dprintk("msp3410: autodetection failed, switching to backup mode: %s (0x%04x)\n",
+ dprintk(KERN_DEBUG "msp3410: 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);
@@ -1170,11 +1184,24 @@ static int msp3410d_thread(void *data)
msp->stereo = VIDEO_SOUND_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);
+#if 0
+ /* radio from SCART_IN2 */
msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0220);
msp3400c_write(client,I2C_MSP3400C_DFP, 0x09, 0x0220);
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0b, 0x0220);
+#else
+ /* 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);
+#endif
break;
case 0x0003:
msp->mode = MSP_MODE_FM_TERRA;
@@ -1197,7 +1224,7 @@ static int msp3410d_thread(void *data)
}
done:
- dprintk("msp3410: thread: exit\n");
+ dprintk(KERN_DEBUG "msp3410: thread: exit\n");
msp->active = 0;
msp->thread = NULL;
@@ -1225,11 +1252,9 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- .flags = I2C_CLIENT_ALLOW_USE,
- .driver = &driver,
- .dev = {
- .name = "(unset)",
- },
+ I2C_DEVNAME("(unset)"),
+ .flags = I2C_CLIENT_ALLOW_USE,
+ .driver = &driver,
};
static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
@@ -1237,7 +1262,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
DECLARE_MUTEX_LOCKED(sem);
struct msp3400c *msp;
struct i2c_client *c;
- int rev1,rev2,i;
+ int i;
client_template.adapter = adap;
client_template.addr = addr;
@@ -1275,10 +1300,10 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
return -1;
}
- rev1 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1e);
- if (-1 != rev1)
- rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f);
- if ((-1 == rev1) || (0 == rev1 && 0 == rev2)) {
+ msp->rev1 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1e);
+ if (-1 != msp->rev1)
+ msp->rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f);
+ if ((-1 == msp->rev1) || (0 == msp->rev1 && 0 == msp->rev2)) {
kfree(msp);
kfree(c);
printk("msp3400: error while reading chip version\n");
@@ -1292,13 +1317,12 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
msp3400c_setvolume(c,msp->muted,msp->left,msp->right);
snprintf(c->dev.name, DEVICE_NAME_SIZE, "MSP34%02d%c-%c%d",
- (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
- msp->nicam = (((rev2>>8)&0xff) != 00) ? 1 : 0;
+ (msp->rev2>>8)&0xff, (msp->rev1&0xff)+'@',
+ ((msp->rev1>>8)&0xff)+'@', msp->rev2&0x1f);
if (simple == -1) {
/* default mode */
- /* msp->simple = (((rev2>>8)&0xff) == 0) ? 0 : 1; */
- msp->simple = ((rev1&0xff)+'@' > 'C');
+ msp->simple = HAVE_SIMPLE(msp);
} else {
/* use insmod option */
msp->simple = simple;
@@ -1310,13 +1334,16 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
msp->wake_stereo.data = (unsigned long)msp;
/* hello world :-) */
- printk(KERN_INFO "msp34xx: init: chip=%s",c->dev.name);
- if (msp->nicam)
- printk(", has NICAM support");
+ printk(KERN_INFO "msp34xx: init: chip=%s",i2c_clientname(c));
+ if (HAVE_NICAM(msp))
+ printk(" +nicam");
+ if (HAVE_SIMPLE(msp))
+ printk(" +simple");
+ if (HAVE_RADIO(msp))
+ printk(" +radio");
printk("\n");
/* startup control thread */
- MOD_INC_USE_COUNT;
msp->notify = &sem;
kernel_thread(msp->simple ? msp3410d_thread : msp3400c_thread,
(void *)c, 0);
@@ -1340,7 +1367,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
static int msp_detach(struct i2c_client *client)
{
DECLARE_MUTEX_LOCKED(sem);
- struct msp3400c *msp = i2c_get_clientdata(client);
+ struct msp3400c *msp = i2c_get_clientdata(client);
int i;
/* shutdown control thread */
@@ -1366,7 +1393,6 @@ static int msp_detach(struct i2c_client *client)
i2c_detach_client(client);
kfree(msp);
kfree(client);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -1379,7 +1405,7 @@ static int msp_probe(struct i2c_adapter *adap)
static void msp_wake_thread(struct i2c_client *client)
{
- struct msp3400c *msp = i2c_get_clientdata(client);
+ struct msp3400c *msp = i2c_get_clientdata(client);
msp3400c_setvolume(client,msp->muted,0,0);
msp->watch_stereo=0;
@@ -1391,7 +1417,7 @@ static void msp_wake_thread(struct i2c_client *client)
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
- struct msp3400c *msp = i2c_get_clientdata(client);
+ struct msp3400c *msp = i2c_get_clientdata(client);
__u16 *sarg = arg;
#if 0
int *iarg = (int*)arg;
@@ -1440,7 +1466,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
msp->norm = VIDEO_MODE_RADIO;
msp->watch_stereo=0;
del_timer(&msp->wake_stereo);
- dprintk("msp34xx: switching to radio mode\n");
+ dprintk(KERN_DEBUG "msp34xx: switching to radio mode\n");
if (msp->simple) {
/* the thread will do for us */
msp_wake_thread(client);
@@ -1459,11 +1485,11 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
case MSP_SET_DFPREG:
{
struct msp_dfpreg *r = arg;
- int i;
+ unsigned int i;
if (r->reg < 0 || r->reg >= DFP_COUNT)
return -EINVAL;
- for (i = 0; i < sizeof(bl_dfp)/sizeof(int); i++)
+ for (i = 0; i < ARRAY_SIZE(bl_dfp); i++)
if (r->reg == bl_dfp[i])
return -EINVAL;
msp->dfp_regs[r->reg] = r->value;
@@ -1527,11 +1553,11 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
msp3400c_setbass(client,msp->bass);
msp3400c_settreble(client,msp->treble);
- if (va->mode != 0) {
+ if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) {
msp->watch_stereo=0;
del_timer(&msp->wake_stereo);
- msp->stereo = va->mode;
- msp3400c_setstereo(client,va->mode);
+ msp->stereo = va->mode & 0x0f;
+ msp3400c_setstereo(client,va->mode & 0x0f);
}
break;
}
@@ -1540,7 +1566,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
struct video_channel *vc = arg;
dprintk(KERN_DEBUG "msp34xx: VIDIOCSCHAN\n");
- dprintk("msp34xx: switching to TV mode\n");
msp->norm = vc->norm;
break;
}
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index d2d58ec70da1..1010f7443e95 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -29,6 +29,7 @@
static char name_mute[] = "mute";
static char name_radio[] = "Radio";
static char name_tv[] = "Television";
+static char name_tv_mono[] = "TV (mono only)";
static char name_comp1[] = "Composite1";
static char name_comp2[] = "Composite2";
static char name_svideo[] = "S-Video";
@@ -61,6 +62,11 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 1,
.amux = TV,
.tv = 1,
+ },{
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE2,
+ .tv = 1,
}},
},
[SAA7134_BOARD_FLYVIDEO3000] = {
@@ -68,27 +74,39 @@ struct saa7134_board saa7134_boards[] = {
.name = "LifeView FlyVIDEO3000",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_PAL,
+ .gpiomask = 0xe000,
.inputs = {{
.name = name_tv,
.vmux = 1,
.amux = TV,
+ .gpio = 0x8000,
+ .tv = 1,
+ },{
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE2,
+ .gpio = 0x0000,
.tv = 1,
},{
.name = name_comp1,
.vmux = 0,
- .amux = LINE1,
+ .amux = LINE2,
+ .gpio = 0x4000,
},{
.name = name_comp2,
.vmux = 3,
- .amux = LINE1,
+ .amux = LINE2,
+ .gpio = 0x4000,
},{
.name = name_svideo,
.vmux = 8,
- .amux = LINE1,
+ .amux = LINE2,
+ .gpio = 0x4000,
}},
.radio = {
.name = name_radio,
.amux = LINE2,
+ .gpio = 0x2000,
},
},
[SAA7134_BOARD_FLYVIDEO2000] = {
@@ -96,7 +114,7 @@ struct saa7134_board saa7134_boards[] = {
.name = "LifeView FlyVIDEO2000",
.audio_clock = 0x00200000,
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
- .gpiomask = 0x6000,
+ .gpiomask = 0xe000,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -122,10 +140,12 @@ struct saa7134_board saa7134_boards[] = {
.radio = {
.name = name_radio,
.amux = LINE2,
+ .gpio = 0x2000,
},
.mute = {
.name = name_mute,
- .amux = LINE1,
+ .amux = LINE2,
+ .gpio = 0x8000,
},
},
[SAA7134_BOARD_EMPRESS] = {
@@ -190,7 +210,7 @@ struct saa7134_board saa7134_boards[] = {
.tv = 1,
},{
/* workaround for problems with normal TV sound */
- .name = "TV (mono only)",
+ .name = name_tv_mono,
.vmux = 1,
.amux = LINE2,
.tv = 1,
@@ -270,6 +290,12 @@ struct saa7134_board saa7134_boards[] = {
.amux = TV,
.tv = 1,
},{
+ /* workaround for problems with normal TV sound */
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE2,
+ .tv = 1,
+ },{
.name = name_comp1,
.vmux = 0,
.amux = LINE2,
@@ -302,7 +328,7 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_tv,
.vmux = 1,
- .amux = TV,
+ .amux = LINE2,
.tv = 1,
}},
},
@@ -332,7 +358,6 @@ struct saa7134_board saa7134_boards[] = {
.name = name_radio,
.amux = LINE2,
},
-
},
[SAA7134_BOARD_MD7134] = {
.name = "Medion 7134",
@@ -343,7 +368,7 @@ struct saa7134_board saa7134_boards[] = {
.name = name_tv,
.vmux = 1,
.amux = LINE2,
- .tv = 1,
+ .tv = 1,
},{
.name = name_comp1,
.vmux = 0,
@@ -361,9 +386,67 @@ struct saa7134_board saa7134_boards[] = {
.name = name_radio,
.amux = LINE2,
},
- },
+ },
+ [SAA7134_BOARD_TYPHOON_90031] = {
+ .name = "Typhoon TV+Radio 90031",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_ELSA] = {
+ .name = "ELSA EX-VISION 300TV",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_HITACHI_NTSC,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE1,
+ },{
+ .name = name_tv,
+ .vmux = 4,
+ .amux = LINE2,
+ .tv = 1,
+ }},
+ },
+ [SAA7134_BOARD_ELSA_500TV] = {
+ .name = "ELSA EX-VISION 500TV",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_HITACHI_NTSC,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 7,
+ .amux = LINE1,
+ },{
+ .name = name_tv,
+ .vmux = 8,
+ .amux = TV,
+ .tv = 1,
+ }},
+ },
+
};
-const int saa7134_bcount = (sizeof(saa7134_boards)/sizeof(struct saa7134_board));
+const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
/* ------------------------------------------------------------------ */
/* PCI ids + subsystem IDs */
@@ -377,6 +460,12 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_PROTEUS_PRO,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = PCI_VENDOR_ID_PHILIPS,
+ .subdevice = 0x2001,
+ .driver_data = SAA7134_BOARD_PROTEUS_PRO,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = PCI_VENDOR_ID_PHILIPS,
.subdevice = 0x6752,
@@ -407,11 +496,29 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_FLYVIDEO3000,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x5168,
+ .subdevice = 0x0138,
+ .driver_data = SAA7134_BOARD_FLYVIDEO2000,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x16be,
.subdevice = 0x0003,
.driver_data = SAA7134_BOARD_MD7134,
},{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x1048,
+ .subdevice = 0x226b,
+ .driver_data = SAA7134_BOARD_ELSA,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x1048,
+ .subdevice = 0x226b,
+ .driver_data = SAA7134_BOARD_ELSA_500TV,
+ },{
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
@@ -435,10 +542,22 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_UNKNOWN,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = SAA7134_BOARD_UNKNOWN,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = SAA7134_BOARD_UNKNOWN,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7135,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = SAA7134_BOARD_UNKNOWN,
},{
/* --- end of list --- */
}
@@ -446,6 +565,67 @@ struct pci_device_id __devinitdata saa7134_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, saa7134_pci_tbl);
/* ----------------------------------------------------------- */
+/* flyvideo tweaks */
+
+#if 0
+static struct {
+ char *model;
+ int tuner_type;
+} fly_list[0x20] = {
+ /* default catch ... */
+ [ 0 ... 0x1f ] = {
+ .model = "UNKNOWN",
+ .tuner_type = TUNER_ABSENT,
+ },
+ /* ... the ones known so far */
+ [ 0x05 ] = {
+ .model = "PAL-BG",
+ .tuner_type = TUNER_LG_PAL_NEW_TAPC,
+ },
+ [ 0x10 ] = {
+ .model = "PAL-BG / PAL-DK",
+ .tuner_type = TUNER_PHILIPS_PAL,
+ },
+ [ 0x15 ] = {
+ .model = "NTSC",
+ .tuner_type = TUNER_ABSENT /* FIXME */,
+ },
+};
+#endif
+
+static void board_flyvideo(struct saa7134_dev *dev)
+{
+ u32 value;
+ int index;
+
+ saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0);
+ value = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+#if 0
+ index = (value & 0x1f00) >> 8;
+ printk(KERN_INFO "%s: flyvideo: gpio is 0x%x [model=%s,tuner=%d]\n",
+ dev->name, value, fly_list[index].model,
+ fly_list[index].tuner_type);
+ dev->tuner_type = fly_list[index].tuner_type;
+#else
+ printk(KERN_INFO "%s: flyvideo: gpio is 0x%x\n",
+ dev->name, value);
+#endif
+}
+
+/* ----------------------------------------------------------- */
+
+int saa7134_board_init(struct saa7134_dev *dev)
+{
+ switch (dev->board) {
+ case SAA7134_BOARD_FLYVIDEO2000:
+ case SAA7134_BOARD_FLYVIDEO3000:
+ board_flyvideo(dev);
+ break;
+ }
+ return 0;
+}
+
+/* ----------------------------------------------------------- */
/*
* Local variables:
* c-basic-offset: 8
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 4fbd9acc03cb..dd1246d7f85b 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -2,7 +2,7 @@
* device driver for philips saa7134 based TV cards
* driver core
*
- * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ * (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -67,6 +67,10 @@ static unsigned int radio_nr = -1;
MODULE_PARM(radio_nr,"i");
MODULE_PARM_DESC(radio_nr,"radio device number");
+static unsigned int oss = 0;
+MODULE_PARM(oss,"i");
+MODULE_PARM_DESC(oss,"register oss devices (default: no)");
+
static unsigned int dsp_nr = -1;
MODULE_PARM(dsp_nr,"i");
MODULE_PARM_DESC(dsp_nr,"oss dsp device number");
@@ -75,20 +79,20 @@ static unsigned int mixer_nr = -1;
MODULE_PARM(mixer_nr,"i");
MODULE_PARM_DESC(mixer_nr,"oss mixer device number");
-static int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = -1};
+static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
MODULE_PARM(tuner,"1-" __stringify(SAA7134_MAXBOARDS) "i");
MODULE_PARM_DESC(tuner,"tuner type");
-static int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = -1};
+static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
MODULE_PARM(card,"1-" __stringify(SAA7134_MAXBOARDS) "i");
MODULE_PARM_DESC(card,"card type");
-static int latency = -1;
+static unsigned int latency = UNSET;
MODULE_PARM(latency,"i");
MODULE_PARM_DESC(latency,"pci latency timer");
struct list_head saa7134_devlist;
-int saa7134_devcount;
+unsigned int saa7134_devcount;
#define dprintk(fmt, arg...) if (core_debug) \
printk(KERN_DEBUG "%s/core: " fmt, dev->name, ## arg)
@@ -102,7 +106,7 @@ static const char *v4l1_ioctls[] = {
"SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
"GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
"SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS (sizeof(v4l1_ioctls)/sizeof(char*))
+#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
static const char *v4l2_ioctls[] = {
"QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
@@ -116,7 +120,7 @@ static const char *v4l2_ioctls[] = {
"S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
"S_MODULATOR"
};
-#define V4L2_IOCTLS (sizeof(v4l2_ioctls)/sizeof(char*))
+#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
static const char *osspcm_ioctls[] = {
"RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
@@ -125,7 +129,7 @@ static const char *osspcm_ioctls[] = {
"GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
"SETDUPLEX", "GETODELAY"
};
-#define OSSPCM_IOCTLS (sizeof(v4l2_ioctls)/sizeof(char*))
+#define OSSPCM_IOCTLS ARRAY_SIZE(v4l2_ioctls)
void saa7134_print_ioctl(char *name, unsigned int cmd)
{
@@ -236,9 +240,9 @@ int saa7134_buffer_pages(int size)
/* calc max # of buffers from size (must not exceed the 4MB virtual
* address space per DMA channel) */
-int saa7134_buffer_count(int size, int count)
+int saa7134_buffer_count(unsigned int size, unsigned int count)
{
- int maxcount;
+ unsigned int maxcount;
maxcount = 1024 / saa7134_buffer_pages(size);
if (count > maxcount)
@@ -277,11 +281,11 @@ int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
}
int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
- struct scatterlist *list, int length,
- int startpage)
+ struct scatterlist *list, unsigned int length,
+ unsigned int startpage)
{
- u32 *ptr;
- int i,p;
+ u32 *ptr;
+ unsigned int i,p;
BUG_ON(NULL == pt || NULL == pt->cpu);
@@ -319,14 +323,25 @@ int saa7134_buffer_queue(struct saa7134_dev *dev,
struct saa7134_dmaqueue *q,
struct saa7134_buf *buf)
{
+ struct saa7134_buf *next = NULL;
#if DEBUG_SPINLOCKS
BUG_ON(!spin_is_locked(&dev->slock));
#endif
dprintk("buffer_queue %p\n",buf);
if (NULL == q->curr) {
- q->curr = buf;
- buf->activate(dev,buf,NULL);
+ if (!q->need_two) {
+ q->curr = buf;
+ buf->activate(dev,buf,NULL);
+ } else if (list_empty(&q->queue)) {
+ list_add_tail(&buf->vb.queue,&q->queue);
+ buf->vb.state = STATE_QUEUED;
+ } else {
+ next = list_entry(q->queue.next,struct saa7134_buf,
+ vb.queue);
+ q->curr = buf;
+ buf->activate(dev,buf,next);
+ }
} else {
list_add_tail(&buf->vb.queue,&q->queue);
buf->vb.state = STATE_QUEUED;
@@ -336,7 +351,7 @@ int saa7134_buffer_queue(struct saa7134_dev *dev,
void saa7134_buffer_finish(struct saa7134_dev *dev,
struct saa7134_dmaqueue *q,
- int state)
+ unsigned int state)
{
#if DEBUG_SPINLOCKS
BUG_ON(!spin_is_locked(&dev->slock));
@@ -388,6 +403,14 @@ void saa7134_buffer_timeout(unsigned long data)
unsigned long flags;
spin_lock_irqsave(&dev->slock,flags);
+
+ /* try to reset the hardware (SWRST) */
+ saa_writeb(SAA7134_REGION_ENABLE, 0x00);
+ saa_writeb(SAA7134_REGION_ENABLE, 0x80);
+ saa_writeb(SAA7134_REGION_ENABLE, 0x00);
+
+ /* flag current buffer as failed,
+ try to start over with the next one. */
if (q->curr) {
dprintk("timeout on %p\n",q->curr);
saa7134_buffer_finish(dev,q,STATE_ERROR);
@@ -400,7 +423,7 @@ void saa7134_buffer_timeout(unsigned long data)
int saa7134_set_dmabits(struct saa7134_dev *dev)
{
- unsigned long task=0, ctrl=0, irq=0, split = 0;
+ u32 split, task=0, ctrl=0, irq=0;
enum v4l2_field cap = V4L2_FIELD_ANY;
enum v4l2_field ov = V4L2_FIELD_ANY;
@@ -460,12 +483,12 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
/* set task conditions + field handling */
if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) {
- /* default config -- use full frames:
- odd A, even A, odd B, even B, repeat */
+ /* default config -- use full frames */
saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
saa_writeb(SAA7134_FIELD_HANDLING(TASK_A), 0x02);
saa_writeb(SAA7134_FIELD_HANDLING(TASK_B), 0x02);
+ split = 0;
} else {
/* split fields between tasks */
if (V4L2_FIELD_TOP == cap) {
@@ -494,7 +517,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
SAA7134_MAIN_CTRL_TE5 |
SAA7134_MAIN_CTRL_TE6,
ctrl);
- dprintk("dmabits: task=0x%02lx ctrl=0x%02lx irq=0x%lx split=%s\n",
+ dprintk("dmabits: task=0x%02x ctrl=0x%02x irq=0x%x split=%s\n",
task, ctrl, irq, split ? "no" : "yes");
return 0;
@@ -508,12 +531,12 @@ static char *irqbits[] = {
"AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC",
"TRIG_ERR", "CONF_ERR", "LOAD_ERR"
};
-#define IRQBITS (sizeof(irqbits)/sizeof(char*))
+#define IRQBITS ARRAY_SIZE(irqbits)
static void print_irqstatus(struct saa7134_dev *dev, int loop,
unsigned long report, unsigned long status)
{
- int i;
+ unsigned int i;
printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx",
dev->name,loop,jiffies,report,status);
@@ -536,18 +559,19 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
{
struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
unsigned long report,status;
- int loop;
+ int loop, handled = 0;
for (loop = 0; loop < 10; loop++) {
report = saa_readl(SAA7134_IRQ_REPORT);
status = saa_readl(SAA7134_IRQ_STATUS);
- saa_writel(SAA7134_IRQ_REPORT,report);
if (0 == report) {
if (irq_debug > 1)
printk(KERN_DEBUG "%s/irq: no (more) work\n",
dev->name);
goto out;
}
+ handled = 1;
+ saa_writel(SAA7134_IRQ_REPORT,report);
if (irq_debug)
print_irqstatus(dev,loop,report,status);
@@ -582,8 +606,9 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
saa_writel(SAA7134_IRQ1,0);
saa_writel(SAA7134_IRQ2,0);
}
-out:
- return IRQ_HANDLED;
+
+ out:
+ return IRQ_RETVAL(handled);
}
/* ------------------------------------------------------------------ */
@@ -599,8 +624,14 @@ static int saa7134_hwinit(struct saa7134_dev *dev)
saa7134_vbi_init(dev);
if (card_has_ts(dev))
saa7134_ts_init(dev);
- if (card_has_audio(dev))
+
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
saa7134_oss_init(dev);
+ break;
+ }
/* RAM FIFO config */
saa_writel(SAA7134_FIFO_SIZE, 0x08070503);
@@ -634,12 +665,15 @@ static int saa7134_hwinit(struct saa7134_dev *dev)
/* enable peripheral devices */
saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
+ /* set vertical line numbering start (vbi needs this) */
+ saa_writeb(SAA7134_SOURCE_TIMING2, 0x20);
+
return 0;
}
static void __devinit must_configure_manually(void)
{
- int i,p;
+ unsigned int i,p;
printk(KERN_WARNING
"saa7134: <rant>\n"
@@ -675,18 +709,39 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
return -ENOMEM;
memset(dev,0,sizeof(*dev));
- /* pci stuff */
+ /* pci init */
dev->pci = pci_dev;
if (pci_enable_device(pci_dev)) {
err = -EIO;
goto fail1;
}
sprintf(dev->name,"saa%x[%d]",pci_dev->device,saa7134_devcount);
- if (-1 != latency) {
+
+ /* pci quirks */
+ if (pci_pci_problems) {
+ if (pci_pci_problems & PCIPCI_TRITON)
+ printk(KERN_INFO "%s: quirk: PCIPCI_TRITON\n", dev->name);
+ if (pci_pci_problems & PCIPCI_NATOMA)
+ printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA\n", dev->name);
+ if (pci_pci_problems & PCIPCI_VIAETBF)
+ printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF\n", dev->name);
+ if (pci_pci_problems & PCIPCI_VSFX)
+ printk(KERN_INFO "%s: quirk: PCIPCI_VSFX\n",dev->name);
+#ifdef PCIPCI_ALIMAGIK
+ if (pci_pci_problems & PCIPCI_ALIMAGIK) {
+ printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
+ dev->name);
+ latency = 0x0A;
+ }
+#endif
+ }
+ if (UNSET != latency) {
printk(KERN_INFO "%s: setting pci latency timer to %d\n",
dev->name,latency);
pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
}
+
+ /* print pci info */
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
@@ -710,7 +765,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
dev->board = SAA7134_BOARD_UNKNOWN;
}
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
- if (-1 != tuner[saa7134_devcount])
+ if (UNSET != tuner[saa7134_devcount])
dev->tuner_type = tuner[saa7134_devcount];
printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
dev->name,pci_dev->subsystem_vendor,
@@ -730,6 +785,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000);
dev->bmmio = (__u8*)dev->lmmio;
+ /* register i2c bus */
+ saa7134_i2c_register(dev);
+
+ /* initialize hardware */
+ saa7134_board_init(dev);
+ saa7134_hwinit(dev);
+
/* get irq */
err = request_irq(pci_dev->irq, saa7134_irq,
SA_SHIRQ | SA_INTERRUPT, dev->name, dev);
@@ -739,12 +801,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
goto fail2;
}
- /* initialize hardware */
- saa7134_hwinit(dev);
-
- /* register i2c bus + load i2c helpers */
- saa7134_i2c_register(dev);
- if (TUNER_ABSENT != card(dev).tuner_type)
+ /* load i2c helpers */
+ if (TUNER_ABSENT != dev->tuner_type)
request_module("tuner");
if (saa7134_boards[dev->board].need_tda9887)
request_module("tda9887");
@@ -793,19 +851,27 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
}
/* register oss devices */
- if (card_has_audio(dev)) {
- dev->oss.minor_dsp = register_sound_dsp(&saa7134_dsp_fops,dsp_nr);
- if (dev->oss.minor_dsp < 0)
- goto fail7;
- printk(KERN_INFO "%s: registered device dsp%d\n",
- dev->name,dev->oss.minor_dsp >> 4);
-
- dev->oss.minor_mixer =
- register_sound_mixer(&saa7134_mixer_fops,mixer_nr);
- if (dev->oss.minor_mixer < 0)
- goto fail8;
- printk(KERN_INFO "%s: registered device mixer%d\n",
- dev->name,dev->oss.minor_mixer >> 4);
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ if (oss) {
+ err = dev->oss.minor_dsp =
+ register_sound_dsp(&saa7134_dsp_fops,dsp_nr);
+ if (err < 0) {
+ goto fail7;
+ }
+ printk(KERN_INFO "%s: registered device dsp%d\n",
+ dev->name,dev->oss.minor_dsp >> 4);
+
+ err = dev->oss.minor_mixer =
+ register_sound_mixer(&saa7134_mixer_fops,mixer_nr);
+ if (err < 0)
+ goto fail8;
+ printk(KERN_INFO "%s: registered device mixer%d\n",
+ dev->name,dev->oss.minor_mixer >> 4);
+ }
+ break;
}
/* everything worked */
@@ -815,8 +881,14 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
return 0;
fail8:
- if (card_has_audio(dev))
- unregister_sound_dsp(dev->oss.minor_dsp);
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ if (oss)
+ unregister_sound_dsp(dev->oss.minor_dsp);
+ break;
+ }
fail7:
if (card_has_radio(dev))
video_unregister_device(&dev->radio_dev);
@@ -828,16 +900,21 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
fail4:
video_unregister_device(&dev->video_dev);
fail3:
- if (card_has_audio(dev))
+ saa7134_i2c_unregister(dev);
+ free_irq(pci_dev->irq, dev);
+ fail2:
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
saa7134_oss_fini(dev);
+ break;
+ }
if (card_has_ts(dev))
saa7134_ts_fini(dev);
saa7134_vbi_fini(dev);
saa7134_video_fini(dev);
saa7134_tvaudio_fini(dev);
- saa7134_i2c_unregister(dev);
- free_irq(pci_dev->irq, dev);
- fail2:
release_mem_region(pci_resource_start(pci_dev,0),
pci_resource_len(pci_dev,0));
fail1:
@@ -849,6 +926,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
{
struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
+ /* debugging ... */
+ if (irq_debug) {
+ u32 report = saa_readl(SAA7134_IRQ_REPORT);
+ u32 status = saa_readl(SAA7134_IRQ_STATUS);
+ print_irqstatus(dev,42,report,status);
+ }
+
/* disable peripheral devices */
saa_writeb(SAA7134_SPECIAL_MODE,0);
@@ -858,8 +942,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
saa_writel(SAA7134_MAIN_CTRL,0);
/* shutdown subsystems */
- if (card_has_audio(dev))
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
saa7134_oss_fini(dev);
+ break;
+ }
if (card_has_ts(dev))
saa7134_ts_fini(dev);
saa7134_vbi_fini(dev);
@@ -874,9 +963,15 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
/* unregister */
saa7134_i2c_unregister(dev);
- if (card_has_audio(dev)) {
- unregister_sound_mixer(dev->oss.minor_mixer);
- unregister_sound_dsp(dev->oss.minor_dsp);
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ if (oss) {
+ unregister_sound_mixer(dev->oss.minor_mixer);
+ unregister_sound_dsp(dev->oss.minor_dsp);
+ }
+ break;
}
if (card_has_radio(dev))
video_unregister_device(&dev->radio_dev);
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index b1249c3aca96..f49b49f5d0a1 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -153,10 +153,7 @@ static int i2c_is_busy_wait(struct saa7134_dev *dev)
status = i2c_get_status(dev);
if (!i2c_is_busy(status))
break;
- if (need_resched())
- schedule();
- else
- udelay(I2C_WAIT_DELAY);
+ saa_wait(I2C_WAIT_DELAY);
}
if (I2C_WAIT_RETRY == count)
return FALSE;
@@ -318,7 +315,7 @@ static u32 functionality(struct i2c_adapter *adap)
static int attach_inform(struct i2c_client *client)
{
struct saa7134_dev *dev = client->adapter->algo_data;
- int tuner = card(dev).tuner_type;
+ int tuner = dev->tuner_type;
saa7134_i2c_call_clients(dev,TUNER_SET_TYPE,&tuner);
return 0;
@@ -334,9 +331,9 @@ static struct i2c_algorithm saa7134_algo = {
static struct i2c_adapter saa7134_adap_template = {
.owner = THIS_MODULE,
+ .class = I2C_ADAP_CLASS_TV_ANALOG,
I2C_DEVNAME("saa7134"),
.id = I2C_ALGO_SAA7134,
- .class = I2C_ADAP_CLASS_TV_ANALOG,
.algo = &saa7134_algo,
.client_register = attach_inform,
};
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index c0d803d3e567..3431bc1e4005 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -94,8 +94,9 @@ static int dsp_buffer_free(struct saa7134_dev *dev)
static int dsp_rec_start(struct saa7134_dev *dev)
{
- int err, fmt, bswap, wswap;
- unsigned long control,flags;
+ int err, bswap, sign;
+ u32 fmt, control;
+ unsigned long flags;
/* prepare buffer */
if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma)))
@@ -110,45 +111,60 @@ static int dsp_rec_start(struct saa7134_dev *dev)
/* sample format */
switch (dev->oss.afmt) {
- case AFMT_U8: fmt = 0x00; break;
- case AFMT_S8: fmt = 0x00 | 0x04; break;
+ case AFMT_U8:
+ case AFMT_S8: fmt = 0x00; break;
case AFMT_U16_LE:
- case AFMT_U16_BE: fmt = 0x01; break;
+ case AFMT_U16_BE:
case AFMT_S16_LE:
- case AFMT_S16_BE: fmt = 0x01 | 0x04; break;
-/* 4front API specs mention these ones,
- the (2.4.15) kernel header hasn't them ... */
-#ifdef AFMT_S32_LE
- case AFMT_S32_LE:
- case AFMT_S32_BE: fmt = 0x02 | 0x04; break;
-#endif
+ case AFMT_S16_BE: fmt = 0x01; break;
default:
err = -EINVAL;
goto fail2;
}
switch (dev->oss.afmt) {
+ case AFMT_S8:
+ case AFMT_S16_LE:
+ case AFMT_S16_BE: sign = 1; break;
+ default: sign = 0; break;
+ }
+
+ switch (dev->oss.afmt) {
case AFMT_U16_BE:
- case AFMT_S16_BE: bswap = 1; wswap = 0; break;
-#ifdef AFMT_S32_LE
- case AFMT_S32_BE: bswap = 1; wswap = 1; break;
-#endif
- default: bswap = 0; wswap = 0; break;
+ case AFMT_S16_BE: bswap = 1; break;
+ default: bswap = 0; break;
}
- if (1 == dev->oss.channels)
- fmt |= (1 << 3);
- if (2 == dev->oss.channels)
- fmt |= (3 << 3);
- fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80;
-
- saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff));
- saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >> 8);
- saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16);
- saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
- dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c%c\n",
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ if (1 == dev->oss.channels)
+ fmt |= (1 << 3);
+ if (2 == dev->oss.channels)
+ fmt |= (3 << 3);
+ if (sign)
+ fmt |= 0x04;
+ fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80;
+
+ saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff));
+ saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >> 8);
+ saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16);
+ saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ if (1 == dev->oss.channels)
+ fmt |= (1 << 4);
+ if (2 == dev->oss.channels)
+ fmt |= (2 << 4);
+ if (!sign)
+ fmt |= 0x04;
+ saa_writel(0x588 >> 2, dev->oss.blksize);
+ saa_writel(0x58c >> 2, 0x543210 | (fmt << 24));
+ break;
+ }
+ dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n",
dev->oss.afmt, dev->oss.channels, fmt,
- bswap ? 'b' : '-', wswap ? 'w' : '-');
+ bswap ? 'b' : '-');
/* dma: setup channel 6 (= AUDIO) */
control = SAA7134_RS_CONTROL_BURST_16 |
@@ -156,8 +172,6 @@ static int dsp_rec_start(struct saa7134_dev *dev)
(dev->oss.pt.dma >> 12);
if (bswap)
control |= SAA7134_RS_CONTROL_BSWAP;
- if (wswap)
- control |= SAA7134_RS_CONTROL_WSWAP;
saa_writel(SAA7134_RS_BA1(6),0);
saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize);
saa_writel(SAA7134_RS_PITCH(6),0);
@@ -201,7 +215,7 @@ static int dsp_rec_stop(struct saa7134_dev *dev)
static int dsp_open(struct inode *inode, struct file *file)
{
- unsigned int minor = minor(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct saa7134_dev *h,*dev = NULL;
struct list_head *list;
int err;
@@ -259,7 +273,8 @@ static ssize_t dsp_read(struct file *file, char *buffer,
{
struct saa7134_dev *dev = file->private_data;
DECLARE_WAITQUEUE(wait, current);
- int bytes,err,ret = 0;
+ unsigned int bytes;
+ int err,ret = 0;
add_wait_queue(&dev->oss.wq, &wait);
down(&dev->oss.lock);
@@ -390,10 +405,6 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case AFMT_U16_BE:
case AFMT_S16_LE:
case AFMT_S16_BE:
-#ifdef AFMT_S32_LE
- case AFMT_S32_LE:
- case AFMT_S32_BE:
-#endif
down(&dev->oss.lock);
dev->oss.afmt = val;
if (dev->oss.recording) {
@@ -416,11 +427,6 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case AFMT_S16_LE:
case AFMT_S16_BE:
return put_user(16, (int*)arg);
-#ifdef AFMT_S32_LE
- case AFMT_S32_LE:
- case AFMT_S32_BE:
- return put_user(20, (int*)arg);
-#endif
default:
return -EINVAL;
}
@@ -499,14 +505,10 @@ struct file_operations saa7134_dsp_fops = {
/* ------------------------------------------------------------------ */
static int
-mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src)
+mixer_recsrc_7134(struct saa7134_dev *dev)
{
- static const char *iname[] = { "Oops", "TV", "LINE1", "LINE2" };
int analog_io,rate;
- dev->oss.count++;
- dev->oss.input = src;
- dprintk("mixer input = %s\n",iname[dev->oss.input]);
switch (dev->oss.input) {
case TV:
saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0);
@@ -525,27 +527,78 @@ mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src)
}
static int
-mixer_level(struct saa7134_dev *dev, enum saa7134_audio_in src, int level)
+mixer_recsrc_7133(struct saa7134_dev *dev)
{
- switch (src) {
+ u32 value = 0xbbbbbb;
+
+ switch (dev->oss.input) {
case TV:
- /* nothing */
+ value = 0xbbbb10; /* MAIN */
break;
case LINE1:
- saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x10,
- (100 == level) ? 0x00 : 0x10);
+ value = 0xbbbb32; /* AUX1 */
break;
case LINE2:
- saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20,
- (100 == level) ? 0x00 : 0x20);
+ value = 0xbbbb54; /* AUX2 */
break;
}
+ saa_dsp_writel(dev, 0x46c >> 2, value);
return 0;
}
+static int
+mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src)
+{
+ static const char *iname[] = { "Oops", "TV", "LINE1", "LINE2" };
+
+ dev->oss.count++;
+ dev->oss.input = src;
+ dprintk("mixer input = %s\n",iname[dev->oss.input]);
+
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ mixer_recsrc_7134(dev);
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ mixer_recsrc_7133(dev);
+ break;
+ }
+ return 0;
+}
+
+static int
+mixer_level(struct saa7134_dev *dev, enum saa7134_audio_in src, int level)
+{
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ switch (src) {
+ case TV:
+ /* nothing */
+ break;
+ case LINE1:
+ saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x10,
+ (100 == level) ? 0x00 : 0x10);
+ break;
+ case LINE2:
+ saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20,
+ (100 == level) ? 0x00 : 0x20);
+ break;
+ }
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ /* nothing */
+ break;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
static int mixer_open(struct inode *inode, struct file *file)
{
- unsigned int minor = minor(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct saa7134_dev *h,*dev = NULL;
struct list_head *list;
@@ -681,13 +734,20 @@ struct file_operations saa7134_mixer_fops = {
int saa7134_oss_init(struct saa7134_dev *dev)
{
+ /* general */
init_MUTEX(&dev->oss.lock);
init_waitqueue_head(&dev->oss.wq);
- dev->oss.line1 = 50;
- dev->oss.line2 = 50;
- mixer_level(dev,LINE1,dev->oss.line1);
- mixer_level(dev,LINE2,dev->oss.line2);
-
+
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ saa_writel(0x588 >> 2, 0x00000fff);
+ saa_writel(0x58c >> 2, 0x00543210);
+ saa_dsp_writel(dev, 0x46c >> 2, 0xbbbbbb);
+ break;
+ }
+
+ /* dsp */
dev->oss.rate = 32000;
if (oss_rate)
dev->oss.rate = oss_rate;
@@ -695,7 +755,13 @@ int saa7134_oss_init(struct saa7134_dev *dev)
dev->oss.rate = saa7134_boards[dev->board].i2s_rate;
dev->oss.rate = (dev->oss.rate > 40000) ? 48000 : 32000;
+ /* mixer */
+ dev->oss.line1 = 50;
+ dev->oss.line2 = 50;
+ mixer_level(dev,LINE1,dev->oss.line1);
+ mixer_level(dev,LINE2,dev->oss.line2);
mixer_recsrc(dev, (dev->oss.rate == 32000) ? TV : LINE2);
+
return 0;
}
@@ -710,7 +776,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
int next_blk, reg = 0;
spin_lock(&dev->slock);
- if (-1 == dev->oss.dma_blk) {
+ if (UNSET == dev->oss.dma_blk) {
dprintk("irq: recording stopped%s\n","");
goto done;
}
diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h
index 17e1c1fde412..ddb7f23e794f 100644
--- a/drivers/media/video/saa7134/saa7134-reg.h
+++ b/drivers/media/video/saa7134/saa7134-reg.h
@@ -9,9 +9,15 @@
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7130
# define PCI_DEVICE_ID_PHILIPS_SAA7130 0x7130
#endif
+#ifndef PCI_DEVICE_ID_PHILIPS_SAA7133
+# define PCI_DEVICE_ID_PHILIPS_SAA7133 0x7133
+#endif
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7134
# define PCI_DEVICE_ID_PHILIPS_SAA7134 0x7134
#endif
+#ifndef PCI_DEVICE_ID_PHILIPS_SAA7135
+# define PCI_DEVICE_ID_PHILIPS_SAA7135 0x7135
+#endif
/* ------------------------------------------------------------------ */
/*
@@ -329,6 +335,13 @@
/* test modes */
#define SAA7134_SPECIAL_MODE 0x1d0
+/* audio -- saa7133 + saa7135 only */
+#define SAA7135_DSP_RWSTATE 0x580
+#define SAA7135_DSP_RWSTATE_ERR (1 << 3)
+#define SAA7135_DSP_RWSTATE_IDA (1 << 2)
+#define SAA7135_DSP_RWSTATE_RDB (1 << 1)
+#define SAA7135_DSP_RWSTATE_WRR (1 << 0)
+
/* ------------------------------------------------------------------ */
/*
* Local variables:
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index 49ea9eb1e101..565fafa35846 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -52,8 +52,9 @@ static int buffer_activate(struct saa7134_dev *dev,
{
u32 control;
- dprintk("buffer_activate [%p]\n",buf);
+ dprintk("buffer_activate [%p]",buf);
buf->vb.state = STATE_ACTIVE;
+ buf->top_seen = 0;
/* dma: setup channel 5 (= TS) */
control = SAA7134_RS_CONTROL_BURST_16 |
@@ -63,11 +64,11 @@ static int buffer_activate(struct saa7134_dev *dev,
if (NULL == next)
next = buf;
if (V4L2_FIELD_TOP == buf->vb.field) {
- dprintk("[top] buf=%p next=%p",buf,next);
+ dprintk("- [top] buf=%p next=%p\n",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
} else {
- dprintk("[bottom] buf=%p next=%p",buf,next);
+ dprintk("- [bottom] buf=%p next=%p\n",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
}
@@ -86,8 +87,11 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
{
struct saa7134_dev *dev = file->private_data;
struct saa7134_buf *buf = (struct saa7134_buf *)vb;
- int lines, llength, size, err;
+ unsigned int lines, llength, size;
+ int err;
+ dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
+
llength = TS_PACKET_SIZE;
lines = TS_NR_PACKETS;
@@ -116,7 +120,6 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
goto oops;
}
buf->vb.state = STATE_PREPARED;
- buf->top_seen = 0;
buf->activate = buffer_activate;
buf->vb.field = field;
return 0;
@@ -163,7 +166,7 @@ static struct videobuf_queue_ops ts_qops = {
static int ts_open(struct inode *inode, struct file *file)
{
- unsigned int minor = minor(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct saa7134_dev *h,*dev = NULL;
struct list_head *list;
int err;
@@ -414,6 +417,7 @@ int saa7134_ts_init(struct saa7134_dev *dev)
dev->ts_q.timeout.function = saa7134_buffer_timeout;
dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q);
dev->ts_q.dev = dev;
+ dev->ts_q.need_two = 1;
videobuf_queue_init(&dev->ts.ts, &ts_qops, dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_ALTERNATE,
@@ -445,7 +449,7 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
spin_lock(&dev->slock);
if (dev->ts_q.curr) {
- field = dev->video_q.curr->vb.field;
+ field = dev->ts_q.curr->vb.field;
if (field == V4L2_FIELD_TOP) {
if ((status & 0x100000) != 0x100000)
goto done;
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 9b2cfcc54b27..c40f28da96bf 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -37,13 +37,23 @@ static unsigned int audio_debug = 0;
MODULE_PARM(audio_debug,"i");
MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]");
+static unsigned int audio_carrier = 0;
+MODULE_PARM(audio_carrier,"i");
+MODULE_PARM_DESC(audio_carrier,"audio carrier location");
+
#define dprintk(fmt, arg...) if (audio_debug) \
printk(KERN_DEBUG "%s/audio: " fmt, dev->name, ## arg)
+#define d2printk(fmt, arg...) if (audio_debug > 1) \
+ printk(KERN_DEBUG "%s/audio: " fmt, dev->name, ## arg)
#define print_regb(reg) printk("%s: reg 0x%03x [%-16s]: 0x%02x\n", \
dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg)))
+#define SCAN_INITIAL_DELAY (HZ)
+#define SCAN_SAMPLE_DELAY (HZ/10)
+
/* ------------------------------------------------------------------ */
+/* saa7134 code */
static struct saa7134_tvaudio tvaudio[] = {
{
@@ -95,6 +105,12 @@ static struct saa7134_tvaudio tvaudio[] = {
.carr2 = 5850,
.mode = TVAUDIO_NICAM_AM,
},{
+ .name = "SECAM-D/K",
+ .std = V4L2_STD_SECAM,
+ .carr1 = 6500,
+ .carr2 = -1,
+ .mode = TVAUDIO_FM_MONO,
+ },{
.name = "NTSC-M",
.std = V4L2_STD_NTSC,
.carr1 = 4500,
@@ -122,7 +138,7 @@ static void tvaudio_init(struct saa7134_dev *dev)
schedule();
else
udelay(10);
-
+
saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff);
@@ -134,9 +150,9 @@ static void tvaudio_init(struct saa7134_dev *dev)
saa_writeb(SAA7134_FM_DEMATRIX, 0x80);
}
-static __u32 tvaudio_carr2reg(__u32 carrier)
+static u32 tvaudio_carr2reg(u32 carrier)
{
- __u64 a = carrier;
+ u64 a = carrier;
a <<= 24;
do_div(a,12288);
@@ -152,17 +168,19 @@ static void tvaudio_setcarrier(struct saa7134_dev *dev,
saa_writel(SAA7134_CARRIER2_FREQ0 >> 2, tvaudio_carr2reg(secondary));
}
-static void saa7134_tvaudio_do_mute_input(struct saa7134_dev *dev)
+static void mute_input_7134(struct saa7134_dev *dev)
{
- int mute;
+ unsigned int mute;
struct saa7134_input *in;
int reg = 0;
int mask;
/* look what is to do ... */
in = dev->input;
- mute = (dev->ctl_mute || dev->automute);
- if (!card_has_audio(dev) && card(dev).mute.name) {
+ mute = (dev->ctl_mute ||
+ (dev->automute && (&card(dev).radio) != in));
+ if (PCI_DEVICE_ID_PHILIPS_SAA7130 == dev->pci->device &&
+ card(dev).mute.name) {
/* 7130 - we'll mute using some unconnected audio input */
if (mute)
in = &card(dev).mute;
@@ -171,14 +189,12 @@ static void saa7134_tvaudio_do_mute_input(struct saa7134_dev *dev)
dev->hw_input == in)
return;
-#if 1
dprintk("ctl_mute=%d automute=%d input=%s => mute=%d input=%s\n",
dev->ctl_mute,dev->automute,dev->input->name,mute,in->name);
-#endif
dev->hw_mute = mute;
dev->hw_input = in;
- if (card_has_audio(dev))
+ if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device)
/* 7134 mute */
saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xff : 0xbb);
@@ -199,25 +215,6 @@ static void saa7134_tvaudio_do_mute_input(struct saa7134_dev *dev)
saa7134_track_gpio(dev,in->name);
}
-void saa7134_tvaudio_setmute(struct saa7134_dev *dev)
-{
- saa7134_tvaudio_do_mute_input(dev);
-}
-
-void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
- struct saa7134_input *in)
-{
- dev->input = in;
- saa7134_tvaudio_do_mute_input(dev);
-}
-
-void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level)
-{
- saa_writeb(SAA7134_CHANNEL1_LEVEL, level & 0x1f);
- saa_writeb(SAA7134_CHANNEL2_LEVEL, level & 0x1f);
- saa_writeb(SAA7134_NICAM_LEVEL_ADJUST, level & 0x1f);
-}
-
static void tvaudio_setmode(struct saa7134_dev *dev,
struct saa7134_tvaudio *audio,
char *note)
@@ -274,8 +271,77 @@ static void tvaudio_setmode(struct saa7134_dev *dev,
saa_writel(0x174 >> 2, 0x0001e000); /* FIXME */
}
-int saa7134_tvaudio_getstereo(struct saa7134_dev *dev,
- struct saa7134_tvaudio *audio)
+static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(&dev->thread.wq, &wait);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(timeout);
+ remove_wait_queue(&dev->thread.wq, &wait);
+ return dev->thread.scan1 != dev->thread.scan2;
+}
+
+static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier)
+{
+ __s32 left,right,value;
+
+ if (audio_debug > 1) {
+ int i;
+ dprintk("debug %d:",carrier);
+ for (i = -150; i <= 150; i += 30) {
+ tvaudio_setcarrier(dev,carrier+i,carrier+i);
+ saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+ if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+ return -1;
+ value = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+ if (0 == i)
+ printk(" # %6d # ",value >> 16);
+ else
+ printk(" %6d",value >> 16);
+ }
+ printk("\n");
+ }
+
+ tvaudio_setcarrier(dev,carrier-90,carrier-90);
+ saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+ if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+ return -1;
+ left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+ tvaudio_setcarrier(dev,carrier+90,carrier+90);
+ saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+ if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+ return -1;
+ right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+ left >>= 16;
+ right >>= 16;
+ value = left > right ? left - right : right - left;
+ dprintk("scanning %d.%03d MHz => dc is %5d [%d/%d]\n",
+ carrier/1000,carrier%1000,value,left,right);
+ return value;
+}
+
+#if 0
+static void sifdebug_dump_regs(struct saa7134_dev *dev)
+{
+ print_regb(AUDIO_STATUS);
+ print_regb(IDENT_SIF);
+ print_regb(LEVEL_READOUT1);
+ print_regb(LEVEL_READOUT2);
+ print_regb(DCXO_IDENT_CTRL);
+ print_regb(DEMODULATOR);
+ print_regb(AGC_GAIN_SELECT);
+ print_regb(MONITOR_SELECT);
+ print_regb(FM_DEEMPHASIS);
+ print_regb(FM_DEMATRIX);
+ print_regb(SIF_SAMPLE_FREQ);
+ print_regb(ANALOG_IO_SELECT);
+}
+#endif
+
+static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio)
{
__u32 idp,nicam;
int retval = -1;
@@ -321,62 +387,42 @@ int saa7134_tvaudio_getstereo(struct saa7134_dev *dev,
return retval;
}
-static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
-{
- DECLARE_WAITQUEUE(wait, current);
-
- add_wait_queue(&dev->thread.wq, &wait);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(timeout);
- remove_wait_queue(&dev->thread.wq, &wait);
- return dev->thread.scan1 != dev->thread.scan2;
-}
-
-static int tvaudio_checkcarrier(struct saa7134_dev *dev, int carrier)
+static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio,
+ u32 mode)
{
- __s32 left,right,value;
-
- tvaudio_setcarrier(dev,carrier-100,carrier-100);
- if (tvaudio_sleep(dev,HZ/10))
- return -1;
- left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
- if (tvaudio_sleep(dev,HZ/10))
- return -1;
- left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
- tvaudio_setcarrier(dev,carrier+100,carrier+100);
- if (tvaudio_sleep(dev,HZ/10))
- return -1;
- right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
- if (tvaudio_sleep(dev,HZ/10))
- return -1;
- right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+ static char *name[] = {
+ [ V4L2_TUNER_MODE_MONO ] = "mono",
+ [ V4L2_TUNER_MODE_STEREO ] = "stereo",
+ [ V4L2_TUNER_MODE_LANG1 ] = "lang1",
+ [ V4L2_TUNER_MODE_LANG2 ] = "lang2",
+ };
+ static u32 fm[] = {
+ [ V4L2_TUNER_MODE_MONO ] = 0x00, /* ch1 */
+ [ V4L2_TUNER_MODE_STEREO ] = 0x80, /* auto */
+ [ V4L2_TUNER_MODE_LANG1 ] = 0x00, /* ch1 */
+ [ V4L2_TUNER_MODE_LANG2 ] = 0x01, /* ch2 */
+ };
+ u32 reg;
- left >>= 16;
- right >>= 16;
- value = left > right ? left - right : right - left;
- dprintk("scanning %d.%03d MHz => dc is %5d [%d/%d]\n",
- carrier/1000,carrier%1000,value,left,right);
- return value;
-}
-
-#if 0
-static void sifdebug_dump_regs(struct saa7134_dev *dev)
-{
- print_regb(AUDIO_STATUS);
- print_regb(IDENT_SIF);
- print_regb(LEVEL_READOUT1);
- print_regb(LEVEL_READOUT2);
- print_regb(DCXO_IDENT_CTRL);
- print_regb(DEMODULATOR);
- print_regb(AGC_GAIN_SELECT);
- print_regb(MONITOR_SELECT);
- print_regb(FM_DEEMPHASIS);
- print_regb(FM_DEMATRIX);
- print_regb(SIF_SAMPLE_FREQ);
- print_regb(ANALOG_IO_SELECT);
+ switch (audio->mode) {
+ case TVAUDIO_FM_MONO:
+ /* nothing to do ... */
+ break;
+ case TVAUDIO_FM_K_STEREO:
+ case TVAUDIO_FM_BG_STEREO:
+ dprintk("setstereo [fm] => %s\n",
+ name[ mode % ARRAY_SIZE(name) ]);
+ reg = fm[ mode % ARRAY_SIZE(fm) ];
+ saa_writeb(SAA7134_FM_DEMATRIX, reg);
+ break;
+ case TVAUDIO_FM_SAT_STEREO:
+ case TVAUDIO_NICAM_AM:
+ case TVAUDIO_NICAM_FM:
+ /* FIXME */
+ break;
+ }
+ return 0;
}
-#endif
static int tvaudio_thread(void *data)
{
@@ -388,7 +434,8 @@ static int tvaudio_thread(void *data)
struct saa7134_dev *dev = data;
const int *carr_scan;
int carr_vals[4];
- int i,max,carrier,audio;
+ unsigned int i, audio;
+ int max1,max2,carrier,rx,mode;
lock_kernel();
daemonize("%s", dev->name);
@@ -410,10 +457,10 @@ static int tvaudio_thread(void *data)
dev->tvaudio = NULL;
tvaudio_init(dev);
dev->automute = 1;
- saa7134_tvaudio_setmute(dev);
+ mute_input_7134(dev);
/* give the tuner some time */
- if (tvaudio_sleep(dev,HZ/2))
+ if (tvaudio_sleep(dev,SCAN_INITIAL_DELAY))
goto restart;
/* find the main carrier */
@@ -433,55 +480,280 @@ static int tvaudio_thread(void *data)
if (dev->thread.scan1 != dev->thread.scan2)
goto restart;
}
- for (carrier = 0, max = 0, i = 0; i < MAX_SCAN; i++) {
+ for (carrier = 0, max1 = 0, max2 = 0, i = 0; i < MAX_SCAN; i++) {
if (!carr_scan[i])
continue;
- if (max < carr_vals[i]) {
- max = carr_vals[i];
+ if (max1 < carr_vals[i]) {
+ max2 = max1;
+ max1 = carr_vals[i];
carrier = carr_scan[i];
+ } else if (max2 < carr_vals[i]) {
+ max2 = carr_vals[i];
}
}
- if (0 == carrier) {
- /* Oops: autoscan didn't work for some reason :-/ */
- printk(KERN_WARNING "%s/audio: oops: audio carrier "
- "scan failed\n", dev->name);
+
+ if (0 != carrier && max1 > 2000 && max1 > max2*3) {
+ /* found good carrier */
+ dprintk("found %s main sound carrier @ %d.%03d MHz [%d/%d]\n",
+ dev->tvnorm->name, carrier/1000, carrier%1000,
+ max1, max2);
+ dev->last_carrier = carrier;
+ } else if (0 != audio_carrier) {
+ /* no carrier -- try insmod option as fallback */
+ carrier = audio_carrier;
+ printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+ "using %d.%03d MHz [insmod option]\n",
+ dev->name, carrier/1000, carrier%1000);
+ } else if (0 != dev->last_carrier) {
+ /* no carrier -- try last detected one as fallback */
+ carrier = dev->last_carrier;
+ printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+ "using %d.%03d MHz [last detected]\n",
+ dev->name, carrier/1000, carrier%1000);
} else {
- dprintk("found %s main sound carrier @ %d.%03d MHz\n",
- dev->tvnorm->name,
- carrier/1000,carrier%1000);
+ /* no carrier + no fallback -- try first in list */
+ carrier = carr_scan[0];
+ printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+ "using %d.%03d MHz [default]\n",
+ dev->name, carrier/1000, carrier%1000);
}
tvaudio_setcarrier(dev,carrier,carrier);
dev->automute = 0;
+ saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00);
saa7134_tvaudio_setmute(dev);
/* find the exact tv audio norm */
- for (audio = -1, i = 0; i < TVAUDIO; i++) {
- if (dev->tvnorm->id != -1 &&
+ for (audio = UNSET, i = 0; i < TVAUDIO; i++) {
+ if (dev->tvnorm->id != UNSET &&
dev->tvnorm->id != tvaudio[i].std)
continue;
if (tvaudio[i].carr1 != carrier)
continue;
- if (-1 == audio)
+ if (UNSET == audio)
audio = i;
tvaudio_setmode(dev,&tvaudio[i],"trying");
if (tvaudio_sleep(dev,HZ))
goto restart;
- if (-1 != saa7134_tvaudio_getstereo(dev,&tvaudio[i])) {
+ if (-1 != tvaudio_getstereo(dev,&tvaudio[i])) {
audio = i;
break;
}
}
- if (-1 == audio)
+ saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x30);
+ if (UNSET == audio)
continue;
tvaudio_setmode(dev,&tvaudio[audio],"using");
+ tvaudio_setstereo(dev,&tvaudio[audio],V4L2_TUNER_MODE_MONO);
dev->tvaudio = &tvaudio[audio];
-#if 1
if (tvaudio_sleep(dev,3*HZ))
goto restart;
- saa7134_tvaudio_getstereo(dev,&tvaudio[i]);
+ rx = tvaudio_getstereo(dev,&tvaudio[i]);
+ mode = saa7134_tvaudio_rx2mode(rx);
+ tvaudio_setstereo(dev,&tvaudio[audio],mode);
+ }
+
+ done:
+ dev->thread.task = NULL;
+ if(dev->thread.notify != NULL)
+ up(dev->thread.notify);
+ return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* saa7133 / saa7135 code */
+
+static char *stdres[0x20] = {
+ [0x00] = "no standard detected",
+ [0x01] = "B/G (in progress)",
+ [0x02] = "D/K (in progress)",
+ [0x03] = "M (in progress)",
+
+ [0x04] = "B/G A2",
+ [0x05] = "B/G NICAM",
+ [0x06] = "D/K A2 (1)",
+ [0x07] = "D/K A2 (2)",
+ [0x08] = "D/K A2 (3)",
+ [0x09] = "D/K NICAM",
+ [0x0a] = "L NICAM",
+ [0x0b] = "I NICAM",
+
+ [0x0c] = "M Korea",
+ [0x0d] = "M BTSC ",
+ [0x0e] = "M EIAJ",
+
+ [0x0f] = "FM radio / IF 10.7 / 50 deemp",
+ [0x10] = "FM radio / IF 10.7 / 75 deemp",
+ [0x11] = "FM radio / IF sel / 50 deemp",
+ [0x12] = "FM radio / IF sel / 75 deemp",
+
+ [0x13 ... 0x1e ] = "unknown",
+ [0x1f] = "??? [in progress]",
+};
+
+#define DSP_RETRY 16
+#define DSP_DELAY 16
+
+static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
+{
+ int state, count = DSP_RETRY;
+
+ state = saa_readb(SAA7135_DSP_RWSTATE);
+ if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
+ printk("%s: dsp access error\n",dev->name);
+ /* FIXME: send ack ... */
+ return -EIO;
+ }
+ while (0 == (state & bit)) {
+ if (unlikely(0 == count)) {
+ printk("%s: dsp access wait timeout [bit=%s]\n",
+ dev->name,
+ (bit & SAA7135_DSP_RWSTATE_WRR) ? "WRR" :
+ (bit & SAA7135_DSP_RWSTATE_RDB) ? "RDB" :
+ (bit & SAA7135_DSP_RWSTATE_IDA) ? "IDA" :
+ "???");
+ return -EIO;
+ }
+ saa_wait(DSP_DELAY);
+ state = saa_readb(SAA7135_DSP_RWSTATE);
+ count--;
+ }
+ return 0;
+}
+
+#if 0
+static int saa_dsp_readl(struct saa7134_dev *dev, int reg, u32 *value)
+{
+ int err;
+
+ d2printk("dsp read reg 0x%x\n", reg<<2);
+ saa_readl(reg);
+ err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_RDB);
+ if (err < 0)
+ return err;
+ *value = saa_readl(reg);
+ d2printk("dsp read => 0x%06x\n", *value & 0xffffff);
+ err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_IDA);
+ if (err < 0)
+ return err;
+ return 0;
+}
#endif
+
+int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value)
+{
+ int err;
+
+ d2printk("dsp write reg 0x%x = 0x%06x\n",reg<<2,value);
+ err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
+ if (err < 0)
+ return err;
+ saa_writel(reg,value);
+ err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+static int getstereo_7133(struct saa7134_dev *dev)
+{
+ int retval = V4L2_TUNER_SUB_MONO;
+ u32 value;
+
+ value = saa_readl(0x528 >> 2);
+ if (value & 0x20)
+ retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+ if (value & 0x40)
+ retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+ return retval;
+}
+
+static int mute_input_7133(struct saa7134_dev *dev)
+{
+ u32 reg = 0;
+
+ switch (dev->input->amux) {
+ case TV: reg = 0x02; break;
+ case LINE1: reg = 0x00; break;
+ case LINE2: reg = 0x01; break;
+ }
+ if (dev->ctl_mute)
+ reg = 0x07;
+ saa_writel(0x594 >> 2, reg);
+ return 0;
+}
+
+static int tvaudio_thread_ddep(void *data)
+{
+ struct saa7134_dev *dev = data;
+ u32 value, norms;
+
+ lock_kernel();
+ daemonize("%s", dev->name);
+ dev->thread.task = current;
+ unlock_kernel();
+ if (dev->thread.notify != NULL)
+ up(dev->thread.notify);
+
+ /* unmute */
+ saa_dsp_writel(dev, 0x474 >> 2, 0x00);
+ saa_dsp_writel(dev, 0x450 >> 2, 0x00);
+
+ for (;;) {
+ if (dev->thread.exit || signal_pending(current))
+ goto done;
+ interruptible_sleep_on(&dev->thread.wq);
+ if (dev->thread.exit || signal_pending(current))
+ goto done;
+
+ restart:
+ dev->thread.scan1 = dev->thread.scan2;
+ dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
+
+ norms = 0;
+ if (dev->tvnorm->id & V4L2_STD_PAL)
+ norms |= 0x2c; /* B/G + D/K + I */
+ if (dev->tvnorm->id & V4L2_STD_NTSC)
+ norms |= 0x40; /* M */
+ if (dev->tvnorm->id & V4L2_STD_SECAM)
+ norms |= 0x18; /* L + D/K */
+ if (0 == norms)
+ norms = 0x0000007c;
+
+ /* quick & dirty -- to be fixed up later ... */
+ saa_dsp_writel(dev, 0x454 >> 2, 0);
+ saa_dsp_writel(dev, 0x454 >> 2, norms | 0x80);
+ saa_dsp_writel(dev, 0x464 >> 2, 0x000000);
+ saa_dsp_writel(dev, 0x470 >> 2, 0x101010);
+
+ if (tvaudio_sleep(dev,3*HZ))
+ goto restart;
+ value = saa_readl(0x528 >> 2) & 0xffffff;
+
+ dprintk("tvaudio thread status: 0x%x [%s%s%s]\n",
+ value, stdres[value & 0x1f],
+ (value & 0x000020) ? ",stereo" : "",
+ (value & 0x000040) ? ",dual" : "");
+ dprintk("detailed status: "
+ "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
+ (value & 0x000080) ? " A2/EIAJ pilot tone " : "",
+ (value & 0x000100) ? " A2/EIAJ dual " : "",
+ (value & 0x000200) ? " A2/EIAJ stereo " : "",
+ (value & 0x000400) ? " A2/EIAJ noise mute " : "",
+
+ (value & 0x000800) ? " BTSC/FM radio pilot " : "",
+ (value & 0x001000) ? " SAP carrier " : "",
+ (value & 0x002000) ? " BTSC stereo noise mute " : "",
+ (value & 0x004000) ? " SAP noise mute " : "",
+ (value & 0x008000) ? " VDSP " : "",
+
+ (value & 0x010000) ? " NICST " : "",
+ (value & 0x020000) ? " NICDU " : "",
+ (value & 0x040000) ? " NICAM muted " : "",
+ (value & 0x080000) ? " NICAM reserve sound " : "",
+
+ (value & 0x100000) ? " init done " : "");
}
done:
@@ -492,14 +764,89 @@ static int tvaudio_thread(void *data)
}
/* ------------------------------------------------------------------ */
+/* common stuff + external entry points */
+
+int saa7134_tvaudio_rx2mode(u32 rx)
+{
+ u32 mode;
+
+ mode = V4L2_TUNER_MODE_MONO;
+ if (rx & V4L2_TUNER_SUB_STEREO)
+ mode = V4L2_TUNER_MODE_STEREO;
+ else if (rx & V4L2_TUNER_SUB_LANG1)
+ mode = V4L2_TUNER_MODE_LANG1;
+ else if (rx & V4L2_TUNER_SUB_LANG2)
+ mode = V4L2_TUNER_MODE_LANG2;
+ return mode;
+}
+
+void saa7134_tvaudio_setmute(struct saa7134_dev *dev)
+{
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7130:
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ mute_input_7134(dev);
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ mute_input_7133(dev);
+ break;
+ }
+}
+
+void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
+ struct saa7134_input *in)
+{
+ dev->input = in;
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7130:
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ mute_input_7134(dev);
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ mute_input_7133(dev);
+ break;
+ }
+}
+
+void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level)
+{
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ saa_writeb(SAA7134_CHANNEL1_LEVEL, level & 0x1f);
+ saa_writeb(SAA7134_CHANNEL2_LEVEL, level & 0x1f);
+ saa_writeb(SAA7134_NICAM_LEVEL_ADJUST, level & 0x1f);
+ break;
+ }
+}
+
+int saa7134_tvaudio_getstereo(struct saa7134_dev *dev)
+{
+ int retval = V4L2_TUNER_SUB_MONO;
+
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ if (dev->tvaudio)
+ retval = tvaudio_getstereo(dev,dev->tvaudio);
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ retval = getstereo_7133(dev);
+ break;
+ }
+ return retval;
+}
int saa7134_tvaudio_init(struct saa7134_dev *dev)
{
DECLARE_MUTEX_LOCKED(sem);
+ int (*my_thread)(void *data) = NULL;
/* enable I2S audio output */
if (saa7134_boards[dev->board].i2s_rate) {
- int rate = (32000 == saa7134_boards[dev->board].i2s_rate) ? 0x01 : 0x03;
+ int rate = (32000 == saa7134_boards[dev->board].i2s_rate)
+ ? 0x01 : 0x03;
/* set rate */
saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate);
@@ -512,13 +859,24 @@ int saa7134_tvaudio_init(struct saa7134_dev *dev)
saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01);
}
- /* start tvaudio thread */
- init_waitqueue_head(&dev->thread.wq);
- dev->thread.notify = &sem;
- kernel_thread(tvaudio_thread,dev,0);
- down(&sem);
- dev->thread.notify = NULL;
- wake_up_interruptible(&dev->thread.wq);
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ my_thread = tvaudio_thread;
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ my_thread = tvaudio_thread_ddep;
+ break;
+ }
+ if (my_thread) {
+ /* start tvaudio thread */
+ init_waitqueue_head(&dev->thread.wq);
+ dev->thread.notify = &sem;
+ kernel_thread(my_thread,dev,0);
+ down(&sem);
+ dev->thread.notify = NULL;
+ wake_up_interruptible(&dev->thread.wq);
+ }
return 0;
}
@@ -541,8 +899,13 @@ int saa7134_tvaudio_fini(struct saa7134_dev *dev)
int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
{
- dev->thread.scan2++;
- wake_up_interruptible(&dev->thread.wq);
+ if (dev->thread.task) {
+ dev->thread.scan2++;
+ wake_up_interruptible(&dev->thread.wq);
+ } else {
+ dev->automute = 0;
+ saa7134_tvaudio_setmute(dev);
+ }
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
index 6304884509d0..cac88785ebcb 100644
--- a/drivers/media/video/saa7134/saa7134-vbi.c
+++ b/drivers/media/video/saa7134/saa7134-vbi.c
@@ -85,6 +85,7 @@ static int buffer_activate(struct saa7134_dev *dev,
dprintk("buffer_activate [%p]\n",buf);
buf->vb.state = STATE_ACTIVE;
+ buf->top_seen = 0;
task_init(dev,buf,TASK_A);
task_init(dev,buf,TASK_B);
@@ -119,7 +120,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
struct saa7134_dev *dev = fh->dev;
struct saa7134_buf *buf = (struct saa7134_buf *)vb;
struct saa7134_tvnorm *norm = dev->tvnorm;
- int lines, llength, size, err;
+ unsigned int lines, llength, size;
+ int err;
lines = norm->vbi_v_stop - norm->vbi_v_start +1;
if (lines > VBI_LINE_COUNT)
@@ -155,7 +157,6 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
goto oops;
}
buf->vb.state = STATE_PREPARED;
- buf->top_seen = 0;
buf->activate = buffer_activate;
buf->vb.field = field;
return 0;
@@ -166,7 +167,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
}
static int
-buffer_setup(struct file *file, int *count, int *size)
+buffer_setup(struct file *file, unsigned int *count, unsigned int *size)
{
struct saa7134_fh *fh = file->private_data;
struct saa7134_dev *dev = fh->dev;
@@ -241,7 +242,7 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
if (dev->vbi_q.curr) {
dev->vbi_fieldcount++;
/* make sure we have seen both fields */
- if ((status & 0x10) == 0x10) {
+ if ((status & 0x10) == 0x00) {
dev->vbi_q.curr->top_seen = 1;
goto done;
}
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index ede39b9f90b8..3afb31f847ab 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -2,7 +2,7 @@
* device driver for philips saa7134 based TV cards
* video4linux video interface
*
- * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ * (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -127,7 +127,7 @@ static struct saa7134_format formats[] = {
.vshift = 1,
}
};
-#define FORMATS (sizeof(formats)/sizeof(struct saa7134_format))
+#define FORMATS ARRAY_SIZE(formats)
static struct saa7134_tvnorm tvnorms[] = {
{
@@ -141,13 +141,15 @@ static struct saa7134_tvnorm tvnorms[] = {
.chroma_ctrl1 = 0x81,
.chroma_gain = 0x2a,
.chroma_ctrl2 = 0x06,
+ .vgate_misc = 0x1c,
.h_start = 0,
.h_stop = 719,
.video_v_start = 24,
.video_v_stop = 311,
- .vbi_v_start = 7-3, /* FIXME */
- .vbi_v_stop = 22-3,
+ .vbi_v_start = 7,
+ .vbi_v_stop = 22,
+ .src_timing = 4,
},{
.name = "NTSC",
.id = V4L2_STD_NTSC,
@@ -159,6 +161,7 @@ static struct saa7134_tvnorm tvnorms[] = {
.chroma_ctrl1 = 0x89,
.chroma_gain = 0x2a,
.chroma_ctrl2 = 0x0e,
+ .vgate_misc = 0x18,
.h_start = 0,
.h_stop = 719,
@@ -166,17 +169,19 @@ static struct saa7134_tvnorm tvnorms[] = {
.video_v_stop = 22+240,
.vbi_v_start = 10, /* FIXME */
.vbi_v_stop = 21, /* FIXME */
+ .src_timing = 1,
},{
.name = "SECAM",
.id = V4L2_STD_SECAM,
.width = 720,
.height = 576,
- .sync_control = 0x58,
+ .sync_control = 0x18, /* old: 0x58, */
.luma_control = 0x1b,
.chroma_ctrl1 = 0xd1,
.chroma_gain = 0x80,
.chroma_ctrl2 = 0x00,
+ .vgate_misc = 0x1c,
.h_start = 0,
.h_stop = 719,
@@ -184,6 +189,47 @@ static struct saa7134_tvnorm tvnorms[] = {
.video_v_stop = 311,
.vbi_v_start = 7,
.vbi_v_stop = 22,
+ .src_timing = 4,
+ },{
+ .name = "PAL-M",
+ .id = V4L2_STD_PAL_M,
+ .width = 720,
+ .height = 480,
+
+ .sync_control = 0x59,
+ .luma_control = 0x40,
+ .chroma_ctrl1 = 0xb9,
+ .chroma_gain = 0x2a,
+ .chroma_ctrl2 = 0x0e,
+ .vgate_misc = 0x18,
+
+ .h_start = 0,
+ .h_stop = 719,
+ .video_v_start = 22,
+ .video_v_stop = 22+240,
+ .vbi_v_start = 10, /* FIXME */
+ .vbi_v_stop = 21, /* FIXME */
+ .src_timing = 1,
+ },{
+ .name = "PAL-Nc",
+ .id = V4L2_STD_PAL_Nc,
+ .width = 720,
+ .height = 576,
+
+ .sync_control = 0x18,
+ .luma_control = 0x40,
+ .chroma_ctrl1 = 0xa1,
+ .chroma_gain = 0x2a,
+ .chroma_ctrl2 = 0x06,
+ .vgate_misc = 0x1c,
+
+ .h_start = 0,
+ .h_stop = 719,
+ .video_v_start = 24,
+ .video_v_stop = 311,
+ .vbi_v_start = 7,
+ .vbi_v_stop = 22,
+ .src_timing = 4,
#if 0
},{
.name = "AUTO",
@@ -196,6 +242,7 @@ static struct saa7134_tvnorm tvnorms[] = {
.chroma_ctrl1 = 0x8b,
.chroma_gain = 0x00,
.chroma_ctrl2 = 0x00,
+ .vgate_misc = 0x18,
.h_start = 0,
.h_stop = 719,
@@ -203,11 +250,11 @@ static struct saa7134_tvnorm tvnorms[] = {
.video_v_stop = 311,
.vbi_v_start = 7,
.vbi_v_stop = 22,
+ .src_timing = 4,
#endif
}
};
-#define TVNORMS (sizeof(tvnorms)/sizeof(struct saa7134_tvnorm))
-
+#define TVNORMS ARRAY_SIZE(tvnorms)
#define V4L2_CID_PRIVATE_INVERT (V4L2_CID_PRIVATE_BASE + 0)
#define V4L2_CID_PRIVATE_Y_ODD (V4L2_CID_PRIVATE_BASE + 1)
@@ -298,11 +345,11 @@ static const struct v4l2_queryctrl video_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
}
};
-const int CTRLS = (sizeof(video_ctrls)/sizeof(struct v4l2_queryctrl));
+static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls);
-static const struct v4l2_queryctrl* ctrl_by_id(int id)
+static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id)
{
- int i;
+ unsigned int i;
for (i = 0; i < CTRLS; i++)
if (video_ctrls[i].id == id)
@@ -310,9 +357,9 @@ static const struct v4l2_queryctrl* ctrl_by_id(int id)
return NULL;
}
-static struct saa7134_format* format_by_fourcc(int fourcc)
+static struct saa7134_format* format_by_fourcc(unsigned int fourcc)
{
- int i;
+ unsigned int i;
for (i = 0; i < FORMATS; i++)
if (formats[i].fourcc == fourcc)
@@ -323,7 +370,7 @@ static struct saa7134_format* format_by_fourcc(int fourcc)
/* ----------------------------------------------------------------------- */
/* resource management */
-static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, int bit)
+static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bit)
{
if (fh->resources & bit)
/* have it already allocated */
@@ -345,19 +392,19 @@ static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, int bit)
}
static
-int res_check(struct saa7134_fh *fh, int bit)
+int res_check(struct saa7134_fh *fh, unsigned int bit)
{
return (fh->resources & bit);
}
static
-int res_locked(struct saa7134_dev *dev, int bit)
+int res_locked(struct saa7134_dev *dev, unsigned int bit)
{
return (dev->resources & bit);
}
static
-void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, int bits)
+void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
{
if ((fh->resources & bits) != bits)
BUG();
@@ -393,7 +440,8 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
saa_writeb(SAA7134_ANALOG_IN_CTRL4, 0x90);
saa_writeb(SAA7134_HSYNC_START, 0xeb);
saa_writeb(SAA7134_HSYNC_STOP, 0xe0);
-
+ saa_writeb(SAA7134_SOURCE_TIMING1, norm->src_timing);
+
saa_writeb(SAA7134_SYNC_CTRL, norm->sync_control);
saa_writeb(SAA7134_LUMA_CTRL, luma_control);
saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright);
@@ -410,7 +458,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
saa_writeb(SAA7134_ANALOG_ADC, 0x01);
saa_writeb(SAA7134_VGATE_START, 0x11);
saa_writeb(SAA7134_VGATE_STOP, 0xfe);
- saa_writeb(SAA7134_MISC_VGATE_MSB, 0x18); /* FIXME */
+ saa_writeb(SAA7134_MISC_VGATE_MSB, norm->vgate_misc);
saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40);
saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80);
@@ -454,7 +502,7 @@ static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
{ 9, 15, 0, 4, 3 },
{ 10, 16, 1, 5, 3 },
};
- static const int count = sizeof(vals)/sizeof(vals[0]);
+ static const int count = ARRAY_SIZE(vals);
int i;
for (i = 0; i < count; i++)
@@ -532,14 +580,14 @@ static void set_size(struct saa7134_dev *dev, int task,
/* deinterlace y offsets */
if (interlace) {
y_odd = dev->ctl_y_odd;
- y_even = dev->ctl_y_even + yscale / 32;
+ y_even = dev->ctl_y_even;
saa_writeb(SAA7134_V_PHASE_OFFSET0(task), y_odd);
saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);
saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);
saa_writeb(SAA7134_V_PHASE_OFFSET3(task), y_even);
} else {
y_odd = dev->ctl_y_odd;
- y_even = dev->ctl_y_even + yscale / 64;
+ y_even = dev->ctl_y_even;
saa_writeb(SAA7134_V_PHASE_OFFSET0(task), y_odd);
saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);
saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);
@@ -688,7 +736,8 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
err = verify_preview(dev,&fh->win);
if (0 != err)
return err;
-
+
+ dev->ovfield = fh->win.field;
dprintk("start_preview %dx%d+%d+%d %s field=%s\n",
fh->win.w.width,fh->win.w.height,
fh->win.w.left,fh->win.w.top,
@@ -752,6 +801,7 @@ static int buffer_activate(struct saa7134_dev *dev,
dprintk("buffer_activate buf=%p\n",buf);
buf->vb.state = STATE_ACTIVE;
+ buf->top_seen = 0;
set_size(dev,TASK_A,buf->vb.width,buf->vb.height,
V4L2_FIELD_HAS_BOTH(buf->vb.field));
@@ -828,7 +878,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
struct saa7134_fh *fh = file->private_data;
struct saa7134_dev *dev = fh->dev;
struct saa7134_buf *buf = (struct saa7134_buf *)vb;
- int size,err;
+ unsigned int size;
+ int err;
/* sanity checks */
if (NULL == fh->fmt)
@@ -842,8 +893,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
- dprintk("buffer_prepare [size=%dx%d,bytes=%d,fields=%s,%s]\n",
- fh->width,fh->height,size,v4l2_field_names[field],
+ dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n",
+ vb->i,fh->width,fh->height,size,v4l2_field_names[field],
fh->fmt->name);
if (buf->vb.width != fh->width ||
buf->vb.height != fh->height ||
@@ -872,7 +923,6 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
goto oops;
}
buf->vb.state = STATE_PREPARED;
- buf->top_seen = 0;
buf->activate = buffer_activate;
return 0;
@@ -1081,7 +1131,7 @@ static int saa7134_resource(struct saa7134_fh *fh)
static int video_open(struct inode *inode, struct file *file)
{
- unsigned int minor = minor(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct saa7134_dev *h,*dev = NULL;
struct saa7134_fh *fh;
struct list_head *list;
@@ -1117,8 +1167,8 @@ static int video_open(struct inode *inode, struct file *file)
fh->radio = radio;
fh->type = type;
fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
- fh->width = 320;
- fh->height = 240;
+ fh->width = 768;
+ fh->height = 576;
videobuf_queue_init(&fh->cap, &video_qops,
dev->pci, &dev->slock,
@@ -1138,7 +1188,9 @@ static int video_open(struct inode *inode, struct file *file)
if (fh->radio) {
/* switch to radio mode */
+ u32 v = 400*16;
saa7134_tvaudio_setinput(dev,&card(dev).radio);
+ saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&v);
saa7134_i2c_call_clients(dev,AUDC_SET_RADIO,NULL);
} else {
/* switch to video/vbi mode */
@@ -1185,7 +1237,7 @@ video_poll(struct file *file, struct poll_table_struct *wait)
buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);
} else {
down(&fh->cap.lock);
- if (-1 == fh->cap.read_off) {
+ if (UNSET == fh->cap.read_off) {
/* need to capture a new frame */
if (res_locked(fh->dev,RESOURCE_VIDEO)) {
up(&fh->cap.lock);
@@ -1263,6 +1315,29 @@ video_mmap(struct file *file, struct vm_area_struct * vma)
/* ------------------------------------------------------------------ */
+void saa7134_vbi_fmt(struct saa7134_dev *dev, struct v4l2_format *f)
+{
+ struct saa7134_tvnorm *norm = dev->tvnorm;
+
+ f->fmt.vbi.sampling_rate = 6750000 * 4;
+ f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
+ f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+ f->fmt.vbi.offset = 64 * 4;
+ f->fmt.vbi.start[0] = norm->vbi_v_start;
+ f->fmt.vbi.count[0] = norm->vbi_v_stop - norm->vbi_v_start +1;
+ f->fmt.vbi.start[1] = norm->video_v_stop + norm->vbi_v_start +1;
+ f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
+ f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */;
+
+#if 0
+ if (V4L2_STD_PAL == norm->id) {
+ /* FIXME */
+ f->fmt.vbi.start[0] += 3;
+ f->fmt.vbi.start[1] += 3*2;
+ }
+#endif
+}
+
int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
struct v4l2_format *f)
{
@@ -1273,27 +1348,17 @@ int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
f->fmt.pix.height = fh->height;
f->fmt.pix.field = fh->cap.field;
f->fmt.pix.pixelformat = fh->fmt->fourcc;
- f->fmt.pix.sizeimage =
- (fh->width*fh->height*fh->fmt->depth)/8;
+ f->fmt.pix.bytesperline =
+ (f->fmt.pix.width * fh->fmt->depth) >> 3;
+ f->fmt.pix.sizeimage =
+ f->fmt.pix.height * f->fmt.pix.bytesperline;
return 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
f->fmt.win = fh->win;
return 0;
case V4L2_BUF_TYPE_VBI_CAPTURE:
- {
- struct saa7134_tvnorm *norm = fh->dev->tvnorm;
-
- f->fmt.vbi.sampling_rate = 6750000 * 4;
- f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
- f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
- f->fmt.vbi.offset = 64 * 4;
- f->fmt.vbi.start[0] = norm->vbi_v_start;
- f->fmt.vbi.count[0] = norm->vbi_v_stop - norm->vbi_v_start +1;
- f->fmt.vbi.start[1] = norm->video_v_stop + norm->vbi_v_start + 1;
- f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
- f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */;
+ saa7134_vbi_fmt(dev,f);
return 0;
- }
default:
return -EINVAL;
}
@@ -1309,7 +1374,7 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
{
struct saa7134_format *fmt;
enum v4l2_field field;
- int maxw, maxh;
+ unsigned int maxw, maxh;
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
if (NULL == fmt)
@@ -1336,12 +1401,18 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
}
f->fmt.pix.field = field;
+ if (f->fmt.pix.width < 48)
+ f->fmt.pix.width = 48;
+ if (f->fmt.pix.height < 32)
+ f->fmt.pix.height = 32;
if (f->fmt.pix.width > maxw)
f->fmt.pix.width = maxw;
if (f->fmt.pix.height > maxh)
f->fmt.pix.height = maxh;
+ f->fmt.pix.bytesperline =
+ (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
- (fh->width * fh->height * fmt->depth)/8;
+ f->fmt.pix.height * f->fmt.pix.bytesperline;
return 0;
}
@@ -1350,6 +1421,9 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
if (0 != err)
return err;
return 0;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ saa7134_vbi_fmt(dev,f);
+ return 0;
default:
return -EINVAL;
}
@@ -1397,6 +1471,9 @@ int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
up(&dev->lock);
return 0;
break;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ saa7134_vbi_fmt(dev,f);
+ return 0;
default:
return -EINVAL;
}
@@ -1442,10 +1519,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *e = arg;
- int i;
+ unsigned int i;
i = e->index;
- if (i < 0 || i >= TVNORMS)
+ if (i >= TVNORMS)
return -EINVAL;
err = v4l2_video_std_construct(e, tvnorms[e->index].id,
tvnorms[e->index].name);
@@ -1464,7 +1541,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg;
- int i;
+ unsigned int i;
for(i = 0; i < TVNORMS; i++)
if (*id & tvnorms[i].id)
@@ -1489,7 +1566,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMINPUT:
{
struct v4l2_input *i = arg;
- int n;
+ unsigned int n;
n = i->index;
if (n >= SAA7134_INPUT_MAX)
@@ -1557,22 +1634,8 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
V4L2_TUNER_CAP_LANG1 |
V4L2_TUNER_CAP_LANG2;
t->rangehigh = 0xffffffffUL;
- t->rxsubchans = -1;
- if (dev->tvaudio)
- t->rxsubchans = saa7134_tvaudio_getstereo
- (dev,dev->tvaudio);
- if (-1 == t->rxsubchans)
- t->rxsubchans = V4L2_TUNER_SUB_MONO;
-#if 1
- /* fill audmode -- FIXME: allow manual switching */
- t->audmode = V4L2_TUNER_MODE_MONO;
- if (t->rxsubchans & V4L2_TUNER_SUB_STEREO)
- t->audmode = V4L2_TUNER_MODE_STEREO;
- else if (t->rxsubchans & V4L2_TUNER_SUB_LANG1)
- t->audmode = V4L2_TUNER_MODE_LANG1;
- else if (t->rxsubchans & V4L2_TUNER_SUB_LANG2)
- t->audmode = V4L2_TUNER_MODE_LANG2;
-#endif
+ t->rxsubchans = saa7134_tvaudio_getstereo(dev);
+ t->audmode = saa7134_tvaudio_rx2mode(t->rxsubchans);
}
if (0 != (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03))
t->signal = 0xffff;
@@ -1655,14 +1718,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
{
struct v4l2_fmtdesc *f = arg;
enum v4l2_buf_type type;
- int index;
+ unsigned int index;
index = f->index;
type = f->type;
switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (index < 0 || index >= FORMATS)
+ if (index >= FORMATS)
return -EINVAL;
if (f->type == V4L2_BUF_TYPE_VIDEO_OVERLAY &&
formats[index].planar)
@@ -1760,21 +1823,23 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
{
struct video_mbuf *mbuf = arg;
struct videobuf_queue *q;
- int i;
+ struct v4l2_requestbuffers req;
+ unsigned int i;
q = saa7134_queue(fh);
- down(&q->lock);
- err = videobuf_mmap_setup(file,q,gbuffers,gbufsize);
- if (err < 0) {
- up(&q->lock);
+ memset(&req,0,sizeof(req));
+ req.type = q->type;
+ req.count = gbuffers;
+ err = videobuf_reqbufs(file,q,&req);
+ if (err < 0)
return err;
- }
memset(mbuf,0,sizeof(*mbuf));
- mbuf->frames = gbuffers;
- mbuf->size = gbuffers * gbufsize;
- for (i = 0; i < gbuffers; i++)
- mbuf->offsets[i] = i * gbufsize;
- up(&q->lock);
+ mbuf->frames = req.count;
+ mbuf->size = 0;
+ for (i = 0; i < mbuf->frames; i++) {
+ mbuf->offsets[i] = q->bufs[i]->boff;
+ mbuf->size += q->bufs[i]->bsize;
+ }
return 0;
}
case VIDIOC_REQBUFS:
@@ -1800,7 +1865,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_STREAMOFF:
{
int res = saa7134_resource(fh);
+
err = videobuf_streamoff(file,saa7134_queue(fh));
+ if (err < 0)
+ return err;
res_free(dev,fh,res);
return 0;
}
@@ -1879,9 +1947,16 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
strcpy(a->name,"Radio");
return 0;
}
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *id = arg;
+ *id = 0;
+ return 0;
+ }
case VIDIOC_S_AUDIO:
case VIDIOC_S_TUNER:
case VIDIOC_S_INPUT:
+ case VIDIOC_S_STD:
return 0;
case VIDIOC_QUERYCTRL:
@@ -2055,7 +2130,7 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status)
if (V4L2_FIELD_HAS_BOTH(field)) {
/* make sure we have seen both fields */
- if ((status & 0x10) == 0x10) {
+ if ((status & 0x10) == 0x00) {
dev->video_q.curr->top_seen = 1;
goto done;
}
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 57f1fc42ed0a..44dc0d002483 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -28,7 +28,7 @@
#include <media/audiochip.h>
#include <media/id.h>
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,2)
+#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,8)
#ifndef TRUE
# define TRUE (1==1)
@@ -36,6 +36,7 @@
#ifndef FALSE
# define FALSE (1==0)
#endif
+#define UNSET (-1U)
/* 2.4 / 2.5 driver compatibility stuff */
@@ -67,50 +68,52 @@ enum saa7134_video_out {
struct saa7134_tvnorm {
char *name;
v4l2_std_id id;
- int width;
- int height;
+ unsigned int width;
+ unsigned int height;
/* video decoder */
- int sync_control;
- int luma_control;
- int chroma_ctrl1;
- int chroma_gain;
- int chroma_ctrl2;
+ unsigned int sync_control;
+ unsigned int luma_control;
+ unsigned int chroma_ctrl1;
+ unsigned int chroma_gain;
+ unsigned int chroma_ctrl2;
+ unsigned int vgate_misc;
/* video scaler */
- int h_start;
- int h_stop;
- int video_v_start;
- int video_v_stop;
- int vbi_v_start;
- int vbi_v_stop;
+ unsigned int h_start;
+ unsigned int h_stop;
+ unsigned int video_v_start;
+ unsigned int video_v_stop;
+ unsigned int vbi_v_start;
+ unsigned int vbi_v_stop;
+ unsigned int src_timing;
};
struct saa7134_tvaudio {
- char *name;
- int std;
- enum saa7134_tvaudio_mode mode;
- int carr1;
- int carr2;
+ char *name;
+ v4l2_std_id std;
+ enum saa7134_tvaudio_mode mode;
+ int carr1;
+ int carr2;
};
struct saa7134_format {
- char *name;
- int fourcc;
- int depth;
- int pm;
- int vshift; /* vertical downsampling (for planar yuv) */
- int hshift; /* horizontal downsampling (for planar yuv) */
- int bswap:1;
- int wswap:1;
- int yuv:1;
- int planar:1;
+ char *name;
+ unsigned int fourcc;
+ unsigned int depth;
+ unsigned int pm;
+ unsigned int vshift; /* vertical downsampling (for planar yuv) */
+ unsigned int hshift; /* horizontal downsampling (for planar yuv) */
+ unsigned int bswap:1;
+ unsigned int wswap:1;
+ unsigned int yuv:1;
+ unsigned int planar:1;
};
/* ----------------------------------------------------------- */
/* card configuration */
-#define SAA7134_BOARD_NOAUTO -1
+#define SAA7134_BOARD_NOAUTO UNSET
#define SAA7134_BOARD_UNKNOWN 0
#define SAA7134_BOARD_PROTEUS_PRO 1
#define SAA7134_BOARD_FLYVIDEO3000 2
@@ -124,38 +127,40 @@ struct saa7134_format {
#define SAA7134_BOARD_KWORLD 10
#define SAA7134_BOARD_CINERGY600 11
#define SAA7134_BOARD_MD7134 12
+#define SAA7134_BOARD_TYPHOON_90031 13
+#define SAA7134_BOARD_ELSA 14
+#define SAA7134_BOARD_ELSA_500TV 15
#define SAA7134_INPUT_MAX 8
struct saa7134_input {
char *name;
- int vmux;
+ unsigned int vmux;
enum saa7134_audio_in amux;
- int gpio;
- int tv:1;
+ unsigned int gpio;
+ unsigned int tv:1;
};
struct saa7134_board {
char *name;
- int audio_clock;
+ unsigned int audio_clock;
/* input switching */
- int gpiomask;
+ unsigned int gpiomask;
struct saa7134_input inputs[SAA7134_INPUT_MAX];
struct saa7134_input radio;
struct saa7134_input mute;
/* peripheral I/O */
- int i2s_rate;
- int has_ts;
+ unsigned int i2s_rate;
+ unsigned int has_ts;
enum saa7134_video_out video_out;
/* i2c chip info */
- int tuner_type;
- int need_tda9887:1;
+ unsigned int tuner_type;
+ unsigned int need_tda9887:1;
};
-#define card_has_audio(dev) (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7134)
#define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name)
#define card_has_ts(dev) (saa7134_boards[dev->board].has_ts)
#define card(dev) (saa7134_boards[dev->board])
@@ -189,9 +194,9 @@ struct saa7134_thread {
struct task_struct *task;
wait_queue_head_t wq;
struct semaphore *notify;
- int exit;
- int scan1;
- int scan2;
+ unsigned int exit;
+ unsigned int scan1;
+ unsigned int scan2;
};
/* buffer for one video/vbi/ts frame */
@@ -201,7 +206,7 @@ struct saa7134_buf {
/* saa7134 specific */
struct saa7134_format *fmt;
- int top_seen;
+ unsigned int top_seen;
int (*activate)(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next);
@@ -215,22 +220,23 @@ struct saa7134_dmaqueue {
struct saa7134_buf *curr;
struct list_head queue;
struct timer_list timeout;
+ unsigned int need_two;
};
/* video filehandle status */
struct saa7134_fh {
struct saa7134_dev *dev;
- int radio;
+ unsigned int radio;
enum v4l2_buf_type type;
struct v4l2_window win;
struct v4l2_clip clips[8];
- int nclips;
- int resources;
+ unsigned int nclips;
+ unsigned int resources;
/* video capture */
struct saa7134_format *fmt;
- int width,height;
+ unsigned int width,height;
struct videobuf_queue cap;
struct saa7134_pgtable pt_cap;
@@ -241,7 +247,7 @@ struct saa7134_fh {
/* TS status */
struct saa7134_ts {
- int users;
+ unsigned int users;
/* TS capture */
struct videobuf_queue ts;
@@ -253,28 +259,28 @@ struct saa7134_oss {
struct semaphore lock;
int minor_mixer;
int minor_dsp;
- int users_dsp;
+ unsigned int users_dsp;
/* mixer */
enum saa7134_audio_in input;
- int count;
- int line1;
- int line2;
+ unsigned int count;
+ unsigned int line1;
+ unsigned int line2;
/* dsp */
- int afmt;
- int rate;
- int channels;
- int recording;
- int blocks;
- int blksize;
- int bufsize;
+ unsigned int afmt;
+ unsigned int rate;
+ unsigned int channels;
+ unsigned int recording;
+ unsigned int blocks;
+ unsigned int blksize;
+ unsigned int bufsize;
struct saa7134_pgtable pt;
struct videobuf_dmabuf dma;
wait_queue_head_t wq;
- int dma_blk;
- int read_offset;
- int read_count;
+ unsigned int dma_blk;
+ unsigned int read_offset;
+ unsigned int read_count;
};
/* global device status */
@@ -284,7 +290,7 @@ struct saa7134_dev {
spinlock_t slock;
/* various device info */
- int resources;
+ unsigned int resources;
struct video_device video_dev;
struct video_device ts_dev;
struct video_device radio_dev;
@@ -300,8 +306,8 @@ struct saa7134_dev {
__u8 *bmmio;
/* config info */
- int board;
- int tuner_type;
+ unsigned int board;
+ unsigned int tuner_type;
/* i2c i/o */
struct i2c_adapter i2c_adap;
@@ -311,19 +317,19 @@ struct saa7134_dev {
/* video overlay */
struct v4l2_framebuffer ovbuf;
struct saa7134_format *ovfmt;
- int ovenable;
+ unsigned int ovenable;
enum v4l2_field ovfield;
/* video+ts+vbi capture */
struct saa7134_dmaqueue video_q;
struct saa7134_dmaqueue ts_q;
struct saa7134_dmaqueue vbi_q;
- int vbi_fieldcount;
+ unsigned int vbi_fieldcount;
/* various v4l controls */
struct saa7134_tvnorm *tvnorm; /* video */
struct saa7134_tvaudio *tvaudio;
- int ctl_input;
+ unsigned int ctl_input;
int ctl_bright;
int ctl_contrast;
int ctl_hue;
@@ -337,11 +343,12 @@ struct saa7134_dev {
int ctl_y_even;
/* other global state info */
- int automute;
+ unsigned int automute;
struct saa7134_thread thread;
struct saa7134_input *input;
struct saa7134_input *hw_input;
- int hw_mute;
+ unsigned int hw_mute;
+ int last_carrier;
};
/* ----------------------------------------------------------- */
@@ -362,12 +369,13 @@ struct saa7134_dev {
#define saa_setb(reg,bit) saa_andorb((reg),(bit),(bit))
#define saa_clearb(reg,bit) saa_andorb((reg),(bit),0)
+#define saa_wait(d) { if (need_resched()) schedule(); else udelay(d);}
/* ----------------------------------------------------------- */
/* saa7134-core.c */
extern struct list_head saa7134_devlist;
-extern int saa7134_devcount;
+extern unsigned int saa7134_devcount;
void saa7134_print_ioctl(char *name, unsigned int cmd);
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
@@ -376,18 +384,18 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt);
int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
- struct scatterlist *list, int length,
- int startpage);
+ struct scatterlist *list, unsigned int length,
+ unsigned int startpage);
void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt);
-int saa7134_buffer_count(int size, int count);
+int saa7134_buffer_count(unsigned int size, unsigned int count);
int saa7134_buffer_startpage(struct saa7134_buf *buf);
unsigned long saa7134_buffer_base(struct saa7134_buf *buf);
int saa7134_buffer_queue(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
struct saa7134_buf *buf);
void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
- int state);
+ unsigned int state);
void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
void saa7134_buffer_timeout(unsigned long data);
void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf);
@@ -398,9 +406,11 @@ int saa7134_set_dmabits(struct saa7134_dev *dev);
/* saa7134-cards.c */
extern struct saa7134_board saa7134_boards[];
-extern const int saa7134_bcount;
+extern const unsigned int saa7134_bcount;
extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
+extern int saa7134_board_init(struct saa7134_dev *dev);
+
/* ----------------------------------------------------------- */
/* saa7134-i2c.c */
@@ -449,17 +459,19 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status);
/* ----------------------------------------------------------- */
/* saa7134-tvaudio.c */
+int saa7134_tvaudio_rx2mode(u32 rx);
+
void saa7134_tvaudio_setmute(struct saa7134_dev *dev);
void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
struct saa7134_input *in);
void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level);
-int saa7134_tvaudio_getstereo(struct saa7134_dev *dev,
- struct saa7134_tvaudio *audio);
+int saa7134_tvaudio_getstereo(struct saa7134_dev *dev);
int saa7134_tvaudio_init(struct saa7134_dev *dev);
int saa7134_tvaudio_fini(struct saa7134_dev *dev);
int saa7134_tvaudio_do_scan(struct saa7134_dev *dev);
+int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value);
/* ----------------------------------------------------------- */
/* saa7134-oss.c */
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 61454f84ff7f..c74fbcc8fb8c 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -330,8 +330,6 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind)
i2c_set_clientdata(client, t);
do_tda7432_init(client);
- MOD_INC_USE_COUNT;
- strncpy(client->dev.name, "TDA7432", DEVICE_NAME_SIZE);
printk(KERN_INFO "tda7432: init\n");
i2c_attach_client(client);
@@ -347,13 +345,12 @@ static int tda7432_probe(struct i2c_adapter *adap)
static int tda7432_detach(struct i2c_client *client)
{
- struct tda7432 *t = i2c_get_clientdata(client);
+ struct tda7432 *t = i2c_get_clientdata(client);
do_tda7432_init(client);
i2c_detach_client(client);
kfree(t);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -525,11 +522,9 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- .id = -1,
- .driver = &driver,
- .dev = {
- .name = "tda7432",
- },
+ I2C_DEVNAME("tda7432"),
+ .id = -1,
+ .driver = &driver,
};
static int tda7432_init(void)
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index bcb44135bef2..ef9dd4854ed0 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -161,7 +161,8 @@ static void tda9875_set(struct i2c_client *client)
struct tda9875 *tda = i2c_get_clientdata(client);
unsigned char a;
- dprintk(KERN_DEBUG "tda9875_set(%04x,%04x,%04x,%04x)\n",tda->lvol,tda->rvol,tda->bass,tda->treble);
+ dprintk(KERN_DEBUG "tda9875_set(%04x,%04x,%04x,%04x)\n",
+ tda->lvol,tda->rvol,tda->bass,tda->treble);
a = tda->lvol & 0xff;
@@ -263,8 +264,6 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind)
}
do_tda9875_init(client);
- MOD_INC_USE_COUNT;
- strncpy(client->dev.name, "TDA9875", DEVICE_NAME_SIZE);
printk(KERN_INFO "tda9875: init\n");
i2c_attach_client(client);
@@ -280,13 +279,12 @@ static int tda9875_probe(struct i2c_adapter *adap)
static int tda9875_detach(struct i2c_client *client)
{
- struct tda9875 *t = i2c_get_clientdata(client);
+ struct tda9875 *t = i2c_get_clientdata(client);
do_tda9875_init(client);
i2c_detach_client(client);
kfree(t);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -395,11 +393,9 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- .id = -1,
- .driver = &driver,
- .dev = {
- .name = "tda9875",
- },
+ I2C_DEVNAME("tda9875"),
+ .id = -1,
+ .driver = &driver,
};
static int tda9875_init(void)
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index d8aecd8acb44..080cfba95fb3 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -293,8 +293,6 @@ static int tda9887_configure(struct tda9887 *t)
unsigned char *buf = NULL;
int rc;
- printk("tda9887_configure\n");
-
if (t->radio) {
dprintk("tda9885/6/7: FM Radio mode\n");
buf = buf_fm_stereo;
@@ -358,11 +356,11 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
return -ENOMEM;
memset(t,0,sizeof(*t));
t->client = client_template;
- i2c_set_clientdata(&t->client, t);
t->pinnacle_id = -1;
+ t->tvnorm=VIDEO_MODE_PAL;
+ i2c_set_clientdata(&t->client, t);
i2c_attach_client(&t->client);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -379,7 +377,6 @@ static int tda9887_detach(struct i2c_client *client)
i2c_detach_client(client);
kfree(t);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -404,6 +401,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
int *i = arg;
t->pinnacle_id = *i;
+ tda9887_miro(t);
break;
}
/* --- v4l ioctls --- */
diff --git a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c
index b193c4c195bc..87d0b861166c 100644
--- a/drivers/media/video/tuner.c
+++ b/drivers/media/video/tuner.c
@@ -20,13 +20,15 @@ static unsigned short normal_i2c[] = {I2C_CLIENT_END};
static unsigned short normal_i2c_range[] = {0x60,0x6f,I2C_CLIENT_END};
I2C_CLIENT_INSMOD;
+#define UNSET (-1U)
+
/* insmod options */
-static int debug = 0;
-static int type = -1;
-static int addr = 0;
+static unsigned int debug = 0;
+static unsigned int type = UNSET;
+static unsigned int addr = 0;
static char *pal = "b";
-static int tv_range[2] = { 44, 958 };
-static int radio_range[2] = { 65, 108 };
+static unsigned int tv_range[2] = { 44, 958 };
+static unsigned int radio_range[2] = { 65, 108 };
MODULE_PARM(debug,"i");
MODULE_PARM(type,"i");
MODULE_PARM(addr,"i");
@@ -45,13 +47,16 @@ static int this_adap;
struct tuner
{
- int type; /* chip type */
- int freq; /* keep track of the current settings */
- int std;
-
- int radio;
- int mode; /* current norm for multi-norm tuners */
- int xogc; // only for MT2032
+ unsigned int type; /* chip type */
+ unsigned int freq; /* keep track of the current settings */
+ unsigned int std;
+
+ unsigned int radio;
+ unsigned int mode; /* current norm for multi-norm tuners */
+
+ // only for MT2032
+ unsigned int xogc;
+ unsigned int radio_if2;
};
static struct i2c_driver driver;
@@ -217,8 +222,11 @@ static struct tunertype tuners[] = {
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
{ "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC,
16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732},
+
+ { "HITACHI V7-J180AT", HITACHI, NTSC,
+ 16*170.00, 16*450.00, 0x01,0x02,0x00,0x8e,940 },
};
-#define TUNERS (sizeof(tuners)/sizeof(struct tunertype))
+#define TUNERS ARRAY_SIZE(tuners)
/* ---------------------------------------------------------------------- */
@@ -381,10 +389,15 @@ static int mt2032_spurcheck(int f1, int f2, int spectrum_from,int spectrum_to)
return 1;
}
-static int mt2032_compute_freq(int rfin, int if1, int if2, int spectrum_from,
- int spectrum_to, unsigned char *buf, int *ret_sel, int xogc) //all in Hz
+static int mt2032_compute_freq(unsigned int rfin,
+ unsigned int if1, unsigned int if2,
+ unsigned int spectrum_from,
+ unsigned int spectrum_to,
+ unsigned char *buf,
+ int *ret_sel,
+ unsigned int xogc) //all in Hz
{
- int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
+ unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
fref= 5250 *1000; //5.25MHz
@@ -513,7 +526,9 @@ static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
}
-static void mt2032_set_if_freq(struct i2c_client *c,int rfin, int if1, int if2, int from, int to)
+static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin,
+ unsigned int if1, unsigned int if2,
+ unsigned int from, unsigned int to)
{
unsigned char buf[21];
int lint_try,ret,sel,lock=0;
@@ -568,28 +583,30 @@ static void mt2032_set_if_freq(struct i2c_client *c,int rfin, int if1, int if2,
}
-static void mt2032_set_tv_freq(struct i2c_client *c, int freq, int norm)
+static void mt2032_set_tv_freq(struct i2c_client *c,
+ unsigned int freq, unsigned int norm)
{
int if2,from,to;
// signal bandwidth and picture carrier
- if(norm==VIDEO_MODE_NTSC) {
+ if (norm==VIDEO_MODE_NTSC) {
from=40750*1000;
to=46750*1000;
if2=45750*1000;
- }
- else { // Pal
+ } else {
+ // Pal
from=32900*1000;
to=39900*1000;
if2=38900*1000;
}
- mt2032_set_if_freq(c,freq* 1000*1000/16, 1090*1000*1000, if2, from, to);
+ mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
+ 1090*1000*1000, if2, from, to);
}
// Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz
-static void set_tv_freq(struct i2c_client *c, int freq)
+static void set_tv_freq(struct i2c_client *c, unsigned int freq)
{
u8 config;
u16 div;
@@ -598,7 +615,7 @@ static void set_tv_freq(struct i2c_client *c, int freq)
unsigned char buffer[4];
int rc;
- if (t->type == -1) {
+ if (t->type == UNSET) {
printk("tuner: tuner type not set\n");
return;
}
@@ -720,22 +737,23 @@ static void set_tv_freq(struct i2c_client *c, int freq)
}
-static void mt2032_set_radio_freq(struct i2c_client *c,int freq)
-{
- int if2;
-
- if2=10700*1000; // 10.7MHz FM intermediate frequency
+static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ int if2 = t->radio_if2;
// per Manual for FM tuning: first if center freq. 1085 MHz
- mt2032_set_if_freq(c,freq* 1000*1000/16, 1085*1000*1000,if2,if2,if2);
+ mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
+ 1085*1000*1000,if2,if2,if2);
}
-static void set_radio_freq(struct i2c_client *c, int freq)
+static void set_radio_freq(struct i2c_client *c, unsigned int freq)
{
struct tunertype *tun;
struct tuner *t = i2c_get_clientdata(c);
unsigned char buffer[4];
- int rc,div;
+ unsigned div;
+ int rc;
if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
printk("tuner: radio freq (%d.%02d) out of range (%d-%d)\n",
@@ -743,7 +761,7 @@ static void set_radio_freq(struct i2c_client *c, int freq)
radio_range[0],radio_range[1]);
return;
}
- if (t->type == -1) {
+ if (t->type == UNSET) {
printk("tuner: tuner type not set\n");
return;
}
@@ -798,20 +816,20 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
kfree(client);
return -ENOMEM;
}
- i2c_set_clientdata(client, t);
memset(t,0,sizeof(struct tuner));
- if (type >= 0 && type < TUNERS) {
+ i2c_set_clientdata(client, t);
+ t->type = UNSET;
+ t->radio_if2 = 10700*1000; // 10.7MHz - FM radio
+
+ if (type < TUNERS) {
t->type = type;
printk("tuner(bttv): type forced to %d (%s) [insmod]\n",t->type,tuners[t->type].name);
strncpy(client->dev.name, tuners[t->type].name, DEVICE_NAME_SIZE);
- } else {
- t->type = -1;
}
i2c_attach_client(client);
if (t->type == TUNER_MT2032)
mt2032_init(client);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -835,7 +853,6 @@ static int tuner_detach(struct i2c_client *client)
i2c_detach_client(client);
kfree(t);
kfree(client);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -843,20 +860,17 @@ static int
tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct tuner *t = i2c_get_clientdata(client);
- int *iarg = (int*)arg;
-#if 0
- __u16 *sarg = (__u16*)arg;
-#endif
+ unsigned int *iarg = (int*)arg;
switch (cmd) {
/* --- configuration --- */
case TUNER_SET_TYPE:
- if (t->type != -1) {
+ if (t->type != UNSET) {
printk("tuner: type already set (%d)\n",t->type);
return 0;
}
- if (*iarg < 0 || *iarg >= TUNERS)
+ if (*iarg >= TUNERS)
return 0;
t->type = *iarg;
printk("tuner: type set to %d (%s)\n",
@@ -868,6 +882,18 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
case AUDC_SET_RADIO:
t->radio = 1;
break;
+ case AUDC_CONFIG_PINNACLE:
+ switch (*iarg) {
+ case 2:
+ dprintk("tuner: pinnacle pal\n");
+ t->radio_if2 = 33300 * 1000;
+ break;
+ case 3:
+ dprintk("tuner: pinnacle ntsc\n");
+ t->radio_if2 = 41300 * 1000;
+ break;
+ }
+ break;
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
@@ -913,35 +939,6 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
va->mode = (tuner_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO);
return 0;
}
-
-#if 0
- /* --- old, obsolete interface --- */
- case TUNER_SET_TVFREQ:
- dprintk("tuner: tv freq set to %d.%02d\n",
- (*iarg)/16,(*iarg)%16*100/16);
- set_tv_freq(client,*iarg);
- t->radio = 0;
- t->freq = *iarg;
- break;
-
- case TUNER_SET_RADIOFREQ:
- dprintk("tuner: radio freq set to %d.%02d\n",
- (*iarg)/16,(*iarg)%16*100/16);
- set_radio_freq(client,*iarg);
- t->radio = 1;
- t->freq = *iarg;
- break;
- case TUNER_SET_MODE:
- if (t->type != TUNER_PHILIPS_SECAM) {
- dprintk("tuner: trying to change mode for other than TUNER_PHILIPS_SECAM\n");
- } else {
- int mode=(*sarg==VIDEO_MODE_SECAM)?1:0;
- dprintk("tuner: mode set to %d\n", *sarg);
- t->mode = mode;
- set_tv_freq(client,t->freq);
- }
- break;
-#endif
default:
/* nothing */
break;
@@ -964,9 +961,9 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
.flags = I2C_CLIENT_ALLOW_USE,
- .driver = &driver,
- .dev = {
- .name = "(tuner unset)",
+ .driver = &driver,
+ .dev = {
+ .name = "(tuner unset)",
},
};
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 0aaba6c19bb8..d755120966e2 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -34,19 +34,19 @@
#include "tvaudio.h"
-
/* ---------------------------------------------------------------------- */
/* insmod args */
MODULE_PARM(debug,"i");
static int debug = 0; /* insmod parameter */
-#define dprintk if (debug) printk
-
MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr");
MODULE_LICENSE("GPL");
+#define UNSET (-1U)
+#define dprintk if (debug) printk
+
/* ---------------------------------------------------------------------- */
/* our structs */
@@ -161,22 +161,24 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
unsigned char buffer[2];
if (-1 == subaddr) {
- dprintk("%s: chip_write: 0x%x\n", chip->c.dev.name, val);
+ dprintk("%s: chip_write: 0x%x\n",
+ i2c_clientname(&chip->c), val);
chip->shadow.bytes[1] = val;
buffer[0] = val;
if (1 != i2c_master_send(&chip->c,buffer,1)) {
printk(KERN_WARNING "%s: I/O error (write 0x%x)\n",
- chip->c.dev.name, val);
+ i2c_clientname(&chip->c), val);
return -1;
}
} else {
- dprintk("%s: chip_write: reg%d=0x%x\n", chip->c.dev.name, subaddr, val);
+ dprintk("%s: chip_write: reg%d=0x%x\n",
+ i2c_clientname(&chip->c), subaddr, val);
chip->shadow.bytes[subaddr+1] = val;
buffer[0] = subaddr;
buffer[1] = val;
if (2 != i2c_master_send(&chip->c,buffer,2)) {
printk(KERN_WARNING "%s: I/O error (write reg%d=0x%x)\n",
- chip->c.dev.name, subaddr, val);
+ i2c_clientname(&chip->c), subaddr, val);
return -1;
}
}
@@ -201,10 +203,10 @@ static int chip_read(struct CHIPSTATE *chip)
if (1 != i2c_master_recv(&chip->c,&buffer,1)) {
printk(KERN_WARNING "%s: I/O error (read)\n",
- chip->c.dev.name);
+ i2c_clientname(&chip->c));
return -1;
}
- dprintk("%s: chip_read: 0x%x\n",chip->c.dev.name,buffer);
+ dprintk("%s: chip_read: 0x%x\n",i2c_clientname(&chip->c),buffer);
return buffer;
}
@@ -220,11 +222,11 @@ static int chip_read2(struct CHIPSTATE *chip, int subaddr)
if (2 != i2c_transfer(chip->c.adapter,msgs,2)) {
printk(KERN_WARNING "%s: I/O error (read2)\n",
- chip->c.dev.name);
+ i2c_clientname(&chip->c));
return -1;
}
dprintk("%s: chip_read2: reg%d=0x%x\n",
- chip->c.dev.name,subaddr,read[0]);
+ i2c_clientname(&chip->c),subaddr,read[0]);
return read[0];
}
@@ -237,7 +239,7 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
/* update our shadow register set; print bytes if (debug > 0) */
dprintk("%s: chip_cmd(%s): reg=%d, data:",
- chip->c.dev.name,name,cmd->bytes[0]);
+ i2c_clientname(&chip->c),name,cmd->bytes[0]);
for (i = 1; i < cmd->count; i++) {
dprintk(" 0x%x",cmd->bytes[i]);
chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i];
@@ -246,7 +248,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)) {
- printk(KERN_WARNING "%s: I/O error (%s)\n", chip->c.dev.name, name);
+ printk(KERN_WARNING "%s: I/O error (%s)\n", i2c_clientname(&chip->c), name);
return -1;
}
return 0;
@@ -270,22 +272,18 @@ static int chip_thread(void *data)
struct CHIPSTATE *chip = data;
struct CHIPDESC *desc = chiplist + chip->type;
-#ifdef CONFIG_SMP
lock_kernel();
-#endif
- daemonize("%s", chip->c.dev.name);
+ daemonize("%s",i2c_clientname(&chip->c));
chip->thread = current;
-#ifdef CONFIG_SMP
unlock_kernel();
-#endif
- dprintk("%s: thread started\n", chip->c.dev.name);
+ dprintk("%s: thread started\n", i2c_clientname(&chip->c));
if(chip->notify != NULL)
up(chip->notify);
for (;;) {
interruptible_sleep_on(&chip->wq);
- dprintk("%s: thread wakeup\n", chip->c.dev.name);
+ dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
if (chip->done || signal_pending(current))
break;
@@ -301,7 +299,7 @@ static int chip_thread(void *data)
}
chip->thread = NULL;
- dprintk("%s: thread exiting\n", chip->c.dev.name);
+ dprintk("%s: thread exiting\n", i2c_clientname(&chip->c));
if(chip->notify != NULL)
up(chip->notify);
@@ -316,7 +314,7 @@ static void generic_checkmode(struct CHIPSTATE *chip)
if (mode == chip->prevmode)
return;
- dprintk("%s: thread checkmode\n", chip->c.dev.name);
+ dprintk("%s: thread checkmode\n", i2c_clientname(&chip->c));
chip->prevmode = mode;
if (mode & VIDEO_SOUND_STEREO)
@@ -764,9 +762,9 @@ static int tda9874a_ESP = 0x07; /* default standard: NICAM D/K */
static int tda9874a_dic = -1; /* device id. code */
/* insmod options for tda9874a */
-static int tda9874a_SIF = -1;
-static int tda9874a_AMSEL = -1;
-static int tda9874a_STD = -1;
+static unsigned int tda9874a_SIF = UNSET;
+static unsigned int tda9874a_AMSEL = UNSET;
+static unsigned int tda9874a_STD = UNSET;
MODULE_PARM(tda9874a_SIF,"i");
MODULE_PARM(tda9874a_AMSEL,"i");
MODULE_PARM(tda9874a_STD,"i");
@@ -981,7 +979,7 @@ static int tda9874a_checkit(struct CHIPSTATE *chip)
dprintk("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
if((dic == 0x11)||(dic == 0x07)) {
- dprintk("tvaudio: found tda9874%s.\n",(dic == 0x11) ? "a (new)":"h (old)");
+ printk("tvaudio: found tda9874%s.\n", (dic == 0x11) ? "a":"h");
tda9874a_dic = dic; /* remember device id. */
return 1;
}
@@ -990,35 +988,27 @@ static int tda9874a_checkit(struct CHIPSTATE *chip)
static int tda9874a_initialize(struct CHIPSTATE *chip)
{
- if(tda9874a_SIF != -1) {
- if(tda9874a_SIF == 1)
- tda9874a_GCONR = 0xc0; /* sound IF input 1 */
- else if(tda9874a_SIF == 2)
- tda9874a_GCONR = 0xc1; /* sound IF input 2 */
- else
- printk(KERN_WARNING "tda9874a: SIF parameter must be 1 or 2.\n");
- }
+ if (tda9874a_SIF > 2)
+ tda9874a_SIF = 1;
+ if (tda9874a_STD >= 8)
+ tda9874a_STD = 0;
+ if(tda9874a_AMSEL > 1)
+ tda9874a_AMSEL = 0;
+
+ if(tda9874a_SIF == 1)
+ tda9874a_GCONR = 0xc0; /* sound IF input 1 */
+ else
+ tda9874a_GCONR = 0xc1; /* sound IF input 2 */
- if(tda9874a_STD != -1) {
- if((tda9874a_STD >= 0)&&(tda9874a_STD <= 8)) {
- tda9874a_ESP = tda9874a_STD;
- tda9874a_mode = (tda9874a_STD < 5) ? 0 : 1;
- } else {
- printk(KERN_WARNING "tda9874a: STD parameter must be between 0 and 8.\n");
- }
- }
+ tda9874a_ESP = tda9874a_STD;
+ tda9874a_mode = (tda9874a_STD < 5) ? 0 : 1;
- if(tda9874a_AMSEL != -1) {
- if(tda9874a_AMSEL == 0)
- tda9874a_NCONR = 0x01; /* auto-mute: analog mono input */
- else if(tda9874a_AMSEL == 1)
- tda9874a_NCONR = 0x05; /* auto-mute: 1st carrier FM or AM */
- else
- printk(KERN_WARNING "tda9874a: AMSEL parameter must be 0 or 1.\n");
- }
+ if(tda9874a_AMSEL == 0)
+ tda9874a_NCONR = 0x01; /* auto-mute: analog mono input */
+ else
+ tda9874a_NCONR = 0x05; /* auto-mute: 1st carrier FM or AM */
tda9874a_setup(chip);
-
return 0;
}
@@ -1132,6 +1122,87 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode)
#define PIC16C54_MISC_SWITCH_TUNER 0x40 /* bit 6 , Switch to Line-in */
#define PIC16C54_MISC_SWITCH_LINE 0x80 /* bit 7 , Switch to Tuner */
+/* ---------------------------------------------------------------------- */
+/* audio chip descriptions - defines+functions for TA8874Z */
+
+// write 1st byte
+#define TA8874Z_LED_STE 0x80
+#define TA8874Z_LED_BIL 0x40
+#define TA8874Z_LED_EXT 0x20
+#define TA8874Z_MONO_SET 0x10
+#define TA8874Z_MUTE 0x08
+#define TA8874Z_F_MONO 0x04
+#define TA8874Z_MODE_SUB 0x02
+#define TA8874Z_MODE_MAIN 0x01
+
+// write 2nd byte
+//#define TA8874Z_TI 0x80 // test mode
+#define TA8874Z_SEPARATION 0x3f
+#define TA8874Z_SEPARATION_DEFAULT 0x10
+
+// read
+#define TA8874Z_B1 0x80
+#define TA8874Z_B0 0x40
+#define TA8874Z_CHAG_FLAG 0x20
+
+// B1 B0
+// mono L H
+// stereo L L
+// BIL H L
+
+static int ta8874z_getmode(struct CHIPSTATE *chip)
+{
+ int val, mode;
+
+ val = chip_read(chip);
+ mode = VIDEO_SOUND_MONO;
+ if (val & TA8874Z_B1){
+ mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }else if (!(val & TA8874Z_B0)){
+ mode |= VIDEO_SOUND_STEREO;
+ }
+ //dprintk ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode);
+ return mode;
+}
+
+static audiocmd ta8874z_stereo = { 2, {0, TA8874Z_SEPARATION_DEFAULT}};
+static audiocmd ta8874z_mono = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}};
+static audiocmd ta8874z_main = {2, { 0, TA8874Z_SEPARATION_DEFAULT}};
+static audiocmd ta8874z_sub = {2, { TA8874Z_MODE_SUB, TA8874Z_SEPARATION_DEFAULT}};
+
+static void ta8874z_setmode(struct CHIPSTATE *chip, int mode)
+{
+ int update = 1;
+ audiocmd *t = NULL;
+ dprintk("ta8874z_setmode(): mode: 0x%02x\n", mode);
+
+ switch(mode){
+ case VIDEO_SOUND_MONO:
+ t = &ta8874z_mono;
+ break;
+ case VIDEO_SOUND_STEREO:
+ t = &ta8874z_stereo;
+ break;
+ case VIDEO_SOUND_LANG1:
+ t = &ta8874z_main;
+ break;
+ case VIDEO_SOUND_LANG2:
+ t = &ta8874z_sub;
+ break;
+ default:
+ update = 0;
+ }
+
+ if(update)
+ chip_cmd(chip, "TA8874Z", t);
+}
+
+static int ta8874z_checkit(struct CHIPSTATE *chip)
+{
+ int rc;
+ rc = chip_read(chip);
+ return ((rc & 0x1f) == 0x1f) ? 1 : 0;
+}
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - struct CHIPDESC */
@@ -1143,9 +1214,11 @@ int tda9850 = 1;
int tda9855 = 1;
int tda9873 = 1;
int tda9874a = 1;
-int tea6300 = 0;
+int tea6300 = 0; // address clash with msp34xx
int tea6420 = 1;
int pic16c54 = 1;
+int ta8874z = 0; // address clash with tda9840
+
MODULE_PARM(tda8425,"i");
MODULE_PARM(tda9840,"i");
MODULE_PARM(tda9850,"i");
@@ -1155,6 +1228,7 @@ MODULE_PARM(tda9874a,"i");
MODULE_PARM(tea6300,"i");
MODULE_PARM(tea6420,"i");
MODULE_PARM(pic16c54,"i");
+MODULE_PARM(ta8874z,"i");
static struct CHIPDESC chiplist[] = {
{
@@ -1319,7 +1393,23 @@ static struct CHIPDESC chiplist[] = {
PIC16C54_MISC_SND_NOTMUTE},
.inputmute = PIC16C54_MISC_SND_MUTE,
},
- { name: NULL } /* EOF */
+ {
+ .name = "ta8874z",
+ .id = -1,
+ //.id = I2C_DRIVERID_TA8874Z,
+ .checkit = ta8874z_checkit,
+ .insmodopt = &ta8874z,
+ .addr_lo = I2C_TDA9840 >> 1,
+ .addr_hi = I2C_TDA9840 >> 1,
+ .registers = 2,
+
+ .getmode = ta8874z_getmode,
+ .setmode = ta8874z_setmode,
+ .checkmode = generic_checkmode,
+
+ .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}},
+ },
+ { .name = NULL } /* EOF */
};
@@ -1356,19 +1446,18 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
dprintk("tvaudio: no matching chip description found\n");
return -EIO;
}
- printk("tvaudio: found %s\n",desc->name);
+ printk("tvaudio: found %s @ 0x%x\n", desc->name, addr<<1);
dprintk("tvaudio: matches:%s%s%s.\n",
(desc->flags & CHIP_HAS_VOLUME) ? " volume" : "",
(desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
(desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : "");
/* fill required data structures */
- strncpy(chip->c.dev.name, desc->name, DEVICE_NAME_SIZE);
+ strcpy(i2c_clientname(&chip->c),desc->name);
chip->type = desc-chiplist;
chip->shadow.count = desc->registers+1;
chip->prevmode = -1;
/* register */
- MOD_INC_USE_COUNT;
i2c_attach_client(&chip->c);
/* initialization */
@@ -1430,7 +1519,6 @@ static int chip_detach(struct i2c_client *client)
i2c_detach_client(&chip->c);
kfree(chip);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -1444,7 +1532,7 @@ static int chip_command(struct i2c_client *client,
struct CHIPSTATE *chip = i2c_get_clientdata(client);
struct CHIPDESC *desc = chiplist + chip->type;
- dprintk("%s: chip_command 0x%x\n",chip->c.dev.name,cmd);
+ dprintk("%s: chip_command 0x%x\n",i2c_clientname(&chip->c),cmd);
switch (cmd) {
case AUDC_SET_INPUT:
@@ -1552,11 +1640,9 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- .flags = I2C_CLIENT_ALLOW_USE,
- .driver = &driver,
- .dev = {
- .name = "(unset)",
- },
+ I2C_DEVNAME("(unset)"),
+ .flags = I2C_CLIENT_ALLOW_USE,
+ .driver = &driver,
};
static int audiochip_init_module(void)
diff --git a/drivers/media/video/tvaudio.h b/drivers/media/video/tvaudio.h
index cff51a62ea50..ba29c35f6376 100644
--- a/drivers/media/video/tvaudio.h
+++ b/drivers/media/video/tvaudio.h
@@ -3,7 +3,7 @@
*/
#define I2C_TDA8425 0x82
-#define I2C_TDA9840 0x84
+#define I2C_TDA9840 0x84 /* also used by TA8874Z */
#define I2C_TDA985x_L 0xb4 /* also used by 9873 */
#define I2C_TDA985x_H 0xb6
#define I2C_TDA9874 0xb0 /* also used by 9875 */
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 7f244b001cb6..3e5ddd692fde 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -10,19 +10,16 @@
#include <linux/videodev.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
-#include <asm/semaphore.h>
-
#include <linux/sound.h>
#include <linux/soundcard.h>
+
+#include <asm/semaphore.h>
#include <asm/uaccess.h>
#define DEV_MAX 4
-static int debug = 0;
static int devnr = -1;
-
-MODULE_PARM(debug,"i");
MODULE_PARM(devnr,"i");
MODULE_AUTHOR("Gerd Knorr");
@@ -87,7 +84,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
if (cmd == SOUND_MIXER_INFO) {
mixer_info info;
strncpy(info.id, "tv card", sizeof(info.id));
- strncpy(info.name, client->dev.name, sizeof(info.name));
+ strncpy(info.name, i2c_clientname(client), sizeof(info.name));
info.modify_counter = 42 /* FIXME */;
if (copy_to_user((void *)arg, &info, sizeof(info)))
return -EFAULT;
@@ -96,7 +93,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
if (cmd == SOUND_OLD_MIXER_INFO) {
_old_mixer_info info;
strncpy(info.id, "tv card", sizeof(info.id));
- strncpy(info.name, client->dev.name, sizeof(info.name));
+ strncpy(info.name, i2c_clientname(client), sizeof(info.name));
if (copy_to_user((void *)arg, &info, sizeof(info)))
return -EFAULT;
return 0;
@@ -143,7 +140,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
case MIXER_READ(SOUND_MIXER_VOLUME):
left = (min(65536 - va.balance,32768) *
va.volume) / 32768;
- right = (min(va.balance,32768) *
+ right = (min(va.balance,(u16)32768) *
va.volume) / 32768;
ret = v4l_to_mix2(left,right);
break;
@@ -218,8 +215,8 @@ static struct i2c_driver driver = {
.name = "tv card mixer driver",
.id = I2C_DRIVERID_TVMIXER,
.flags = I2C_DF_NOTIFY,
- .attach_adapter = tvmixer_adapters,
.detach_adapter = tvmixer_adapters,
+ .attach_adapter = tvmixer_adapters,
.detach_client = tvmixer_clients,
};
@@ -238,9 +235,6 @@ static int tvmixer_adapters(struct i2c_adapter *adap)
struct list_head *item;
struct i2c_client *client;
- if (debug)
- printk("tvmixer: adapter %s\n",adap->dev.name);
-
list_for_each(item,&adap->clients) {
client = list_entry(item, struct i2c_client, list);
tvmixer_clients(client);
@@ -253,16 +247,8 @@ static int tvmixer_clients(struct i2c_client *client)
struct video_audio va;
int i,minor;
- /* TV card ??? */
- if (!(client->adapter->class & I2C_ADAP_CLASS_TV_ANALOG)) {
- /* ignore that one */
- if (debug)
- printk("tvmixer: %s is not a tv card\n",
- client->adapter->dev.name);
+ if (!(client->adapter->class & I2C_ADAP_CLASS_TV_ANALOG))
return -1;
- }
- if (debug)
- printk("tvmixer: debug: %s\n",client->dev.name);
/* unregister ?? */
for (i = 0; i < DEV_MAX; i++) {
@@ -271,7 +257,8 @@ static int tvmixer_clients(struct i2c_client *client)
unregister_sound_mixer(devices[i].minor);
devices[i].dev = NULL;
devices[i].minor = -1;
- printk("tvmixer: %s unregistered (#1)\n",client->dev.name);
+ printk("tvmixer: %s unregistered (#1)\n",
+ i2c_clientname(client));
return 0;
}
}
@@ -286,25 +273,13 @@ static int tvmixer_clients(struct i2c_client *client)
}
/* audio chip with mixer ??? */
- if (NULL == client->driver->command) {
- if (debug)
- printk("tvmixer: %s: driver->command is NULL\n",
- client->driver->name);
+ if (NULL == client->driver->command)
return -1;
- }
memset(&va,0,sizeof(va));
- if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) {
- if (debug)
- printk("tvmixer: %s: VIDIOCGAUDIO failed\n",
- client->dev.name);
+ if (0 != client->driver->command(client,VIDIOCGAUDIO,&va))
return -1;
- }
- if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) {
- if (debug)
- printk("tvmixer: %s: has no volume control\n",
- client->dev.name);
+ if (0 == (va.flags & VIDEO_AUDIO_VOLUME))
return -1;
- }
/* everything is fine, register */
if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) {
@@ -342,7 +317,7 @@ static void tvmixer_cleanup_module(void)
if (devices[i].minor != -1) {
unregister_sound_mixer(devices[i].minor);
printk("tvmixer: %s unregistered (#2)\n",
- devices[i].dev->dev.name);
+ i2c_clientname(devices[i].dev));
}
}
}
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 844aa31ed8a2..e47b835a4a5a 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -127,6 +127,8 @@ set_v4l_control(struct inode *inode,
return 0;
}
+/* ----------------------------------------------------------------- */
+
static int palette2pixelformat[] = {
[VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY,
[VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555,
@@ -145,16 +147,16 @@ static int palette2pixelformat[] = {
[VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
};
-static int
-palette_to_pixelformat(int palette)
+static unsigned int
+palette_to_pixelformat(unsigned int palette)
{
- if (palette < sizeof(palette2pixelformat)/sizeof(int))
+ if (palette < ARRAY_SIZE(palette2pixelformat))
return palette2pixelformat[palette];
else
return 0;
}
-static int
+static unsigned int
pixelformat_to_palette(int pixelformat)
{
int palette = 0;
@@ -199,66 +201,43 @@ pixelformat_to_palette(int pixelformat)
return palette;
}
-/* Do an 'in' (wait for input) select on a single file descriptor */
-/* This stuff plaigarized from linux/fs/select.c */
-#define __FD_IN(fds, n) (fds->in + n)
-#define BIT(i) (1UL << ((i)&(__NFDBITS-1)))
-#define SET(i,m) (*(m) |= (i))
-extern int do_select(int n, fd_set_bits *fds, long *timeout);
+/* ----------------------------------------------------------------- */
-
-static int
-simple_select(struct file *file)
+static int poll_one(struct file *file)
{
- fd_set_bits fds;
- char *bits;
- long timeout;
- int i, fd, n, ret, size;
-
- for (i = 0; i < current->files->max_fds; ++i)
- if (file == current->files->fd[i])
- break;
- if (i == current->files->max_fds)
- return -EINVAL;
- fd = i;
- n = fd + 1;
-
- timeout = MAX_SCHEDULE_TIMEOUT;
- /*
- * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
- * since we used fdset we need to allocate memory in units of
- * long-words.
- */
- ret = -ENOMEM;
- size = FDS_BYTES(n);
- bits = kmalloc(6 * size, GFP_KERNEL);
- if (!bits)
- goto out_nofds;
- fds.in = (unsigned long *) bits;
- fds.out = (unsigned long *) (bits + size);
- fds.ex = (unsigned long *) (bits + 2*size);
- fds.res_in = (unsigned long *) (bits + 3*size);
- fds.res_out = (unsigned long *) (bits + 4*size);
- fds.res_ex = (unsigned long *) (bits + 5*size);
-
- /* All zero except our one file descriptor bit, for input */
- memset(bits, 0, 6 * size);
- SET(BIT(fd), __FD_IN((&fds), fd / __NFDBITS));
-
- ret = do_select(n, &fds, &timeout);
-
- if (ret < 0)
- goto out;
- if (!ret) {
- ret = -ERESTARTNOHAND;
- if (signal_pending(current))
- goto out;
- ret = 0;
+ int retval = 1;
+ poll_table *table;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)
+ poll_table wait_table;
+
+ poll_initwait(&wait_table);
+ table = &wait_table;
+#else
+ struct poll_wqueues pwq;
+
+ poll_initwait(&pwq);
+ table = &pwq.pt;
+#endif
+ for (;;) {
+ int mask;
+ set_current_state(TASK_INTERRUPTIBLE);
+ mask = file->f_op->poll(file, table);
+ if (mask & POLLIN)
+ break;
+ table = NULL;
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ schedule();
}
-out:
- kfree(bits);
-out_nofds:
- return ret;
+ current->state = TASK_RUNNING;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)
+ poll_freewait(&wait_table);
+#else
+ poll_freewait(&pwq);
+#endif
+ return retval;
}
static int count_inputs(struct inode *inode,
@@ -306,6 +285,7 @@ static int check_size(struct inode *inode,
return 0;
}
+/* ----------------------------------------------------------------- */
/*
* This function is exported.
@@ -317,26 +297,36 @@ v4l_compat_translate_ioctl(struct inode *inode,
void *arg,
v4l2_kioctl drv)
{
- int err = -ENOIOCTLCMD;
+ struct v4l2_capability *cap2 = NULL;
+ struct v4l2_format *fmt2 = NULL;
+
+ struct v4l2_framebuffer fbuf2;
+ struct v4l2_input input2;
+ struct v4l2_tuner tun2;
+ struct v4l2_standard std2;
+ struct v4l2_frequency freq2;
+ struct v4l2_audio aud2;
+ struct v4l2_queryctrl qctrl2;
+ struct v4l2_buffer buf2;
+ v4l2_std_id sid;
+ int i, err = 0;
- switch (cmd)
- {
+ switch (cmd) {
case VIDIOCGCAP: /* capability */
{
struct video_capability *cap = arg;
- struct v4l2_capability cap2;
- struct v4l2_framebuffer fbuf2;
-
+
+ cap2 = kmalloc(sizeof(*cap2),GFP_KERNEL);
memset(cap, 0, sizeof(*cap));
- memset(&cap2, 0, sizeof(cap2));
+ memset(cap2, 0, sizeof(*cap2));
memset(&fbuf2, 0, sizeof(fbuf2));
- err = drv(inode, file, VIDIOC_QUERYCAP, &cap2);
+ err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
if (err < 0) {
dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
break;
}
- if (cap2.capabilities & V4L2_CAP_VIDEO_OVERLAY) {
+ if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
if (err < 0) {
dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
@@ -345,16 +335,16 @@ v4l_compat_translate_ioctl(struct inode *inode,
err = 0;
}
- memcpy(cap->name, cap2.card,
- min(sizeof(cap->name), sizeof(cap2.card)));
+ memcpy(cap->name, cap2->card,
+ min(sizeof(cap->name), sizeof(cap2->card)));
cap->name[sizeof(cap->name) - 1] = 0;
- if (cap2.capabilities & V4L2_CAP_VIDEO_CAPTURE)
+ if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
cap->type |= VID_TYPE_CAPTURE;
- if (cap2.capabilities & V4L2_CAP_TUNER)
+ if (cap2->capabilities & V4L2_CAP_TUNER)
cap->type |= VID_TYPE_TUNER;
- if (cap2.capabilities & V4L2_CAP_VBI_CAPTURE)
+ if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
cap->type |= VID_TYPE_TELETEXT;
- if (cap2.capabilities & V4L2_CAP_VIDEO_OVERLAY)
+ if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
cap->type |= VID_TYPE_OVERLAY;
if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
cap->type |= VID_TYPE_CLIPPING;
@@ -370,7 +360,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCGFBUF: /* get frame buffer */
{
struct video_buffer *buffer = arg;
- struct v4l2_framebuffer fbuf2;
err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
if (err < 0) {
@@ -412,7 +401,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSFBUF: /* set frame buffer */
{
struct video_buffer *buffer = arg;
- struct v4l2_framebuffer fbuf2;
memset(&fbuf2, 0, sizeof(fbuf2));
fbuf2.base = buffer->base;
@@ -444,36 +432,36 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCGWIN: /* get window or capture dimensions */
{
struct video_window *win = arg;
- struct v4l2_format fmt2;
+ fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
memset(win,0,sizeof(*win));
- memset(&fmt2,0,sizeof(fmt2));
+ memset(fmt2,0,sizeof(*fmt2));
- fmt2.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
- err = drv(inode, file, VIDIOC_G_FMT, &fmt2);
+ fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0)
dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
if (err == 0) {
- win->x = fmt2.fmt.win.w.left;
- win->y = fmt2.fmt.win.w.top;
- win->width = fmt2.fmt.win.w.width;
- win->height = fmt2.fmt.win.w.height;
- win->chromakey = fmt2.fmt.win.chromakey;
+ win->x = fmt2->fmt.win.w.left;
+ win->y = fmt2->fmt.win.w.top;
+ win->width = fmt2->fmt.win.w.width;
+ win->height = fmt2->fmt.win.w.height;
+ win->chromakey = fmt2->fmt.win.chromakey;
win->clips = NULL;
win->clipcount = 0;
break;
}
- fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, &fmt2);
+ fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0) {
dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
break;
}
win->x = 0;
win->y = 0;
- win->width = fmt2.fmt.pix.width;
- win->height = fmt2.fmt.pix.height;
+ win->width = fmt2->fmt.pix.width;
+ win->height = fmt2->fmt.pix.height;
win->chromakey = 0;
win->clips = NULL;
win->clipcount = 0;
@@ -482,37 +470,41 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSWIN: /* set window and/or capture dimensions */
{
struct video_window *win = arg;
- struct v4l2_format fmt2;
+ int err1,err2;
- memset(&fmt2,0,sizeof(fmt2));
- fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, &fmt2);
- if (err < 0)
+ fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ memset(fmt2,0,sizeof(*fmt2));
+ fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
+ if (err1 < 0)
dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
- if (err == 0) {
- fmt2.fmt.pix.width = win->width;
- fmt2.fmt.pix.height = win->height;
- fmt2.fmt.pix.field = V4L2_FIELD_ANY;
- err = drv(inode, file, VIDIOC_S_FMT, &fmt2);
+ if (err1 == 0) {
+ fmt2->fmt.pix.width = win->width;
+ fmt2->fmt.pix.height = win->height;
+ fmt2->fmt.pix.field = V4L2_FIELD_ANY;
+ err = drv(inode, file, VIDIOC_S_FMT, fmt2);
if (err < 0)
dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
err);
- win->width = fmt2.fmt.pix.width;
- win->height = fmt2.fmt.pix.height;
- }
-
- memset(&fmt2,0,sizeof(fmt2));
- fmt2.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
- fmt2.fmt.win.w.left = win->x;
- fmt2.fmt.win.w.top = win->y;
- fmt2.fmt.win.w.width = win->width;
- fmt2.fmt.win.w.height = win->height;
- fmt2.fmt.win.chromakey = win->chromakey;
- fmt2.fmt.win.clips = (void *)win->clips;
- fmt2.fmt.win.clipcount = win->clipcount;
- err = drv(inode, file, VIDIOC_S_FMT, &fmt2);
- if (err < 0)
+ win->width = fmt2->fmt.pix.width;
+ win->height = fmt2->fmt.pix.height;
+ }
+
+ memset(fmt2,0,sizeof(*fmt2));
+ fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ fmt2->fmt.win.w.left = win->x;
+ fmt2->fmt.win.w.top = win->y;
+ fmt2->fmt.win.w.width = win->width;
+ fmt2->fmt.win.w.height = win->height;
+ fmt2->fmt.win.chromakey = win->chromakey;
+ fmt2->fmt.win.clips = (void *)win->clips;
+ fmt2->fmt.win.clipcount = win->clipcount;
+ err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
+ if (err2 < 0)
dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);
+
+ if (err1 != 0 && err2 != 0)
+ err = err1;
break;
}
case VIDIOCCAPTURE: /* turn on/off preview */
@@ -525,8 +517,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCGCHAN: /* get input information */
{
struct video_channel *chan = arg;
- struct v4l2_input input2;
- v4l2_std_id sid;
memset(&input2,0,sizeof(input2));
input2.index = chan->channel;
@@ -568,16 +558,32 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSCHAN: /* set input */
{
struct video_channel *chan = arg;
-
+
+ sid = 0;
err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
if (err < 0)
dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
+ switch (chan->norm) {
+ case VIDEO_MODE_PAL:
+ sid = V4L2_STD_PAL;
+ break;
+ case VIDEO_MODE_NTSC:
+ sid = V4L2_STD_NTSC;
+ break;
+ case VIDEO_MODE_SECAM:
+ sid = V4L2_STD_SECAM;
+ break;
+ }
+ if (0 != sid) {
+ err = drv(inode, file, VIDIOC_S_STD, &sid);
+ if (err < 0)
+ dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
+ }
break;
}
case VIDIOCGPICT: /* get tone controls & partial capture format */
{
struct video_picture *pict = arg;
- struct v4l2_format fmt2;
pict->brightness = get_v4l_control(inode, file,
V4L2_CID_BRIGHTNESS,drv);
@@ -590,25 +596,24 @@ v4l_compat_translate_ioctl(struct inode *inode,
pict->whiteness = get_v4l_control(inode, file,
V4L2_CID_WHITENESS, drv);
- memset(&fmt2,0,sizeof(fmt2));
- fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, &fmt2);
+ fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ memset(fmt2,0,sizeof(*fmt2));
+ fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0) {
dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
break;
}
#if 0 /* FIXME */
- pict->depth = fmt2.fmt.pix.depth;
+ pict->depth = fmt2->fmt.pix.depth;
#endif
pict->palette = pixelformat_to_palette(
- fmt2.fmt.pix.pixelformat);
+ fmt2->fmt.pix.pixelformat);
break;
}
case VIDIOCSPICT: /* set tone controls & partial capture format */
{
struct video_picture *pict = arg;
- struct v4l2_format fmt2;
- struct v4l2_framebuffer fbuf2;
set_v4l_control(inode, file,
V4L2_CID_BRIGHTNESS, pict->brightness, drv);
@@ -621,16 +626,17 @@ v4l_compat_translate_ioctl(struct inode *inode,
set_v4l_control(inode, file,
V4L2_CID_WHITENESS, pict->whiteness, drv);
- memset(&fmt2,0,sizeof(fmt2));
- fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, &fmt2);
+ fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ memset(fmt2,0,sizeof(*fmt2));
+ fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0)
dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
- if (fmt2.fmt.pix.pixelformat !=
+ if (fmt2->fmt.pix.pixelformat !=
palette_to_pixelformat(pict->palette)) {
- fmt2.fmt.pix.pixelformat = palette_to_pixelformat(
+ fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
pict->palette);
- err = drv(inode, file, VIDIOC_S_FMT, &fmt2);
+ err = drv(inode, file, VIDIOC_S_FMT, fmt2);
if (err < 0)
dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err);
}
@@ -652,8 +658,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCGTUNER: /* get tuner information */
{
struct video_tuner *tun = arg;
- struct v4l2_tuner tun2;
- v4l2_std_id sid;
memset(&tun2,0,sizeof(tun2));
err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
@@ -669,6 +673,19 @@ v4l_compat_translate_ioctl(struct inode *inode,
tun->flags = 0;
tun->mode = VIDEO_MODE_AUTO;
+ for (i = 0; i < 64; i++) {
+ memset(&std2,0,sizeof(std2));
+ std2.index = i;
+ if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
+ break;
+ if (std2.id & V4L2_STD_PAL)
+ tun->flags |= VIDEO_TUNER_PAL;
+ if (std2.id & V4L2_STD_NTSC)
+ tun->flags |= VIDEO_TUNER_NTSC;
+ if (std2.id & V4L2_STD_SECAM)
+ tun->flags |= VIDEO_TUNER_SECAM;
+ }
+
err = drv(inode, file, VIDIOC_G_STD, &sid);
if (err < 0)
dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
@@ -688,21 +705,20 @@ v4l_compat_translate_ioctl(struct inode *inode,
tun->signal = tun2.signal;
break;
}
-#if 0 /* FIXME */
case VIDIOCSTUNER: /* select a tuner input */
{
- int i;
-
+#if 0 /* FIXME */
err = drv(inode, file, VIDIOC_S_INPUT, &i);
if (err < 0)
dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
+#else
+ err = 0;
+#endif
break;
}
-#endif
case VIDIOCGFREQ: /* get frequency */
{
int *freq = arg;
- struct v4l2_frequency freq2;
err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
if (err < 0)
@@ -714,7 +730,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSFREQ: /* set frequency */
{
int *freq = arg;
- struct v4l2_frequency freq2;
drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
freq2.frequency = *freq;
@@ -726,10 +741,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCGAUDIO: /* get audio properties/controls */
{
struct video_audio *aud = arg;
- struct v4l2_audio aud2;
- struct v4l2_queryctrl qctrl2;
- struct v4l2_tuner tun2;
- int v;
err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
if (err < 0) {
@@ -741,34 +752,29 @@ v4l_compat_translate_ioctl(struct inode *inode,
aud->name[sizeof(aud->name) - 1] = 0;
aud->audio = aud2.index;
aud->flags = 0;
- v = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
- if (v >= 0)
- {
- aud->volume = v;
+ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
+ if (i >= 0) {
+ aud->volume = i;
aud->flags |= VIDEO_AUDIO_VOLUME;
}
- v = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
- if (v >= 0)
- {
- aud->bass = v;
+ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
+ if (i >= 0) {
+ aud->bass = i;
aud->flags |= VIDEO_AUDIO_BASS;
}
- v = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
- if (v >= 0)
- {
- aud->treble = v;
+ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
+ if (i >= 0) {
+ aud->treble = i;
aud->flags |= VIDEO_AUDIO_TREBLE;
}
- v = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
- if (v >= 0)
- {
- aud->balance = v;
+ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
+ if (i >= 0) {
+ aud->balance = i;
aud->flags |= VIDEO_AUDIO_BALANCE;
}
- v = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
- if (v >= 0)
- {
- if (v)
+ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
+ if (i >= 0) {
+ if (i)
aud->flags |= VIDEO_AUDIO_MUTE;
aud->flags |= VIDEO_AUDIO_MUTABLE;
}
@@ -795,8 +801,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSAUDIO: /* set audio controls */
{
struct video_audio *aud = arg;
- struct v4l2_audio aud2;
- struct v4l2_tuner tun2;
memset(&aud2,0,sizeof(aud2));
memset(&tun2,0,sizeof(tun2));
@@ -844,83 +848,36 @@ v4l_compat_translate_ioctl(struct inode *inode,
break;
}
#if 0
- case VIDIOCGMBUF: /* get mmap parameters */
- {
- struct video_mbuf *mbuf = arg;
- struct v4l2_requestbuffers reqbuf2;
- struct v4l2_buffer buf2;
- struct v4l2_format fmt2, fmt2o;
- struct v4l2_capability cap2;
- int i;
-
- /* Set the format to maximum dimensions */
- if ((err = drv(inode, file, VIDIOC_QUERYCAP, &cap2)) < 0)
- break;
- fmt2o.type = V4L2_BUF_TYPE_CAPTURE;
- if ((err = drv(inode, file, VIDIOC_G_FMT, &fmt2o)) < 0)
- break;
- fmt2 = fmt2o;
- fmt2.fmt.pix.width = cap2.maxwidth;
- fmt2.fmt.pix.height = cap2.maxheight;
- fmt2.fmt.pix.flags |= V4L2_FMT_FLAG_INTERLACED;
- if ((err = drv(inode, file, VIDIOC_S_FMT, &fmt2)) < 0)
- break;
- reqbuf2.count = 2; /* v4l always used two buffers */
- reqbuf2.type = V4L2_BUF_TYPE_CAPTURE | V4L2_BUF_REQ_CONTIG;
- err = drv(inode, file, VIDIOC_REQBUFS, &reqbuf2);
- if (err < 0 || reqbuf2.count < 2 || reqbuf2.type
- != (V4L2_BUF_TYPE_CAPTURE | V4L2_BUF_REQ_CONTIG))
- {/* Driver doesn't support v4l back-compatibility */
- fmt2o.fmt.pix.flags |= V4L2_FMT_FLAG_INTERLACED;
- drv(inode, file, VIDIOC_S_FMT, &fmt2o);
- reqbuf2.count = 1;
- reqbuf2.type = V4L2_BUF_TYPE_CAPTURE;
- err = drv(inode, file, VIDIOC_REQBUFS, &reqbuf2);
- if (err < 0)
- {
- err = -EINVAL;
- break;
- }
- printk(KERN_INFO"V4L2: Device \"%s\" doesn't support"
- " v4l memory mapping\n", vfl->name);
- }
- buf2.index = 0;
- buf2.type = V4L2_BUF_TYPE_CAPTURE;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
- mbuf->size = buf2.length * reqbuf2.count;
- mbuf->frames = reqbuf2.count;
- memset(mbuf->offsets, 0, sizeof(mbuf->offsets));
- for (i = 0; i < mbuf->frames; ++i)
- mbuf->offsets[i] = i * buf2.length;
- break;
- }
+ case VIDIOCGMBUF:
+ /* v4l2 drivers must implement that themself. The
+ mmap() differences can't be translated fully
+ transparent, thus there is no point to try that */
#endif
case VIDIOCMCAPTURE: /* capture a frame */
{
struct video_mmap *mm = arg;
- struct v4l2_buffer buf2;
- struct v4l2_format fmt2;
+ fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
memset(&buf2,0,sizeof(buf2));
- memset(&fmt2,0,sizeof(fmt2));
+ memset(fmt2,0,sizeof(*fmt2));
- fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, &fmt2);
+ fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
break;
}
- if (mm->width != fmt2.fmt.pix.width ||
- mm->height != fmt2.fmt.pix.height ||
+ if (mm->width != fmt2->fmt.pix.width ||
+ mm->height != fmt2->fmt.pix.height ||
palette_to_pixelformat(mm->format) !=
- fmt2.fmt.pix.pixelformat)
+ fmt2->fmt.pix.pixelformat)
{/* New capture format... */
- fmt2.fmt.pix.width = mm->width;
- fmt2.fmt.pix.height = mm->height;
- fmt2.fmt.pix.pixelformat =
+ fmt2->fmt.pix.width = mm->width;
+ fmt2->fmt.pix.height = mm->height;
+ fmt2->fmt.pix.pixelformat =
palette_to_pixelformat(mm->format);
- fmt2.fmt.pix.field = V4L2_FIELD_ANY;
- err = drv(inode, file, VIDIOC_S_FMT, &fmt2);
+ fmt2->fmt.pix.field = V4L2_FIELD_ANY;
+ err = drv(inode, file, VIDIOC_S_FMT, fmt2);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
break;
@@ -946,7 +903,6 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSYNC: /* wait for a frame */
{
int *i = arg;
- struct v4l2_buffer buf2;
buf2.index = *i;
buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -967,7 +923,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
(V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
== V4L2_BUF_FLAG_QUEUED)
{
- err = simple_select(file);
+ err = poll_one(file);
if (err < 0 || /* error or sleep was interrupted */
err == 0) /* timeout? Shouldn't occur. */
break;
@@ -984,20 +940,80 @@ v4l_compat_translate_ioctl(struct inode *inode,
} while (err == 0 && buf2.index != *i);
break;
}
- case VIDIOCGUNIT: /* get related device minors */
- /* No translation */
- break;
- case VIDIOCGCAPTURE: /* */
- /* No translation, yet... */
- printk(KERN_INFO"v4l1-compat: VIDIOCGCAPTURE not implemented."
- " Send patches to bdirks@pacbell.net :-)\n");
- break;
- case VIDIOCSCAPTURE: /* */
- /* No translation, yet... */
- printk(KERN_INFO"v4l1-compat: VIDIOCSCAPTURE not implemented."
- " Send patches to bdirks@pacbell.net :-)\n");
+
+ case VIDIOCGVBIFMT: /* query VBI data capture format */
+ {
+ struct vbi_format *fmt = arg;
+
+ fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ memset(fmt2, 0, sizeof(*fmt2));
+ fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+
+ err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+ if (err < 0) {
+ dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
+ break;
+ }
+ memset(fmt, 0, sizeof(*fmt));
+ fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
+ fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate;
+ fmt->sample_format = VIDEO_PALETTE_RAW;
+ fmt->start[0] = fmt2->fmt.vbi.start[0];
+ fmt->count[0] = fmt2->fmt.vbi.count[0];
+ fmt->start[1] = fmt2->fmt.vbi.start[1];
+ fmt->count[1] = fmt2->fmt.vbi.count[1];
+ fmt->flags = fmt2->fmt.vbi.flags & 0x03;
+ break;
+ }
+ case VIDIOCSVBIFMT:
+ {
+ struct vbi_format *fmt = arg;
+
+ fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ memset(fmt2, 0, sizeof(*fmt2));
+
+ fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
+ fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate;
+ 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];
+ fmt2->fmt.vbi.count[1] = fmt->count[1];
+ fmt2->fmt.vbi.flags = fmt->flags;
+ err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
+ if (err < 0) {
+ dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
+ break;
+ }
+
+ if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
+ fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate ||
+ 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] ||
+ fmt2->fmt.vbi.count[1] != fmt->count[1] ||
+ fmt2->fmt.vbi.flags != fmt->flags) {
+ err = -EINVAL;
+ break;
+ }
+ err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+ if (err < 0) {
+ dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
+ break;
+ }
+ }
+
+ default:
+ err = -ENOIOCTLCMD;
break;
}
+
+ if (cap2)
+ kfree(cap2);
+ if (fmt2)
+ kfree(fmt2);
return err;
}
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index 36c155bfd42f..dd4ed151448b 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -362,21 +362,33 @@ videobuf_queue_is_busy(struct videobuf_queue *q)
{
int i;
- if (q->reading)
+ if (q->streaming) {
+ dprintk(1,"busy: streaming active\n");
return 1;
- if (q->streaming)
+ }
+ if (q->reading) {
+ dprintk(1,"busy: pending read #1\n");
return 1;
- if (q->read_buf)
+ }
+ if (q->read_buf) {
+ dprintk(1,"busy: pending read #2\n");
return 1;
+ }
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i])
continue;
- if (q->bufs[i]->map)
+ if (q->bufs[i]->map) {
+ dprintk(1,"busy: buffer #%d mapped\n",i);
return 1;
- if (q->bufs[i]->state == STATE_QUEUED)
+ }
+ if (q->bufs[i]->state == STATE_QUEUED) {
+ dprintk(1,"busy: buffer #%d queued\n",i);
return 1;
- if (q->bufs[i]->state == STATE_ACTIVE)
+ }
+ if (q->bufs[i]->state == STATE_ACTIVE) {
+ dprintk(1,"busy: buffer #%d avtive\n",i);
return 1;
+ }
}
return 0;
}
@@ -569,7 +581,7 @@ videobuf_dqbuf(struct file *file, struct videobuf_queue *q,
if (list_empty(&q->stream))
goto done;
buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
- retval = videobuf_waiton(buf,1,1);
+ retval = videobuf_waiton(buf, file->f_flags & O_NONBLOCK, 1);
if (retval < 0)
goto done;
switch (buf->state) {
@@ -925,6 +937,9 @@ static void
videobuf_vm_open(struct vm_area_struct *vma)
{
struct videobuf_mapping *map = vma->vm_private_data;
+
+ dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map,
+ map->count,vma->vm_start,vma->vm_end);
map->count++;
}
@@ -934,6 +949,9 @@ videobuf_vm_close(struct vm_area_struct *vma)
struct videobuf_mapping *map = vma->vm_private_data;
int i;
+ dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map,
+ map->count,vma->vm_start,vma->vm_end);
+
/* down(&fh->lock); FIXME */
map->count--;
if (0 == map->count) {
@@ -1081,11 +1099,11 @@ int videobuf_mmap_mapper(struct vm_area_struct *vma,
q->bufs[i]->map = map;
q->bufs[i]->baddr = vma->vm_start + size;
}
- map->count = 1;
- map->start = vma->vm_start;
- map->end = vma->vm_end;
- map->q = q;
- vma->vm_ops = &videobuf_vm_ops;
+ map->count = 1;
+ map->start = vma->vm_start;
+ map->end = vma->vm_end;
+ map->q = q;
+ vma->vm_ops = &videobuf_vm_ops;
vma->vm_flags |= VM_DONTEXPAND;
vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
vma->vm_private_data = map;
@@ -1119,6 +1137,7 @@ EXPORT_SYMBOL_GPL(videobuf_queue_init);
EXPORT_SYMBOL_GPL(videobuf_queue_cancel);
EXPORT_SYMBOL_GPL(videobuf_queue_is_busy);
+EXPORT_SYMBOL_GPL(videobuf_next_field);
EXPORT_SYMBOL_GPL(videobuf_status);
EXPORT_SYMBOL_GPL(videobuf_reqbufs);
EXPORT_SYMBOL_GPL(videobuf_querybuf);
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 7eb3df17ebf5..daa8a8273c04 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -466,6 +466,9 @@ enum vortex_chips {
CH_3C920,
CH_3C982A,
CH_3C982B,
+
+ CH_905BT4,
+ CH_920B_EMB_WNM,
};
@@ -565,6 +568,11 @@ static struct vortex_chip_info {
{"3c982 Hydra Dual Port B",
PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
+ {"3c905B-T4",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+ {"3c920B-EMB-WNM Tornado",
+ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
+
{0,}, /* 0 terminated list. */
};
@@ -611,6 +619,10 @@ static struct pci_device_id vortex_pci_tbl[] __devinitdata = {
{ 0x10B7, 0x9201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C920 },
{ 0x10B7, 0x1201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C982A },
{ 0x10B7, 0x1202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C982B },
+
+ { 0x10B7, 0x9056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_905BT4 },
+ { 0x10B7, 0x9210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_920B_EMB_WNM },
+
{0,} /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
@@ -2321,7 +2333,6 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
long ioaddr;
int status;
int work_done = max_interrupt_work;
- int handled;
ioaddr = dev->base_addr;
@@ -2336,18 +2347,14 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (vortex_debug > 6)
printk(KERN_DEBUG "boomerang_interrupt. status=0x%4x\n", status);
- if ((status & IntLatch) == 0) {
- handled = 0;
+ if ((status & IntLatch) == 0)
goto handler_exit; /* No interrupt: shared IRQs can cause this */
- }
if (status == 0xffff) { /* h/w no longer present (hotplug)? */
if (vortex_debug > 1)
printk(KERN_DEBUG "boomerang_interrupt(1): status = 0xffff\n");
- handled = 0;
goto handler_exit;
}
- handled = 1;
if (status & IntReq) {
status |= vp->deferred;
@@ -2442,7 +2449,7 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dev->name, status);
handler_exit:
spin_unlock(&vp->lock);
- return IRQ_RETVAL(handled);
+ return IRQ_HANDLED;
}
static int vortex_rx(struct net_device *dev)
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 3aa5c482d3bb..76ba172d5e39 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -803,7 +803,7 @@ int __init ppp_init(void)
S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
}
- if (!err)
+ if (err)
printk(KERN_ERR "failed to register PPP device (%d)\n", err);
return err;
}
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
index 0ca895cf8a66..dfe9b2b44120 100644
--- a/drivers/net/wan/sdla_chdlc.c
+++ b/drivers/net/wan/sdla_chdlc.c
@@ -1071,7 +1071,7 @@ static void disable_comm (sdla_t *card)
card->tty=NULL;
tty_card_map[card->tty_minor]=NULL;
state = &rs_table[card->tty_minor];
- memset(state,0,sizeof(state));
+ memset(state, 0, sizeof(*state));
}
return;
}
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 3b5890316ea4..b760b186ebd3 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4838,7 +4838,7 @@ static int airo_get_range(struct net_device *dev,
readCapabilityRid(local, &cap_rid);
dwrq->length = sizeof(struct iw_range);
- memset(range, 0, sizeof(range));
+ memset(range, 0, sizeof(*range));
range->min_nwid = 0x0000;
range->max_nwid = 0x0000;
range->num_channels = 14;
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
index 8fbbe5747188..87aa28e962c5 100644
--- a/drivers/pci/pci.ids
+++ b/drivers/pci/pci.ids
@@ -2264,6 +2264,7 @@
1028 0095 Integrated 3C905C-TX Fast Etherlink for PC Management NIC
10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC
10b7 7000 10/100 Mini PCI Ethernet Adapter
+ 9210 3C920B-EMB-WNM Integrated Fast Ethernet Controller
9300 3CSOHO100B-TX [910-A01]
9800 3c980-TX [Fast Etherlink XL Server Adapter]
10b7 9800 3c980-TX Fast Etherlink XL Server Adapter
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 16929cb0c10c..7ac6bcd6e032 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -4664,7 +4664,7 @@ mega_is_bios_enabled(adapter_t *adapter)
mbox = (mbox_t *)raw_mbox;
- memset(mbox, 0, sizeof(mbox));
+ memset(mbox, 0, sizeof(*mbox));
memset((void *)adapter->mega_buffer, 0, MEGA_BUFFER_SIZE);
@@ -4697,7 +4697,7 @@ mega_enum_raid_scsi(adapter_t *adapter)
mbox = (mbox_t *)raw_mbox;
- memset(mbox, 0, sizeof(mbox));
+ memset(mbox, 0, sizeof(*mbox));
/*
* issue command to find out what channels are raid/scsi
@@ -4818,7 +4818,7 @@ mega_support_random_del(adapter_t *adapter)
mbox = (mbox_t *)raw_mbox;
- memset(mbox, 0, sizeof(mbox));
+ memset(mbox, 0, sizeof(*mbox));
/*
* issue command
@@ -4847,7 +4847,7 @@ mega_support_ext_cdb(adapter_t *adapter)
mbox = (mbox_t *)raw_mbox;
- memset(mbox, 0, sizeof (mbox));
+ memset(mbox, 0, sizeof(*mbox));
/*
* issue command to find out if controller supports extended CDBs.
*/
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index e7c027d4c8ca..4c8f33e5f99b 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -2840,8 +2840,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
}
/* map the regions */
- rinfo->mmio_base = (u32) ioremap (rinfo->mmio_base_phys,
- RADEON_REGSIZE);
+ rinfo->mmio_base = (unsigned long) ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
if (!rinfo->mmio_base) {
printk ("radeonfb: cannot map MMIO\n");
release_mem_region (rinfo->mmio_base_phys,
@@ -2978,8 +2977,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
}
}
- rinfo->fb_base = (u32) ioremap (rinfo->fb_base_phys,
- rinfo->video_ram);
+ rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys, rinfo->video_ram);
if (!rinfo->fb_base) {
printk ("radeonfb: cannot map FB\n");
iounmap ((void*)rinfo->mmio_base);
diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c
index 17b5ba21e222..7aa23490541f 100644
--- a/fs/cifs/md5.c
+++ b/fs/cifs/md5.c
@@ -148,7 +148,7 @@ MD5Final(unsigned char digest[16], struct MD5Context *ctx)
MD5Transform(ctx->buf, (__u32 *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memmove(digest, ctx->buf, 16);
- memset(ctx, 0, sizeof (ctx)); /* In case it's sensitive */
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
diff --git a/fs/open.c b/fs/open.c
index f3d0de4d7867..b8ea4700af59 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -902,7 +902,7 @@ asmlinkage long sys_vhangup(void)
/*
* Called when an inode is about to be open.
- * We use this to disallow opening RW large files on 32bit systems if
+ * We use this to disallow opening large files on 32bit systems if
* the caller didn't specify O_LARGEFILE. On 64bit systems we force
* on this flag in sys_open.
*/
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 65d2824a0cbf..a81a2c5d7bf1 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -9,6 +9,7 @@
#include <linux/errno.h>
#include <linux/buffer_head.h>
#include <linux/kernel.h>
+#include <linux/pagemap.h>
#include <linux/reiserfs_fs_sb.h>
#include <linux/reiserfs_fs_i.h>
@@ -733,7 +734,7 @@ static inline int allocate_without_wrapping_disk (reiserfs_blocknr_hint_t * hint
int rest = amount_needed;
int nr_allocated;
- while (rest > 0) {
+ while (rest > 0 && start <= finish) {
nr_allocated = scan_bitmap (hint->th, &start, finish, 1,
rest + prealloc_size, !hint->formatted_node,
hint->block);
@@ -879,7 +880,9 @@ void reiserfs_claim_blocks_to_be_allocated(
if ( !blocks )
return;
+ spin_lock(&REISERFS_SB(sb)->bitmap_lock);
REISERFS_SB(sb)->reserved_blocks += blocks;
+ spin_unlock(&REISERFS_SB(sb)->bitmap_lock);
}
/* Unreserve @blocks amount of blocks in fs pointed by @sb */
@@ -896,6 +899,22 @@ void reiserfs_release_claimed_blocks(
if ( !blocks )
return;
+ spin_lock(&REISERFS_SB(sb)->bitmap_lock);
REISERFS_SB(sb)->reserved_blocks -= blocks;
+ spin_unlock(&REISERFS_SB(sb)->bitmap_lock);
RFALSE( REISERFS_SB(sb)->reserved_blocks < 0, "amount of blocks reserved became zero?");
}
+
+/* This function estimates how much pages we will be able to write to FS
+ used for reiserfs_file_write() purposes for now. */
+int reiserfs_can_fit_pages ( struct super_block *sb /* superblock of filesystem
+ to estimate space */ )
+{
+ unsigned long space;
+
+ spin_lock(&REISERFS_SB(sb)->bitmap_lock);
+ space = (SB_FREE_BLOCKS(sb) - REISERFS_SB(sb)->reserved_blocks) >> ( PAGE_CACHE_SHIFT - sb->s_blocksize_bits);
+ spin_unlock(&REISERFS_SB(sb)->bitmap_lock);
+
+ return space;
+}
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
index 0e5c173f5634..8528f8f06d31 100644
--- a/fs/reiserfs/do_balan.c
+++ b/fs/reiserfs/do_balan.c
@@ -319,8 +319,6 @@ static int balance_leaf (struct tree_balance * tb,
int new_item_len;
int version;
- RFALSE (!is_direct_le_ih (ih),
- "PAP-12075: only direct inserted item can be broken. %h", ih);
ret_val = leaf_shift_left (tb, tb->lnum[0]-1, -1);
/* Calculate item length to insert to S[0] */
@@ -343,7 +341,7 @@ static int balance_leaf (struct tree_balance * tb,
version = ih_version (ih);
/* Calculate key component, item length and body to insert into S[0] */
- set_le_ih_k_offset( ih, le_ih_k_offset( ih ) + tb->lbytes );
+ set_le_ih_k_offset( ih, le_ih_k_offset( ih ) + (tb->lbytes << (is_indirect_le_ih(ih)?tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT:0)) );
put_ih_item_len( ih, new_item_len );
if ( tb->lbytes > zeros_num ) {
@@ -452,23 +450,28 @@ static int balance_leaf (struct tree_balance * tb,
ih_item_len( B_N_PITEM_HEAD(tb->L[0],n+item_pos-ret_val)),
l_n,body, zeros_num > l_n ? l_n : zeros_num
);
-
- RFALSE( l_n &&
- is_indirect_le_ih(B_N_PITEM_HEAD
- (tb->L[0],
- n + item_pos - ret_val)),
- "PAP-12110: pasting more than 1 unformatted node pointer into indirect item");
-
/* 0-th item in S0 can be only of DIRECT type when l_n != 0*/
{
- int version;
-
- version = ih_version (B_N_PITEM_HEAD (tbS0, 0));
- set_le_key_k_offset (version, B_N_PKEY (tbS0, 0),
- le_key_k_offset (version, B_N_PKEY (tbS0, 0)) + l_n);
- version = ih_version (B_N_PITEM_HEAD(tb->CFL[0],tb->lkey[0]));
- set_le_key_k_offset (version, B_N_PDELIM_KEY(tb->CFL[0],tb->lkey[0]),
- le_key_k_offset (version, B_N_PDELIM_KEY(tb->CFL[0],tb->lkey[0])) + l_n);
+ int version;
+ int temp_l = l_n;
+
+ RFALSE (ih_item_len (B_N_PITEM_HEAD (tbS0, 0)),
+ "PAP-12106: item length must be 0");
+ RFALSE (comp_short_le_keys (B_N_PKEY (tbS0, 0),
+ B_N_PKEY (tb->L[0],
+ n + item_pos - ret_val)),
+ "PAP-12107: items must be of the same file");
+ if (is_indirect_le_ih(B_N_PITEM_HEAD (tb->L[0],
+ n + item_pos - ret_val))) {
+ temp_l = l_n << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT);
+ }
+ /* update key of first item in S0 */
+ version = ih_version (B_N_PITEM_HEAD (tbS0, 0));
+ set_le_key_k_offset (version, B_N_PKEY (tbS0, 0),
+ le_key_k_offset (version, B_N_PKEY (tbS0, 0)) + temp_l);
+ /* update left delimiting key */
+ set_le_key_k_offset (version, B_N_PDELIM_KEY(tb->CFL[0],tb->lkey[0]),
+ le_key_k_offset (version, B_N_PDELIM_KEY(tb->CFL[0],tb->lkey[0])) + temp_l);
}
/* Calculate new body, position in item and insert_size[0] */
@@ -537,7 +540,7 @@ static int balance_leaf (struct tree_balance * tb,
);
/* if appended item is indirect item, put unformatted node into un list */
if (is_indirect_le_ih (pasted))
- set_ih_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (pasted, 0);
tb->insert_size[0] = 0;
zeros_num = 0;
}
@@ -565,15 +568,11 @@ static int balance_leaf (struct tree_balance * tb,
{ /* new item or its part falls to R[0] */
if ( item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1 )
{ /* part of new item falls into R[0] */
- int old_key_comp, old_len, r_zeros_number;
+ loff_t old_key_comp, old_len, r_zeros_number;
const char * r_body;
int version;
loff_t offset;
- RFALSE( !is_direct_le_ih (ih),
- "PAP-12135: only direct item can be split. (%h)",
- ih);
-
leaf_shift_right(tb,tb->rnum[0]-1,-1);
version = ih_version(ih);
@@ -582,7 +581,7 @@ static int balance_leaf (struct tree_balance * tb,
old_len = ih_item_len(ih);
/* Calculate key component and item length to insert into R[0] */
- offset = le_ih_k_offset( ih ) + (old_len - tb->rbytes );
+ offset = le_ih_k_offset( ih ) + ((old_len - tb->rbytes )<<(is_indirect_le_ih(ih)?tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT:0));
set_le_ih_k_offset( ih, offset );
put_ih_item_len( ih, tb->rbytes);
/* Insert part of the item into R[0] */
@@ -590,13 +589,13 @@ static int balance_leaf (struct tree_balance * tb,
bi.bi_bh = tb->R[0];
bi.bi_parent = tb->FR[0];
bi.bi_position = get_right_neighbor_position (tb, 0);
- if ( offset - old_key_comp > zeros_num ) {
+ if ( (old_len - tb->rbytes) > zeros_num ) {
r_zeros_number = 0;
- r_body = body + offset - old_key_comp - zeros_num;
+ r_body = body + (old_len - tb->rbytes) - zeros_num;
}
else {
r_body = body;
- r_zeros_number = zeros_num - (offset - old_key_comp);
+ r_zeros_number = zeros_num - (old_len - tb->rbytes);
zeros_num -= r_zeros_number;
}
@@ -707,12 +706,17 @@ static int balance_leaf (struct tree_balance * tb,
{
int version;
+ unsigned long temp_rem = n_rem;
version = ih_version (B_N_PITEM_HEAD (tb->R[0],0));
+ if (is_indirect_le_key(version,B_N_PKEY(tb->R[0],0))){
+ temp_rem = n_rem << (tb->tb_sb->s_blocksize_bits -
+ UNFM_P_SHIFT);
+ }
set_le_key_k_offset (version, B_N_PKEY(tb->R[0],0),
- le_key_k_offset (version, B_N_PKEY(tb->R[0],0)) + n_rem);
+ le_key_k_offset (version, B_N_PKEY(tb->R[0],0)) + temp_rem);
set_le_key_k_offset (version, B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0]),
- le_key_k_offset (version, B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) + n_rem);
+ le_key_k_offset (version, B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) + temp_rem);
}
/* k_offset (B_N_PKEY(tb->R[0],0)) += n_rem;
k_offset (B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) += n_rem;*/
@@ -736,13 +740,12 @@ static int balance_leaf (struct tree_balance * tb,
leaf_paste_in_buffer(&bi, 0, n_shift, tb->insert_size[0] - n_rem, r_body, r_zeros_number);
if (is_indirect_le_ih (B_N_PITEM_HEAD(tb->R[0],0))) {
-
+#if 0
RFALSE( n_rem,
"PAP-12160: paste more than one unformatted node pointer");
-
- set_ih_free_space (B_N_PITEM_HEAD(tb->R[0],0), ((struct unfm_nodeinfo*)body)->unfm_freespace);
+#endif
+ set_ih_free_space (B_N_PITEM_HEAD(tb->R[0],0), 0);
}
-
tb->insert_size[0] = n_rem;
if ( ! n_rem )
pos_in_item ++;
@@ -781,7 +784,7 @@ static int balance_leaf (struct tree_balance * tb,
}
if (is_indirect_le_ih (pasted))
- set_ih_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (pasted, 0);
zeros_num = tb->insert_size[0] = 0;
}
}
@@ -858,12 +861,6 @@ static int balance_leaf (struct tree_balance * tb,
const char * r_body;
int version;
- RFALSE( !is_direct_le_ih(ih),
- /* The items which can be inserted are:
- Stat_data item, direct item, indirect item and directory item which consist of only two entries "." and "..".
- These items must not be broken except for a direct one. */
- "PAP-12205: non-direct item can not be broken when inserting");
-
/* Move snum[i]-1 items from S[0] to S_new[i] */
leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i] - 1, -1, S_new[i]);
/* Remember key component and item length */
@@ -873,7 +870,7 @@ static int balance_leaf (struct tree_balance * tb,
/* Calculate key component and item length to insert into S_new[i] */
set_le_ih_k_offset( ih,
- le_ih_k_offset(ih) + (old_len - sbytes[i] ) );
+ le_ih_k_offset(ih) + ((old_len - sbytes[i] )<<(is_indirect_le_ih(ih)?tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT:0)) );
put_ih_item_len( ih, sbytes[i] );
@@ -883,13 +880,13 @@ static int balance_leaf (struct tree_balance * tb,
bi.bi_parent = 0;
bi.bi_position = 0;
- if ( le_ih_k_offset (ih) - old_key_comp > zeros_num ) {
+ if ( (old_len - sbytes[i]) > zeros_num ) {
r_zeros_number = 0;
- r_body = body + (le_ih_k_offset(ih) - old_key_comp) - zeros_num;
+ r_body = body + (old_len - sbytes[i]) - zeros_num;
}
else {
r_body = body;
- r_zeros_number = zeros_num - (le_ih_k_offset (ih) - old_key_comp);
+ r_zeros_number = zeros_num - (old_len - sbytes[i]);
zeros_num -= r_zeros_number;
}
@@ -1010,11 +1007,13 @@ static int balance_leaf (struct tree_balance * tb,
tmp = B_N_PITEM_HEAD(S_new[i],0);
if (is_indirect_le_ih (tmp)) {
- if (n_rem)
- reiserfs_panic (tb->tb_sb, "PAP-12230: balance_leaf: invalid action with indirect item");
- set_ih_free_space (tmp, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (tmp, 0);
+ set_le_ih_k_offset( tmp, le_ih_k_offset(tmp) +
+ (n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT)));
+ } else {
+ set_le_ih_k_offset( tmp, le_ih_k_offset(tmp) +
+ n_rem );
}
- set_le_ih_k_offset( tmp, le_ih_k_offset(tmp) + n_rem );
}
tb->insert_size[0] = n_rem;
@@ -1060,7 +1059,7 @@ static int balance_leaf (struct tree_balance * tb,
/* if we paste to indirect item update ih_free_space */
if (is_indirect_le_ih (pasted))
- set_ih_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (pasted, 0);
zeros_num = tb->insert_size[0] = 0;
}
}
@@ -1152,11 +1151,12 @@ static int balance_leaf (struct tree_balance * tb,
leaf_paste_in_buffer (&bi, item_pos, pos_in_item, tb->insert_size[0], body, zeros_num);
if (is_indirect_le_ih (pasted)) {
-
+#if 0
RFALSE( tb->insert_size[0] != UNFM_P_SIZE,
"PAP-12280: insert_size for indirect item must be %d, not %d",
UNFM_P_SIZE, tb->insert_size[0]);
- set_ih_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+#endif
+ set_ih_free_space (pasted, 0);
}
tb->insert_size[0] = 0;
}
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 58e620c9e675..9bdf8109430e 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -6,6 +6,8 @@
#include <linux/time.h>
#include <linux/reiserfs_fs.h>
#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+#include <linux/pagemap.h>
/*
** We pack the tails of files on file close, not at the time they are written.
@@ -140,9 +142,1018 @@ out:
return error ;
}
+/* I really do not want to play with memory shortage right now, so
+ to simplify the code, we are not going to write more than this much pages at
+ a time. This still should considerably improve performance compared to 4k
+ at a time case. This is 32 pages of 4k size. */
+#define REISERFS_WRITE_PAGES_AT_A_TIME (128 * 1024) / PAGE_CACHE_SIZE
+
+/* Allocates blocks for a file to fulfil write request.
+ Maps all unmapped but prepared pages from the list.
+ Updates metadata with newly allocated blocknumbers as needed */
+int reiserfs_allocate_blocks_for_region(
+ struct inode *inode, /* Inode we work with */
+ loff_t pos, /* Writing position */
+ int num_pages, /* number of pages write going
+ to touch */
+ int write_bytes, /* amount of bytes to write */
+ struct page **prepared_pages, /* array of
+ prepared pages
+ */
+ int blocks_to_allocate /* Amount of blocks we
+ need to allocate to
+ fit the data into file
+ */
+ )
+{
+ struct cpu_key key; // cpu key of item that we are going to deal with
+ struct item_head *ih; // pointer to item head that we are going to deal with
+ struct buffer_head *bh; // Buffer head that contains items that we are going to deal with
+ struct reiserfs_transaction_handle th; // transaction handle for transaction we are going to create.
+ __u32 * item; // pointer to item we are going to deal with
+ INITIALIZE_PATH(path); // path to item, that we are going to deal with.
+ b_blocknr_t allocated_blocks[blocks_to_allocate]; // Pointer to a place where allocated blocknumbers would be stored. Right now statically allocated, later that will change.
+ reiserfs_blocknr_hint_t hint; // hint structure for block allocator.
+ size_t res; // return value of various functions that we call.
+ int curr_block; // current block used to keep track of unmapped blocks.
+ int i; // loop counter
+ int itempos; // position in item
+ unsigned int from = (pos & (PAGE_CACHE_SIZE - 1)); // writing position in
+ // first page
+ unsigned int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1; /* last modified byte offset in last page */
+ __u64 hole_size ; // amount of blocks for a file hole, if it needed to be created.
+ int modifying_this_item = 0; // Flag for items traversal code to keep track
+ // of the fact that we already prepared
+ // current block for journal
+
+
+ RFALSE(!blocks_to_allocate, "green-9004: tried to allocate zero blocks?");
+
+ /* First we compose a key to point at the writing position, we want to do
+ that outside of any locking region. */
+ make_cpu_key (&key, inode, pos+1, TYPE_ANY, 3/*key length*/);
+
+ /* If we came here, it means we absolutely need to open a transaction,
+ since we need to allocate some blocks */
+ reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that.
+ journal_begin(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1); // Wish I know if this number enough
+ reiserfs_update_inode_transaction(inode) ;
+
+ /* Look for the in-tree position of our write, need path for block allocator */
+ res = search_for_position_by_key(inode->i_sb, &key, &path);
+ if ( res == IO_ERROR ) {
+ res = -EIO;
+ goto error_exit;
+ }
+
+ /* Allocate blocks */
+ /* First fill in "hint" structure for block allocator */
+ hint.th = &th; // transaction handle.
+ hint.path = &path; // Path, so that block allocator can determine packing locality or whatever it needs to determine.
+ hint.inode = inode; // Inode is needed by block allocator too.
+ hint.search_start = 0; // We have no hint on where to search free blocks for block allocator.
+ hint.key = key.on_disk_key; // on disk key of file.
+ hint.block = inode->i_blocks>>(inode->i_sb->s_blocksize_bits-9); // Number of disk blocks this file occupies already.
+ hint.formatted_node = 0; // We are allocating blocks for unformatted node.
+ hint.preallocate = 0; // We do not do any preallocation for now.
+
+ /* Call block allocator to allocate blocks */
+ res = reiserfs_allocate_blocknrs(&hint, allocated_blocks, blocks_to_allocate, blocks_to_allocate);
+ if ( res != CARRY_ON ) {
+ if ( res == NO_DISK_SPACE ) {
+ /* We flush the transaction in case of no space. This way some
+ blocks might become free */
+ SB_JOURNAL(inode->i_sb)->j_must_wait = 1;
+ restart_transaction(&th, inode, &path);
+
+ /* We might have scheduled, so search again */
+ res = search_for_position_by_key(inode->i_sb, &key, &path);
+ if ( res == IO_ERROR ) {
+ res = -EIO;
+ goto error_exit;
+ }
+
+ /* update changed info for hint structure. */
+ res = reiserfs_allocate_blocknrs(&hint, allocated_blocks, blocks_to_allocate, blocks_to_allocate);
+ if ( res != CARRY_ON ) {
+ res = -ENOSPC;
+ pathrelse(&path);
+ goto error_exit;
+ }
+ } else {
+ res = -ENOSPC;
+ pathrelse(&path);
+ goto error_exit;
+ }
+ }
+
+#ifdef __BIG_ENDIAN
+ // Too bad, I have not found any way to convert a given region from
+ // cpu format to little endian format
+ {
+ int i;
+ for ( i = 0; i < blocks_to_allocate ; i++)
+ allocated_blocks[i]=cpu_to_le32(allocated_blocks[i]);
+ }
+#endif
+
+ /* Blocks allocating well might have scheduled and tree might have changed,
+ let's search the tree again */
+ /* find where in the tree our write should go */
+ res = search_for_position_by_key(inode->i_sb, &key, &path);
+ if ( res == IO_ERROR ) {
+ res = -EIO;
+ goto error_exit_free_blocks;
+ }
+
+ bh = get_last_bh( &path ); // Get a bufferhead for last element in path.
+ ih = get_ih( &path ); // Get a pointer to last item head in path.
+ item = get_item( &path ); // Get a pointer to last item in path
+
+ /* Let's see what we have found */
+ if ( res != POSITION_FOUND ) { /* position not found, this means that we
+ might need to append file with holes
+ first */
+ // Since we are writing past the file's end, we need to find out if
+ // there is a hole that needs to be inserted before our writing
+ // position, and how many blocks it is going to cover (we need to
+ // populate pointers to file blocks representing the hole with zeros)
+
+ hole_size = (pos + 1 - (le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key))+op_bytes_number(ih, inode->i_sb->s_blocksize))) >> inode->i_sb->s_blocksize_bits;
+
+ if ( hole_size > 0 ) {
+ int to_paste = min_t(__u64, hole_size, MAX_ITEM_LEN(inode->i_sb->s_blocksize)/UNFM_P_SIZE ); // How much data to insert first time.
+ /* area filled with zeroes, to supply as list of zero blocknumbers
+ We allocate it outside of loop just in case loop would spin for
+ several iterations. */
+ char *zeros = kmalloc(to_paste*UNFM_P_SIZE, GFP_ATOMIC); // We cannot insert more than MAX_ITEM_LEN bytes anyway.
+ if ( !zeros ) {
+ res = -ENOMEM;
+ goto error_exit_free_blocks;
+ }
+ memset ( zeros, 0, to_paste*UNFM_P_SIZE);
+ do {
+ to_paste = min_t(__u64, hole_size, MAX_ITEM_LEN(inode->i_sb->s_blocksize)/UNFM_P_SIZE );
+ if ( is_indirect_le_ih(ih) ) {
+ /* Ok, there is existing indirect item already. Need to append it */
+ /* Calculate position past inserted item */
+ make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);
+ res = reiserfs_paste_into_item( &th, &path, &key, (char *)zeros, UNFM_P_SIZE*to_paste);
+ if ( res ) {
+ kfree(zeros);
+ goto error_exit_free_blocks;
+ }
+ } else if ( is_statdata_le_ih(ih) ) {
+ /* No existing item, create it */
+ /* item head for new item */
+ struct item_head ins_ih;
+
+ /* create a key for our new item */
+ make_cpu_key( &key, inode, 1, TYPE_INDIRECT, 3);
+
+ /* Create new item head for our new item */
+ make_le_item_head (&ins_ih, &key, key.version, 1,
+ TYPE_INDIRECT, to_paste*UNFM_P_SIZE,
+ 0 /* free space */);
+
+ /* Find where such item should live in the tree */
+ res = search_item (inode->i_sb, &key, &path);
+ if ( res != ITEM_NOT_FOUND ) {
+ /* item should not exist, otherwise we have error */
+ if ( res != -ENOSPC ) {
+ reiserfs_warning ("green-9008: search_by_key (%K) returned %d\n",
+ &key, res);
+ }
+ res = -EIO;
+ kfree(zeros);
+ goto error_exit_free_blocks;
+ }
+ res = reiserfs_insert_item( &th, &path, &key, &ins_ih, (char *)zeros);
+ } else {
+ reiserfs_panic(inode->i_sb, "green-9011: Unexpected key type %K\n", &key);
+ }
+ if ( res ) {
+ kfree(zeros);
+ goto error_exit_free_blocks;
+ }
+ /* Now we want to check if transaction is too full, and if it is
+ we restart it. This will also free the path. */
+ if (journal_transaction_should_end(&th, th.t_blocks_allocated))
+ restart_transaction(&th, inode, &path);
+
+ /* Well, need to recalculate path and stuff */
+ set_cpu_key_k_offset( &key, cpu_key_k_offset(&key) + (to_paste << inode->i_blkbits));
+ res = search_for_position_by_key(inode->i_sb, &key, &path);
+ if ( res == IO_ERROR ) {
+ res = -EIO;
+ kfree(zeros);
+ goto error_exit_free_blocks;
+ }
+ bh=get_last_bh(&path);
+ ih=get_ih(&path);
+ item = get_item(&path);
+ hole_size -= to_paste;
+ } while ( hole_size );
+ kfree(zeros);
+ }
+ }
+
+ // Go through existing indirect items first
+ // replace all zeroes with blocknumbers from list
+ // Note that if no corresponding item was found, by previous search,
+ // it means there are no existing in-tree representation for file area
+ // we are going to overwrite, so there is nothing to scan through for holes.
+ for ( curr_block = 0, itempos = path.pos_in_item ; curr_block < blocks_to_allocate && res == POSITION_FOUND ; ) {
+
+ if ( itempos >= ih_item_len(ih)/UNFM_P_SIZE ) {
+ /* We run out of data in this indirect item, let's look for another
+ one. */
+ /* First if we are already modifying current item, log it */
+ if ( modifying_this_item ) {
+ journal_mark_dirty (&th, inode->i_sb, bh);
+ modifying_this_item = 0;
+ }
+ /* Then set the key to look for a new indirect item (offset of old
+ item is added to old item length */
+ set_cpu_key_k_offset( &key, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize));
+ /* Search ofor position of new key in the tree. */
+ res = search_for_position_by_key(inode->i_sb, &key, &path);
+ if ( res == IO_ERROR) {
+ res = -EIO;
+ goto error_exit_free_blocks;
+ }
+ bh=get_last_bh(&path);
+ ih=get_ih(&path);
+ item = get_item(&path);
+ itempos = path.pos_in_item;
+ continue; // loop to check all kinds of conditions and so on.
+ }
+ /* Ok, we have correct position in item now, so let's see if it is
+ representing file hole (blocknumber is zero) and fill it if needed */
+ if ( !item[itempos] ) {
+ /* Ok, a hole. Now we need to check if we already prepared this
+ block to be journaled */
+ while ( !modifying_this_item ) { // loop until succeed
+ /* Well, this item is not journaled yet, so we must prepare
+ it for journal first, before we can change it */
+ struct item_head tmp_ih; // We copy item head of found item,
+ // here to detect if fs changed under
+ // us while we were preparing for
+ // journal.
+ int fs_gen; // We store fs generation here to find if someone
+ // changes fs under our feet
+
+ copy_item_head (&tmp_ih, ih); // Remember itemhead
+ fs_gen = get_generation (inode->i_sb); // remember fs generation
+ reiserfs_prepare_for_journal(inode->i_sb, bh, 1); // Prepare a buffer within which indirect item is stored for changing.
+ if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {
+ // Sigh, fs was changed under us, we need to look for new
+ // location of item we are working with
+
+ /* unmark prepaerd area as journaled and search for it's
+ new position */
+ reiserfs_restore_prepared_buffer(inode->i_sb, bh);
+ res = search_for_position_by_key(inode->i_sb, &key, &path);
+ if ( res == IO_ERROR) {
+ res = -EIO;
+ goto error_exit_free_blocks;
+ }
+ bh=get_last_bh(&path);
+ ih=get_ih(&path);
+ item = get_item(&path);
+ // Itempos is still the same
+ continue;
+ }
+ modifying_this_item = 1;
+ }
+ item[itempos] = allocated_blocks[curr_block]; // Assign new block
+ curr_block++;
+ }
+ itempos++;
+ }
+
+ if ( modifying_this_item ) { // We need to log last-accessed block, if it
+ // was modified, but not logged yet.
+ journal_mark_dirty (&th, inode->i_sb, bh);
+ }
+
+ if ( curr_block < blocks_to_allocate ) {
+ // Oh, well need to append to indirect item, or to create indirect item
+ // if there weren't any
+ if ( is_indirect_le_ih(ih) ) {
+ // Existing indirect item - append. First calculate key for append
+ // position. We do not need to recalculate path as it should
+ // already point to correct place.
+ make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);
+ res = reiserfs_paste_into_item( &th, &path, &key, (char *)(allocated_blocks+curr_block), UNFM_P_SIZE*(blocks_to_allocate-curr_block));
+ if ( res ) {
+ goto error_exit_free_blocks;
+ }
+ } else if (is_statdata_le_ih(ih) ) {
+ // Last found item was statdata. That means we need to create indirect item.
+ struct item_head ins_ih; /* itemhead for new item */
+
+ /* create a key for our new item */
+ make_cpu_key( &key, inode, 1, TYPE_INDIRECT, 3); // Position one,
+ // because that's
+ // where first
+ // indirect item
+ // begins
+ /* Create new item head for our new item */
+ make_le_item_head (&ins_ih, &key, key.version, 1, TYPE_INDIRECT,
+ (blocks_to_allocate-curr_block)*UNFM_P_SIZE,
+ 0 /* free space */);
+ /* Find where such item should live in the tree */
+ res = search_item (inode->i_sb, &key, &path);
+ if ( res != ITEM_NOT_FOUND ) {
+ /* Well, if we have found such item already, or some error
+ occured, we need to warn user and return error */
+ if ( res != -ENOSPC ) {
+ reiserfs_warning ("green-9009: search_by_key (%K) returned %d\n",
+ &key, res);
+ }
+ res = -EIO;
+ goto error_exit_free_blocks;
+ }
+ /* Insert item into the tree with the data as its body */
+ res = reiserfs_insert_item( &th, &path, &key, &ins_ih, (char *)(allocated_blocks+curr_block));
+ } else {
+ reiserfs_panic(inode->i_sb, "green-9010: unexpected item type for key %K\n",&key);
+ }
+ }
+
+ /* Now the final thing, if we have grew the file, we must update it's size*/
+ if ( pos + write_bytes > inode->i_size) {
+ inode->i_size = pos + write_bytes; // Set new size
+ }
+
+ /* Amount of on-disk blocks used by file have changed, update it */
+ inode->i_blocks += blocks_to_allocate << (inode->i_blkbits - 9);
+ reiserfs_update_sd(&th, inode); // And update on-disk metadata
+ // finish all journal stuff now, We are not going to play with metadata
+ // anymore.
+ pathrelse(&path);
+ journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1);
+ reiserfs_write_unlock(inode->i_sb);
+
+ // go through all the pages/buffers and map the buffers to newly allocated
+ // blocks (so that system knows where to write these pages later).
+ curr_block = 0;
+ for ( i = 0; i < num_pages ; i++ ) {
+ struct page *page=prepared_pages[i]; //current page
+ struct buffer_head *head = page_buffers(page);// first buffer for a page
+ int block_start, block_end; // in-page offsets for buffers.
+
+ if (!page_buffers(page))
+ reiserfs_panic(inode->i_sb, "green-9005: No buffers for prepared page???");
+
+ /* For each buffer in page */
+ for(bh = head, block_start = 0; bh != head || !block_start;
+ block_start=block_end, bh = bh->b_this_page) {
+ if (!bh)
+ reiserfs_panic(inode->i_sb, "green-9006: Allocated but absent buffer for a page?");
+ block_end = block_start+inode->i_sb->s_blocksize;
+ if (i == 0 && block_end <= from )
+ /* if this buffer is before requested data to map, skip it */
+ continue;
+ if (i == num_pages - 1 && block_start >= to)
+ /* If this buffer is after requested data to map, abort
+ processing of current page */
+ break;
+
+ if ( !buffer_mapped(bh) ) { // Ok, unmapped buffer, need to map it
+ map_bh( bh, inode->i_sb, le32_to_cpu(allocated_blocks[curr_block]));
+ curr_block++;
+ }
+ }
+ }
+
+ RFALSE( curr_block > blocks_to_allocate, "green-9007: Used too many blocks? weird");
+
+ return 0;
+
+// Need to deal with transaction here.
+error_exit_free_blocks:
+ pathrelse(&path);
+ // free blocks
+ for( i = 0; i < blocks_to_allocate; i++ )
+ reiserfs_free_block( &th, le32_to_cpu(allocated_blocks[i]));
+
+error_exit:
+ journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1);
+ reiserfs_write_unlock(inode->i_sb);
+
+ return res;
+}
+
+/* Unlock pages prepared by reiserfs_prepare_file_region_for_write */
+void reiserfs_unprepare_pages(struct page **prepared_pages, /* list of locked pages */
+ int num_pages /* amount of pages */) {
+ int i; // loop counter
+
+ for (i=0; i < num_pages ; i++) {
+ struct page *page = prepared_pages[i];
+
+ try_to_free_buffers(page);
+ kunmap(page);
+ unlock_page(page);
+ page_cache_release(page);
+ }
+}
+
+/* This function will copy data from userspace to specified pages within
+ supplied byte range */
+int reiserfs_copy_from_user_to_file_region(
+ loff_t pos, /* In-file position */
+ int num_pages, /* Number of pages affected */
+ int write_bytes, /* Amount of bytes to write */
+ struct page **prepared_pages, /* pointer to
+ array to
+ prepared pages
+ */
+ const char *buf /* Pointer to user-supplied
+ data*/
+ )
+{
+ long page_fault=0; // status of copy_from_user.
+ int i; // loop counter.
+ int offset; // offset in page
+
+ for ( i = 0, offset = (pos & (PAGE_CACHE_SIZE-1)); i < num_pages ; i++,offset=0) {
+ int count = min_t(int,PAGE_CACHE_SIZE-offset,write_bytes); // How much of bytes to write to this page
+ struct page *page=prepared_pages[i]; // Current page we process.
+
+ fault_in_pages_readable( buf, count);
+
+ /* Copy data from userspace to the current page */
+ kmap(page);
+ page_fault = __copy_from_user(page_address(page)+offset, buf, count); // Copy the data.
+ /* Flush processor's dcache for this page */
+ flush_dcache_page(page);
+ kunmap(page);
+ buf+=count;
+ write_bytes-=count;
+
+ if (page_fault)
+ break; // Was there a fault? abort.
+ }
+
+ return page_fault?-EFAULT:0;
+}
+
+
+
+/* Submit pages for write. This was separated from actual file copying
+ because we might want to allocate block numbers in-between.
+ This function assumes that caller will adjust file size to correct value. */
+int reiserfs_submit_file_region_for_write(
+ loff_t pos, /* Writing position offset */
+ int num_pages, /* Number of pages to write */
+ int write_bytes, /* number of bytes to write */
+ struct page **prepared_pages /* list of pages */
+ )
+{
+ int status; // return status of block_commit_write.
+ int retval = 0; // Return value we are going to return.
+ int i; // loop counter
+ int offset; // Writing offset in page.
+
+ for ( i = 0, offset = (pos & (PAGE_CACHE_SIZE-1)); i < num_pages ; i++,offset=0) {
+ int count = min_t(int,PAGE_CACHE_SIZE-offset,write_bytes); // How much of bytes to write to this page
+ struct page *page=prepared_pages[i]; // Current page we process.
+
+ status = block_commit_write(page, offset, offset+count);
+ if ( status )
+ retval = status; // To not overcomplicate matters We are going to
+ // submit all the pages even if there was error.
+ // we only remember error status to report it on
+ // exit.
+ write_bytes-=count;
+ SetPageReferenced(page);
+ unlock_page(page); // We unlock the page as it was locked by earlier call
+ // to grab_cache_page
+ page_cache_release(page);
+ }
+ return retval;
+}
+
+/* Look if passed writing region is going to touch file's tail
+ (if it is present). And if it is, convert the tail to unformatted node */
+int reiserfs_check_for_tail_and_convert( struct inode *inode, /* inode to deal with */
+ loff_t pos, /* Writing position */
+ int write_bytes /* amount of bytes to write */
+ )
+{
+ INITIALIZE_PATH(path); // needed for search_for_position
+ struct cpu_key key; // Key that would represent last touched writing byte.
+ struct item_head *ih; // item header of found block;
+ int res; // Return value of various functions we call.
+ int cont_expand_offset; // We will put offset for generic_cont_expand here
+ // This can be int just because tails are created
+ // only for small files.
+
+/* this embodies a dependency on a particular tail policy */
+ if ( inode->i_size >= inode->i_sb->s_blocksize*4 ) {
+ /* such a big files do not have tails, so we won't bother ourselves
+ to look for tails, simply return */
+ return 0;
+ }
+
+ reiserfs_write_lock(inode->i_sb);
+ /* find the item containing the last byte to be written, or if
+ * writing past the end of the file then the last item of the
+ * file (and then we check its type). */
+ make_cpu_key (&key, inode, pos+write_bytes+1, TYPE_ANY, 3/*key length*/);
+ res = search_for_position_by_key(inode->i_sb, &key, &path);
+ if ( res == IO_ERROR ) {
+ reiserfs_write_unlock(inode->i_sb);
+ return -EIO;
+ }
+ ih = get_ih(&path);
+ res = 0;
+ if ( is_direct_le_ih(ih) ) {
+ /* Ok, closest item is file tail (tails are stored in "direct"
+ * items), so we need to unpack it. */
+ /* To not overcomplicate matters, we just call generic_cont_expand
+ which will in turn call other stuff and finally will boil down to
+ reiserfs_get_block() that would do necessary conversion. */
+ cont_expand_offset = le_key_k_offset(get_inode_item_key_version(inode), &(ih->ih_key));
+ pathrelse(&path);
+ res = generic_cont_expand( inode, cont_expand_offset);
+ } else
+ pathrelse(&path);
+
+ reiserfs_write_unlock(inode->i_sb);
+ return res;
+}
+
+/* This function locks pages starting from @pos for @inode.
+ @num_pages pages are locked and stored in
+ @prepared_pages array. Also buffers are allocated for these pages.
+ First and last page of the region is read if it is overwritten only
+ partially. If last page did not exist before write (file hole or file
+ append), it is zeroed, then.
+ Returns number of unallocated blocks that should be allocated to cover
+ new file data.*/
+int reiserfs_prepare_file_region_for_write(
+ struct inode *inode /* Inode of the file */,
+ loff_t pos, /* position in the file */
+ int num_pages, /* number of pages to
+ prepare */
+ int write_bytes, /* Amount of bytes to be
+ overwritten from
+ @pos */
+ struct page **prepared_pages /* pointer to array
+ where to store
+ prepared pages */
+ )
+{
+ int res=0; // Return values of different functions we call.
+ unsigned long index = pos >> PAGE_CACHE_SHIFT; // Offset in file in pages.
+ int from = (pos & (PAGE_CACHE_SIZE - 1)); // Writing offset in first page
+ int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1;
+ /* offset of last modified byte in last
+ page */
+ struct address_space *mapping = inode->i_mapping; // Pages are mapped here.
+ int i; // Simple counter
+ int blocks = 0; /* Return value (blocks that should be allocated) */
+ struct buffer_head *bh, *head; // Current bufferhead and first bufferhead
+ // of a page.
+ unsigned block_start, block_end; // Starting and ending offsets of current
+ // buffer in the page.
+ struct buffer_head *wait[2], **wait_bh=wait; // Buffers for page, if
+ // Page appeared to be not up
+ // to date. Note how we have
+ // at most 2 buffers, this is
+ // because we at most may
+ // partially overwrite two
+ // buffers for one page. One at // the beginning of write area
+ // and one at the end.
+ // Everything inthe middle gets // overwritten totally.
+
+ struct cpu_key key; // cpu key of item that we are going to deal with
+ struct item_head *ih = NULL; // pointer to item head that we are going to deal with
+ struct buffer_head *itembuf=NULL; // Buffer head that contains items that we are going to deal with
+ INITIALIZE_PATH(path); // path to item, that we are going to deal with.
+ __u32 * item=0; // pointer to item we are going to deal with
+
+
+ if ( num_pages < 1 ) {
+ reiserfs_warning("green-9001: reiserfs_prepare_file_region_for_write called with zero number of pages to process\n");
+ return -EFAULT;
+ }
+
+ /* We have 2 loops for pages. In first loop we grab and lock the pages, so
+ that nobody would touch these until we release the pages. Then
+ we'd start to deal with mapping buffers to blocks. */
+ for ( i = 0; i < num_pages; i++) {
+ prepared_pages[i] = grab_cache_page(mapping, index + i); // locks the page
+ if ( !prepared_pages[i]) {
+ res = -ENOMEM;
+ goto failed_page_grabbing;
+ }
+ if (!page_has_buffers(prepared_pages[i]))
+ create_empty_buffers(prepared_pages[i], inode->i_sb->s_blocksize, 0);
+ }
+
+ /* Let's count amount of blocks for a case where all the blocks
+ overwritten are new (we will substract already allocated blocks later)*/
+ if ( num_pages > 2 )
+ /* These are full-overwritten pages so we count all the blocks in
+ these pages are counted as needed to be allocated */
+ blocks = (num_pages - 2) << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+
+ /* count blocks needed for first page (possibly partially written) */
+ blocks += ((PAGE_CACHE_SIZE - from) >> inode->i_blkbits) +
+ !!(from & (inode->i_sb->s_blocksize-1)); /* roundup */
+
+ /* Now we account for last page. If last page == first page (we
+ overwrite only one page), we substract all the blocks past the
+ last writing position in a page out of already calculated number
+ of blocks */
+ blocks += ((num_pages > 1) << (PAGE_CACHE_SHIFT-inode->i_blkbits)) -
+ ((PAGE_CACHE_SIZE - to) >> inode->i_blkbits);
+ /* Note how we do not roundup here since partial blocks still
+ should be allocated */
+
+ /* Now if all the write area lies past the file end, no point in
+ maping blocks, since there is none, so we just zero out remaining
+ parts of first and last pages in write area (if needed) */
+ if ( (pos & ~(PAGE_CACHE_SIZE - 1)) > inode->i_size ) {
+ if ( from != 0 ) {/* First page needs to be partially zeroed */
+ char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0);
+ memset(kaddr, 0, from);
+ kunmap_atomic( kaddr, KM_USER0);
+ }
+ if ( to != PAGE_CACHE_SIZE ) { /* Last page needs to be partially zeroed */
+ char *kaddr = kmap_atomic(prepared_pages[num_pages-1], KM_USER0);
+ memset(kaddr+to, 0, PAGE_CACHE_SIZE - to);
+ kunmap_atomic( kaddr, KM_USER0);
+ }
+
+ /* Since all blocks are new - use already calculated value */
+ return blocks;
+ }
+
+ /* Well, since we write somewhere into the middle of a file, there is
+ possibility we are writing over some already allocated blocks, so
+ let's map these blocks and substract number of such blocks out of blocks
+ we need to allocate (calculated above) */
+ /* Mask write position to start on blocksize, we do it out of the
+ loop for performance reasons */
+ pos &= ~(inode->i_sb->s_blocksize - 1);
+ /* Set cpu key to the starting position in a file (on left block boundary)*/
+ make_cpu_key (&key, inode, 1 + ((pos) & ~(inode->i_sb->s_blocksize - 1)), TYPE_ANY, 3/*key length*/);
+
+ reiserfs_write_lock(inode->i_sb); // We need that for at least search_by_key()
+ for ( i = 0; i < num_pages ; i++ ) {
+ int item_pos=-1; /* Position in indirect item */
+
+ head = page_buffers(prepared_pages[i]);
+ /* For each buffer in the page */
+ for(bh = head, block_start = 0; bh != head || !block_start;
+ block_start=block_end, bh = bh->b_this_page) {
+ if (!bh)
+ reiserfs_panic(inode->i_sb, "green-9002: Allocated but absent buffer for a page?");
+ /* Find where this buffer ends */
+ block_end = block_start+inode->i_sb->s_blocksize;
+ if (i == 0 && block_end <= from )
+ /* if this buffer is before requested data to map, skip it*/
+ continue;
+
+ if (i == num_pages - 1 && block_start >= to) {
+ /* If this buffer is after requested data to map, abort
+ processing of current page */
+ break;
+ }
+
+ if ( buffer_mapped(bh) && bh->b_blocknr !=0 ) {
+ /* This is optimisation for a case where buffer is mapped
+ and have blocknumber assigned. In case significant amount
+ of such buffers are present, we may avoid some amount
+ of search_by_key calls.
+ Probably it would be possible to move parts of this code
+ out of BKL, but I afraid that would overcomplicate code
+ without any noticeable benefit.
+ */
+ item_pos++;
+ /* Update the key */
+ set_cpu_key_k_offset( &key, cpu_key_k_offset(&key) + inode->i_sb->s_blocksize);
+ blocks--; // Decrease the amount of blocks that need to be
+ // allocated
+ continue; // Go to the next buffer
+ }
+
+ if ( !itembuf || /* if first iteration */
+ item_pos >= ih_item_len(ih)/UNFM_P_SIZE)
+ { /* or if we progressed past the
+ current unformatted_item */
+ /* Try to find next item */
+ res = search_for_position_by_key(inode->i_sb, &key, &path);
+ /* Abort if no more items */
+ if ( res != POSITION_FOUND )
+ break;
+
+ /* Update information about current indirect item */
+ itembuf = get_last_bh( &path );
+ ih = get_ih( &path );
+ item = get_item( &path );
+ item_pos = path.pos_in_item;
+
+ RFALSE( !is_indirect_le_ih (ih), "green-9003: indirect item expected");
+ }
+
+ /* See if there is some block associated with the file
+ at that position, map the buffer to this block */
+ if ( get_block_num(item,item_pos) ) {
+ map_bh(bh, inode->i_sb, get_block_num(item,item_pos));
+ blocks--; // Decrease the amount of blocks that need to be
+ // allocated
+ }
+ item_pos++;
+ /* Update the key */
+ set_cpu_key_k_offset( &key, cpu_key_k_offset(&key) + inode->i_sb->s_blocksize);
+ }
+ }
+ pathrelse(&path); // Free the path
+ reiserfs_write_unlock(inode->i_sb);
+
+ /* Now zero out unmappend buffers for the first and last pages of
+ write area or issue read requests if page is mapped. */
+ /* First page, see if it is not uptodate */
+ if ( !PageUptodate(prepared_pages[0]) ) {
+ head = page_buffers(prepared_pages[0]);
+
+ /* For each buffer in page */
+ for(bh = head, block_start = 0; bh != head || !block_start;
+ block_start=block_end, bh = bh->b_this_page) {
+
+ if (!bh)
+ reiserfs_panic(inode->i_sb, "green-9002: Allocated but absent buffer for a page?");
+ /* Find where this buffer ends */
+ block_end = block_start+inode->i_sb->s_blocksize;
+ if ( block_end <= from )
+ /* if this buffer is before requested data to map, skip it*/
+ continue;
+ if ( block_start < from ) { /* Aha, our partial buffer */
+ if ( buffer_mapped(bh) ) { /* If it is mapped, we need to
+ issue READ request for it to
+ not loose data */
+ ll_rw_block(READ, 1, &bh);
+ *wait_bh++=bh;
+ } else { /* Not mapped, zero it */
+ char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0);
+ memset(kaddr+block_start, 0, from-block_start);
+ kunmap_atomic( kaddr, KM_USER0);
+ set_buffer_uptodate(bh);
+ }
+ }
+ }
+ }
+
+ /* Last page, see if it is not uptodate, or if the last page is past the end of the file. */
+ if ( !PageUptodate(prepared_pages[num_pages-1]) ||
+ ((pos+write_bytes)>>PAGE_CACHE_SHIFT) > (inode->i_size>>PAGE_CACHE_SHIFT) ) {
+ head = page_buffers(prepared_pages[num_pages-1]);
+
+ /* for each buffer in page */
+ for(bh = head, block_start = 0; bh != head || !block_start;
+ block_start=block_end, bh = bh->b_this_page) {
+
+ if (!bh)
+ reiserfs_panic(inode->i_sb, "green-9002: Allocated but absent buffer for a page?");
+ /* Find where this buffer ends */
+ block_end = block_start+inode->i_sb->s_blocksize;
+ if ( block_start >= to )
+ /* if this buffer is after requested data to map, skip it*/
+ break;
+ if ( block_end > to ) { /* Aha, our partial buffer */
+ if ( buffer_mapped(bh) ) { /* If it is mapped, we need to
+ issue READ request for it to
+ not loose data */
+ ll_rw_block(READ, 1, &bh);
+ *wait_bh++=bh;
+ } else { /* Not mapped, zero it */
+ char *kaddr = kmap_atomic(prepared_pages[num_pages-1], KM_USER0);
+ memset(kaddr+to, 0, block_end-to);
+ kunmap_atomic( kaddr, KM_USER0);
+ set_buffer_uptodate(bh);
+ }
+ }
+ }
+ }
+
+ /* Wait for read requests we made to happen, if necessary */
+ while(wait_bh > wait) {
+ wait_on_buffer(*--wait_bh);
+ if (!buffer_uptodate(*wait_bh)) {
+ res = -EIO;
+ goto failed_read;
+ }
+ }
+
+ return blocks;
+failed_page_grabbing:
+ num_pages = i;
+failed_read:
+ reiserfs_unprepare_pages(prepared_pages, num_pages);
+ return res;
+}
+
+/* Write @count bytes at position @ppos in a file indicated by @file
+ from the buffer @buf.
+
+ generic_file_write() is only appropriate for filesystems that are not seeking to optimize performance and want
+ something simple that works. It is not for serious use by general purpose filesystems, excepting the one that it was
+ written for (ext2/3). This is for several reasons:
+
+ * It has no understanding of any filesystem specific optimizations.
+
+ * It enters the filesystem repeatedly for each page that is written.
+
+ * It depends on reiserfs_get_block() function which if implemented by reiserfs performs costly search_by_key
+ * operation for each page it is supplied with. By contrast reiserfs_file_write() feeds as much as possible at a time
+ * to reiserfs which allows for fewer tree traversals.
+
+ * Each indirect pointer insertion takes a lot of cpu, because it involves memory moves inside of blocks.
+
+ * Asking the block allocation code for blocks one at a time is slightly less efficient.
+
+ All of these reasons for not using only generic file write were understood back when reiserfs was first miscoded to
+ use it, but we were in a hurry to make code freeze, and so it couldn't be revised then. This new code should make
+ things right finally.
+
+ Future Features: providing search_by_key with hints.
+
+*/
+ssize_t reiserfs_file_write( struct file *file, /* the file we are going to write into */
+ const char *buf, /* pointer to user supplied data
+(in userspace) */
+ size_t count, /* amount of bytes to write */
+ loff_t *ppos /* pointer to position in file that we start writing at. Should be updated to
+ * new current position before returning. */ )
+{
+ size_t already_written = 0; // Number of bytes already written to the file.
+ loff_t pos; // Current position in the file.
+ size_t res; // return value of various functions that we call.
+ struct inode *inode = file->f_dentry->d_inode; // Inode of the file that we are writing to.
+ struct page * prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME];
+ /* To simplify coding at this time, we store
+ locked pages in array for now */
+ if ( count <= PAGE_CACHE_SIZE || file->f_flags & O_DIRECT)
+ return generic_file_write(file, buf, count, ppos);
+
+ if ( unlikely((ssize_t) count < 0 ))
+ return -EINVAL;
+
+ if (unlikely(!access_ok(VERIFY_READ, buf, count)))
+ return -EFAULT;
+
+ down(&inode->i_sem); // locks the entire file for just us
+
+ pos = *ppos;
+
+ /* Check if we can write to specified region of file, file
+ is not overly big and this kind of stuff. Adjust pos and
+ count, if needed */
+ res = generic_write_checks(inode, file, &pos, &count, 0);
+ if (res)
+ goto out;
+
+ if ( count == 0 )
+ goto out;
+
+ remove_suid(file->f_dentry);
+ inode_update_time(inode, 1); /* Both mtime and ctime */
+
+ // Ok, we are done with all the checks.
+
+ // Now we should start real work
+
+ /* If we are going to write past the file's packed tail or if we are going
+ to overwrite part of the tail, we need that tail to be converted into
+ unformatted node */
+ res = reiserfs_check_for_tail_and_convert( inode, pos, count);
+ if (res)
+ goto out;
+
+ while ( count > 0) {
+ /* This is the main loop in which we running until some error occures
+ or until we write all of the data. */
+ int num_pages;/* amount of pages we are going to write this iteration */
+ int write_bytes; /* amount of bytes to write during this iteration */
+ int blocks_to_allocate; /* how much blocks we need to allocate for
+ this iteration */
+
+ /* (pos & (PAGE_CACHE_SIZE-1)) is an idiom for offset into a page of pos*/
+ num_pages = !!((pos+count) & (PAGE_CACHE_SIZE - 1)) + /* round up partial
+ pages */
+ ((count + (pos & (PAGE_CACHE_SIZE-1))) >> PAGE_CACHE_SHIFT);
+ /* convert size to amount of
+ pages */
+ reiserfs_write_lock(inode->i_sb);
+ if ( num_pages > REISERFS_WRITE_PAGES_AT_A_TIME
+ || num_pages > reiserfs_can_fit_pages(inode->i_sb) ) {
+ /* If we were asked to write more data than we want to or if there
+ is not that much space, then we shorten amount of data to write
+ for this iteration. */
+ num_pages = min_t(int, REISERFS_WRITE_PAGES_AT_A_TIME, reiserfs_can_fit_pages(inode->i_sb));
+ /* Also we should not forget to set size in bytes accordingly */
+ write_bytes = (num_pages << PAGE_CACHE_SHIFT) -
+ (pos & (PAGE_CACHE_SIZE-1));
+ /* If position is not on the
+ start of the page, we need
+ to substract the offset
+ within page */
+ } else
+ write_bytes = count;
+
+ /* reserve the blocks to be allocated later, so that later on
+ we still have the space to write the blocks to */
+ reiserfs_claim_blocks_to_be_allocated(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits));
+ reiserfs_write_unlock(inode->i_sb);
+
+ if ( !num_pages ) { /* If we do not have enough space even for */
+ res = -ENOSPC; /* single page, return -ENOSPC */
+ if ( pos > (inode->i_size & (inode->i_sb->s_blocksize-1)))
+ break; // In case we are writing past the file end, break.
+ // Otherwise we are possibly overwriting the file, so
+ // let's set write size to be equal or less than blocksize.
+ // This way we get it correctly for file holes.
+ // But overwriting files on absolutelly full volumes would not
+ // be very efficient. Well, people are not supposed to fill
+ // 100% of disk space anyway.
+ write_bytes = min_t(int, count, inode->i_sb->s_blocksize - (pos & (inode->i_sb->s_blocksize - 1)));
+ num_pages = 1;
+ }
+
+ /* Prepare for writing into the region, read in all the
+ partially overwritten pages, if needed. And lock the pages,
+ so that nobody else can access these until we are done.
+ We get number of actual blocks needed as a result.*/
+ blocks_to_allocate = reiserfs_prepare_file_region_for_write(inode, pos, num_pages, write_bytes, prepared_pages);
+ if ( blocks_to_allocate < 0 ) {
+ res = blocks_to_allocate;
+ reiserfs_release_claimed_blocks(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits));
+ break;
+ }
+
+ /* First we correct our estimate of how many blocks we need */
+ reiserfs_release_claimed_blocks(inode->i_sb, (num_pages << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits)) - blocks_to_allocate );
+
+ if ( blocks_to_allocate > 0) {/*We only allocate blocks if we need to*/
+ /* Fill in all the possible holes and append the file if needed */
+ res = reiserfs_allocate_blocks_for_region(inode, pos, num_pages, write_bytes, prepared_pages, blocks_to_allocate);
+ } else if ( pos + write_bytes > inode->i_size ) {
+ /* File might have grown even though no new blocks were added */
+ inode->i_size = pos + write_bytes;
+ inode->i_sb->s_op->dirty_inode(inode);
+ }
+
+ /* well, we have allocated the blocks, so it is time to free
+ the reservation we made earlier. */
+ reiserfs_release_claimed_blocks(inode->i_sb, blocks_to_allocate);
+ if ( res ) {
+ reiserfs_unprepare_pages(prepared_pages, num_pages);
+ break;
+ }
+
+/* NOTE that allocating blocks and filling blocks can be done in reverse order
+ and probably we would do that just to get rid of garbage in files after a
+ crash */
+
+ /* Copy data from user-supplied buffer to file's pages */
+ res = reiserfs_copy_from_user_to_file_region(pos, num_pages, write_bytes, prepared_pages, buf);
+ if ( res ) {
+ reiserfs_unprepare_pages(prepared_pages, num_pages);
+ break;
+ }
+
+ /* Send the pages to disk and unlock them. */
+ res = reiserfs_submit_file_region_for_write(pos, num_pages, write_bytes, prepared_pages);
+ if ( res )
+ break;
+
+ already_written += write_bytes;
+ buf += write_bytes;
+ *ppos = pos += write_bytes;
+ count -= write_bytes;
+ }
+
+ if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
+ res = generic_osync_inode(inode, OSYNC_METADATA|OSYNC_DATA);
+
+ up(&inode->i_sem);
+ return (already_written != 0)?already_written:res;
+
+out:
+ up(&inode->i_sem); // unlock the file on exit.
+ return res;
+}
+
struct file_operations reiserfs_file_operations = {
.read = generic_file_read,
- .write = generic_file_write,
+ .write = reiserfs_file_write,
.ioctl = reiserfs_ioctl,
.mmap = generic_file_mmap,
.release = reiserfs_file_release,
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index fb7f27f1f532..53caf4f460d0 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -14,6 +14,8 @@
#include <linux/mpage.h>
#include <linux/writeback.h>
+extern int reiserfs_default_io_size; /* default io size devuned in super.c */
+
/* args for the create parameter of reiserfs_get_block */
#define GET_BLOCK_NO_CREATE 0 /* don't create new blocks or convert tails */
#define GET_BLOCK_CREATE 1 /* add anything you need to find block */
@@ -766,7 +768,11 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
pointer to 'block'-th block use block, which is already
allocated */
struct cpu_key tmp_key;
- struct unfm_nodeinfo un = {0, 0};
+ unp_t unf_single=0; // We use this in case we need to allocate only
+ // one block which is a fastpath
+ unp_t *un;
+ __u64 max_to_insert=MAX_ITEM_LEN(inode->i_sb->s_blocksize)/UNFM_P_SIZE;
+ __u64 blocks_needed;
RFALSE( pos_in_item != ih_item_len(ih) / UNFM_P_SIZE,
"vs-804: invalid position for append");
@@ -775,30 +781,58 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
le_key_k_offset (version, &(ih->ih_key)) + op_bytes_number (ih, inode->i_sb->s_blocksize),
//pos_in_item * inode->i_sb->s_blocksize,
TYPE_INDIRECT, 3);// key type is unimportant
-
- if (cpu_key_k_offset (&tmp_key) == cpu_key_k_offset (&key)) {
+
+ blocks_needed = 1 + ((cpu_key_k_offset (&key) - cpu_key_k_offset (&tmp_key)) >> inode->i_sb->s_blocksize_bits);
+ RFALSE( blocks_needed < 0, "green-805: invalid offset");
+
+ if ( blocks_needed == 1 ) {
+ un = &unf_single;
+ } else {
+ un=kmalloc( min(blocks_needed,max_to_insert)*UNFM_P_SIZE,
+ GFP_ATOMIC); // We need to avoid scheduling.
+ if ( !un) {
+ un = &unf_single;
+ blocks_needed = 1;
+ max_to_insert = 0;
+ } else
+ memset(un, 0, UNFM_P_SIZE * min(blocks_needed,max_to_insert));
+ }
+ if ( blocks_needed <= max_to_insert) {
/* we are going to add target block to the file. Use allocated
block for that */
- un.unfm_nodenum = cpu_to_le32 (allocated_block_nr);
+ un[blocks_needed-1] = cpu_to_le32 (allocated_block_nr);
set_block_dev_mapped (bh_result, allocated_block_nr, inode);
set_buffer_new(bh_result);
done = 1;
} else {
/* paste hole to the indirect item */
+ /* If kmalloc failed, max_to_insert becomes zero and it means we
+ only have space for one block */
+ blocks_needed=max_to_insert?max_to_insert:1;
}
- retval = reiserfs_paste_into_item (&th, &path, &tmp_key, (char *)&un, UNFM_P_SIZE);
+ retval = reiserfs_paste_into_item (&th, &path, &tmp_key, (char *)un, UNFM_P_SIZE * blocks_needed);
+
+ if (blocks_needed != 1)
+ kfree(un);
+
if (retval) {
reiserfs_free_block (&th, allocated_block_nr);
goto failure;
}
- if (un.unfm_nodenum)
+ if (done) {
inode->i_blocks += inode->i_sb->s_blocksize / 512;
+ } else {
+ /* We need to mark new file size in case this function will be
+ interrupted/aborted later on. And we may do this only for
+ holes. */
+ inode->i_size += inode->i_sb->s_blocksize * blocks_needed;
+ }
//mark_tail_converted (inode);
}
-
+
if (done == 1)
break;
-
+
/* this loop could log more blocks than we had originally asked
** for. So, we have to allow the transaction to end if it is
** too big or too full. Update the inode so things are
@@ -876,7 +910,7 @@ static void init_inode (struct inode * inode, struct path * path)
copy_key (INODE_PKEY (inode), &(ih->ih_key));
- inode->i_blksize = PAGE_SIZE;
+ inode->i_blksize = reiserfs_default_io_size;
INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list ));
REISERFS_I(inode)->i_flags = 0;
@@ -1566,7 +1600,7 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
}
// these do not go to on-disk stat data
inode->i_ino = le32_to_cpu (ih.ih_key.k_objectid);
- inode->i_blksize = PAGE_SIZE;
+ inode->i_blksize = reiserfs_default_io_size;
// store in in-core inode the key of stat data and version all
// object items will have (directory items will have old offset
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index b461b4c324f3..a70cd0986486 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -532,6 +532,11 @@ static const arg_desc_t tails[] = {
{NULL, 0}
};
+int reiserfs_default_io_size = 128 * 1024; /* Default recommended I/O size is 128k.
+ There might be broken applications that are
+ confused by this. Use nolargeio mount option
+ to get usual i/o size = PAGE_SIZE.
+ */
/* proceed only one option from a list *cur - string containing of mount options
opts - array of options which are accepted
@@ -657,6 +662,7 @@ for old setups still work */
{"block-allocator", 'a', balloc, -1},
{"resize", 'r', 0, -1},
{"jdev", 'j', 0, -1},
+ {"nolargeio", 'w', 0, -1},
{NULL, 0, 0, -1}
};
@@ -688,6 +694,10 @@ for old setups still work */
}
}
+ if ( c == 'w' ) {
+ reiserfs_default_io_size = PAGE_SIZE;
+ }
+
if (c == 'j') {
if (arg && *arg && jdev_name) {
*jdev_name = arg;
@@ -1318,6 +1328,7 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent)
reiserfs_proc_register( s, "oidmap", reiserfs_oidmap_in_proc );
reiserfs_proc_register( s, "journal", reiserfs_journal_in_proc );
init_waitqueue_head (&(sbi->s_wait));
+ sbi->bitmap_lock = SPIN_LOCK_UNLOCKED;
return (0);
diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
index 9be2d624b989..48d614d41638 100644
--- a/fs/reiserfs/tail_conversion.c
+++ b/fs/reiserfs/tail_conversion.c
@@ -30,7 +30,7 @@ int direct2indirect (struct reiserfs_transaction_handle *th, struct inode * inod
key of unfm pointer to be pasted */
int n_blk_size,
n_retval; /* returned value for reiserfs_insert_item and clones */
- struct unfm_nodeinfo unfm_ptr; /* Handle on an unformatted node
+ unp_t unfm_ptr; /* Handle on an unformatted node
that will be inserted in the
tree. */
@@ -59,8 +59,7 @@ int direct2indirect (struct reiserfs_transaction_handle *th, struct inode * inod
p_le_ih = PATH_PITEM_HEAD (path);
- unfm_ptr.unfm_nodenum = cpu_to_le32 (unbh->b_blocknr);
- unfm_ptr.unfm_freespace = 0; // ???
+ unfm_ptr = cpu_to_le32 (unbh->b_blocknr);
if ( is_statdata_le_ih (p_le_ih) ) {
/* Insert new indirect item. */
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 5a2bd9c90a38..8ec65b81bdce 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -80,7 +80,7 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * nam
char * s;
depth = object_depth(kobj);
- size = object_path_length(target) + depth * 3 - 1;
+ size = object_path_length(target) + depth * 3 + 1;
if (size > PATH_MAX)
return -ENAMETOOLONG;
pr_debug("%s: depth = %d, size = %d\n",__FUNCTION__,depth,size);
diff --git a/include/asm-i386/genapic.h b/include/asm-i386/genapic.h
index d6d94d5436b0..0fb2bd405e96 100644
--- a/include/asm-i386/genapic.h
+++ b/include/asm-i386/genapic.h
@@ -59,6 +59,7 @@ struct genapic {
unsigned (*get_apic_id)(unsigned long x);
unsigned long apic_id_mask;
+ unsigned int (*cpu_mask_to_apicid)(unsigned long cpumask);
/* ipi */
void (*send_IPI_mask)(int mask, int vector);
@@ -95,6 +96,7 @@ struct genapic {
APICFUNC(mps_oem_check), \
APICFUNC(get_apic_id), \
.apic_id_mask = APIC_ID_MASK, \
+ APICFUNC(cpu_mask_to_apicid), \
APICFUNC(acpi_madt_oem_check), \
APICFUNC(send_IPI_mask), \
APICFUNC(send_IPI_allbutself), \
diff --git a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h
index 7b6435b052f3..7b84277e526c 100644
--- a/include/asm-i386/mach-bigsmp/mach_apic.h
+++ b/include/asm-i386/mach-bigsmp/mach_apic.h
@@ -40,10 +40,18 @@ static inline unsigned long check_apicid_present(int bit)
#define apicid_cluster(apicid) (apicid & 0xF0)
+static inline unsigned get_apic_id(unsigned long x)
+{
+ return (((x)>>24)&0x0F);
+}
+
+#define GET_APIC_ID(x) get_apic_id(x)
+
static inline unsigned long calculate_ldr(unsigned long old)
{
unsigned long id;
- id = xapic_phys_to_log_apicid(hard_smp_processor_id());
+ id = xapic_phys_to_log_apicid(
+ GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR)));
return ((old & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(id));
}
@@ -129,13 +137,6 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
#define APIC_ID_MASK (0x0F<<24)
-static inline unsigned get_apic_id(unsigned long x)
-{
- return (((x)>>24)&0x0F);
-}
-
-#define GET_APIC_ID(x) get_apic_id(x)
-
static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
{
int num_bits_set;
diff --git a/include/asm-i386/mach-generic/mach_apic.h b/include/asm-i386/mach-generic/mach_apic.h
index 9adab2c3f2fc..e498c6574568 100644
--- a/include/asm-i386/mach-generic/mach_apic.h
+++ b/include/asm-i386/mach-generic/mach_apic.h
@@ -26,5 +26,6 @@
#define check_apicid_used (genapic->check_apicid_used)
#define GET_APIC_ID (genapic->get_apic_id)
#define APIC_ID_MASK (genapic->apic_id_mask)
+#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index 93207f09d43b..cc5a532f6c95 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -48,12 +48,20 @@ static inline unsigned long check_apicid_present(int bit)
extern u8 bios_cpu_apicid[];
+static inline unsigned get_apic_id(unsigned long x)
+{
+ return (((x)>>24)&0xFF);
+}
+
+#define GET_APIC_ID(x) get_apic_id(x)
+
static inline void init_apic_ldr(void)
{
unsigned long val, id;
if (x86_summit)
- id = xapic_phys_to_log_apicid(hard_smp_processor_id());
+ id = xapic_phys_to_log_apicid(
+ GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID)));
else
id = 1UL << smp_processor_id();
apic_write_around(APIC_DFR, APIC_DFR_VALUE);
@@ -137,13 +145,6 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
#define APIC_ID_MASK (0xFF<<24)
-static inline unsigned get_apic_id(unsigned long x)
-{
- return (((x)>>24)&0xFF);
-}
-
-#define GET_APIC_ID(x) get_apic_id(x)
-
static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
{
int num_bits_set;
diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
index ff9a645cd798..14b1fa1ebef8 100644
--- a/include/asm-i386/mmu_context.h
+++ b/include/asm-i386/mmu_context.h
@@ -45,8 +45,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
#ifdef CONFIG_SMP
else {
cpu_tlbstate[cpu].state = TLBSTATE_OK;
- if (cpu_tlbstate[cpu].active_mm != next)
- BUG();
+ BUG_ON(cpu_tlbstate[cpu].active_mm != next);
+
if (!test_and_set_bit(cpu, &next->cpu_vm_mask)) {
/* We were in lazy tlb mode and leave_mm disabled
* tlb flush IPI delivery. We must reload %cr3.
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
index ae3615feecdb..47cb9c591a2e 100644
--- a/include/asm-i386/spinlock.h
+++ b/include/asm-i386/spinlock.h
@@ -5,6 +5,7 @@
#include <asm/rwlock.h>
#include <asm/page.h>
#include <linux/config.h>
+#include <linux/compiler.h>
extern int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2)));
@@ -70,10 +71,8 @@ typedef struct {
static inline void _raw_spin_unlock(spinlock_t *lock)
{
#ifdef CONFIG_DEBUG_SPINLOCK
- if (lock->magic != SPINLOCK_MAGIC)
- BUG();
- if (!spin_is_locked(lock))
- BUG();
+ BUG_ON(lock->magic != SPINLOCK_MAGIC);
+ BUG_ON(!spin_is_locked(lock));
#endif
__asm__ __volatile__(
spin_unlock_string
@@ -91,10 +90,8 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
{
char oldval = 1;
#ifdef CONFIG_DEBUG_SPINLOCK
- if (lock->magic != SPINLOCK_MAGIC)
- BUG();
- if (!spin_is_locked(lock))
- BUG();
+ BUG_ON(lock->magic != SPINLOCK_MAGIC);
+ BUG_ON(!spin_is_locked(lock));
#endif
__asm__ __volatile__(
spin_unlock_string
@@ -118,8 +115,8 @@ static inline void _raw_spin_lock(spinlock_t *lock)
#ifdef CONFIG_DEBUG_SPINLOCK
__label__ here;
here:
- if (lock->magic != SPINLOCK_MAGIC) {
-printk("eip: %p\n", &&here);
+ if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
+ printk("eip: %p\n", &&here);
BUG();
}
#endif
@@ -174,8 +171,7 @@ typedef struct {
static inline void _raw_read_lock(rwlock_t *rw)
{
#ifdef CONFIG_DEBUG_SPINLOCK
- if (rw->magic != RWLOCK_MAGIC)
- BUG();
+ BUG_ON(rw->magic != RWLOCK_MAGIC);
#endif
__build_read_lock(rw, "__read_lock_failed");
}
@@ -183,8 +179,7 @@ static inline void _raw_read_lock(rwlock_t *rw)
static inline void _raw_write_lock(rwlock_t *rw)
{
#ifdef CONFIG_DEBUG_SPINLOCK
- if (rw->magic != RWLOCK_MAGIC)
- BUG();
+ BUG_ON(rw->magic != RWLOCK_MAGIC);
#endif
__build_write_lock(rw, "__write_lock_failed");
}
diff --git a/include/asm-i386/types.h b/include/asm-i386/types.h
index b0d095271284..ced00fe8fe61 100644
--- a/include/asm-i386/types.h
+++ b/include/asm-i386/types.h
@@ -51,7 +51,7 @@ typedef unsigned long long u64;
/* DMA addresses come in generic and 64-bit flavours. */
-#ifdef CONFIG_HIGHMEM
+#ifdef CONFIG_HIGHMEM64G
typedef u64 dma_addr_t;
#else
typedef u32 dma_addr_t;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e514d070e334..7365aef817b5 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -313,7 +313,7 @@ struct backing_dev_info;
struct address_space {
struct inode *host; /* owner: inode, block_device */
struct radix_tree_root page_tree; /* radix tree of all pages */
- spinlock_t page_lock; /* and rwlock protecting it */
+ spinlock_t page_lock; /* and spinlock protecting it */
struct list_head clean_pages; /* list of clean pages */
struct list_head dirty_pages; /* list of dirty pages */
struct list_head locked_pages; /* list of locked pages */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 46b7f07a0069..492bc8aeb053 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -218,7 +218,7 @@ struct page {
*/
#define put_page_testzero(p) \
({ \
- BUG_ON(page_count(page) == 0); \
+ BUG_ON(page_count(p) == 0); \
atomic_dec_and_test(&(p)->count); \
})
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index bd3f28d266c2..fa5b3bdb0de6 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1268,6 +1268,7 @@ struct path var = {ILLEGAL_PATH_ELEMENT_OFFSET, }
/* Size of pointer to the unformatted node. */
#define UNFM_P_SIZE (sizeof(unp_t))
+#define UNFM_P_SHIFT 2
// in in-core inode key is stored on le form
#define INODE_PKEY(inode) ((struct key *)(REISERFS_I(inode)->i_key))
@@ -1838,7 +1839,7 @@ void reiserfs_do_truncate (struct reiserfs_transaction_handle *th,
void padd_item (char * item, int total_length, int length);
/* inode.c */
-
+void restart_transaction(struct reiserfs_transaction_handle *th, struct inode *inode, struct path *path);
void reiserfs_read_locked_inode(struct inode * inode, struct reiserfs_iget_args *args) ;
int reiserfs_find_actor(struct inode * inode, void *p) ;
int reiserfs_init_locked_inode(struct inode * inode, void *p) ;
@@ -2111,6 +2112,7 @@ void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th);
#endif
void reiserfs_claim_blocks_to_be_allocated( struct super_block *sb, int blocks);
void reiserfs_release_claimed_blocks( struct super_block *sb, int blocks);
+int reiserfs_can_fit_pages(struct super_block *sb);
/* hashes.c */
__u32 keyed_hash (const signed char *msg, int len);
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 28b31edd08dc..25eae6a8ece8 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -397,6 +397,7 @@ struct reiserfs_sb_info
reiserfs_proc_info_data_t s_proc_info_data;
struct proc_dir_entry *procdir;
int reserved_blocks; /* amount of blocks reserved for further allocations */
+ spinlock_t bitmap_lock; /* this lock on now only used to protect reserved_blocks variable */
};
/* Definitions of reiserfs on-disk properties: */
diff --git a/include/media/audiochip.h b/include/media/audiochip.h
index e5a5cd2bb172..1fbc90e53232 100644
--- a/include/media/audiochip.h
+++ b/include/media/audiochip.h
@@ -18,6 +18,15 @@
#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)
diff --git a/include/media/tuner.h b/include/media/tuner.h
index f716e23dda8e..c1a826b504ed 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -64,7 +64,7 @@
#define TUNER_LG_PAL_NEW_TAPC 37
#define TUNER_PHILIPS_FM1216ME_MK3 38
#define TUNER_LG_NTSC_NEW_TAPC 39
-
+#define TUNER_HITACHI_NTSC 40
@@ -83,6 +83,7 @@
#define SHARP 6
#define Samsung 7
#define Microtune 8
+#define HITACHI 9
#define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */
#define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */
diff --git a/include/media/video-buf.h b/include/media/video-buf.h
index fceea3e24f75..aefb7fa99f35 100644
--- a/include/media/video-buf.h
+++ b/include/media/video-buf.h
@@ -196,6 +196,7 @@ void videobuf_queue_init(struct videobuf_queue *q,
int videobuf_queue_is_busy(struct videobuf_queue *q);
void videobuf_queue_cancel(struct file *file, struct videobuf_queue *q);
+enum v4l2_field videobuf_next_field(struct videobuf_queue *q);
void videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb,
enum v4l2_buf_type type);
int videobuf_reqbufs(struct file *file, struct videobuf_queue *q,
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index cd8f9810ddc9..eed4ac9b8f51 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -223,6 +223,7 @@ EXPORT_SYMBOL(block_sync_page);
EXPORT_SYMBOL(generic_cont_expand);
EXPORT_SYMBOL(cont_prepare_write);
EXPORT_SYMBOL(generic_commit_write);
+EXPORT_SYMBOL(block_commit_write);
EXPORT_SYMBOL(block_truncate_page);
EXPORT_SYMBOL(generic_block_bmap);
EXPORT_SYMBOL(generic_file_read);
@@ -556,6 +557,8 @@ EXPORT_SYMBOL(buffer_insert_list);
EXPORT_SYMBOL(make_bad_inode);
EXPORT_SYMBOL(is_bad_inode);
EXPORT_SYMBOL(__inode_dir_notify);
+EXPORT_SYMBOL(generic_osync_inode);
+EXPORT_SYMBOL(remove_suid);
#ifdef CONFIG_UID16
EXPORT_SYMBOL(overflowuid);
diff --git a/mm/memory.c b/mm/memory.c
index 8397ea054459..e0dee2c62f5d 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1108,17 +1108,12 @@ int vmtruncate(struct inode * inode, loff_t offset)
if (inode->i_size < offset)
goto do_expand;
inode->i_size = offset;
+ pgoff = (offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
down(&mapping->i_shared_sem);
- if (list_empty(&mapping->i_mmap) && list_empty(&mapping->i_mmap_shared))
- goto out_unlock;
-
- pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- if (!list_empty(&mapping->i_mmap))
+ if (unlikely(!list_empty(&mapping->i_mmap)))
vmtruncate_list(&mapping->i_mmap, pgoff);
- if (!list_empty(&mapping->i_mmap_shared))
+ if (unlikely(!list_empty(&mapping->i_mmap_shared)))
vmtruncate_list(&mapping->i_mmap_shared, pgoff);
-
-out_unlock:
up(&mapping->i_shared_sem);
truncate_inode_pages(mapping, offset);
goto out_truncate;
diff --git a/mm/truncate.c b/mm/truncate.c
index 8828e0e48bf0..0f6706fcda18 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -173,15 +173,13 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
}
pagevec_release(&pvec);
}
- if (lstart == 0 && mapping->nrpages)
- printk("%s: I goofed!\n", __FUNCTION__);
}
/**
* invalidate_mapping_pages - Invalidate all the unlocked pages of one inode
- * @inode: the address_space which holds the pages to invalidate
- * @end: the index of the last page to invalidate (inclusive)
- * @nr_pages: defines the pagecache span. Invalidate up to @start + @nr_pages
+ * @mapping: the address_space which holds the pages to invalidate
+ * @start: the offset 'from' which to invalidate
+ * @end: the offset 'to' which to invalidate (inclusive)
*
* This function only removes the unlocked pages, if you want to
* remove all the pages of one inode, you must call truncate_inode_pages.
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index fa85cae733f4..df47a86da3b3 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -110,7 +110,8 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
kfree(nr_neigh);
return -ENOMEM;
}
- memcpy(nr_neigh->digipeat, ax25_digi, sizeof(ax25_digi));
+ memcpy(nr_neigh->digipeat, ax25_digi,
+ sizeof(*ax25_digi));
}
spin_lock_bh(&nr_neigh_lock);
@@ -387,7 +388,7 @@ static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net
kfree(nr_neigh);
return -ENOMEM;
}
- memcpy(nr_neigh->digipeat, ax25_digi, sizeof(ax25_digi));
+ memcpy(nr_neigh->digipeat, ax25_digi, sizeof(*ax25_digi));
}
spin_lock_bh(&nr_neigh_lock);
diff --git a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c
index 258efe39f34d..5757af590054 100644
--- a/sound/oss/cs4281/cs4281m.c
+++ b/sound/oss/cs4281/cs4281m.c
@@ -1944,8 +1944,8 @@ static void clear_advance(void *buf, unsigned bsize, unsigned bptr,
len -= x;
}
CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO
- "cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n",
- (unsigned)c, (unsigned)((char *) buf) + bptr, len));
+ "cs4281: clear_advance(): memset %d at %p for %d size \n",
+ (unsigned)c, ((char *) buf) + bptr, len));
memset(((char *) buf) + bptr, c, len);
}
@@ -1980,9 +1980,8 @@ static void cs4281_update_ptr(struct cs4281_state *s, int intflag)
wake_up(&s->dma_adc.wait);
}
CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO
- "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",
- (unsigned)s, s->dma_adc.hwptr,
- s->dma_adc.total_bytes, s->dma_adc.count));
+ "cs4281: cs4281_update_ptr(): s=%p hwptr=%d total_bytes=%d count=%d \n",
+ s, s->dma_adc.hwptr, s->dma_adc.total_bytes, s->dma_adc.count));
}
// update DAC pointer
//
@@ -2014,11 +2013,10 @@ static void cs4281_update_ptr(struct cs4281_state *s, int intflag)
// Continue to play silence until the _release.
//
CS_DBGOUT(CS_WAVE_WRITE, 6, printk(KERN_INFO
- "cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n",
+ "cs4281: cs4281_update_ptr(): memset %d at %p for %d size \n",
(unsigned)(s->prop_dac.fmt &
(AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,
- (unsigned)s->dma_dac.rawbuf,
- s->dma_dac.dmasize));
+ s->dma_dac.rawbuf, s->dma_dac.dmasize));
memset(s->dma_dac.rawbuf,
(s->prop_dac.
fmt & (AFMT_U8 | AFMT_U16_LE)) ?
@@ -2049,9 +2047,8 @@ static void cs4281_update_ptr(struct cs4281_state *s, int intflag)
}
}
CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO
- "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",
- (unsigned) s, s->dma_dac.hwptr,
- s->dma_dac.total_bytes, s->dma_dac.count));
+ "cs4281: cs4281_update_ptr(): s=%p hwptr=%d total_bytes=%d count=%d \n",
+ s, s->dma_dac.hwptr, s->dma_dac.total_bytes, s->dma_dac.count));
}
}
@@ -2182,8 +2179,7 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd,
VALIDATE_STATE(s);
CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
- "cs4281: mixer_ioctl(): s=0x%.8x cmd=0x%.8x\n",
- (unsigned) s, cmd));
+ "cs4281: mixer_ioctl(): s=%p cmd=0x%.8x\n", s, cmd));
#if CSDEBUG
cs_printioctl(cmd);
#endif
@@ -2748,9 +2744,8 @@ static void CopySamples(char *dst, char *src, int count, int iChannels,
CS_DBGOUT(CS_FUNCTION, 2,
printk(KERN_INFO "cs4281: CopySamples()+ "));
CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
- " dst=0x%x src=0x%x count=%d iChannels=%d fmt=0x%x\n",
- (unsigned) dst, (unsigned) src, (unsigned) count,
- (unsigned) iChannels, (unsigned) fmt));
+ " dst=%p src=%p count=%d iChannels=%d fmt=0x%x\n",
+ dst, src, (unsigned) count, (unsigned) iChannels, (unsigned) fmt));
// Gershwin does format conversion in hardware so normally
// we don't do any host based coversion. The data formatter
@@ -2830,9 +2825,9 @@ static unsigned cs_copy_to_user(struct cs4281_state *s, void *dest,
void *src = hwsrc; //default to the standard destination buffer addr
CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO
- "cs_copy_to_user()+ fmt=0x%x fmt_o=0x%x cnt=%d dest=0x%.8x\n",
+ "cs_copy_to_user()+ fmt=0x%x fmt_o=0x%x cnt=%d dest=%p\n",
s->prop_adc.fmt, s->prop_adc.fmt_original,
- (unsigned) cnt, (unsigned) dest));
+ (unsigned) cnt, dest));
if (cnt > s->dma_adc.dmasize) {
cnt = s->dma_adc.dmasize;
@@ -2877,7 +2872,7 @@ static ssize_t cs4281_read(struct file *file, char *buffer, size_t count,
unsigned copied = 0;
CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2,
- printk(KERN_INFO "cs4281: cs4281_read()+ %d \n", count));
+ printk(KERN_INFO "cs4281: cs4281_read()+ %Zu \n", count));
VALIDATE_STATE(s);
if (ppos != &file->f_pos)
@@ -2900,7 +2895,7 @@ static ssize_t cs4281_read(struct file *file, char *buffer, size_t count,
//
while (count > 0) {
CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
- "_read() count>0 count=%d .count=%d .swptr=%d .hwptr=%d \n",
+ "_read() count>0 count=%Zu .count=%d .swptr=%d .hwptr=%d \n",
count, s->dma_adc.count,
s->dma_adc.swptr, s->dma_adc.hwptr));
spin_lock_irqsave(&s->lock, flags);
@@ -2957,11 +2952,10 @@ static ssize_t cs4281_read(struct file *file, char *buffer, size_t count,
// the "cnt" is the number of bytes to read.
CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO
- "_read() copy_to cnt=%d count=%d ", cnt, count));
+ "_read() copy_to cnt=%d count=%Zu ", cnt, count));
CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
- " .dmasize=%d .count=%d buffer=0x%.8x ret=%d\n",
- s->dma_adc.dmasize, s->dma_adc.count,
- (unsigned) buffer, ret));
+ " .dmasize=%d .count=%d buffer=%p ret=%Zd\n",
+ s->dma_adc.dmasize, s->dma_adc.count, buffer, ret));
if (cs_copy_to_user
(s, buffer, s->dma_adc.rawbuf + swptr, cnt, &copied))
@@ -2977,7 +2971,7 @@ static ssize_t cs4281_read(struct file *file, char *buffer, size_t count,
start_adc(s);
}
CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2,
- printk(KERN_INFO "cs4281: cs4281_read()- %d\n", ret));
+ printk(KERN_INFO "cs4281: cs4281_read()- %Zd\n", ret));
return ret;
}
@@ -2993,7 +2987,7 @@ static ssize_t cs4281_write(struct file *file, const char *buffer,
int cnt;
CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2,
- printk(KERN_INFO "cs4281: cs4281_write()+ count=%d\n",
+ printk(KERN_INFO "cs4281: cs4281_write()+ count=%Zu\n",
count));
VALIDATE_STATE(s);
@@ -3049,7 +3043,7 @@ static ssize_t cs4281_write(struct file *file, const char *buffer,
start_dac(s);
}
CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2,
- printk(KERN_INFO "cs4281: cs4281_write()- %d\n", ret));
+ printk(KERN_INFO "cs4281: cs4281_write()- %Zd\n", ret));
return ret;
}
@@ -3170,8 +3164,7 @@ static int cs4281_ioctl(struct inode *inode, struct file *file,
int val, mapped, ret;
CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
- "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n",
- (unsigned) file, cmd));
+ "cs4281: cs4281_ioctl(): file=%p cmd=0x%.8x\n", file, cmd));
#if CSDEBUG
cs_printioctl(cmd);
#endif
@@ -3601,8 +3594,8 @@ static int cs4281_release(struct inode *inode, struct file *file)
(struct cs4281_state *) file->private_data;
CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk(KERN_INFO
- "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x f_mode=%d\n",
- (unsigned) inode, (unsigned) file, file->f_mode));
+ "cs4281: cs4281_release(): inode=%p file=%p f_mode=%d\n",
+ inode, file, file->f_mode));
VALIDATE_STATE(s);
@@ -3636,8 +3629,8 @@ static int cs4281_open(struct inode *inode, struct file *file)
struct list_head *entry;
CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
- "cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x f_mode=0x%x\n",
- (unsigned) inode, (unsigned) file, file->f_mode));
+ "cs4281: cs4281_open(): inode=%p file=%p f_mode=0x%x\n",
+ inode, file, file->f_mode));
list_for_each(entry, &cs4281_devs)
{
@@ -4347,10 +4340,8 @@ static int __devinit cs4281_probe(struct pci_dev *pcidev,
CS_DBGOUT(CS_INIT, 2,
printk(KERN_INFO
- "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n",
- (unsigned) temp1, (unsigned) temp2,
- (unsigned) s->pBA0, (unsigned) s->pBA1));
-
+ "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=%p pBA1=%p \n",
+ (unsigned) temp1, (unsigned) temp2, s->pBA0, s->pBA1));
CS_DBGOUT(CS_INIT, 2,
printk(KERN_INFO
"cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n",
@@ -4397,15 +4388,13 @@ static int __devinit cs4281_probe(struct pci_dev *pcidev,
if (pmdev)
{
CS_DBGOUT(CS_INIT | CS_PM, 4, printk(KERN_INFO
- "cs4281: probe() pm_register() succeeded (0x%x).\n",
- (unsigned)pmdev));
+ "cs4281: probe() pm_register() succeeded (%p).\n", pmdev));
pmdev->data = s;
}
else
{
CS_DBGOUT(CS_INIT | CS_PM | CS_ERROR, 0, printk(KERN_INFO
- "cs4281: probe() pm_register() failed (0x%x).\n",
- (unsigned)pmdev));
+ "cs4281: probe() pm_register() failed (%p).\n", pmdev));
s->pm.flags |= CS4281_PM_NOT_REGISTERED;
}
#endif
diff --git a/sound/oss/cs4281/cs4281pm-24.c b/sound/oss/cs4281/cs4281pm-24.c
index eaada08be1e5..faa091b8cb0d 100644
--- a/sound/oss/cs4281/cs4281pm-24.c
+++ b/sound/oss/cs4281/cs4281pm-24.c
@@ -46,8 +46,8 @@ int cs4281_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
struct cs4281_state *state;
CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
- "cs4281: cs4281_pm_callback dev=0x%x rqst=0x%x state=%d\n",
- (unsigned)dev,(unsigned)rqst,(unsigned)data));
+ "cs4281: cs4281_pm_callback dev=%p rqst=0x%x state=%p\n",
+ dev,(unsigned)rqst,data));
state = (struct cs4281_state *) dev->data;
if (state) {
switch(rqst) {
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 6d7a655cf7f5..02e2ec335502 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -2206,7 +2206,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
unsigned short fxbus_mask, extin_mask, extout_mask;
int res;
- memset(info, 0, sizeof(info));
+ memset(info, 0, sizeof(*info));
info->card = emu->card_type;
info->internal_tram_size = emu->fx8010.itram_size;
info->external_tram_size = emu->fx8010.etram_size;