diff options
783 files changed, 27532 insertions, 21432 deletions
@@ -2299,8 +2299,8 @@ E: acme@redhat.com W: http://oops.ghostprotocols.net:81/blog/ P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD 841A B6AB 4681 9224 DF01 D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks -S: R. Brasílio Itiberê, 4270/1010 - Água Verde -S: 80240-060 - Curitiba - Paraná +S: R. BrasÃlio Itiberê, 4270/1010 - Ãgua Verde +S: 80240-060 - Curitiba - Paraná S: Brazil N: Karsten Merker diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist index 6491b2c45dd4..3af3e65cf43b 100644 --- a/Documentation/SubmitChecklist +++ b/Documentation/SubmitChecklist @@ -73,9 +73,9 @@ kernel patches. If the new code is substantial, addition of subsystem-specific fault injection might be appropriate. -22: Newly-added code has been compiled with `gcc -W'. This will generate - lots of noise, but is good for finding bugs like "warning: comparison - between signed and unsigned". +22: Newly-added code has been compiled with `gcc -W' (use "make + EXTRA_CFLAGS=-W"). This will generate lots of noise, but is good for + finding bugs like "warning: comparison between signed and unsigned". 23: Tested after it has been merged into the -mm patchset to make sure that it still works with all of the other queued patches and various diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index c6322c760348..498ff31f3aa1 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -328,3 +328,22 @@ Who: Adrian Bunk <bunk@stusta.de> --------------------------- +What: libata.spindown_compat module parameter +When: Dec 2008 +Why: halt(8) synchronizes caches for and spins down libata disks + because libata didn't use to spin down disk on system halt + (only synchronized caches). + Spin down on system halt is now implemented and can be tested + using sysfs node /sys/class/scsi_disk/h:c:i:l/manage_start_stop. + Because issuing spin down command to an already spun down disk + makes some disks spin up just to spin down again, the old + behavior needs to be maintained till userspace tool is updated + to check the sysfs node and not to spin down disks with the + node set to one. + This module parameter is to give userspace tool the time to + get updated and should be removed after userspace is + reasonably updated. +Who: Tejun Heo <htejun@gmail.com> + +--------------------------- + diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index f8528db967fa..e8be0abb346c 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt @@ -66,7 +66,9 @@ registers; another might implement it by delegating through abstractions used for several very different kinds of GPIO controller. That said, if the convention is supported on their platform, drivers should -use it when possible: +use it when possible. Platforms should declare GENERIC_GPIO support in +Kconfig (boolean true), which multi-platform drivers can depend on when +using the include file: #include <asm/gpio.h> diff --git a/Documentation/kref.txt b/Documentation/kref.txt index 42fe28445916..f38b59d00c63 100644 --- a/Documentation/kref.txt +++ b/Documentation/kref.txt @@ -67,7 +67,7 @@ void more_data_handling(void *cb_data) . . do stuff with data here . - kref_put(data, data_release); + kref_put(&data->refcount, data_release); } int my_data_handler(void) diff --git a/Documentation/mips/pci/pci.README b/Documentation/mips/pci/pci.README deleted file mode 100644 index 8697ee41372d..000000000000 --- a/Documentation/mips/pci/pci.README +++ /dev/null @@ -1,54 +0,0 @@ - -Pete Popov, ppopov@pacbell.net -07/11/2001 - -This README briefly explains how to use the pci and pci_auto -code in arch/mips/kernel. The code was ported from PowerPC and -modified slightly. It has been tested pretty well on PPC on some -rather complex systems with multiple bridges and devices behind -each bridge. However, at the time this README was written, the -mips port was tested only on boards with a single pci bus and -no P2P bridges. It's very possible that on boards with P2P -bridges some modifications have to be made. The code will -evolve, no doubt, but currently every single mips board -is doing its own pcibios thing and it has become a big -mess. This generic pci code is meant to clean up the mips -pci mess and make it easier to add pci support to new boards. - -inside the define for your board in arch/mips/config.in. -For example, the Galileo EV96100 board looks like this: - -if [ "$CONFIG_MIPS_EV96100" = "y" ]; then - define_bool CONFIG_PCI y - define_bool CONFIG_MIPS_GT96100 y - define_bool CONFIG_NEW_PCI y - define_bool CONFIG_SWAP_IO_SPACE y -fi - - -Next, if you want to use the arch/mips/kernel/pci code, which has the -pcibios_init() function, add - -define_bool CONFIG_NEW_PCI y - -inside the define for your board. Again, the EV96100 example above -show NEW_PCI turned on. - - -Now you need to add your files to hook in your pci configuration -cycles. Usually you'll need only a couple of files named something -like pci_fixups.c and pci_ops.c. You can copy the templates -provided and fill in the code. - -The file pci_ops.c should contain the pci configuration cycles routines. -It also has the mips_pci_channels[] array which contains the descriptors -of each pci controller. - -The file pci_fixups.c contains a few routines to do interrupt fixups, -resources fixups, and, if needed, pci bios fixups. - -Usually you'll put your pci_fixups.c file in your board specific directory, -since the functions in that file are board specific. The functions in -pci_ops.c, on the other hand, are usually pci controller specific so that -file could be shared among a few different boards using the same -pci controller. diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 73e9a174b642..57b878cc393c 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -821,6 +821,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 6stack-dig 6-jack digital with SPDIF I/O arima Arima W820Di1 macpro MacPro support + w2jc ASUS W2JC auto auto-config reading BIOS (default) ALC883/888 @@ -852,6 +853,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack-dig 3-jack with SPDIF OUT 6stack-dig 6-jack with SPDIF OUT 3stack-660 3-jack (for ALC660VD) + lenovo Lenovo 3000 C200 auto auto-config reading BIOS (default) CMI9880 @@ -909,6 +911,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. macbook Intel Mac Book macbook-pro-v1 Intel Mac Book Pro 1st generation macbook-pro Intel Mac Book Pro 2nd generation + imac-intel Intel iMac STAC9202/9250/9251 ref Reference board, base config @@ -924,6 +927,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. vaio Setup for VAIO FE550G/SZ110 vaio-ar Setup for VAIO AR + The model name "genric" is treated as a special case. When this + model is given, the driver uses the generic codec parser without + "codec-patch". It's sometimes good for testing and debugging. + If the default configuration doesn't work and one of the above matches with your device, report it together with the PCI subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel @@ -1278,6 +1285,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. port - port number or -1 (disable) irq - IRQ number or -1 (disable) pnp - PnP detection - 0 = disable, 1 = enable (default) + uart_enter - Issue UART_ENTER command at open - bool, default = on This module supports multiple devices and PnP. @@ -1692,6 +1700,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. This module supports multiple devices, autoprobe and hotplugging. + Module snd-usb-caiaq + -------------------- + + Module for caiaq UB audio interfaces, + * Native Instruments RigKontrol2 + * Native Instruments Kore Controller + * Native Instruments Audio Kontrol 1 + * Native Instruments Audio 8 DJ + + This module supports multiple devices, autoprobe and hotplugging. + Module snd-usb-usx2y -------------------- @@ -2046,4 +2065,4 @@ Links and Addresses https://bugtrack.alsa-project.org/bugs/ ALSA Developers ML - mailto:alsa-devel@lists.sourceforge.net + mailto:alsa-devel@alsa-project.org diff --git a/Documentation/sound/alsa/Bt87x.txt b/Documentation/sound/alsa/Bt87x.txt index 11edb2fd2a5a..f158cde8b065 100644 --- a/Documentation/sound/alsa/Bt87x.txt +++ b/Documentation/sound/alsa/Bt87x.txt @@ -36,8 +36,8 @@ recorded data is not right, try to specify the digital_rate option with other values than the default 32000 (often it's 44100 or 64000). If you have an unknown card, please mail the ID and board name to -<alsa-devel@lists.sf.net>, regardless of whether audio capture works or -not, so that future versions of this driver know about your card. +<alsa-devel@alsa-project.org>, regardless of whether audio capture works +or not, so that future versions of this driver know about your card. Audio modes diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index d7bb2e2e4d9b..712e8c8333cc 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -52,7 +52,7 @@ 51 -> ProVideo PV952 [1540:9524] 52 -> AverMedia AverTV/305 [1461:2108] 53 -> ASUS TV-FM 7135 [1043:4845] - 54 -> LifeView FlyTV Platinum FM / Gold [5168:0214,1489:0214,5168:0304] + 54 -> LifeView FlyTV Platinum FM / Gold [5168:0214,5168:5214,1489:0214,5168:0304] 55 -> LifeView FlyDVB-T DUO / MSI TV@nywhere Duo [5168:0306,4E42:0306] 56 -> Avermedia AVerTV 307 [1461:a70a] 57 -> Avermedia AVerTV GO 007 FM [1461:f31f] @@ -111,3 +111,6 @@ 110 -> Avermedia M102 [1461:f31e] 111 -> ASUS P7131 4871 [1043:4871] 112 -> ASUSTeK P7131 Hybrid [1043:4876] +113 -> Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM) [1019:4cb6] +114 -> KWorld DVB-T 210 [17de:7250] +115 -> Sabrent PCMCIA TV-PCB05 [0919:2003] diff --git a/Documentation/video4linux/sn9c102.txt b/Documentation/video4linux/sn9c102.txt index 5fe0ad7dfc20..279717c96f63 100644 --- a/Documentation/video4linux/sn9c102.txt +++ b/Documentation/video4linux/sn9c102.txt @@ -355,6 +355,9 @@ devices assembling the SN9C1xx PC camera controllers: Vendor ID Product ID --------- ---------- +0x0458 0x7025 +0x045e 0x00f5 +0x045e 0x00f7 0x0471 0x0327 0x0471 0x0328 0x0c45 0x6001 @@ -432,7 +435,7 @@ Image sensor / SN9C1xx bridge | SN9C10[12] SN9C103 SN9C105 SN9C120 HV7131D Hynix Semiconductor | Yes No No No HV7131R Hynix Semiconductor | No Yes Yes Yes MI-0343 Micron Technology | Yes No No No -MI-0360 Micron Technology | No Yes No No +MI-0360 Micron Technology | No Yes Yes Yes OV7630 OmniVision Technologies | Yes Yes No No OV7660 OmniVision Technologies | No No Yes Yes PAS106B PixArt Imaging | Yes No No No @@ -478,13 +481,12 @@ scaling factor is restored to 1. This driver supports two different video formats: the first one is the "8-bit Sequential Bayer" format and can be used to obtain uncompressed video data from the device through the current I/O method, while the second one provides -"raw" compressed video data (without frame headers not related to the -compressed data). The compression quality may vary from 0 to 1 and can be -selected or queried thanks to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 -ioctl's. For maximum flexibility, both the default active video format and the -default compression quality depend on how the image sensor being used is -initialized (as described in the documentation of the API for the image sensors -supplied by this driver). +either "raw" compressed video data (without frame headers not related to the +compressed data) or standard JPEG (with frame headers). The compression quality +may vary from 0 to 1 and can be selected or queried thanks to the +VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum flexibility, +both the default active video format and the default compression quality +depend on how the image sensor being used is initialized. 11. Video frame formats [1] diff --git a/MAINTAINERS b/MAINTAINERS index bd558ac5bb73..68a56add73e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -372,7 +372,7 @@ AOA (Apple Onboard Audio) ALSA DRIVER P: Johannes Berg M: johannes@sipsolutions.net L: linuxppc-dev@ozlabs.org -L: alsa-devel@alsa-project.org +L: alsa-devel@alsa-project.org (subscribers-only) S: Maintained APM DRIVER @@ -3239,13 +3239,13 @@ S: Maintained SOUND P: Jaroslav Kysela M: perex@suse.cz -L: alsa-devel@alsa-project.org +L: alsa-devel@alsa-project.org (subscribers-only) S: Maintained SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT P: Liam Girdwood M: liam.girdwood@wolfsonmicro.com -L: alsa-devel@alsa-project.org +L: alsa-devel@alsa-project.org (subscribers-only) S: Supported SPI SUBSYSTEM @@ -3269,7 +3269,6 @@ W: http://tpmdd.sourceforge.net P: Marcel Selhorst M: tpm@selhorst.net W: http://www.prosec.rub.de/tpm/ -L: tpmdd-devel@lists.sourceforge.net S: Maintained Telecom Clock Driver for MCPL0010 diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c index 9550f37fb62c..1e7a101cbf4c 100644 --- a/arch/frv/kernel/gdb-stub.c +++ b/arch/frv/kernel/gdb-stub.c @@ -1195,7 +1195,7 @@ static void gdbstub_check_breakpoint(void) /* * */ -static void __attribute__((unused)) gdbstub_show_regs(void) +static void __maybe_unused gdbstub_show_regs(void) { unsigned long *reg; int loop; @@ -1223,7 +1223,7 @@ static void __attribute__((unused)) gdbstub_show_regs(void) /* * dump debugging regs */ -static void __attribute__((unused)) gdbstub_dump_debugregs(void) +static void __maybe_unused gdbstub_dump_debugregs(void) { gdbstub_printk("DCR %08lx ", __debug_status.dcr); gdbstub_printk("BRR %08lx\n", __debug_status.brr); @@ -2079,25 +2079,25 @@ void gdbstub_exit(int status) * GDB wants to call malloc() and free() to allocate memory for calling kernel * functions directly from its command line */ -static void *malloc(size_t size) __attribute__((unused)); +static void *malloc(size_t size) __maybe_unused; static void *malloc(size_t size) { return kmalloc(size, GFP_ATOMIC); } -static void free(void *p) __attribute__((unused)); +static void free(void *p) __maybe_unused; static void free(void *p) { kfree(p); } -static uint32_t ___get_HSR0(void) __attribute__((unused)); +static uint32_t ___get_HSR0(void) __maybe_unused; static uint32_t ___get_HSR0(void) { return __get_HSR(0); } -static uint32_t ___set_HSR0(uint32_t x) __attribute__((unused)); +static uint32_t ___set_HSR0(uint32_t x) __maybe_unused; static uint32_t ___set_HSR0(uint32_t x) { __set_HSR(0, x); diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S index dab98fd99e63..54e21c3f2057 100644 --- a/arch/h8300/kernel/syscalls.S +++ b/arch/h8300/kernel/syscalls.S @@ -31,7 +31,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_mknod) .long SYMBOL_NAME(sys_chmod) /* 15 */ .long SYMBOL_NAME(sys_chown16) - .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ .long SYMBOL_NAME(sys_stat) .long SYMBOL_NAME(sys_lseek) .long SYMBOL_NAME(sys_getpid) /* 20 */ @@ -45,11 +45,11 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_fstat) .long SYMBOL_NAME(sys_pause) .long SYMBOL_NAME(sys_utime) /* 30 */ - .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */ - .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */ .long SYMBOL_NAME(sys_access) .long SYMBOL_NAME(sys_nice) - .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* 35 old ftime syscall holder */ .long SYMBOL_NAME(sys_sync) .long SYMBOL_NAME(sys_kill) .long SYMBOL_NAME(sys_rename) @@ -58,7 +58,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_dup) .long SYMBOL_NAME(sys_pipe) .long SYMBOL_NAME(sys_times) - .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ .long SYMBOL_NAME(sys_brk) /* 45 */ .long SYMBOL_NAME(sys_setgid16) .long SYMBOL_NAME(sys_getgid16) @@ -66,13 +66,13 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_geteuid16) .long SYMBOL_NAME(sys_getegid16) /* 50 */ .long SYMBOL_NAME(sys_acct) - .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ - .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ + .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ + .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ .long SYMBOL_NAME(sys_ioctl) .long SYMBOL_NAME(sys_fcntl) /* 55 */ - .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */ .long SYMBOL_NAME(sys_setpgid) - .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */ .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_umask) /* 60 */ .long SYMBOL_NAME(sys_chroot) @@ -112,7 +112,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_fchown16) /* 95 */ .long SYMBOL_NAME(sys_getpriority) .long SYMBOL_NAME(sys_setpriority) - .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ .long SYMBOL_NAME(sys_statfs) .long SYMBOL_NAME(sys_fstatfs) /* 100 */ .long SYMBOL_NAME(sys_ni_syscall) /* ioperm for i386 */ @@ -202,8 +202,8 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_capset) /* 185 */ .long SYMBOL_NAME(sys_sigaltstack) .long SYMBOL_NAME(sys_sendfile) - .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ - .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ + .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ + .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ .long SYMBOL_NAME(sys_vfork) /* 190 */ .long SYMBOL_NAME(sys_getrlimit) .long SYMBOL_NAME(sys_mmap2) @@ -236,10 +236,10 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_getdents64) /* 220 */ .long SYMBOL_NAME(sys_fcntl64) - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ - .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* reserved TUX */ + .long SYMBOL_NAME(sys_ni_syscall) /* reserved Security */ .long SYMBOL_NAME(sys_gettid) - .long SYMBOL_NAME(sys_ni_syscall) /* 225 */ /* sys_readahead */ + .long SYMBOL_NAME(sys_readahead) /* 225 */ .long SYMBOL_NAME(sys_setxattr) .long SYMBOL_NAME(sys_lsetxattr) .long SYMBOL_NAME(sys_fsetxattr) @@ -257,8 +257,8 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_futex) /* 240 */ .long SYMBOL_NAME(sys_sched_setaffinity) .long SYMBOL_NAME(sys_sched_getaffinity) - .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_thread_area */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_get_thread_area */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_io_setup) /* 245 */ .long SYMBOL_NAME(sys_io_destroy) .long SYMBOL_NAME(sys_io_getevents) @@ -288,8 +288,8 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_utimes) .long SYMBOL_NAME(sys_fadvise64_64) .long SYMBOL_NAME(sys_ni_syscall) /* sys_vserver */ - .long SYMBOL_NAME(sys_mbind) - .long SYMBOL_NAME(sys_get_mempolicy) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_get_mempolicy) /* 275 */ .long SYMBOL_NAME(sys_set_mempolicy) .long SYMBOL_NAME(sys_mq_open) .long SYMBOL_NAME(sys_mq_unlink) @@ -297,16 +297,42 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_mq_timedreceive) /* 280 */ .long SYMBOL_NAME(sys_mq_notify) .long SYMBOL_NAME(sys_mq_getsetattr) - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for kexec */ .long SYMBOL_NAME(sys_waitid) - .long SYMBOL_NAME(sys_ni_syscall) /* 285 */ /* available */ - .long SYMBOL_NAME(sys_add_key) + .long SYMBOL_NAME(sys_ni_syscall) /* sys_kexec_load */ + .long SYMBOL_NAME(sys_add_key) /* 285 */ .long SYMBOL_NAME(sys_request_key) .long SYMBOL_NAME(sys_keyctl) - - .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 - .long SYMBOL_NAME(sys_ni_syscall) - .endr + .long SYMBOL_NAME(sys_ioprio_set) + .long SYMBOL_NAME(sys_ioprio_get) /* 290 */ + .long SYMBOL_NAME(sys_inotify_init) + .long SYMBOL_NAME(sys_inotify_add_watch) + .long SYMBOL_NAME(sys_inotify_rm_watch) + .long SYMBOL_NAME(sys_migrate_pages) + .long SYMBOL_NAME(sys_openat) /* 295 */ + .long SYMBOL_NAME(sys_mkdirat) + .long SYMBOL_NAME(sys_mknodat) + .long SYMBOL_NAME(sys_fchownat) + .long SYMBOL_NAME(sys_futimesat) + .long SYMBOL_NAME(sys_fstatat64) /* 300 */ + .long SYMBOL_NAME(sys_unlinkat) + .long SYMBOL_NAME(sys_renameat) + .long SYMBOL_NAME(sys_linkat) + .long SYMBOL_NAME(sys_symlinkat) + .long SYMBOL_NAME(sys_readlinkat) /* 305 */ + .long SYMBOL_NAME(sys_fchmodat) + .long SYMBOL_NAME(sys_faccessat) + .long SYMBOL_NAME(sys_ni_syscall) /* sys_pselect6 */ + .long SYMBOL_NAME(sys_ni_syscall) /* sys_ppoll */ + .long SYMBOL_NAME(sys_unshare) /* 310 */ + .long SYMBOL_NAME(sys_set_robust_list) + .long SYMBOL_NAME(sys_get_robust_list) + .long SYMBOL_NAME(sys_splice) + .long SYMBOL_NAME(sys_sync_file_range) + .long SYMBOL_NAME(sys_tee) /* 315 */ + .long SYMBOL_NAME(sys_vmsplice) + .long SYMBOL_NAME(sys_ni_syscall) /* sys_move_pages */ + .long SYMBOL_NAME(sys_getcpu) + .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_pwait */ .macro call_sp addr mov.l #SYMBOL_NAME(\addr),er6 diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 30944ee2e61a..c2d54b802232 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -55,6 +55,10 @@ config ZONE_DMA bool default y +config QUICKLIST + bool + default y + config SBUS bool @@ -79,10 +83,6 @@ config ARCH_MAY_HAVE_PC_FDC bool default y -config ARCH_USES_SLAB_PAGE_STRUCT - bool - default y - config DMI bool default y diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index d76d9bc33b30..06dfa65ad180 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -186,6 +186,7 @@ void cpu_idle(void) if (__get_cpu_var(cpu_idle_state)) __get_cpu_var(cpu_idle_state) = 0; + check_pgt_cache(); rmb(); idle = pm_idle; diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 93f202a855fa..706bda72dc60 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -421,7 +421,7 @@ void flush_tlb_mm (struct mm_struct * mm) } if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL); - + check_pgt_cache(); preempt_enable(); } diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 0772678ceecf..bf6adce52267 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -320,3 +320,6 @@ ENTRY(sys_call_table) .long sys_getcpu .long sys_epoll_pwait .long sys_utimensat /* 320 */ + .long sys_signalfd + .long sys_timerfd + .long sys_eventfd diff --git a/arch/i386/kernel/verify_cpu.S b/arch/i386/kernel/verify_cpu.S index e51a8695d54e..b2a9d80b6421 100644 --- a/arch/i386/kernel/verify_cpu.S +++ b/arch/i386/kernel/verify_cpu.S @@ -10,7 +10,9 @@ verify_cpu: #if CONFIG_X86_MINIMUM_CPU_MODEL >= 4 pushfl - orl $(1<<18),(%esp) # try setting AC + pop %eax + orl $(1<<18),%eax # try setting AC + push %eax popfl pushfl popl %eax diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index c50782efa5c3..b22ce8d6b1ba 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -740,7 +740,6 @@ int remove_memory(u64 start, u64 size) EXPORT_SYMBOL_GPL(remove_memory); #endif -struct kmem_cache *pgd_cache; struct kmem_cache *pmd_cache; void __init pgtable_cache_init(void) @@ -764,12 +763,6 @@ void __init pgtable_cache_init(void) pgd_size = PAGE_SIZE; } } - pgd_cache = kmem_cache_create("pgd", - pgd_size, - pgd_size, - SLAB_PANIC, - pgd_ctor, - (!SHARED_KERNEL_PMD) ? pgd_dtor : NULL); } /* diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c index 9a96c1647428..8d7c0864cc04 100644 --- a/arch/i386/mm/pgtable.c +++ b/arch/i386/mm/pgtable.c @@ -13,6 +13,7 @@ #include <linux/pagemap.h> #include <linux/spinlock.h> #include <linux/module.h> +#include <linux/quicklist.h> #include <asm/system.h> #include <asm/pgtable.h> @@ -205,8 +206,6 @@ void pmd_ctor(void *pmd, struct kmem_cache *cache, unsigned long flags) * against pageattr.c; it is the unique case in which a valid change * of kernel pagetables can't be lazily synchronized by vmalloc faults. * vmalloc faults work because attached pagetables are never freed. - * The locking scheme was chosen on the basis of manfred's - * recommendations and having no core impact whatsoever. * -- wli */ DEFINE_SPINLOCK(pgd_lock); @@ -232,9 +231,11 @@ static inline void pgd_list_del(pgd_t *pgd) set_page_private(next, (unsigned long)pprev); } + + #if (PTRS_PER_PMD == 1) /* Non-PAE pgd constructor */ -void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) +void pgd_ctor(void *pgd) { unsigned long flags; @@ -256,7 +257,7 @@ void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) } #else /* PTRS_PER_PMD > 1 */ /* PAE pgd constructor */ -void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) +void pgd_ctor(void *pgd) { /* PAE, kernel PMD may be shared */ @@ -275,11 +276,12 @@ void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) } #endif /* PTRS_PER_PMD */ -void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused) +void pgd_dtor(void *pgd) { unsigned long flags; /* can be called from interrupt context */ - BUG_ON(SHARED_KERNEL_PMD); + if (SHARED_KERNEL_PMD) + return; paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT); spin_lock_irqsave(&pgd_lock, flags); @@ -321,7 +323,7 @@ static void pmd_cache_free(pmd_t *pmd, int idx) pgd_t *pgd_alloc(struct mm_struct *mm) { int i; - pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL); + pgd_t *pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor); if (PTRS_PER_PMD == 1 || !pgd) return pgd; @@ -344,7 +346,7 @@ out_oom: paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT); pmd_cache_free(pmd, i); } - kmem_cache_free(pgd_cache, pgd); + quicklist_free(0, pgd_dtor, pgd); return NULL; } @@ -361,5 +363,11 @@ void pgd_free(pgd_t *pgd) pmd_cache_free(pmd, i); } /* in the non-PAE case, free_pgtables() clears user pgd entries */ - kmem_cache_free(pgd_cache, pgd); + quicklist_free(0, pgd_dtor, pgd); } + +void check_pgt_cache(void) +{ + quicklist_trim(0, pgd_dtor, 25, 16); +} + diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 6e41471449c0..de1bff659969 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -31,6 +31,10 @@ config ZONE_DMA def_bool y depends on !IA64_SGI_SN2 +config QUICKLIST + bool + default y + config MMU bool default y diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c index 2153bcacbe6c..94e57109fad6 100644 --- a/arch/ia64/hp/common/hwsw_iommu.c +++ b/arch/ia64/hp/common/hwsw_iommu.c @@ -63,7 +63,7 @@ use_swiotlb (struct device *dev) return dev && dev->dma_mask && !hwiommu_dma_supported(dev, *dev->dma_mask); } -void +void __init hwsw_init (void) { /* default to a smallish 2MB sw I/O TLB */ diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c index 92d7d0c8d93f..8850fe40ea34 100644 --- a/arch/ia64/ia32/audit.c +++ b/arch/ia64/ia32/audit.c @@ -20,6 +20,11 @@ unsigned ia32_read_class[] = { ~0U }; +unsigned ia32_signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + int ia32_classify_syscall(unsigned syscall) { switch(syscall) { diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c index 04682555a28c..f3802ae89b10 100644 --- a/arch/ia64/kernel/audit.c +++ b/arch/ia64/kernel/audit.c @@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ~0U }; +static unsigned signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + +int audit_classify_arch(int arch) +{ +#ifdef CONFIG_IA32_SUPPORT + if (arch == AUDIT_ARCH_I386) + return 1; +#endif + return 0; +} + int audit_classify_syscall(int abi, unsigned syscall) { #ifdef CONFIG_IA32_SUPPORT @@ -49,15 +63,18 @@ static int __init audit_classes_init(void) extern __u32 ia32_write_class[]; extern __u32 ia32_read_class[]; extern __u32 ia32_chattr_class[]; + extern __u32 ia32_signal_class[]; audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class); audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class); #endif audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL, signal_class); return 0; } diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index b50bf208678e..144b056282af 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1583,5 +1583,7 @@ sys_call_table: data8 sys_vmsplice data8 sys_ni_syscall // reserved for move_pages data8 sys_getcpu + data8 sys_epoll_pwait // 1305 + data8 sys_utimensat .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c index 6a49600cf337..b642648cc2ac 100644 --- a/arch/ia64/kernel/err_inject.c +++ b/arch/ia64/kernel/err_inject.c @@ -291,5 +291,5 @@ module_init(err_inject_init); module_exit(err_inject_exit); MODULE_AUTHOR("Fenghua Yu <fenghua.yu@intel.com>"); -MODULE_DESCRIPTION("MC error injection kenrel sysfs interface"); +MODULE_DESCRIPTION("MC error injection kernel sysfs interface"); MODULE_LICENSE("GPL"); diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index ce49c85c928f..b4c239685d2e 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -104,6 +104,17 @@ void set_irq_affinity_info (unsigned int irq, int hwid, int redir) irq_redir[irq] = (char) (redir & 0xff); } } + +bool is_affinity_mask_valid(cpumask_t cpumask) +{ + if (ia64_platform_is("sn2")) { + /* Only allow one CPU to be specified in the smp_affinity mask */ + if (cpus_weight(cpumask) != 1) + return false; + } + return true; +} + #endif /* CONFIG_SMP */ #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 4f5fd0960ba7..72e593e94053 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -370,14 +370,18 @@ static int __kprobes valid_kprobe_addr(int template, int slot, static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) { - kcb->prev_kprobe.kp = kprobe_running(); - kcb->prev_kprobe.status = kcb->kprobe_status; + unsigned int i; + i = atomic_add_return(1, &kcb->prev_kprobe_index); + kcb->prev_kprobe[i-1].kp = kprobe_running(); + kcb->prev_kprobe[i-1].status = kcb->kprobe_status; } static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; - kcb->kprobe_status = kcb->prev_kprobe.status; + unsigned int i; + i = atomic_sub_return(1, &kcb->prev_kprobe_index); + __get_cpu_var(current_kprobe) = kcb->prev_kprobe[i].kp; + kcb->kprobe_status = kcb->prev_kprobe[i].status; } static void __kprobes set_current_kprobe(struct kprobe *p, diff --git a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c index 9620822270a6..13df337508e7 100644 --- a/arch/ia64/kernel/machvec.c +++ b/arch/ia64/kernel/machvec.c @@ -35,7 +35,7 @@ lookup_machvec (const char *name) return 0; } -void +void __init machvec_init (const char *name) { struct ia64_machine_vector *mv; diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index f8ae709de0b5..26814de6c29a 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -118,7 +118,9 @@ static ia64_mc_info_t ia64_mc_info; #define CPE_HISTORY_LENGTH 5 #define CMC_HISTORY_LENGTH 5 +#ifdef CONFIG_ACPI static struct timer_list cpe_poll_timer; +#endif static struct timer_list cmc_poll_timer; /* * This variable tells whether we are currently in polling mode. diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 44ce5ed9444c..7ac8592a35b6 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -88,7 +88,7 @@ void show_mem(void) printk(KERN_INFO "%d pages shared\n", total_shared); printk(KERN_INFO "%d pages swap cached\n", total_cached); printk(KERN_INFO "Total of %ld pages in page table cache\n", - pgtable_quicklist_total_size()); + quicklist_total_size()); printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages()); } diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 94844442812a..38085ac18338 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -561,7 +561,7 @@ void show_mem(void) printk(KERN_INFO "%d pages shared\n", total_shared); printk(KERN_INFO "%d pages swap cached\n", total_cached); printk(KERN_INFO "Total of %ld pages in page table cache\n", - pgtable_quicklist_total_size()); + quicklist_total_size()); printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages()); } diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index cffb1e8325e8..c14abefabafa 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -39,9 +39,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); -DEFINE_PER_CPU(unsigned long *, __pgtable_quicklist); -DEFINE_PER_CPU(long, __pgtable_quicklist_size); - extern void ia64_tlb_init (void); unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL; @@ -56,54 +53,6 @@ EXPORT_SYMBOL(vmem_map); struct page *zero_page_memmap_ptr; /* map entry for zero page */ EXPORT_SYMBOL(zero_page_memmap_ptr); -#define MIN_PGT_PAGES 25UL -#define MAX_PGT_FREES_PER_PASS 16L -#define PGT_FRACTION_OF_NODE_MEM 16 - -static inline long -max_pgt_pages(void) -{ - u64 node_free_pages, max_pgt_pages; - -#ifndef CONFIG_NUMA - node_free_pages = nr_free_pages(); -#else - node_free_pages = node_page_state(numa_node_id(), NR_FREE_PAGES); -#endif - max_pgt_pages = node_free_pages / PGT_FRACTION_OF_NODE_MEM; - max_pgt_pages = max(max_pgt_pages, MIN_PGT_PAGES); - return max_pgt_pages; -} - -static inline long -min_pages_to_free(void) -{ - long pages_to_free; - - pages_to_free = pgtable_quicklist_size - max_pgt_pages(); - pages_to_free = min(pages_to_free, MAX_PGT_FREES_PER_PASS); - return pages_to_free; -} - -void -check_pgt_cache(void) -{ - long pages_to_free; - - if (unlikely(pgtable_quicklist_size <= MIN_PGT_PAGES)) - return; - - preempt_disable(); - while (unlikely((pages_to_free = min_pages_to_free()) > 0)) { - while (pages_to_free--) { - free_page((unsigned long)pgtable_quicklist_alloc()); - } - preempt_enable(); - preempt_disable(); - } - preempt_enable(); -} - void lazy_mmu_prot_update (pte_t pte) { diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c index d48bcd83253c..7ed72d3faf73 100644 --- a/arch/ia64/sn/kernel/io_common.c +++ b/arch/ia64/sn/kernel/io_common.c @@ -364,7 +364,7 @@ void sn_bus_store_sysdata(struct pci_dev *dev) element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL); if (!element) { - dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__); + dev_dbg(&dev->dev, "%s: out of memory!\n", __FUNCTION__); return; } element->sysdata = SN_PCIDEV_INFO(dev); diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index 57c723f5cba4..7ba403232cb8 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.c @@ -574,7 +574,7 @@ xpc_update_partition_info(struct xpc_partition *part, u8 remote_rp_version, u64 remote_vars_pa, struct xpc_vars *remote_vars) { part->remote_rp_version = remote_rp_version; - dev_dbg(xpc_part, " remote_rp_version = 0x%016lx\n", + dev_dbg(xpc_part, " remote_rp_version = 0x%016x\n", part->remote_rp_version); part->remote_rp_stamp = *remote_rp_stamp; diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c index 88fad85ceeff..da7213530972 100644 --- a/arch/ia64/sn/kernel/xpnet.c +++ b/arch/ia64/sn/kernel/xpnet.c @@ -343,8 +343,8 @@ xpnet_dev_open(struct net_device *dev) enum xpc_retval ret; - dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %d, " - "%d)\n", XPC_NET_CHANNEL, xpnet_connection_activity, + dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %ld, " + "%ld)\n", XPC_NET_CHANNEL, xpnet_connection_activity, XPNET_MSG_SIZE, XPNET_MSG_NENTRIES, XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS); diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index 9740d6b8ae11..c3bb8a755b00 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -241,6 +241,10 @@ config GENERIC_CALIBRATE_DELAY bool default y +config SCHED_NO_NO_OMIT_FRAME_POINTER + bool + default y + config PREEMPT bool "Preemptible Kernel" help diff --git a/arch/m32r/mm/mmu.S b/arch/m32r/mm/mmu.S index 8bb74b10dca7..49a6d16a3d58 100644 --- a/arch/m32r/mm/mmu.S +++ b/arch/m32r/mm/mmu.S @@ -163,7 +163,8 @@ ENTRY(tme_handler) ; pte_data = (unsigned long)pte_val(*pte); ld r2, @r3 ; r2: pte data - or3 r2, r2, #2 ; _PAGE_PRESENT(=2) + and3 r3, r2, #2 ; _PAGE_PRESENT(=2) check + beqz r3, 3f .fillinsn 5: @@ -264,11 +265,8 @@ ENTRY(tme_handler) ; and3 r1, r1, #0xeff ldi r4, #611 ; _KERNPG_TABLE(=611) - beq r1, r4, 4f ; !pmd_bad(*pmd) ? - .fillinsn -3: - ldi r1, #0 ; r1: pte_data = 0 - bra 5f + bne r1, r4, 3f ; !pmd_bad(*pmd) ? + .fillinsn 4: ; pte = pte_offset(pmd, address); @@ -282,8 +280,10 @@ ENTRY(tme_handler) add r4, r3 ; r4: pte ; pte_data = (unsigned long)pte_val(*pte); ld r1, @r4 ; r1: pte_data - .fillinsn + and3 r3, r1, #2 ; _PAGE_PRESENT(=2) check + beqz r3, 3f + .fillinsn ;; set tlb ; r0: address, r1: pte_data, r2: entry ; r3,r4: (free) @@ -295,8 +295,7 @@ ENTRY(tme_handler) and3 r4, r4, #(MMU_CONTEXT_ASID_MASK) or r3, r4 st r3, @r2 - or3 r4, r1, #2 ; _PAGE_PRESENT(=2) - st r4, @(4,r2) ; set_tlb_data(entry, pte_data); + st r1, @(4,r2) ; set_tlb_data(entry, pte_data); ld r4, @sp+ ld r3, @sp+ @@ -306,6 +305,11 @@ ENTRY(tme_handler) ld sp, @sp+ rte + .fillinsn +3: + ldi r1, #2 ; r1: pte_data = 0 | _PAGE_PRESENT(=2) + bra 5b + #else #error unknown isa configuration #endif diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 16ecea3c0813..0f09412e1b7f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -15,121 +15,8 @@ choice prompt "System type" default SGI_IP22 -config MIPS_MTX1 - bool "4G Systems MTX-1 board" - select DMA_NONCOHERENT - select HW_HAS_PCI - select RESOURCES_64BIT if PCI - select SOC_AU1500 - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_BOSPORUS - bool "AMD Alchemy Bosporus board" - select SOC_AU1500 - select DMA_NONCOHERENT - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1000 - bool "AMD Alchemy PB1000 board" - select SOC_AU1000 - select DMA_NONCOHERENT - select HW_HAS_PCI - select RESOURCES_64BIT if PCI - select SWAP_IO_SPACE - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1100 - bool "AMD Alchemy PB1100 board" - select SOC_AU1100 - select DMA_NONCOHERENT - select HW_HAS_PCI - select RESOURCES_64BIT if PCI - select SWAP_IO_SPACE - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1500 - bool "AMD Alchemy PB1500 board" - select SOC_AU1500 - select DMA_NONCOHERENT - select HW_HAS_PCI - select RESOURCES_64BIT if PCI - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1550 - bool "AMD Alchemy PB1550 board" - select SOC_AU1550 - select DMA_NONCOHERENT - select HW_HAS_PCI - select MIPS_DISABLE_OBSOLETE_IDE - select RESOURCES_64BIT if PCI - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_PB1200 - bool "AMD Alchemy PB1200 board" - select SOC_AU1200 - select DMA_NONCOHERENT - select MIPS_DISABLE_OBSOLETE_IDE - select RESOURCES_64BIT if PCI - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1000 - bool "AMD Alchemy DB1000 board" - select SOC_AU1000 - select DMA_NONCOHERENT - select HW_HAS_PCI - select RESOURCES_64BIT if PCI - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1100 - bool "AMD Alchemy DB1100 board" - select SOC_AU1100 - select DMA_NONCOHERENT - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1500 - bool "AMD Alchemy DB1500 board" - select SOC_AU1500 - select DMA_NONCOHERENT - select HW_HAS_PCI - select MIPS_DISABLE_OBSOLETE_IDE - select RESOURCES_64BIT if PCI - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1550 - bool "AMD Alchemy DB1550 board" - select SOC_AU1550 - select HW_HAS_PCI - select DMA_NONCOHERENT - select MIPS_DISABLE_OBSOLETE_IDE - select RESOURCES_64BIT if PCI - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_DB1200 - bool "AMD Alchemy DB1200 board" - select SOC_AU1200 - select DMA_COHERENT - select MIPS_DISABLE_OBSOLETE_IDE - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN - -config MIPS_MIRAGE - bool "AMD Alchemy Mirage board" - select DMA_NONCOHERENT - select SOC_AU1500 - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_LITTLE_ENDIAN +config MACH_ALCHEMY + bool "Alchemy processor based machines" config BASLER_EXCITE bool "Basler eXcite smart camera" @@ -369,28 +256,6 @@ config MIPS_SIM This option enables support for MIPS Technologies MIPSsim software emulator. -config MOMENCO_JAGUAR_ATX - bool "Momentum Jaguar board" - select BOOT_ELF32 - select DMA_NONCOHERENT - select HW_HAS_PCI - select IRQ_CPU - select IRQ_CPU_RM7K - select IRQ_MV64340 - select LIMITED_DMA - select PCI_MARVELL - select RM7000_CPU_SCACHE - select SWAP_IO_SPACE - select SYS_HAS_CPU_RM9000 - select SYS_HAS_EARLY_PRINTK - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_SUPPORTS_KGDB - help - The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by - Momentum Computer <http://www.momenco.com/>. - config MOMENCO_OCELOT bool "Momentum Ocelot board" select DMA_NONCOHERENT @@ -446,29 +311,6 @@ config MOMENCO_OCELOT_C The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer <http://www.momenco.com/>. -config MOMENCO_OCELOT_G - bool "Momentum Ocelot-G board" - select DMA_NONCOHERENT - select HW_HAS_PCI - select IRQ_CPU - select IRQ_CPU_RM7K - select PCI_MARVELL - select RM7000_CPU_SCACHE - select SWAP_IO_SPACE - select SYS_HAS_CPU_RM7000 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL if BROKEN - select SYS_SUPPORTS_BIG_ENDIAN - help - The Ocelot is a MIPS-based Single Board Computer (SBC) made by - Momentum Computer <http://www.momenco.com/>. - -config MIPS_XXS1500 - bool "MyCable XXS1500 board" - select DMA_NONCOHERENT - select SOC_AU1500 - select SYS_SUPPORTS_LITTLE_ENDIAN - config PNX8550_JBS bool "Philips PNX8550 based JBS board" select PNX8550 @@ -775,7 +617,6 @@ config TOSHIBA_JMR3927 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_BIG_ENDIAN - select TOSHIBA_BOARDS select GENERIC_HARDIRQS_NO__DO_IRQ config TOSHIBA_RBTX4927 @@ -791,7 +632,6 @@ config TOSHIBA_RBTX4927 select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_KGDB - select TOSHIBA_BOARDS select GENERIC_HARDIRQS_NO__DO_IRQ help This Toshiba board is based on the TX4927 processor. Say Y here to @@ -811,7 +651,6 @@ config TOSHIBA_RBTX4938 select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_KGDB - select TOSHIBA_BOARDS select GENERIC_HARDIRQS_NO__DO_IRQ help This Toshiba board is based on the TX4938 processor. Say Y here to @@ -819,11 +658,11 @@ config TOSHIBA_RBTX4938 endchoice +source "arch/mips/au1000/Kconfig" source "arch/mips/ddb5xxx/Kconfig" source "arch/mips/gt64120/ev64120/Kconfig" source "arch/mips/jazz/Kconfig" source "arch/mips/lasat/Kconfig" -source "arch/mips/momentum/Kconfig" source "arch/mips/pmc-sierra/Kconfig" source "arch/mips/sgi-ip27/Kconfig" source "arch/mips/sibyte/Kconfig" @@ -923,11 +762,6 @@ config GENERIC_ISA_DMA config I8259 bool -config LIMITED_DMA - bool - select HIGHMEM - select SYS_SUPPORTS_HIGHMEM - config MIPS_BONITO64 bool @@ -1013,33 +847,6 @@ config MIPS_RM9122 config PCI_MARVELL bool -config SOC_AU1000 - bool - select SOC_AU1X00 - -config SOC_AU1100 - bool - select SOC_AU1X00 - -config SOC_AU1500 - bool - select SOC_AU1X00 - -config SOC_AU1550 - bool - select SOC_AU1X00 - -config SOC_AU1200 - bool - select SOC_AU1X00 - -config SOC_AU1X00 - bool - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_APM_EMULATION - select SYS_SUPPORTS_KGDB - config SERIAL_RM9000 bool @@ -1081,9 +888,9 @@ config WDT_RM9000 choice prompt "Galileo Chip Clock" #default SYSCLK_83 if MIPS_EV64120 - depends on MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G + depends on MIPS_EV64120 || MOMENCO_OCELOT default SYSCLK_83 if MIPS_EV64120 - default SYSCLK_100 if MOMENCO_OCELOT || MOMENCO_OCELOT_G + default SYSCLK_100 if MOMENCO_OCELOT config SYSCLK_75 bool "75" if MIPS_EV64120 @@ -1092,7 +899,7 @@ config SYSCLK_83 bool "83.3" if MIPS_EV64120 config SYSCLK_100 - bool "100" if MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G + bool "100" if MIPS_EV64120 || MOMENCO_OCELOT endchoice @@ -1131,9 +938,6 @@ config ARC64 config BOOT_ELF64 bool -config TOSHIBA_BOARDS - bool - menu "CPU selection" choice @@ -1557,6 +1361,7 @@ config MIPS_MT_SMP bool "Use 1 TC on each available VPE for SMP" depends on SYS_SUPPORTS_MULTITHREADING select CPU_MIPSR2_IRQ_VI + select CPU_MIPSR2_IRQ_EI select CPU_MIPSR2_SRS select MIPS_MT select NR_CPUS_DEFAULT_2 @@ -1572,6 +1377,7 @@ config MIPS_MT_SMTC #depends on CPU_MIPS64_R2 # once there is hardware ... depends on SYS_SUPPORTS_MULTITHREADING select CPU_MIPSR2_IRQ_VI + select CPU_MIPSR2_IRQ_EI select CPU_MIPSR2_SRS select MIPS_MT select NR_CPUS_DEFAULT_8 @@ -1584,6 +1390,8 @@ config MIPS_MT_SMTC config MIPS_VPE_LOADER bool "VPE loader support." depends on SYS_SUPPORTS_MULTITHREADING + select CPU_MIPSR2_IRQ_VI + select CPU_MIPSR2_IRQ_EI select MIPS_MT help Includes a loader for loading an elf relocatable object diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 4892db88a86a..f450066b6241 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -343,15 +343,6 @@ cflags-$(CONFIG_MOMENCO_OCELOT) += -Iinclude/asm-mips/mach-ocelot load-$(CONFIG_MOMENCO_OCELOT) += 0xffffffff80100000 # -# Momentum Ocelot-G board -# -# The Ocelot-G setup.o must be linked early - it does the ioremap() for the -# mips_io_port_base. -# -core-$(CONFIG_MOMENCO_OCELOT_G) += arch/mips/momentum/ocelot_g/ -load-$(CONFIG_MOMENCO_OCELOT_G) += 0xffffffff80100000 - -# # Momentum Ocelot-C and -CS boards # # The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the @@ -388,17 +379,6 @@ cflags-$(CONFIG_BASLER_EXCITE) += -Iinclude/asm-mips/mach-excite load-$(CONFIG_BASLER_EXCITE) += 0x80100000 # -# Momentum Jaguar ATX -# -core-$(CONFIG_MOMENCO_JAGUAR_ATX) += arch/mips/momentum/jaguar_atx/ -cflags-$(CONFIG_MOMENCO_JAGUAR_ATX) += -Iinclude/asm-mips/mach-ja -#ifdef CONFIG_JAGUAR_DMALOW -#load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0xffffffff88000000 -#else -load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0xffffffff80100000 -#endif - -# # NEC DDB # core-$(CONFIG_DDB5XXX_COMMON) += arch/mips/ddb5xxx/common/ @@ -729,3 +709,25 @@ archclean: CLEAN_FILES += vmlinux.32 \ vmlinux.64 \ vmlinux.ecoff + +quiet_cmd_syscalls_n32 = CALL-N32 $< + cmd_syscalls_n32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=n32 + +quiet_cmd_syscalls_o32 = CALL-O32 $< + cmd_syscalls_o32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=32 + +PHONY += missing-syscalls-n32 missing-syscalls-o32 + +missing-syscalls-n32: scripts/checksyscalls.sh FORCE + $(call cmd,syscalls_n32) + +missing-syscalls-o32: scripts/checksyscalls.sh FORCE + $(call cmd,syscalls_o32) + +archprepare: +ifdef CONFIG_MIPS32_N32 + $(Q)$(MAKE) $(build)=arch/mips missing-syscalls-n32 +endif +ifdef CONFIG_MIPS32_O32 + $(Q)$(MAKE) $(build)=arch/mips missing-syscalls-o32 +endif diff --git a/arch/mips/au1000/Kconfig b/arch/mips/au1000/Kconfig new file mode 100644 index 000000000000..abea88098253 --- /dev/null +++ b/arch/mips/au1000/Kconfig @@ -0,0 +1,142 @@ +choice + prompt "Machine type" + depends on MACH_ALCHEMY + default MIPS_DB1000 + +config MIPS_MTX1 + bool "4G Systems MTX-1 board" + select DMA_NONCOHERENT + select HW_HAS_PCI + select RESOURCES_64BIT if PCI + select SOC_AU1500 + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_BOSPORUS + bool "Alchemy Bosporus board" + select SOC_AU1500 + select DMA_NONCOHERENT + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1000 + bool "Alchemy DB1000 board" + select SOC_AU1000 + select DMA_NONCOHERENT + select HW_HAS_PCI + select RESOURCES_64BIT if PCI + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1100 + bool "Alchemy DB1100 board" + select SOC_AU1100 + select DMA_NONCOHERENT + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1200 + bool "Alchemy DB1200 board" + select SOC_AU1200 + select DMA_COHERENT + select MIPS_DISABLE_OBSOLETE_IDE + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1500 + bool "Alchemy DB1500 board" + select SOC_AU1500 + select DMA_NONCOHERENT + select HW_HAS_PCI + select MIPS_DISABLE_OBSOLETE_IDE + select RESOURCES_64BIT if PCI + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_DB1550 + bool "Alchemy DB1550 board" + select SOC_AU1550 + select HW_HAS_PCI + select DMA_NONCOHERENT + select MIPS_DISABLE_OBSOLETE_IDE + select RESOURCES_64BIT if PCI + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_MIRAGE + bool "Alchemy Mirage board" + select DMA_NONCOHERENT + select SOC_AU1500 + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1000 + bool "Alchemy PB1000 board" + select SOC_AU1000 + select DMA_NONCOHERENT + select HW_HAS_PCI + select RESOURCES_64BIT if PCI + select SWAP_IO_SPACE + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1100 + bool "Alchemy PB1100 board" + select SOC_AU1100 + select DMA_NONCOHERENT + select HW_HAS_PCI + select RESOURCES_64BIT if PCI + select SWAP_IO_SPACE + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1200 + bool "Alchemy PB1200 board" + select SOC_AU1200 + select DMA_NONCOHERENT + select MIPS_DISABLE_OBSOLETE_IDE + select RESOURCES_64BIT if PCI + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1500 + bool "Alchemy PB1500 board" + select SOC_AU1500 + select DMA_NONCOHERENT + select HW_HAS_PCI + select RESOURCES_64BIT if PCI + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_PB1550 + bool "Alchemy PB1550 board" + select SOC_AU1550 + select DMA_NONCOHERENT + select HW_HAS_PCI + select MIPS_DISABLE_OBSOLETE_IDE + select RESOURCES_64BIT if PCI + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MIPS_XXS1500 + bool "MyCable XXS1500 board" + select DMA_NONCOHERENT + select SOC_AU1500 + select SYS_SUPPORTS_LITTLE_ENDIAN + +endchoice + +config SOC_AU1000 + bool + select SOC_AU1X00 + +config SOC_AU1100 + bool + select SOC_AU1X00 + +config SOC_AU1500 + bool + select SOC_AU1X00 + +config SOC_AU1550 + bool + select SOC_AU1X00 + +config SOC_AU1200 + bool + select SOC_AU1X00 + +config SOC_AU1X00 + bool + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_APM_EMULATION + select SYS_SUPPORTS_KGDB diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c index cc1ce77eab4a..e00bc2d7f301 100644 --- a/arch/mips/basler/excite/excite_device.c +++ b/arch/mips/basler/excite/excite_device.c @@ -68,7 +68,7 @@ enum { static struct resource - excite_ctr_resource __attribute__((unused)) = { + excite_ctr_resource __maybe_unused = { .name = "GPI counters", .start = 0, .end = 5, @@ -77,7 +77,7 @@ static struct resource .sibling = NULL, .child = NULL }, - excite_gpislice_resource __attribute__((unused)) = { + excite_gpislice_resource __maybe_unused = { .name = "GPI slices", .start = 0, .end = 1, @@ -86,7 +86,7 @@ static struct resource .sibling = NULL, .child = NULL }, - excite_mdio_channel_resource __attribute__((unused)) = { + excite_mdio_channel_resource __maybe_unused = { .name = "MDIO channels", .start = 0, .end = 1, @@ -95,7 +95,7 @@ static struct resource .sibling = NULL, .child = NULL }, - excite_fifomem_resource __attribute__((unused)) = { + excite_fifomem_resource __maybe_unused = { .name = "FIFO memory", .start = 0, .end = 767, @@ -104,7 +104,7 @@ static struct resource .sibling = NULL, .child = NULL }, - excite_scram_resource __attribute__((unused)) = { + excite_scram_resource __maybe_unused = { .name = "Scratch RAM", .start = EXCITE_PHYS_SCRAM, .end = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1, @@ -113,7 +113,7 @@ static struct resource .sibling = NULL, .child = NULL }, - excite_fpga_resource __attribute__((unused)) = { + excite_fpga_resource __maybe_unused = { .name = "System FPGA", .start = EXCITE_PHYS_FPGA, .end = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1, @@ -122,7 +122,7 @@ static struct resource .sibling = NULL, .child = NULL }, - excite_nand_resource __attribute__((unused)) = { + excite_nand_resource __maybe_unused = { .name = "NAND flash control", .start = EXCITE_PHYS_NAND, .end = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1, @@ -131,7 +131,7 @@ static struct resource .sibling = NULL, .child = NULL }, - excite_titan_resource __attribute__((unused)) = { + excite_titan_resource __maybe_unused = { .name = "TITAN registers", .start = EXCITE_PHYS_TITAN, .end = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1, diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile index 9565b2104dcd..c292f80a8c74 100644 --- a/arch/mips/cobalt/Makefile +++ b/arch/mips/cobalt/Makefile @@ -2,7 +2,7 @@ # Makefile for the Cobalt micro systems family specific parts of the kernel # -obj-y := irq.o reset.o setup.o buttons.o +obj-y := buttons.o irq.o reset.o rtc.o serial.o setup.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_EARLY_PRINTK) += console.o diff --git a/arch/mips/cobalt/rtc.c b/arch/mips/cobalt/rtc.c new file mode 100644 index 000000000000..284daefc5c55 --- /dev/null +++ b/arch/mips/cobalt/rtc.c @@ -0,0 +1,63 @@ +/* + * Registration of Cobalt RTC platform device. + * + * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> + +static struct resource cobalt_rtc_resource[] __initdata = { + { + .start = 0x70, + .end = 0x77, + .flags = IORESOURCE_IO, + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_IRQ, + }, +}; + +static __init int cobalt_rtc_add(void) +{ + struct platform_device *pdev; + int retval; + + pdev = platform_device_alloc("rtc_cmos", -1); + if (!pdev) + return -ENOMEM; + + retval = platform_device_add_resources(pdev, cobalt_rtc_resource, + ARRAY_SIZE(cobalt_rtc_resource)); + if (retval) + goto err_free_device; + + retval = platform_device_add(pdev); + if (retval) + goto err_free_device; + + return 0; + +err_free_device: + platform_device_put(pdev); + + return retval; +} +device_initcall(cobalt_rtc_add); diff --git a/arch/mips/cobalt/serial.c b/arch/mips/cobalt/serial.c new file mode 100644 index 000000000000..c27116599a5f --- /dev/null +++ b/arch/mips/cobalt/serial.c @@ -0,0 +1,85 @@ +/* + * Registration of Cobalt UART platform device. + * + * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> + +#include <cobalt.h> + +static struct resource cobalt_uart_resource[] __initdata = { + { + .start = 0x1c800000, + .end = 0x1c800007, + .flags = IORESOURCE_MEM, + }, + { + .start = COBALT_SERIAL_IRQ, + .end = COBALT_SERIAL_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct plat_serial8250_port cobalt_serial8250_port[] = { + { + .irq = COBALT_SERIAL_IRQ, + .uartclk = 18432000, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .mapbase = 0x1c800000, + }, + {}, +}; + +static __init int cobalt_uart_add(void) +{ + struct platform_device *pdev; + int retval; + + /* + * Cobalt Qube1 and RAQ1 have no UART. + */ + if (cobalt_board_id <= COBALT_BRD_ID_RAQ1) + return 0; + + pdev = platform_device_alloc("serial8250", -1); + if (!pdev) + return -ENOMEM; + + pdev->id = PLAT8250_DEV_PLATFORM; + pdev->dev.platform_data = cobalt_serial8250_port; + + retval = platform_device_add_resources(pdev, cobalt_uart_resource, ARRAY_SIZE(cobalt_uart_resource)); + if (retval) + goto err_free_device; + + retval = platform_device_add(pdev); + if (retval) + goto err_free_device; + + return 0; + +err_free_device: + platform_device_put(pdev); + + return retval; +} +device_initcall(cobalt_uart_add); diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c index d0dd81790f74..7abe45e78425 100644 --- a/arch/mips/cobalt/setup.c +++ b/arch/mips/cobalt/setup.c @@ -10,11 +10,8 @@ * */ #include <linux/interrupt.h> -#include <linux/pci.h> #include <linux/init.h> #include <linux/pm.h> -#include <linux/serial.h> -#include <linux/serial_core.h> #include <asm/bootinfo.h> #include <asm/time.h> @@ -27,9 +24,6 @@ extern void cobalt_machine_restart(char *command); extern void cobalt_machine_halt(void); extern void cobalt_machine_power_off(void); -extern void cobalt_early_console(void); - -int cobalt_board_id; const char *get_system_type(void) { @@ -95,8 +89,6 @@ static struct resource cobalt_reserved_resources[] = { void __init plat_mem_setup(void) { - static struct uart_port uart; - unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0); int i; _machine_restart = cobalt_machine_restart; @@ -111,29 +103,6 @@ void __init plat_mem_setup(void) /* These resources have been reserved by VIA SuperI/O chip. */ for (i = 0; i < ARRAY_SIZE(cobalt_reserved_resources); i++) request_resource(&ioport_resource, cobalt_reserved_resources + i); - - /* Read the cobalt id register out of the PCI config space */ - PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3)); - cobalt_board_id = GT_READ(GT_PCI0_CFGDATA_OFS); - cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8); - cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id); - - printk("Cobalt board ID: %d\n", cobalt_board_id); - - if (cobalt_board_id > COBALT_BRD_ID_RAQ1) { -#ifdef CONFIG_SERIAL_8250 - uart.line = 0; - uart.type = PORT_UNKNOWN; - uart.uartclk = 18432000; - uart.irq = COBALT_SERIAL_IRQ; - uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | - UPF_SKIP_TEST; - uart.iotype = UPIO_MEM; - uart.mapbase = 0x1c800000; - - early_serial_setup(&uart); -#endif - } } /* diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig index ba593b510b76..631b2138ad68 100644 --- a/arch/mips/configs/cobalt_defconfig +++ b/arch/mips/configs/cobalt_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.20 -# Tue Feb 20 21:47:24 2007 +# Linux kernel version: 2.6.21-rc7 +# Wed Apr 18 14:25:45 2007 # CONFIG_MIPS=y @@ -62,7 +62,6 @@ CONFIG_MIPS_COBALT=y # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_TOSHIBA_RBTX4927 is not set # CONFIG_TOSHIBA_RBTX4938 is not set -CONFIG_EARLY_PRINTK=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set @@ -74,12 +73,14 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_DMA_NONCOHERENT=y CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_EARLY_PRINTK=y +CONFIG_SYS_HAS_EARLY_PRINTK=y CONFIG_I8259=y # CONFIG_CPU_BIG_ENDIAN is not set CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_IRQ_CPU=y -CONFIG_MIPS_GT64111=y +CONFIG_PCI_GT64XXX_PCI0=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # @@ -179,6 +180,7 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_IKCONFIG is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_RELAY=y +# CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_EMBEDDED=y @@ -477,7 +479,6 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set CONFIG_CDROM_PKTCDVD=y CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set @@ -518,7 +519,7 @@ CONFIG_BLK_DEV_IDEPCI=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set -# CONFIG_IDEDMA_PCI_AUTO is not set +# CONFIG_IDEDMA_ONLYDISK is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -546,7 +547,6 @@ CONFIG_BLK_DEV_TC86C001=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set -# CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set # @@ -779,7 +779,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -CONFIG_RTC=y +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set CONFIG_COBALT_LCD=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -815,6 +816,11 @@ CONFIG_COBALT_LCD=y # CONFIG_HWMON_VID is not set # +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -827,7 +833,7 @@ CONFIG_COBALT_LCD=y # # Graphics support # -# CONFIG_FIRMWARE_EDID is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # CONFIG_FB is not set # @@ -835,7 +841,6 @@ CONFIG_COBALT_LCD=y # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -894,7 +899,29 @@ CONFIG_USB_ARCH_HAS_EHCI=y # # Real Time Clock # -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_CMOS=y +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set # # DMA Engine support diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig index 0db6a8b37301..10f6af43753d 100644 --- a/arch/mips/configs/db1000_defconfig +++ b/arch/mips/configs/db1000_defconfig @@ -9,6 +9,7 @@ CONFIG_MIPS=y # Machine selection # CONFIG_ZONE_DMA=y +CONFIG_MACH_ALCHEMY=y # CONFIG_MIPS_MTX1 is not set # CONFIG_MIPS_BOSPORUS is not set # CONFIG_MIPS_PB1000 is not set diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig index 162add97c5ef..4b0862927748 100644 --- a/arch/mips/configs/db1100_defconfig +++ b/arch/mips/configs/db1100_defconfig @@ -9,6 +9,7 @@ CONFIG_MIPS=y # Machine selection # CONFIG_ZONE_DMA=y +CONFIG_MACH_ALCHEMY=y # CONFIG_MIPS_MTX1 is not set # CONFIG_MIPS_BOSPORUS is not set # CONFIG_MIPS_PB1000 is not set diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig index 82801ec43e6a..820659e810dc 100644 --- a/arch/mips/configs/db1200_defconfig +++ b/arch/mips/configs/db1200_defconfig @@ -9,6 +9,7 @@ CONFIG_MIPS=y # Machine selection # CONFIG_ZONE_DMA=y +CONFIG_MACH_ALCHEMY=y # CONFIG_MIPS_MTX1 is not set # CONFIG_MIPS_BOSPORUS is not set # CONFIG_MIPS_PB1000 is not set diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig index 545f23094e13..4050b9b91bcb 100644 --- a/arch/mips/configs/db1500_defconfig +++ b/arch/mips/configs/db1500_defconfig @@ -9,6 +9,7 @@ CONFIG_MIPS=y # Machine selection # CONFIG_ZONE_DMA=y +CONFIG_MACH_ALCHEMY=y # CONFIG_MIPS_MTX1 is not set # CONFIG_MIPS_BOSPORUS is not set # CONFIG_MIPS_PB1000 is not set diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig index 5bd3b4328e57..7b3519058ab8 100644 --- a/arch/mips/configs/db1550_defconfig +++ b/arch/mips/configs/db1550_defconfig @@ -9,6 +9,7 @@ CONFIG_MIPS=y # Machine selection # CONFIG_ZONE_DMA=y +CONFIG_MACH_ALCHEMY=y # CONFIG_MIPS_MTX1 is not set # CONFIG_MIPS_BOSPORUS is not set # CONFIG_MIPS_PB1000 is not set diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig deleted file mode 100644 index 083104daa2ca..000000000000 --- a/arch/mips/configs/jaguar-atx_defconfig +++ /dev/null @@ -1,897 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.20 -# Tue Feb 20 21:47:33 2007 -# -CONFIG_MIPS=y - -# -# Machine selection -# -CONFIG_ZONE_DMA=y -# CONFIG_MIPS_MTX1 is not set -# CONFIG_MIPS_BOSPORUS is not set -# CONFIG_MIPS_PB1000 is not set -# CONFIG_MIPS_PB1100 is not set -# CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_PB1550 is not set -# CONFIG_MIPS_PB1200 is not set -# CONFIG_MIPS_DB1000 is not set -# CONFIG_MIPS_DB1100 is not set -# CONFIG_MIPS_DB1500 is not set -# CONFIG_MIPS_DB1550 is not set -# CONFIG_MIPS_DB1200 is not set -# CONFIG_MIPS_MIRAGE is not set -# CONFIG_BASLER_EXCITE is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_MACH_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MACH_JAZZ is not set -# CONFIG_LASAT is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_WR_PPMC is not set -# CONFIG_MIPS_SIM is not set -CONFIG_MOMENCO_JAGUAR_ATX=y -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_3 is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MIPS_XXS1500 is not set -# CONFIG_PNX8550_JBS is not set -# CONFIG_PNX8550_STB810 is not set -# CONFIG_DDB5477 is not set -# CONFIG_MACH_VR41XX is not set -# CONFIG_PMC_YOSEMITE is not set -# CONFIG_QEMU is not set -# CONFIG_MARKEINS is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP27 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SIBYTE_BIGSUR is not set -# CONFIG_SIBYTE_SWARM is not set -# CONFIG_SIBYTE_SENTOSA is not set -# CONFIG_SIBYTE_RHONE is not set -# CONFIG_SIBYTE_CARMEL is not set -# CONFIG_SIBYTE_PTSWARM is not set -# CONFIG_SIBYTE_LITTLESUR is not set -# CONFIG_SIBYTE_CRHINE is not set -# CONFIG_SIBYTE_CRHONE is not set -# CONFIG_SNI_RM is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_TOSHIBA_RBTX4938 is not set -CONFIG_JAGUAR_DMALOW=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_TIME=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set -CONFIG_DMA_NONCOHERENT=y -CONFIG_DMA_NEED_PCI_MAP_STATE=y -CONFIG_LIMITED_DMA=y -CONFIG_CPU_BIG_ENDIAN=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_IRQ_CPU_RM7K=y -CONFIG_IRQ_MV64340=y -CONFIG_PCI_MARVELL=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_BOOT_ELF32=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 - -# -# CPU selection -# -# CONFIG_CPU_MIPS32_R1 is not set -# CONFIG_CPU_MIPS32_R2 is not set -# CONFIG_CPU_MIPS64_R1 is not set -# CONFIG_CPU_MIPS64_R2 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -CONFIG_CPU_RM9000=y -# CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_RM9000=y -CONFIG_WEAK_ORDERING=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y - -# -# Kernel type -# -CONFIG_32BIT=y -# CONFIG_64BIT is not set -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_BOARD_SCACHE=y -CONFIG_RM7000_CPU_SCACHE=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_MIPS_MT_DISABLED=y -# CONFIG_MIPS_MT_SMP is not set -# CONFIG_MIPS_MT_SMTC is not set -# CONFIG_MIPS_VPE_LOADER is not set -# CONFIG_64BIT_PHYS_ADDR is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_HIGHMEM=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_SYS_SUPPORTS_HIGHMEM=y -CONFIG_ARCH_FLATMEM_ENABLE=y -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -# CONFIG_HZ_48 is not set -# CONFIG_HZ_100 is not set -# CONFIG_HZ_128 is not set -# CONFIG_HZ_250 is not set -# CONFIG_HZ_256 is not set -CONFIG_HZ_1000=y -# CONFIG_HZ_1024 is not set -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_HZ=1000 -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# Code maturity level options -# -# CONFIG_EXPERIMENTAL is not set -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_IPC_NS is not set -CONFIG_SYSVIPC_SYSCTL=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set -# CONFIG_UTS_NS is not set -# CONFIG_AUDIT is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_SYSFS_DEPRECATED=y -CONFIG_RELAY=y -CONFIG_SYSCTL=y -CONFIG_EMBEDDED=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SHMEM=y -CONFIG_SLAB=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODVERSIONS is not set -CONFIG_MODULE_SRCVERSION_ALL=y -CONFIG_KMOD=y - -# -# Block layer -# -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_DEFAULT_AS=y -# CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_HW_HAS_PCI=y -CONFIG_PCI=y -CONFIG_MMU=y - -# -# PCCARD (PCMCIA/CardBus) support -# -# CONFIG_PCCARD is not set - -# -# PCI Hotplug Support -# - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Power management options -# -CONFIG_PM=y -# CONFIG_PM_LEGACY is not set -# CONFIG_PM_DEBUG is not set -# CONFIG_PM_SYSFS_DEPRECATED is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_NETDEBUG is not set -# CONFIG_PACKET is not set -CONFIG_UNIX=y -CONFIG_XFRM=y -CONFIG_XFRM_USER=m -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=m -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m -CONFIG_INET_XFRM_MODE_BEET=m -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_INET6_XFRM_TUNNEL=m -CONFIG_INET6_TUNNEL=m -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -CONFIG_IPV6_SIT=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETWORK_SECMARK=y -# CONFIG_NETFILTER is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_IEEE80211=m -# CONFIG_IEEE80211_DEBUG is not set -CONFIG_IEEE80211_CRYPT_WEP=m -CONFIG_IEEE80211_CRYPT_CCMP=m - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m -# CONFIG_SYS_HYPERVISOR is not set - -# -# Connector - unified userspace <-> kernelspace linker -# -CONFIG_CONNECTOR=m - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNPACPI is not set - -# -# Block devices -# -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_SX8 is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_CDROM_PKTCDVD=m -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -CONFIG_ATA_OVER_ETH=m - -# -# Misc devices -# -CONFIG_SGI_IOC4=m - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_RAID_ATTRS=m -# CONFIG_SCSI is not set -# CONFIG_SCSI_NETLINK is not set - -# -# Serial ATA (prod) and Parallel ATA (experimental) drivers -# -# CONFIG_ATA is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# PHY device support -# -CONFIG_PHYLIB=m - -# -# MII PHY device drivers -# -CONFIG_MARVELL_PHY=m -CONFIG_DAVICOM_PHY=m -CONFIG_QSEMI_PHY=m -CONFIG_LXT_PHY=m -CONFIG_CICADA_PHY=m -CONFIG_VITESSE_PHY=m -CONFIG_SMSC_PHY=m -# CONFIG_BROADCOM_PHY is not set -# CONFIG_FIXED_PHY is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_CASSINI is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_DM9000 is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_AMD8111_ETH is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_B44 is not set -# CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set -CONFIG_EEPRO100=y -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_8139TOO is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set -# CONFIG_VIA_VELOCITY is not set -# CONFIG_TIGON3 is not set -# CONFIG_BNX2 is not set -CONFIG_MV643XX_ETH=y -CONFIG_QLA3XXX=m - -# -# Ethernet (10000 Mbit) -# -# CONFIG_CHELSIO_T1 is not set -CONFIG_CHELSIO_T3=m -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set -# CONFIG_MYRI10GE is not set -CONFIG_NETXEN_NIC=m - -# -# Token Ring devices -# -# CONFIG_TR is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_FDDI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -# CONFIG_INPUT is not set - -# -# Hardware I/O ports -# -# CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Hardware Monitoring support -# -# CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# LED devices -# -# CONFIG_NEW_LEDS is not set - -# -# LED drivers -# - -# -# LED Triggers -# - -# -# InfiniBand support -# -# CONFIG_INFINIBAND is not set - -# -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) -# - -# -# Real Time Clock -# - -# -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices -# - -# -# Auxiliary Display support -# - -# -# Virtualization -# - -# -# File systems -# -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -CONFIG_FUSE_FS=m -CONFIG_GENERIC_ACL=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_HFSPLUS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# -# CONFIG_NLS is not set - -# -# Kernel hacking -# -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_MUST_CHECK=y -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set -# CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_KERNEL is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="" -CONFIG_SYS_SUPPORTS_KGDB=y - -# -# Security options -# -CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=m -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=m -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_WP512=m -CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_CBC=m -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_FCRYPT=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_TWOFISH_COMMON=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -CONFIG_CRYPTO_CAMELLIA=m -# CONFIG_CRYPTO_TEST is not set - -# -# Hardware crypto devices -# - -# -# Library routines -# -CONFIG_BITREVERSE=m -# CONFIG_CRC_CCITT is not set -CONFIG_CRC16=m -CONFIG_CRC32=m -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=m -CONFIG_ZLIB_DEFLATE=m -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig index 068e48ec7093..1b364cf69140 100644 --- a/arch/mips/configs/jmr3927_defconfig +++ b/arch/mips/configs/jmr3927_defconfig @@ -80,7 +80,6 @@ CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_MIPS_TX3927=y CONFIG_SWAP_IO_SPACE=y CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_TOSHIBA_BOARDS=y # # CPU selection diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig index 69678d99ae61..37d696c64541 100644 --- a/arch/mips/configs/pb1100_defconfig +++ b/arch/mips/configs/pb1100_defconfig @@ -9,6 +9,7 @@ CONFIG_MIPS=y # Machine selection # CONFIG_ZONE_DMA=y +CONFIG_MACH_ALCHEMY=y # CONFIG_MIPS_MTX1 is not set # CONFIG_MIPS_BOSPORUS is not set # CONFIG_MIPS_PB1000 is not set diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig index 070672799dac..b11f0e8b6059 100644 --- a/arch/mips/configs/pb1500_defconfig +++ b/arch/mips/configs/pb1500_defconfig @@ -9,6 +9,7 @@ CONFIG_MIPS=y # Machine selection # CONFIG_ZONE_DMA=y +CONFIG_MACH_ALCHEMY=y # CONFIG_MIPS_MTX1 is not set # CONFIG_MIPS_BOSPORUS is not set # CONFIG_MIPS_PB1000 is not set diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig index 354e49b7a5f1..2927f38f4907 100644 --- a/arch/mips/configs/pb1550_defconfig +++ b/arch/mips/configs/pb1550_defconfig @@ -9,6 +9,7 @@ CONFIG_MIPS=y # Machine selection # CONFIG_ZONE_DMA=y +CONFIG_MACH_ALCHEMY=y # CONFIG_MIPS_MTX1 is not set # CONFIG_MIPS_BOSPORUS is not set # CONFIG_MIPS_PB1000 is not set diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/rbhma4200_defconfig index 7078e6b3ea11..35d64260917e 100644 --- a/arch/mips/configs/ocelot_g_defconfig +++ b/arch/mips/configs/rbhma4200_defconfig @@ -1,14 +1,13 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.20 -# Tue Feb 20 21:47:36 2007 +# Linux kernel version: 2.6.21 +# Wed May 9 23:44:19 2007 # CONFIG_MIPS=y # # Machine selection # -CONFIG_ZONE_DMA=y # CONFIG_MIPS_MTX1 is not set # CONFIG_MIPS_BOSPORUS is not set # CONFIG_MIPS_PB1000 is not set @@ -33,11 +32,9 @@ CONFIG_ZONE_DMA=y # CONFIG_MIPS_SEAD is not set # CONFIG_WR_PPMC is not set # CONFIG_MIPS_SIM is not set -# CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_OCELOT_C is not set -CONFIG_MOMENCO_OCELOT_G=y # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_JBS is not set # CONFIG_PNX8550_STB810 is not set @@ -60,8 +57,9 @@ CONFIG_MOMENCO_OCELOT_G=y # CONFIG_SIBYTE_CRHONE is not set # CONFIG_SNI_RM is not set # CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_TOSHIBA_RBTX4927=y # CONFIG_TOSHIBA_RBTX4938 is not set +# CONFIG_TOSHIBA_FPCIB0 is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set @@ -70,19 +68,15 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_TIME=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_DMA_NONCOHERENT=y CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_I8259=y CONFIG_CPU_BIG_ENDIAN=y # CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_IRQ_CPU_RM7K=y -CONFIG_PCI_MARVELL=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SWAP_IO_SPACE=y -# CONFIG_SYSCLK_75 is not set -# CONFIG_SYSCLK_83 is not set -CONFIG_SYSCLK_100=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # @@ -97,18 +91,19 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_TX49XX=y # CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set # CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set # CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set -CONFIG_CPU_RM7000=y +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_RM9000 is not set # CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_RM7000=y +CONFIG_SYS_HAS_CPU_TX49XX=y CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y @@ -121,19 +116,15 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set # CONFIG_PAGE_SIZE_64KB is not set -CONFIG_BOARD_SCACHE=y -CONFIG_RM7000_CPU_SCACHE=y CONFIG_CPU_HAS_PREFETCH=y CONFIG_MIPS_MT_DISABLED=y # CONFIG_MIPS_MT_SMP is not set # CONFIG_MIPS_MT_SMTC is not set # CONFIG_MIPS_VPE_LOADER is not set -# CONFIG_64BIT_PHYS_ADDR is not set CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -143,17 +134,17 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_RESOURCES_64BIT=y -CONFIG_ZONE_DMA_FLAG=1 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 # CONFIG_HZ_48 is not set # CONFIG_HZ_100 is not set # CONFIG_HZ_128 is not set -# CONFIG_HZ_250 is not set +CONFIG_HZ_250=y # CONFIG_HZ_256 is not set -CONFIG_HZ_1000=y +# CONFIG_HZ_1000 is not set # CONFIG_HZ_1024 is not set CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_HZ=1000 +CONFIG_HZ=250 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set @@ -183,34 +174,42 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_TASKSTATS is not set # CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED=y -CONFIG_RELAY=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_EMBEDDED=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y +# CONFIG_HOTPLUG is not set CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set CONFIG_SHMEM=y -CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_RT_MUTEXES=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set # # Loadable module support # -# CONFIG_MODULES is not set +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y # # Block layer @@ -218,7 +217,7 @@ CONFIG_BASE_SMALL=0 CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -CONFIG_LSF=y +# CONFIG_LSF is not set # # IO Schedulers @@ -238,17 +237,12 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_HW_HAS_PCI=y CONFIG_PCI=y +# CONFIG_ARCH_SUPPORTS_MSI is not set CONFIG_MMU=y # # PCCARD (PCMCIA/CardBus) support # -# CONFIG_PCCARD is not set - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set # # Executable file formats @@ -260,10 +254,7 @@ CONFIG_TRAD_SIGNALS=y # # Power management options # -CONFIG_PM=y -# CONFIG_PM_LEGACY is not set -# CONFIG_PM_DEBUG is not set -# CONFIG_PM_SYSFS_DEPRECATED is not set +# CONFIG_PM is not set # # Networking @@ -273,25 +264,21 @@ CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set -# CONFIG_PACKET is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -# CONFIG_XFRM_SUB_POLICY is not set -CONFIG_XFRM_MIGRATE=y -CONFIG_NET_KEY=y -CONFIG_NET_KEY_MIGRATE=y +# CONFIG_NET_KEY is not set CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_FIB_HASH=y CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_DHCP is not set # CONFIG_IP_PNP_BOOTP is not set # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set @@ -299,19 +286,19 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_TCP_MD5SIG=y +# CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set -CONFIG_NETWORK_SECMARK=y +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -352,13 +339,16 @@ CONFIG_NETWORK_SECMARK=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -CONFIG_IEEE80211=y -# CONFIG_IEEE80211_DEBUG is not set -CONFIG_IEEE80211_CRYPT_WEP=y -CONFIG_IEEE80211_CRYPT_CCMP=y -CONFIG_IEEE80211_SOFTMAC=y -# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set -CONFIG_WIRELESS_EXT=y +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set # # Device Drivers @@ -369,18 +359,12 @@ CONFIG_WIRELESS_EXT=y # CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y # CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker # -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y - -# -# Memory Technology Devices (MTD) -# +# CONFIG_CONNECTOR is not set # CONFIG_MTD is not set # @@ -401,21 +385,24 @@ CONFIG_PROC_EVENTS=y # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_CDROM_PKTCDVD=y -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -# CONFIG_CDROM_PKTCDVD_WCACHE is not set -CONFIG_ATA_OVER_ETH=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set # # Misc devices # -CONFIG_SGI_IOC4=y +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set +# CONFIG_BLINK is not set # # ATA/ATAPI/MFM/RLL support @@ -425,7 +412,7 @@ CONFIG_SGI_IOC4=y # # SCSI device support # -CONFIG_RAID_ATTRS=y +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_NETLINK is not set @@ -471,27 +458,13 @@ CONFIG_NETDEVICES=y # # PHY device support # -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -CONFIG_MARVELL_PHY=y -CONFIG_DAVICOM_PHY=y -CONFIG_QSEMI_PHY=y -CONFIG_LXT_PHY=y -CONFIG_CICADA_PHY=y -CONFIG_VITESSE_PHY=y -CONFIG_SMSC_PHY=y -# CONFIG_BROADCOM_PHY is not set -# CONFIG_FIXED_PHY is not set +# CONFIG_PHYLIB is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -CONFIG_MII=y -CONFIG_GALILEO_64240_ETH=y +# CONFIG_MII is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set @@ -503,6 +476,7 @@ CONFIG_GALILEO_64240_ETH=y # # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set +CONFIG_NE2000=y # CONFIG_NET_PCI is not set # @@ -521,18 +495,18 @@ CONFIG_GALILEO_64240_ETH=y # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set -CONFIG_QLA3XXX=y +# CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set # # Ethernet (10000 Mbit) # # CONFIG_CHELSIO_T1 is not set -CONFIG_CHELSIO_T3=y +# CONFIG_CHELSIO_T3 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set -CONFIG_NETXEN_NIC=y +# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -540,9 +514,10 @@ CONFIG_NETXEN_NIC=y # CONFIG_TR is not set # -# Wireless LAN (non-hamradio) +# Wireless LAN # -# CONFIG_NET_RADIO is not set +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # # Wan interfaces @@ -570,29 +545,7 @@ CONFIG_NETXEN_NIC=y # # Input device support # -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set +# CONFIG_INPUT is not set # # Hardware I/O ports @@ -601,34 +554,31 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_PCIPS2 is not set -# CONFIG_SERIO_LIBPS2 is not set -CONFIG_SERIO_RAW=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set # CONFIG_GAMEPORT is not set # # Character devices # -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_TXX9=y +CONFIG_HAS_TXX9_SERIAL=y +CONFIG_SERIAL_TXX9_NR_UARTS=6 +CONFIG_SERIAL_TXX9_CONSOLE=y +CONFIG_SERIAL_TXX9_STDSERIAL=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y @@ -656,10 +606,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # TPM devices # # CONFIG_TCG_TPM is not set - -# -# I2C support -# +CONFIG_DEVPORT=y # CONFIG_I2C is not set # @@ -672,12 +619,12 @@ CONFIG_LEGACY_PTY_COUNT=256 # Dallas's 1-wire bus # # CONFIG_W1 is not set +# CONFIG_HWMON is not set # -# Hardware Monitoring support +# Multifunction device drivers # -# CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set +# CONFIG_MFD_SM501 is not set # # Multimedia devices @@ -692,15 +639,14 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Graphics support # -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # -# Console display driver support +# Display device support # -# CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +# CONFIG_FB is not set # # Sound @@ -708,11 +654,6 @@ CONFIG_DUMMY_CONSOLE=y # CONFIG_SOUND is not set # -# HID Devices -# -# CONFIG_HID is not set - -# # USB support # CONFIG_USB_ARCH_HAS_HCD=y @@ -728,10 +669,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y # USB Gadget Support # # CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# # CONFIG_MMC is not set # @@ -759,7 +696,40 @@ CONFIG_USB_ARCH_HAS_EHCI=y # # Real Time Clock # -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +CONFIG_RTC_DRV_DS1742=y +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# # # DMA Engine support @@ -785,9 +755,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y # # File systems # -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4DEV_FS is not set # CONFIG_REISERFS_FS is not set @@ -801,10 +769,10 @@ CONFIG_FS_POSIX_ACL=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y +# CONFIG_DNOTIFY is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -CONFIG_FUSE_FS=y +# CONFIG_FUSE_FS is not set CONFIG_GENERIC_ACL=y # @@ -824,21 +792,20 @@ CONFIG_GENERIC_ACL=y # Pseudo filesystems # CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y +# CONFIG_PROC_KCORE is not set CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -CONFIG_CONFIGFS_FS=y +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems # # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set -# CONFIG_ECRYPT_FS is not set # CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set @@ -855,17 +822,17 @@ CONFIG_CONFIGFS_FS=y # Network File Systems # CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set # CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +# CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y -CONFIG_EXPORTFS=y +CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -889,10 +856,7 @@ CONFIG_MSDOS_PARTITION=y # # Distributed Lock Manager # -CONFIG_DLM=y -CONFIG_DLM_TCP=y -# CONFIG_DLM_SCTP is not set -# CONFIG_DLM_DEBUG is not set +# CONFIG_DLM is not set # # Profiling support @@ -910,72 +874,29 @@ CONFIG_ENABLE_MUST_CHECK=y # CONFIG_DEBUG_FS is not set # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_LOG_BUF_SHIFT=14 CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" +CONFIG_SYS_SUPPORTS_KGDB=y # # Security options # -CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # # Cryptographic options # -CONFIG_CRYPTO=y -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_WP512=y -CONFIG_CRYPTO_TGR192=y -CONFIG_CRYPTO_GF128MUL=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_PCBC=y -CONFIG_CRYPTO_LRW=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_FCRYPT=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_TWOFISH_COMMON=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_CAST5=y -CONFIG_CRYPTO_CAST6=y -CONFIG_CRYPTO_TEA=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_KHAZAD=y -CONFIG_CRYPTO_ANUBIS=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CAMELLIA=y - -# -# Hardware crypto devices -# +# CONFIG_CRYPTO is not set # # Library routines # CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set -CONFIG_CRC16=y +# CONFIG_CRC16 is not set CONFIG_CRC32=y -CONFIG_LIBCRC32C=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_PLIST=y +# CONFIG_LIBCRC32C is not set CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig index 7d0f2174614e..41011f770a67 100644 --- a/arch/mips/configs/rbhma4500_defconfig +++ b/arch/mips/configs/rbhma4500_defconfig @@ -89,7 +89,6 @@ CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SWAP_IO_SPACE=y CONFIG_MIPS_L1_CACHE_SHIFT=5 CONFIG_HAVE_STD_PC_SERIAL_PORT=y -CONFIG_TOSHIBA_BOARDS=y # # CPU selection diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0219_defconfig index 1756d2bdf6b8..8b1675c07ec4 100644 --- a/arch/mips/configs/tb0229_defconfig +++ b/arch/mips/configs/tb0219_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.20 -# Tue Feb 20 21:47:41 2007 +# Linux kernel version: 2.6.21-rc6 +# Sun Apr 15 01:06:01 2007 # CONFIG_MIPS=y @@ -66,10 +66,11 @@ CONFIG_MACH_VR41XX=y # CONFIG_IBM_WORKPAD is not set # CONFIG_NEC_CMBVR4133 is not set CONFIG_TANBAC_TB022X=y -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0287 is not set # CONFIG_VICTOR_MPC30X is not set # CONFIG_ZAO_CAPCELLA is not set +CONFIG_TANBAC_TB0219=y +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0287 is not set CONFIG_PCI_VR41XX=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set @@ -184,6 +185,7 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_IKCONFIG is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_EMBEDDED=y @@ -375,7 +377,7 @@ CONFIG_FIB_RULES=y # CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=m # CONFIG_SYS_HYPERVISOR is not set # @@ -415,7 +417,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -# CONFIG_BLK_DEV_INITRD is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -646,7 +647,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -CONFIG_TANBAC_TB0219=y +CONFIG_GPIO_TB0219=y # CONFIG_DRM is not set CONFIG_GPIO_VR41XX=y # CONFIG_RAW_DRIVER is not set @@ -679,6 +680,11 @@ CONFIG_GPIO_VR41XX=y # CONFIG_HWMON_VID is not set # +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -692,7 +698,7 @@ CONFIG_GPIO_VR41XX=y # # Graphics support # -# CONFIG_FIRMWARE_EDID is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # CONFIG_FB is not set # @@ -700,7 +706,6 @@ CONFIG_GPIO_VR41XX=y # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -831,6 +836,7 @@ CONFIG_USB_MON=y # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # diff --git a/arch/mips/kernel/early_printk.c b/arch/mips/kernel/early_printk.c index 4fa54b230c09..9dccfa4752b2 100644 --- a/arch/mips/kernel/early_printk.c +++ b/arch/mips/kernel/early_printk.c @@ -12,7 +12,8 @@ extern void prom_putchar(char); -static void early_console_write(struct console *con, const char *s, unsigned n) +static void __init +early_console_write(struct console *con, const char *s, unsigned n) { while (n-- && *s) { if (*s == '\n') @@ -22,14 +23,20 @@ static void early_console_write(struct console *con, const char *s, unsigned n) } } -static struct console early_console = { +static struct console early_console __initdata = { .name = "early", .write = early_console_write, .flags = CON_PRINTBUFFER | CON_BOOT, .index = -1 }; +static int early_console_initialized __initdata; + void __init setup_early_printk(void) { + if (early_console_initialized) + return; + early_console_initialized = 1; + register_console(&early_console); } diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c index 2967537221e2..410868b5ea5f 100644 --- a/arch/mips/kernel/irq-msc01.c +++ b/arch/mips/kernel/irq-msc01.c @@ -132,11 +132,11 @@ struct irq_chip msc_edgeirq_type = { }; -void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq) +void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq) { extern void (*board_bind_eic_interrupt)(unsigned int irq, unsigned int regset); - _icctrl_msc = (unsigned long) ioremap (MIPS_MSC01_IC_REG_BASE, 0x40000); + _icctrl_msc = (unsigned long) ioremap (icubase, 0x40000); /* Reset interrupt controller - initialises all registers to 0 */ MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT); @@ -148,14 +148,14 @@ void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq) switch (imp->im_type) { case MSC01_IRQ_EDGE: - set_irq_chip(base+n, &msc_edgeirq_type); + set_irq_chip(irqbase+n, &msc_edgeirq_type); if (cpu_has_veic) MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT); else MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl); break; case MSC01_IRQ_LEVEL: - set_irq_chip(base+n, &msc_levelirq_type); + set_irq_chip(irqbase+n, &msc_levelirq_type); if (cpu_has_veic) MSCIC_WRITE(MSC01_IC_SUP+n*8, 0); else @@ -163,7 +163,7 @@ void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq) } } - irq_base = base; + irq_base = irqbase; MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT); /* Enable interrupt generation */ diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 2fe4c868a801..aeded6c17de5 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -28,7 +28,7 @@ static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; -int __devinit allocate_irqno(void) +int allocate_irqno(void) { int irq; @@ -59,7 +59,7 @@ void __init alloc_legacy_irqno(void) BUG_ON(test_and_set_bit(i, irq_map)); } -void __devinit free_irqno(unsigned int irq) +void free_irqno(unsigned int irq) { smp_mb__before_clear_bit(); clear_bit(irq, irq_map); diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index e5e56bd498db..751b4a18b133 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -306,7 +306,7 @@ static unsigned int __init calibrate_hpt(void) struct clocksource clocksource_mips = { .name = "MIPS", - .mask = 0xffffffff, + .mask = CLOCKSOURCE_MASK(32), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index ff45a4b8fbaa..200de027f354 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -927,9 +927,9 @@ asmlinkage void do_reserved(struct pt_regs *regs) (regs->cp0_cause & 0x7f) >> 2); } -asmlinkage void do_default_vi(struct pt_regs *regs) +static asmlinkage void do_default_vi(void) { - show_regs(regs); + show_regs(get_irq_regs()); panic("Caught unexpected vectored interrupt."); } @@ -1128,7 +1128,7 @@ void mips_srs_free(int set) clear_bit(set, &sr->sr_allocated); } -static void *set_vi_srs_handler(int n, void *addr, int srs) +static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) { unsigned long handler; unsigned long old_handler = vi_handlers[n]; @@ -1217,7 +1217,7 @@ static void *set_vi_srs_handler(int n, void *addr, int srs) return (void *)old_handler; } -void *set_vi_handler(int n, void *addr) +void *set_vi_handler(int n, vi_handler_t addr) { return set_vi_srs_handler(n, addr, 0); } diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index d7d3b14dcfb2..5dad13efba7e 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -9,4 +9,4 @@ obj-y += iomap.o obj-$(CONFIG_PCI) += iomap-pci.o # libgcc-style stuff needed in the kernel -lib-y += ashldi3.o ashrdi3.o lshrdi3.o +lib-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c new file mode 100644 index 000000000000..e9ff258ef028 --- /dev/null +++ b/arch/mips/lib/ucmpdi2.c @@ -0,0 +1,19 @@ +#include <linux/module.h> + +#include "libgcc.h" + +word_type __ucmpdi2 (unsigned long a, unsigned long b) +{ + const DWunion au = {.ll = a}; + const DWunion bu = {.ll = b}; + + if ((unsigned int) au.s.high < (unsigned int) bu.s.high) + return 0; + else if ((unsigned int) au.s.high > (unsigned int) bu.s.high) + return 2; + if ((unsigned int) au.s.low < (unsigned int) bu.s.low) + return 0; + else if ((unsigned int) au.s.low > (unsigned int) bu.s.low) + return 2; + return 1; +} diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c index 83d76025d61d..1cd830e3d933 100644 --- a/arch/mips/mips-boards/malta/malta_int.c +++ b/arch/mips/mips-boards/malta/malta_int.c @@ -311,16 +311,21 @@ void __init arch_init_irq(void) if (!cpu_has_veic) mips_cpu_irq_init(); - switch(mips_revision_corid) { - case MIPS_REVISION_CORID_CORE_MSC: - case MIPS_REVISION_CORID_CORE_FPGA2: - case MIPS_REVISION_CORID_CORE_FPGA3: - case MIPS_REVISION_CORID_CORE_24K: - case MIPS_REVISION_CORID_CORE_EMUL_MSC: + switch(mips_revision_sconid) { + case MIPS_REVISION_SCON_SOCIT: + case MIPS_REVISION_SCON_ROCIT: + if (cpu_has_veic) + init_msc_irqs (MIPS_MSC01_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs); + else + init_msc_irqs (MIPS_MSC01_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs); + break; + + case MIPS_REVISION_SCON_SOCITSC: + case MIPS_REVISION_SCON_SOCITSCP: if (cpu_has_veic) - init_msc_irqs (MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs); + init_msc_irqs (MIPS_SOCITSC_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs); else - init_msc_irqs (MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs); + init_msc_irqs (MIPS_SOCITSC_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs); } if (cpu_has_veic) { diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c index 675502ada5a2..10dd2af2343b 100644 --- a/arch/mips/mm/highmem.c +++ b/arch/mips/mm/highmem.c @@ -80,7 +80,6 @@ void __kunmap_atomic(void *kvaddr, enum km_type type) pagefault_enable(); } -#ifndef CONFIG_LIMITED_DMA /* * This is the same as kmap_atomic() but can map memory that doesn't * have a struct page associated with it. @@ -99,7 +98,6 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) return (void*) vaddr; } -#endif /* CONFIG_LIMITED_DMA */ struct page *__kmap_atomic_to_page(void *ptr) { diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 2d1c2c024822..4c80528deadd 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -424,9 +424,6 @@ void __init mem_init(void) continue; } ClearPageReserved(page); -#ifdef CONFIG_LIMITED_DMA - set_page_address(page, lowmem_page_address(page)); -#endif init_page_count(page); __free_page(page); totalhigh_pages++; diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 492c518e7ba5..e7149290d1cb 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -35,24 +35,24 @@ #include <asm/smp.h> #include <asm/war.h> -static __init int __attribute__((unused)) r45k_bvahwbug(void) +static __init int __maybe_unused r45k_bvahwbug(void) { /* XXX: We should probe for the presence of this bug, but we don't. */ return 0; } -static __init int __attribute__((unused)) r4k_250MHZhwbug(void) +static __init int __maybe_unused r4k_250MHZhwbug(void) { /* XXX: We should probe for the presence of this bug, but we don't. */ return 0; } -static __init int __attribute__((unused)) bcm1250_m3_war(void) +static __init int __maybe_unused bcm1250_m3_war(void) { return BCM1250_M3_WAR; } -static __init int __attribute__((unused)) r10000_llsc_war(void) +static __init int __maybe_unused r10000_llsc_war(void) { return R10000_LLSC_WAR; } @@ -511,18 +511,18 @@ L_LA(_r3000_write_probe_fail) #define i_ehb(buf) i_sll(buf, 0, 0, 3) #ifdef CONFIG_64BIT -static __init int __attribute__((unused)) in_compat_space_p(long addr) +static __init int __maybe_unused in_compat_space_p(long addr) { /* Is this address in 32bit compat space? */ return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L); } -static __init int __attribute__((unused)) rel_highest(long val) +static __init int __maybe_unused rel_highest(long val) { return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; } -static __init int __attribute__((unused)) rel_higher(long val) +static __init int __maybe_unused rel_higher(long val) { return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; } @@ -556,8 +556,8 @@ static __init void i_LA_mostly(u32 **buf, unsigned int rs, long addr) i_lui(buf, rs, rel_hi(addr)); } -static __init void __attribute__((unused)) i_LA(u32 **buf, unsigned int rs, - long addr) +static __init void __maybe_unused i_LA(u32 **buf, unsigned int rs, + long addr) { i_LA_mostly(buf, rs, addr); if (rel_lo(addr)) @@ -636,8 +636,8 @@ static __init void copy_handler(struct reloc *rel, struct label *lab, move_labels(lab, first, end, off); } -static __init int __attribute__((unused)) insn_has_bdelay(struct reloc *rel, - u32 *addr) +static __init int __maybe_unused insn_has_bdelay(struct reloc *rel, + u32 *addr) { for (; rel->lab != label_invalid; rel++) { if (rel->addr == addr @@ -650,15 +650,15 @@ static __init int __attribute__((unused)) insn_has_bdelay(struct reloc *rel, } /* convenience functions for labeled branches */ -static void __init __attribute__((unused)) +static void __init __maybe_unused il_bltz(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) { r_mips_pc16(r, *p, l); i_bltz(p, reg, 0); } -static void __init __attribute__((unused)) il_b(u32 **p, struct reloc **r, - enum label_id l) +static void __init __maybe_unused il_b(u32 **p, struct reloc **r, + enum label_id l) { r_mips_pc16(r, *p, l); i_b(p, 0); @@ -671,7 +671,7 @@ static void __init il_beqz(u32 **p, struct reloc **r, unsigned int reg, i_beqz(p, reg, 0); } -static void __init __attribute__((unused)) +static void __init __maybe_unused il_beqzl(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) { r_mips_pc16(r, *p, l); @@ -692,7 +692,7 @@ static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg, i_bgezl(p, reg, 0); } -static void __init __attribute__((unused)) +static void __init __maybe_unused il_bgez(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) { r_mips_pc16(r, *p, l); @@ -810,7 +810,7 @@ static __initdata u32 final_handler[64]; * * As if we MIPS hackers wouldn't know how to nop pipelines happy ... */ -static __init void __attribute__((unused)) build_tlb_probe_entry(u32 **p) +static __init void __maybe_unused build_tlb_probe_entry(u32 **p) { switch (current_cpu_data.cputype) { /* Found by experiment: R4600 v2.0 needs this, too. */ @@ -1098,7 +1098,7 @@ build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r, * TMP and PTR are scratch. * TMP will be clobbered, PTR will hold the pgd entry. */ -static __init void __attribute__((unused)) +static __init void __maybe_unused build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) { long pgdc = (long)pgd_current; diff --git a/arch/mips/momentum/Kconfig b/arch/mips/momentum/Kconfig deleted file mode 100644 index 70a61cf7174d..000000000000 --- a/arch/mips/momentum/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -config JAGUAR_DMALOW - bool "Low DMA Mode" - depends on MOMENCO_JAGUAR_ATX - help - Select to Y if jump JP5 is set on your board, N otherwise. Normally - the jumper is set, so if you feel unsafe, just say Y. diff --git a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile deleted file mode 100644 index 2e8cebd49bc0..000000000000 --- a/arch/mips/momentum/jaguar_atx/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for Momentum Computer's Jaguar-ATX board. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# - -obj-y += irq.o platform.o prom.o reset.o setup.o - -obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o -obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o diff --git a/arch/mips/momentum/jaguar_atx/dbg_io.c b/arch/mips/momentum/jaguar_atx/dbg_io.c deleted file mode 100644 index b85a6521f72d..000000000000 --- a/arch/mips/momentum/jaguar_atx/dbg_io.c +++ /dev/null @@ -1,125 +0,0 @@ - -#if defined(CONFIG_REMOTE_DEBUG) - -#include <asm/serial.h> /* For the serial port location and base baud */ - -/* --- CONFIG --- */ - -typedef unsigned char uint8; -typedef unsigned int uint32; - -/* --- END OF CONFIG --- */ - -#define UART16550_BAUD_2400 2400 -#define UART16550_BAUD_4800 4800 -#define UART16550_BAUD_9600 9600 -#define UART16550_BAUD_19200 19200 -#define UART16550_BAUD_38400 38400 -#define UART16550_BAUD_57600 57600 -#define UART16550_BAUD_115200 115200 - -#define UART16550_PARITY_NONE 0 -#define UART16550_PARITY_ODD 0x08 -#define UART16550_PARITY_EVEN 0x18 -#define UART16550_PARITY_MARK 0x28 -#define UART16550_PARITY_SPACE 0x38 - -#define UART16550_DATA_5BIT 0x0 -#define UART16550_DATA_6BIT 0x1 -#define UART16550_DATA_7BIT 0x2 -#define UART16550_DATA_8BIT 0x3 - -#define UART16550_STOP_1BIT 0x0 -#define UART16550_STOP_2BIT 0x4 - -/* ----------------------------------------------------- */ - -/* === CONFIG === */ - -/* [jsun] we use the second serial port for kdb */ -#define BASE OCELOT_SERIAL1_BASE -#define MAX_BAUD OCELOT_BASE_BAUD - -/* === END OF CONFIG === */ - -#define REG_OFFSET 4 - -/* register offset */ -#define OFS_RCV_BUFFER 0 -#define OFS_TRANS_HOLD 0 -#define OFS_SEND_BUFFER 0 -#define OFS_INTR_ENABLE (1*REG_OFFSET) -#define OFS_INTR_ID (2*REG_OFFSET) -#define OFS_DATA_FORMAT (3*REG_OFFSET) -#define OFS_LINE_CONTROL (3*REG_OFFSET) -#define OFS_MODEM_CONTROL (4*REG_OFFSET) -#define OFS_RS232_OUTPUT (4*REG_OFFSET) -#define OFS_LINE_STATUS (5*REG_OFFSET) -#define OFS_MODEM_STATUS (6*REG_OFFSET) -#define OFS_RS232_INPUT (6*REG_OFFSET) -#define OFS_SCRATCH_PAD (7*REG_OFFSET) - -#define OFS_DIVISOR_LSB (0*REG_OFFSET) -#define OFS_DIVISOR_MSB (1*REG_OFFSET) - - -/* memory-mapped read/write of the port */ -#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) -#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) - -void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) -{ - /* disable interrupts */ - UART16550_WRITE(OFS_INTR_ENABLE, 0); - - /* set up baud rate */ - { - uint32 divisor; - - /* set DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x80); - - /* set divisor */ - divisor = MAX_BAUD / baud; - UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); - UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); - - /* clear DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x0); - } - - /* set data format */ - UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); -} - -static int remoteDebugInitialized = 0; - -uint8 getDebugChar(void) -{ - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_38400, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); - return UART16550_READ(OFS_RCV_BUFFER); -} - - -int putDebugChar(uint8 byte) -{ - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_38400, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); - UART16550_WRITE(OFS_SEND_BUFFER, byte); - return 1; -} - -#endif diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c deleted file mode 100644 index f2b432585df2..000000000000 --- a/arch/mips/momentum/jaguar_atx/irq.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2002 Momentum Computer, Inc. - * Author: Matthew Dharm, mdharm@momenco.com - * - * Based on work by: - * Copyright (C) 2000 RidgeRun, Inc. - * Author: RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * Copyright (C) 2000, 01, 06 Ralf Baechle (ralf@linux-mips.org) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/signal.h> -#include <linux/types.h> -#include <asm/irq_cpu.h> -#include <asm/mipsregs.h> -#include <asm/time.h> - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_cause() & read_c0_status(); - - if (pending & STATUSF_IP0) - do_IRQ(0); - else if (pending & STATUSF_IP1) - do_IRQ(1); - else if (pending & STATUSF_IP2) - do_IRQ(2); - else if (pending & STATUSF_IP3) - do_IRQ(3); - else if (pending & STATUSF_IP4) - do_IRQ(4); - else if (pending & STATUSF_IP5) - do_IRQ(5); - else if (pending & STATUSF_IP6) - do_IRQ(6); - else if (pending & STATUSF_IP7) - ll_timer_interrupt(7); - else { - /* - * Now look at the extended interrupts - */ - pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16; - if (pending & STATUSF_IP8) - ll_mv64340_irq(); - } -} - -static struct irqaction cascade_mv64340 = { - no_action, IRQF_DISABLED, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL -}; - -void __init arch_init_irq(void) -{ - /* - * Clear all of the interrupts while we change the able around a bit. - * int-handler is not on bootstrap - */ - clear_c0_status(ST0_IM); - - mips_cpu_irq_init(); - rm7k_cpu_irq_init(); - - /* set up the cascading interrupts */ - setup_irq(8, &cascade_mv64340); - - mv64340_irq_init(16); - - set_c0_status(ST0_IM); -} diff --git a/arch/mips/momentum/jaguar_atx/ja-console.c b/arch/mips/momentum/jaguar_atx/ja-console.c deleted file mode 100644 index 2c30b4f56245..000000000000 --- a/arch/mips/momentum/jaguar_atx/ja-console.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001, 2002, 2004 Ralf Baechle - */ -#include <linux/init.h> -#include <linux/console.h> -#include <linux/kdev_t.h> -#include <linux/major.h> -#include <linux/termios.h> -#include <linux/sched.h> -#include <linux/tty.h> - -#include <linux/serial.h> -#include <linux/serial_core.h> -#include <asm/serial.h> - -/* SUPERIO uart register map */ -struct ja_uartregs { - union { - volatile u8 pad0[3]; - volatile u8 rbr; /* read only, DLAB == 0 */ - volatile u8 pad1[3]; - volatile u8 thr; /* write only, DLAB == 0 */ - volatile u8 pad2[3]; - volatile u8 dll; /* DLAB == 1 */ - } u1; - union { - volatile u8 pad0[3]; - volatile u8 ier; /* DLAB == 0 */ - volatile u8 pad1[3]; - volatile u8 dlm; /* DLAB == 1 */ - } u2; - union { - volatile u8 pad0[3]; - volatile u8 iir; /* read only */ - volatile u8 pad1[3]; - volatile u8 fcr; /* write only */ - } u3; - volatile u8 pad0[3]; - volatile u8 iu_lcr; - volatile u8 pad1[3]; - volatile u8 iu_mcr; - volatile u8 pad2[3]; - volatile u8 iu_lsr; - volatile u8 pad3[3]; - volatile u8 iu_msr; - volatile u8 pad4[3]; - volatile u8 iu_scr; -} ja_uregs_t; - -#define iu_rbr u1.rbr -#define iu_thr u1.thr -#define iu_dll u1.dll -#define iu_ier u2.ier -#define iu_dlm u2.dlm -#define iu_iir u3.iir -#define iu_fcr u3.fcr - -extern unsigned long uart_base; - -static inline struct ja_uartregs *console_uart(void) -{ - return (struct ja_uartregs *) (uart_base + 0x23UL); -} - -void prom_putchar(char c) -{ - struct ja_uartregs *uart = console_uart(); - - while ((uart->iu_lsr & 0x20) == 0); - uart->iu_thr = c; -} - -static void inline ja_console_probe(void) -{ - struct uart_port up; - - /* - * Register to interrupt zero because we share the interrupt with - * the serial driver which we don't properly support yet. - */ - memset(&up, 0, sizeof(up)); - up.membase = (unsigned char *) uart_base + 0x23UL; - up.irq = JAGUAR_ATX_SERIAL1_IRQ; - up.uartclk = JAGUAR_ATX_UART_CLK; - up.regshift = 2; - up.iotype = UPIO_MEM; - up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; - up.line = 0; - - if (early_serial_setup(&up)) - printk(KERN_ERR "Early serial init of port 0 failed\n"); -} - -__init void ja_setup_console(void) -{ - ja_console_probe(); -} diff --git a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h b/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h deleted file mode 100644 index 022f6974b76e..000000000000 --- a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Jaguar-ATX Board Register Definitions - * - * (C) 2002 Momentum Computer Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef __JAGUAR_ATX_FPGA_H__ -#define __JAGUAR_ATX_FPGA_H__ - -#define JAGUAR_ATX_REG_BOARDREV 0x0 -#define JAGUAR_ATX_REG_FPGA_REV 0x1 -#define JAGUAR_ATX_REG_FPGA_TYPE 0x2 -#define JAGUAR_ATX_REG_RESET_STATUS 0x3 -#define JAGUAR_ATX_REG_BOARD_STATUS 0x4 -#define JAGUAR_ATX_REG_RESERVED1 0x5 -#define JAGUAR_ATX_REG_SET 0x6 -#define JAGUAR_ATX_REG_CLR 0x7 -#define JAGUAR_ATX_REG_EEPROM_MODE 0x9 -#define JAGUAR_ATX_REG_RESERVED2 0xa -#define JAGUAR_ATX_REG_RESERVED3 0xb -#define JAGUAR_ATX_REG_RESERVED4 0xc -#define JAGUAR_ATX_REG_PHY_INTSTAT 0xd -#define JAGUAR_ATX_REG_RESERVED5 0xe -#define JAGUAR_ATX_REG_RESERVED6 0xf - -#define JAGUAR_ATX_CS0_ADDR 0xfc000000L - -extern unsigned long ja_fpga_base; - -#define __FPGA_REG_TO_ADDR(reg) \ - ((void *) ja_fpga_base + JAGUAR_ATX_REG_##reg) -#define JAGUAR_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg)) -#define JAGUAR_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg)) - -#endif diff --git a/arch/mips/momentum/jaguar_atx/platform.c b/arch/mips/momentum/jaguar_atx/platform.c deleted file mode 100644 index 561844878a90..000000000000 --- a/arch/mips/momentum/jaguar_atx/platform.c +++ /dev/null @@ -1,208 +0,0 @@ -#include <linux/delay.h> -#include <linux/if_ether.h> -#include <linux/ioport.h> -#include <linux/mv643xx.h> -#include <linux/platform_device.h> - -#include "jaguar_atx_fpga.h" - -#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) - -static struct resource mv643xx_eth_shared_resources[] = { - [0] = { - .name = "ethernet shared base", - .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, - .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + - MV643XX_ETH_SHARED_REGS_SIZE - 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device mv643xx_eth_shared_device = { - .name = MV643XX_ETH_SHARED_NAME, - .id = 0, - .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), - .resource = mv643xx_eth_shared_resources, -}; - -#define MV_SRAM_BASE 0xfe000000UL -#define MV_SRAM_SIZE (256 * 1024) - -#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) -#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) - -#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE -#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) - -#define MV64x60_IRQ_ETH_0 48 -#define MV64x60_IRQ_ETH_1 49 -#define MV64x60_IRQ_ETH_2 50 - -static struct resource mv64x60_eth0_resources[] = { - [0] = { - .name = "eth0 irq", - .start = MV64x60_IRQ_ETH_0, - .end = MV64x60_IRQ_ETH_0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct mv643xx_eth_platform_data eth0_pd = { - .port_number = 0, - - .tx_sram_addr = MV_SRAM_BASE_ETH0, - .tx_sram_size = MV_SRAM_TXRING_SIZE, - .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, - - .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, - .rx_sram_size = MV_SRAM_RXRING_SIZE, - .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, -}; - -static struct platform_device eth0_device = { - .name = MV643XX_ETH_NAME, - .id = 0, - .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), - .resource = mv64x60_eth0_resources, - .dev = { - .platform_data = ð0_pd, - }, -}; - -static struct resource mv64x60_eth1_resources[] = { - [0] = { - .name = "eth1 irq", - .start = MV64x60_IRQ_ETH_1, - .end = MV64x60_IRQ_ETH_1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct mv643xx_eth_platform_data eth1_pd = { - .port_number = 1, - - .tx_sram_addr = MV_SRAM_BASE_ETH1, - .tx_sram_size = MV_SRAM_TXRING_SIZE, - .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, - - .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, - .rx_sram_size = MV_SRAM_RXRING_SIZE, - .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, -}; - -static struct platform_device eth1_device = { - .name = MV643XX_ETH_NAME, - .id = 1, - .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), - .resource = mv64x60_eth1_resources, - .dev = { - .platform_data = ð1_pd, - }, -}; - -static struct resource mv64x60_eth2_resources[] = { - [0] = { - .name = "eth2 irq", - .start = MV64x60_IRQ_ETH_2, - .end = MV64x60_IRQ_ETH_2, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct mv643xx_eth_platform_data eth2_pd = { - .port_number = 2, -}; - -static struct platform_device eth2_device = { - .name = MV643XX_ETH_NAME, - .id = 2, - .num_resources = ARRAY_SIZE(mv64x60_eth2_resources), - .resource = mv64x60_eth2_resources, - .dev = { - .platform_data = ð2_pd, - }, -}; - -static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { - &mv643xx_eth_shared_device, - ð0_device, - ð1_device, - ð2_device, -}; - -static u8 __init exchange_bit(u8 val, u8 cs) -{ - /* place the data */ - JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); - udelay(1); - - /* turn the clock on */ - JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); - udelay(1); - - /* turn the clock off and read-strobe */ - JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); - - /* return the data */ - return (JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1; -} - -static void __init get_mac(char dest[6]) -{ - u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i,j; - - for (i = 0; i < 12; i++) - exchange_bit(read_opcode[i], 1); - - for (j = 0; j < 6; j++) { - dest[j] = 0; - for (i = 0; i < 8; i++) { - dest[j] <<= 1; - dest[j] |= exchange_bit(0, 1); - } - } - - /* turn off CS */ - exchange_bit(0,0); -} - -/* - * Copy and increment ethernet MAC address by a small value. - * - * This is useful for systems where the only one MAC address is stored in - * non-volatile memory for multiple ports. - */ -static inline void eth_mac_add(unsigned char *dst, unsigned char *src, - unsigned int add) -{ - int i; - - BUG_ON(add >= 256); - - for (i = ETH_ALEN; i >= 0; i--) { - dst[i] = src[i] + add; - add = dst[i] < src[i]; /* compute carry */ - } - - WARN_ON(add); -} - -static int __init mv643xx_eth_add_pds(void) -{ - unsigned char mac[ETH_ALEN]; - int ret; - - get_mac(mac); - eth_mac_add(eth0_pd.mac_addr, mac, 0); - eth_mac_add(eth1_pd.mac_addr, mac, 1); - eth_mac_add(eth2_pd.mac_addr, mac, 2); - ret = platform_add_devices(mv643xx_eth_pd_devs, - ARRAY_SIZE(mv643xx_eth_pd_devs)); - - return ret; -} - -device_initcall(mv643xx_eth_add_pds); - -#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c deleted file mode 100644 index 5dd154ee58f6..000000000000 --- a/arch/mips/momentum/jaguar_atx/prom.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2002 Momentum Computer Inc. - * Author: Matthew Dharm <mdharm@momenco.com> - * - * Louis Hamilton, Red Hat, Inc. - * hamilton@redhat.com [MIPS64 modifications] - * - * Based on Ocelot Linux port, which is - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Added changes for SMP - Manish Lachwani (lachwani@pmc-sierra.com) - */ -#include <linux/init.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/bootmem.h> -#include <linux/mv643xx.h> - -#include <asm/addrspace.h> -#include <asm/bootinfo.h> -#include <asm/pmon.h> - -#include "jaguar_atx_fpga.h" - -extern void ja_setup_console(void); - -struct callvectors *debug_vectors; - -extern unsigned long cpu_clock; - -const char *get_system_type(void) -{ - return "Momentum Jaguar-ATX"; -} - -#ifdef CONFIG_64BIT - -unsigned long signext(unsigned long addr) -{ - addr &= 0xffffffff; - return (unsigned long)((int)addr); -} - -void *get_arg(unsigned long args, int arc) -{ - unsigned long ul; - unsigned char *puc, uc; - - args += (arc * 4); - ul = (unsigned long)signext(args); - puc = (unsigned char *)ul; - if (puc == 0) - return (void *)0; - -#ifdef CONFIG_CPU_LITTLE_ENDIAN - uc = *puc++; - l = (unsigned long)uc; - uc = *puc++; - ul |= (((unsigned long)uc) << 8); - uc = *puc++; - ul |= (((unsigned long)uc) << 16); - uc = *puc++; - ul |= (((unsigned long)uc) << 24); -#else - uc = *puc++; - ul = ((unsigned long)uc) << 24; - uc = *puc++; - ul |= (((unsigned long)uc) << 16); - uc = *puc++; - ul |= (((unsigned long)uc) << 8); - uc = *puc++; - ul |= ((unsigned long)uc); -#endif - ul = signext(ul); - - return (void *)ul; -} - -char *arg64(unsigned long addrin, int arg_index) -{ - unsigned long args; - char *p; - - args = signext(addrin); - p = (char *)get_arg(args, arg_index); - - return p; -} -#endif /* CONFIG_64BIT */ - -/* PMON passes arguments in C main() style */ -void __init prom_init(void) -{ - int argc = fw_arg0; - char **arg = (char **) fw_arg1; - char **env = (char **) fw_arg2; - struct callvectors *cv = (struct callvectors *) fw_arg3; - int i; - -#ifdef CONFIG_SERIAL_8250_CONSOLE -// ja_setup_console(); /* The very first thing. */ -#endif - -#ifdef CONFIG_64BIT - char *ptr; - - printk("Mips64 Jaguar-ATX\n"); - /* save the PROM vectors for debugging use */ - debug_vectors = (struct callvectors *)signext((unsigned long)cv); - - /* arg[0] is "g", the rest is boot parameters */ - arcs_cmdline[0] = '\0'; - - for (i = 1; i < argc; i++) { - ptr = (char *)arg64((unsigned long)arg, i); - if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >= - sizeof(arcs_cmdline)) - break; - strcat(arcs_cmdline, ptr); - strcat(arcs_cmdline, " "); - } - - i = 0; - while (1) { - ptr = (char *)arg64((unsigned long)env, i); - if (! ptr) - break; - - if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) { - marvell_base = simple_strtol(ptr + strlen("gtbase="), - NULL, 16); - - if ((marvell_base & 0xffffffff00000000) == 0) - marvell_base |= 0xffffffff00000000; - - printk("marvell_base set to 0x%016lx\n", marvell_base); - } - if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) { - cpu_clock = simple_strtol(ptr + strlen("cpuclock="), - NULL, 10); - printk("cpu_clock set to %d\n", cpu_clock); - } - i++; - } - printk("arcs_cmdline: %s\n", arcs_cmdline); - -#else /* CONFIG_64BIT */ - /* save the PROM vectors for debugging use */ - debug_vectors = cv; - - /* arg[0] is "g", the rest is boot parameters */ - arcs_cmdline[0] = '\0'; - for (i = 1; i < argc; i++) { - if (strlen(arcs_cmdline) + strlen(arg[i] + 1) - >= sizeof(arcs_cmdline)) - break; - strcat(arcs_cmdline, arg[i]); - strcat(arcs_cmdline, " "); - } - - while (*env) { - if (strncmp("gtbase", *env, strlen("gtbase")) == 0) { - marvell_base = simple_strtol(*env + strlen("gtbase="), - NULL, 16); - } - if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) { - cpu_clock = simple_strtol(*env + strlen("cpuclock="), - NULL, 10); - } - env++; - } -#endif /* CONFIG_64BIT */ - mips_machgroup = MACH_GROUP_MOMENCO; - mips_machtype = MACH_MOMENCO_JAGUAR_ATX; -} - -void __init prom_free_prom_memory(void) -{ -} - -void __init prom_fixup_mem_map(unsigned long start, unsigned long end) -{ -} - -int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp) -{ - /* Clear the semaphore */ - *(volatile uint32_t *)(0xbb000a68) = 0x80000000; - - return 1; -} - -void prom_init_secondary(void) -{ - clear_c0_config(CONF_CM_CMASK); - set_c0_config(0x2); - - clear_c0_status(ST0_IM); - set_c0_status(0x1ffff); -} - -void prom_smp_finish(void) -{ -} diff --git a/arch/mips/momentum/jaguar_atx/reset.c b/arch/mips/momentum/jaguar_atx/reset.c deleted file mode 100644 index c73b0897dc52..000000000000 --- a/arch/mips/momentum/jaguar_atx/reset.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Copyright (C) 1997, 2001 Ralf Baechle - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - * Copyright (C) 2002 Momentum Computer Inc. - * Author: Matthew Dharm <mdharm@momenco.com> - * - * Louis Hamilton, Red Hat, Inc. - * hamilton@redhat.com [MIPS64 modifications] - */ -#include <linux/sched.h> -#include <linux/mm.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/reboot.h> -#include <asm/system.h> -#include <linux/delay.h> - -void momenco_jaguar_restart(char *command) -{ - /* base address of timekeeper portion of part */ -#ifdef CONFIG_64BIT - void *nvram = (void*) 0xfffffffffc807000; -#else - void *nvram = (void*) 0xfc807000; -#endif - /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ - writeb(0x84, nvram + 0xff7); - - /* wait for the watchdog to go off */ - mdelay(100+(1000/16)); - - /* if the watchdog fails for some reason, let people know */ - printk(KERN_NOTICE "Watchdog reset failed\n"); -} - -void momenco_jaguar_halt(void) -{ - printk(KERN_NOTICE "\n** You can safely turn off the power\n"); - while (1) - __asm__(".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); -} - -void momenco_jaguar_power_off(void) -{ - momenco_jaguar_halt(); -} diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c deleted file mode 100644 index 5a510142b978..000000000000 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Momentum Computer Jaguar-ATX board dependent boot routines - * - * Copyright (C) 1996, 1997, 2001, 04, 06 Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2000 RidgeRun, Inc. - * Copyright (C) 2001 Red Hat, Inc. - * Copyright (C) 2002 Momentum Computer - * - * Author: Matthew Dharm, Momentum Computer - * mdharm@momenco.com - * - * Louis Hamilton, Red Hat, Inc. - * hamilton@redhat.com [MIPS64 modifications] - * - * Author: RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include <linux/bcd.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/bootmem.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/swap.h> -#include <linux/ioport.h> -#include <linux/pm.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/timex.h> -#include <linux/vmalloc.h> -#include <linux/mv643xx.h> - -#include <asm/time.h> -#include <asm/bootinfo.h> -#include <asm/page.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/processor.h> -#include <asm/reboot.h> -#include <asm/tlbflush.h> - -#include "jaguar_atx_fpga.h" - -extern unsigned long mv64340_sram_base; -unsigned long cpu_clock; - -/* These functions are used for rebooting or halting the machine*/ -extern void momenco_jaguar_restart(char *command); -extern void momenco_jaguar_halt(void); -extern void momenco_jaguar_power_off(void); - -void momenco_time_init(void); - -static char reset_reason; - -static inline unsigned long ENTRYLO(unsigned long paddr) -{ - return ((paddr & PAGE_MASK) | - (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL | - _CACHE_UNCACHED)) >> 6; -} - -void __init bus_error_init(void) { /* nothing */ } - -/* - * Load a few TLB entries for the MV64340 and perhiperals. The MV64340 is going - * to be hit on every IRQ anyway - there's absolutely no point in letting it be - * a random TLB entry, as it'll just cause needless churning of the TLB. And we - * use the other half for the serial port, which is just a PITA otherwise :) - * - * Device Physical Virtual - * MV64340 Internal Regs 0xf4000000 0xf4000000 - * Ocelot-C[S] PLD (CS0) 0xfc000000 0xfc000000 - * NVRAM (CS1) 0xfc800000 0xfc800000 - * UARTs (CS2) 0xfd000000 0xfd000000 - * Internal SRAM 0xfe000000 0xfe000000 - * M-Systems DOC (CS3) 0xff000000 0xff000000 - */ - -static __init void wire_stupidity_into_tlb(void) -{ -#ifdef CONFIG_32BIT - write_c0_wired(0); - local_flush_tlb_all(); - - /* marvell and extra space */ - add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), - 0xf4000000UL, PM_64K); - /* fpga, rtc, and uart */ - add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), - 0xfc000000UL, PM_16M); -// /* m-sys and internal SRAM */ -// add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), -// 0xfe000000UL, PM_16M); - - marvell_base = 0xf4000000; - //mv64340_sram_base = 0xfe000000; /* Currently unused */ -#endif -} - -unsigned long marvell_base = 0xf4000000L; -unsigned long ja_fpga_base = JAGUAR_ATX_CS0_ADDR; -unsigned long uart_base = 0xfd000000L; -static unsigned char *rtc_base = (unsigned char*) 0xfc800000L; - -EXPORT_SYMBOL(marvell_base); - -static __init int per_cpu_mappings(void) -{ - marvell_base = (unsigned long) ioremap(0xf4000000, 0x10000); - ja_fpga_base = (unsigned long) ioremap(JAGUAR_ATX_CS0_ADDR, 0x1000); - uart_base = (unsigned long) ioremap(0xfd000000UL, 0x1000); - rtc_base = ioremap(0xfc000000UL, 0x8000); - // ioremap(0xfe000000, 32 << 20); - write_c0_wired(0); - local_flush_tlb_all(); - ja_setup_console(); - - return 0; -} -arch_initcall(per_cpu_mappings); - -unsigned long m48t37y_get_time(void) -{ - unsigned int year, month, day, hour, min, sec; - unsigned long flags; - - spin_lock_irqsave(&rtc_lock, flags); - /* stop the update */ - rtc_base[0x7ff8] = 0x40; - - year = BCD2BIN(rtc_base[0x7fff]); - year += BCD2BIN(rtc_base[0x7ff1]) * 100; - - month = BCD2BIN(rtc_base[0x7ffe]); - - day = BCD2BIN(rtc_base[0x7ffd]); - - hour = BCD2BIN(rtc_base[0x7ffb]); - min = BCD2BIN(rtc_base[0x7ffa]); - sec = BCD2BIN(rtc_base[0x7ff9]); - - /* start the update */ - rtc_base[0x7ff8] = 0x00; - spin_unlock_irqrestore(&rtc_lock, flags); - - return mktime(year, month, day, hour, min, sec); -} - -int m48t37y_set_time(unsigned long sec) -{ - struct rtc_time tm; - unsigned long flags; - - /* convert to a more useful format -- note months count from 0 */ - to_tm(sec, &tm); - tm.tm_mon += 1; - - spin_lock_irqsave(&rtc_lock, flags); - /* enable writing */ - rtc_base[0x7ff8] = 0x80; - - /* year */ - rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100); - rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100); - - /* month */ - rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon); - - /* day */ - rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday); - - /* hour/min/sec */ - rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour); - rtc_base[0x7ffa] = BIN2BCD(tm.tm_min); - rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec); - - /* day of week -- not really used, but let's keep it up-to-date */ - rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1); - - /* disable writing */ - rtc_base[0x7ff8] = 0x00; - spin_unlock_irqrestore(&rtc_lock, flags); - - return 0; -} - -void __init plat_timer_setup(struct irqaction *irq) -{ - setup_irq(8, irq); -} - -/* - * Ugly but the least of all evils. TLB initialization did flush the TLB so - * We need to setup mappings again before we can touch the RTC. - */ -void momenco_time_init(void) -{ - wire_stupidity_into_tlb(); - - mips_hpt_frequency = cpu_clock / 2; - - rtc_mips_get_time = m48t37y_get_time; - rtc_mips_set_time = m48t37y_set_time; -} - -static struct resource mv_pci_io_mem0_resource = { - .name = "MV64340 PCI0 IO MEM", - .flags = IORESOURCE_IO -}; - -static struct resource mv_pci_mem0_resource = { - .name = "MV64340 PCI0 MEM", - .flags = IORESOURCE_MEM -}; - -static struct mv_pci_controller mv_bus0_controller = { - .pcic = { - .pci_ops = &mv_pci_ops, - .mem_resource = &mv_pci_mem0_resource, - .io_resource = &mv_pci_io_mem0_resource, - }, - .config_addr = MV64340_PCI_0_CONFIG_ADDR, - .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG, -}; - -static uint32_t mv_io_base, mv_io_size; - -static void ja_pci0_init(void) -{ - uint32_t mem0_base, mem0_size; - uint32_t io_base, io_size; - - io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16; - io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16; - mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16; - mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16; - - mv_pci_io_mem0_resource.start = 0; - mv_pci_io_mem0_resource.end = io_size - 1; - mv_pci_mem0_resource.start = mem0_base; - mv_pci_mem0_resource.end = mem0_base + mem0_size - 1; - mv_bus0_controller.pcic.mem_offset = mem0_base; - mv_bus0_controller.pcic.io_offset = 0; - - ioport_resource.end = io_size - 1; - - register_pci_controller(&mv_bus0_controller.pcic); - - mv_io_base = io_base; - mv_io_size = io_size; -} - -static struct resource mv_pci_io_mem1_resource = { - .name = "MV64340 PCI1 IO MEM", - .flags = IORESOURCE_IO -}; - -static struct resource mv_pci_mem1_resource = { - .name = "MV64340 PCI1 MEM", - .flags = IORESOURCE_MEM -}; - -static struct mv_pci_controller mv_bus1_controller = { - .pcic = { - .pci_ops = &mv_pci_ops, - .mem_resource = &mv_pci_mem1_resource, - .io_resource = &mv_pci_io_mem1_resource, - }, - .config_addr = MV64340_PCI_1_CONFIG_ADDR, - .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG, -}; - -static __init void ja_pci1_init(void) -{ - uint32_t mem0_base, mem0_size; - uint32_t io_base, io_size; - - io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16; - io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16; - mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16; - mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16; - - /* - * Here we assume the I/O window of second bus to be contiguous with - * the first. A gap is no problem but would waste address space for - * remapping the port space. - */ - mv_pci_io_mem1_resource.start = mv_io_size; - mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1; - mv_pci_mem1_resource.start = mem0_base; - mv_pci_mem1_resource.end = mem0_base + mem0_size - 1; - mv_bus1_controller.pcic.mem_offset = mem0_base; - mv_bus1_controller.pcic.io_offset = 0; - - ioport_resource.end = io_base + io_size -mv_io_base - 1; - - register_pci_controller(&mv_bus1_controller.pcic); - - mv_io_size = io_base + io_size - mv_io_base; -} - -static __init int __init ja_pci_init(void) -{ - unsigned long io_v_base; - uint32_t enable; - - enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE); - - /* - * We require at least one enabled I/O or PCI memory window or we - * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3. - */ - if (enable & (0x01 << 9) || enable & (0x01 << 10)) - ja_pci0_init(); - - if (enable & (0x01 << 14) || enable & (0x01 << 15)) - ja_pci1_init(); - - if (mv_io_size) { - io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size); - if (!io_v_base) - panic("Could not ioremap I/O port range"); - - set_io_port_base(io_v_base); - } - - return 0; -} - -arch_initcall(ja_pci_init); - -void __init plat_mem_setup(void) -{ - unsigned int tmpword; - - board_time_init = momenco_time_init; - - _machine_restart = momenco_jaguar_restart; - _machine_halt = momenco_jaguar_halt; - pm_power_off = momenco_jaguar_power_off; - - /* - * initrd_start = (unsigned long)jaguar_initrd_start; - * initrd_end = (unsigned long)jaguar_initrd_start + (ulong)jaguar_initrd_size; - * initrd_below_start_ok = 1; - */ - - wire_stupidity_into_tlb(); - - /* - * shut down ethernet ports, just to be sure our memory doesn't get - * corrupted by random ethernet traffic. - */ - MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8); - MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8); - MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8); - MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8); - MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8); - MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8); - while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff); - while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff); - while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff); - while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff); - while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff); - while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff); - MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0), - MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1); - MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1), - MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1); - MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2), - MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1); - - /* Turn off the Bit-Error LED */ - JAGUAR_FPGA_WRITE(0x80, CLR); - - tmpword = JAGUAR_FPGA_READ(BOARDREV); - if (tmpword < 26) - printk("Momentum Jaguar-ATX: Board Assembly Rev. %c\n", - 'A'+tmpword); - else - printk("Momentum Jaguar-ATX: Board Assembly Revision #0x%x\n", - tmpword); - - tmpword = JAGUAR_FPGA_READ(FPGA_REV); - printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15); - tmpword = JAGUAR_FPGA_READ(RESET_STATUS); - printk("Reset reason: 0x%x\n", tmpword); - switch (tmpword) { - case 0x1: - printk(" - Power-up reset\n"); - break; - case 0x2: - printk(" - Push-button reset\n"); - break; - case 0x8: - printk(" - Watchdog reset\n"); - break; - case 0x10: - printk(" - JTAG reset\n"); - break; - default: - printk(" - Unknown reset cause\n"); - } - reset_reason = tmpword; - JAGUAR_FPGA_WRITE(0xff, RESET_STATUS); - - tmpword = JAGUAR_FPGA_READ(BOARD_STATUS); - printk("Board Status register: 0x%02x\n", tmpword); - printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); - printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); - - /* 256MiB of RM9000x2 DDR */ -// add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM); - - /* 128MiB of MV-64340 DDR */ -// add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM); - - /* XXX Memory configuration should be picked up from PMON2k */ -#ifdef CONFIG_JAGUAR_DMALOW - printk("Jaguar ATX DMA-low mode set\n"); - add_memory_region(0x00000000, 0x08000000, BOOT_MEM_RAM); - add_memory_region(0x08000000, 0x10000000, BOOT_MEM_RAM); -#else - /* 128MiB of MV-64340 DDR RAM */ - printk("Jaguar ATX DMA-low mode is not set\n"); - add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM); -#endif - -#ifdef GEMDEBUG_TRACEBUFFER - { - unsigned int tbControl; - tbControl = - 0 << 26 | /* post trigger delay 0 */ - 0x2 << 16 | /* sequential trace mode */ - // 0x0 << 16 | /* non-sequential trace mode */ - // 0xf << 4 | /* watchpoints disabled */ - 2 << 2 | /* armed */ - 2 ; /* interrupt disabled */ - printk ("setting tbControl = %08lx\n", tbControl); - write_32bit_cp0_set1_register($22, tbControl); - __asm__ __volatile__(".set noreorder\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - ".set reorder\n\t"); - - } -#endif -} diff --git a/arch/mips/momentum/ocelot_g/Makefile b/arch/mips/momentum/ocelot_g/Makefile deleted file mode 100644 index c0a0030d949d..000000000000 --- a/arch/mips/momentum/ocelot_g/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for Momentum Computer's Ocelot-G board. -# - -obj-y += irq.o gt-irq.o prom.o reset.o setup.o -obj-$(CONFIG_KGDB) += dbg_io.o diff --git a/arch/mips/momentum/ocelot_g/dbg_io.c b/arch/mips/momentum/ocelot_g/dbg_io.c deleted file mode 100644 index 32d6fb4ee679..000000000000 --- a/arch/mips/momentum/ocelot_g/dbg_io.c +++ /dev/null @@ -1,121 +0,0 @@ - -#include <asm/serial.h> /* For the serial port location and base baud */ - -/* --- CONFIG --- */ - -typedef unsigned char uint8; -typedef unsigned int uint32; - -/* --- END OF CONFIG --- */ - -#define UART16550_BAUD_2400 2400 -#define UART16550_BAUD_4800 4800 -#define UART16550_BAUD_9600 9600 -#define UART16550_BAUD_19200 19200 -#define UART16550_BAUD_38400 38400 -#define UART16550_BAUD_57600 57600 -#define UART16550_BAUD_115200 115200 - -#define UART16550_PARITY_NONE 0 -#define UART16550_PARITY_ODD 0x08 -#define UART16550_PARITY_EVEN 0x18 -#define UART16550_PARITY_MARK 0x28 -#define UART16550_PARITY_SPACE 0x38 - -#define UART16550_DATA_5BIT 0x0 -#define UART16550_DATA_6BIT 0x1 -#define UART16550_DATA_7BIT 0x2 -#define UART16550_DATA_8BIT 0x3 - -#define UART16550_STOP_1BIT 0x0 -#define UART16550_STOP_2BIT 0x4 - -/* ----------------------------------------------------- */ - -/* === CONFIG === */ - -/* [jsun] we use the second serial port for kdb */ -#define BASE OCELOT_SERIAL1_BASE -#define MAX_BAUD OCELOT_BASE_BAUD - -/* === END OF CONFIG === */ - -#define REG_OFFSET 4 - -/* register offset */ -#define OFS_RCV_BUFFER 0 -#define OFS_TRANS_HOLD 0 -#define OFS_SEND_BUFFER 0 -#define OFS_INTR_ENABLE (1*REG_OFFSET) -#define OFS_INTR_ID (2*REG_OFFSET) -#define OFS_DATA_FORMAT (3*REG_OFFSET) -#define OFS_LINE_CONTROL (3*REG_OFFSET) -#define OFS_MODEM_CONTROL (4*REG_OFFSET) -#define OFS_RS232_OUTPUT (4*REG_OFFSET) -#define OFS_LINE_STATUS (5*REG_OFFSET) -#define OFS_MODEM_STATUS (6*REG_OFFSET) -#define OFS_RS232_INPUT (6*REG_OFFSET) -#define OFS_SCRATCH_PAD (7*REG_OFFSET) - -#define OFS_DIVISOR_LSB (0*REG_OFFSET) -#define OFS_DIVISOR_MSB (1*REG_OFFSET) - - -/* memory-mapped read/write of the port */ -#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) -#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) - -void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) -{ - /* disable interrupts */ - UART16550_WRITE(OFS_INTR_ENABLE, 0); - - /* set up baud rate */ - { - uint32 divisor; - - /* set DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x80); - - /* set divisor */ - divisor = MAX_BAUD / baud; - UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); - UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); - - /* clear DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x0); - } - - /* set data format */ - UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); -} - -static int remoteDebugInitialized = 0; - -uint8 getDebugChar(void) -{ - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_38400, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); - return UART16550_READ(OFS_RCV_BUFFER); -} - - -int putDebugChar(uint8 byte) -{ - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_38400, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); - UART16550_WRITE(OFS_SEND_BUFFER, byte); - return 1; -} diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c deleted file mode 100644 index e5576bd50fa9..000000000000 --- a/arch/mips/momentum/ocelot_g/gt-irq.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * - * Copyright 2002 Momentum Computer - * Author: mdharm@momenco.com - * - * arch/mips/momentum/ocelot_g/gt_irq.c - * Interrupt routines for gt64240. Currently it only handles timer irq. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/kernel_stat.h> -#include <asm/gt64240.h> -#include <asm/io.h> - -unsigned long bus_clock; - -/* - * These are interrupt handlers for the GT on-chip interrupts. They - * all come in to the MIPS on a single interrupt line, and have to - * be handled and ack'ed differently than other MIPS interrupts. - */ - -#if 0 - -struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; -void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); - -/* - * Hooks IRQ handler to the system. When the system is interrupted - * the interrupt service routine is called. - * - * Inputs : - * int_cause - The interrupt cause number. In EVB64120 two parameters - * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. - * bit_num - Indicates which bit number in the cause register - * isr_ptr - Pointer to the interrupt service routine - */ -void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr) -{ - irq_handlers[int_cause][bit_num].routine = isr_ptr; -} - - -/* - * Enables the IRQ on Galileo Chip - * - * Inputs : - * int_cause - The interrupt cause number. In EVB64120 two parameters - * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. - * bit_num - Indicates which bit number in the cause register - * - * Outputs : - * 1 if successful, 0 if failure - */ -int enable_galileo_irq(int int_cause, int bit_num) -{ - if (int_cause == INT_CAUSE_MAIN) - SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num)); - else if (int_cause == INT_CAUSE_HIGH) - SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, - (1 << bit_num)); - else - return 0; - - return 1; -} - -/* - * Disables the IRQ on Galileo Chip - * - * Inputs : - * int_cause - The interrupt cause number. In EVB64120 two parameters - * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. - * bit_num - Indicates which bit number in the cause register - * - * Outputs : - * 1 if successful, 0 if failure - */ -int disable_galileo_irq(int int_cause, int bit_num) -{ - if (int_cause == INT_CAUSE_MAIN) - RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, - (1 << bit_num)); - else if (int_cause == INT_CAUSE_HIGH) - RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, - (1 << bit_num)); - else - return 0; - return 1; -} -#endif /* 0 */ - -/* - * Interrupt handler for interrupts coming from the Galileo chip via P0_INT#. - * - * We route the timer interrupt to P0_INT# (IRQ 6), and that's all this - * routine can handle, for now. - * - * In the future, we'll route more interrupts to this pin, and that's why - * we keep this particular structure in the function. - */ - -static irqreturn_t gt64240_p0int_irq(int irq, void *dev) -{ - uint32_t irq_src, irq_src_mask; - int handled; - - /* get the low interrupt cause register */ - irq_src = MV_READ(LOW_INTERRUPT_CAUSE_REGISTER); - - /* get the mask register for this pin */ - irq_src_mask = MV_READ(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW); - - /* mask off only the interrupts we're interested in */ - irq_src = irq_src & irq_src_mask; - - handled = IRQ_NONE; - - /* Check for timer interrupt */ - if (irq_src & 0x00000100) { - handled = IRQ_HANDLED; - irq_src &= ~0x00000100; - - /* Clear any pending cause bits */ - MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0); - - /* handle the timer call */ - do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - } - - if (irq_src) { - printk(KERN_INFO - "UNKNOWN P0_INT# interrupt received, irq_src=0x%x\n", - irq_src); - } - - return handled; -} - -/* - * Initializes timer using galileo's built in timer. - */ - -/* - * This will ignore the standard MIPS timer interrupt handler - * that is passed in as *irq (=irq0 in ../kernel/time.c). - * We will do our own timer interrupt handling. - */ -void gt64240_time_init(void) -{ - static struct irqaction timer; - - /* Stop the timer -- we'll use timer #0 */ - MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x0); - - /* Load timer value for 100 Hz */ - MV_WRITE(TIMER_COUNTER0, bus_clock / 100); - - /* - * Create the IRQ structure entry for the timer. Since we're too early - * in the boot process to use the "request_irq()" call, we'll hard-code - * the values to the correct interrupt line. - */ - timer.handler = >64240_p0int_irq; - timer.flags = IRQF_SHARED | IRQF_DISABLED; - timer.name = "timer"; - timer.dev_id = NULL; - timer.next = NULL; - timer.mask = CPU_MASK_NONE; - irq_desc[6].action = &timer; - - enable_irq(6); - - /* Clear any pending cause bits */ - MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0); - - /* Enable the interrupt for timer 0 */ - MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_MASK, 0x1); - - /* Enable the timer interrupt for GT-64240 pin P0_INT# */ - MV_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0x100); - - /* Configure and start the timer */ - MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x3); -} - -void gt64240_irq_init(void) -{ -#if 0 - int i, j; - - /* Reset irq handlers pointers to NULL */ - for (i = 0; i < MAX_CAUSE_REGS; i++) { - for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) { - irq_handlers[i][j].next = NULL; - irq_handlers[i][j].sync = 0; - irq_handlers[i][j].routine = NULL; - irq_handlers[i][j].data = NULL; - } - } -#endif /* 0 */ -} diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c deleted file mode 100644 index 273541fe7087..000000000000 --- a/arch/mips/momentum/ocelot_g/irq.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2000 RidgeRun, Inc. - * Author: RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * Copyright (C) 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/kernel_stat.h> -#include <linux/module.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/timex.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/bitops.h> -#include <asm/bootinfo.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/irq_cpu.h> -#include <asm/mipsregs.h> -#include <asm/system.h> - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_cause() & read_c0_status(); - - if (pending & STATUSF_IP2) - do_IRQ(2); - else if (pending & STATUSF_IP3) - do_IRQ(3); - else if (pending & STATUSF_IP4) - do_IRQ(4); - else if (pending & STATUSF_IP5) - do_IRQ(5); - else if (pending & STATUSF_IP6) - do_IRQ(6); - else if (pending & STATUSF_IP7) - do_IRQ(7); - else { - /* - * Now look at the extended interrupts - */ - pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16; - - if (pending & STATUSF_IP8) - do_IRQ(8); - else if (pending & STATUSF_IP9) - do_IRQ(9); - else if (pending & STATUSF_IP10) - do_IRQ(10); - else if (pending & STATUSF_IP11) - do_IRQ(11); - else - spurious_interrupt(); - } -} - -extern void gt64240_irq_init(void); - -void __init arch_init_irq(void) -{ - /* - * Clear all of the interrupts while we change the able around a bit. - * int-handler is not on bootstrap - */ - clear_c0_status(ST0_IM); - local_irq_disable(); - - mips_cpu_irq_init(); - rm7k_cpu_irq_init(); - - gt64240_irq_init(); -} diff --git a/arch/mips/momentum/ocelot_g/ocelot_pld.h b/arch/mips/momentum/ocelot_g/ocelot_pld.h deleted file mode 100644 index 95e0534026d0..000000000000 --- a/arch/mips/momentum/ocelot_g/ocelot_pld.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Ocelot Board Register Definitions - * - * (C) 2001 Red Hat, Inc. - * - * GPL'd - */ -#ifndef __MOMENCO_OCELOT_PLD_H__ -#define __MOMENCO_OCELOT_PLD_H__ - -#define OCELOT_CS0_ADDR (0xfc000000) - -#define OCELOT_REG_BOARDREV (0) -#define OCELOT_REG_PLD1_ID (1) -#define OCELOT_REG_PLD2_ID (2) -#define OCELOT_REG_RESET_STATUS (3) -#define OCELOT_REG_BOARD_STATUS (4) -#define OCELOT_REG_CPCI_ID (5) -#define OCELOT_REG_I2C_CTRL (8) -#define OCELOT_REG_EEPROM_MODE (9) -#define OCELOT_REG_INTMASK (10) -#define OCELOT_REG_INTSTATUS (11) -#define OCELOT_REG_INTSET (12) -#define OCELOT_REG_INTCLR (13) - -#define __PLD_REG_TO_ADDR(reg) ((void *) OCELOT_CS0_ADDR + OCELOT_REG_##reg) -#define OCELOT_PLD_WRITE(x, reg) writeb(x, __PLD_REG_TO_ADDR(reg)) -#define OCELOT_PLD_READ(reg) readb(__PLD_REG_TO_ADDR(reg)) - -#endif /* __MOMENCO_OCELOT_PLD_H__ */ diff --git a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c deleted file mode 100644 index 836d0830720d..000000000000 --- a/arch/mips/momentum/ocelot_g/prom.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2002 Momentum Computer Inc. - * Author: Matthew Dharm <mdharm@momenco.com> - * - * Based on Ocelot Linux port, which is - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include <linux/init.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/bootmem.h> - -#include <asm/addrspace.h> -#include <asm/bootinfo.h> -#include <asm/pmon.h> -#include <asm/gt64240.h> - -#include "ocelot_pld.h" - -struct callvectors* debug_vectors; - -extern unsigned long marvell_base; -extern unsigned long bus_clock; - -#ifdef CONFIG_GALILEO_GT64240_ETH -extern unsigned char prom_mac_addr_base[6]; -#endif - -const char *get_system_type(void) -{ - return "Momentum Ocelot"; -} - -void __init prom_init(void) -{ - int argc = fw_arg0; - char **arg = (char **) fw_arg1; - char **env = (char **) fw_arg2; - struct callvectors *cv = (struct callvectors *) fw_arg3; - int i; - - /* save the PROM vectors for debugging use */ - debug_vectors = cv; - - /* arg[0] is "g", the rest is boot parameters */ - arcs_cmdline[0] = '\0'; - for (i = 1; i < argc; i++) { - if (strlen(arcs_cmdline) + strlen(arg[i] + 1) - >= sizeof(arcs_cmdline)) - break; - strcat(arcs_cmdline, arg[i]); - strcat(arcs_cmdline, " "); - } - - mips_machgroup = MACH_GROUP_MOMENCO; - mips_machtype = MACH_MOMENCO_OCELOT_G; - -#ifdef CONFIG_GALILEO_GT64240_ETH - /* get the base MAC address for on-board ethernet ports */ - memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6); -#endif - - while (*env) { - if (strncmp("gtbase", *env, strlen("gtbase")) == 0) { - marvell_base = simple_strtol(*env + strlen("gtbase="), - NULL, 16); - } - if (strncmp("busclock", *env, strlen("busclock")) == 0) { - bus_clock = simple_strtol(*env + strlen("busclock="), - NULL, 10); - } - env++; - } -} - -void __init prom_free_prom_memory(void) -{ -} diff --git a/arch/mips/momentum/ocelot_g/reset.c b/arch/mips/momentum/ocelot_g/reset.c deleted file mode 100644 index 3fd499adf4cf..000000000000 --- a/arch/mips/momentum/ocelot_g/reset.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Copyright (C) 1997, 2001 Ralf Baechle - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - */ -#include <linux/sched.h> -#include <linux/mm.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/reboot.h> -#include <asm/system.h> -#include <linux/delay.h> - -void momenco_ocelot_restart(char *command) -{ - void *nvram = ioremap_nocache(0x2c807000, 0x1000); - - if (!nvram) { - printk(KERN_NOTICE "ioremap of reset register failed\n"); - return; - } - writeb(0x84, nvram + 0xff7); /* Ask the NVRAM/RTC/watchdog chip to - assert reset in 1/16 second */ - mdelay(10+(1000/16)); - iounmap(nvram); - printk(KERN_NOTICE "Watchdog reset failed\n"); -} - -void momenco_ocelot_halt(void) -{ - printk(KERN_NOTICE "\n** You can safely turn off the power\n"); - while (1) - __asm__(".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); -} - -void momenco_ocelot_power_off(void) -{ - momenco_ocelot_halt(); -} diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c deleted file mode 100644 index 9db638a7982c..000000000000 --- a/arch/mips/momentum/ocelot_g/setup.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Momentum Computer Ocelot-G (CP7000G) - board dependent boot routines - * - * Copyright (C) 1996, 1997, 2001 Ralf Baechle - * Copyright (C) 2000 RidgeRun, Inc. - * Copyright (C) 2001 Red Hat, Inc. - * Copyright (C) 2002 Momentum Computer - * - * Author: Matthew Dharm, Momentum Computer - * mdharm@momenco.com - * - * Author: RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/swap.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/pm.h> -#include <linux/timex.h> -#include <linux/vmalloc.h> - -#include <asm/time.h> -#include <asm/bootinfo.h> -#include <asm/page.h> -#include <asm/io.h> -#include <asm/gt64240.h> -#include <asm/irq.h> -#include <asm/pci.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/reboot.h> -#include <linux/bootmem.h> - -#include "ocelot_pld.h" - -#ifdef CONFIG_GALILEO_GT64240_ETH -extern unsigned char prom_mac_addr_base[6]; -#endif - -unsigned long marvell_base; - -/* These functions are used for rebooting or halting the machine*/ -extern void momenco_ocelot_restart(char *command); -extern void momenco_ocelot_halt(void); -extern void momenco_ocelot_power_off(void); - -extern void gt64240_time_init(void); -extern void momenco_ocelot_irq_setup(void); - -static char reset_reason; - -static unsigned long ENTRYLO(unsigned long paddr) -{ - return ((paddr & PAGE_MASK) | - (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL | - _CACHE_UNCACHED)) >> 6; -} - -/* setup code for a handoff from a version 2 PMON 2000 PROM */ -void PMON_v2_setup(void) -{ - /* A wired TLB entry for the GT64240 and the serial port. The - GT64240 is going to be hit on every IRQ anyway - there's - absolutely no point in letting it be a random TLB entry, as - it'll just cause needless churning of the TLB. And we use - the other half for the serial port, which is just a PITA - otherwise :) - - Device Physical Virtual - GT64240 Internal Regs 0xf4000000 0xe0000000 - UARTs (CS2) 0xfd000000 0xe0001000 - */ - add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), - 0xf4000000, PM_64K); - add_wired_entry(ENTRYLO(0xfd000000), ENTRYLO(0xfd001000), - 0xfd000000, PM_4K); - - /* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM - in the CS[012] region. We can't use ioremap() yet. The NVRAM - is a ST M48T37Y, which includes NVRAM, RTC, and Watchdog functions. - - Ocelot PLD (CS0) 0xfc000000 0xe0020000 - NVRAM (CS1) 0xfc800000 0xe0030000 - */ - add_temporary_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfc010000), - 0xfc000000, PM_64K); - add_temporary_entry(ENTRYLO(0xfc800000), ENTRYLO(0xfc810000), - 0xfc800000, PM_64K); - - marvell_base = 0xf4000000; -} - -extern int rm7k_tcache_enabled; - -/* - * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache() - */ -#define Page_Invalidate_T 0x16 -static void __init setup_l3cache(unsigned long size) -{ - int register i; - - printk("Enabling L3 cache..."); - - /* Enable the L3 cache in the GT64120A's CPU Configuration register */ - MV_WRITE(0, MV_READ(0) | (1<<14)); - - /* Enable the L3 cache in the CPU */ - set_c0_config(1<<12 /* CONF_TE */); - - /* Clear the cache */ - write_c0_taglo(0); - write_c0_taghi(0); - - for (i=0; i < size; i+= 4096) { - __asm__ __volatile__ ( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (KSEG0ADDR(i)), - "i" (Page_Invalidate_T)); - } - - /* Let the RM7000 MM code know that the tertiary cache is enabled */ - rm7k_tcache_enabled = 1; - - printk("Done\n"); -} - -void __init plat_timer_setup(struct irqaction *irq) -{ -} - -void __init plat_mem_setup(void) -{ - void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache); - unsigned int tmpword; - - board_time_init = gt64240_time_init; - - _machine_restart = momenco_ocelot_restart; - _machine_halt = momenco_ocelot_halt; - pm_power_off = momenco_ocelot_power_off; - - /* - * initrd_start = (unsigned long)ocelot_initrd_start; - * initrd_end = (unsigned long)ocelot_initrd_start + (ulong)ocelot_initrd_size; - * initrd_below_start_ok = 1; - */ - - /* do handoff reconfiguration */ - PMON_v2_setup(); - -#ifdef CONFIG_GALILEO_GT64240_ETH - /* get the mac addr */ - memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6); -#endif - - /* Turn off the Bit-Error LED */ - OCELOT_PLD_WRITE(0x80, INTCLR); - - tmpword = OCELOT_PLD_READ(BOARDREV); - if (tmpword < 26) - printk("Momenco Ocelot-G: Board Assembly Rev. %c\n", 'A'+tmpword); - else - printk("Momenco Ocelot-G: Board Assembly Revision #0x%x\n", tmpword); - - tmpword = OCELOT_PLD_READ(PLD1_ID); - printk("PLD 1 ID: %d.%d\n", tmpword>>4, tmpword&15); - tmpword = OCELOT_PLD_READ(PLD2_ID); - printk("PLD 2 ID: %d.%d\n", tmpword>>4, tmpword&15); - tmpword = OCELOT_PLD_READ(RESET_STATUS); - printk("Reset reason: 0x%x\n", tmpword); - reset_reason = tmpword; - OCELOT_PLD_WRITE(0xff, RESET_STATUS); - - tmpword = OCELOT_PLD_READ(BOARD_STATUS); - printk("Board Status register: 0x%02x\n", tmpword); - printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); - printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); - printk(" - Tulip PHY %s connected\n", (tmpword&0x10)?"is":"not"); - printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1); - printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3))); - - if (tmpword&12) - l3func((1<<(((tmpword&12) >> 2)+20))); - - switch(tmpword &3) { - case 3: - /* 512MiB -- two banks of 256MiB */ - add_memory_region( 0x0<<20, 0x100<<20, BOOT_MEM_RAM); -/* - add_memory_region(0x100<<20, 0x100<<20, BOOT_MEM_RAM); -*/ - break; - case 2: - /* 256MiB -- two banks of 128MiB */ - add_memory_region( 0x0<<20, 0x80<<20, BOOT_MEM_RAM); - add_memory_region(0x80<<20, 0x80<<20, BOOT_MEM_RAM); - break; - case 1: - /* 128MiB -- 64MiB per bank */ - add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM); - add_memory_region(0x40<<20, 0x40<<20, BOOT_MEM_RAM); - break; - case 0: - /* 64MiB */ - add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM); - break; - } - - /* FIXME: Fix up the DiskOnChip mapping */ - MV_WRITE(0x468, 0xfef73); -} - -/* This needs to be one of the first initcalls, because no I/O port access - can work before this */ - -static int io_base_ioremap(void) -{ - /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */ - unsigned long io_remap_range; - - io_remap_range = (unsigned long) ioremap(0xc0000000, 0x30000000); - if (!io_remap_range) - panic("Could not ioremap I/O port range"); - - set_io_port_base(io_remap_range - 0xc0000000); - - return 0; -} - -module_init(io_base_ioremap); diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index df487c063b1d..aba3dbf47eda 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -30,11 +30,9 @@ obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o -obj-$(CONFIG_MOMENCO_JAGUAR_ATX)+= fixup-jaguar.o obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o obj-$(CONFIG_MOMENCO_OCELOT_3) += fixup-ocelot3.o obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup-ocelot-c.o pci-ocelot-c.o -obj-$(CONFIG_MOMENCO_OCELOT_G) += fixup-ocelot-g.o pci-ocelot-g.o obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \ pci-yosemite.o obj-$(CONFIG_SGI_IP27) += ops-bridge.o pci-ip27.o diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c index 7d5f6bbf7a9d..d57ffd7242ca 100644 --- a/arch/mips/pci/fixup-cobalt.c +++ b/arch/mips/pci/fixup-cobalt.c @@ -17,9 +17,7 @@ #include <asm/io.h> #include <asm/gt64120.h> -#include <asm/mach-cobalt/cobalt.h> - -extern int cobalt_board_id; +#include <cobalt.h> static void qube_raq_galileo_early_fixup(struct pci_dev *dev) { @@ -115,6 +113,27 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111, qube_raq_galileo_fixup); +int cobalt_board_id; + +static void qube_raq_via_board_id_fixup(struct pci_dev *dev) +{ + u8 id; + int retval; + + retval = pci_read_config_byte(dev, VIA_COBALT_BRD_ID_REG, &id); + if (retval) { + panic("Cannot read board ID"); + return; + } + + cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(id); + + printk(KERN_INFO "Cobalt board ID: %d\n", cobalt_board_id); +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, + qube_raq_via_board_id_fixup); + static char irq_tab_qube1[] __initdata = { [COBALT_PCICONF_CPU] = 0, [COBALT_PCICONF_ETH0] = COBALT_QUBE1_ETH0_IRQ, diff --git a/arch/mips/pci/fixup-jaguar.c b/arch/mips/pci/fixup-jaguar.c deleted file mode 100644 index 6c5e1d47179c..000000000000 --- a/arch/mips/pci/fixup-jaguar.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Marvell MV64340 interrupt fixup code. - * - * Marvell wants an NDA for their docs so this was written without - * documentation. You've been warned. - * - * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org) - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/pci.h> - -#include <asm/mipsregs.h> - -/* - * WARNING: Example of how _NOT_ to do it. - */ -int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int bus = dev->bus->number; - - if (bus == 0 && slot == 1) - return 3; /* PCI-X A */ - if (bus == 0 && slot == 2) - return 4; /* PCI-X B */ - if (bus == 1 && slot == 1) - return 5; /* PCI A */ - if (bus == 1 && slot == 2) - return 6; /* PCI B */ - -return 0; - panic("Whooops in pcibios_map_irq"); -} - -/* Do platform specific device initialization at pci_enable_device() time */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - return 0; -} diff --git a/arch/mips/pci/fixup-ocelot-g.c b/arch/mips/pci/fixup-ocelot-g.c deleted file mode 100644 index d7a652e326c5..000000000000 --- a/arch/mips/pci/fixup-ocelot-g.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org) - */ -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/init.h> - -int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int bus = dev->bus->number; - - if (bus == 0 && slot == 1) /* Intel 82543 Gigabit MAC */ - return 2; /* irq_nr is 2 for INT0 */ - - if (bus == 0 && slot == 2) /* Intel 82543 Gigabit MAC */ - return 3; /* irq_nr is 3 for INT1 */ - - if (bus == 1 && slot == 3) /* Intel 21555 bridge */ - return 5; /* irq_nr is 8 for INT6 */ - - if (bus == 1 && slot == 4) /* PMC Slot */ - return 9; /* irq_nr is 9 for INT7 */ - - return -1; -} - -/* Do platform specific device initialization at pci_enable_device() time */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - return 0; -} diff --git a/arch/mips/pci/pci-ocelot-g.c b/arch/mips/pci/pci-ocelot-g.c deleted file mode 100644 index 1e3430154fa0..000000000000 --- a/arch/mips/pci/pci-ocelot-g.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) - * - * This doesn't really fly - but I don't have a GT64240 system for testing. - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <asm/gt64240.h> - -/* - * We assume these address ranges have been programmed into the GT-64240 by - * the firmware. PMON in case of the Ocelot G does that. Note the size of - * the I/O range is completly stupid; I/O mappings are limited to at most - * 256 bytes by the PCI spec and deprecated; and just to make things worse - * apparently many devices don't decode more than 64k of I/O space. - */ - -#define gt_io_size 0x20000000UL -#define gt_io_base 0xe0000000UL - -static struct resource gt_pci_mem0_resource = { - .name = "MV64240 PCI0 MEM", - .start = 0xc0000000UL, - .end = 0xcfffffffUL, - .flags = IORESOURCE_MEM -}; - -static struct resource gt_pci_io_mem0_resource = { - .name = "MV64240 PCI0 IO MEM", - .start = 0xe0000000UL, - .end = 0xefffffffUL, - .flags = IORESOURCE_IO -}; - -static struct mv_pci_controller gt_bus0_controller = { - .pcic = { - .pci_ops = &mv_pci_ops, - .mem_resource = >_pci_mem0_resource, - .mem_offset = 0xc0000000UL, - .io_resource = >_pci_io_mem0_resource, - .io_offset = 0x00000000UL - }, - .config_addr = PCI_0CONFIGURATION_ADDRESS, - .config_vreg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, -}; - -static struct resource gt_pci_mem1_resource = { - .name = "MV64240 PCI1 MEM", - .start = 0xd0000000UL, - .end = 0xdfffffffUL, - .flags = IORESOURCE_MEM -}; - -static struct resource gt_pci_io_mem1_resource = { - .name = "MV64240 PCI1 IO MEM", - .start = 0xf0000000UL, - .end = 0xffffffffUL, - .flags = IORESOURCE_IO -}; - -static struct mv_pci_controller gt_bus1_controller = { - .pcic = { - .pci_ops = &mv_pci_ops, - .mem_resource = >_pci_mem1_resource, - .mem_offset = 0xd0000000UL, - .io_resource = >_pci_io_mem1_resource, - .io_offset = 0x10000000UL - }, - .config_addr = PCI_1CONFIGURATION_ADDRESS, - .config_vreg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER, -}; - -static __init int __init ocelot_g_pci_init(void) -{ - unsigned long io_v_base; - - if (gt_io_size) { - io_v_base = (unsigned long) ioremap(gt_io_base, gt_io_size); - if (!io_v_base) - panic("Could not ioremap I/O port range"); - - set_io_port_base(io_v_base); - } - - register_pci_controller(>_bus0_controller.pcic); - register_pci_controller(>_bus1_controller.pcic); - - return 0; -} - -arch_initcall(ocelot_g_pci_init); diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile index b6d649241dc1..1fb3e353e212 100644 --- a/arch/mips/sgi-ip22/Makefile +++ b/arch/mips/sgi-ip22/Makefile @@ -4,6 +4,6 @@ # obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \ - ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o + ip22-time.o ip22-nvram.o ip22-platform.o ip22-reset.o ip22-setup.o obj-$(CONFIG_EISA) += ip22-eisa.o diff --git a/arch/mips/sgi-ip22/ip22-platform.c b/arch/mips/sgi-ip22/ip22-platform.c new file mode 100644 index 000000000000..78b608d2d4e1 --- /dev/null +++ b/arch/mips/sgi-ip22/ip22-platform.c @@ -0,0 +1,177 @@ +#include <linux/init.h> +#include <linux/if_ether.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <asm/paccess.h> +#include <asm/sgi/ip22.h> +#include <asm/sgi/hpc3.h> +#include <asm/sgi/mc.h> +#include <asm/sgi/seeq.h> +#include <asm/sgi/wd.h> + +static struct resource sgiwd93_0_resources[] = { + { + .name = "eth0 irq", + .start = SGI_WD93_0_IRQ, + .end = SGI_WD93_0_IRQ, + .flags = IORESOURCE_IRQ + } +}; + +static struct sgiwd93_platform_data sgiwd93_0_pd = { + .unit = 0, + .irq = SGI_WD93_0_IRQ, +}; + +static struct platform_device sgiwd93_0_device = { + .name = "sgiwd93", + .id = 0, + .num_resources = ARRAY_SIZE(sgiwd93_0_resources), + .resource = sgiwd93_0_resources, + .dev = { + .platform_data = &sgiwd93_0_pd, + }, +}; + +static struct resource sgiwd93_1_resources[] = { + { + .name = "eth0 irq", + .start = SGI_WD93_1_IRQ, + .end = SGI_WD93_1_IRQ, + .flags = IORESOURCE_IRQ + } +}; + +static struct sgiwd93_platform_data sgiwd93_1_pd = { + .unit = 1, + .irq = SGI_WD93_1_IRQ, +}; + +static struct platform_device sgiwd93_1_device = { + .name = "sgiwd93", + .id = 1, + .num_resources = ARRAY_SIZE(sgiwd93_1_resources), + .resource = sgiwd93_1_resources, + .dev = { + .platform_data = &sgiwd93_1_pd, + }, +}; + +/* + * Create a platform device for the GPI port that receives the + * image data from the embedded camera. + */ +static int __init sgiwd93_devinit(void) +{ + int res; + + sgiwd93_0_pd.hregs = &hpc3c0->scsi_chan0; + sgiwd93_0_pd.wdregs = (unsigned char *) hpc3c0->scsi0_ext; + + res = platform_device_register(&sgiwd93_0_device); + if (res) + return res; + + if (!ip22_is_fullhouse()) + return 0; + + sgiwd93_1_pd.hregs = &hpc3c0->scsi_chan1; + sgiwd93_1_pd.wdregs = (unsigned char *) hpc3c0->scsi1_ext; + + return platform_device_register(&sgiwd93_1_device); +} + +device_initcall(sgiwd93_devinit); + +static struct resource sgiseeq_0_resources[] = { + { + .name = "eth0 irq", + .start = SGI_ENET_IRQ, + .end = SGI_ENET_IRQ, + .flags = IORESOURCE_IRQ + } +}; + +static struct sgiseeq_platform_data eth0_pd; + +static struct platform_device eth0_device = { + .name = "sgiseeq", + .id = 0, + .num_resources = ARRAY_SIZE(sgiseeq_0_resources), + .resource = sgiseeq_0_resources, + .dev = { + .platform_data = ð0_pd, + }, +}; + +static struct resource sgiseeq_1_resources[] = { + { + .name = "eth1 irq", + .start = SGI_GIO_0_IRQ, + .end = SGI_GIO_0_IRQ, + .flags = IORESOURCE_IRQ + } +}; + +static struct sgiseeq_platform_data eth1_pd; + +static struct platform_device eth1_device = { + .name = "sgiseeq", + .id = 1, + .num_resources = ARRAY_SIZE(sgiseeq_1_resources), + .resource = sgiseeq_1_resources, + .dev = { + .platform_data = ð1_pd, + }, +}; + +/* + * Create a platform device for the GPI port that receives the + * image data from the embedded camera. + */ +static int __init sgiseeq_devinit(void) +{ + unsigned int tmp; + int res, i; + + eth0_pd.hpc = hpc3c0; + eth0_pd.irq = SGI_ENET_IRQ; +#define EADDR_NVOFS 250 + for (i = 0; i < 3; i++) { + unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i); + + eth0_pd.mac[2 * i] = tmp >> 8; + eth0_pd.mac[2 * i + 1] = tmp & 0xff; + } + + res = platform_device_register(ð0_device); + if (res) + return res; + + /* Second HPC is missing? */ + if (ip22_is_fullhouse() || + !get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1])) + return 0; + + sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 | SGIMC_GIOPAR_EXP164 | + SGIMC_GIOPAR_HPC264; + hpc3c1->pbus_piocfg[0][0] = 0x3ffff; + /* interrupt/config register on Challenge S Mezz board */ + hpc3c1->pbus_extregs[0][0] = 0x30; + + eth1_pd.hpc = hpc3c1; + eth1_pd.irq = SGI_GIO_0_IRQ; +#define EADDR_NVOFS 250 + for (i = 0; i < 3; i++) { + unsigned short tmp = ip22_eeprom_read(&hpc3c1->eeprom, + EADDR_NVOFS / 2 + i); + + eth1_pd.mac[2 * i] = tmp >> 8; + eth1_pd.mac[2 * i + 1] = tmp & 0xff; + } + + return platform_device_register(ð1_device); +} + +device_initcall(sgiseeq_devinit); diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index ccc5410af996..56d3c0dcd2b8 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -389,6 +389,9 @@ config NOT_COHERENT_CACHE bool depends on 4xx || 8xx || E200 default y + +config CONFIG_CHECK_CACHE_COHERENCY + bool endmenu source "init/Kconfig" @@ -451,7 +454,7 @@ config ARCH_ENABLE_MEMORY_HOTPLUG config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on PPC_MULTIPLATFORM && EXPERIMENTAL + depends on (PPC_PRPMC2800 || PPC_MULTIPLATFORM) && EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 81a531d84ff9..d6014a67694b 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE) CPPFLAGS_vmlinux.lds := -Upowerpc -BOOT_TARGETS = zImage zImage.initrd uImage +BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage PHONY += $(BOOT_TARGETS) diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 5c384aad1184..d4f9fef7f9e9 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -43,9 +43,9 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \ src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c \ - 44x.c ebony.c + 44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ - cuboot-ebony.c treeboot-ebony.c + cuboot-ebony.c treeboot-ebony.c prpmc2800.c src-boot := $(src-wlib) $(src-plat) empty.c src-boot := $(addprefix $(obj)/, $(src-boot)) @@ -132,6 +132,7 @@ image-$(CONFIG_PPC_CHRP) += zImage.chrp image-$(CONFIG_PPC_EFIKA) += zImage.chrp image-$(CONFIG_PPC_PMAC) += zImage.pmac image-$(CONFIG_PPC_HOLLY) += zImage.holly-elf +image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 image-$(CONFIG_DEFAULT_UIMAGE) += uImage ifneq ($(CONFIG_DEVICE_TREE),"") @@ -154,9 +155,27 @@ targets += $(image-y) $(initrd-y) $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz +dts- := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-)) +dts-y := $(patsubst zImage%, zImage.dts%, $(image-y)) +dts-y := $(filter-out $(image-y), $(dts-y)) +targets += $(image-y) $(dts-y) + +dts_initrd- := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-)) +dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y)) +dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y)) +targets += $(image-y) $(dts_initrd-y) + +$(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz + # Don't put the ramdisk on the pattern rule; when its missing make will try # the pattern rule with less dependencies that also matches (even with the # hard dependency listed). +$(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz + $(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz) + +$(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts) + $(call if_changed,wrap,$*,$(dts)) + $(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz) @@ -195,13 +214,18 @@ $(obj)/zImage: $(addprefix $(obj)/, $(image-y)) @rm -f $@; ln $< $@ $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) @rm -f $@; ln $< $@ +$(obj)/zImage.dts: $(addprefix $(obj)/, $(dts-y)) + @rm -f $@; ln $< $@ +$(obj)/zImage.dts_initrd: $(addprefix $(obj)/, $(dts_initrd-y)) + @rm -f $@; ln $< $@ + install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< # anything not in $(targets) clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \ - treeImage.* + treeImage.* zImage.dts zImage.dts_initrd # clean up files cached by wrapper clean-kernel := vmlinux.strip vmlinux.bin diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c index 6cbc20afb4d8..9af554eea54b 100644 --- a/arch/powerpc/boot/cuboot-83xx.c +++ b/arch/powerpc/boot/cuboot-83xx.c @@ -57,7 +57,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, memcpy(&bd, (bd_t *)r3, sizeof(bd)); loader_info.initrd_addr = r4; - loader_info.initrd_size = r4 ? r5 : 0; + loader_info.initrd_size = r4 ? r5 - r4 : 0; loader_info.cmdline = (char *)r6; loader_info.cmdline_len = r7 - r6; diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c index f88ba00ac122..e2560317f278 100644 --- a/arch/powerpc/boot/cuboot-85xx.c +++ b/arch/powerpc/boot/cuboot-85xx.c @@ -58,7 +58,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, memcpy(&bd, (bd_t *)r3, sizeof(bd)); loader_info.initrd_addr = r4; - loader_info.initrd_size = r4 ? r5 : 0; + loader_info.initrd_size = r4 ? r5 - r4 : 0; loader_info.cmdline = (char *)r6; loader_info.cmdline_len = r7 - r6; diff --git a/arch/powerpc/boot/dts/prpmc2800.dts b/arch/powerpc/boot/dts/prpmc2800.dts new file mode 100644 index 000000000000..568965a022b9 --- /dev/null +++ b/arch/powerpc/boot/dts/prpmc2800.dts @@ -0,0 +1,315 @@ +/* Device Tree Source for Motorola PrPMC2800 + * + * Author: Mark A. Greer <mgreer@mvista.com> + * + * 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Property values that are labeled as "Default" will be updated by bootwrapper + * if it can determine the exact PrPMC type. + * + * To build: + * dtc -I dts -O asm -o prpmc2800.S -b 0 prpmc2800.dts + * dtc -I dts -O dtb -o prpmc2800.dtb -b 0 prpmc2800.dts + */ + +/ { + #address-cells = <1>; + #size-cells = <1>; + model = "PrPMC280/PrPMC2800"; /* Default */ + compatible = "motorola,PrPMC2800"; + coherency-off; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,7447 { + device_type = "cpu"; + reg = <0>; + clock-frequency = <2bb0b140>; /* Default (733 MHz) */ + bus-frequency = <7f28155>; /* 133.333333 MHz */ + timebase-frequency = <1fca055>; /* 33.333333 MHz */ + i-cache-line-size = <20>; + d-cache-line-size = <20>; + i-cache-size = <8000>; + d-cache-size = <8000>; + }; + }; + + memory { + device_type = "memory"; + reg = <00000000 20000000>; /* Default (512MB) */ + }; + + mv64x60@f1000000 { /* Marvell Discovery */ + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <1>; + model = "mv64360"; /* Default */ + compatible = "marvell,mv64x60"; + clock-frequency = <7f28155>; /* 133.333333 MHz */ + reg = <f1000000 00010000>; + virtual-reg = <f1000000>; + ranges = <88000000 88000000 01000000 /* PCI 0 I/O Space */ + 80000000 80000000 08000000 /* PCI 0 MEM Space */ + a0000000 a0000000 04000000 /* User FLASH */ + 00000000 f1000000 00010000 /* Bridge's regs */ + f2000000 f2000000 00040000>; /* Integrated SRAM */ + + flash@a0000000 { + device_type = "rom"; + compatible = "direct-mapped"; + reg = <a0000000 4000000>; /* Default (64MB) */ + probe-type = "CFI"; + bank-width = <4>; + partitions = <00000000 00100000 /* RO */ + 00100000 00040001 /* RW */ + 00140000 00400000 /* RO */ + 00540000 039c0000 /* RO */ + 03f00000 00100000>; /* RO */ + partition-names = "FW Image A", "FW Config Data", "Kernel Image", "Filesystem", "FW Image B"; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + device_type = "mdio"; + compatible = "marvell,mv64x60-mdio"; + ethernet-phy@1 { + device_type = "ethernet-phy"; + compatible = "broadcom,bcm5421"; + interrupts = <4c>; /* GPP 12 */ + interrupt-parent = <&/mv64x60/pic>; + reg = <1>; + }; + ethernet-phy@3 { + device_type = "ethernet-phy"; + compatible = "broadcom,bcm5421"; + interrupts = <4c>; /* GPP 12 */ + interrupt-parent = <&/mv64x60/pic>; + reg = <3>; + }; + }; + + ethernet@2000 { + reg = <2000 2000>; + eth0 { + device_type = "network"; + compatible = "marvell,mv64x60-eth"; + block-index = <0>; + interrupts = <20>; + interrupt-parent = <&/mv64x60/pic>; + phy = <&/mv64x60/mdio/ethernet-phy@1>; + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + eth1 { + device_type = "network"; + compatible = "marvell,mv64x60-eth"; + block-index = <1>; + interrupts = <21>; + interrupt-parent = <&/mv64x60/pic>; + phy = <&/mv64x60/mdio/ethernet-phy@3>; + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + }; + + sdma@4000 { + device_type = "dma"; + compatible = "marvell,mv64x60-sdma"; + reg = <4000 c18>; + virtual-reg = <f1004000>; + interrupt-base = <0>; + interrupts = <24>; + interrupt-parent = <&/mv64x60/pic>; + }; + + sdma@6000 { + device_type = "dma"; + compatible = "marvell,mv64x60-sdma"; + reg = <6000 c18>; + virtual-reg = <f1006000>; + interrupt-base = <0>; + interrupts = <26>; + interrupt-parent = <&/mv64x60/pic>; + }; + + brg@b200 { + compatible = "marvell,mv64x60-brg"; + reg = <b200 8>; + clock-src = <8>; + clock-frequency = <7ed6b40>; + current-speed = <2580>; + bcr = <0>; + }; + + brg@b208 { + compatible = "marvell,mv64x60-brg"; + reg = <b208 8>; + clock-src = <8>; + clock-frequency = <7ed6b40>; + current-speed = <2580>; + bcr = <0>; + }; + + cunit@f200 { + reg = <f200 200>; + }; + + mpscrouting@b400 { + reg = <b400 c>; + }; + + mpscintr@b800 { + reg = <b800 100>; + virtual-reg = <f100b800>; + }; + + mpsc@8000 { + device_type = "serial"; + compatible = "marvell,mpsc"; + reg = <8000 38>; + virtual-reg = <f1008000>; + sdma = <&/mv64x60/sdma@4000>; + brg = <&/mv64x60/brg@b200>; + cunit = <&/mv64x60/cunit@f200>; + mpscrouting = <&/mv64x60/mpscrouting@b400>; + mpscintr = <&/mv64x60/mpscintr@b800>; + block-index = <0>; + max_idle = <28>; + chr_1 = <0>; + chr_2 = <0>; + chr_10 = <3>; + mpcr = <0>; + interrupts = <28>; + interrupt-parent = <&/mv64x60/pic>; + }; + + mpsc@9000 { + device_type = "serial"; + compatible = "marvell,mpsc"; + reg = <9000 38>; + virtual-reg = <f1009000>; + sdma = <&/mv64x60/sdma@6000>; + brg = <&/mv64x60/brg@b208>; + cunit = <&/mv64x60/cunit@f200>; + mpscrouting = <&/mv64x60/mpscrouting@b400>; + mpscintr = <&/mv64x60/mpscintr@b800>; + block-index = <1>; + max_idle = <28>; + chr_1 = <0>; + chr_2 = <0>; + chr_10 = <3>; + mpcr = <0>; + interrupts = <2a>; + interrupt-parent = <&/mv64x60/pic>; + }; + + i2c@c000 { + device_type = "i2c"; + compatible = "marvell,mv64x60-i2c"; + reg = <c000 20>; + virtual-reg = <f100c000>; + freq_m = <8>; + freq_n = <3>; + timeout = <3e8>; /* 1000 = 1 second */ + retries = <1>; + interrupts = <25>; + interrupt-parent = <&/mv64x60/pic>; + }; + + pic { + #interrupt-cells = <1>; + #address-cells = <0>; + compatible = "marvell,mv64x60-pic"; + reg = <0000 88>; + interrupt-controller; + }; + + mpp@f000 { + compatible = "marvell,mv64x60-mpp"; + reg = <f000 10>; + }; + + gpp@f100 { + compatible = "marvell,mv64x60-gpp"; + reg = <f100 20>; + }; + + pci@80000000 { + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + compatible = "marvell,mv64x60-pci"; + reg = <0cf8 8>; + ranges = <01000000 0 0 88000000 0 01000000 + 02000000 0 80000000 80000000 0 08000000>; + bus-range = <0 ff>; + clock-frequency = <3EF1480>; + interrupt-pci-iack = <0c34>; + interrupt-parent = <&/mv64x60/pic>; + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + /* IDSEL 0x0a */ + 5000 0 0 1 &/mv64x60/pic 50 + 5000 0 0 2 &/mv64x60/pic 51 + 5000 0 0 3 &/mv64x60/pic 5b + 5000 0 0 4 &/mv64x60/pic 5d + + /* IDSEL 0x0b */ + 5800 0 0 1 &/mv64x60/pic 5b + 5800 0 0 2 &/mv64x60/pic 5d + 5800 0 0 3 &/mv64x60/pic 50 + 5800 0 0 4 &/mv64x60/pic 51 + + /* IDSEL 0x0c */ + 6000 0 0 1 &/mv64x60/pic 5b + 6000 0 0 2 &/mv64x60/pic 5d + 6000 0 0 3 &/mv64x60/pic 50 + 6000 0 0 4 &/mv64x60/pic 51 + + /* IDSEL 0x0d */ + 6800 0 0 1 &/mv64x60/pic 5d + 6800 0 0 2 &/mv64x60/pic 50 + 6800 0 0 3 &/mv64x60/pic 51 + 6800 0 0 4 &/mv64x60/pic 5b + >; + }; + + cpu-error@0070 { + compatible = "marvell,mv64x60-cpu-error"; + reg = <0070 10 0128 28>; + interrupts = <03>; + interrupt-parent = <&/mv64x60/pic>; + }; + + sram-ctrl@0380 { + compatible = "marvell,mv64x60-sram-ctrl"; + reg = <0380 80>; + interrupts = <0d>; + interrupt-parent = <&/mv64x60/pic>; + }; + + pci-error@1d40 { + compatible = "marvell,mv64x60-pci-error"; + reg = <1d40 40 0c28 4>; + interrupts = <0c>; + interrupt-parent = <&/mv64x60/pic>; + }; + + mem-ctrl@1400 { + compatible = "marvell,mv64x60-mem-ctrl"; + reg = <1400 60>; + interrupts = <11>; + interrupt-parent = <&/mv64x60/pic>; + }; + }; + + chosen { + bootargs = "ip=on console=ttyMM0"; + linux,stdout-path = "/mv64x60@f1000000/mpsc@8000"; + }; +}; diff --git a/arch/powerpc/boot/mpsc.c b/arch/powerpc/boot/mpsc.c new file mode 100644 index 000000000000..f1c0e965e5ce --- /dev/null +++ b/arch/powerpc/boot/mpsc.c @@ -0,0 +1,170 @@ +/* + * MPSC/UART driver for the Marvell mv64360, mv64460, ... + * + * Author: Mark A. Greer <mgreer@mvista.com> + * + * 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <stdarg.h> +#include <stddef.h> +#include "types.h" +#include "string.h" +#include "stdio.h" +#include "io.h" +#include "ops.h" + +extern void udelay(long delay); + +#define MPSC_CHR_1 0x000c + +#define MPSC_CHR_2 0x0010 +#define MPSC_CHR_2_TA (1<<7) +#define MPSC_CHR_2_TCS (1<<9) +#define MPSC_CHR_2_RA (1<<23) +#define MPSC_CHR_2_CRD (1<<25) +#define MPSC_CHR_2_EH (1<<31) + +#define MPSC_CHR_4 0x0018 +#define MPSC_CHR_4_Z (1<<29) + +#define MPSC_CHR_5 0x001c +#define MPSC_CHR_5_CTL1_INTR (1<<12) +#define MPSC_CHR_5_CTL1_VALID (1<<15) + +#define MPSC_CHR_10 0x0030 + +#define MPSC_INTR_CAUSE 0x0000 +#define MPSC_INTR_CAUSE_RCC (1<<6) +#define MPSC_INTR_MASK 0x0080 + +#define SDMA_SDCM 0x0008 +#define SDMA_SDCM_AR (1<<15) +#define SDMA_SDCM_AT (1<<31) + +static volatile char *mpsc_base; +static volatile char *mpscintr_base; +static u32 chr1, chr2; + +static int mpsc_open(void) +{ + chr1 = in_le32((u32 *)(mpsc_base + MPSC_CHR_1)) & 0x00ff0000; + chr2 = in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & ~(MPSC_CHR_2_TA + | MPSC_CHR_2_TCS | MPSC_CHR_2_RA | MPSC_CHR_2_CRD + | MPSC_CHR_2_EH); + out_le32((u32 *)(mpsc_base + MPSC_CHR_4), MPSC_CHR_4_Z); + out_le32((u32 *)(mpsc_base + MPSC_CHR_5), + MPSC_CHR_5_CTL1_INTR | MPSC_CHR_5_CTL1_VALID); + out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_EH); + return 0; +} + +static void mpsc_putc(unsigned char c) +{ + while (in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & MPSC_CHR_2_TCS); + + out_le32((u32 *)(mpsc_base + MPSC_CHR_1), chr1 | c); + out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_TCS); +} + +static unsigned char mpsc_getc(void) +{ + u32 cause = 0; + unsigned char c; + + while (!(cause & MPSC_INTR_CAUSE_RCC)) + cause = in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE)); + + c = in_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2)); + out_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2), c); + out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), + cause & ~MPSC_INTR_CAUSE_RCC); + + return c; +} + +static u8 mpsc_tstc(void) +{ + return (u8)((in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE)) + & MPSC_INTR_CAUSE_RCC) != 0); +} + +static void mpsc_stop_dma(volatile char *sdma_base) +{ + out_le32((u32 *)(mpsc_base + MPSC_CHR_2),MPSC_CHR_2_TA | MPSC_CHR_2_RA); + out_le32((u32 *)(sdma_base + SDMA_SDCM), SDMA_SDCM_AR | SDMA_SDCM_AT); + + while ((in_le32((u32 *)(sdma_base + SDMA_SDCM)) + & (SDMA_SDCM_AR | SDMA_SDCM_AT)) != 0) + udelay(100); +} + +static volatile char *mpsc_get_virtreg_of_phandle(void *devp, char *prop) +{ + void *v; + int n; + + n = getprop(devp, prop, &v, sizeof(v)); + if (n != sizeof(v)) + goto err_out; + + devp = find_node_by_linuxphandle((u32)v); + if (devp == NULL) + goto err_out; + + n = getprop(devp, "virtual-reg", &v, sizeof(v)); + if (n == sizeof(v)) + return v; + +err_out: + return NULL; +} + +int mpsc_console_init(void *devp, struct serial_console_data *scdp) +{ + void *v; + int n, reg_set; + volatile char *sdma_base; + + n = getprop(devp, "virtual-reg", &v, sizeof(v)); + if (n != sizeof(v)) + goto err_out; + mpsc_base = v; + + sdma_base = mpsc_get_virtreg_of_phandle(devp, "sdma"); + if (sdma_base == NULL) + goto err_out; + + mpscintr_base = mpsc_get_virtreg_of_phandle(devp, "mpscintr"); + if (mpscintr_base == NULL) + goto err_out; + + n = getprop(devp, "block-index", &v, sizeof(v)); + if (n != sizeof(v)) + goto err_out; + reg_set = (int)v; + + mpscintr_base += (reg_set == 0) ? 0x4 : 0xc; + + /* Make sure the mpsc ctlrs are shutdown */ + out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0); + out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0); + out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0); + out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0); + + mpsc_stop_dma(sdma_base); + + scdp->open = mpsc_open; + scdp->putc = mpsc_putc; + scdp->getc = mpsc_getc; + scdp->tstc = mpsc_tstc; + scdp->close = NULL; + + return 0; + +err_out: + return -1; +} diff --git a/arch/powerpc/boot/mv64x60.c b/arch/powerpc/boot/mv64x60.c new file mode 100644 index 000000000000..b43259455d4b --- /dev/null +++ b/arch/powerpc/boot/mv64x60.c @@ -0,0 +1,581 @@ +/* + * Marvell hostbridge routines + * + * Author: Mark A. Greer <source@mvista.com> + * + * 2004, 2005, 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <stdarg.h> +#include <stddef.h> +#include "types.h" +#include "elf.h" +#include "page.h" +#include "string.h" +#include "stdio.h" +#include "io.h" +#include "ops.h" +#include "mv64x60.h" + +#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) + +#define MV64x60_CPU2MEM_WINDOWS 4 +#define MV64x60_CPU2MEM_0_BASE 0x0008 +#define MV64x60_CPU2MEM_0_SIZE 0x0010 +#define MV64x60_CPU2MEM_1_BASE 0x0208 +#define MV64x60_CPU2MEM_1_SIZE 0x0210 +#define MV64x60_CPU2MEM_2_BASE 0x0018 +#define MV64x60_CPU2MEM_2_SIZE 0x0020 +#define MV64x60_CPU2MEM_3_BASE 0x0218 +#define MV64x60_CPU2MEM_3_SIZE 0x0220 + +#define MV64x60_ENET2MEM_BAR_ENABLE 0x2290 +#define MV64x60_ENET2MEM_0_BASE 0x2200 +#define MV64x60_ENET2MEM_0_SIZE 0x2204 +#define MV64x60_ENET2MEM_1_BASE 0x2208 +#define MV64x60_ENET2MEM_1_SIZE 0x220c +#define MV64x60_ENET2MEM_2_BASE 0x2210 +#define MV64x60_ENET2MEM_2_SIZE 0x2214 +#define MV64x60_ENET2MEM_3_BASE 0x2218 +#define MV64x60_ENET2MEM_3_SIZE 0x221c +#define MV64x60_ENET2MEM_4_BASE 0x2220 +#define MV64x60_ENET2MEM_4_SIZE 0x2224 +#define MV64x60_ENET2MEM_5_BASE 0x2228 +#define MV64x60_ENET2MEM_5_SIZE 0x222c +#define MV64x60_ENET2MEM_ACC_PROT_0 0x2294 +#define MV64x60_ENET2MEM_ACC_PROT_1 0x2298 +#define MV64x60_ENET2MEM_ACC_PROT_2 0x229c + +#define MV64x60_MPSC2MEM_BAR_ENABLE 0xf250 +#define MV64x60_MPSC2MEM_0_BASE 0xf200 +#define MV64x60_MPSC2MEM_0_SIZE 0xf204 +#define MV64x60_MPSC2MEM_1_BASE 0xf208 +#define MV64x60_MPSC2MEM_1_SIZE 0xf20c +#define MV64x60_MPSC2MEM_2_BASE 0xf210 +#define MV64x60_MPSC2MEM_2_SIZE 0xf214 +#define MV64x60_MPSC2MEM_3_BASE 0xf218 +#define MV64x60_MPSC2MEM_3_SIZE 0xf21c +#define MV64x60_MPSC_0_REMAP 0xf240 +#define MV64x60_MPSC_1_REMAP 0xf244 +#define MV64x60_MPSC2MEM_ACC_PROT_0 0xf254 +#define MV64x60_MPSC2MEM_ACC_PROT_1 0xf258 +#define MV64x60_MPSC2REGS_BASE 0xf25c + +#define MV64x60_IDMA2MEM_BAR_ENABLE 0x0a80 +#define MV64x60_IDMA2MEM_0_BASE 0x0a00 +#define MV64x60_IDMA2MEM_0_SIZE 0x0a04 +#define MV64x60_IDMA2MEM_1_BASE 0x0a08 +#define MV64x60_IDMA2MEM_1_SIZE 0x0a0c +#define MV64x60_IDMA2MEM_2_BASE 0x0a10 +#define MV64x60_IDMA2MEM_2_SIZE 0x0a14 +#define MV64x60_IDMA2MEM_3_BASE 0x0a18 +#define MV64x60_IDMA2MEM_3_SIZE 0x0a1c +#define MV64x60_IDMA2MEM_4_BASE 0x0a20 +#define MV64x60_IDMA2MEM_4_SIZE 0x0a24 +#define MV64x60_IDMA2MEM_5_BASE 0x0a28 +#define MV64x60_IDMA2MEM_5_SIZE 0x0a2c +#define MV64x60_IDMA2MEM_6_BASE 0x0a30 +#define MV64x60_IDMA2MEM_6_SIZE 0x0a34 +#define MV64x60_IDMA2MEM_7_BASE 0x0a38 +#define MV64x60_IDMA2MEM_7_SIZE 0x0a3c +#define MV64x60_IDMA2MEM_ACC_PROT_0 0x0a70 +#define MV64x60_IDMA2MEM_ACC_PROT_1 0x0a74 +#define MV64x60_IDMA2MEM_ACC_PROT_2 0x0a78 +#define MV64x60_IDMA2MEM_ACC_PROT_3 0x0a7c + +#define MV64x60_PCI_ACC_CNTL_WINDOWS 6 +#define MV64x60_PCI0_PCI_DECODE_CNTL 0x0d3c +#define MV64x60_PCI1_PCI_DECODE_CNTL 0x0dbc + +#define MV64x60_PCI0_BAR_ENABLE 0x0c3c +#define MV64x60_PCI02MEM_0_SIZE 0x0c08 +#define MV64x60_PCI0_ACC_CNTL_0_BASE_LO 0x1e00 +#define MV64x60_PCI0_ACC_CNTL_0_BASE_HI 0x1e04 +#define MV64x60_PCI0_ACC_CNTL_0_SIZE 0x1e08 +#define MV64x60_PCI0_ACC_CNTL_1_BASE_LO 0x1e10 +#define MV64x60_PCI0_ACC_CNTL_1_BASE_HI 0x1e14 +#define MV64x60_PCI0_ACC_CNTL_1_SIZE 0x1e18 +#define MV64x60_PCI0_ACC_CNTL_2_BASE_LO 0x1e20 +#define MV64x60_PCI0_ACC_CNTL_2_BASE_HI 0x1e24 +#define MV64x60_PCI0_ACC_CNTL_2_SIZE 0x1e28 +#define MV64x60_PCI0_ACC_CNTL_3_BASE_LO 0x1e30 +#define MV64x60_PCI0_ACC_CNTL_3_BASE_HI 0x1e34 +#define MV64x60_PCI0_ACC_CNTL_3_SIZE 0x1e38 +#define MV64x60_PCI0_ACC_CNTL_4_BASE_LO 0x1e40 +#define MV64x60_PCI0_ACC_CNTL_4_BASE_HI 0x1e44 +#define MV64x60_PCI0_ACC_CNTL_4_SIZE 0x1e48 +#define MV64x60_PCI0_ACC_CNTL_5_BASE_LO 0x1e50 +#define MV64x60_PCI0_ACC_CNTL_5_BASE_HI 0x1e54 +#define MV64x60_PCI0_ACC_CNTL_5_SIZE 0x1e58 + +#define MV64x60_PCI1_BAR_ENABLE 0x0cbc +#define MV64x60_PCI12MEM_0_SIZE 0x0c88 +#define MV64x60_PCI1_ACC_CNTL_0_BASE_LO 0x1e80 +#define MV64x60_PCI1_ACC_CNTL_0_BASE_HI 0x1e84 +#define MV64x60_PCI1_ACC_CNTL_0_SIZE 0x1e88 +#define MV64x60_PCI1_ACC_CNTL_1_BASE_LO 0x1e90 +#define MV64x60_PCI1_ACC_CNTL_1_BASE_HI 0x1e94 +#define MV64x60_PCI1_ACC_CNTL_1_SIZE 0x1e98 +#define MV64x60_PCI1_ACC_CNTL_2_BASE_LO 0x1ea0 +#define MV64x60_PCI1_ACC_CNTL_2_BASE_HI 0x1ea4 +#define MV64x60_PCI1_ACC_CNTL_2_SIZE 0x1ea8 +#define MV64x60_PCI1_ACC_CNTL_3_BASE_LO 0x1eb0 +#define MV64x60_PCI1_ACC_CNTL_3_BASE_HI 0x1eb4 +#define MV64x60_PCI1_ACC_CNTL_3_SIZE 0x1eb8 +#define MV64x60_PCI1_ACC_CNTL_4_BASE_LO 0x1ec0 +#define MV64x60_PCI1_ACC_CNTL_4_BASE_HI 0x1ec4 +#define MV64x60_PCI1_ACC_CNTL_4_SIZE 0x1ec8 +#define MV64x60_PCI1_ACC_CNTL_5_BASE_LO 0x1ed0 +#define MV64x60_PCI1_ACC_CNTL_5_BASE_HI 0x1ed4 +#define MV64x60_PCI1_ACC_CNTL_5_SIZE 0x1ed8 + +#define MV64x60_CPU2PCI_SWAP_NONE 0x01000000 + +#define MV64x60_CPU2PCI0_IO_BASE 0x0048 +#define MV64x60_CPU2PCI0_IO_SIZE 0x0050 +#define MV64x60_CPU2PCI0_IO_REMAP 0x00f0 +#define MV64x60_CPU2PCI0_MEM_0_BASE 0x0058 +#define MV64x60_CPU2PCI0_MEM_0_SIZE 0x0060 +#define MV64x60_CPU2PCI0_MEM_0_REMAP_LO 0x00f8 +#define MV64x60_CPU2PCI0_MEM_0_REMAP_HI 0x0320 + +#define MV64x60_CPU2PCI1_IO_BASE 0x0090 +#define MV64x60_CPU2PCI1_IO_SIZE 0x0098 +#define MV64x60_CPU2PCI1_IO_REMAP 0x0108 +#define MV64x60_CPU2PCI1_MEM_0_BASE 0x00a0 +#define MV64x60_CPU2PCI1_MEM_0_SIZE 0x00a8 +#define MV64x60_CPU2PCI1_MEM_0_REMAP_LO 0x0110 +#define MV64x60_CPU2PCI1_MEM_0_REMAP_HI 0x0340 + +struct mv64x60_mem_win { + u32 hi; + u32 lo; + u32 size; +}; + +struct mv64x60_pci_win { + u32 fcn; + u32 hi; + u32 lo; + u32 size; +}; + +/* PCI config access routines */ +struct { + u32 addr; + u32 data; +} static mv64x60_pci_cfgio[2] = { + { /* hose 0 */ + .addr = 0xcf8, + .data = 0xcfc, + }, + { /* hose 1 */ + .addr = 0xc78, + .data = 0xc7c, + } +}; + +u32 mv64x60_cfg_read(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset) +{ + out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), + (1 << 31) | (bus << 16) | (devfn << 8) | offset); + return in_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data)); +} + +void mv64x60_cfg_write(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset, + u32 val) +{ + out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), + (1 << 31) | (bus << 16) | (devfn << 8) | offset); + out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data), val); +} + +/* I/O ctlr -> system memory setup */ +static struct mv64x60_mem_win mv64x60_cpu2mem[MV64x60_CPU2MEM_WINDOWS] = { + { + .lo = MV64x60_CPU2MEM_0_BASE, + .size = MV64x60_CPU2MEM_0_SIZE, + }, + { + .lo = MV64x60_CPU2MEM_1_BASE, + .size = MV64x60_CPU2MEM_1_SIZE, + }, + { + .lo = MV64x60_CPU2MEM_2_BASE, + .size = MV64x60_CPU2MEM_2_SIZE, + }, + { + .lo = MV64x60_CPU2MEM_3_BASE, + .size = MV64x60_CPU2MEM_3_SIZE, + }, +}; + +static struct mv64x60_mem_win mv64x60_enet2mem[MV64x60_CPU2MEM_WINDOWS] = { + { + .lo = MV64x60_ENET2MEM_0_BASE, + .size = MV64x60_ENET2MEM_0_SIZE, + }, + { + .lo = MV64x60_ENET2MEM_1_BASE, + .size = MV64x60_ENET2MEM_1_SIZE, + }, + { + .lo = MV64x60_ENET2MEM_2_BASE, + .size = MV64x60_ENET2MEM_2_SIZE, + }, + { + .lo = MV64x60_ENET2MEM_3_BASE, + .size = MV64x60_ENET2MEM_3_SIZE, + }, +}; + +static struct mv64x60_mem_win mv64x60_mpsc2mem[MV64x60_CPU2MEM_WINDOWS] = { + { + .lo = MV64x60_MPSC2MEM_0_BASE, + .size = MV64x60_MPSC2MEM_0_SIZE, + }, + { + .lo = MV64x60_MPSC2MEM_1_BASE, + .size = MV64x60_MPSC2MEM_1_SIZE, + }, + { + .lo = MV64x60_MPSC2MEM_2_BASE, + .size = MV64x60_MPSC2MEM_2_SIZE, + }, + { + .lo = MV64x60_MPSC2MEM_3_BASE, + .size = MV64x60_MPSC2MEM_3_SIZE, + }, +}; + +static struct mv64x60_mem_win mv64x60_idma2mem[MV64x60_CPU2MEM_WINDOWS] = { + { + .lo = MV64x60_IDMA2MEM_0_BASE, + .size = MV64x60_IDMA2MEM_0_SIZE, + }, + { + .lo = MV64x60_IDMA2MEM_1_BASE, + .size = MV64x60_IDMA2MEM_1_SIZE, + }, + { + .lo = MV64x60_IDMA2MEM_2_BASE, + .size = MV64x60_IDMA2MEM_2_SIZE, + }, + { + .lo = MV64x60_IDMA2MEM_3_BASE, + .size = MV64x60_IDMA2MEM_3_SIZE, + }, +}; + +static u32 mv64x60_dram_selects[MV64x60_CPU2MEM_WINDOWS] = {0xe,0xd,0xb,0x7}; + +/* + * ENET, MPSC, and IDMA ctlrs on the MV64x60 have separate windows that + * must be set up so that the respective ctlr can access system memory. + * Configure them to be same as cpu->memory windows. + */ +void mv64x60_config_ctlr_windows(u8 *bridge_base, u8 *bridge_pbase, + u8 is_coherent) +{ + u32 i, base, size, enables, prot = 0, snoop_bits = 0; + + /* Disable ctlr->mem windows */ + out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0x3f); + out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), 0xf); + out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0xff); + + if (is_coherent) + snoop_bits = 0x2 << 12; /* Writeback */ + + enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; + + for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) { + if (enables & (1 << i)) /* Set means disabled */ + continue; + + base = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].lo)) + << 16; + base |= snoop_bits | (mv64x60_dram_selects[i] << 8); + size = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].size)) + << 16; + prot |= (0x3 << (i << 1)); /* RW access */ + + out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].lo), base); + out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].size), size); + out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].lo), base); + out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].size), size); + out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].lo), base); + out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].size), size); + } + + out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_0), prot); + out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_1), prot); + out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_2), prot); + out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_0), prot); + out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_1), prot); + out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_0), prot); + out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_1), prot); + out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_2), prot); + out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_3), prot); + + /* Set mpsc->bridge's reg window to the bridge's internal registers. */ + out_le32((u32 *)(bridge_base + MV64x60_MPSC2REGS_BASE), + (u32)bridge_pbase); + + out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), enables); + out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), enables); + out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_BAR_ENABLE), enables); +} + +/* PCI MEM -> system memory, et. al. setup */ +static struct mv64x60_pci_win mv64x60_pci2mem[2] = { + { /* hose 0 */ + .fcn = 0, + .hi = 0x14, + .lo = 0x10, + .size = MV64x60_PCI02MEM_0_SIZE, + }, + { /* hose 1 */ + .fcn = 0, + .hi = 0x94, + .lo = 0x90, + .size = MV64x60_PCI12MEM_0_SIZE, + }, +}; + +static struct +mv64x60_mem_win mv64x60_pci_acc[2][MV64x60_PCI_ACC_CNTL_WINDOWS] = { + { /* hose 0 */ + { + .hi = MV64x60_PCI0_ACC_CNTL_0_BASE_HI, + .lo = MV64x60_PCI0_ACC_CNTL_0_BASE_LO, + .size = MV64x60_PCI0_ACC_CNTL_0_SIZE, + }, + { + .hi = MV64x60_PCI0_ACC_CNTL_1_BASE_HI, + .lo = MV64x60_PCI0_ACC_CNTL_1_BASE_LO, + .size = MV64x60_PCI0_ACC_CNTL_1_SIZE, + }, + { + .hi = MV64x60_PCI0_ACC_CNTL_2_BASE_HI, + .lo = MV64x60_PCI0_ACC_CNTL_2_BASE_LO, + .size = MV64x60_PCI0_ACC_CNTL_2_SIZE, + }, + { + .hi = MV64x60_PCI0_ACC_CNTL_3_BASE_HI, + .lo = MV64x60_PCI0_ACC_CNTL_3_BASE_LO, + .size = MV64x60_PCI0_ACC_CNTL_3_SIZE, + }, + }, + { /* hose 1 */ + { + .hi = MV64x60_PCI1_ACC_CNTL_0_BASE_HI, + .lo = MV64x60_PCI1_ACC_CNTL_0_BASE_LO, + .size = MV64x60_PCI1_ACC_CNTL_0_SIZE, + }, + { + .hi = MV64x60_PCI1_ACC_CNTL_1_BASE_HI, + .lo = MV64x60_PCI1_ACC_CNTL_1_BASE_LO, + .size = MV64x60_PCI1_ACC_CNTL_1_SIZE, + }, + { + .hi = MV64x60_PCI1_ACC_CNTL_2_BASE_HI, + .lo = MV64x60_PCI1_ACC_CNTL_2_BASE_LO, + .size = MV64x60_PCI1_ACC_CNTL_2_SIZE, + }, + { + .hi = MV64x60_PCI1_ACC_CNTL_3_BASE_HI, + .lo = MV64x60_PCI1_ACC_CNTL_3_BASE_LO, + .size = MV64x60_PCI1_ACC_CNTL_3_SIZE, + }, + }, +}; + +static struct mv64x60_mem_win mv64x60_pci2reg[2] = { + { + .hi = 0x24, + .lo = 0x20, + .size = 0, + }, + { + .hi = 0xa4, + .lo = 0xa0, + .size = 0, + }, +}; + +/* Only need to use 1 window (per hose) to get access to all of system memory */ +void mv64x60_config_pci_windows(u8 *bridge_base, u8 *bridge_pbase, u8 hose, + u8 bus, u32 mem_size, u32 acc_bits) +{ + u32 i, offset, bar_enable, enables; + + /* Disable all windows but PCI MEM -> Bridge's regs window */ + enables = ~(1 << 9); + bar_enable = hose ? MV64x60_PCI1_BAR_ENABLE : MV64x60_PCI0_BAR_ENABLE; + out_le32((u32 *)(bridge_base + bar_enable), enables); + + for (i=0; i<MV64x60_PCI_ACC_CNTL_WINDOWS; i++) + out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][i].lo), 0); + + /* If mem_size is 0, leave windows disabled */ + if (mem_size == 0) + return; + + /* Cause automatic updates of PCI remap regs */ + offset = hose ? + MV64x60_PCI1_PCI_DECODE_CNTL : MV64x60_PCI0_PCI_DECODE_CNTL; + i = in_le32((u32 *)(bridge_base + offset)); + out_le32((u32 *)(bridge_base + offset), i & ~0x1); + + mem_size = (mem_size - 1) & 0xfffff000; + + /* Map PCI MEM addr 0 -> System Mem addr 0 */ + mv64x60_cfg_write(bridge_base, hose, bus, + PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), + mv64x60_pci2mem[hose].hi, 0); + mv64x60_cfg_write(bridge_base, hose, bus, + PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), + mv64x60_pci2mem[hose].lo, 0); + out_le32((u32 *)(bridge_base + mv64x60_pci2mem[hose].size),mem_size); + + acc_bits |= MV64x60_PCI_ACC_CNTL_ENABLE; + out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].hi), 0); + out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].lo), acc_bits); + out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].size),mem_size); + + /* Set PCI MEM->bridge's reg window to where they are in CPU mem map */ + i = (u32)bridge_base; + i &= 0xffff0000; + i |= (0x2 << 1); + mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), + mv64x60_pci2reg[hose].hi, 0); + mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), + mv64x60_pci2reg[hose].lo, i); + + enables &= ~0x1; /* Enable PCI MEM -> System Mem window 0 */ + out_le32((u32 *)(bridge_base + bar_enable), enables); +} + +/* CPU -> PCI I/O & MEM setup */ +struct mv64x60_cpu2pci_win mv64x60_cpu2pci_io[2] = { + { /* hose 0 */ + .lo = MV64x60_CPU2PCI0_IO_BASE, + .size = MV64x60_CPU2PCI0_IO_SIZE, + .remap_hi = 0, + .remap_lo = MV64x60_CPU2PCI0_IO_REMAP, + }, + { /* hose 1 */ + .lo = MV64x60_CPU2PCI1_IO_BASE, + .size = MV64x60_CPU2PCI1_IO_SIZE, + .remap_hi = 0, + .remap_lo = MV64x60_CPU2PCI1_IO_REMAP, + }, +}; + +struct mv64x60_cpu2pci_win mv64x60_cpu2pci_mem[2] = { + { /* hose 0 */ + .lo = MV64x60_CPU2PCI0_MEM_0_BASE, + .size = MV64x60_CPU2PCI0_MEM_0_SIZE, + .remap_hi = MV64x60_CPU2PCI0_MEM_0_REMAP_HI, + .remap_lo = MV64x60_CPU2PCI0_MEM_0_REMAP_LO, + }, + { /* hose 1 */ + .lo = MV64x60_CPU2PCI1_MEM_0_BASE, + .size = MV64x60_CPU2PCI1_MEM_0_SIZE, + .remap_hi = MV64x60_CPU2PCI1_MEM_0_REMAP_HI, + .remap_lo = MV64x60_CPU2PCI1_MEM_0_REMAP_LO, + }, +}; + +/* Only need to set up 1 window to pci mem space */ +void mv64x60_config_cpu2pci_window(u8 *bridge_base, u8 hose, u32 pci_base_hi, + u32 pci_base_lo, u32 cpu_base, u32 size, + struct mv64x60_cpu2pci_win *offset_tbl) +{ + cpu_base >>= 16; + cpu_base |= MV64x60_CPU2PCI_SWAP_NONE; + out_le32((u32 *)(bridge_base + offset_tbl[hose].lo), cpu_base); + + if (offset_tbl[hose].remap_hi != 0) + out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_hi), + pci_base_hi); + out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_lo), + pci_base_lo >> 16); + + size = (size - 1) >> 16; + out_le32((u32 *)(bridge_base + offset_tbl[hose].size), size); +} + +/* Read mem ctlr to get the amount of mem in system */ +u32 mv64x60_get_mem_size(u8 *bridge_base) +{ + u32 enables, i, v; + u32 mem = 0; + + enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; + + for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) + if (!(enables & (1<<i))) { + v = in_le32((u32*)(bridge_base + + mv64x60_cpu2mem[i].size)); + v = ((v & 0xffff) + 1) << 16; + mem += v; + } + + return mem; +} + +/* Get physical address of bridge's registers */ +u8 *mv64x60_get_bridge_pbase(void) +{ + u32 v[2]; + void *devp; + + devp = finddevice("/mv64x60"); + if (devp == NULL) + goto err_out; + if (getprop(devp, "reg", v, sizeof(v)) != sizeof(v)) + goto err_out; + + return (u8 *)v[0]; + +err_out: + return 0; +} + +/* Get virtual address of bridge's registers */ +u8 *mv64x60_get_bridge_base(void) +{ + u32 v; + void *devp; + + devp = finddevice("/mv64x60"); + if (devp == NULL) + goto err_out; + if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v)) + goto err_out; + + return (u8 *)v; + +err_out: + return 0; +} + +u8 mv64x60_is_coherent(void) +{ + u32 v; + void *devp; + + devp = finddevice("/"); + if (devp == NULL) + return 1; /* Assume coherency on */ + + if (getprop(devp, "coherency-off", &v, sizeof(v)) < 0) + return 1; /* Coherency on */ + else + return 0; +} diff --git a/arch/powerpc/boot/mv64x60.h b/arch/powerpc/boot/mv64x60.h new file mode 100644 index 000000000000..b827105e6e54 --- /dev/null +++ b/arch/powerpc/boot/mv64x60.h @@ -0,0 +1,70 @@ +/* + * Author: Mark A. Greer <source@mvista.com> + * + * 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef _PPC_BOOT_MV64x60_H_ +#define _PPC_BOOT_MV64x60_H_ + +#define MV64x60_CPU_BAR_ENABLE 0x0278 + +#define MV64x60_PCI_ACC_CNTL_ENABLE (1<<0) +#define MV64x60_PCI_ACC_CNTL_REQ64 (1<<1) +#define MV64x60_PCI_ACC_CNTL_SNOOP_NONE 0x00000000 +#define MV64x60_PCI_ACC_CNTL_SNOOP_WT 0x00000004 +#define MV64x60_PCI_ACC_CNTL_SNOOP_WB 0x00000008 +#define MV64x60_PCI_ACC_CNTL_SNOOP_MASK 0x0000000c +#define MV64x60_PCI_ACC_CNTL_ACCPROT (1<<4) +#define MV64x60_PCI_ACC_CNTL_WRPROT (1<<5) +#define MV64x60_PCI_ACC_CNTL_SWAP_BYTE 0x00000000 +#define MV64x60_PCI_ACC_CNTL_SWAP_NONE 0x00000040 +#define MV64x60_PCI_ACC_CNTL_SWAP_BYTE_WORD 0x00000080 +#define MV64x60_PCI_ACC_CNTL_SWAP_WORD 0x000000c0 +#define MV64x60_PCI_ACC_CNTL_SWAP_MASK 0x000000c0 +#define MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES 0x00000000 +#define MV64x60_PCI_ACC_CNTL_MBURST_64_BYTES 0x00000100 +#define MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES 0x00000200 +#define MV64x60_PCI_ACC_CNTL_MBURST_MASK 0x00000300 +#define MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES 0x00000000 +#define MV64x60_PCI_ACC_CNTL_RDSIZE_64_BYTES 0x00000400 +#define MV64x60_PCI_ACC_CNTL_RDSIZE_128_BYTES 0x00000800 +#define MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES 0x00000c00 +#define MV64x60_PCI_ACC_CNTL_RDSIZE_MASK 0x00000c00 + +struct mv64x60_cpu2pci_win { + u32 lo; + u32 size; + u32 remap_hi; + u32 remap_lo; +}; + +extern struct mv64x60_cpu2pci_win mv64x60_cpu2pci_io[2]; +extern struct mv64x60_cpu2pci_win mv64x60_cpu2pci_mem[2]; + +u32 mv64x60_cfg_read(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, + u8 offset); +void mv64x60_cfg_write(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, + u8 offset, u32 val); + +void mv64x60_config_ctlr_windows(u8 *bridge_base, u8 *bridge_pbase, + u8 is_coherent); +void mv64x60_config_pci_windows(u8 *bridge_base, u8 *bridge_pbase, u8 hose, + u8 bus, u32 mem_size, u32 acc_bits); +void mv64x60_config_cpu2pci_window(u8 *bridge_base, u8 hose, u32 pci_base_hi, + u32 pci_base_lo, u32 cpu_base, u32 size, + struct mv64x60_cpu2pci_win *offset_tbl); +u32 mv64x60_get_mem_size(u8 *bridge_base); +u8 *mv64x60_get_bridge_pbase(void); +u8 *mv64x60_get_bridge_base(void); +u8 mv64x60_is_coherent(void); + +int mv64x60_i2c_open(void); +int mv64x60_i2c_read(u32 devaddr, u8 *buf, u32 offset, u32 offset_size, + u32 count); +void mv64x60_i2c_close(void); + +#endif /* _PPC_BOOT_MV64x60_H_ */ diff --git a/arch/powerpc/boot/mv64x60_i2c.c b/arch/powerpc/boot/mv64x60_i2c.c new file mode 100644 index 000000000000..435fe8528680 --- /dev/null +++ b/arch/powerpc/boot/mv64x60_i2c.c @@ -0,0 +1,206 @@ +/* + * Bootloader version of the i2c driver for the MV64x60. + * + * Author: Dale Farnsworth <dfarnsworth@mvista.com> + * Maintained by: Mark A. Greer <mgreer@mvista.com> + * + * 2003, 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express or + * implied. + */ + +#include <stdarg.h> +#include <stddef.h> +#include "types.h" +#include "elf.h" +#include "page.h" +#include "string.h" +#include "stdio.h" +#include "io.h" +#include "ops.h" +#include "mv64x60.h" + +extern void udelay(long); + +/* Register defines */ +#define MV64x60_I2C_REG_SLAVE_ADDR 0x00 +#define MV64x60_I2C_REG_DATA 0x04 +#define MV64x60_I2C_REG_CONTROL 0x08 +#define MV64x60_I2C_REG_STATUS 0x0c +#define MV64x60_I2C_REG_BAUD 0x0c +#define MV64x60_I2C_REG_EXT_SLAVE_ADDR 0x10 +#define MV64x60_I2C_REG_SOFT_RESET 0x1c + +#define MV64x60_I2C_CONTROL_ACK 0x04 +#define MV64x60_I2C_CONTROL_IFLG 0x08 +#define MV64x60_I2C_CONTROL_STOP 0x10 +#define MV64x60_I2C_CONTROL_START 0x20 +#define MV64x60_I2C_CONTROL_TWSIEN 0x40 +#define MV64x60_I2C_CONTROL_INTEN 0x80 + +#define MV64x60_I2C_STATUS_BUS_ERR 0x00 +#define MV64x60_I2C_STATUS_MAST_START 0x08 +#define MV64x60_I2C_STATUS_MAST_REPEAT_START 0x10 +#define MV64x60_I2C_STATUS_MAST_WR_ADDR_ACK 0x18 +#define MV64x60_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20 +#define MV64x60_I2C_STATUS_MAST_WR_ACK 0x28 +#define MV64x60_I2C_STATUS_MAST_WR_NO_ACK 0x30 +#define MV64x60_I2C_STATUS_MAST_LOST_ARB 0x38 +#define MV64x60_I2C_STATUS_MAST_RD_ADDR_ACK 0x40 +#define MV64x60_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48 +#define MV64x60_I2C_STATUS_MAST_RD_DATA_ACK 0x50 +#define MV64x60_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58 +#define MV64x60_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0 +#define MV64x60_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8 +#define MV64x60_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0 +#define MV64x60_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8 +#define MV64x60_I2C_STATUS_NO_STATUS 0xf8 + +static u8 *ctlr_base; + +static int mv64x60_i2c_wait_for_status(int wanted) +{ + int i; + int status; + + for (i=0; i<1000; i++) { + udelay(10); + status = in_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_STATUS)) + & 0xff; + if (status == wanted) + return status; + } + return -status; +} + +static int mv64x60_i2c_control(int control, int status) +{ + out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_CONTROL), control & 0xff); + return mv64x60_i2c_wait_for_status(status); +} + +static int mv64x60_i2c_read_byte(int control, int status) +{ + out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_CONTROL), control & 0xff); + if (mv64x60_i2c_wait_for_status(status) < 0) + return -1; + return in_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_DATA)) & 0xff; +} + +static int mv64x60_i2c_write_byte(int data, int control, int status) +{ + out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_DATA), data & 0xff); + out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_CONTROL), control & 0xff); + return mv64x60_i2c_wait_for_status(status); +} + +int mv64x60_i2c_read(u32 devaddr, u8 *buf, u32 offset, u32 offset_size, + u32 count) +{ + int i; + int data; + int control; + int status; + + if (ctlr_base == NULL) + return -1; + + /* send reset */ + out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_SOFT_RESET), 0); + out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_SLAVE_ADDR), 0); + out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_EXT_SLAVE_ADDR), 0); + out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_BAUD), (4 << 3) | 0x4); + + if (mv64x60_i2c_control(MV64x60_I2C_CONTROL_TWSIEN, + MV64x60_I2C_STATUS_NO_STATUS) < 0) + return -1; + + /* send start */ + control = MV64x60_I2C_CONTROL_START | MV64x60_I2C_CONTROL_TWSIEN; + status = MV64x60_I2C_STATUS_MAST_START; + if (mv64x60_i2c_control(control, status) < 0) + return -1; + + /* select device for writing */ + data = devaddr & ~0x1; + control = MV64x60_I2C_CONTROL_TWSIEN; + status = MV64x60_I2C_STATUS_MAST_WR_ADDR_ACK; + if (mv64x60_i2c_write_byte(data, control, status) < 0) + return -1; + + /* send offset of data */ + control = MV64x60_I2C_CONTROL_TWSIEN; + status = MV64x60_I2C_STATUS_MAST_WR_ACK; + if (offset_size > 1) { + if (mv64x60_i2c_write_byte(offset >> 8, control, status) < 0) + return -1; + } + if (mv64x60_i2c_write_byte(offset, control, status) < 0) + return -1; + + /* resend start */ + control = MV64x60_I2C_CONTROL_START | MV64x60_I2C_CONTROL_TWSIEN; + status = MV64x60_I2C_STATUS_MAST_REPEAT_START; + if (mv64x60_i2c_control(control, status) < 0) + return -1; + + /* select device for reading */ + data = devaddr | 0x1; + control = MV64x60_I2C_CONTROL_TWSIEN; + status = MV64x60_I2C_STATUS_MAST_RD_ADDR_ACK; + if (mv64x60_i2c_write_byte(data, control, status) < 0) + return -1; + + /* read all but last byte of data */ + control = MV64x60_I2C_CONTROL_ACK | MV64x60_I2C_CONTROL_TWSIEN; + status = MV64x60_I2C_STATUS_MAST_RD_DATA_ACK; + + for (i=1; i<count; i++) { + data = mv64x60_i2c_read_byte(control, status); + if (data < 0) { + printf("errors on iteration %d\n", i); + return -1; + } + *buf++ = data; + } + + /* read last byte of data */ + control = MV64x60_I2C_CONTROL_TWSIEN; + status = MV64x60_I2C_STATUS_MAST_RD_DATA_NO_ACK; + data = mv64x60_i2c_read_byte(control, status); + if (data < 0) + return -1; + *buf++ = data; + + /* send stop */ + control = MV64x60_I2C_CONTROL_STOP | MV64x60_I2C_CONTROL_TWSIEN; + status = MV64x60_I2C_STATUS_NO_STATUS; + if (mv64x60_i2c_control(control, status) < 0) + return -1; + + return count; +} + +int mv64x60_i2c_open(void) +{ + u32 v; + void *devp; + + devp = finddevice("/mv64x60/i2c"); + if (devp == NULL) + goto err_out; + if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v)) + goto err_out; + + ctlr_base = (u8 *)v; + return 0; + +err_out: + return -1; +} + +void mv64x60_i2c_close(void) +{ + ctlr_base = NULL; +} diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 73bd47a3a079..959124f3f9af 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h @@ -79,6 +79,7 @@ void start(void); int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); int serial_console_init(void); int ns16550_console_init(void *devp, struct serial_console_data *scdp); +int mpsc_console_init(void *devp, struct serial_console_data *scdp); void *simple_alloc_init(char *base, unsigned long heap_size, unsigned long granularity, unsigned long max_allocs); extern void flush_cache(void *, unsigned long); diff --git a/arch/powerpc/boot/prpmc2800.c b/arch/powerpc/boot/prpmc2800.c new file mode 100644 index 000000000000..f428bac10d4a --- /dev/null +++ b/arch/powerpc/boot/prpmc2800.c @@ -0,0 +1,577 @@ +/* + * Motorola ECC prpmc280/f101 & prpmc2800/f101e platform code. + * + * Author: Mark A. Greer <mgreer@mvista.com> + * + * 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <stdarg.h> +#include <stddef.h> +#include "types.h" +#include "elf.h" +#include "page.h" +#include "string.h" +#include "stdio.h" +#include "io.h" +#include "ops.h" +#include "gunzip_util.h" +#include "mv64x60.h" + +extern char _end[]; +extern char _vmlinux_start[], _vmlinux_end[]; +extern char _dtb_start[], _dtb_end[]; + +extern void udelay(long delay); + +#define KB 1024U +#define MB (KB*KB) +#define GB (KB*MB) +#define MHz (1000U*1000U) +#define GHz (1000U*MHz) + +#define BOARD_MODEL "PrPMC2800" +#define BOARD_MODEL_MAX 32 /* max strlen(BOARD_MODEL) + 1 */ + +#define EEPROM2_ADDR 0xa4 +#define EEPROM3_ADDR 0xa8 + +BSS_STACK(16*KB); + +static u8 *bridge_base; + +typedef enum { + BOARD_MODEL_PRPMC280, + BOARD_MODEL_PRPMC2800, +} prpmc2800_board_model; + +typedef enum { + BRIDGE_TYPE_MV64360, + BRIDGE_TYPE_MV64362, +} prpmc2800_bridge_type; + +struct prpmc2800_board_info { + prpmc2800_board_model model; + char variant; + prpmc2800_bridge_type bridge_type; + u8 subsys0; + u8 subsys1; + u8 vpd4; + u8 vpd4_mask; + u32 core_speed; + u32 mem_size; + u32 boot_flash; + u32 user_flash; +}; + +static struct prpmc2800_board_info prpmc2800_board_info[] = { + { + .model = BOARD_MODEL_PRPMC280, + .variant = 'a', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xff, + .subsys1 = 0xff, + .vpd4 = 0x00, + .vpd4_mask = 0x0f, + .core_speed = 1*GHz, + .mem_size = 512*MB, + .boot_flash = 1*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC280, + .variant = 'b', + .bridge_type = BRIDGE_TYPE_MV64362, + .subsys0 = 0xff, + .subsys1 = 0xff, + .vpd4 = 0x01, + .vpd4_mask = 0x0f, + .core_speed = 1*GHz, + .mem_size = 512*MB, + .boot_flash = 0, + .user_flash = 0, + }, + { + .model = BOARD_MODEL_PRPMC280, + .variant = 'c', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xff, + .subsys1 = 0xff, + .vpd4 = 0x02, + .vpd4_mask = 0x0f, + .core_speed = 733*MHz, + .mem_size = 512*MB, + .boot_flash = 1*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC280, + .variant = 'd', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xff, + .subsys1 = 0xff, + .vpd4 = 0x03, + .vpd4_mask = 0x0f, + .core_speed = 1*GHz, + .mem_size = 1*GB, + .boot_flash = 1*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC280, + .variant = 'e', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xff, + .subsys1 = 0xff, + .vpd4 = 0x04, + .vpd4_mask = 0x0f, + .core_speed = 1*GHz, + .mem_size = 512*MB, + .boot_flash = 1*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC280, + .variant = 'f', + .bridge_type = BRIDGE_TYPE_MV64362, + .subsys0 = 0xff, + .subsys1 = 0xff, + .vpd4 = 0x05, + .vpd4_mask = 0x0f, + .core_speed = 733*MHz, + .mem_size = 128*MB, + .boot_flash = 1*MB, + .user_flash = 0, + }, + { + .model = BOARD_MODEL_PRPMC280, + .variant = 'g', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xff, + .subsys1 = 0xff, + .vpd4 = 0x06, + .vpd4_mask = 0x0f, + .core_speed = 1*GHz, + .mem_size = 256*MB, + .boot_flash = 1*MB, + .user_flash = 0, + }, + { + .model = BOARD_MODEL_PRPMC280, + .variant = 'h', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xff, + .subsys1 = 0xff, + .vpd4 = 0x07, + .vpd4_mask = 0x0f, + .core_speed = 1*GHz, + .mem_size = 1*GB, + .boot_flash = 1*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC2800, + .variant = 'a', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xb2, + .subsys1 = 0x8c, + .vpd4 = 0x00, + .vpd4_mask = 0x00, + .core_speed = 1*GHz, + .mem_size = 512*MB, + .boot_flash = 2*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC2800, + .variant = 'b', + .bridge_type = BRIDGE_TYPE_MV64362, + .subsys0 = 0xb2, + .subsys1 = 0x8d, + .vpd4 = 0x00, + .vpd4_mask = 0x00, + .core_speed = 1*GHz, + .mem_size = 512*MB, + .boot_flash = 0, + .user_flash = 0, + }, + { + .model = BOARD_MODEL_PRPMC2800, + .variant = 'c', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xb2, + .subsys1 = 0x8e, + .vpd4 = 0x00, + .vpd4_mask = 0x00, + .core_speed = 733*MHz, + .mem_size = 512*MB, + .boot_flash = 2*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC2800, + .variant = 'd', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xb2, + .subsys1 = 0x8f, + .vpd4 = 0x00, + .vpd4_mask = 0x00, + .core_speed = 1*GHz, + .mem_size = 1*GB, + .boot_flash = 2*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC2800, + .variant = 'e', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xa2, + .subsys1 = 0x8a, + .vpd4 = 0x00, + .vpd4_mask = 0x00, + .core_speed = 1*GHz, + .mem_size = 512*MB, + .boot_flash = 2*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC2800, + .variant = 'f', + .bridge_type = BRIDGE_TYPE_MV64362, + .subsys0 = 0xa2, + .subsys1 = 0x8b, + .vpd4 = 0x00, + .vpd4_mask = 0x00, + .core_speed = 733*MHz, + .mem_size = 128*MB, + .boot_flash = 2*MB, + .user_flash = 0, + }, + { + .model = BOARD_MODEL_PRPMC2800, + .variant = 'g', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xa2, + .subsys1 = 0x8c, + .vpd4 = 0x00, + .vpd4_mask = 0x00, + .core_speed = 1*GHz, + .mem_size = 2*GB, + .boot_flash = 2*MB, + .user_flash = 64*MB, + }, + { + .model = BOARD_MODEL_PRPMC2800, + .variant = 'h', + .bridge_type = BRIDGE_TYPE_MV64360, + .subsys0 = 0xa2, + .subsys1 = 0x8d, + .vpd4 = 0x00, + .vpd4_mask = 0x00, + .core_speed = 733*MHz, + .mem_size = 1*GB, + .boot_flash = 2*MB, + .user_flash = 64*MB, + }, +}; + +static struct prpmc2800_board_info *prpmc2800_get_board_info(u8 *vpd) +{ + struct prpmc2800_board_info *bip; + int i; + + for (i=0,bip=prpmc2800_board_info; i<ARRAY_SIZE(prpmc2800_board_info); + i++,bip++) + if ((vpd[0] == bip->subsys0) && (vpd[1] == bip->subsys1) + && ((vpd[4] & bip->vpd4_mask) == bip->vpd4)) + return bip; + + return NULL; +} + +/* Get VPD from i2c eeprom 2, then match it to a board info entry */ +static struct prpmc2800_board_info *prpmc2800_get_bip(void) +{ + struct prpmc2800_board_info *bip; + u8 vpd[5]; + int rc; + + if (mv64x60_i2c_open()) + fatal("Error: Can't open i2c device\n\r"); + + /* Get VPD from i2c eeprom-2 */ + memset(vpd, 0, sizeof(vpd)); + rc = mv64x60_i2c_read(EEPROM2_ADDR, vpd, 0x1fde, 2, sizeof(vpd)); + if (rc < 0) + fatal("Error: Couldn't read eeprom2\n\r"); + mv64x60_i2c_close(); + + /* Get board type & related info */ + bip = prpmc2800_get_board_info(vpd); + if (bip == NULL) { + printf("Error: Unsupported board or corrupted VPD:\n\r"); + printf(" 0x%x 0x%x 0x%x 0x%x 0x%x\n\r", + vpd[0], vpd[1], vpd[2], vpd[3], vpd[4]); + printf("Using device tree defaults...\n\r"); + } + + return bip; +} + +static void prpmc2800_bridge_setup(u32 mem_size) +{ + u32 i, v[12], enables, acc_bits; + u32 pci_base_hi, pci_base_lo, size, buf[2]; + unsigned long cpu_base; + int rc; + void *devp; + u8 *bridge_pbase, is_coherent; + struct mv64x60_cpu2pci_win *tbl; + + bridge_pbase = mv64x60_get_bridge_pbase(); + is_coherent = mv64x60_is_coherent(); + + if (is_coherent) + acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_WB + | MV64x60_PCI_ACC_CNTL_SWAP_NONE + | MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES + | MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES; + else + acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_NONE + | MV64x60_PCI_ACC_CNTL_SWAP_NONE + | MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES + | MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES; + + mv64x60_config_ctlr_windows(bridge_base, bridge_pbase, is_coherent); + mv64x60_config_pci_windows(bridge_base, bridge_pbase, 0, 0, mem_size, + acc_bits); + + /* Get the cpu -> pci i/o & mem mappings from the device tree */ + devp = finddevice("/mv64x60/pci@80000000"); + if (devp == NULL) + fatal("Error: Missing /mv64x60/pci@80000000" + " device tree node\n\r"); + + rc = getprop(devp, "ranges", v, sizeof(v)); + if (rc != sizeof(v)) + fatal("Error: Can't find /mv64x60/pci@80000000/ranges" + " property\n\r"); + + /* Get the cpu -> pci i/o & mem mappings from the device tree */ + devp = finddevice("/mv64x60"); + if (devp == NULL) + fatal("Error: Missing /mv64x60 device tree node\n\r"); + + enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)); + enables |= 0x0007fe00; /* Disable all cpu->pci windows */ + out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables); + + for (i=0; i<12; i+=6) { + switch (v[i] & 0xff000000) { + case 0x01000000: /* PCI I/O Space */ + tbl = mv64x60_cpu2pci_io; + break; + case 0x02000000: /* PCI MEM Space */ + tbl = mv64x60_cpu2pci_mem; + break; + default: + continue; + } + + pci_base_hi = v[i+1]; + pci_base_lo = v[i+2]; + cpu_base = v[i+3]; + size = v[i+5]; + + buf[0] = cpu_base; + buf[1] = size; + + if (!dt_xlate_addr(devp, buf, sizeof(buf), &cpu_base)) + fatal("Error: Can't translate PCI address 0x%x\n\r", + (u32)cpu_base); + + mv64x60_config_cpu2pci_window(bridge_base, 0, pci_base_hi, + pci_base_lo, cpu_base, size, tbl); + } + + enables &= ~0x00000600; /* Enable cpu->pci0 i/o, cpu->pci0 mem0 */ + out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables); +} + +static void prpmc2800_fixups(void) +{ + u32 v[2], l, mem_size; + int rc; + void *devp; + char model[BOARD_MODEL_MAX]; + struct prpmc2800_board_info *bip; + + bip = prpmc2800_get_bip(); /* Get board info based on VPD */ + + mem_size = (bip) ? bip->mem_size : mv64x60_get_mem_size(bridge_base); + prpmc2800_bridge_setup(mem_size); /* Do necessary bridge setup */ + + /* If the VPD doesn't match what we know about, just use the + * defaults already in the device tree. + */ + if (!bip) + return; + + /* Know the board type so override device tree defaults */ + /* Set /model appropriately */ + devp = finddevice("/"); + if (devp == NULL) + fatal("Error: Missing '/' device tree node\n\r"); + memset(model, 0, BOARD_MODEL_MAX); + strncpy(model, BOARD_MODEL, BOARD_MODEL_MAX - 2); + l = strlen(model); + if (bip->model == BOARD_MODEL_PRPMC280) + l--; + model[l++] = bip->variant; + model[l++] = '\0'; + setprop(devp, "model", model, l); + + /* Set /cpus/PowerPC,7447/clock-frequency */ + devp = finddevice("/cpus/PowerPC,7447"); + if (devp == NULL) + fatal("Error: Missing proper /cpus device tree node\n\r"); + v[0] = bip->core_speed; + setprop(devp, "clock-frequency", &v[0], sizeof(v[0])); + + /* Set /memory/reg size */ + devp = finddevice("/memory"); + if (devp == NULL) + fatal("Error: Missing /memory device tree node\n\r"); + v[0] = 0; + v[1] = bip->mem_size; + setprop(devp, "reg", v, sizeof(v)); + + /* Update /mv64x60/model, if this is a mv64362 */ + if (bip->bridge_type == BRIDGE_TYPE_MV64362) { + devp = finddevice("/mv64x60"); + if (devp == NULL) + fatal("Error: Missing /mv64x60 device tree node\n\r"); + setprop(devp, "model", "mv64362", strlen("mv64362") + 1); + } + + /* Set User FLASH size */ + devp = finddevice("/mv64x60/flash@a0000000"); + if (devp == NULL) + fatal("Error: Missing User FLASH device tree node\n\r"); + rc = getprop(devp, "reg", v, sizeof(v)); + if (rc != sizeof(v)) + fatal("Error: Can't find User FLASH reg property\n\r"); + v[1] = bip->user_flash; + setprop(devp, "reg", v, sizeof(v)); +} + +#define MV64x60_MPP_CNTL_0 0xf000 +#define MV64x60_MPP_CNTL_2 0xf008 +#define MV64x60_GPP_IO_CNTL 0xf100 +#define MV64x60_GPP_LEVEL_CNTL 0xf110 +#define MV64x60_GPP_VALUE_SET 0xf118 + +static void prpmc2800_reset(void) +{ + u32 temp; + + udelay(5000000); + + if (bridge_base != 0) { + temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0)); + temp &= 0xFFFF0FFF; + out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0), temp); + + temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL)); + temp |= 0x00000004; + out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp); + + temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL)); + temp |= 0x00000004; + out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp); + + temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2)); + temp &= 0xFFFF0FFF; + out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2), temp); + + temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL)); + temp |= 0x00080000; + out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp); + + temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL)); + temp |= 0x00080000; + out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp); + + out_le32((u32 *)(bridge_base + MV64x60_GPP_VALUE_SET), + 0x00080004); + } + + for (;;); +} + +#define HEAP_SIZE (16*MB) +static struct gunzip_state gzstate; + +void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + struct elf_info ei; + char *heap_start, *dtb; + int dt_size = _dtb_end - _dtb_start; + void *vmlinuz_addr = _vmlinux_start; + unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start; + char elfheader[256]; + + if (dt_size <= 0) /* No fdt */ + exit(); + + /* + * Start heap after end of the kernel (after decompressed to + * address 0) or the end of the zImage, whichever is higher. + * That's so things allocated by simple_alloc won't overwrite + * any part of the zImage and the kernel won't overwrite the dtb + * when decompressed & relocated. + */ + gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size); + gunzip_exactly(&gzstate, elfheader, sizeof(elfheader)); + + if (!parse_elf32(elfheader, &ei)) + exit(); + + heap_start = (char *)(ei.memsize + ei.elfoffset); /* end of kernel*/ + heap_start = max(heap_start, (char *)_end); /* end of zImage */ + + if ((unsigned)simple_alloc_init(heap_start, HEAP_SIZE, 2*KB, 16) + > (128*MB)) + exit(); + + /* Relocate dtb to safe area past end of zImage & kernel */ + dtb = malloc(dt_size); + if (!dtb) + exit(); + memmove(dtb, _dtb_start, dt_size); + if (ft_init(dtb, dt_size, 16)) + exit(); + + bridge_base = mv64x60_get_bridge_base(); + + platform_ops.fixups = prpmc2800_fixups; + platform_ops.exit = prpmc2800_reset; + + if (serial_console_init() < 0) + exit(); +} + +/* _zimage_start called very early--need to turn off external interrupts */ +asm (" .globl _zimage_start\n\ + _zimage_start:\n\ + mfmsr 10\n\ + rlwinm 10,10,0,~(1<<15) /* Clear MSR_EE */\n\ + sync\n\ + mtmsr 10\n\ + isync\n\ + b _zimage_start_lib\n\ +"); diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c index e8de4cf59be7..7fd32330a9a5 100644 --- a/arch/powerpc/boot/serial.c +++ b/arch/powerpc/boot/serial.c @@ -125,6 +125,8 @@ int serial_console_init(void) if (!strcmp(compat, "ns16550")) rc = ns16550_console_init(devp, &serial_cd); + else if (!strcmp(compat, "marvell,mpsc")) + rc = mpsc_console_init(devp, &serial_cd); /* Add other serial console driver calls here */ diff --git a/arch/powerpc/configs/prpmc2800_defconfig b/arch/powerpc/configs/prpmc2800_defconfig new file mode 100644 index 000000000000..c70a73082007 --- /dev/null +++ b/arch/powerpc/configs/prpmc2800_defconfig @@ -0,0 +1,1442 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.21 +# Wed May 9 09:42:46 2007 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_ARCH_HAS_ILOG2_U32=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +# CONFIG_PPC_UDBG_16550 is not set +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_AUDIT_ARCH=y +CONFIG_GENERIC_BUG=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +CONFIG_CLASSIC32=y +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_PPC_8xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_PPC_FPU=y +# CONFIG_PPC_DCR_NATIVE is not set +# CONFIG_PPC_DCR_MMIO is not set +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_PPC_MM_SLICES is not set +# CONFIG_SMP is not set +CONFIG_NOT_COHERENT_CACHE=y +CONFIG_CONFIG_CHECK_CACHE_COHERENCY=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +CONFIG_BLOCK=y +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Platform support +# +# CONFIG_PPC_MULTIPLATFORM is not set +CONFIG_EMBEDDED6xx=y +# CONFIG_APUS is not set +# CONFIG_PPC_MPC52xx is not set +# CONFIG_PPC_MPC5200 is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +# CONFIG_PQ2ADS is not set +# CONFIG_LINKSTATION is not set +# CONFIG_MPC7448HPC2 is not set +# CONFIG_PPC_HOLLY is not set +CONFIG_PPC_PRPMC2800=y +CONFIG_MV64X60=y +# CONFIG_MPIC is not set +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +# CONFIG_PPC_RTAS is not set +# CONFIG_MMIO_NVRAM is not set +# CONFIG_PPC_MPC106 is not set +# CONFIG_PPC_970_NAP is not set +# CONFIG_PPC_INDIRECT_IO is not set +# CONFIG_GENERIC_IOMAP is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_TAU is not set +# CONFIG_CPM2 is not set + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +# CONFIG_KEXEC is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SECCOMP is not set +CONFIG_WANT_DEVICE_TREE=y +CONFIG_DEVICE_TREE="prpmc2800.dts" +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_PPC_INDIRECT_PCI=y +# CONFIG_PPC_INDIRECT_PCI_BE is not set +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set +CONFIG_ARCH_SUPPORTS_MSI=y +# CONFIG_PCI_MSI is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_CONSISTENT_START=0xff100000 +CONFIG_CONSISTENT_SIZE=0x00200000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNPACPI is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_BLINK is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_JMICRON is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT8213 is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SL82C105 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_TC86C001 is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_ESP_CORE is not set +# CONFIG_SCSI_SRP is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_SVW is not set +# CONFIG_ATA_PIIX is not set +CONFIG_SATA_MV=y +# CONFIG_SATA_NV is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIL24 is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +CONFIG_MACINTOSH_DRIVERS=y +# CONFIG_MAC_EMUMOUSEBTN is not set +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_FIXED_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +CONFIG_8139TOO=y +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_SC92031 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_MV643XX_ETH=y +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_MPSC=y +CONFIG_SERIAL_MPSC_CONSOLE=y +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_MPC is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +CONFIG_I2C_MV64XXX=y + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +# CONFIG_FB is not set +# CONFIG_FB_IBM_GXT4500 is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# HID Devices +# +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_PPC_OF is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1672 is not set +CONFIG_RTC_DRV_MAX6900=y +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# Auxiliary Display support +# + +# +# Virtualization +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Distributed Lock Manager +# +# CONFIG_DLM is not set +# CONFIG_UCC_SLOW is not set +# CONFIG_UCC_FAST is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index fd604968f9a2..477934558f06 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.21 -# Mon Apr 30 12:03:35 2007 +# Fri May 11 10:16:27 2007 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -40,6 +40,7 @@ CONFIG_PPC_FPU=y # CONFIG_PPC_OF_PLATFORM_PCI is not set CONFIG_ALTIVEC=y CONFIG_PPC_STD_MMU=y +# CONFIG_PPC_MM_SLICES is not set CONFIG_VIRT_CPU_ACCOUNTING=y CONFIG_SMP=y CONFIG_NR_CPUS=2 @@ -67,6 +68,7 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CPUSETS is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set @@ -87,12 +89,13 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set # # Loadable module support @@ -213,6 +216,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_RESOURCES_64BIT=y CONFIG_ZONE_DMA_FLAG=1 CONFIG_ARCH_MEMORY_PROBE=y +# CONFIG_PPC_HAS_HASH_64K is not set # CONFIG_PPC_64K_PAGES is not set # CONFIG_SCHED_SMT is not set CONFIG_PROC_DEVICETREE=y @@ -229,15 +233,12 @@ CONFIG_ZONE_DMA=y CONFIG_GENERIC_ISA_DMA=y # CONFIG_PCI is not set # CONFIG_PCI_DOMAINS is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set # # PCCARD (PCMCIA/CardBus) support # # CONFIG_PCCARD is not set - -# -# PCI Hotplug Support -# CONFIG_KERNEL_START=0xc000000000000000 # @@ -363,7 +364,9 @@ CONFIG_BT_HCIUSB_SCO=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set # # Device Drivers @@ -414,6 +417,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # # Misc devices # +# CONFIG_BLINK is not set # # ATA/ATAPI/MFM/RLL support @@ -447,6 +451,7 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports @@ -473,25 +478,7 @@ CONFIG_CHR_DEV_SG=m # Multi-device support (RAID and LVM) # # CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Macintosh device drivers -# -# CONFIG_MAC_EMUMOUSEBTN is not set -# CONFIG_WINDFARM is not set +# CONFIG_MACINTOSH_DRIVERS is not set # # Network device support @@ -519,6 +506,7 @@ CONFIG_MII=m # # Ethernet (10000 Mbit) # +CONFIG_MLX4_DEBUG=y # # Token Ring devices @@ -531,6 +519,25 @@ CONFIG_MII=m # CONFIG_WLAN_80211 is not set # +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +CONFIG_USB_PEGASUS=m +# CONFIG_USB_RTL8150 is not set +CONFIG_USB_USBNET_MII=m +CONFIG_USB_USBNET=m +# CONFIG_USB_NET_CDCETHER is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +CONFIG_USB_NET_MCS7830=m +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set + +# # Wan interfaces # # CONFIG_WAN is not set @@ -575,6 +582,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -609,15 +617,10 @@ CONFIG_LEGACY_PTY_COUNT=16 # IPMI # # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set -# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_HANGCHECK_TIMER is not set @@ -626,10 +629,6 @@ CONFIG_GEN_RTC=y # TPM devices # # CONFIG_TCG_TPM is not set - -# -# I2C support -# # CONFIG_I2C is not set # @@ -642,12 +641,7 @@ CONFIG_GEN_RTC=y # Dallas's 1-wire bus # # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set # # Multifunction device drivers @@ -669,12 +663,23 @@ CONFIG_GEN_RTC=y # Graphics support # # CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_SYS_FOPS is not set +CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -702,10 +707,6 @@ CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y - -# -# Logo configuration -# CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set @@ -768,6 +769,20 @@ CONFIG_HID=y # CONFIG_HID_DEBUG is not set # +# USB Input Devices +# +CONFIG_USB_HID=m +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set + +# # USB support # CONFIG_USB_ARCH_HAS_HCD=y @@ -827,56 +842,10 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_LIBUSUAL is not set # -# USB Input Devices -# -CONFIG_USB_HID=m -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -# CONFIG_USB_HIDDEV is not set - -# -# USB HID Boot Protocol drivers -# -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_TOUCHSCREEN is not set -# CONFIG_USB_YEALINK is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_GTCO is not set - -# # USB Imaging devices # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -CONFIG_USB_PEGASUS=m -# CONFIG_USB_RTL8150 is not set -CONFIG_USB_USBNET_MII=m -CONFIG_USB_USBNET=m -# CONFIG_USB_NET_CDCETHER is not set -# CONFIG_USB_NET_DM9601 is not set -# CONFIG_USB_NET_GL620A is not set -# CONFIG_USB_NET_NET1080 is not set -# CONFIG_USB_NET_PLUSB is not set -CONFIG_USB_NET_MCS7830=m -# CONFIG_USB_NET_RNDIS_HOST is not set -# CONFIG_USB_NET_CDC_SUBSET is not set -# CONFIG_USB_NET_ZAURUS is not set CONFIG_USB_MON=y # @@ -920,10 +889,6 @@ CONFIG_USB_MON=y # USB Gadget Support # # CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# # CONFIG_MMC is not set # @@ -966,14 +931,6 @@ CONFIG_USB_MON=y # # -# Auxiliary Display support -# - -# -# Virtualization -# - -# # File systems # CONFIG_EXT2_FS=m @@ -1071,6 +1028,7 @@ CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_BIND34 is not set CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1148,11 +1106,13 @@ CONFIG_NLS_ISO8859_1=y CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y # # Instrumentation Support @@ -1171,7 +1131,6 @@ CONFIG_ENABLE_MUST_CHECK=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set -CONFIG_LOG_BUF_SHIFT=17 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set @@ -1205,6 +1164,7 @@ CONFIG_PPC_EARLY_DEBUG=y # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set # CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set # CONFIG_PPC_EARLY_DEBUG_BEAT is not set +# CONFIG_PPC_EARLY_DEBUG_44x is not set # # Security options @@ -1234,6 +1194,7 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/powerpc/kernel/audit.c b/arch/powerpc/kernel/audit.c index 7fe5e6300e9a..a4dab7cab348 100644 --- a/arch/powerpc/kernel/audit.c +++ b/arch/powerpc/kernel/audit.c @@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ~0U }; +static unsigned signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + +int audit_classify_arch(int arch) +{ +#ifdef CONFIG_PPC64 + if (arch == AUDIT_ARCH_PPC) + return 1; +#endif + return 0; +} + int audit_classify_syscall(int abi, unsigned syscall) { #ifdef CONFIG_PPC64 @@ -51,15 +65,18 @@ static int __init audit_classes_init(void) extern __u32 ppc32_write_class[]; extern __u32 ppc32_read_class[]; extern __u32 ppc32_chattr_class[]; + extern __u32 ppc32_signal_class[]; audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class); audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class); audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL_32, ppc32_signal_class); #endif audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL, signal_class); return 0; } diff --git a/arch/powerpc/kernel/compat_audit.c b/arch/powerpc/kernel/compat_audit.c index 640d4bb29321..108ff14e2122 100644 --- a/arch/powerpc/kernel/compat_audit.c +++ b/arch/powerpc/kernel/compat_audit.c @@ -21,6 +21,11 @@ unsigned ppc32_read_class[] = { ~0U }; +unsigned ppc32_signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + int ppc32_classify_syscall(unsigned syscall) { switch(syscall) { diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 9ed4931af164..068377a2a8dc 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -173,7 +173,7 @@ void local_irq_restore(unsigned long en) lv1_get_version_info(&tmp); } - hard_irq_enable(); + __hard_irq_enable(); } #endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index b5c96af955c6..3786dcc8a7b6 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -24,7 +24,7 @@ /* Max address size we deal with */ #define OF_MAX_ADDR_CELLS 4 #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ - (ns) > 0) + (ns) >= 0) static struct of_bus *of_match_bus(struct device_node *np); static int __of_address_to_resource(struct device_node *dev, diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 370803722e47..ed07a198f8d6 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -530,3 +530,44 @@ void __init setup_panic(void) { atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block); } + +#ifdef CONFIG_CHECK_CACHE_COHERENCY +/* + * For platforms that have configurable cache-coherency. This function + * checks that the cache coherency setting of the kernel matches the setting + * left by the firmware, as indicated in the device tree. Since a mismatch + * will eventually result in DMA failures, we print * and error and call + * BUG() in that case. + */ + +#ifdef CONFIG_NOT_COHERENT_CACHE +#define KERNEL_COHERENCY 0 +#else +#define KERNEL_COHERENCY 1 +#endif + +static int __init check_cache_coherency(void) +{ + struct device_node *np; + const void *prop; + int devtree_coherency; + + np = of_find_node_by_path("/"); + prop = of_get_property(np, "coherency-off", NULL); + of_node_put(np); + + devtree_coherency = prop ? 0 : 1; + + if (devtree_coherency != KERNEL_COHERENCY) { + printk(KERN_ERR + "kernel coherency:%s != device tree_coherency:%s\n", + KERNEL_COHERENCY ? "on" : "off", + devtree_coherency ? "on" : "off"); + BUG(); + } + + return 0; +} + +late_initcall(check_cache_coherency); +#endif /* CONFIG_CHECK_CACHE_COHERENCY */ diff --git a/arch/powerpc/kernel/swsusp.c b/arch/powerpc/kernel/swsusp.c index 064a7ba4f02c..77b7b34b5955 100644 --- a/arch/powerpc/kernel/swsusp.c +++ b/arch/powerpc/kernel/swsusp.c @@ -36,8 +36,4 @@ void restore_processor_state(void) #ifdef CONFIG_PPC32 set_context(current->active_mm->context.id, current->active_mm->pgd); #endif - -#ifdef CONFIG_PPC64 - hard_irq_enable(); -#endif } diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 7cedef8f5f70..2c8564d54e4d 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -711,30 +711,15 @@ void wakeup_decrementer(void) void __init smp_space_timers(unsigned int max_cpus) { int i; - unsigned long half = tb_ticks_per_jiffy / 2; - unsigned long offset = tb_ticks_per_jiffy / max_cpus; u64 previous_tb = per_cpu(last_jiffy, boot_cpuid); /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ previous_tb -= tb_ticks_per_jiffy; - /* - * The stolen time calculation for POWER5 shared-processor LPAR - * systems works better if the two threads' timebase interrupts - * are staggered by half a jiffy with respect to each other. - */ + for_each_possible_cpu(i) { if (i == boot_cpuid) continue; - if (i == (boot_cpuid ^ 1)) - per_cpu(last_jiffy, i) = - per_cpu(last_jiffy, boot_cpuid) - half; - else if (i & 1) - per_cpu(last_jiffy, i) = - per_cpu(last_jiffy, i ^ 1) + half; - else { - previous_tb += offset; - per_cpu(last_jiffy, i) = previous_tb; - } + per_cpu(last_jiffy, i) = previous_tb; } } #endif diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 7d722eea4ea8..4a20d890e2f4 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -351,7 +351,7 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot, unsigned long hpte_r = hpte->r; unsigned long hpte_v = hpte->v; unsigned long avpn; - int i, size, shift, penc, avpnm_bits; + int i, size, shift, penc; if (!(hpte_v & HPTE_V_LARGE)) size = MMU_PAGE_4K; @@ -395,7 +395,7 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot, vpi = (vsid ^ (vsid << 25) ^ pteg) & htab_hash_mask; break; default: - avpn = vpi = psize = 0; + avpn = vpi = size = 0; } avpn |= (vpi << mmu_psize_defs[size].shift); } diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 8c20f0fb8651..812bf563ed65 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -43,12 +43,10 @@ static void cbe_power_save(void) unsigned long ctrl, thread_switch_control; /* - * We need to hard disable interrupts, but we also need to mark them - * hard disabled in the PACA so that the local_irq_enable() done by - * our caller upon return propertly hard enables. + * We need to hard disable interrupts, the local_irq_enable() done by + * our caller upon return will hard re-enable. */ hard_irq_disable(); - get_paca()->hard_enabled = 0; ctrl = mfspr(SPRN_CTRLF); diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 8f3c2a73e165..f2d26268ca6f 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig @@ -31,6 +31,14 @@ config PPC_HOLLY help Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval Board with TSI108/9 bridge (Hickory/Holly) + +config PPC_PRPMC2800 + bool "Motorola-PrPMC2800" + select MV64X60 + select NOT_COHERENT_CACHE + select WANT_DEVICE_TREE + help + This option enables support for the Motorola PrPMC2800 board endchoice config TSI108_BRIDGE @@ -46,6 +54,11 @@ config MPC10X_BRIDGE select PPC_INDIRECT_PCI default y +config MV64X60 + bool + select PPC_INDIRECT_PCI + select CONFIG_CHECK_CACHE_COHERENCY + config MPC10X_OPENPIC bool depends on LINKSTATION diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile index b39fe4f470d5..844947cfc5db 100644 --- a/arch/powerpc/platforms/embedded6xx/Makefile +++ b/arch/powerpc/platforms/embedded6xx/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o obj-$(CONFIG_PPC_HOLLY) += holly.o +obj-$(CONFIG_PPC_PRPMC2800) += prpmc2800.o diff --git a/arch/powerpc/platforms/embedded6xx/prpmc2800.c b/arch/powerpc/platforms/embedded6xx/prpmc2800.c new file mode 100644 index 000000000000..53420951dc53 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/prpmc2800.c @@ -0,0 +1,171 @@ +/* + * Board setup routines for the Motorola PrPMC2800 + * + * Author: Dale Farnsworth <dale@farnsworth.org> + * + * 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/seq_file.h> + +#include <asm/machdep.h> +#include <asm/prom.h> +#include <asm/system.h> +#include <asm/time.h> +#include <asm/kexec.h> + +#include <mm/mmu_decl.h> + +#include <sysdev/mv64x60.h> + +#define MV64x60_MPP_CNTL_0 0x0000 +#define MV64x60_MPP_CNTL_2 0x0008 + +#define MV64x60_GPP_IO_CNTL 0x0000 +#define MV64x60_GPP_LEVEL_CNTL 0x0010 +#define MV64x60_GPP_VALUE_SET 0x0018 + +#define PLATFORM_NAME_MAX 32 + +static char prpmc2800_platform_name[PLATFORM_NAME_MAX]; + +static void __iomem *mv64x60_mpp_reg_base; +static void __iomem *mv64x60_gpp_reg_base; + +static void __init prpmc2800_setup_arch(void) +{ + struct device_node *np; + phys_addr_t paddr; + const unsigned int *reg; + const unsigned int *prop; + + /* + * ioremap mpp and gpp registers in case they are later + * needed by prpmc2800_reset_board(). + */ + np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-mpp"); + reg = of_get_property(np, "reg", NULL); + paddr = of_translate_address(np, reg); + of_node_put(np); + mv64x60_mpp_reg_base = ioremap(paddr, reg[1]); + + np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-gpp"); + reg = of_get_property(np, "reg", NULL); + paddr = of_translate_address(np, reg); + of_node_put(np); + mv64x60_gpp_reg_base = ioremap(paddr, reg[1]); + + np = of_find_node_by_type(NULL, "cpu"); + prop = of_get_property(np, "clock-frequency", NULL); + if (prop) + loops_per_jiffy = *prop / HZ; + of_node_put(np); + +#ifdef CONFIG_PCI + mv64x60_pci_init(); +#endif + + printk("Motorola %s\n", prpmc2800_platform_name); +} + +static void prpmc2800_reset_board(void) +{ + u32 temp; + + local_irq_disable(); + + temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0); + temp &= 0xFFFF0FFF; + out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0, temp); + + temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL); + temp |= 0x00000004; + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp); + + temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL); + temp |= 0x00000004; + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp); + + temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2); + temp &= 0xFFFF0FFF; + out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2, temp); + + temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL); + temp |= 0x00080000; + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp); + + temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL); + temp |= 0x00080000; + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp); + + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_VALUE_SET, 0x00080004); +} + +static void prpmc2800_restart(char *cmd) +{ + volatile ulong i = 10000000; + + prpmc2800_reset_board(); + + while (i-- > 0); + panic("restart failed\n"); +} + +#ifdef CONFIG_NOT_COHERENT_CACHE +#define PPRPM2800_COHERENCY_SETTING "off" +#else +#define PPRPM2800_COHERENCY_SETTING "on" +#endif + +void prpmc2800_show_cpuinfo(struct seq_file *m) +{ + uint memsize = total_memory; + + seq_printf(m, "Vendor\t\t: Motorola\n"); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); + seq_printf(m, "coherency\t: %s\n", PPRPM2800_COHERENCY_SETTING); +} + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init prpmc2800_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + unsigned long len = PLATFORM_NAME_MAX; + void *m; + + if (!of_flat_dt_is_compatible(root, "motorola,PrPMC2800")) + return 0; + + /* Update ppc_md.name with name from dt */ + m = of_get_flat_dt_prop(root, "model", &len); + if (m) + strncpy(prpmc2800_platform_name, m, + min((int)len, PLATFORM_NAME_MAX - 1)); + + return 1; +} + +define_machine(prpmc2800){ + .name = prpmc2800_platform_name, + .probe = prpmc2800_probe, + .setup_arch = prpmc2800_setup_arch, + .show_cpuinfo = prpmc2800_show_cpuinfo, + .init_IRQ = mv64x60_init_irq, + .get_irq = mv64x60_get_irq, + .restart = prpmc2800_restart, + .calibrate_decr = generic_calibrate_decr, +#ifdef CONFIG_KEXEC + .machine_kexec = default_machine_kexec, + .machine_kexec_prepare = default_machine_kexec_prepare, + .machine_crash_shutdown = default_machine_crash_shutdown, +#endif +}; diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c index 5985ce0c5c48..03cd45d8fefa 100644 --- a/arch/powerpc/platforms/pasemi/idle.c +++ b/arch/powerpc/platforms/pasemi/idle.c @@ -22,6 +22,7 @@ #include <linux/kernel.h> #include <linux/string.h> +#include <linux/irq.h> #include <asm/machdep.h> #include <asm/reg.h> diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index c9894933084f..935396766621 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -99,6 +99,7 @@ static void ps3_panic(char *str) while(1); } +#ifdef CONFIG_FB_PS3 static void prealloc(struct ps3_prealloc *p) { if (!p->size) @@ -115,7 +116,6 @@ static void prealloc(struct ps3_prealloc *p) p->address); } -#ifdef CONFIG_FB_PS3 struct ps3_prealloc ps3fb_videomemory = { .name = "ps3fb videomemory", .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024, diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c index 8729348c0608..53416ec5198b 100644 --- a/arch/powerpc/platforms/ps3/smp.c +++ b/arch/powerpc/platforms/ps3/smp.c @@ -118,9 +118,11 @@ static void __init ps3_smp_setup_cpu(int cpu) DBG("%s:%d: (%d, %d) => virq %u\n", __func__, __LINE__, cpu, i, virqs[i]); + result = request_irq(virqs[i], ipi_function_handler, + IRQF_DISABLED, names[i], (void*)(long)i); - request_irq(virqs[i], ipi_function_handler, IRQF_DISABLED, - names[i], (void*)(long)i); + if (result) + virqs[i] = NO_IRQ; } ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]); diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 3c48cce98a5c..6bda51027cc6 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -274,13 +274,13 @@ static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { - struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); - int i; - #if defined(CONFIG_PS3_DYNAMIC_DMA) BUG_ON("do"); return -EPERM; #else + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + int i; + for (i = 0; i < nents; i++, sg++) { int result = ps3_dma_map(dev->d_region, page_to_phys(sg->page) + sg->offset, sg->length, diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 9ce775c38ab7..c3ce0bd12c0b 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_FSL_SOC) += fsl_soc.o obj-$(CONFIG_FSL_PCIE) += fsl_pcie.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ +mv64x60-$(CONFIG_PCI) += mv64x60_pci.o +obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o # contains only the suspend handler for time obj-$(CONFIG_PM) += timer.o diff --git a/arch/powerpc/sysdev/mv64x60.h b/arch/powerpc/sysdev/mv64x60.h new file mode 100644 index 000000000000..2ff0b4ef2681 --- /dev/null +++ b/arch/powerpc/sysdev/mv64x60.h @@ -0,0 +1,11 @@ +#ifndef __MV64X60_H__ +#define __MV64X60_H__ + +#include <linux/init.h> + +extern void __init mv64x60_init_irq(void); +extern unsigned int mv64x60_get_irq(void); + +extern void __init mv64x60_pci_init(void); + +#endif /* __MV64X60_H__ */ diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c new file mode 100644 index 000000000000..4b0a9c88eeb3 --- /dev/null +++ b/arch/powerpc/sysdev/mv64x60_dev.c @@ -0,0 +1,422 @@ +/* + * Platform device setup for Marvell mv64360/mv64460 host bridges (Discovery) + * + * Author: Dale Farnsworth <dale@farnsworth.org> + * + * 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/mv643xx.h> +#include <linux/platform_device.h> + +#include <asm/prom.h> + +/* + * These functions provide the necessary setup for the mv64x60 drivers. + * These drivers are unusual in that they work on both the MIPS and PowerPC + * architectures. Because of that, the drivers do not support the normal + * PowerPC of_platform_bus_type. They support platform_bus_type instead. + */ + +/* + * Create MPSC platform devices + */ +static int __init mv64x60_mpsc_register_shared_pdev(struct device_node *np) +{ + struct platform_device *pdev; + struct resource r[2]; + struct mpsc_shared_pdata pdata; + const phandle *ph; + struct device_node *mpscrouting, *mpscintr; + int err; + + ph = of_get_property(np, "mpscrouting", NULL); + mpscrouting = of_find_node_by_phandle(*ph); + if (!mpscrouting) + return -ENODEV; + + err = of_address_to_resource(mpscrouting, 0, &r[0]); + of_node_put(mpscrouting); + if (err) + return err; + + ph = of_get_property(np, "mpscintr", NULL); + mpscintr = of_find_node_by_phandle(*ph); + if (!mpscintr) + return -ENODEV; + + err = of_address_to_resource(mpscintr, 0, &r[1]); + of_node_put(mpscintr); + if (err) + return err; + + memset(&pdata, 0, sizeof(pdata)); + + pdev = platform_device_alloc(MPSC_SHARED_NAME, 0); + if (!pdev) + return -ENOMEM; + + err = platform_device_add_resources(pdev, r, 2); + if (err) + goto error; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto error; + + err = platform_device_add(pdev); + if (err) + goto error; + + return 0; + +error: + platform_device_put(pdev); + return err; +} + + +static int __init mv64x60_mpsc_device_setup(struct device_node *np, int id) +{ + struct resource r[5]; + struct mpsc_pdata pdata; + struct platform_device *pdev; + const unsigned int *prop; + const phandle *ph; + struct device_node *sdma, *brg; + int err; + int port_number; + + /* only register the shared platform device the first time through */ + if (id == 0 && (err = mv64x60_mpsc_register_shared_pdev(np))) + return err; + + memset(r, 0, sizeof(r)); + + err = of_address_to_resource(np, 0, &r[0]); + if (err) + return err; + + of_irq_to_resource(np, 0, &r[4]); + + ph = of_get_property(np, "sdma", NULL); + sdma = of_find_node_by_phandle(*ph); + if (!sdma) + return -ENODEV; + + of_irq_to_resource(sdma, 0, &r[3]); + err = of_address_to_resource(sdma, 0, &r[1]); + of_node_put(sdma); + if (err) + return err; + + ph = of_get_property(np, "brg", NULL); + brg = of_find_node_by_phandle(*ph); + if (!brg) + return -ENODEV; + + err = of_address_to_resource(brg, 0, &r[2]); + of_node_put(brg); + if (err) + return err; + + prop = of_get_property(np, "block-index", NULL); + if (!prop) + return -ENODEV; + port_number = *(int *)prop; + + memset(&pdata, 0, sizeof(pdata)); + + pdata.cache_mgmt = 1; /* All current revs need this set */ + + prop = of_get_property(np, "max_idle", NULL); + if (prop) + pdata.max_idle = *prop; + + prop = of_get_property(brg, "current-speed", NULL); + if (prop) + pdata.default_baud = *prop; + + /* Default is 8 bits, no parity, no flow control */ + pdata.default_bits = 8; + pdata.default_parity = 'n'; + pdata.default_flow = 'n'; + + prop = of_get_property(np, "chr_1", NULL); + if (prop) + pdata.chr_1_val = *prop; + + prop = of_get_property(np, "chr_2", NULL); + if (prop) + pdata.chr_2_val = *prop; + + prop = of_get_property(np, "chr_10", NULL); + if (prop) + pdata.chr_10_val = *prop; + + prop = of_get_property(np, "mpcr", NULL); + if (prop) + pdata.mpcr_val = *prop; + + prop = of_get_property(brg, "bcr", NULL); + if (prop) + pdata.bcr_val = *prop; + + pdata.brg_can_tune = 1; /* All current revs need this set */ + + prop = of_get_property(brg, "clock-src", NULL); + if (prop) + pdata.brg_clk_src = *prop; + + prop = of_get_property(brg, "clock-frequency", NULL); + if (prop) + pdata.brg_clk_freq = *prop; + + pdev = platform_device_alloc(MPSC_CTLR_NAME, port_number); + if (!pdev) + return -ENOMEM; + + err = platform_device_add_resources(pdev, r, 5); + if (err) + goto error; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto error; + + err = platform_device_add(pdev); + if (err) + goto error; + + return 0; + +error: + platform_device_put(pdev); + return err; +} + +/* + * Create mv64x60_eth platform devices + */ +static int __init eth_register_shared_pdev(struct device_node *np) +{ + struct platform_device *pdev; + struct resource r[1]; + int err; + + np = of_get_parent(np); + if (!np) + return -ENODEV; + + err = of_address_to_resource(np, 0, &r[0]); + of_node_put(np); + if (err) + return err; + + pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, 0, + r, 1); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + return 0; +} + +static int __init mv64x60_eth_device_setup(struct device_node *np, int id) +{ + struct resource r[1]; + struct mv643xx_eth_platform_data pdata; + struct platform_device *pdev; + struct device_node *phy; + const u8 *mac_addr; + const int *prop; + const phandle *ph; + int err; + + /* only register the shared platform device the first time through */ + if (id == 0 && (err = eth_register_shared_pdev(np))) + return err;; + + memset(r, 0, sizeof(r)); + of_irq_to_resource(np, 0, &r[0]); + + memset(&pdata, 0, sizeof(pdata)); + + prop = of_get_property(np, "block-index", NULL); + if (!prop) + return -ENODEV; + pdata.port_number = *prop; + + mac_addr = of_get_mac_address(np); + if (mac_addr) + memcpy(pdata.mac_addr, mac_addr, 6); + + prop = of_get_property(np, "speed", NULL); + if (prop) + pdata.speed = *prop; + + prop = of_get_property(np, "tx_queue_size", NULL); + if (prop) + pdata.tx_queue_size = *prop; + + prop = of_get_property(np, "rx_queue_size", NULL); + if (prop) + pdata.rx_queue_size = *prop; + + prop = of_get_property(np, "tx_sram_addr", NULL); + if (prop) + pdata.tx_sram_addr = *prop; + + prop = of_get_property(np, "tx_sram_size", NULL); + if (prop) + pdata.tx_sram_size = *prop; + + prop = of_get_property(np, "rx_sram_addr", NULL); + if (prop) + pdata.rx_sram_addr = *prop; + + prop = of_get_property(np, "rx_sram_size", NULL); + if (prop) + pdata.rx_sram_size = *prop; + + ph = of_get_property(np, "phy", NULL); + if (!ph) + return -ENODEV; + + phy = of_find_node_by_phandle(*ph); + if (phy == NULL) + return -ENODEV; + + prop = of_get_property(phy, "reg", NULL); + if (prop) { + pdata.force_phy_addr = 1; + pdata.phy_addr = *prop; + } + + of_node_put(phy); + + pdev = platform_device_alloc(MV643XX_ETH_NAME, pdata.port_number); + if (!pdev) + return -ENOMEM; + + err = platform_device_add_resources(pdev, r, 1); + if (err) + goto error; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto error; + + err = platform_device_add(pdev); + if (err) + goto error; + + return 0; + +error: + platform_device_put(pdev); + return err; +} + +/* + * Create mv64x60_i2c platform devices + */ +static int __init mv64x60_i2c_device_setup(struct device_node *np, int id) +{ + struct resource r[2]; + struct platform_device *pdev; + struct mv64xxx_i2c_pdata pdata; + const unsigned int *prop; + int err; + + memset(r, 0, sizeof(r)); + + err = of_address_to_resource(np, 0, &r[0]); + if (err) + return err; + + of_irq_to_resource(np, 0, &r[1]); + + memset(&pdata, 0, sizeof(pdata)); + + prop = of_get_property(np, "freq_m", NULL); + if (!prop) + return -ENODEV; + pdata.freq_m = *prop; + + prop = of_get_property(np, "freq_n", NULL); + if (!prop) + return -ENODEV; + pdata.freq_n = *prop; + + prop = of_get_property(np, "timeout", NULL); + if (prop) + pdata.timeout = *prop; + else + pdata.timeout = 1000; /* 1 second */ + + prop = of_get_property(np, "retries", NULL); + if (prop) + pdata.retries = *prop; + else + pdata.retries = 1; + + pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id); + if (!pdev) + return -ENOMEM; + + err = platform_device_add_resources(pdev, r, 2); + if (err) + goto error; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto error; + + err = platform_device_add(pdev); + if (err) + goto error; + + return 0; + +error: + platform_device_put(pdev); + return err; +} + +static int __init mv64x60_device_setup(void) +{ + struct device_node *np = NULL; + int id; + int err; + + for (id = 0; + (np = of_find_compatible_node(np, "serial", "marvell,mpsc")); id++) + if ((err = mv64x60_mpsc_device_setup(np, id))) + goto error; + + for (id = 0; + (np = of_find_compatible_node(np, "network", + "marvell,mv64x60-eth")); + id++) + if ((err = mv64x60_eth_device_setup(np, id))) + goto error; + + for (id = 0; + (np = of_find_compatible_node(np, "i2c", "marvell,mv64x60-i2c")); + id++) + if ((err = mv64x60_i2c_device_setup(np, id))) + goto error; + + return 0; + +error: + of_node_put(np); + return err; +} +arch_initcall(mv64x60_device_setup); diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c new file mode 100644 index 000000000000..b5aef4cbc8d2 --- /dev/null +++ b/arch/powerpc/sysdev/mv64x60_pci.c @@ -0,0 +1,172 @@ +/* + * PCI bus setup for Marvell mv64360/mv64460 host bridges (Discovery) + * + * Author: Dale Farnsworth <dale@farnsworth.org> + * + * 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/pci.h> + +#include <asm/prom.h> +#include <asm/pci-bridge.h> + +#define PCI_HEADER_TYPE_INVALID 0x7f /* Invalid PCI header type */ + +#ifdef CONFIG_SYSFS +/* 32-bit hex or dec stringified number + '\n' */ +#define MV64X60_VAL_LEN_MAX 11 +#define MV64X60_PCICFG_CPCI_HOTSWAP 0x68 + +static ssize_t mv64x60_hs_reg_read(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct pci_dev *phb; + u32 v; + + if (off > 0) + return 0; + if (count < MV64X60_VAL_LEN_MAX) + return -EINVAL; + + phb = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); + if (!phb) + return -ENODEV; + pci_read_config_dword(phb, MV64X60_PCICFG_CPCI_HOTSWAP, &v); + pci_dev_put(phb); + + return sprintf(buf, "0x%08x\n", v); +} + +static ssize_t mv64x60_hs_reg_write(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct pci_dev *phb; + u32 v; + + if (off > 0) + return 0; + if (count <= 0) + return -EINVAL; + + if (sscanf(buf, "%i", &v) != 1) + return -EINVAL; + + phb = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); + if (!phb) + return -ENODEV; + pci_write_config_dword(phb, MV64X60_PCICFG_CPCI_HOTSWAP, v); + pci_dev_put(phb); + + return count; +} + +static struct bin_attribute mv64x60_hs_reg_attr = { /* Hotswap register */ + .attr = { + .name = "hs_reg", + .mode = S_IRUGO | S_IWUSR, + .owner = THIS_MODULE, + }, + .size = MV64X60_VAL_LEN_MAX, + .read = mv64x60_hs_reg_read, + .write = mv64x60_hs_reg_write, +}; + +static int __init mv64x60_sysfs_init(void) +{ + struct device_node *np; + struct platform_device *pdev; + const unsigned int *prop; + + np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60"); + if (!np) + return 0; + + prop = of_get_property(np, "hs_reg_valid", NULL); + of_node_put(np); + + pdev = platform_device_register_simple("marvell,mv64x60", 0, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + return sysfs_create_bin_file(&pdev->dev.kobj, &mv64x60_hs_reg_attr); +} + +subsys_initcall(mv64x60_sysfs_init); + +#endif /* CONFIG_SYSFS */ + +static void __init mv64x60_pci_fixup_early(struct pci_dev *dev) +{ + /* + * Set the host bridge hdr_type to an invalid value so that + * pci_setup_device() will ignore the host bridge. + */ + dev->hdr_type = PCI_HEADER_TYPE_INVALID; +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360, + mv64x60_pci_fixup_early); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64460, + mv64x60_pci_fixup_early); + +static int __init mv64x60_add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + const int *bus_range; + int primary; + + memset(&rsrc, 0, sizeof(rsrc)); + + /* Fetch host bridge registers address */ + if (of_address_to_resource(dev, 0, &rsrc)) { + printk(KERN_ERR "No PCI reg property in device tree\n"); + return -ENODEV; + } + + /* Get bus range if any */ + bus_range = of_get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + + hose->arch_data = dev; + hose->set_cfg_type = 1; + + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + setup_indirect_pci(hose, rsrc.start, rsrc.start + 4); + hose->bus_offset = hose->first_busno; + + printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. " + "Firmware bus number: %d->%d\n", + (unsigned long long)rsrc.start, hose->first_busno, + hose->last_busno); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + primary = (hose->first_busno == 0); + pci_process_bridge_OF_ranges(hose, dev, primary); + + return 0; +} + +void __init mv64x60_pci_init(void) +{ + struct device_node *np = NULL; + + while ((np = of_find_compatible_node(np, "pci", "marvell,mv64x60-pci"))) + mv64x60_add_bridge(np); +} diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c new file mode 100644 index 000000000000..01d316287772 --- /dev/null +++ b/arch/powerpc/sysdev/mv64x60_pic.c @@ -0,0 +1,305 @@ +/* + * Interrupt handling for Marvell mv64360/mv64460 host bridges (Discovery) + * + * Author: Dale Farnsworth <dale@farnsworth.org> + * + * 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> + +#include <asm/byteorder.h> +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/irq.h> + +#include "mv64x60.h" + +/* Interrupt Controller Interface Registers */ +#define MV64X60_IC_MAIN_CAUSE_LO 0x0004 +#define MV64X60_IC_MAIN_CAUSE_HI 0x000c +#define MV64X60_IC_CPU0_INTR_MASK_LO 0x0014 +#define MV64X60_IC_CPU0_INTR_MASK_HI 0x001c +#define MV64X60_IC_CPU0_SELECT_CAUSE 0x0024 + +#define MV64X60_HIGH_GPP_GROUPS 0x0f000000 +#define MV64X60_SELECT_CAUSE_HIGH 0x40000000 + +/* General Purpose Pins Controller Interface Registers */ +#define MV64x60_GPP_INTR_CAUSE 0x0008 +#define MV64x60_GPP_INTR_MASK 0x000c + +#define MV64x60_LEVEL1_LOW 0 +#define MV64x60_LEVEL1_HIGH 1 +#define MV64x60_LEVEL1_GPP 2 + +#define MV64x60_LEVEL1_MASK 0x00000060 +#define MV64x60_LEVEL1_OFFSET 5 + +#define MV64x60_LEVEL2_MASK 0x0000001f + +#define MV64x60_NUM_IRQS 96 + +static DEFINE_SPINLOCK(mv64x60_lock); + +static void __iomem *mv64x60_irq_reg_base; +static void __iomem *mv64x60_gpp_reg_base; + +/* + * Interrupt Controller Handling + * + * The interrupt controller handles three groups of interrupts: + * main low: IRQ0-IRQ31 + * main high: IRQ32-IRQ63 + * gpp: IRQ64-IRQ95 + * + * This code handles interrupts in two levels. Level 1 selects the + * interrupt group, and level 2 selects an IRQ within that group. + * Each group has its own irq_chip structure. + */ + +static u32 mv64x60_cached_low_mask; +static u32 mv64x60_cached_high_mask = MV64X60_HIGH_GPP_GROUPS; +static u32 mv64x60_cached_gpp_mask; + +static struct irq_host *mv64x60_irq_host; + +/* + * mv64x60_chip_low functions + */ + +static void mv64x60_mask_low(unsigned int virq) +{ + int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK; + unsigned long flags; + + spin_lock_irqsave(&mv64x60_lock, flags); + mv64x60_cached_low_mask &= ~(1 << level2); + out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO, + mv64x60_cached_low_mask); + spin_unlock_irqrestore(&mv64x60_lock, flags); + (void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO); +} + +static void mv64x60_unmask_low(unsigned int virq) +{ + int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK; + unsigned long flags; + + spin_lock_irqsave(&mv64x60_lock, flags); + mv64x60_cached_low_mask |= 1 << level2; + out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO, + mv64x60_cached_low_mask); + spin_unlock_irqrestore(&mv64x60_lock, flags); + (void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO); +} + +static struct irq_chip mv64x60_chip_low = { + .name = "mv64x60_low", + .mask = mv64x60_mask_low, + .mask_ack = mv64x60_mask_low, + .unmask = mv64x60_unmask_low, +}; + +/* + * mv64x60_chip_high functions + */ + +static void mv64x60_mask_high(unsigned int virq) +{ + int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK; + unsigned long flags; + + spin_lock_irqsave(&mv64x60_lock, flags); + mv64x60_cached_high_mask &= ~(1 << level2); + out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI, + mv64x60_cached_high_mask); + spin_unlock_irqrestore(&mv64x60_lock, flags); + (void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI); +} + +static void mv64x60_unmask_high(unsigned int virq) +{ + int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK; + unsigned long flags; + + spin_lock_irqsave(&mv64x60_lock, flags); + mv64x60_cached_high_mask |= 1 << level2; + out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI, + mv64x60_cached_high_mask); + spin_unlock_irqrestore(&mv64x60_lock, flags); + (void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI); +} + +static struct irq_chip mv64x60_chip_high = { + .name = "mv64x60_high", + .mask = mv64x60_mask_high, + .mask_ack = mv64x60_mask_high, + .unmask = mv64x60_unmask_high, +}; + +/* + * mv64x60_chip_gpp functions + */ + +static void mv64x60_mask_gpp(unsigned int virq) +{ + int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK; + unsigned long flags; + + spin_lock_irqsave(&mv64x60_lock, flags); + mv64x60_cached_gpp_mask &= ~(1 << level2); + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK, + mv64x60_cached_gpp_mask); + spin_unlock_irqrestore(&mv64x60_lock, flags); + (void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK); +} + +static void mv64x60_mask_ack_gpp(unsigned int virq) +{ + int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK; + unsigned long flags; + + spin_lock_irqsave(&mv64x60_lock, flags); + mv64x60_cached_gpp_mask &= ~(1 << level2); + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK, + mv64x60_cached_gpp_mask); + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_CAUSE, + ~(1 << level2)); + spin_unlock_irqrestore(&mv64x60_lock, flags); + (void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_CAUSE); +} + +static void mv64x60_unmask_gpp(unsigned int virq) +{ + int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK; + unsigned long flags; + + spin_lock_irqsave(&mv64x60_lock, flags); + mv64x60_cached_gpp_mask |= 1 << level2; + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK, + mv64x60_cached_gpp_mask); + spin_unlock_irqrestore(&mv64x60_lock, flags); + (void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK); +} + +static struct irq_chip mv64x60_chip_gpp = { + .name = "mv64x60_gpp", + .mask = mv64x60_mask_gpp, + .mask_ack = mv64x60_mask_ack_gpp, + .unmask = mv64x60_unmask_gpp, +}; + +/* + * mv64x60_host_ops functions + */ + +static int mv64x60_host_match(struct irq_host *h, struct device_node *np) +{ + return mv64x60_irq_host->host_data == np; +} + +static struct irq_chip *mv64x60_chips[] = { + [MV64x60_LEVEL1_LOW] = &mv64x60_chip_low, + [MV64x60_LEVEL1_HIGH] = &mv64x60_chip_high, + [MV64x60_LEVEL1_GPP] = &mv64x60_chip_gpp, +}; + +static int mv64x60_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hwirq) +{ + int level1; + + get_irq_desc(virq)->status |= IRQ_LEVEL; + + level1 = (hwirq & MV64x60_LEVEL1_MASK) >> MV64x60_LEVEL1_OFFSET; + BUG_ON(level1 > MV64x60_LEVEL1_GPP); + set_irq_chip_and_handler(virq, mv64x60_chips[level1], handle_level_irq); + + return 0; +} + +static struct irq_host_ops mv64x60_host_ops = { + .match = mv64x60_host_match, + .map = mv64x60_host_map, +}; + +/* + * Global functions + */ + +void __init mv64x60_init_irq(void) +{ + struct device_node *np; + phys_addr_t paddr; + unsigned int size; + const unsigned int *reg; + unsigned long flags; + + np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-gpp"); + reg = of_get_property(np, "reg", &size); + paddr = of_translate_address(np, reg); + mv64x60_gpp_reg_base = ioremap(paddr, reg[1]); + of_node_put(np); + + np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-pic"); + reg = of_get_property(np, "reg", &size); + paddr = of_translate_address(np, reg); + of_node_put(np); + mv64x60_irq_reg_base = ioremap(paddr, reg[1]); + + mv64x60_irq_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, MV64x60_NUM_IRQS, + &mv64x60_host_ops, MV64x60_NUM_IRQS); + + mv64x60_irq_host->host_data = np; + + spin_lock_irqsave(&mv64x60_lock, flags); + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK, + mv64x60_cached_gpp_mask); + out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO, + mv64x60_cached_low_mask); + out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI, + mv64x60_cached_high_mask); + + out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_CAUSE, 0); + out_le32(mv64x60_irq_reg_base + MV64X60_IC_MAIN_CAUSE_LO, 0); + out_le32(mv64x60_irq_reg_base + MV64X60_IC_MAIN_CAUSE_HI, 0); + spin_unlock_irqrestore(&mv64x60_lock, flags); +} + +unsigned int mv64x60_get_irq(void) +{ + u32 cause; + int level1; + irq_hw_number_t hwirq; + int virq = NO_IRQ; + + cause = in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_SELECT_CAUSE); + if (cause & MV64X60_SELECT_CAUSE_HIGH) { + cause &= mv64x60_cached_high_mask; + level1 = MV64x60_LEVEL1_HIGH; + if (cause & MV64X60_HIGH_GPP_GROUPS) { + cause = in_le32(mv64x60_gpp_reg_base + + MV64x60_GPP_INTR_CAUSE); + cause &= mv64x60_cached_gpp_mask; + level1 = MV64x60_LEVEL1_GPP; + } + } else { + cause &= mv64x60_cached_low_mask; + level1 = MV64x60_LEVEL1_LOW; + } + if (cause) { + hwirq = (level1 << MV64x60_LEVEL1_OFFSET) | __ilog2(cause); + virq = irq_linear_revmap(mv64x60_irq_host, hwirq); + } + + return virq; +} diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index e35483961b90..efa0a56e230b 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -3,7 +3,7 @@ * * Based on drivers/char/serial_amba.c, by ARM Ltd. * - * Copyright 2001 IBM Crop. + * Copyright 2001 IBM Corp. * Author: IBM China Research Lab * Yudong Yang <yangyud@cn.ibm.com> * Yi Ge <geyi@cn.ibm.com> @@ -155,16 +155,16 @@ /* serial port transmit command register */ -#define _TxCR_ET_MASK 0x80 /* transmiter enable mask */ +#define _TxCR_ET_MASK 0x80 /* transmitter enable mask */ #define _TxCR_DME_MASK 0x60 /* dma mode mask */ #define _TxCR_TIE_MASK 0x10 /* empty interrupt enable mask */ #define _TxCR_EIE_MASK 0x08 /* error interrupt enable mask */ #define _TxCR_SPE_MASK 0x04 /* stop/pause mask */ #define _TxCR_TB_MASK 0x02 /* transmit break mask */ -#define _TxCR_ET_ENABLE _TxCR_ET_MASK /* transmiter enabled */ -#define _TxCR_DME_DISABLE 0x00 /* transmiter disabled, TBR intr disabled */ -#define _TxCR_DME_TBR 0x20 /* transmiter disabled, TBR intr enabled */ +#define _TxCR_ET_ENABLE _TxCR_ET_MASK /* transmitter enabled */ +#define _TxCR_DME_DISABLE 0x00 /* transmitter disabled, TBR intr disabled */ +#define _TxCR_DME_TBR 0x20 /* transmitter disabled, TBR intr enabled */ #define _TxCR_DME_CHAN_2 0x40 /* dma enabled, destination chann 2 */ #define _TxCR_DME_CHAN_3 0x60 /* dma enabled, destination chann 3 */ diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c index e2c6210f234b..7088428e1fe2 100644 --- a/arch/ppc/8xx_io/commproc.c +++ b/arch/ppc/8xx_io/commproc.c @@ -144,7 +144,7 @@ m8xx_cpm_reset(void) /* Set SDMA Bus Request priority 5. * On 860T, this also enables FEC priority 6. I am not sure - * this is what we realy want for some applications, but the + * this is what we really want for some applications, but the * manual recommends it. * Bit 25, FAM can also be set to use FEC aggressive mode (860T). */ diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c index 57a9a61e54b5..d38335d2d710 100644 --- a/arch/ppc/8xx_io/fec.c +++ b/arch/ppc/8xx_io/fec.c @@ -1878,7 +1878,7 @@ fec_restart(struct net_device *dev, int duplex) bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* ...and the same for transmmit. + /* ...and the same for transmit. */ bdp = fep->tx_bd_base; for (i=0; i<TX_RING_SIZE; i++) { diff --git a/arch/ppc/boot/lib/vreset.c b/arch/ppc/boot/lib/vreset.c index 463ba001fb9b..98539e9f7f96 100644 --- a/arch/ppc/boot/lib/vreset.c +++ b/arch/ppc/boot/lib/vreset.c @@ -518,7 +518,7 @@ setTextRegs(struct VgaRegs *svp) outb(0x3c6, 0xff); /* MASK */ for ( i = 0; i < 0x10; i++) - writeAttr(i, AC[i], 0); /* pallete */ + writeAttr(i, AC[i], 0); /* palette */ writeAttr(0x10, 0x0c, 0); /* text mode */ writeAttr(0x11, 0x00, 0); /* overscan color (border) */ writeAttr(0x12, 0x0f, 0); /* plane enable */ diff --git a/arch/ppc/boot/simple/m8xx_tty.c b/arch/ppc/boot/simple/m8xx_tty.c index cacc40fdbcfa..ea615d8ca541 100644 --- a/arch/ppc/boot/simple/m8xx_tty.c +++ b/arch/ppc/boot/simple/m8xx_tty.c @@ -1,7 +1,7 @@ /* Minimal serial functions needed to send messages out the serial * port on the MBX console. * - * The MBX uxes SMC1 for the serial port. We reset the port and use + * The MBX uses SMC1 for the serial port. We reset the port and use * only the first BD that EPPC-Bug set up as a character FIFO. * * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug diff --git a/arch/ppc/boot/simple/misc-embedded.c b/arch/ppc/boot/simple/misc-embedded.c index 10219eeca054..8a08ad397ed5 100644 --- a/arch/ppc/boot/simple/misc-embedded.c +++ b/arch/ppc/boot/simple/misc-embedded.c @@ -136,7 +136,7 @@ load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *b /* * We link ourself to an arbitrary low address. When we run, we - * relocate outself to that address. __image_being points to + * relocate ourself to that address. __image_being points to * the part of the image where the zImage is. -- Tom */ zimage_start = (char *)(unsigned long)(&__image_begin); diff --git a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c index 7b5924cc3c02..6955891fb031 100644 --- a/arch/ppc/boot/simple/mpc52xx_tty.c +++ b/arch/ppc/boot/simple/mpc52xx_tty.c @@ -33,7 +33,7 @@ static struct mpc52xx_psc __iomem *psc = * rtc. We read the decrementer change during one rtc tick * and multiply by 4 to get the system bus clock frequency. Since a * rtc tick is one seconds, and that's pretty long, we change the rtc - * dividers temporarly to set them 64x faster ;) + * dividers temporarily to set them 64x faster ;) */ static int mpc52xx_ipbfreq(void) diff --git a/arch/ppc/boot/simple/mv64x60_tty.c b/arch/ppc/boot/simple/mv64x60_tty.c index 781e040a97d1..8a735787a6e9 100644 --- a/arch/ppc/boot/simple/mv64x60_tty.c +++ b/arch/ppc/boot/simple/mv64x60_tty.c @@ -338,7 +338,7 @@ serial_tstc(unsigned long com_port) rdp = &rd[com_port][cur_rd[com_port]]; - /* Go thru rcv desc's until empty looking for one with data (no error)*/ + /* Go through rcv descs until empty looking for one with data (no error)*/ while (((rdp->cmd_stat & SDMA_DESC_CMDSTAT_O) == 0) && (loop_count++ < RX_NUM_DESC)) { diff --git a/arch/ppc/boot/simple/rw4/stb.h b/arch/ppc/boot/simple/rw4/stb.h index fd98ee0f843e..9afa5ab24d26 100644 --- a/arch/ppc/boot/simple/rw4/stb.h +++ b/arch/ppc/boot/simple/rw4/stb.h @@ -88,7 +88,7 @@ /*----------------------------------------------------------------------------+ | STB tasks, task stack sizes, and task priorities. The actual task priority | is 1 more than the specified number since priority 0 is reserved (system -| internaly adds 1 to supplied priority number). +| internally adds 1 to supplied priority number). +----------------------------------------------------------------------------*/ #define STB_IDLE_TASK_SS (5* 1024) #define STB_IDLE_TASK_PRIO 0 diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 810f7aa72e92..aea100be52c8 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -577,7 +577,7 @@ void program_check_exception(struct pt_regs *regs) * ESR_DST (!?) or 0. In the process of chasing this with the * hardware people - not sure if it can happen on any illegal * instruction or only on FP instructions, whether there is a - * pattern to occurences etc. -dgibson 31/Mar/2003 */ + * pattern to occurrences etc. -dgibson 31/Mar/2003 */ if (!(reason & REASON_TRAP) && do_mathemu(regs) == 0) { emulate_single_step(regs); return; @@ -860,7 +860,7 @@ void SPEFloatingPointException(struct pt_regs *regs) spefscr = current->thread.spefscr; fpexc_mode = current->thread.fpexc_mode; - /* Hardware does not neccessarily set sticky + /* Hardware does not necessarily set sticky * underflow/overflow/invalid flags */ if ((spefscr & SPEFSCR_FOVF) && (fpexc_mode & PR_FP_EXC_OVF)) { code = FPE_FLTOVF; diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index c374e53ae03a..390dd1995c2a 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -48,7 +48,7 @@ #include "mmu_decl.h" #if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL) -/* The ammount of lowmem must be within 0xF0000000 - KERNELBASE. */ +/* The amount of lowmem must be within 0xF0000000 - KERNELBASE. */ #if (CONFIG_LOWMEM_SIZE > (0xF0000000 - KERNELBASE)) #error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_START_KERNEL" #endif diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c index 75857b38e894..1a7f075b754f 100644 --- a/arch/ppc/platforms/4xx/bubinga.c +++ b/arch/ppc/platforms/4xx/bubinga.c @@ -197,7 +197,7 @@ bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) hose->first_busno, PCI_SLOT(hose->first_busno), PCI_FUNC(hose->first_busno), bar, bar_response); } - /* end work arround */ + /* end workaround */ #ifdef DEBUG printk("PCI bridge regs after fixup \n"); diff --git a/arch/ppc/platforms/4xx/ep405.c b/arch/ppc/platforms/4xx/ep405.c index e5adf9ba1fca..5aa295022804 100644 --- a/arch/ppc/platforms/4xx/ep405.c +++ b/arch/ppc/platforms/4xx/ep405.c @@ -130,7 +130,7 @@ bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) hose->first_busno, PCI_SLOT(hose->first_busno), PCI_FUNC(hose->first_busno), bar, bar_response); } - /* end work arround */ + /* end workaround */ #endif } diff --git a/arch/ppc/platforms/4xx/ibmnp405h.h b/arch/ppc/platforms/4xx/ibmnp405h.h index 4aa8821b478b..08a6a7791903 100644 --- a/arch/ppc/platforms/4xx/ibmnp405h.h +++ b/arch/ppc/platforms/4xx/ibmnp405h.h @@ -80,7 +80,7 @@ #define DCRN_CPMFR_BASE 0x0B9 #define DCRN_CPMER_BASE 0x0B8 -/* CPM Clocking & Power Mangement defines */ +/* CPM Clocking & Power Management defines */ #define IBM_CPM_PCI 0x40000000 /* PCI */ #define IBM_CPM_EMAC2 0x20000000 /* EMAC 2 MII */ #define IBM_CPM_EMAC3 0x04000000 /* EMAC 3 MII */ diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c index c47493e344c2..8689f3e8ef3a 100644 --- a/arch/ppc/platforms/4xx/sycamore.c +++ b/arch/ppc/platforms/4xx/sycamore.c @@ -225,7 +225,7 @@ bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) hose->first_busno, PCI_SLOT(hose->first_busno), PCI_FUNC(hose->first_busno), bar, bar_response); } - /* end work arround */ + /* end workaround */ #ifdef DEBUG printk("PCI bridge regs after fixup \n"); diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c index f414d2d4c58e..2f9772340854 100644 --- a/arch/ppc/platforms/4xx/walnut.c +++ b/arch/ppc/platforms/4xx/walnut.c @@ -200,7 +200,7 @@ bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) hose->first_busno, PCI_SLOT(hose->first_busno), PCI_FUNC(hose->first_busno), bar, bar_response); } - /* end work arround */ + /* end work around */ #ifdef DEBUG printk("PCI bridge regs after fixup \n"); diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c index f87e06f6bab9..f8baf05f16ce 100644 --- a/arch/ppc/platforms/ev64360.c +++ b/arch/ppc/platforms/ev64360.c @@ -473,7 +473,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, * are non-zero, then we should use the board info from the bd_t * structure and the cmdline pointed to by r6 instead of the * information from birecs, if any. Otherwise, use the information - * from birecs as discovered by the preceeding call to + * from birecs as discovered by the preceding call to * parse_bootinfo(). This rule should work with both PPCBoot, which * uses a bd_t board info structure, and the kernel boot wrapper, * which uses birecs. diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c index d809e17aa536..ca5de13712fd 100644 --- a/arch/ppc/platforms/hdpu.c +++ b/arch/ppc/platforms/hdpu.c @@ -144,7 +144,7 @@ static void __init hdpu_setup_peripherals(void) /* Enable pipelining */ mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 13)); - /* Enable Snoop Pipelineing */ + /* Enable Snoop Pipelining */ mv64x60_set_bits(&bh, MV64360_D_UNIT_CONTROL_HIGH, (1 << 24)); /* diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c index 720f8b3e2fbc..c289e9f1b251 100644 --- a/arch/ppc/platforms/katana.c +++ b/arch/ppc/platforms/katana.c @@ -880,7 +880,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, * are non-zero, then we should use the board info from the bd_t * structure and the cmdline pointed to by r6 instead of the * information from birecs, if any. Otherwise, use the information - * from birecs as discovered by the preceeding call to + * from birecs as discovered by the preceding call to * parse_bootinfo(). This rule should work with both PPCBoot, which * uses a bd_t board info structure, and the kernel boot wrapper, * which uses birecs. diff --git a/arch/ppc/platforms/mbx.h b/arch/ppc/platforms/mbx.h index fe81ca4ea0a2..1cf36fa3592d 100644 --- a/arch/ppc/platforms/mbx.h +++ b/arch/ppc/platforms/mbx.h @@ -37,7 +37,7 @@ typedef struct bd_info { /* Memory map for the MBX as configured by EPPC-Bug. We could reprogram * The SIU and PCI bridge, and try to use larger MMU pages, but the - * performance gain is not measureable and it certainly complicates the + * performance gain is not measurable and it certainly complicates the * generic MMU model. * * In a effort to minimize memory usage for embedded applications, any diff --git a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h index 9e2a09e636ae..fbb5495165c7 100644 --- a/arch/ppc/platforms/mvme5100.h +++ b/arch/ppc/platforms/mvme5100.h @@ -69,7 +69,7 @@ #define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF -/* All UART IRQ's are wire-OR'd to one MPIC IRQ */ +/* All UART IRQs are wire-OR'd to one MPIC IRQ */ #define STD_SERIAL_PORT_DFNS \ { 0, BASE_BAUD, MVME5100_SERIAL_1, \ MVME5100_SERIAL_IRQ, \ diff --git a/arch/ppc/platforms/pplus.h b/arch/ppc/platforms/pplus.h index a07cbbdd72c6..a4bbaa8d858f 100644 --- a/arch/ppc/platforms/pplus.h +++ b/arch/ppc/platforms/pplus.h @@ -18,7 +18,7 @@ #include <asm/io.h> /* - * Due to limiations imposed by legacy hardware (primaryily IDE controllers), + * Due to limitations imposed by legacy hardware (primarily IDE controllers), * the PPLUS boards operate using a PReP address map. * * From Processor (physical) -> PCI: diff --git a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c index c627ba41335f..1df3150f016e 100644 --- a/arch/ppc/platforms/prep_pci.c +++ b/arch/ppc/platforms/prep_pci.c @@ -589,9 +589,9 @@ static unsigned char prep_pci_intpins[4][4] = { 4, 1, 2, 3}, /* Buses 3, 7, 11 ... */ }; -/* We have to turn on LEVEL mode for changed IRQ's */ -/* All PCI IRQ's need to be level mode, so this should be something - * other than hard-coded as well... IRQ's are individually mappable +/* We have to turn on LEVEL mode for changed IRQs */ +/* All PCI IRQs need to be level mode, so this should be something + * other than hard-coded as well... IRQs are individually mappable * to either edge or level. */ @@ -923,8 +923,8 @@ prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)"; Motherboard_map = ibm6015_pci_IRQ_map; Motherboard_routes = ibm6015_pci_IRQ_routes; - *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ - *irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */ + *irq_edge_mask_lo = 0x00; /* IRQs 0-7 all edge-triggered */ + *irq_edge_mask_hi = 0xA0; /* IRQs 13, 15 level-triggered */ } void __init @@ -933,8 +933,8 @@ prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) Motherboard_map_name = "IBM Thinkpad 850/860"; Motherboard_map = Nobis_pci_IRQ_map; Motherboard_routes = Nobis_pci_IRQ_routes; - *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ - *irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */ + *irq_edge_mask_lo = 0x00; /* IRQs 0-7 all edge-triggered */ + *irq_edge_mask_hi = 0xA0; /* IRQs 13, 15 level-triggered */ } void __init @@ -943,8 +943,8 @@ prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) Motherboard_map_name = "IBM 7248, PowerSeries 830/850 (Carolina)"; Motherboard_map = ibm8xx_pci_IRQ_map; Motherboard_routes = ibm8xx_pci_IRQ_routes; - *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ - *irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */ + *irq_edge_mask_lo = 0x00; /* IRQs 0-7 all edge-triggered */ + *irq_edge_mask_hi = 0xA4; /* IRQs 10, 13, 15 level-triggered */ } void __init @@ -954,8 +954,8 @@ prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) Motherboard_map = ibm43p_pci_IRQ_map; Motherboard_routes = ibm43p_pci_IRQ_routes; Motherboard_non0 = ibm43p_pci_map_non0; - *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ - *irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */ + *irq_edge_mask_lo = 0x00; /* IRQs 0-7 all edge-triggered */ + *irq_edge_mask_hi = 0xA0; /* IRQs 13, 15 level-triggered */ } void __init diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index f166299571d6..6f21110a9747 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c @@ -593,7 +593,7 @@ static void __init prep_init_sound(void) PPC_DEVICE *audiodevice = NULL; /* - * Get the needed resource informations from residual data. + * Get the needed resource information from residual data. * */ if (have_residual_data) @@ -632,9 +632,9 @@ static void __init prep_init_sound(void) } /* - * Find a way to push these informations to the cs4232 driver + * Find a way to push this information to the cs4232 driver * Give it out with printk, when not in cmd_line? - * Append it to cmd_line and boot_command_line? + * Append it to cmd_line and boot_command_line? * Format is cs4232=io,irq,dma,dma2 */ } diff --git a/arch/ppc/platforms/prpmc750.h b/arch/ppc/platforms/prpmc750.h index 4c7adcc9ae33..c4dcff09d7ca 100644 --- a/arch/ppc/platforms/prpmc750.h +++ b/arch/ppc/platforms/prpmc750.h @@ -16,7 +16,7 @@ #define __ASM_PRPMC750_H__ /* - * Due to limiations imposed by legacy hardware (primaryily IDE controllers), + * Due to limitations imposed by legacy hardware (primarily IDE controllers), * the PrPMC750 carrier board operates using a PReP address map. * * From Processor (physical) -> PCI: diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c index 13d70ab50bf1..b55860734a72 100644 --- a/arch/ppc/platforms/radstone_ppc7d.c +++ b/arch/ppc/platforms/radstone_ppc7d.c @@ -1371,7 +1371,7 @@ void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, * are non-zero, then we should use the board info from the bd_t * structure and the cmdline pointed to by r6 instead of the * information from birecs, if any. Otherwise, use the information - * from birecs as discovered by the preceeding call to + * from birecs as discovered by the preceding call to * parse_bootinfo(). This rule should work with both PPCBoot, which * uses a bd_t board info structure, and the kernel boot wrapper, * which uses birecs. diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c index a76002af686f..3352fae1c722 100644 --- a/arch/ppc/platforms/sandpoint.c +++ b/arch/ppc/platforms/sandpoint.c @@ -54,7 +54,7 @@ * * * Motorola has finally released a version of DINK32 that correctly - * (seemingly) initalizes the memory controller correctly, regardless + * (seemingly) initializes the memory controller correctly, regardless * of the amount of memory in the system. Once a method of determining * what version of DINK initializes the system for us, if applicable, is * found, we can hopefully stop hardcoding 32MB of RAM. @@ -473,7 +473,7 @@ sandpoint_request_io(void) arch_initcall(sandpoint_request_io); /* - * Interrupt setup and service. Interrrupts on the Sandpoint come + * Interrupt setup and service. Interrupts on the Sandpoint come * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO). * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4, * IDE is on EPIC 7 and 8. @@ -505,7 +505,7 @@ sandpoint_find_end_of_memory(void) if (bp->bi_memsize) return bp->bi_memsize; - /* DINK32 13.0 correctly initalizes things, so iff you use + /* DINK32 13.0 correctly initializes things, so iff you use * this you _should_ be able to change this instead of a * hardcoded value. */ #if 0 @@ -677,7 +677,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, * are non-zero, then we should use the board info from the bd_t * structure and the cmdline pointed to by r6 instead of the * information from birecs, if any. Otherwise, use the information - * from birecs as discovered by the preceeding call to + * from birecs as discovered by the preceding call to * parse_bootinfo(). This rule should work with both PPCBoot, which * uses a bd_t board info structure, and the kernel boot wrapper, * which uses birecs. diff --git a/arch/ppc/syslib/harrier.c b/arch/ppc/syslib/harrier.c index c1583f488325..45b797b3a336 100644 --- a/arch/ppc/syslib/harrier.c +++ b/arch/ppc/syslib/harrier.c @@ -210,7 +210,7 @@ harrier_init(struct pci_controller *hose, * This assumes that PPCBug has initialized the memory controller (SMC) * on the Harrier correctly (i.e., it does no sanity checking). * It also assumes that the memory base registers are set to configure the - * memory as contigous starting with "RAM A BASE", "RAM B BASE", etc. + * memory as contiguous starting with "RAM A BASE", "RAM B BASE", etc. * however, RAM base registers can be skipped (e.g. A, B, C are set, * D is skipped but E is set is okay). */ diff --git a/arch/ppc/syslib/hawk_common.c b/arch/ppc/syslib/hawk_common.c index c5bf16b0d6a1..86821d8753ed 100644 --- a/arch/ppc/syslib/hawk_common.c +++ b/arch/ppc/syslib/hawk_common.c @@ -165,7 +165,7 @@ hawk_init(struct pci_controller *hose, processor_pci_mem_start + hose->mem_space.start) | 0x0); - /* Map MPIC into vitual memory */ + /* Map MPIC into virtual memory */ OpenPIC_Addr = ioremap(processor_mpic_base, HAWK_MPIC_SIZE); return 0; @@ -176,7 +176,7 @@ hawk_init(struct pci_controller *hose, * This assumes that PPCBug has initialized the memory controller (SMC) * on the Falcon/HAWK correctly (i.e., it does no sanity checking). * It also assumes that the memory base registers are set to configure the - * memory as contigous starting with "RAM A BASE", "RAM B BASE", etc. + * memory as contiguous starting with "RAM A BASE", "RAM B BASE", etc. * however, RAM base registers can be skipped (e.g. A, B, C are set, * D is skipped but E is set is okay). */ diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c index e3b586b1ede9..fe860d52e2e4 100644 --- a/arch/ppc/syslib/m82xx_pci.c +++ b/arch/ppc/syslib/m82xx_pci.c @@ -197,7 +197,7 @@ pq2ads_setup_pci(struct pci_controller *hose) CPM high 0b0000 CPM middle 0b0001 CPM low 0b0010 - PCI reguest 0b0011 + PCI request 0b0011 Reserved 0b0100 Reserved 0b0101 Internal Core 0b0110 diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c index 2fc7c4150a18..437a294527a9 100644 --- a/arch/ppc/syslib/mpc10x_common.c +++ b/arch/ppc/syslib/mpc10x_common.c @@ -432,7 +432,7 @@ mpc10x_bridge_init(struct pci_controller *hose, phys_eumb_base); } - /* IRQ's are determined at runtime */ + /* IRQs are determined at runtime */ ppc_sys_platform_devices[MPC10X_IIC1].resource[1].start = MPC10X_I2C_IRQ; ppc_sys_platform_devices[MPC10X_IIC1].resource[1].end = MPC10X_I2C_IRQ; ppc_sys_platform_devices[MPC10X_DMA0].resource[1].start = MPC10X_DMA0_IRQ; @@ -646,7 +646,7 @@ void __init mpc10x_set_openpic(void) openpic_set_sources(EPIC_IRQ_BASE, 3, OpenPIC_Addr + 0x11020); /* Skip reserved space and map Message Unit Interrupt (I2O) */ openpic_set_sources(EPIC_IRQ_BASE + 3, 1, OpenPIC_Addr + 0x110C0); - /* Skip reserved space and map Serial Interupts */ + /* Skip reserved space and map Serial Interrupts */ openpic_set_sources(EPIC_IRQ_BASE + 4, 2, OpenPIC_Addr + 0x11120); openpic_init(NUM_8259_INTERRUPTS); diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c index 80c609019bda..ecfa2c0f8ba3 100644 --- a/arch/ppc/syslib/mpc52xx_setup.c +++ b/arch/ppc/syslib/mpc52xx_setup.c @@ -252,7 +252,7 @@ mpc52xx_setup_cpu(void) out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d); /* Disable XLB pipelining */ - /* (cfr errate 292. We could do this only just before ATA PIO + /* (cfr errata 292. We could do this only just before ATA PIO transaction and re-enable it after ...) */ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c index 31fb56593d17..c05ac87ece4c 100644 --- a/arch/ppc/syslib/mpc8xx_devices.c +++ b/arch/ppc/syslib/mpc8xx_devices.c @@ -21,7 +21,7 @@ #include <asm/irq.h> #include <asm/ppc_sys.h> -/* We use offsets for IORESOURCE_MEM to do not set dependences at compile time. +/* We use offsets for IORESOURCE_MEM to do not set dependencies at compile time. * They will get fixed up by mach_mpc8xx_fixup */ diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index a6f8b686ea83..8485a68cd475 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -490,7 +490,7 @@ static struct platform_device *mv64x60_pd_devs[] __initdata = { /* * mv64x60_init() * - * Initialze the bridge based on setting passed in via 'si'. The bridge + * Initialize the bridge based on setting passed in via 'si'. The bridge * handle, 'bh', will be set so that it can be used to make subsequent * calls to routines in this file. */ @@ -1704,7 +1704,7 @@ gt64260_disable_all_windows(struct mv64x60_handle *bh, /* * gt64260a_chip_specific_init() * - * Implement errata work arounds for the GT64260A. + * Implement errata workarounds for the GT64260A. */ static void __init gt64260a_chip_specific_init(struct mv64x60_handle *bh, @@ -1776,7 +1776,7 @@ gt64260a_chip_specific_init(struct mv64x60_handle *bh, /* * gt64260b_chip_specific_init() * - * Implement errata work arounds for the GT64260B. + * Implement errata workarounds for the GT64260B. */ static void __init gt64260b_chip_specific_init(struct mv64x60_handle *bh, @@ -2316,7 +2316,7 @@ mv64360_set_mpsc2regs_window(struct mv64x60_handle *bh, u32 base) /* * mv64360_chip_specific_init() * - * Implement errata work arounds for the MV64360. + * Implement errata workarounds for the MV64360. */ static void __init mv64360_chip_specific_init(struct mv64x60_handle *bh, @@ -2336,7 +2336,7 @@ mv64360_chip_specific_init(struct mv64x60_handle *bh, /* * mv64460_chip_specific_init() * - * Implement errata work arounds for the MV64460. + * Implement errata workarounds for the MV64460. */ static void __init mv64460_chip_specific_init(struct mv64x60_handle *bh, diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c index 50c55622ece9..491fe9a57229 100644 --- a/arch/ppc/syslib/ocp.c +++ b/arch/ppc/syslib/ocp.c @@ -27,7 +27,7 @@ * device model. The devices on the OCP bus are seeded by an * an initial OCP device array created by the arch-specific * Device entries can be added/removed/modified through OCP - * helper functions to accomodate system and board-specific + * helper functions to accommodate system and board-specific * parameters commonly found in embedded systems. OCP also * provides a standard method for devices to describe extended * attributes about themselves to the system. A standard access diff --git a/arch/ppc/syslib/ppc403_pic.c b/arch/ppc/syslib/ppc403_pic.c index 607ebd111d44..c3b7b8bfbcfe 100644 --- a/arch/ppc/syslib/ppc403_pic.c +++ b/arch/ppc/syslib/ppc403_pic.c @@ -112,7 +112,7 @@ ppc4xx_pic_init(void) /* * Disable all external interrupts until they are - * explicity requested. + * explicitly requested. */ ppc_cached_irq_mask[0] = 0; diff --git a/arch/ppc/syslib/ppc405_pci.c b/arch/ppc/syslib/ppc405_pci.c index d6d838b16dac..9e9035693bfa 100644 --- a/arch/ppc/syslib/ppc405_pci.c +++ b/arch/ppc/syslib/ppc405_pci.c @@ -137,7 +137,7 @@ ppc4xx_find_bridges(void) hose_a->pci_mem_offset = 0; /* Setup bridge memory/IO ranges & resources - * TODO: Handle firmwares setting up a legacy ISA mem base + * TODO: Handle firmware setting up a legacy ISA mem base */ hose_a->io_space.start = PPC405_PCI_LOWER_IO; hose_a->io_space.end = PPC405_PCI_UPPER_IO; diff --git a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c index 1eef4ffed4fb..bd301868996b 100644 --- a/arch/ppc/syslib/ppc4xx_dma.c +++ b/arch/ppc/syslib/ppc4xx_dma.c @@ -241,7 +241,7 @@ ppc4xx_set_dma_count(unsigned int dmanr, unsigned int count) } /* - * Returns the number of bytes left to be transfered. + * Returns the number of bytes left to be transferred. * After a DMA transfer, this should return zero. * Reading this while a DMA transfer is still in progress will return * unpredictable results. diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c index 2b097800cdd9..af2425e4655f 100644 --- a/arch/ppc/syslib/ppc85xx_rio.c +++ b/arch/ppc/syslib/ppc85xx_rio.c @@ -349,7 +349,7 @@ EXPORT_SYMBOL_GPL(rio_hw_add_outb_message); * @dev_instance: Pointer to interrupt-specific data * * Handles outbound message interrupts. Executes a register outbound - * mailbox event handler and acks the interrupt occurence. + * mailbox event handler and acks the interrupt occurrence. */ static irqreturn_t mpc85xx_rio_tx_handler(int irq, void *dev_instance) @@ -516,7 +516,7 @@ void rio_close_outb_mbox(struct rio_mport *mport, int mbox) * @dev_instance: Pointer to interrupt-specific data * * Handles inbound message interrupts. Executes a registered inbound - * mailbox event handler and acks the interrupt occurence. + * mailbox event handler and acks the interrupt occurrence. */ static irqreturn_t mpc85xx_rio_rx_handler(int irq, void *dev_instance) diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c index 6fd4cdbada72..3b82333e96d8 100644 --- a/arch/ppc/syslib/xilinx_pic.c +++ b/arch/ppc/syslib/xilinx_pic.c @@ -130,7 +130,7 @@ ppc4xx_pic_init(void) /* * Disable all external interrupts until they are - * explicity requested. + * explicitly requested. */ intc_out_be32(intc + IER, 0); diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c index 0741d9193390..d1c76fe10f29 100644 --- a/arch/s390/kernel/audit.c +++ b/arch/s390/kernel/audit.c @@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ~0U }; +static unsigned signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + +int audit_classify_arch(int arch) +{ +#ifdef CONFIG_COMPAT + if (arch == AUDIT_ARCH_S390) + return 1; +#endif + return 0; +} + int audit_classify_syscall(int abi, unsigned syscall) { #ifdef CONFIG_COMPAT @@ -51,15 +65,18 @@ static int __init audit_classes_init(void) extern __u32 s390_write_class[]; extern __u32 s390_read_class[]; extern __u32 s390_chattr_class[]; + extern __u32 s390_signal_class[]; audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class); audit_register_class(AUDIT_CLASS_READ_32, s390_read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class); audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL_32, s390_signal_class); #endif audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL, signal_class); return 0; } diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c index 16d9436bfa91..0569f5126e49 100644 --- a/arch/s390/kernel/compat_audit.c +++ b/arch/s390/kernel/compat_audit.c @@ -21,6 +21,11 @@ unsigned s390_read_class[] = { ~0U }; +unsigned s390_signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + int s390_classify_syscall(unsigned syscall) { switch(syscall) { diff --git a/arch/sparc/kernel/auxio.c b/arch/sparc/kernel/auxio.c index 118f3eca373e..baf4ed3fb0f3 100644 --- a/arch/sparc/kernel/auxio.c +++ b/arch/sparc/kernel/auxio.c @@ -88,7 +88,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off) break; case sun4m: if(!auxio_register) - break; /* VME chassic sun4m, no auxio. */ + break; /* VME chassis sun4m, no auxio. */ regval = sbus_readb(auxio_register); sbus_writeb(((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M, auxio_register); diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 987ec6782f99..62182d2d7b0d 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -617,7 +617,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba) * size must be the same as what as passed into pci_alloc_consistent, * and likewise dma_addr must be the same as what *dma_addrp was set to. * - * References to the memory and mappings assosciated with cpu_addr/dma_addr + * References to the memory and mappings associated with cpu_addr/dma_addr * past this call are illegal. */ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba) diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index bdbefa8a9742..f257a67bcf93 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -1,6 +1,6 @@ /* $Id: irq.c,v 1.114 2001/12/11 04:55:51 davem Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the - * Sparc the IRQ's are basically 'cast in stone' + * Sparc the IRQs are basically 'cast in stone' * and you are supposed to probe the prom's device * node trees to find out who's got which IRQ. * @@ -330,7 +330,7 @@ void handler_irq(int irq, struct pt_regs * regs) irq_enter(); disable_pil_irq(irq); #ifdef CONFIG_SMP - /* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */ + /* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */ if((sparc_cpu_model==sun4m) && (irq < 10)) smp4m_irq_rotate(cpu); #endif @@ -371,7 +371,7 @@ void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) } #endif -/* Fast IRQ's on the Sparc can only have one routine attached to them, +/* Fast IRQs on the Sparc can only have one routine attached to them, * thus no sharing possible. */ int request_fast_irq(unsigned int irq, @@ -608,7 +608,7 @@ void __init init_IRQ(void) break; default: - prom_printf("Cannot initialize IRQ's on this Sun machine..."); + prom_printf("Cannot initialize IRQs on this Sun machine..."); break; } btfixup(); diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 5ca7e8f42bd9..791771196905 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -755,7 +755,7 @@ void __init pci_time_init(void) static __inline__ unsigned long do_gettimeoffset(void) { /* - * We devide all to 100 + * We divide all by 100 * to have microsecond resolution and to avoid overflow */ unsigned long count = @@ -956,7 +956,7 @@ EXPORT_SYMBOL(pci_device_to_OF_node); * Also, think for a moment about likes of floppy.c that * include architecture specific parts. They may want to redefine ins/outs. * - * We do not use horroble macroses here because we want to + * We do not use horrible macros here because we want to * advance pointer by sizeof(size). */ void outsb(unsigned long addr, const void *src, unsigned long count) diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 2940d2c1a778..8c37f8f5adb7 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -683,7 +683,7 @@ out: * NOTE! Only a kernel-only process(ie the swapper or direct descendants * who haven't done an "execve()") should use this: it will work within * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. + * not be freed until both the parent and the child have exited. */ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 116d6a241ca2..396797e20c39 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -521,7 +521,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) lvl14_save[2] += smp4d_ticker - real_irq_entry; /* For SMP we use the level 14 ticker, however the bootup code - * has copied the firmwares level 14 vector into boot cpu's + * has copied the firmware's level 14 vector into the boot cpu's * trap table, we must fix this now or we get squashed. */ local_irq_save(flags); diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index a654c16f4027..91a803ea88be 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -299,7 +299,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; /* For SMP we use the level 14 ticker, however the bootup code - * has copied the firmwares level 14 vector into boot cpu's + * has copied the firmware's level 14 vector into the boot cpu's * trap table, we must fix this now or we get squashed. */ local_irq_save(flags); diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index e3f5b8ed4c52..90b52d4dab9a 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -80,7 +80,7 @@ sys_call_table: /*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare /*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy /*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait -/*310*/ .long sys_utimensat +/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -197,6 +197,7 @@ sunos_sys_table: .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys -/*310*/ .long sunos_nosys +/*310*/ .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys #endif diff --git a/arch/sparc/prom/printf.c b/arch/sparc/prom/printf.c index dc8b598bedbb..27fdac99f790 100644 --- a/arch/sparc/prom/printf.c +++ b/arch/sparc/prom/printf.c @@ -5,7 +5,7 @@ * Copyright (c) 2002 Pete Zaitcev (zaitcev@yahoo.com) * * We used to warn all over the code: DO NOT USE prom_printf(), - * and yet people do. Anton's banking code was outputing banks + * and yet people do. Anton's banking code was outputting banks * with prom_printf for most of the 2.4 lifetime. Since an effective * stick is not available, we deployed a carrot: an early printk * through PROM by means of -p boot option. This ought to fix it. diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index ad8d6b256a70..831781cab271 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -226,9 +226,6 @@ config ARCH_SPARSEMEM_DEFAULT def_bool y select SPARSEMEM_STATIC -config LARGE_ALLOCS - def_bool y - source "mm/Kconfig" config ISA diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 37c2d3695658..585ef4fb7591 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.21 -# Sun May 6 22:46:54 2007 +# Fri May 11 14:31:45 2007 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -9,6 +9,7 @@ CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_64BIT=y CONFIG_MMU=y +CONFIG_QUICKLIST=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y @@ -49,6 +50,7 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=18 CONFIG_SYSFS_DEPRECATED=y CONFIG_RELAY=y # CONFIG_BLK_DEV_INITRD is not set @@ -66,14 +68,20 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set # # Loadable module support @@ -137,7 +145,6 @@ CONFIG_HUGETLB_PAGE_SIZE_4MB=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y -CONFIG_LARGE_ALLOCS=y CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -148,6 +155,7 @@ CONFIG_SPARSEMEM_STATIC=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_RESOURCES_64BIT=y CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=1 CONFIG_SBUS=y CONFIG_SBUSCHAR=y CONFIG_SUN_AUXIO=y @@ -305,6 +313,7 @@ CONFIG_NET_TCPPROBE=m # CONFIG_WIRELESS_EXT is not set # CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set # # Device Drivers @@ -359,8 +368,10 @@ CONFIG_ATA_OVER_ETH=m # # Misc devices # +# CONFIG_PHANTOM is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set +# CONFIG_BLINK is not set # # ATA/ATAPI/MFM/RLL support @@ -379,6 +390,7 @@ CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes @@ -386,6 +398,7 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_IDE_GENERIC=y CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set +CONFIG_IDEPCI_PCIBUS_ORDER=y # CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_BLK_DEV_GENERIC is not set # CONFIG_BLK_DEV_OPTI621 is not set @@ -521,6 +534,7 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m # CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set # # Fusion MPT device support @@ -533,6 +547,7 @@ CONFIG_DM_ZERO=m # # IEEE 1394 (FireWire) support # +# CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set # @@ -629,6 +644,8 @@ CONFIG_BNX2=m # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set +# CONFIG_MLX4_CORE is not set +CONFIG_MLX4_DEBUG=y # # Token Ring devices @@ -642,6 +659,16 @@ CONFIG_BNX2=m # CONFIG_WLAN_80211 is not set # +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set + +# # Wan interfaces # # CONFIG_WAN is not set @@ -711,11 +738,18 @@ CONFIG_MOUSE_PS2_LIFEBOOK=y CONFIG_MOUSE_PS2_TRACKPOINT=y # CONFIG_MOUSE_PS2_TOUCHKIT is not set CONFIG_MOUSE_SERIAL=y +# CONFIG_MOUSE_APPLETOUCH is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y CONFIG_INPUT_SPARCSPKR=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set # CONFIG_INPUT_UINPUT is not set # CONFIG_INPUT_POLLDEV is not set @@ -762,14 +796,9 @@ CONFIG_UNIX98_PTYS=y # IPMI # # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set CONFIG_RTC=y -# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set # CONFIG_DRM is not set @@ -779,6 +808,7 @@ CONFIG_RTC=y # TPM devices # # CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y # CONFIG_I2C_CHARDEV is not set @@ -841,13 +871,10 @@ CONFIG_I2C_ALGOBIT=y # Dallas's 1-wire bus # # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_AD7418 is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -874,6 +901,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set # CONFIG_SENSORS_SIS5595 is not set @@ -901,23 +929,30 @@ CONFIG_HWMON=y # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set # -# Digital Video Broadcasting Devices +# Graphics support # -# CONFIG_DVB is not set -# CONFIG_USB_DABUSB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # -# Graphics support +# Display device support # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set CONFIG_FB_DDC=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_SYS_FOPS is not set +CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -949,7 +984,10 @@ CONFIG_FB_RADEON_I2C=y # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set # CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set # CONFIG_FB_XVR500 is not set # CONFIG_FB_XVR2500 is not set # CONFIG_FB_PCI is not set @@ -972,10 +1010,6 @@ CONFIG_FONTS=y CONFIG_FONT_SUN8x16=y # CONFIG_FONT_SUN12x22 is not set # CONFIG_FONT_10x18 is not set - -# -# Logo configuration -# CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set @@ -1083,6 +1117,7 @@ CONFIG_SND_ALI5451=m # USB devices # # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set # # ALSA Sparc devices @@ -1092,7 +1127,7 @@ CONFIG_SND_SUN_CS4231=m # CONFIG_SND_SUN_DBRI is not set # -# SoC audio support +# System on Chip audio support # # CONFIG_SND_SOC is not set @@ -1178,37 +1213,10 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_LIBUSUAL is not set # -# USB Input Devices -# -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_TOUCHSCREEN is not set -# CONFIG_USB_YEALINK is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_GTCO is not set - -# # USB Imaging devices # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET_MII is not set -# CONFIG_USB_USBNET is not set # CONFIG_USB_MON is not set # @@ -1252,10 +1260,6 @@ CONFIG_USB_STORAGE=m # USB Gadget Support # # CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# # CONFIG_MMC is not set # @@ -1299,14 +1303,6 @@ CONFIG_USB_STORAGE=m # # -# Auxiliary Display support -# - -# -# Virtualization -# - -# # Misc Linux/SPARC drivers # CONFIG_SUN_OPENPROMIO=m @@ -1486,11 +1482,9 @@ CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set -CONFIG_LOG_BUF_SHIFT=18 CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHEDSTATS=y # CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1574,6 +1568,7 @@ CONFIG_CRYPTO_TEST=m CONFIG_BITREVERSE=y CONFIG_CRC_CCITT=m CONFIG_CRC16=m +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y @@ -1581,3 +1576,4 @@ CONFIG_ZLIB_DEFLATE=y CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/sparc64/kernel/audit.c b/arch/sparc64/kernel/audit.c index aef19cc27072..24d7f4b4178a 100644 --- a/arch/sparc64/kernel/audit.c +++ b/arch/sparc64/kernel/audit.c @@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ~0U }; +static unsigned signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + +int audit_classify_arch(int arch) +{ +#ifdef CONFIG_SPARC32_COMPAT + if (arch == AUDIT_ARCH_SPARC) + return 1; +#endif + return 0; +} + int audit_classify_syscall(int abi, unsigned syscall) { #ifdef CONFIG_SPARC32_COMPAT @@ -51,15 +65,18 @@ static int __init audit_classes_init(void) extern __u32 sparc32_write_class[]; extern __u32 sparc32_read_class[]; extern __u32 sparc32_chattr_class[]; + extern __u32 sparc32_signal_class[]; audit_register_class(AUDIT_CLASS_WRITE_32, sparc32_write_class); audit_register_class(AUDIT_CLASS_READ_32, sparc32_read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, sparc32_dir_class); audit_register_class(AUDIT_CLASS_CHATTR_32, sparc32_chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL_32, sparc32_signal_class); #endif audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL, signal_class); return 0; } diff --git a/arch/sparc64/kernel/compat_audit.c b/arch/sparc64/kernel/compat_audit.c index cca96c91b780..c1979482aa92 100644 --- a/arch/sparc64/kernel/compat_audit.c +++ b/arch/sparc64/kernel/compat_audit.c @@ -20,6 +20,11 @@ unsigned sparc32_read_class[] = { ~0U }; +unsigned sparc32_signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + int sparc32_classify_syscall(unsigned syscall) { switch(syscall) { diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index ec10f7edcf86..0e03c8e218cd 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c @@ -21,7 +21,7 @@ #include <asm/timer.h> #include <asm/cpudata.h> -/* Used to synchronize acceses to NatSemi SUPER I/O chip configure +/* Used to synchronize accesses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h */ DEFINE_SPINLOCK(ns87303_lock); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 9ac9a307999a..7455f5d05519 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -596,7 +596,7 @@ static void __init build_device_resources(struct of_device *op, /* Convert to num-entries. */ num_reg /= na + ns; - /* Prevent overruning the op->resources[] array. */ + /* Prevent overrunning the op->resources[] array. */ if (num_reg > PROMREG_MAX) { printk(KERN_WARNING "%s: Too many regs (%d), " "limiting to %d.\n", @@ -904,7 +904,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, op->num_irqs = 0; } - /* Prevent overruning the op->irqs[] array. */ + /* Prevent overrunning the op->irqs[] array. */ if (op->num_irqs > PROMINTR_MAX) { printk(KERN_WARNING "%s: Too many irqs (%d), " "limiting to %d.\n", diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index cf9a75112d0f..d4c077dc5e85 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -495,8 +495,8 @@ static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) *last_p = last; } -static void __init pci_resource_adjust(struct resource *res, - struct resource *root) +static void pci_resource_adjust(struct resource *res, + struct resource *root) { res->start += root->start; res->end += root->start; diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 9198c1a0f7a5..7f5d473901c4 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -37,7 +37,7 @@ static void pci_fire_scan_bus(struct pci_pbm_info *pbm) #define FIRE_IOMMU_CONTROL 0x40000UL #define FIRE_IOMMU_TSBBASE 0x40008UL #define FIRE_IOMMU_FLUSH 0x40100UL -#define FIRE_IOMMU_FLUSHINV 0x40100UL +#define FIRE_IOMMU_FLUSHINV 0x40108UL static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) { diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index dfd6f9f4790b..70d2364fdfe0 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -542,7 +542,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, /* Map a set of buffers described by SGLIST with NELEMS array * elements in streaming mode for PCI DMA. * When making changes here, inspect the assembly output. I was having - * hard time to kepp this routine out of using stack slots for holding variables. + * hard time to keep this routine out of using stack slots for holding variables. */ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 34df4047587a..044e8ec4c0f5 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -731,7 +731,7 @@ struct pci_sun4v_msiq_entry { u64 msi_address; - /* The format of this value is message type dependant. + /* The format of this value is message type dependent. * For MSI bits 15:0 are the data from the MSI packet. * For MSI-X bits 31:0 are the data from the MSI packet. * For MSG, the message code and message routing code where: diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 8e3c6e435110..952762bfb4c0 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -677,7 +677,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, * NOTE! Only a kernel-only process(ie the swapper or direct descendants * who haven't done an "execve()") should use this: it will work within * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. + * not be freed until both the parent and the child have exited. */ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index b7976b14d0ba..02830e4671f5 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -899,7 +899,7 @@ static unsigned int fire_irq_build(struct device_node *dp, /* The interrupt map registers do not have an INO field * like other chips do. They return zero in the INO * field, and the interrupt controller number is controlled - * in bits 6 thru 9. So in order for build_irq() to get + * in bits 6 to 9. So in order for build_irq() to get * the INO right we pass it in as part of the fixup * which will get added to the map register zero value * read by build_irq(). diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 5fe7f9ad4a92..8765e32155a0 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -81,7 +81,7 @@ sys_call_table32: .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare /*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait -/*310*/ .word compat_sys_utimensat +/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, compat_sys_timerfd, sys_eventfd #endif /* CONFIG_COMPAT */ @@ -153,7 +153,7 @@ sys_call_table: .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare /*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait -/*310*/ .word sys_utimensat +/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -271,6 +271,7 @@ sunos_sys_table: .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys -/*310*/ .long sunos_nosys +/*310*/ .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys #endif diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 259063f41f95..6b9a06e42542 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -55,6 +55,7 @@ DEFINE_SPINLOCK(rtc_lock); void __iomem *mstk48t02_regs = NULL; #ifdef CONFIG_PCI unsigned long ds1287_regs = 0UL; +static void __iomem *bq4802_regs; #endif static void __iomem *mstk48t08_regs; @@ -565,12 +566,14 @@ static void __init set_system_time(void) void __iomem *mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; + void __iomem *bregs = bq4802_regs; #else unsigned long dregs = 0UL; + void __iomem *bregs = 0UL; #endif u8 tmp; - if (!mregs && !dregs) { + if (!mregs && !dregs && !bregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); } @@ -589,6 +592,33 @@ static void __init set_system_time(void) day = MSTK_REG_DOM(mregs); mon = MSTK_REG_MONTH(mregs); year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + } else if (bregs) { + unsigned char val = readb(bregs + 0x0e); + unsigned int century; + + /* BQ4802 RTC chip. */ + + writeb(val | 0x08, bregs + 0x0e); + + sec = readb(bregs + 0x00); + min = readb(bregs + 0x02); + hour = readb(bregs + 0x04); + day = readb(bregs + 0x06); + mon = readb(bregs + 0x09); + year = readb(bregs + 0x0a); + century = readb(bregs + 0x0f); + + writeb(val, bregs + 0x0e); + + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + BCD_TO_BIN(century); + + year += (century * 100); } else { /* Dallas 12887 RTC chip. */ @@ -712,7 +742,8 @@ static int __init clock_model_matches(const char *model) strcmp(model, "m5819") && strcmp(model, "m5819p") && strcmp(model, "m5823") && - strcmp(model, "ds1287")) + strcmp(model, "ds1287") && + strcmp(model, "bq4802")) return 0; return 1; @@ -722,9 +753,13 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id { struct device_node *dp = op->node; const char *model = of_get_property(dp, "model", NULL); + const char *compat = of_get_property(dp, "compatible", NULL); unsigned long size, flags; void __iomem *regs; + if (!model) + model = compat; + if (!model || !clock_model_matches(model)) return -ENODEV; @@ -746,6 +781,8 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id !strcmp(model, "m5819p") || !strcmp(model, "m5823")) { ds1287_regs = (unsigned long) regs; + } else if (!strcmp(model, "bq4802")) { + bq4802_regs = regs; } else #endif if (model[5] == '0' && model[6] == '2') { @@ -1070,8 +1107,10 @@ static int set_rtc_mmss(unsigned long nowtime) void __iomem *mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; + void __iomem *bregs = bq4802_regs; #else unsigned long dregs = 0UL; + void __iomem *bregs = 0UL; #endif unsigned long flags; u8 tmp; @@ -1080,7 +1119,7 @@ static int set_rtc_mmss(unsigned long nowtime) * Not having a register set can lead to trouble. * Also starfire doesn't have a tod clock. */ - if (!mregs && !dregs) + if (!mregs && !dregs & !bregs) return -1; if (mregs) { @@ -1129,6 +1168,37 @@ static int set_rtc_mmss(unsigned long nowtime) return -1; } + } else if (bregs) { + int retval = 0; + unsigned char val = readb(bregs + 0x0e); + + /* BQ4802 RTC chip. */ + + writeb(val | 0x08, bregs + 0x0e); + + chip_minutes = readb(bregs + 0x02); + BCD_TO_BIN(chip_minutes); + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) + real_minutes += 30; + real_minutes %= 60; + + if (abs(real_minutes - chip_minutes) < 30) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + writeb(real_seconds, bregs + 0x00); + writeb(real_minutes, bregs + 0x02); + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + chip_minutes, real_minutes); + retval = -1; + } + + writeb(val, bregs + 0x0e); + + return retval; } else { int retval = 0; unsigned char save_control, save_freq_select; @@ -1259,38 +1329,152 @@ static void to_tm(int tim, struct rtc_time *tm) /* Both Starfire and SUN4V give us seconds since Jan 1st, 1970, * aka Unix time. So we have to convert to/from rtc_time. */ -static inline void mini_get_rtc_time(struct rtc_time *time) +static void starfire_get_rtc_time(struct rtc_time *time) { - unsigned long flags; - u32 seconds; + u32 seconds = starfire_get_time(); - spin_lock_irqsave(&rtc_lock, flags); - seconds = 0; - if (this_is_starfire) - seconds = starfire_get_time(); - else if (tlb_type == hypervisor) - seconds = hypervisor_get_time(); - spin_unlock_irqrestore(&rtc_lock, flags); + to_tm(seconds, time); + time->tm_year -= 1900; + time->tm_mon -= 1; +} + +static int starfire_set_rtc_time(struct rtc_time *time) +{ + u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, + time->tm_mday, time->tm_hour, + time->tm_min, time->tm_sec); + + return starfire_set_time(seconds); +} + +static void hypervisor_get_rtc_time(struct rtc_time *time) +{ + u32 seconds = hypervisor_get_time(); to_tm(seconds, time); time->tm_year -= 1900; time->tm_mon -= 1; } -static inline int mini_set_rtc_time(struct rtc_time *time) +static int hypervisor_set_rtc_time(struct rtc_time *time) { u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); + + return hypervisor_set_time(seconds); +} + +static void bq4802_get_rtc_time(struct rtc_time *time) +{ + unsigned char val = readb(bq4802_regs + 0x0e); + unsigned int century; + + writeb(val | 0x08, bq4802_regs + 0x0e); + + time->tm_sec = readb(bq4802_regs + 0x00); + time->tm_min = readb(bq4802_regs + 0x02); + time->tm_hour = readb(bq4802_regs + 0x04); + time->tm_mday = readb(bq4802_regs + 0x06); + time->tm_mon = readb(bq4802_regs + 0x09); + time->tm_year = readb(bq4802_regs + 0x0a); + time->tm_wday = readb(bq4802_regs + 0x08); + century = readb(bq4802_regs + 0x0f); + + writeb(val, bq4802_regs + 0x0e); + + BCD_TO_BIN(time->tm_sec); + BCD_TO_BIN(time->tm_min); + BCD_TO_BIN(time->tm_hour); + BCD_TO_BIN(time->tm_mday); + BCD_TO_BIN(time->tm_mon); + BCD_TO_BIN(time->tm_year); + BCD_TO_BIN(time->tm_wday); + BCD_TO_BIN(century); + + time->tm_year += (century * 100); + time->tm_year -= 1900; + + time->tm_mon--; +} + +static int bq4802_set_rtc_time(struct rtc_time *time) +{ + unsigned char val = readb(bq4802_regs + 0x0e); + unsigned char sec, min, hrs, day, mon, yrs, century; + unsigned int year; + + year = time->tm_year + 1900; + century = year / 100; + yrs = year % 100; + + mon = time->tm_mon + 1; /* tm_mon starts at zero */ + day = time->tm_mday; + hrs = time->tm_hour; + min = time->tm_min; + sec = time->tm_sec; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + BIN_TO_BCD(day); + BIN_TO_BCD(mon); + BIN_TO_BCD(yrs); + BIN_TO_BCD(century); + + writeb(val | 0x08, bq4802_regs + 0x0e); + + writeb(sec, bq4802_regs + 0x00); + writeb(min, bq4802_regs + 0x02); + writeb(hrs, bq4802_regs + 0x04); + writeb(day, bq4802_regs + 0x06); + writeb(mon, bq4802_regs + 0x09); + writeb(yrs, bq4802_regs + 0x0a); + writeb(century, bq4802_regs + 0x0f); + + writeb(val, bq4802_regs + 0x0e); + + return 0; +} + +struct mini_rtc_ops { + void (*get_rtc_time)(struct rtc_time *); + int (*set_rtc_time)(struct rtc_time *); +}; + +static struct mini_rtc_ops starfire_rtc_ops = { + .get_rtc_time = starfire_get_rtc_time, + .set_rtc_time = starfire_set_rtc_time, +}; + +static struct mini_rtc_ops hypervisor_rtc_ops = { + .get_rtc_time = hypervisor_get_rtc_time, + .set_rtc_time = hypervisor_set_rtc_time, +}; + +static struct mini_rtc_ops bq4802_rtc_ops = { + .get_rtc_time = bq4802_get_rtc_time, + .set_rtc_time = bq4802_set_rtc_time, +}; + +static struct mini_rtc_ops *mini_rtc_ops; + +static inline void mini_get_rtc_time(struct rtc_time *time) +{ + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + mini_rtc_ops->get_rtc_time(time); + spin_unlock_irqrestore(&rtc_lock, flags); +} + +static inline int mini_set_rtc_time(struct rtc_time *time) +{ unsigned long flags; int err; spin_lock_irqsave(&rtc_lock, flags); - err = -ENODEV; - if (this_is_starfire) - err = starfire_set_time(seconds); - else if (tlb_type == hypervisor) - err = hypervisor_set_time(seconds); + err = mini_rtc_ops->set_rtc_time(time); spin_unlock_irqrestore(&rtc_lock, flags); return err; @@ -1391,7 +1575,13 @@ static int __init rtc_mini_init(void) { int retval; - if (tlb_type != hypervisor && !this_is_starfire) + if (tlb_type == hypervisor) + mini_rtc_ops = &hypervisor_rtc_ops; + else if (this_is_starfire) + mini_rtc_ops = &starfire_rtc_ops; + else if (bq4802_regs) + mini_rtc_ops = &bq4802_rtc_ops; + else return -ENODEV; printk(KERN_INFO "Mini RTC Driver\n"); diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index d7004eaf1c8e..6e5b01d779d2 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1008,7 +1008,7 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, if (initrd_start) { size = initrd_end - initrd_start; - /* Resert the initrd image area. */ + /* Reserve the initrd image area. */ #ifdef CONFIG_DEBUG_BOOTMEM prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n", initrd_start, initrd_end); diff --git a/arch/um/Kconfig b/arch/um/Kconfig index b9c0f307a8fa..c504312219b4 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -277,7 +277,8 @@ config HIGHMEM config KERNEL_STACK_ORDER int "Kernel stack size order" - default 2 + default 1 if 64BIT + default 0 if !64BIT help This option determines the size of UML kernel stacks. They will be 1 << order pages. The default is OK unless you're running Valgrind diff --git a/arch/um/defconfig b/arch/um/defconfig index f938fa822146..a54d0efecae1 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -86,7 +86,7 @@ CONFIG_MCONSOLE=y # CONFIG_MAGIC_SYSRQ is not set CONFIG_NEST_LEVEL=0 # CONFIG_HIGHMEM is not set -CONFIG_KERNEL_STACK_ORDER=2 +CONFIG_KERNEL_STACK_ORDER=0 CONFIG_UML_REAL_TIME_CLOCK=y # diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h index 5593a8027083..541f4a8ca512 100644 --- a/arch/um/include/common-offsets.h +++ b/arch/um/include/common-offsets.h @@ -28,3 +28,5 @@ DEFINE(UM_NR_CPUS, NR_CPUS); /* For crypto assembler code. */ DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); + +DEFINE(UM_THREAD_SIZE, THREAD_SIZE); diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 50a49691e0e6..8d7f7c1cb9c6 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -117,4 +117,7 @@ extern void sigio_handler(int sig, union uml_pt_regs *regs); extern void copy_sc(union uml_pt_regs *regs, void *from); +unsigned long to_irq_stack(int sig, unsigned long *mask_out); +unsigned long from_irq_stack(int nested); + #endif diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 688d181b5f8a..4d9fb26387d5 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -272,7 +272,6 @@ extern void do_longjmp(void *p, int val); /* util.c */ extern void stack_protections(unsigned long address); -extern void task_protections(unsigned long address); extern int raw(int fd); extern void setup_machinename(char *machine_out); extern void setup_hostinfo(char *buf, int len); diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index e36f92b463ce..87a4e4427d8d 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -97,6 +97,8 @@ SECTIONS .data : { . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ *(.data.init_task) + . = ALIGN(KERNEL_STACK_SIZE); + *(.data.init_irqstack) *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) } diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index cda91aa8e703..d4f1d1ab252b 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,intel.linux}.com) * Licensed under the GPL */ @@ -33,28 +33,20 @@ EXPORT_SYMBOL(init_task); /* * Initial thread structure. * - * We need to make sure that this is 16384-byte aligned due to the + * We need to make sure that this is aligned due to the * way process stacks are handled. This is done by having a special * "init_task" linker map entry.. */ -union thread_union init_thread_union -__attribute__((__section__(".data.init_task"))) = -{ INIT_THREAD_INFO(init_task) }; +union thread_union init_thread_union + __attribute__((__section__(".data.init_task"))) = + { INIT_THREAD_INFO(init_task) }; + +union thread_union cpu0_irqstack + __attribute__((__section__(".data.init_irqstack"))) = + { INIT_THREAD_INFO(init_task) }; void unprotect_stack(unsigned long stack) { - os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, - 1, 1, 0); + os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0); } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 8f2ed3690315..dba04d88b432 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: @@ -32,6 +32,7 @@ #include "sigio.h" #include "um_malloc.h" #include "misc_constants.h" +#include "as-layout.h" /* * Generic, controller-independent functions: @@ -53,7 +54,7 @@ int show_interrupts(struct seq_file *p, void *v) if (i < NR_IRQS) { spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; - if (!action) + if (!action) goto skip; seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP @@ -468,3 +469,113 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler) out: return err; } + +/* + * IRQ stack entry and exit: + * + * Unlike i386, UML doesn't receive IRQs on the normal kernel stack + * and switch over to the IRQ stack after some preparation. We use + * sigaltstack to receive signals on a separate stack from the start. + * These two functions make sure the rest of the kernel won't be too + * upset by being on a different stack. The IRQ stack has a + * thread_info structure at the bottom so that current et al continue + * to work. + * + * to_irq_stack copies the current task's thread_info to the IRQ stack + * thread_info and sets the tasks's stack to point to the IRQ stack. + * + * from_irq_stack copies the thread_info struct back (flags may have + * been modified) and resets the task's stack pointer. + * + * Tricky bits - + * + * What happens when two signals race each other? UML doesn't block + * signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal + * could arrive while a previous one is still setting up the + * thread_info. + * + * There are three cases - + * The first interrupt on the stack - sets up the thread_info and + * handles the interrupt + * A nested interrupt interrupting the copying of the thread_info - + * can't handle the interrupt, as the stack is in an unknown state + * A nested interrupt not interrupting the copying of the + * thread_info - doesn't do any setup, just handles the interrupt + * + * The first job is to figure out whether we interrupted stack setup. + * This is done by xchging the signal mask with thread_info->pending. + * If the value that comes back is zero, then there is no setup in + * progress, and the interrupt can be handled. If the value is + * non-zero, then there is stack setup in progress. In order to have + * the interrupt handled, we leave our signal in the mask, and it will + * be handled by the upper handler after it has set up the stack. + * + * Next is to figure out whether we are the outer handler or a nested + * one. As part of setting up the stack, thread_info->real_thread is + * set to non-NULL (and is reset to NULL on exit). This is the + * nesting indicator. If it is non-NULL, then the stack is already + * set up and the handler can run. + */ + +static unsigned long pending_mask; + +unsigned long to_irq_stack(int sig, unsigned long *mask_out) +{ + struct thread_info *ti; + unsigned long mask, old; + int nested; + + mask = xchg(&pending_mask, 1 << sig); + if(mask != 0){ + /* If any interrupts come in at this point, we want to + * make sure that their bits aren't lost by our + * putting our bit in. So, this loop accumulates bits + * until xchg returns the same value that we put in. + * When that happens, there were no new interrupts, + * and pending_mask contains a bit for each interrupt + * that came in. + */ + old = 1 << sig; + do { + old |= mask; + mask = xchg(&pending_mask, old); + } while(mask != old); + return 1; + } + + ti = current_thread_info(); + nested = (ti->real_thread != NULL); + if(!nested){ + struct task_struct *task; + struct thread_info *tti; + + task = cpu_tasks[ti->cpu].task; + tti = task_thread_info(task); + *ti = *tti; + ti->real_thread = tti; + task->stack = ti; + } + + mask = xchg(&pending_mask, 0); + *mask_out |= mask | nested; + return 0; +} + +unsigned long from_irq_stack(int nested) +{ + struct thread_info *ti, *to; + unsigned long mask; + + ti = current_thread_info(); + + pending_mask = 1; + + to = ti->real_thread; + current->stack = to; + ti->real_thread = NULL; + *to = *ti; + + mask = xchg(&pending_mask, 0); + return mask & ~1; +} + diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index a96ae1a0610e..2a69a7ce5792 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -163,8 +163,12 @@ static int start_kernel_proc(void *unused) extern int userspace_pid[]; +extern char cpu0_irqstack[]; + int start_uml_skas(void) { + stack_protections((unsigned long) &cpu0_irqstack); + set_sigstack(cpu0_irqstack, THREAD_SIZE); if(proc_mm) userspace_pid[0] = start_userspace(0); diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index 98e21743e604..40126cb51801 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c @@ -57,7 +57,7 @@ void flush_thread_tt(void) enable_timer(); free_page(stack); protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); - task_protections((unsigned long) current_thread); + stack_protections((unsigned long) current_thread); force_flush_all(); unblock_signals(); } diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index c631303cb800..74347adf81bf 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -209,7 +209,7 @@ void finish_fork_handler(int sig) if(current->mm != current->parent->mm) protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); - task_protections((unsigned long) current_thread); + stack_protections((unsigned long) current_thread); free_page(current->thread.temp_stack); local_irq_disable(); diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 1cf954a47fd7..ecc458fe51b9 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -459,7 +459,7 @@ int __init linux_main(int argc, char **argv) uml_postsetup(); - task_protections((unsigned long) &init_thread_info); + stack_protections((unsigned long) &init_thread_info); os_flush_stdout(); return CHOOSE_MODE(start_uml_tt(), start_uml_skas()); diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index f6301274cf3c..bc59f97e34d0 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -59,6 +59,8 @@ SECTIONS { . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ *(.data.init_task) + . = ALIGN(KERNEL_STACK_SIZE); + *(.data.init_irqstack) *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 48d493415301..18e5c8b67eb8 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -61,15 +61,19 @@ void sig_handler(int sig, struct sigcontext *sc) static void real_alarm_handler(int sig, struct sigcontext *sc) { + union uml_pt_regs regs; + if(sig == SIGALRM) switch_timers(0); - CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, - sig, sc); + if(sc != NULL) + copy_sc(®s, sc); + regs.skas.is_user = 0; + unblock_signals(); + timer_handler(sig, ®s); if(sig == SIGALRM) switch_timers(1); - } void alarm_handler(int sig, struct sigcontext *sc) @@ -113,6 +117,46 @@ void remove_sigstack(void) void (*handlers[_NSIG])(int sig, struct sigcontext *sc); +void handle_signal(int sig, struct sigcontext *sc) +{ + unsigned long pending = 0; + + do { + int nested, bail; + + /* + * pending comes back with one bit set for each + * interrupt that arrived while setting up the stack, + * plus a bit for this interrupt, plus the zero bit is + * set if this is a nested interrupt. + * If bail is true, then we interrupted another + * handler setting up the stack. In this case, we + * have to return, and the upper handler will deal + * with this interrupt. + */ + bail = to_irq_stack(sig, &pending); + if(bail) + return; + + nested = pending & 1; + pending &= ~1; + + while((sig = ffs(pending)) != 0){ + sig--; + pending &= ~(1 << sig); + (*handlers[sig])(sig, sc); + } + + /* Again, pending comes back with a mask of signals + * that arrived while tearing down the stack. If this + * is non-zero, we just go back, set up the stack + * again, and handle the new interrupts. + */ + if(!nested) + pending = from_irq_stack(nested); + } while(pending); +} + extern void hard_handler(int sig); void set_handler(int sig, void (*handler)(int), int flags, ...) diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 6a0e466d01e3..f9d2f8545afe 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -288,7 +288,8 @@ int start_userspace(unsigned long stub_stack) void userspace(union uml_pt_regs *regs) { int err, status, op, pid = userspace_pid[0]; - int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ + /* To prevent races if using_sysemu changes under us.*/ + int local_using_sysemu; while(1){ restore_registers(pid, regs); @@ -296,7 +297,8 @@ void userspace(union uml_pt_regs *regs) /* Now we set local_using_sysemu to be used for one loop */ local_using_sysemu = get_using_sysemu(); - op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); + op = SELECT_PTRACE_OPERATION(local_using_sysemu, + singlestepping(NULL)); err = ptrace(op, pid, 0, 0); if(err) @@ -490,8 +492,8 @@ void map_stub_pages(int fd, unsigned long code, void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) { (*buf)[0].JB_IP = (unsigned long) handler; - (*buf)[0].JB_SP = (unsigned long) stack + - (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *); + (*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE - + sizeof(void *); } #define INIT_JMP_NEW_THREAD 0 @@ -533,8 +535,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) case INIT_JMP_NEW_THREAD: (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; (*switch_buf)[0].JB_SP = (unsigned long) stack + - (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - - sizeof(void *); + UM_THREAD_SIZE - sizeof(void *); break; case INIT_JMP_CALLBACK: (*cb_proc)(cb_arg); diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c index 0d3eae518352..f311609f93da 100644 --- a/arch/um/os-Linux/sys-i386/signal.c +++ b/arch/um/os-Linux/sys-i386/signal.c @@ -1,15 +1,13 @@ /* - * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <signal.h> -extern void (*handlers[])(int sig, struct sigcontext *sc); +extern void handle_signal(int sig, struct sigcontext *sc); void hard_handler(int sig) { - struct sigcontext *sc = (struct sigcontext *) (&sig + 1); - - (*handlers[sig])(sig, sc); + handle_signal(sig, (struct sigcontext *) (&sig + 1)); } diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c index 3f369e5f976b..82a388822cd3 100644 --- a/arch/um/os-Linux/sys-x86_64/signal.c +++ b/arch/um/os-Linux/sys-x86_64/signal.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <signal.h> -extern void (*handlers[])(int sig, struct sigcontext *sc); +extern void handle_signal(int sig, struct sigcontext *sc); void hard_handler(int sig) { struct ucontext *uc; asm("movq %%rdx, %0" : "=r" (uc)); - (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext); + handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext); } diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index c307a89ed259..7cbcf484e13d 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -33,25 +33,8 @@ void stack_protections(unsigned long address) { - int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - - if(mprotect((void *) address, UM_KERN_PAGE_SIZE, prot) < 0) - panic("protecting stack failed, errno = %d", errno); -} - -void task_protections(unsigned long address) -{ - unsigned long guard = address + UM_KERN_PAGE_SIZE; - unsigned long stack = guard + UM_KERN_PAGE_SIZE; - int prot = 0, pages; - -#ifdef notdef - if(mprotect((void *) stack, UM_KERN_PAGE_SIZE, prot) < 0) - panic("protecting guard page failed, errno = %d", errno); -#endif - pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; - prot = PROT_READ | PROT_WRITE | PROT_EXEC; - if(mprotect((void *) stack, pages * UM_KERN_PAGE_SIZE, prot) < 0) + if(mprotect((void *) address, UM_THREAD_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC) < 0) panic("protecting stack failed, errno = %d", errno); } @@ -72,7 +55,7 @@ int raw(int fd) /* XXX tcsetattr could have applied only some changes * (and cfmakeraw() is a set of changes) */ - return(0); + return 0; } void setup_machinename(char *machine_out) diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c index 92d7d0c8d93f..8850fe40ea34 100644 --- a/arch/x86_64/ia32/audit.c +++ b/arch/x86_64/ia32/audit.c @@ -20,6 +20,11 @@ unsigned ia32_read_class[] = { ~0U }; +unsigned ia32_signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + int ia32_classify_syscall(unsigned syscall) { switch(syscall) { diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index f21068378272..21868f9bed7c 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -716,4 +716,7 @@ ia32_sys_call_table: .quad sys_getcpu .quad sys_epoll_pwait .quad compat_sys_utimensat /* 320 */ -ia32_syscall_end: + .quad compat_sys_signalfd + .quad compat_sys_timerfd + .quad sys_eventfd +ia32_syscall_end: diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index a52af5820592..a3d450d6c15b 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c @@ -86,7 +86,7 @@ static int __init aperture_valid(u64 aper_base, u32 aper_size) printk("Aperture too small (%d MB)\n", aper_size>>20); return 0; } - if (aper_base + aper_size >= 0xffffffff) { + if (aper_base + aper_size > 0x100000000UL) { printk("Aperture beyond 4GB. Ignoring.\n"); return 0; } diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c index 21f33387bef3..06d3e5a14d9d 100644 --- a/arch/x86_64/kernel/audit.c +++ b/arch/x86_64/kernel/audit.c @@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ~0U }; +static unsigned signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + +int audit_classify_arch(int arch) +{ +#ifdef CONFIG_IA32_EMULATION + if (arch == AUDIT_ARCH_I386) + return 1; +#endif + return 0; +} + int audit_classify_syscall(int abi, unsigned syscall) { #ifdef CONFIG_IA32_EMULATION @@ -49,15 +63,18 @@ static int __init audit_classes_init(void) extern __u32 ia32_write_class[]; extern __u32 ia32_read_class[]; extern __u32 ia32_chattr_class[]; + extern __u32 ia32_signal_class[]; audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class); audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class); #endif audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL, signal_class); return 0; } diff --git a/arch/x86_64/kernel/bugs.c b/arch/x86_64/kernel/bugs.c index 12b585b5345d..c3c6b91566ed 100644 --- a/arch/x86_64/kernel/bugs.c +++ b/arch/x86_64/kernel/bugs.c @@ -9,10 +9,12 @@ #include <linux/init.h> #include <asm/alternative.h> #include <asm/processor.h> +#include <asm/mtrr.h> void __init check_bugs(void) { identify_cpu(&boot_cpu_data); + mtrr_bp_init(); #if !defined(CONFIG_SMP) printk("CPU: "); print_cpu_info(&boot_cpu_data); diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index 213d90e04755..6c34bdd22e26 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c @@ -62,13 +62,6 @@ void __init x86_64_start_kernel(char * real_mode_data) { int i; - /* - * Make sure kernel is aligned to 2MB address. Catching it at compile - * time is better. Change your config file and compile the kernel - * for a 2MB aligned address (CONFIG_PHYSICAL_START) - */ - BUILD_BUG_ON(CONFIG_PHYSICAL_START & (__KERNEL_ALIGN - 1)); - /* clear bss before set_intr_gate with early_idt_handler */ clear_bss(); diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 373ef66ca1dc..ae091cdc1a4d 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -476,7 +476,7 @@ static __init unsigned read_aperture(struct pci_dev *dev, u32 *size) aper_base <<= 25; aper_size = (32 * 1024 * 1024) << aper_order; - if (aper_base + aper_size >= 0xffffffff || !aper_size) + if (aper_base + aper_size > 0x100000000UL || !aper_size) aper_base = 0; *size = aper_size; diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index db51577bda32..eb6524f3ac29 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -891,9 +891,7 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) #ifdef CONFIG_X86_MCE mcheck_init(c); #endif - if (c == &boot_cpu_data) - mtrr_bp_init(); - else + if (c != &boot_cpu_data) mtrr_ap_init(); #ifdef CONFIG_NUMA numa_add_cpu(smp_processor_id()); diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 17e188973428..74a567afb830 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3116,7 +3116,7 @@ static inline int should_fail_request(struct bio *bio) * bi_sector for remaps as it sees fit. So the values of these fields * should NOT be depended on after the call to generic_make_request. */ -void generic_make_request(struct bio *bio) +static inline void __generic_make_request(struct bio *bio) { request_queue_t *q; sector_t maxsector; @@ -3215,6 +3215,57 @@ end_io: } while (ret); } +/* + * We only want one ->make_request_fn to be active at a time, + * else stack usage with stacked devices could be a problem. + * So use current->bio_{list,tail} to keep a list of requests + * submited by a make_request_fn function. + * current->bio_tail is also used as a flag to say if + * generic_make_request is currently active in this task or not. + * If it is NULL, then no make_request is active. If it is non-NULL, + * then a make_request is active, and new requests should be added + * at the tail + */ +void generic_make_request(struct bio *bio) +{ + if (current->bio_tail) { + /* make_request is active */ + *(current->bio_tail) = bio; + bio->bi_next = NULL; + current->bio_tail = &bio->bi_next; + return; + } + /* following loop may be a bit non-obvious, and so deserves some + * explanation. + * Before entering the loop, bio->bi_next is NULL (as all callers + * ensure that) so we have a list with a single bio. + * We pretend that we have just taken it off a longer list, so + * we assign bio_list to the next (which is NULL) and bio_tail + * to &bio_list, thus initialising the bio_list of new bios to be + * added. __generic_make_request may indeed add some more bios + * through a recursive call to generic_make_request. If it + * did, we find a non-NULL value in bio_list and re-enter the loop + * from the top. In this case we really did just take the bio + * of the top of the list (no pretending) and so fixup bio_list and + * bio_tail or bi_next, and call into __generic_make_request again. + * + * The loop was structured like this to make only one call to + * __generic_make_request (which is important as it is large and + * inlined) and to keep the structure simple. + */ + BUG_ON(bio->bi_next); + do { + current->bio_list = bio->bi_next; + if (bio->bi_next == NULL) + current->bio_tail = ¤t->bio_list; + else + bio->bi_next = NULL; + __generic_make_request(bio); + bio = current->bio_list; + } while (bio); + current->bio_tail = NULL; /* deactivate */ +} + EXPORT_SYMBOL(generic_make_request); /** diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index f031b8732330..ad1f59c1b3fc 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -2,11 +2,9 @@ # SATA/PATA driver configuration # -menu "Serial ATA (prod) and Parallel ATA (experimental) drivers" +menuconfig ATA + tristate "Serial ATA (prod) and Parallel ATA (experimental) drivers" depends on HAS_IOMEM - -config ATA - tristate "ATA device support" depends on BLOCK depends on !(M32R || M68K) || BROKEN depends on !SUN4 || BROKEN @@ -24,6 +22,19 @@ config ATA_NONSTANDARD bool default n +config ATA_ACPI + bool + depends on ACPI && PCI + default y + help + This option adds support for ATA-related ACPI objects. + These ACPI objects add the ability to retrieve taskfiles + from the ACPI BIOS and write them to the disk controller. + These objects may be related to performance, security, + power management, or other areas. + You can disable this at kernel boot time by using the + option libata.noacpi=1 + config SATA_AHCI tristate "AHCI SATA support" depends on PCI @@ -157,19 +168,6 @@ config SATA_INIC162X help This option enables support for Initio 162x Serial ATA. -config SATA_ACPI - bool - depends on ACPI && PCI - default y - help - This option adds support for SATA-related ACPI objects. - These ACPI objects add the ability to retrieve taskfiles - from the ACPI BIOS and write them to the disk controller. - These objects may be related to performance, security, - power management, or other areas. - You can disable this at kernel boot time by using the - option libata.noacpi=1 - config PATA_ALI tristate "ALi PATA support (Experimental)" depends on PCI && EXPERIMENTAL @@ -585,6 +583,4 @@ config PATA_SCC If unsure, say N. -endif -endmenu - +endif # ATA diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 6f42a0e2812d..8149c68ac2c7 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -69,4 +69,4 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o -libata-$(CONFIG_SATA_ACPI) += libata-acpi.o +libata-$(CONFIG_ATA_ACPI) += libata-acpi.o diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index d9617892fc23..1ae443d7ab92 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -250,10 +250,6 @@ static struct scsi_host_template ahci_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const struct ata_port_operations ahci_ops = { @@ -400,6 +396,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ + { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700 */ /* VIA */ { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 92a491ddd030..c3d753296bc6 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -54,7 +54,7 @@ static int generic_set_mode(struct ata_port *ap, struct ata_device **unused) for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (ata_dev_ready(dev)) { + if (ata_dev_enabled(dev)) { /* We don't really care */ dev->pio_mode = XFER_PIO_0; dev->dma_mode = XFER_MW_DMA_0; @@ -90,10 +90,6 @@ static struct scsi_host_template generic_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations generic_port_ops = { @@ -145,7 +141,7 @@ static int all_generic_ide; /* Set to claim all devices */ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) { u16 command; - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &generic_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -153,7 +149,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id .udma_mask = 0x3f, .port_ops = &generic_port_ops }; - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; /* Don't use the generic entry unless instructed to do so */ if (id->driver_data == 1 && all_generic_ide == 0) @@ -179,7 +175,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id if (dev->vendor == PCI_VENDOR_ID_AL) ata_pci_clear_simplex(dev); - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_init_one(dev, ppi); } static struct pci_device_id ata_generic[] = { diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 4a795fdb6a02..13b6b1df2ac4 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -275,10 +275,6 @@ static struct scsi_host_template piix_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static const struct ata_port_operations piix_pata_ops = { @@ -1034,7 +1030,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; struct device *dev = &pdev->dev; struct ata_port_info port_info[2]; - struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] }; + const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] }; struct piix_host_priv *hpriv; unsigned long port_flags; @@ -1093,7 +1089,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) port_info[1].mwdma_mask = 0; port_info[1].udma_mask = 0; } - return ata_pci_init_one(pdev, ppinfo, 2); + return ata_pci_init_one(pdev, ppi); } static int __init piix_init(void) diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index cb3eab6e379d..ed4138e24b0c 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -270,8 +270,7 @@ out: /** * do_drive_get_GTF - get the drive bootup default taskfile settings - * @ap: the ata_port for the drive - * @ix: target ata_device (drive) index + * @dev: target ATA device * @gtf_length: number of bytes of _GTF data returned at @gtf_address * @gtf_address: buffer containing _GTF taskfile arrays * @@ -286,20 +285,19 @@ out: * The returned @gtf_length and @gtf_address are only valid if the * function return value is 0. */ -static int do_drive_get_GTF(struct ata_port *ap, int ix, - unsigned int *gtf_length, unsigned long *gtf_address, - unsigned long *obj_loc) +static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length, + unsigned long *gtf_address, unsigned long *obj_loc) { - acpi_status status; - acpi_handle dev_handle = NULL; - acpi_handle chan_handle, drive_handle; - acpi_integer pcidevfn = 0; - u32 dev_adr; - struct acpi_buffer output; - union acpi_object *out_obj; - struct device *dev = ap->host->dev; - struct ata_device *atadev = &ap->device[ix]; - int err = -ENODEV; + struct ata_port *ap = dev->ap; + acpi_status status; + acpi_handle dev_handle = NULL; + acpi_handle chan_handle, drive_handle; + acpi_integer pcidevfn = 0; + u32 dev_adr; + struct acpi_buffer output; + union acpi_object *out_obj; + struct device *gdev = ap->host->dev; + int err = -ENODEV; *gtf_length = 0; *gtf_address = 0UL; @@ -309,14 +307,14 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, return 0; if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, "%s: ENTER: port#: %d\n", + ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n", __FUNCTION__, ap->port_no); - if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) { + if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED)) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, "%s: ERR: " + ata_dev_printk(dev, KERN_DEBUG, "%s: ERR: " "ata_dev_present: %d, PORT_DISABLED: %lu\n", - __FUNCTION__, ata_dev_enabled(atadev), + __FUNCTION__, ata_dev_enabled(dev), ap->flags & ATA_FLAG_DISABLED); goto out; } @@ -324,19 +322,19 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, /* Don't continue if device has no _ADR method. * _GTF is intended for known motherboard devices. */ if (!(ap->cbl == ATA_CBL_SATA)) { - err = pata_get_dev_handle(dev, &dev_handle, &pcidevfn); + err = pata_get_dev_handle(gdev, &dev_handle, &pcidevfn); if (err < 0) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, + ata_dev_printk(dev, KERN_DEBUG, "%s: pata_get_dev_handle failed (%d)\n", __FUNCTION__, err); goto out; } } else { - err = sata_get_dev_handle(dev, &dev_handle, &pcidevfn); + err = sata_get_dev_handle(gdev, &dev_handle, &pcidevfn); if (err < 0) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, + ata_dev_printk(dev, KERN_DEBUG, "%s: sata_get_dev_handle failed (%d\n", __FUNCTION__, err); goto out; @@ -344,7 +342,7 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, } /* Get this drive's _ADR info. if not already known. */ - if (!atadev->obj_handle) { + if (!dev->obj_handle) { if (!(ap->cbl == ATA_CBL_SATA)) { /* get child objects of dev_handle == channel objects, * + _their_ children == drive objects */ @@ -352,7 +350,7 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, chan_handle = acpi_get_child(dev_handle, ap->port_no); if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, + ata_dev_printk(dev, KERN_DEBUG, "%s: chan adr=%d: chan_handle=0x%p\n", __FUNCTION__, ap->port_no, chan_handle); @@ -361,26 +359,26 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, goto out; } /* TBD: could also check ACPI object VALID bits */ - drive_handle = acpi_get_child(chan_handle, ix); + drive_handle = acpi_get_child(chan_handle, dev->devno); if (!drive_handle) { err = -ENODEV; goto out; } - dev_adr = ix; - atadev->obj_handle = drive_handle; + dev_adr = dev->devno; + dev->obj_handle = drive_handle; } else { /* for SATA mode */ dev_adr = SATA_ADR_RSVD; - err = get_sata_adr(dev, dev_handle, pcidevfn, 0, - ap, atadev, &dev_adr); + err = get_sata_adr(gdev, dev_handle, pcidevfn, 0, + ap, dev, &dev_adr); } if (err < 0 || dev_adr == SATA_ADR_RSVD || - !atadev->obj_handle) { + !dev->obj_handle) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, + ata_dev_printk(dev, KERN_DEBUG, "%s: get_sata/pata_adr failed: " "err=%d, dev_adr=%u, obj_handle=0x%p\n", __FUNCTION__, err, dev_adr, - atadev->obj_handle); + dev->obj_handle); goto out; } } @@ -391,11 +389,11 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, /* _GTF has no input parameters */ err = -EIO; - status = acpi_evaluate_object(atadev->obj_handle, "_GTF", + status = acpi_evaluate_object(dev->obj_handle, "_GTF", NULL, &output); if (ACPI_FAILURE(status)) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, + ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF error: status = 0x%x\n", __FUNCTION__, status); goto out; @@ -403,7 +401,7 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, if (!output.length || !output.pointer) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: " + ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: " "length or ptr is NULL (0x%llx, 0x%p)\n", __FUNCTION__, (unsigned long long)output.length, @@ -416,7 +414,7 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, if (out_obj->type != ACPI_TYPE_BUFFER) { kfree(output.pointer); if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: " + ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: " "error: expected object type of " " ACPI_TYPE_BUFFER, got 0x%x\n", __FUNCTION__, out_obj->type); @@ -427,7 +425,7 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, if (!out_obj->buffer.length || !out_obj->buffer.pointer || out_obj->buffer.length % REGS_PER_GTF) { if (ata_msg_drv(ap)) - ata_dev_printk(atadev, KERN_ERR, + ata_dev_printk(dev, KERN_ERR, "%s: unexpected GTF length (%d) or addr (0x%p)\n", __FUNCTION__, out_obj->buffer.length, out_obj->buffer.pointer); @@ -439,7 +437,7 @@ static int do_drive_get_GTF(struct ata_port *ap, int ix, *gtf_address = (unsigned long)out_obj->buffer.pointer; *obj_loc = (unsigned long)out_obj; if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, "%s: returning " + ata_dev_printk(dev, KERN_DEBUG, "%s: returning " "gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n", __FUNCTION__, *gtf_length, *gtf_address, *obj_loc); err = 0; @@ -449,7 +447,7 @@ out: /** * taskfile_load_raw - send taskfile registers to host controller - * @ap: Port to which output is sent + * @dev: target ATA device * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) * * Outputs ATA taskfile to standard ATA host controller using MMIO @@ -466,15 +464,15 @@ out: * LOCKING: TBD: * Inherited from caller. */ -static void taskfile_load_raw(struct ata_port *ap, - struct ata_device *atadev, - const struct taskfile_array *gtf) +static void taskfile_load_raw(struct ata_device *dev, + const struct taskfile_array *gtf) { + struct ata_port *ap = dev->ap; struct ata_taskfile tf; unsigned int err; if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: " + ata_dev_printk(dev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: " "%02x %02x %02x %02x %02x %02x %02x\n", __FUNCTION__, gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], @@ -485,7 +483,7 @@ static void taskfile_load_raw(struct ata_port *ap, && (gtf->tfa[6] == 0)) return; - ata_tf_init(atadev, &tf); + ata_tf_init(dev, &tf); /* convert gtf to tf */ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */ @@ -498,17 +496,16 @@ static void taskfile_load_raw(struct ata_port *ap, tf.device = gtf->tfa[5]; /* 0x1f6 */ tf.command = gtf->tfa[6]; /* 0x1f7 */ - err = ata_exec_internal(atadev, &tf, NULL, DMA_NONE, NULL, 0); + err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); if (err && ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_ERR, + ata_dev_printk(dev, KERN_ERR, "%s: ata_exec_internal failed: %u\n", __FUNCTION__, err); } /** * do_drive_set_taskfiles - write the drive taskfile settings from _GTF - * @ap: the ata_port for the drive - * @atadev: target ata_device + * @dev: target ATA device * @gtf_length: total number of bytes of _GTF taskfiles * @gtf_address: location of _GTF taskfile arrays * @@ -517,30 +514,31 @@ static void taskfile_load_raw(struct ata_port *ap, * Write {gtf_address, length gtf_length} in groups of * REGS_PER_GTF bytes. */ -static int do_drive_set_taskfiles(struct ata_port *ap, - struct ata_device *atadev, unsigned int gtf_length, - unsigned long gtf_address) +static int do_drive_set_taskfiles(struct ata_device *dev, + unsigned int gtf_length, + unsigned long gtf_address) { - int err = -ENODEV; - int gtf_count = gtf_length / REGS_PER_GTF; - int ix; + struct ata_port *ap = dev->ap; + int err = -ENODEV; + int gtf_count = gtf_length / REGS_PER_GTF; + int ix; struct taskfile_array *gtf; if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, "%s: ENTER: port#: %d\n", + ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n", __FUNCTION__, ap->port_no); if (libata_noacpi || !(ap->cbl == ATA_CBL_SATA)) return 0; - if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) + if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED)) goto out; if (!gtf_count) /* shouldn't be here */ goto out; if (gtf_length % REGS_PER_GTF) { if (ata_msg_drv(ap)) - ata_dev_printk(atadev, KERN_ERR, + ata_dev_printk(dev, KERN_ERR, "%s: unexpected GTF length (%d)\n", __FUNCTION__, gtf_length); goto out; @@ -551,7 +549,7 @@ static int do_drive_set_taskfiles(struct ata_port *ap, (gtf_address + ix * REGS_PER_GTF); /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ - taskfile_load_raw(ap, atadev, gtf); + taskfile_load_raw(dev, gtf); } err = 0; @@ -567,11 +565,11 @@ out: */ int ata_acpi_exec_tfs(struct ata_port *ap) { - int ix; - int ret =0; - unsigned int gtf_length; - unsigned long gtf_address; - unsigned long obj_loc; + int ix; + int ret = 0; + unsigned int gtf_length; + unsigned long gtf_address; + unsigned long obj_loc; if (libata_noacpi) return 0; @@ -584,11 +582,13 @@ int ata_acpi_exec_tfs(struct ata_port *ap) return 0; for (ix = 0; ix < ATA_MAX_DEVICES; ix++) { - if (!ata_dev_enabled(&ap->device[ix])) + struct ata_device *dev = &ap->device[ix]; + + if (!ata_dev_enabled(dev)) continue; - ret = do_drive_get_GTF(ap, ix, - >f_length, >f_address, &obj_loc); + ret = do_drive_get_GTF(dev, >f_length, >f_address, + &obj_loc); if (ret < 0) { if (ata_msg_probe(ap)) ata_port_printk(ap, KERN_DEBUG, @@ -597,8 +597,7 @@ int ata_acpi_exec_tfs(struct ata_port *ap) break; } - ret = do_drive_set_taskfiles(ap, &ap->device[ix], - gtf_length, gtf_address); + ret = do_drive_set_taskfiles(dev, gtf_length, gtf_address); kfree((void *)obj_loc); if (ret < 0) { if (ata_msg_probe(ap)) @@ -614,8 +613,7 @@ int ata_acpi_exec_tfs(struct ata_port *ap) /** * ata_acpi_push_id - send Identify data to drive - * @ap: the ata_port for the drive - * @ix: drive index + * @dev: target ATA device * * _SDD ACPI object: for SATA mode only * Must be after Identify (Packet) Device -- uses its data @@ -623,57 +621,57 @@ int ata_acpi_exec_tfs(struct ata_port *ap) * method and if it fails for whatever reason, we should still * just keep going. */ -int ata_acpi_push_id(struct ata_port *ap, unsigned int ix) +int ata_acpi_push_id(struct ata_device *dev) { - acpi_handle handle; - acpi_integer pcidevfn; - int err; - struct device *dev = ap->host->dev; - struct ata_device *atadev = &ap->device[ix]; - u32 dev_adr; - acpi_status status; - struct acpi_object_list input; - union acpi_object in_params[1]; + struct ata_port *ap = dev->ap; + acpi_handle handle; + acpi_integer pcidevfn; + int err; + struct device *gdev = ap->host->dev; + u32 dev_adr; + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[1]; if (libata_noacpi) return 0; if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, "%s: ix = %d, port#: %d\n", - __FUNCTION__, ix, ap->port_no); + ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n", + __FUNCTION__, dev->devno, ap->port_no); /* Don't continue if not a SATA device. */ if (!(ap->cbl == ATA_CBL_SATA)) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, + ata_dev_printk(dev, KERN_DEBUG, "%s: Not a SATA device\n", __FUNCTION__); goto out; } /* Don't continue if device has no _ADR method. * _SDD is intended for known motherboard devices. */ - err = sata_get_dev_handle(dev, &handle, &pcidevfn); + err = sata_get_dev_handle(gdev, &handle, &pcidevfn); if (err < 0) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, + ata_dev_printk(dev, KERN_DEBUG, "%s: sata_get_dev_handle failed (%d\n", __FUNCTION__, err); goto out; } /* Get this drive's _ADR info, if not already known */ - if (!atadev->obj_handle) { + if (!dev->obj_handle) { dev_adr = SATA_ADR_RSVD; - err = get_sata_adr(dev, handle, pcidevfn, ix, ap, atadev, + err = get_sata_adr(gdev, handle, pcidevfn, dev->devno, ap, dev, &dev_adr); if (err < 0 || dev_adr == SATA_ADR_RSVD || - !atadev->obj_handle) { + !dev->obj_handle) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, + ata_dev_printk(dev, KERN_DEBUG, "%s: get_sata_adr failed: " "err=%d, dev_adr=%u, obj_handle=0x%p\n", __FUNCTION__, err, dev_adr, - atadev->obj_handle); + dev->obj_handle); goto out; } } @@ -683,19 +681,19 @@ int ata_acpi_push_id(struct ata_port *ap, unsigned int ix) input.count = 1; input.pointer = in_params; in_params[0].type = ACPI_TYPE_BUFFER; - in_params[0].buffer.length = sizeof(atadev->id[0]) * ATA_ID_WORDS; - in_params[0].buffer.pointer = (u8 *)atadev->id; + in_params[0].buffer.length = sizeof(dev->id[0]) * ATA_ID_WORDS; + in_params[0].buffer.pointer = (u8 *)dev->id; /* Output buffer: _SDD has no output */ /* It's OK for _SDD to be missing too. */ - swap_buf_le16(atadev->id, ATA_ID_WORDS); - status = acpi_evaluate_object(atadev->obj_handle, "_SDD", &input, NULL); - swap_buf_le16(atadev->id, ATA_ID_WORDS); + swap_buf_le16(dev->id, ATA_ID_WORDS); + status = acpi_evaluate_object(dev->obj_handle, "_SDD", &input, NULL); + swap_buf_le16(dev->id, ATA_ID_WORDS); err = ACPI_FAILURE(status) ? -EIO : 0; if (err < 0) { if (ata_msg_probe(ap)) - ata_dev_printk(atadev, KERN_DEBUG, + ata_dev_printk(dev, KERN_DEBUG, "%s _SDD error: status = 0x%x\n", __FUNCTION__, status); } diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4595d1f8cf60..4166407eb47c 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -101,6 +101,12 @@ int libata_noacpi = 1; module_param_named(noacpi, libata_noacpi, int, 0444); MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set"); +int ata_spindown_compat = 1; +module_param_named(spindown_compat, ata_spindown_compat, int, 0644); +MODULE_PARM_DESC(spindown_compat, "Enable backward compatible spindown " + "behavior. Will be removed. More info can be found in " + "Documentation/feature-removal-schedule.txt\n"); + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); @@ -1654,7 +1660,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, struct ata_taskfile tf; unsigned int err_mask = 0; const char *reason; - int tried_spinup = 0; + int may_fallback = 1, tried_spinup = 0; int rc; if (ata_msg_ctl(ap)) @@ -1698,11 +1704,31 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, return -ENOENT; } + /* Device or controller might have reported the wrong + * device class. Give a shot at the other IDENTIFY if + * the current one is aborted by the device. + */ + if (may_fallback && + (err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) { + may_fallback = 0; + + if (class == ATA_DEV_ATA) + class = ATA_DEV_ATAPI; + else + class = ATA_DEV_ATA; + goto retry; + } + rc = -EIO; reason = "I/O error"; goto err_out; } + /* Falling back doesn't make sense if ID data was read + * successfully at least once. + */ + may_fallback = 0; + swap_buf_le16(id, ATA_ID_WORDS); /* sanity check */ @@ -1843,7 +1869,7 @@ int ata_dev_configure(struct ata_device *dev) ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); /* set _SDD */ - rc = ata_acpi_push_id(ap, dev->devno); + rc = ata_acpi_push_id(dev); if (rc) { ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n", rc); @@ -2860,7 +2886,7 @@ int ata_do_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) dev = &ap->device[i]; /* don't update suspended devices' xfer mode */ - if (!ata_dev_ready(dev)) + if (!ata_dev_enabled(dev)) continue; rc = ata_dev_set_mode(dev); @@ -5845,37 +5871,11 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, */ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) { - int i, j, rc; + int rc; rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1); - if (rc) - goto fail; - - /* EH is quiescent now. Fail if we have any ready device. - * This happens if hotplug occurs between completion of device - * suspension and here. - */ - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - - for (j = 0; j < ATA_MAX_DEVICES; j++) { - struct ata_device *dev = &ap->device[j]; - - if (ata_dev_ready(dev)) { - ata_port_printk(ap, KERN_WARNING, - "suspend failed, device %d " - "still active\n", dev->devno); - rc = -EBUSY; - goto fail; - } - } - } - - host->dev->power.power_state = mesg; - return 0; - - fail: - ata_host_resume(host); + if (rc == 0) + host->dev->power.power_state = mesg; return rc; } @@ -5984,6 +5984,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host) if (!ap) return NULL; + ap->pflags |= ATA_PFLAG_INITIALIZING; ap->lock = &host->lock; ap->flags = ATA_FLAG_DISABLED; ap->print_id = -1; @@ -6352,6 +6353,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) ehi->action |= ATA_EH_SOFTRESET; ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; + ap->pflags &= ~ATA_PFLAG_INITIALIZING; ap->pflags |= ATA_PFLAG_LOADING; ata_port_schedule_eh(ap); @@ -6876,6 +6878,7 @@ EXPORT_SYMBOL_GPL(ata_timing_merge); #ifdef CONFIG_PCI EXPORT_SYMBOL_GPL(pci_test_config_bits); EXPORT_SYMBOL_GPL(ata_pci_init_native_host); +EXPORT_SYMBOL_GPL(ata_pci_init_bmdma); EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host); EXPORT_SYMBOL_GPL(ata_pci_init_one); EXPORT_SYMBOL_GPL(ata_pci_remove_one); @@ -6889,11 +6892,6 @@ EXPORT_SYMBOL_GPL(ata_pci_default_filter); EXPORT_SYMBOL_GPL(ata_pci_clear_simplex); #endif /* CONFIG_PCI */ -#ifdef CONFIG_PM -EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); -EXPORT_SYMBOL_GPL(ata_scsi_device_resume); -#endif /* CONFIG_PM */ - EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_port_schedule_eh); EXPORT_SYMBOL_GPL(ata_port_abort); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8256655ce7d9..5309c312f517 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -77,29 +77,12 @@ static void ata_eh_finish(struct ata_port *ap); #ifdef CONFIG_PM static void ata_eh_handle_port_suspend(struct ata_port *ap); static void ata_eh_handle_port_resume(struct ata_port *ap); -static int ata_eh_suspend(struct ata_port *ap, - struct ata_device **r_failed_dev); -static void ata_eh_prep_resume(struct ata_port *ap); -static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev); #else /* CONFIG_PM */ static void ata_eh_handle_port_suspend(struct ata_port *ap) { } static void ata_eh_handle_port_resume(struct ata_port *ap) { } - -static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev) -{ - return 0; -} - -static void ata_eh_prep_resume(struct ata_port *ap) -{ } - -static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev) -{ - return 0; -} #endif /* CONFIG_PM */ static void ata_ering_record(struct ata_ering *ering, int is_io, @@ -568,6 +551,9 @@ void ata_port_schedule_eh(struct ata_port *ap) { WARN_ON(!ap->ops->error_handler); + if (ap->pflags & ATA_PFLAG_INITIALIZING) + return; + ap->pflags |= ATA_PFLAG_EH_PENDING; scsi_schedule_eh(ap->scsi_host); @@ -1791,7 +1777,7 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, if (ehc->i.flags & ATA_EHI_DID_RESET) readid_flags |= ATA_READID_POSTRESET; - if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { + if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) { if (ata_port_offline(ap)) { rc = -EIO; goto err; @@ -1872,166 +1858,6 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, return rc; } -#ifdef CONFIG_PM -/** - * ata_eh_suspend - handle suspend EH action - * @ap: target host port - * @r_failed_dev: result parameter to indicate failing device - * - * Handle suspend EH action. Disk devices are spinned down and - * other types of devices are just marked suspended. Once - * suspended, no EH action to the device is allowed until it is - * resumed. - * - * LOCKING: - * Kernel thread context (may sleep). - * - * RETURNS: - * 0 on success, -errno otherwise - */ -static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev) -{ - struct ata_device *dev; - int i, rc = 0; - - DPRINTK("ENTER\n"); - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - unsigned long flags; - unsigned int action, err_mask; - - dev = &ap->device[i]; - action = ata_eh_dev_action(dev); - - if (!ata_dev_enabled(dev) || !(action & ATA_EH_SUSPEND)) - continue; - - WARN_ON(dev->flags & ATA_DFLAG_SUSPENDED); - - ata_eh_about_to_do(ap, dev, ATA_EH_SUSPEND); - - if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) { - /* flush cache */ - rc = ata_flush_cache(dev); - if (rc) - break; - - /* spin down */ - err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1); - if (err_mask) { - ata_dev_printk(dev, KERN_ERR, "failed to " - "spin down (err_mask=0x%x)\n", - err_mask); - rc = -EIO; - break; - } - } - - spin_lock_irqsave(ap->lock, flags); - dev->flags |= ATA_DFLAG_SUSPENDED; - spin_unlock_irqrestore(ap->lock, flags); - - ata_eh_done(ap, dev, ATA_EH_SUSPEND); - } - - if (rc) - *r_failed_dev = dev; - - DPRINTK("EXIT\n"); - return rc; -} - -/** - * ata_eh_prep_resume - prep for resume EH action - * @ap: target host port - * - * Clear SUSPENDED in preparation for scheduled resume actions. - * This allows other parts of EH to access the devices being - * resumed. - * - * LOCKING: - * Kernel thread context (may sleep). - */ -static void ata_eh_prep_resume(struct ata_port *ap) -{ - struct ata_device *dev; - unsigned long flags; - int i; - - DPRINTK("ENTER\n"); - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - unsigned int action; - - dev = &ap->device[i]; - action = ata_eh_dev_action(dev); - - if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME)) - continue; - - spin_lock_irqsave(ap->lock, flags); - dev->flags &= ~ATA_DFLAG_SUSPENDED; - spin_unlock_irqrestore(ap->lock, flags); - } - - DPRINTK("EXIT\n"); -} - -/** - * ata_eh_resume - handle resume EH action - * @ap: target host port - * @r_failed_dev: result parameter to indicate failing device - * - * Handle resume EH action. Target devices are already reset and - * revalidated. Spinning up is the only operation left. - * - * LOCKING: - * Kernel thread context (may sleep). - * - * RETURNS: - * 0 on success, -errno otherwise - */ -static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev) -{ - struct ata_device *dev; - int i, rc = 0; - - DPRINTK("ENTER\n"); - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - unsigned int action, err_mask; - - dev = &ap->device[i]; - action = ata_eh_dev_action(dev); - - if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME)) - continue; - - ata_eh_about_to_do(ap, dev, ATA_EH_RESUME); - - if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) { - err_mask = ata_do_simple_cmd(dev, - ATA_CMD_IDLEIMMEDIATE); - if (err_mask) { - ata_dev_printk(dev, KERN_ERR, "failed to " - "spin up (err_mask=0x%x)\n", - err_mask); - rc = -EIO; - break; - } - } - - ata_eh_done(ap, dev, ATA_EH_RESUME); - } - - if (rc) - *r_failed_dev = dev; - - DPRINTK("EXIT\n"); - return 0; -} -#endif /* CONFIG_PM */ - static int ata_port_nr_enabled(struct ata_port *ap) { int i, cnt = 0; @@ -2057,17 +1883,6 @@ static int ata_eh_skip_recovery(struct ata_port *ap) struct ata_eh_context *ehc = &ap->eh_context; int i; - /* skip if all possible devices are suspended */ - for (i = 0; i < ata_port_max_devices(ap); i++) { - struct ata_device *dev = &ap->device[i]; - - if (!(dev->flags & ATA_DFLAG_SUSPENDED)) - break; - } - - if (i == ata_port_max_devices(ap)) - return 1; - /* thaw frozen port, resume link and recover failed devices */ if ((ap->pflags & ATA_PFLAG_FROZEN) || (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap)) @@ -2147,9 +1962,6 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, if (ap->pflags & ATA_PFLAG_UNLOADING) goto out; - /* prep for resume */ - ata_eh_prep_resume(ap); - /* skip EH if possible. */ if (ata_eh_skip_recovery(ap)) ehc->i.action = 0; @@ -2177,11 +1989,6 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, if (rc) goto dev_fail; - /* resume devices */ - rc = ata_eh_resume(ap, &dev); - if (rc) - goto dev_fail; - /* configure transfer mode if necessary */ if (ehc->i.flags & ATA_EHI_SETMODE) { rc = ata_set_mode(ap, &dev); @@ -2190,25 +1997,16 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ehc->i.flags &= ~ATA_EHI_SETMODE; } - /* suspend devices */ - rc = ata_eh_suspend(ap, &dev); - if (rc) - goto dev_fail; - goto out; dev_fail: ehc->tries[dev->devno]--; switch (rc) { - case -EINVAL: - /* eeek, something went very wrong, give up */ - ehc->tries[dev->devno] = 0; - break; - case -ENODEV: /* device missing or wrong IDENTIFY data, schedule probing */ ehc->i.probe_mask |= (1 << dev->devno); + case -EINVAL: /* give it just one more chance */ ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); case -EIO: @@ -2390,22 +2188,13 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) * * Resume @ap. * - * This function also waits upto one second until all devices - * hanging off this port requests resume EH action. This is to - * prevent invoking EH and thus reset multiple times on resume. - * - * On DPM resume, where some of devices might not be resumed - * together, this may delay port resume upto one second, but such - * DPM resumes are rare and 1 sec delay isn't too bad. - * * LOCKING: * Kernel thread context (may sleep). */ static void ata_eh_handle_port_resume(struct ata_port *ap) { - unsigned long timeout; unsigned long flags; - int i, rc = 0; + int rc = 0; /* are we resuming? */ spin_lock_irqsave(ap->lock, flags); @@ -2416,31 +2205,12 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) } spin_unlock_irqrestore(ap->lock, flags); - /* spurious? */ - if (!(ap->pflags & ATA_PFLAG_SUSPENDED)) - goto done; + WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED)); if (ap->ops->port_resume) rc = ap->ops->port_resume(ap); - /* give devices time to request EH */ - timeout = jiffies + HZ; /* 1s max */ - while (1) { - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - unsigned int action = ata_eh_dev_action(dev); - - if ((dev->flags & ATA_DFLAG_SUSPENDED) && - !(action & ATA_EH_RESUME)) - break; - } - - if (i == ATA_MAX_DEVICES || time_after(jiffies, timeout)) - break; - msleep(10); - } - - done: + /* report result */ spin_lock_irqsave(ap->lock, flags); ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED); if (ap->pm_result) { diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9afba2ba489e..dd81fa78cdcf 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -510,133 +510,6 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf) } } -#ifdef CONFIG_PM -/** - * ata_scsi_device_suspend - suspend ATA device associated with sdev - * @sdev: the SCSI device to suspend - * @mesg: target power management message - * - * Request suspend EH action on the ATA device associated with - * @sdev and wait for the operation to complete. - * - * LOCKING: - * Kernel thread context (may sleep). - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t mesg) -{ - struct ata_port *ap = ata_shost_to_port(sdev->host); - struct ata_device *dev = ata_scsi_find_dev(ap, sdev); - unsigned long flags; - unsigned int action; - int rc = 0; - - if (!dev) - goto out; - - spin_lock_irqsave(ap->lock, flags); - - /* wait for the previous resume to complete */ - while (dev->flags & ATA_DFLAG_SUSPENDED) { - spin_unlock_irqrestore(ap->lock, flags); - ata_port_wait_eh(ap); - spin_lock_irqsave(ap->lock, flags); - } - - /* if @sdev is already detached, nothing to do */ - if (sdev->sdev_state == SDEV_OFFLINE || - sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL) - goto out_unlock; - - /* request suspend */ - action = ATA_EH_SUSPEND; - if (mesg.event != PM_EVENT_SUSPEND) - action |= ATA_EH_PM_FREEZE; - ap->eh_info.dev_action[dev->devno] |= action; - ap->eh_info.flags |= ATA_EHI_QUIET; - ata_port_schedule_eh(ap); - - spin_unlock_irqrestore(ap->lock, flags); - - /* wait for EH to do the job */ - ata_port_wait_eh(ap); - - spin_lock_irqsave(ap->lock, flags); - - /* If @sdev is still attached but the associated ATA device - * isn't suspended, the operation failed. - */ - if (sdev->sdev_state != SDEV_OFFLINE && - sdev->sdev_state != SDEV_CANCEL && sdev->sdev_state != SDEV_DEL && - !(dev->flags & ATA_DFLAG_SUSPENDED)) - rc = -EIO; - - out_unlock: - spin_unlock_irqrestore(ap->lock, flags); - out: - if (rc == 0) - sdev->sdev_gendev.power.power_state = mesg; - return rc; -} - -/** - * ata_scsi_device_resume - resume ATA device associated with sdev - * @sdev: the SCSI device to resume - * - * Request resume EH action on the ATA device associated with - * @sdev and return immediately. This enables parallel - * wakeup/spinup of devices. - * - * LOCKING: - * Kernel thread context (may sleep). - * - * RETURNS: - * 0. - */ -int ata_scsi_device_resume(struct scsi_device *sdev) -{ - struct ata_port *ap = ata_shost_to_port(sdev->host); - struct ata_device *dev = ata_scsi_find_dev(ap, sdev); - struct ata_eh_info *ehi = &ap->eh_info; - unsigned long flags; - unsigned int action; - - if (!dev) - goto out; - - spin_lock_irqsave(ap->lock, flags); - - /* if @sdev is already detached, nothing to do */ - if (sdev->sdev_state == SDEV_OFFLINE || - sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL) - goto out_unlock; - - /* request resume */ - action = ATA_EH_RESUME; - if (sdev->sdev_gendev.power.power_state.event == PM_EVENT_SUSPEND) - __ata_ehi_hotplugged(ehi); - else - action |= ATA_EH_PM_FREEZE | ATA_EH_SOFTRESET; - ehi->dev_action[dev->devno] |= action; - - /* We don't want autopsy and verbose EH messages. Disable - * those if we're the only device on this link. - */ - if (ata_port_max_devices(ap) == 1) - ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; - - ata_port_schedule_eh(ap); - - out_unlock: - spin_unlock_irqrestore(ap->lock, flags); - out: - sdev->sdev_gendev.power.power_state = PMSG_ON; - return 0; -} -#endif /* CONFIG_PM */ - /** * ata_to_sense_error - convert ATA error to SCSI error * @id: ATA device number @@ -929,6 +802,8 @@ int ata_scsi_slave_config(struct scsi_device *sdev) blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); + sdev->manage_start_stop = 1; + if (dev) ata_scsi_dev_config(sdev, dev); @@ -1069,9 +944,35 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) } tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ - } else + } else { + /* XXX: This is for backward compatibility, will be + * removed. Read Documentation/feature-removal-schedule.txt + * for more info. + */ + if (ata_spindown_compat && + (system_state == SYSTEM_HALT || + system_state == SYSTEM_POWER_OFF)) { + static int warned = 0; + + if (!warned) { + spin_unlock_irq(qc->ap->lock); + ata_dev_printk(qc->dev, KERN_WARNING, + "DISK MIGHT NOT BE SPUN DOWN PROPERLY. " + "UPDATE SHUTDOWN UTILITY\n"); + ata_dev_printk(qc->dev, KERN_WARNING, + "For more info, visit " + "http://linux-ata.org/shutdown.html\n"); + warned = 1; + ssleep(5); + spin_lock_irq(qc->ap->lock); + } + scmd->result = SAM_STAT_GOOD; + return 1; + } + /* Issue ATA STANDBY IMMEDIATE command */ tf->command = ATA_CMD_STANDBYNOW1; + } /* * Standby and Idle condition timers could be implemented but that diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index d211db6b35a2..e35d13466c69 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -544,7 +544,7 @@ static int ata_resources_present(struct pci_dev *pdev, int port) * RETURNS: * 0 on success, -errno otherwise. */ -static int ata_pci_init_bmdma(struct ata_host *host) +int ata_pci_init_bmdma(struct ata_host *host) { struct device *gdev = host->dev; struct pci_dev *pdev = to_pci_dev(gdev); @@ -566,7 +566,7 @@ static int ata_pci_init_bmdma(struct ata_host *host) } host->iomap = pcim_iomap_table(pdev); - for (i = 0; i < host->n_ports; i++) { + for (i = 0; i < 2; i++) { struct ata_port *ap = host->ports[i]; void __iomem *bmdma = host->iomap[4] + 8 * i; @@ -585,54 +585,52 @@ static int ata_pci_init_bmdma(struct ata_host *host) /** * ata_pci_init_native_host - acquire native ATA resources and init host * @host: target ATA host - * @port_mask: ports to consider * - * Acquire native PCI ATA resources for @host and initialize - * @host accordoingly. + * Acquire native PCI ATA resources for @host and initialize the + * first two ports of @host accordingly. Ports marked dummy are + * skipped and allocation failure makes the port dummy. * * LOCKING: * Inherited from calling layer (may sleep). * * RETURNS: - * 0 on success, -errno otherwise. + * 0 if at least one port is initialized, -ENODEV if no port is + * available. */ -int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) +int ata_pci_init_native_host(struct ata_host *host) { struct device *gdev = host->dev; struct pci_dev *pdev = to_pci_dev(gdev); + unsigned int mask = 0; int i, rc; - /* Discard disabled ports. Some controllers show their unused - * channels this way. Disabled ports are made dummy. - */ - for (i = 0; i < 2; i++) { - if ((port_mask & (1 << i)) && !ata_resources_present(pdev, i)) { - host->ports[i]->ops = &ata_dummy_port_ops; - port_mask &= ~(1 << i); - } - } - - if (!port_mask) { - dev_printk(KERN_ERR, gdev, "no available port\n"); - return -ENODEV; - } - /* request, iomap BARs and init port addresses accordingly */ for (i = 0; i < 2; i++) { struct ata_port *ap = host->ports[i]; int base = i * 2; void __iomem * const *iomap; - if (!(port_mask & (1 << i))) + if (ata_port_is_dummy(ap)) + continue; + + /* Discard disabled ports. Some controllers show + * their unused channels this way. Disabled ports are + * made dummy. + */ + if (!ata_resources_present(pdev, i)) { + ap->ops = &ata_dummy_port_ops; continue; + } rc = pcim_iomap_regions(pdev, 0x3 << base, DRV_NAME); if (rc) { - dev_printk(KERN_ERR, gdev, "failed to request/iomap " - "BARs for port %d (errno=%d)\n", i, rc); + dev_printk(KERN_WARNING, gdev, + "failed to request/iomap BARs for port %d " + "(errno=%d)\n", i, rc); if (rc == -EBUSY) pcim_pin_device(pdev); - return rc; + ap->ops = &ata_dummy_port_ops; + continue; } host->iomap = iomap = pcim_iomap_table(pdev); @@ -641,6 +639,13 @@ int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) ap->ioaddr.ctl_addr = (void __iomem *) ((unsigned long)iomap[base + 1] | ATA_PCI_CTL_OFS); ata_std_ports(&ap->ioaddr); + + mask |= 1 << i; + } + + if (!mask) { + dev_printk(KERN_ERR, gdev, "no available native port\n"); + return -ENODEV; } return 0; @@ -649,8 +654,7 @@ int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) /** * ata_pci_prepare_native_host - helper to prepare native PCI ATA host * @pdev: target PCI device - * @ppi: array of port_info - * @n_ports: number of ports to allocate + * @ppi: array of port_info, must be enough for two ports * @r_host: out argument for the initialized ATA host * * Helper to allocate ATA host for @pdev, acquire all native PCI @@ -664,10 +668,9 @@ int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) */ int ata_pci_prepare_native_host(struct pci_dev *pdev, const struct ata_port_info * const * ppi, - int n_ports, struct ata_host **r_host) + struct ata_host **r_host) { struct ata_host *host; - unsigned int port_mask; int rc; if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) @@ -681,11 +684,7 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev, goto err_out; } - port_mask = ATA_PORT_PRIMARY; - if (n_ports > 1) - port_mask |= ATA_PORT_SECONDARY; - - rc = ata_pci_init_native_host(host, port_mask); + rc = ata_pci_init_native_host(host); if (rc) goto err_out; @@ -777,8 +776,11 @@ static int ata_init_legacy_port(struct ata_port *ap, /* iomap cmd and ctl ports */ legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8); legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1); - if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) + if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) { + dev_printk(KERN_WARNING, host->dev, + "failed to map cmd/ctl ports\n"); return -ENOMEM; + } /* init IO addresses */ ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no]; @@ -792,19 +794,20 @@ static int ata_init_legacy_port(struct ata_port *ap, /** * ata_init_legacy_host - acquire legacy ATA resources and init ATA host * @host: target ATA host - * @legacy_mask: out parameter, mask indicating ports is in legacy mode * @was_busy: out parameter, indicates whether any port was busy * - * Acquire legacy ATA resources for ports. + * Acquire legacy ATA resources for the first two ports of @host + * and initialize it accordingly. Ports marked dummy are skipped + * and resource acquistion failure makes the port dummy. * * LOCKING: * Inherited from calling layer (may sleep). * * RETURNS: - * 0 on success, -errno otherwise. + * 0 if at least one port is initialized, -ENODEV if no port is + * available. */ -static int ata_init_legacy_host(struct ata_host *host, - unsigned int *legacy_mask, int *was_busy) +static int ata_init_legacy_host(struct ata_host *host, int *was_busy) { struct device *gdev = host->dev; struct ata_legacy_devres *legacy_dr; @@ -821,22 +824,23 @@ static int ata_init_legacy_host(struct ata_host *host, devres_add(gdev, legacy_dr); for (i = 0; i < 2; i++) { - *legacy_mask &= ~(1 << i); + if (ata_port_is_dummy(host->ports[i])) + continue; + rc = ata_init_legacy_port(host->ports[i], legacy_dr); if (rc == 0) legacy_dr->mask |= 1 << i; - else if (rc == -EBUSY) - (*was_busy)++; - } - - if (!legacy_dr->mask) - return -EBUSY; - - for (i = 0; i < 2; i++) - if (!(legacy_dr->mask & (1 << i))) + else { + if (rc == -EBUSY) + (*was_busy)++; host->ports[i]->ops = &ata_dummy_port_ops; + } + } - *legacy_mask |= legacy_dr->mask; + if (!legacy_dr->mask) { + dev_printk(KERN_ERR, gdev, "no available legacy port\n"); + return -ENODEV; + } devres_remove_group(gdev, NULL); return 0; @@ -875,7 +879,7 @@ static int ata_request_legacy_irqs(struct ata_host *host, legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL); BUG_ON(!legacy_dr); - for (i = 0; i < host->n_ports; i++) { + for (i = 0; i < 2; i++) { unsigned int irq; /* FIXME: ATA_*_IRQ() should take generic device not pci_dev */ @@ -923,8 +927,7 @@ static int ata_request_legacy_irqs(struct ata_host *host, /** * ata_pci_init_one - Initialize/register PCI IDE host controller * @pdev: Controller to be initialized - * @port_info: Information from low-level host driver - * @n_ports: Number of ports attached to host controller + * @ppi: array of port_info, must be enough for two ports * * This is a helper function which can be called from a driver's * xxx_init_one() probe function if the hardware uses traditional @@ -944,26 +947,34 @@ static int ata_request_legacy_irqs(struct ata_host *host, * RETURNS: * Zero on success, negative on errno-based value on error. */ - -int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, - unsigned int n_ports) +int ata_pci_init_one(struct pci_dev *pdev, + const struct ata_port_info * const * ppi) { struct device *dev = &pdev->dev; + const struct ata_port_info *pi = NULL; struct ata_host *host = NULL; - const struct ata_port_info *port[2]; u8 mask; - unsigned int legacy_mode = 0; - int rc; + int legacy_mode = 0; + int i, rc; DPRINTK("ENTER\n"); - if (!devres_open_group(dev, NULL, GFP_KERNEL)) - return -ENOMEM; + /* look up the first valid port_info */ + for (i = 0; i < 2 && ppi[i]; i++) { + if (ppi[i]->port_ops != &ata_dummy_port_ops) { + pi = ppi[i]; + break; + } + } - BUG_ON(n_ports < 1 || n_ports > 2); + if (!pi) { + dev_printk(KERN_ERR, &pdev->dev, + "no valid port_info specified\n"); + return -EINVAL; + } - port[0] = port_info[0]; - port[1] = (n_ports > 1) ? port_info[1] : NULL; + if (!devres_open_group(dev, NULL, GFP_KERNEL)) + return -ENOMEM; /* FIXME: Really for ATA it isn't safe because the device may be multi-purpose and we want to leave it alone if it was already @@ -984,7 +995,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); mask = (1 << 2) | (1 << 0); if ((tmp8 & mask) != mask) - legacy_mode = (1 << 3); + legacy_mode = 1; #if defined(CONFIG_NO_ATA_LEGACY) /* Some platforms with PCI limits cannot address compat port space. In that case we punt if their firmware has @@ -998,7 +1009,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, } /* alloc and init host */ - host = ata_host_alloc_pinfo(dev, port, n_ports); + host = ata_host_alloc_pinfo(dev, ppi, 2); if (!host) { dev_printk(KERN_ERR, &pdev->dev, "failed to allocate ATA host\n"); @@ -1007,19 +1018,13 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, } if (!legacy_mode) { - unsigned int port_mask; - - port_mask = ATA_PORT_PRIMARY; - if (n_ports > 1) - port_mask |= ATA_PORT_SECONDARY; - - rc = ata_pci_init_native_host(host, port_mask); + rc = ata_pci_init_native_host(host); if (rc) goto err_out; } else { int was_busy = 0; - rc = ata_init_legacy_host(host, &legacy_mode, &was_busy); + rc = ata_init_legacy_host(host, &was_busy); if (was_busy) pcim_pin_device(pdev); if (rc) @@ -1040,8 +1045,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, goto err_out; if (!legacy_mode) - rc = devm_request_irq(dev, pdev->irq, - port_info[0]->port_ops->irq_handler, + rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler, IRQF_SHARED, DRV_NAME, host); else { irq_handler_t handler[2] = { host->ops->irq_handler, @@ -1055,7 +1059,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, goto err_out; /* register */ - rc = ata_host_register(host, port_info[0]->sht); + rc = ata_host_register(host, pi->sht); if (rc) goto err_out; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 5f4d40cd3288..8b71b73a199c 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -58,6 +58,7 @@ extern int atapi_enabled; extern int atapi_dmadir; extern int libata_fua; extern int libata_noacpi; +extern int ata_spindown_compat; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, @@ -96,15 +97,15 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern struct ata_port *ata_port_alloc(struct ata_host *host); /* libata-acpi.c */ -#ifdef CONFIG_SATA_ACPI +#ifdef CONFIG_ATA_ACPI extern int ata_acpi_exec_tfs(struct ata_port *ap); -extern int ata_acpi_push_id(struct ata_port *ap, unsigned int ix); +extern int ata_acpi_push_id(struct ata_device *dev); #else static inline int ata_acpi_exec_tfs(struct ata_port *ap) { return 0; } -static inline int ata_acpi_push_id(struct ata_port *ap, unsigned int ix) +static inline int ata_acpi_push_id(struct ata_device *dev) { return 0; } diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index d40edebb510a..3c55a5ff74c7 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -291,10 +291,6 @@ static struct scsi_host_template ali_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; /* @@ -522,14 +518,14 @@ static void ali_init_chipset(struct pci_dev *pdev) static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - static struct ata_port_info info_early = { + static const struct ata_port_info info_early = { .sht = &ali_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &ali_early_port_ops }; /* Revision 0x20 added DMA */ - static struct ata_port_info info_20 = { + static const struct ata_port_info info_20 = { .sht = &ali_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, @@ -537,7 +533,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &ali_20_port_ops }; /* Revision 0x20 with support logic added UDMA */ - static struct ata_port_info info_20_udma = { + static const struct ata_port_info info_20_udma = { .sht = &ali_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, @@ -546,7 +542,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &ali_20_port_ops }; /* Revision 0xC2 adds UDMA66 */ - static struct ata_port_info info_c2 = { + static const struct ata_port_info info_c2 = { .sht = &ali_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, @@ -555,7 +551,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &ali_c2_port_ops }; /* Revision 0xC3 is UDMA100 */ - static struct ata_port_info info_c3 = { + static const struct ata_port_info info_c3 = { .sht = &ali_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, @@ -564,7 +560,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &ali_c2_port_ops }; /* Revision 0xC4 is UDMA133 */ - static struct ata_port_info info_c4 = { + static const struct ata_port_info info_c4 = { .sht = &ali_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, @@ -573,7 +569,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &ali_c2_port_ops }; /* Revision 0xC5 is UDMA133 with LBA48 DMA */ - static struct ata_port_info info_c5 = { + static const struct ata_port_info info_c5 = { .sht = &ali_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -582,7 +578,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &ali_c5_port_ops }; - static struct ata_port_info *port_info[2]; + const struct ata_port_info *ppi[] = { NULL, NULL }; u8 rev, tmp; struct pci_dev *isa_bridge; @@ -594,17 +590,17 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) */ if (rev < 0x20) { - port_info[0] = port_info[1] = &info_early; + ppi[0] = &info_early; } else if (rev < 0xC2) { - port_info[0] = port_info[1] = &info_20; + ppi[0] = &info_20; } else if (rev == 0xC2) { - port_info[0] = port_info[1] = &info_c2; + ppi[0] = &info_c2; } else if (rev == 0xC3) { - port_info[0] = port_info[1] = &info_c3; + ppi[0] = &info_c3; } else if (rev == 0xC4) { - port_info[0] = port_info[1] = &info_c4; + ppi[0] = &info_c4; } else - port_info[0] = port_info[1] = &info_c5; + ppi[0] = &info_c5; ali_init_chipset(pdev); @@ -613,10 +609,10 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) /* Are we paired with a UDMA capable chip */ pci_read_config_byte(isa_bridge, 0x5E, &tmp); if ((tmp & 0x1E) == 0x12) - port_info[0] = port_info[1] = &info_20_udma; + ppi[0] = &info_20_udma; pci_dev_put(isa_bridge); } - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 67c7e87dec04..b439351f1fd3 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -324,10 +324,6 @@ static struct scsi_host_template amd_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations amd33_port_ops = { @@ -542,7 +538,7 @@ static struct ata_port_operations nv133_port_ops = { static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - static struct ata_port_info info[10] = { + static const struct ata_port_info info[10] = { { /* 0: AMD 7401 */ .sht = &amd_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, @@ -624,7 +620,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &amd100_port_ops } }; - static struct ata_port_info *port_info[2]; + const struct ata_port_info *ppi[] = { NULL, NULL }; static int printed_version; int type = id->driver_data; u8 rev; @@ -656,9 +652,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) ata_pci_clear_simplex(pdev); /* And fire it up */ - - port_info[0] = port_info[1] = &info[type]; - return ata_pci_init_one(pdev, port_info, 2); + ppi[0] = &info[type]; + return ata_pci_init_one(pdev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index ef51940c3adb..9861059dd673 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -414,7 +414,7 @@ static const struct ata_port_operations artop6260_ops = { static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) { static int printed_version; - static struct ata_port_info info_6210 = { + static const struct ata_port_info info_6210 = { .sht = &artop_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ @@ -422,7 +422,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) .udma_mask = ATA_UDMA2, .port_ops = &artop6210_ops, }; - static struct ata_port_info info_626x = { + static const struct ata_port_info info_626x = { .sht = &artop_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ @@ -430,7 +430,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) .udma_mask = ATA_UDMA4, .port_ops = &artop6260_ops, }; - static struct ata_port_info info_626x_fast = { + static const struct ata_port_info info_626x_fast = { .sht = &artop_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ @@ -438,32 +438,30 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) .udma_mask = ATA_UDMA5, .port_ops = &artop6260_ops, }; - struct ata_port_info *port_info[2]; - struct ata_port_info *info = NULL; - int ports = 2; + const struct ata_port_info *ppi[] = { NULL, NULL }; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); if (id->driver_data == 0) { /* 6210 variant */ - info = &info_6210; + ppi[0] = &info_6210; + ppi[1] = &ata_dummy_port_info; /* BIOS may have left us in UDMA, clear it before libata probe */ pci_write_config_byte(pdev, 0x54, 0); /* For the moment (also lacks dsc) */ printk(KERN_WARNING "ARTOP 6210 requires serialize functionality not yet supported by libata.\n"); printk(KERN_WARNING "Secondary ATA ports will not be activated.\n"); - ports = 1; } else if (id->driver_data == 1) /* 6260 */ - info = &info_626x; + ppi[0] = &info_626x; else if (id->driver_data == 2) { /* 6260 or 6260 + fast */ unsigned long io = pci_resource_start(pdev, 4); u8 reg; - info = &info_626x; + ppi[0] = &info_626x; if (inb(io) & 0x10) - info = &info_626x_fast; + ppi[0] = &info_626x_fast; /* Mac systems come up with some registers not set as we will need them */ @@ -484,10 +482,9 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) } - BUG_ON(info == NULL); + BUG_ON(ppi[0] == NULL); - port_info[0] = port_info[1] = info; - return ata_pci_init_one(pdev, port_info, ports); + return ata_pci_init_one(pdev, ppi); } static const struct pci_device_id artop_pci_tbl[] = { diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 21515381b5b3..844914681a2a 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -229,10 +229,6 @@ static struct scsi_host_template atiixp_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations atiixp_port_ops = { @@ -272,7 +268,7 @@ static struct ata_port_operations atiixp_port_ops = { static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &atiixp_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -280,8 +276,8 @@ static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id) .udma_mask = 0x3F, .port_ops = &atiixp_port_ops }; - static struct ata_port_info *port_info[2] = { &info, &info }; - return ata_pci_init_one(dev, port_info, 2); + const struct ata_port_info *ppi[] = { &info, NULL }; + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id atiixp[] = { diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c index 2105985a8013..ed00fa9d53be 100644 --- a/drivers/ata/pata_cmd640.c +++ b/drivers/ata/pata_cmd640.c @@ -181,10 +181,6 @@ static struct scsi_host_template cmd640_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations cmd640_port_ops = { @@ -253,17 +249,16 @@ static void cmd640_hardware_init(struct pci_dev *pdev) static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &cmd640_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &cmd640_port_ops }; - - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; cmd640_hardware_init(pdev); - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } static int cmd640_reinit_one(struct pci_dev *pdev) diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 3989cc577fcd..2a79b335cfcc 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -266,10 +266,6 @@ static struct scsi_host_template cmd64x_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations cmd64x_port_ops = { @@ -381,7 +377,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { u32 class_rev; - static struct ata_port_info cmd_info[6] = { + static const struct ata_port_info cmd_info[6] = { { /* CMD 643 - no UDMA */ .sht = &cmd64x_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, @@ -428,11 +424,9 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &cmd648_port_ops } }; - static struct ata_port_info *port_info[2], *info; + const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL }; u8 mrdmode; - info = &cmd_info[id->driver_data]; - pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xFF; @@ -442,10 +436,10 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (pdev->device == PCI_DEVICE_ID_CMD_646) { /* Does UDMA work ? */ if (class_rev > 4) - info = &cmd_info[2]; + ppi[0] = &cmd_info[2]; /* Early rev with other problems ? */ else if (class_rev == 1) - info = &cmd_info[3]; + ppi[0] = &cmd_info[3]; } pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); @@ -461,8 +455,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) pci_write_config_byte(pdev, UDIDETCR0, 0xF0); #endif - port_info[0] = port_info[1] = info; - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 79bef0d1fad3..83bcc5b32597 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -155,10 +155,6 @@ static struct scsi_host_template cs5520_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations cs5520_port_ops = { diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index 29642d5ee189..1b67923d7a4e 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -176,10 +176,6 @@ static struct scsi_host_template cs5530_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations cs5530_port_ops = { @@ -339,7 +335,7 @@ fail_put: static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &cs5530_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -348,23 +344,23 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &cs5530_port_ops }; /* The docking connector doesn't do UDMA, and it seems not MWDMA */ - static struct ata_port_info info_palmax_secondary = { + static const struct ata_port_info info_palmax_secondary = { .sht = &cs5530_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &cs5530_port_ops }; - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; /* Chip initialisation */ if (cs5530_init_chip()) return -ENODEV; if (cs5530_is_palmax()) - port_info[1] = &info_palmax_secondary; + ppi[1] = &info_palmax_secondary; /* Now kick off ATA set up */ - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 22006ae71941..f37d4cd812a1 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -173,10 +173,6 @@ static struct scsi_host_template cs5535_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations cs5535_port_ops = { @@ -227,7 +223,7 @@ static struct ata_port_operations cs5535_port_ops = { static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &cs5535_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -235,7 +231,7 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id) .udma_mask = 0x1f, .port_ops = &cs5535_port_ops }; - struct ata_port_info *ports[1] = { &info }; + const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; u32 timings, dummy; @@ -247,7 +243,7 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id) rdmsr(ATAC_CH0D1_PIO, timings, dummy); if (CS5535_BAD_PIO(timings)) wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0); - return ata_pci_init_one(dev, ports, 1); + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id cs5535[] = { diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c index 6ec049c3b1dc..27b9f29c01e3 100644 --- a/drivers/ata/pata_cypress.c +++ b/drivers/ata/pata_cypress.c @@ -125,10 +125,6 @@ static struct scsi_host_template cy82c693_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations cy82c693_port_ops = { @@ -169,14 +165,14 @@ static struct ata_port_operations cy82c693_port_ops = { static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &cy82c693_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &cy82c693_port_ops }; - static struct ata_port_info *port_info[1] = { &info }; + const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; /* Devfn 1 is the ATA primary. The secondary is magic and on devfn2. For the moment we don't handle the secondary. FIXME */ @@ -184,7 +180,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i if (PCI_FUNC(pdev->devfn) != 1) return -ENODEV; - return ata_pci_init_one(pdev, port_info, 1); + return ata_pci_init_one(pdev, ppi); } static const struct pci_device_id cy82c693[] = { diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index d0f52e034906..079248a9b460 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -247,10 +247,6 @@ static struct scsi_host_template efar_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static const struct ata_port_operations efar_ops = { @@ -305,7 +301,7 @@ static const struct ata_port_operations efar_ops = { static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &efar_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ @@ -313,13 +309,13 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) .udma_mask = 0x0f, /* UDMA 66 */ .port_ops = &efar_ops, }; - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } static const struct pci_device_id efar_pci_tbl[] = { diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index e64e05e5c7fe..c6c8a8bb06d0 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -331,10 +331,6 @@ static struct scsi_host_template hpt36x_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; /* @@ -421,7 +417,7 @@ static void hpt36x_init_chipset(struct pci_dev *dev) static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info_hpt366 = { + static const struct ata_port_info info_hpt366 = { .sht = &hpt36x_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -429,7 +425,8 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .udma_mask = 0x1f, .port_ops = &hpt366_port_ops }; - struct ata_port_info *port_info[2] = {&info_hpt366, &info_hpt366}; + struct ata_port_info info = info_hpt366; + const struct ata_port_info *ppi[] = { &info, NULL }; u32 class_rev; u32 reg1; @@ -450,17 +447,17 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* info_hpt366 is safe against re-entry so we can scribble on it */ switch((reg1 & 0x700) >> 8) { case 5: - info_hpt366.private_data = &hpt366_40; + info.private_data = &hpt366_40; break; case 9: - info_hpt366.private_data = &hpt366_25; + info.private_data = &hpt366_25; break; default: - info_hpt366.private_data = &hpt366_33; + info.private_data = &hpt366_33; break; } /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_init_one(dev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 1614e8c822a4..5a0a410654e2 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -887,7 +887,7 @@ static int hpt37x_calibrate_dpll(struct pci_dev *dev) static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { /* HPT370 - UDMA100 */ - static struct ata_port_info info_hpt370 = { + static const struct ata_port_info info_hpt370 = { .sht = &hpt37x_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -896,7 +896,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ - static struct ata_port_info info_hpt370a = { + static const struct ata_port_info info_hpt370a = { .sht = &hpt37x_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -905,7 +905,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &hpt370a_port_ops }; /* HPT370 - UDMA100 */ - static struct ata_port_info info_hpt370_33 = { + static const struct ata_port_info info_hpt370_33 = { .sht = &hpt37x_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -914,7 +914,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ - static struct ata_port_info info_hpt370a_33 = { + static const struct ata_port_info info_hpt370a_33 = { .sht = &hpt37x_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -923,7 +923,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &hpt370a_port_ops }; /* HPT371, 372 and friends - UDMA133 */ - static struct ata_port_info info_hpt372 = { + static const struct ata_port_info info_hpt372 = { .sht = &hpt37x_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -932,7 +932,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &hpt372_port_ops }; /* HPT371, 372 and friends - UDMA100 at 50MHz clock */ - static struct ata_port_info info_hpt372_50 = { + static const struct ata_port_info info_hpt372_50 = { .sht = &hpt37x_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -941,7 +941,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &hpt372_port_ops }; /* HPT374 - UDMA133 */ - static struct ata_port_info info_hpt374 = { + static const struct ata_port_info info_hpt374 = { .sht = &hpt37x_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -951,9 +951,10 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) }; static const int MHz[4] = { 33, 40, 50, 66 }; - - struct ata_port_info *port_info[2]; - struct ata_port_info *port; + const struct ata_port_info *port; + void *private_data = NULL; + struct ata_port_info port_info; + const struct ata_port_info *ppi[] = { &port_info, NULL }; u8 irqmask; u32 class_rev; @@ -1124,13 +1125,13 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) return -ENODEV; } if (clock_slot == 3) - port->private_data = (void *)hpt37x_timings_66; + private_data = (void *)hpt37x_timings_66; else - port->private_data = (void *)hpt37x_timings_50; + private_data = (void *)hpt37x_timings_50; printk(KERN_INFO "hpt37x: Bus clock %dMHz, using DPLL.\n", MHz[clock_slot]); } else { - port->private_data = (void *)chip_table->clocks[clock_slot]; + private_data = (void *)chip_table->clocks[clock_slot]; /* * Perform a final fixup. Note that we will have used the * DPLL on the HPT372 which means we don't have to worry @@ -1144,9 +1145,11 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) printk(KERN_INFO "hpt37x: %s: Bus clock %dMHz.\n", chip_table->name, MHz[clock_slot]); } - port_info[0] = port_info[1] = port; /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); + port_info = *port; + port_info.private_data = private_data; + + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id hpt37x[] = { diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index ea1037d67860..f25154aed75d 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -488,7 +488,7 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev) static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) { /* HPT372N and friends - UDMA133 */ - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &hpt3x2n_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -496,8 +496,8 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) .udma_mask = 0x7f, .port_ops = &hpt3x2n_port_ops }; - struct ata_port_info *port_info[2]; - struct ata_port_info *port = &info; + struct ata_port_info port = info; + const struct ata_port_info *ppi[] = { &port, NULL }; u8 irqmask; u32 class_rev; @@ -585,9 +585,9 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* Set our private data up. We only need a few flags so we use it directly */ - port->private_data = NULL; + port.private_data = NULL; if (pci_mhz > 60) { - port->private_data = (void *)PCI66; + port.private_data = (void *)PCI66; /* * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in * the MISC. register to stretch the UltraDMA Tss timing. @@ -598,8 +598,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) } /* Now kick off ATA set up */ - port_info[0] = port_info[1] = port; - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id hpt3x2n[] = { diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index ac28ec8c50aa..bbabe7902fbb 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -100,10 +100,6 @@ static struct scsi_host_template hpt3x3_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations hpt3x3_port_ops = { @@ -175,7 +171,7 @@ static void hpt3x3_init_chipset(struct pci_dev *dev) static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &hpt3x3_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -183,11 +179,11 @@ static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) .udma_mask = 0x07, .port_ops = &hpt3x3_port_ops }; - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; hpt3x3_init_chipset(dev); /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_init_one(dev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c index 17bf9f3ed013..a769952646e1 100644 --- a/drivers/ata/pata_it8213.c +++ b/drivers/ata/pata_it8213.c @@ -257,10 +257,6 @@ static struct scsi_host_template it8213_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static const struct ata_port_operations it8213_ops = { @@ -315,7 +311,7 @@ static const struct ata_port_operations it8213_ops = { static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &it8213_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ @@ -323,14 +319,14 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en .udma_mask = 0x1f, /* UDMA 100 */ .port_ops = &it8213_ops, }; - static struct ata_port_info *port_info[2] = { &info, &info }; + /* Current IT8213 stuff is single port */ + const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - /* Current IT8213 stuff is single port */ - return ata_pci_init_one(pdev, port_info, 1); + return ata_pci_init_one(pdev, ppi); } static const struct pci_device_id it8213_pci_tbl[] = { diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index f1f8cec8c224..ff9a6fd36657 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -620,10 +620,6 @@ static struct scsi_host_template it821x_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations it821x_smart_port_ops = { @@ -722,14 +718,14 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { u8 conf; - static struct ata_port_info info_smart = { + static const struct ata_port_info info_smart = { .sht = &it821x_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &it821x_smart_port_ops }; - static struct ata_port_info info_passthru = { + static const struct ata_port_info info_passthru = { .sht = &it821x_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -737,8 +733,8 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .udma_mask = 0x7f, .port_ops = &it821x_passthru_port_ops }; - static struct ata_port_info *port_info[2]; + const struct ata_port_info *ppi[] = { NULL, NULL }; static char *mode[2] = { "pass through", "smart" }; /* Force the card into bypass mode if so requested */ @@ -751,11 +747,11 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) printk(KERN_INFO DRV_NAME ": controller in %s mode.\n", mode[conf]); if (conf == 0) - port_info[0] = port_info[1] = &info_passthru; + ppi[0] = &info_passthru; else - port_info[0] = port_info[1] = &info_smart; + ppi[0] = &info_smart; - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 420c343e5711..b994351fbcd0 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -31,7 +31,7 @@ static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error) for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (ata_dev_ready(dev)) { + if (ata_dev_enabled(dev)) { ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); dev->pio_mode = XFER_PIO_0; dev->xfer_mode = XFER_PIO_0; diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 1daf78ac6efb..8d799e87f752 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -138,10 +138,6 @@ static struct scsi_host_template jmicron_sht = { .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const struct ata_port_operations jmicron_ops = { @@ -195,7 +191,7 @@ static const struct ata_port_operations jmicron_ops = { static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &jmicron_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, @@ -205,9 +201,9 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i .port_ops = &jmicron_ops, }; - struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } static const struct pci_device_id jmicron_pci_tbl[] = { diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 837b7fe77dc7..edbfe0dbbf78 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -107,10 +107,6 @@ static struct scsi_host_template marvell_sht = { .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static const struct ata_port_operations marvell_ops = { @@ -165,7 +161,7 @@ static const struct ata_port_operations marvell_ops = { static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &marvell_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, @@ -175,7 +171,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i .port_ops = &marvell_ops, }; - static struct ata_port_info info_sata = { + static const struct ata_port_info info_sata = { .sht = &marvell_sht, /* Slave possible as its magically mapped not real */ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, @@ -186,13 +182,12 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i .port_ops = &marvell_ops, }; - struct ata_port_info *port_info[2] = { &info, &info_sata }; - int n_port = 2; + const struct ata_port_info *ppi[] = { &info, &info_sata }; if (pdev->device == 0x6101) - n_port = 1; + ppi[1] = &ata_dummy_port_info; - return ata_pci_init_one(pdev, port_info, n_port); + return ata_pci_init_one(pdev, ppi); } static const struct pci_device_id marvell_pci_tbl[] = { diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 9587a89f9683..368fac7d168b 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -280,10 +280,6 @@ static struct scsi_host_template mpc52xx_ata_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static struct ata_port_operations mpc52xx_ata_port_ops = { diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index 3bfbd495f643..4ea42838297e 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c @@ -165,10 +165,6 @@ static struct scsi_host_template mpiix_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations mpiix_port_ops = { diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index dbba5b77d79c..81f563458666 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c @@ -37,10 +37,6 @@ static struct scsi_host_template netcell_sht = { .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static const struct ata_port_operations netcell_ops = { @@ -96,7 +92,7 @@ static const struct ata_port_operations netcell_ops = { static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &netcell_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, /* Actually we don't really care about these as the @@ -106,7 +102,7 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e .udma_mask = 0x3f, /* UDMA 133 */ .port_ops = &netcell_ops, }; - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *port_info[] = { &info, NULL }; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, @@ -116,7 +112,7 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e ata_pci_clear_simplex(pdev); /* And let the library code do the work */ - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, port_info); } static const struct pci_device_id netcell_pci_tbl[] = { diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c index ebc58a907d26..ea70ec744879 100644 --- a/drivers/ata/pata_ns87410.c +++ b/drivers/ata/pata_ns87410.c @@ -158,10 +158,6 @@ static struct scsi_host_template ns87410_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations ns87410_port_ops = { @@ -195,14 +191,14 @@ static struct ata_port_operations ns87410_port_ops = { static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &ns87410_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x0F, .port_ops = &ns87410_port_ops }; - static struct ata_port_info *port_info[2] = {&info, &info}; - return ata_pci_init_one(dev, port_info, 2); + const struct ata_port_info *ppi[] = { &info, NULL }; + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id ns87410[] = { diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index 4d75d32e5826..29c23ddd6550 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -234,10 +234,6 @@ static struct scsi_host_template oldpiix_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static const struct ata_port_operations oldpiix_pata_ops = { @@ -293,20 +289,20 @@ static const struct ata_port_operations oldpiix_pata_ops = { static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &oldpiix_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma1-2 */ .port_ops = &oldpiix_pata_ops, }; - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } static const struct pci_device_id oldpiix_pci_tbl[] = { diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c index 0af8a2c77cc9..1c44653e1e06 100644 --- a/drivers/ata/pata_opti.c +++ b/drivers/ata/pata_opti.c @@ -179,10 +179,6 @@ static struct scsi_host_template opti_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations opti_port_ops = { @@ -220,19 +216,19 @@ static struct ata_port_operations opti_port_ops = { static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &opti_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &opti_port_ops }; - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; static int printed_version; if (!printed_version++) dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id opti[] = { diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 2843e480f216..3093b02286ce 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -363,10 +363,6 @@ static struct scsi_host_template optidma_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations optidma_port_ops = { @@ -486,14 +482,14 @@ done_nomsg: /* Wrong chip revision */ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info_82c700 = { + static const struct ata_port_info info_82c700 = { .sht = &optidma_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &optidma_port_ops }; - static struct ata_port_info info_82c700_udma = { + static const struct ata_port_info info_82c700_udma = { .sht = &optidma_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -501,8 +497,7 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id) .udma_mask = 0x07, .port_ops = &optiplus_port_ops }; - static struct ata_port_info *port_info[2]; - struct ata_port_info *info = &info_82c700; + const struct ata_port_info *ppi[] = { &info_82c700, NULL }; static int printed_version; if (!printed_version++) @@ -514,10 +509,9 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id) pci_clock = inb(0x1F5) & 1; /* 0 = 33Mhz, 1 = 25Mhz */ if (optiplus_with_udma(dev)) - info = &info_82c700_udma; + ppi[0] = &info_82c700_udma; - port_info[0] = port_info[1] = info; - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id optidma[] = { diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 11245e331f77..4d44c7555db1 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -397,6 +397,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), + PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index ee636beb05e1..edbaf9d653b8 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -244,10 +244,6 @@ static struct scsi_host_template pdc202xx_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations pdc2024x_port_ops = { @@ -321,7 +317,7 @@ static struct ata_port_operations pdc2026x_port_ops = { static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info[3] = { + static const struct ata_port_info info[3] = { { .sht = &pdc202xx_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, @@ -348,9 +344,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id } }; - static struct ata_port_info *port_info[2]; - - port_info[0] = port_info[1] = &info[id->driver_data]; + const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL }; if (dev->device == PCI_DEVICE_ID_PROMISE_20265) { struct pci_dev *bridge = dev->bus->self; @@ -362,7 +356,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id return -ENODEV; } } - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id pdc202xx[] = { diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index a0a650c7f272..1f6384895a4f 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -48,6 +48,8 @@ static int pata_platform_set_mode(struct ata_port *ap, struct ata_device **unuse return 0; } +static int ata_dummy_ret0(struct ata_port *ap) { return 0; } + static struct scsi_host_template pata_platform_sht = { .module = THIS_MODULE, .name = DRV_NAME, @@ -91,7 +93,7 @@ static struct ata_port_operations pata_platform_port_ops = { .irq_on = ata_irq_on, .irq_ack = ata_irq_ack, - .port_start = ata_port_start, + .port_start = ata_dummy_ret0, }; static void pata_platform_setup_port(struct ata_ioports *ioaddr, diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 1c54673e008d..ba96b54f5b87 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -200,10 +200,6 @@ static struct scsi_host_template radisys_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static const struct ata_port_operations radisys_pata_ops = { @@ -259,7 +255,7 @@ static const struct ata_port_operations radisys_pata_ops = { static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &radisys_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ @@ -267,13 +263,13 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e .udma_mask = 0x14, /* UDMA33/66 only */ .port_ops = &radisys_pata_ops, }; - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } static const struct pci_device_id radisys_pci_tbl[] = { diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index 85c45290eeee..2bfd7ef42af5 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -40,7 +40,7 @@ static int rz1000_set_mode(struct ata_port *ap, struct ata_device **unused) for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (ata_dev_ready(dev)) { + if (ata_dev_enabled(dev)) { /* We don't really care */ dev->pio_mode = XFER_PIO_0; dev->xfer_mode = XFER_PIO_0; @@ -69,10 +69,6 @@ static struct scsi_host_template rz1000_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations rz1000_port_ops = { @@ -135,22 +131,20 @@ static int rz1000_fifo_disable(struct pci_dev *pdev) static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - struct ata_port_info *port_info[2]; - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &rz1000_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &rz1000_port_ops }; + const struct ata_port_info *ppi[] = { &info, NULL }; if (!printed_version++) printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); - if (rz1000_fifo_disable(pdev) == 0) { - port_info[0] = &info; - port_info[1] = &info; - return ata_pci_init_one(pdev, port_info, 2); - } + if (rz1000_fifo_disable(pdev) == 0) + return ata_pci_init_one(pdev, ppi); + printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n"); /* Not safe to use so skip */ return -ENODEV; diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 66e8ff467c8d..225013ecf4b6 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -194,10 +194,6 @@ static struct scsi_host_template sc1200_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations sc1200_port_ops = { @@ -247,7 +243,7 @@ static struct ata_port_operations sc1200_port_ops = { static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &sc1200_sht, .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -255,10 +251,10 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) .udma_mask = 0x07, .port_ops = &sc1200_port_ops }; - static struct ata_port_info *port_info[2] = { &info, &info }; - /* Can't enable port 2 yet, see top comments */ - return ata_pci_init_one(dev, port_info, 1); + const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; + + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id sc1200[] = { diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 203f463ac39f..cca3aa225efe 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -984,10 +984,6 @@ static struct scsi_host_template scc_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static const struct ata_port_operations scc_pata_ops = { diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index b6e020383dd9..dee6e211949d 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -315,10 +315,6 @@ static struct scsi_host_template serverworks_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations serverworks_osb4_port_ops = { @@ -479,8 +475,7 @@ static void serverworks_fixup_ht1000(struct pci_dev *pdev) static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - int ports = 2; - static struct ata_port_info info[4] = { + static const struct ata_port_info info[4] = { { /* OSB4 */ .sht = &serverworks_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, @@ -511,8 +506,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id .port_ops = &serverworks_csb_port_ops } }; - static struct ata_port_info *port_info[2]; - struct ata_port_info *devinfo = &info[id->driver_data]; + const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL }; /* Force master latency timer to 64 PCI clocks */ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); @@ -521,7 +515,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { /* Select non UDMA capable OSB4 if we can't do fixups */ if ( serverworks_fixup_osb4(pdev) < 0) - devinfo = &info[1]; + ppi[0] = &info[1]; } /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ else if ((pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || @@ -531,11 +525,11 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id /* If the returned btr is the newer revision then select the right info block */ if (serverworks_fixup_csb(pdev) == 3) - devinfo = &info[3]; + ppi[0] = &info[3]; /* Is this the 3rd channel CSB6 IDE ? */ if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2) - ports = 1; + ppi[1] = &ata_dummy_port_info; } /* setup HT1000E */ else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) @@ -544,8 +538,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ata_pci_clear_simplex(pdev); - port_info[0] = port_info[1] = devinfo; - return ata_pci_init_one(pdev, port_info, ports); + return ata_pci_init_one(pdev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index a5886f061c0b..440e2cb6ee75 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -232,10 +232,6 @@ static struct scsi_host_template sil680_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static struct ata_port_operations sil680_port_ops = { @@ -345,7 +341,7 @@ static u8 sil680_init_chip(struct pci_dev *pdev) static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &sil680_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -353,7 +349,7 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .udma_mask = 0x7f, .port_ops = &sil680_port_ops }; - static struct ata_port_info info_slow = { + static const struct ata_port_info info_slow = { .sht = &sil680_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, @@ -361,7 +357,7 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .udma_mask = 0x3f, .port_ops = &sil680_port_ops }; - static struct ata_port_info *port_info[2] = {&info, &info}; + const struct ata_port_info *ppi[] = { &info, NULL }; static int printed_version; if (!printed_version++) @@ -370,12 +366,12 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) switch(sil680_init_chip(pdev)) { case 0: - port_info[0] = port_info[1] = &info_slow; + ppi[0] = &info_slow; break; case 0x30: return -ENODEV; } - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index f5838cc11728..f2231267e011 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -38,8 +38,8 @@ #define DRV_VERSION "0.5.1" struct sis_chipset { - u16 device; /* PCI host ID */ - struct ata_port_info *info; /* Info block */ + u16 device; /* PCI host ID */ + const struct ata_port_info *info; /* Info block */ /* Probably add family, cable detect type etc here to clean up code later */ }; @@ -524,10 +524,6 @@ static struct scsi_host_template sis_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static const struct ata_port_operations sis_133_ops = { @@ -700,7 +696,7 @@ static const struct ata_port_operations sis_old_ops = { .port_start = ata_port_start, }; -static struct ata_port_info sis_info = { +static const struct ata_port_info sis_info = { .sht = &sis_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ @@ -708,7 +704,7 @@ static struct ata_port_info sis_info = { .udma_mask = 0, .port_ops = &sis_old_ops, }; -static struct ata_port_info sis_info33 = { +static const struct ata_port_info sis_info33 = { .sht = &sis_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ @@ -716,35 +712,35 @@ static struct ata_port_info sis_info33 = { .udma_mask = ATA_UDMA2, /* UDMA 33 */ .port_ops = &sis_old_ops, }; -static struct ata_port_info sis_info66 = { +static const struct ata_port_info sis_info66 = { .sht = &sis_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA4, /* UDMA 66 */ .port_ops = &sis_66_ops, }; -static struct ata_port_info sis_info100 = { +static const struct ata_port_info sis_info100 = { .sht = &sis_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA5, .port_ops = &sis_100_ops, }; -static struct ata_port_info sis_info100_early = { +static const struct ata_port_info sis_info100_early = { .sht = &sis_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .udma_mask = ATA_UDMA5, .pio_mask = 0x1f, /* pio0-4 */ .port_ops = &sis_66_ops, }; -struct ata_port_info sis_info133 = { +const struct ata_port_info sis_info133 = { .sht = &sis_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &sis_133_ops, }; -static struct ata_port_info sis_info133_early = { +static const struct ata_port_info sis_info133_early = { .sht = &sis_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ @@ -827,8 +823,8 @@ static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis) static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - static struct ata_port_info *port_info[2]; - struct ata_port_info *port; + struct ata_port_info port; + const struct ata_port_info *ppi[] = { &port, NULL }; struct pci_dev *host = NULL; struct sis_chipset *chipset = NULL; struct sis_chipset *sets; @@ -968,13 +964,12 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (chipset == NULL) return -ENODEV; - port = chipset->info; - port->private_data = chipset; + port = *chipset->info; + port.private_data = chipset; sis_fixup(pdev, chipset); - port_info[0] = port_info[1] = port; - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } static const struct pci_device_id sis_pci_tbl[] = { diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index 9aeffdbe2829..f48491ad5f3a 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c @@ -301,20 +301,22 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev) static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info_dma = { + static const struct ata_port_info info_dma = { .sht = &sl82c105_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &sl82c105_port_ops }; - static struct ata_port_info info_early = { + static const struct ata_port_info info_early = { .sht = &sl82c105_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &sl82c105_port_ops }; - static struct ata_port_info *port_info[2] = { &info_early, &info_early }; + /* for now use only the first port */ + const struct ata_port_info *ppi[] = { &info_early, + &ata_dummy_port_info }; u32 val; int rev; @@ -324,17 +326,14 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Unable to find bridge, disabling DMA.\n"); else if (rev <= 5) dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Early bridge revision, no DMA available.\n"); - else { - port_info[0] = &info_dma; - port_info[1] = &info_dma; - } + else + ppi[0] = &info_dma; pci_read_config_dword(dev, 0x40, &val); val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; pci_write_config_dword(dev, 0x40, val); - - return ata_pci_init_one(dev, port_info, 1); /* For now */ + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id sl82c105[] = { diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index 349887bf5b93..b1d3076dfe51 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c @@ -194,10 +194,6 @@ static struct scsi_host_template triflex_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations triflex_port_ops = { @@ -237,20 +233,20 @@ static struct ata_port_operations triflex_port_ops = { static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info = { + static const struct ata_port_info info = { .sht = &triflex_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &triflex_port_ops }; - static struct ata_port_info *port_info[2] = { &info, &info }; + const struct ata_port_info *ppi[] = { &info, NULL }; static int printed_version; if (!printed_version++) dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_init_one(dev, ppi); } static const struct pci_device_id triflex[] = { diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 362beb2f489c..e4c71f76bd55 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -301,10 +301,6 @@ static struct scsi_host_template via_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, -#endif }; static struct ata_port_operations via_port_ops = { @@ -425,7 +421,7 @@ static void via_config_fifo(struct pci_dev *pdev, unsigned int flags) static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { /* Early VIA without UDMA support */ - static struct ata_port_info via_mwdma_info = { + static const struct ata_port_info via_mwdma_info = { .sht = &via_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .pio_mask = 0x1f, @@ -433,7 +429,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &via_port_ops }; /* Ditto with IRQ masking required */ - static struct ata_port_info via_mwdma_info_borked = { + static const struct ata_port_info via_mwdma_info_borked = { .sht = &via_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .pio_mask = 0x1f, @@ -441,7 +437,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &via_port_ops_noirq, }; /* VIA UDMA 33 devices (and borked 66) */ - static struct ata_port_info via_udma33_info = { + static const struct ata_port_info via_udma33_info = { .sht = &via_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .pio_mask = 0x1f, @@ -450,7 +446,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &via_port_ops }; /* VIA UDMA 66 devices */ - static struct ata_port_info via_udma66_info = { + static const struct ata_port_info via_udma66_info = { .sht = &via_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .pio_mask = 0x1f, @@ -459,7 +455,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &via_port_ops }; /* VIA UDMA 100 devices */ - static struct ata_port_info via_udma100_info = { + static const struct ata_port_info via_udma100_info = { .sht = &via_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .pio_mask = 0x1f, @@ -468,7 +464,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .port_ops = &via_port_ops }; /* UDMA133 with bad AST (All current 133) */ - static struct ata_port_info via_udma133_info = { + static const struct ata_port_info via_udma133_info = { .sht = &via_sht, .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING, .pio_mask = 0x1f, @@ -476,7 +472,8 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .udma_mask = 0x7f, /* FIXME: should check north bridge */ .port_ops = &via_port_ops }; - struct ata_port_info *port_info[2], *type; + struct ata_port_info type; + const struct ata_port_info *ppi[] = { &type, NULL }; struct pci_dev *isa = NULL; const struct via_isa_bridge *config; static int printed_version; @@ -521,25 +518,25 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) switch(config->flags & VIA_UDMA) { case VIA_UDMA_NONE: if (config->flags & VIA_NO_UNMASK) - type = &via_mwdma_info_borked; + type = via_mwdma_info_borked; else - type = &via_mwdma_info; + type = via_mwdma_info; break; case VIA_UDMA_33: - type = &via_udma33_info; + type = via_udma33_info; break; case VIA_UDMA_66: - type = &via_udma66_info; + type = via_udma66_info; /* The 66 MHz devices require we enable the clock */ pci_read_config_dword(pdev, 0x50, &timing); timing |= 0x80008; pci_write_config_dword(pdev, 0x50, timing); break; case VIA_UDMA_100: - type = &via_udma100_info; + type = via_udma100_info; break; case VIA_UDMA_133: - type = &via_udma133_info; + type = via_udma133_info; break; default: WARN_ON(1); @@ -554,10 +551,9 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) } /* We have established the device type, now fire it up */ - type->private_data = (void *)config; + type.private_data = (void *)config; - port_info[0] = port_info[1] = type; - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppi); } #ifdef CONFIG_PM diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index b3b62e985f19..bda5e7747c21 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -135,10 +135,6 @@ static struct scsi_host_template inic_sht = { .slave_configure = inic_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const int scr_map[] = { diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index a097595d4dc7..4cea3ef75226 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -325,10 +325,6 @@ static struct scsi_host_template nv_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static struct scsi_host_template nv_adma_sht = { @@ -347,10 +343,6 @@ static struct scsi_host_template nv_adma_sht = { .slave_configure = nv_adma_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const struct ata_port_operations nv_generic_ops = { @@ -465,7 +457,7 @@ static const struct ata_port_operations nv_adma_ops = { .host_stop = nv_adma_host_stop, }; -static struct ata_port_info nv_port_info[] = { +static const struct ata_port_info nv_port_info[] = { /* generic */ { .sht = &nv_sht, @@ -1545,7 +1537,7 @@ static void nv_adma_error_handler(struct ata_port *ap) static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version = 0; - const struct ata_port_info *ppi[2]; + const struct ata_port_info *ppi[] = { NULL, NULL }; struct ata_host *host; struct nv_host_priv *hpriv; int rc; @@ -1573,8 +1565,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) type = ADMA; } - ppi[0] = ppi[1] = &nv_port_info[type]; - rc = ata_pci_prepare_native_host(pdev, ppi, 2, &host); + ppi[0] = &nv_port_info[type]; + rc = ata_pci_prepare_native_host(pdev, ppi, &host); if (rc) return rc; diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 0a1e417f309c..e8483aadd11b 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -182,10 +182,6 @@ static struct scsi_host_template sil_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const struct ata_port_operations sil_ops = { diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index b97ee9f31aec..a69d78cd8e9b 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -380,10 +380,6 @@ static struct scsi_host_template sil24_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const struct ata_port_operations sil24_ops = { diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index d8ee062e82fc..ee66c5fa7ac8 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -129,7 +129,7 @@ static const struct ata_port_operations sis_ops = { .port_start = ata_port_start, }; -static struct ata_port_info sis_port_info = { +static const struct ata_port_info sis_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0x7, @@ -255,7 +255,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; struct ata_port_info pi = sis_port_info; - const struct ata_port_info *ppi[2] = { &pi, &pi }; + const struct ata_port_info *ppi[] = { &pi, NULL }; struct ata_host *host; u32 genctl, val; u8 pmr; @@ -335,7 +335,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) break; } - rc = ata_pci_prepare_native_host(pdev, ppi, 2, &host); + rc = ata_pci_prepare_native_host(pdev, ppi, &host); if (rc) return rc; diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index f74e383de083..006f5e352658 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -125,7 +125,7 @@ static const struct ata_port_operations uli_ops = { .port_start = ata_port_start, }; -static struct ata_port_info uli_port_info = { +static const struct ata_port_info uli_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_IGN_SIMPLEX, .pio_mask = 0x1f, /* pio0-4 */ @@ -201,19 +201,33 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) n_ports = 2; if (board_idx == uli_5287) n_ports = 4; - rc = ata_pci_prepare_native_host(pdev, ppi, n_ports, &host); - if (rc) - return rc; + + /* allocate the host */ + host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); + if (!host) + return -ENOMEM; hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL); if (!hpriv) return -ENOMEM; host->private_data = hpriv; + /* the first two ports are standard SFF */ + rc = ata_pci_init_native_host(host); + if (rc) + return rc; + + rc = ata_pci_init_bmdma(host); + if (rc) + return rc; + iomap = host->iomap; switch (board_idx) { case uli_5287: + /* If there are four, the last two live right after + * the standard SFF ports. + */ hpriv->scr_cfg_addr[0] = ULI5287_BASE; hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 939c9246fdd1..d105d2c189d2 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -116,10 +116,6 @@ static struct scsi_host_template svia_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const struct ata_port_operations vt6420_sata_ops = { @@ -415,7 +411,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) struct ata_host *host; int rc; - rc = ata_pci_prepare_native_host(pdev, ppi, 2, &host); + rc = ata_pci_prepare_native_host(pdev, ppi, &host); if (rc) return rc; *r_host = host; diff --git a/drivers/ata/sis.h b/drivers/ata/sis.h index 231da8fc2200..0f2208d8d5ef 100644 --- a/drivers/ata/sis.h +++ b/drivers/ata/sis.h @@ -2,4 +2,4 @@ struct ata_port_info; /* pata_sis.c */ -extern struct ata_port_info sis_info133; +extern const struct ata_port_info sis_info133; diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig index 33687454eb32..f5a47a48c3b4 100644 --- a/drivers/atm/Kconfig +++ b/drivers/atm/Kconfig @@ -2,19 +2,22 @@ # ATM device configuration # -menu "ATM drivers" +menuconfig ATM_DRIVERS + bool "ATM drivers" depends on NETDEVICES && ATM + default y + +if ATM_DRIVERS config ATM_DUMMY tristate "Dummy ATM driver" - depends on ATM help Dummy ATM driver. Useful for proxy signalling, testing, and development. If unsure, say N. config ATM_TCP tristate "ATM over TCP" - depends on INET && ATM + depends on INET help ATM over TCP driver. Useful mainly for development and for experiments. If unsure, say N. @@ -30,7 +33,7 @@ config ATM_LANAI config ATM_ENI tristate "Efficient Networks ENI155P" - depends on PCI && ATM + depends on PCI ---help--- Driver for the Efficient Networks ENI155p series and SMC ATM Power155 155 Mbps ATM adapters. Both, the versions with 512KB and @@ -139,7 +142,7 @@ config ATM_ENI_BURST_RX_2W config ATM_FIRESTREAM tristate "Fujitsu FireStream (FS50/FS155) " - depends on PCI && ATM + depends on PCI help Driver for the Fujitsu FireStream 155 (MB86697) and FireStream 50 (MB86695) ATM PCI chips. @@ -149,7 +152,7 @@ config ATM_FIRESTREAM config ATM_ZATM tristate "ZeitNet ZN1221/ZN1225" - depends on PCI && ATM + depends on PCI help Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM adapters. @@ -169,7 +172,7 @@ config ATM_ZATM_DEBUG config ATM_NICSTAR tristate "IDT 77201 (NICStAR) (ForeRunnerLE)" - depends on PCI && ATM && !64BIT + depends on PCI && !64BIT help The NICStAR chipset family is used in a large number of ATM NICs for 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE @@ -202,7 +205,7 @@ config ATM_NICSTAR_USE_IDT77105 config ATM_IDT77252 tristate "IDT 77252 (NICStAR II)" - depends on PCI && ATM + depends on PCI help Driver for the IDT 77252 ATM PCI chips. @@ -237,7 +240,7 @@ config ATM_IDT77252_USE_SUNI config ATM_AMBASSADOR tristate "Madge Ambassador (Collage PCI 155 Server)" - depends on PCI && ATM + depends on PCI select BITREVERSE help This is a driver for ATMizer based ATM card produced by Madge @@ -262,7 +265,7 @@ config ATM_AMBASSADOR_DEBUG config ATM_HORIZON tristate "Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)" - depends on PCI && ATM + depends on PCI help This is a driver for the Horizon chipset ATM adapter cards once produced by Madge Networks Ltd. Say Y (or M to compile as a module @@ -286,7 +289,7 @@ config ATM_HORIZON_DEBUG config ATM_IA tristate "Interphase ATM PCI x575/x525/x531" - depends on PCI && ATM && !64BIT + depends on PCI && !64BIT ---help--- This is a driver for the Interphase (i)ChipSAR adapter cards which include a variety of variants in term of the size of the @@ -319,7 +322,7 @@ config ATM_IA_DEBUG config ATM_FORE200E_MAYBE tristate "FORE Systems 200E-series" - depends on (PCI || SBUS) && ATM + depends on PCI || SBUS ---help--- This is a driver for the FORE Systems 200E-series ATM adapter cards. It simultaneously supports PCA-200E and SBA-200E models @@ -436,7 +439,7 @@ config ATM_FORE200E config ATM_HE tristate "ForeRunner HE Series" - depends on PCI && ATM + depends on PCI help This is a driver for the Marconi ForeRunner HE-series ATM adapter cards. It simultaneously supports the 155 and 622 versions. @@ -448,5 +451,4 @@ config ATM_HE_USE_SUNI Support for the S/UNI-Ultra and S/UNI-622 found in the ForeRunner HE cards. This driver provides carrier detection some statistics. -endmenu - +endif # ATM diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 18cdd8c77626..e2fc4b6734cf 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1317,18 +1317,6 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a } #endif -static struct loop_device *loop_find_dev(int number) -{ - struct loop_device *lo; - - list_for_each_entry(lo, &loop_devices, lo_list) { - if (lo->lo_number == number) - return lo; - } - return NULL; -} - -static struct loop_device *loop_init_one(int i); static int lo_open(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; @@ -1337,11 +1325,6 @@ static int lo_open(struct inode *inode, struct file *file) lo->lo_refcnt++; mutex_unlock(&lo->lo_ctl_mutex); - mutex_lock(&loop_devices_mutex); - if (!loop_find_dev(lo->lo_number + 1)) - loop_init_one(lo->lo_number + 1); - mutex_unlock(&loop_devices_mutex); - return 0; } @@ -1448,7 +1431,7 @@ out_free_queue: out_free_dev: kfree(lo); out: - return ERR_PTR(-ENOMEM); + return NULL; } static void loop_del_one(struct loop_device *lo) @@ -1460,36 +1443,30 @@ static void loop_del_one(struct loop_device *lo) kfree(lo); } +static int loop_lock(dev_t dev, void *data) +{ + mutex_lock(&loop_devices_mutex); + return 0; +} + static struct kobject *loop_probe(dev_t dev, int *part, void *data) { - unsigned int number = dev & MINORMASK; - struct loop_device *lo; + struct loop_device *lo = loop_init_one(dev & MINORMASK); + struct kobject *kobj; - mutex_lock(&loop_devices_mutex); - lo = loop_find_dev(number); - if (lo == NULL) - lo = loop_init_one(number); + kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM); mutex_unlock(&loop_devices_mutex); *part = 0; - if (IS_ERR(lo)) - return (void *)lo; - else - return &lo->lo_disk->kobj; + return kobj; } static int __init loop_init(void) { - struct loop_device *lo; - if (register_blkdev(LOOP_MAJOR, "loop")) return -EIO; blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS, - THIS_MODULE, loop_probe, NULL, NULL); - - lo = loop_init_one(0); - if (IS_ERR(lo)) - goto out; + THIS_MODULE, loop_probe, loop_lock, NULL); if (max_loop) { printk(KERN_INFO "loop: the max_loop option is obsolete " @@ -1498,11 +1475,6 @@ static int __init loop_init(void) } printk(KERN_INFO "loop: module loaded\n"); return 0; - -out: - unregister_blkdev(LOOP_MAJOR, "loop"); - printk(KERN_ERR "loop: ran out of memory\n"); - return -ENOMEM; } static void __exit loop_exit(void) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 0f4203b499af..6055b9c0ac0f 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -307,7 +307,9 @@ static void hci_uart_tty_close(struct tty_struct *tty) if (hu) { struct hci_dev *hdev = hu->hdev; - hci_uart_close(hdev); + + if (hdev) + hci_uart_close(hdev); if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { hu->proto->close(hu); @@ -473,12 +475,18 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, tty->low_latency = 1; } else return -EBUSY; + break; case HCIUARTGETPROTO: if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) return hu->proto->id; return -EUNATCH; + case HCIUARTGETDEVICE: + if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) + return hu->hdev->id; + return -EUNATCH; + default: err = n_tty_ioctl(tty, file, cmd, arg); break; diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index b250e6789dee..1097ce72393f 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -28,8 +28,9 @@ #endif /* Ioctls */ -#define HCIUARTSETPROTO _IOW('U', 200, int) -#define HCIUARTGETPROTO _IOR('U', 201, int) +#define HCIUARTSETPROTO _IOW('U', 200, int) +#define HCIUARTGETPROTO _IOR('U', 201, int) +#define HCIUARTGETDEVICE _IOR('U', 202, int) /* UART protocols */ #define HCI_UART_MAX_PROTO 4 diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index c9f0f250d78f..801abdd29066 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -268,7 +268,7 @@ static int __devinit aperture_valid(u64 aper, u32 size) printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20); return 0; } - if (aper + size > 0xffffffff) { + if ((u64)aper + size > 0x100000000ULL) { printk(KERN_ERR PFX "Aperture out of bounds\n"); return 0; } diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 6c5d15de3317..78e1b962fe35 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1915,10 +1915,10 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { info->io_setup = mem_setup; - info->io.addr_type = IPMI_IO_ADDR_SPACE; + info->io.addr_type = IPMI_MEM_ADDR_SPACE; } else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { info->io_setup = port_setup; - info->io.addr_type = IPMI_MEM_ADDR_SPACE; + info->io.addr_type = IPMI_IO_ADDR_SPACE; } else { kfree(info); printk("ipmi_si: Unknown ACPI I/O Address type\n"); @@ -2974,6 +2974,10 @@ static __devinit int init_ipmi_si(void) #ifdef CONFIG_PCI pci_unregister_driver(&ipmi_pci_driver); #endif + +#ifdef CONFIG_PPC_OF + of_unregister_platform_driver(&ipmi_of_platform_driver); +#endif driver_unregister(&ipmi_driver); printk("ipmi_si: Unable to find any System Interface(s)\n"); return -ENODEV; diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 6ac3ca4c723c..b3d4ccc33a47 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -1544,21 +1544,18 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol } struct tty_ldisc tty_ldisc_N_TTY = { - TTY_LDISC_MAGIC, /* magic */ - "n_tty", /* name */ - 0, /* num */ - 0, /* flags */ - n_tty_open, /* open */ - n_tty_close, /* close */ - n_tty_flush_buffer, /* flush_buffer */ - n_tty_chars_in_buffer, /* chars_in_buffer */ - read_chan, /* read */ - write_chan, /* write */ - n_tty_ioctl, /* ioctl */ - n_tty_set_termios, /* set_termios */ - normal_poll, /* poll */ - NULL, /* hangup */ - n_tty_receive_buf, /* receive_buf */ - n_tty_write_wakeup /* write_wakeup */ + .magic = TTY_LDISC_MAGIC, + .name = "n_tty", + .open = n_tty_open, + .close = n_tty_close, + .flush_buffer = n_tty_flush_buffer, + .chars_in_buffer = n_tty_chars_in_buffer, + .read = read_chan, + .write = write_chan, + .ioctl = n_tty_ioctl, + .set_termios = n_tty_set_termios, + .poll = normal_poll, + .receive_buf = n_tty_receive_buf, + .write_wakeup = n_tty_write_wakeup }; diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 245f03195b7c..8cc60b693460 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -402,7 +402,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name); rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); - if (Rup >= (unsigned short) MAX_RUP) { + if (Rup < (unsigned short) MAX_RUP) { rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name); } else rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name); diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 61a63da420c2..a3fd7e7ba5a9 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1014,9 +1014,6 @@ static int rp_open(struct tty_struct *tty, struct file *filp) /* * Info->count is now 1; so it's safe to sleep now. */ - info->session = process_session(current); - info->pgrp = process_group(current); - if ((info->flags & ROCKET_INITIALIZED) == 0) { cp = &info->channel; sSetRxTrigger(cp, TRIG_1); diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h index 89b4d7b10d12..b4c53dfa7951 100644 --- a/drivers/char/rocket_int.h +++ b/drivers/char/rocket_int.h @@ -1158,8 +1158,6 @@ struct r_port { int xmit_head; int xmit_tail; int xmit_cnt; - int session; - int pgrp; int cd_status; int ignore_status_mask; int read_status_mask; diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c index 2f56e8c54897..1b75b0b7d542 100644 --- a/drivers/char/snsc_event.c +++ b/drivers/char/snsc_event.c @@ -203,8 +203,6 @@ scdrv_dispatch_event(char *event, int len) class = (code & EV_CLASS_MASK); if (class == EV_CLASS_PWRD_NOTIFY || code == ENV_PWRDN_PEND) { - struct task_struct *p; - if (snsc_shutting_down) return; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 2a7736b5f2f7..02b49bc00028 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1171,6 +1171,112 @@ static int ioctl(struct tty_struct *tty, struct file *file, } /* + * support for 32 bit ioctl calls on 64 bit systems + */ +#ifdef CONFIG_COMPAT +static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params) +{ + struct MGSL_PARAMS32 tmp_params; + + DBGINFO(("%s get_params32\n", info->device_name)); + tmp_params.mode = (compat_ulong_t)info->params.mode; + tmp_params.loopback = info->params.loopback; + tmp_params.flags = info->params.flags; + tmp_params.encoding = info->params.encoding; + tmp_params.clock_speed = (compat_ulong_t)info->params.clock_speed; + tmp_params.addr_filter = info->params.addr_filter; + tmp_params.crc_type = info->params.crc_type; + tmp_params.preamble_length = info->params.preamble_length; + tmp_params.preamble = info->params.preamble; + tmp_params.data_rate = (compat_ulong_t)info->params.data_rate; + tmp_params.data_bits = info->params.data_bits; + tmp_params.stop_bits = info->params.stop_bits; + tmp_params.parity = info->params.parity; + if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32))) + return -EFAULT; + return 0; +} + +static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params) +{ + struct MGSL_PARAMS32 tmp_params; + + DBGINFO(("%s set_params32\n", info->device_name)); + if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32))) + return -EFAULT; + + spin_lock(&info->lock); + info->params.mode = tmp_params.mode; + info->params.loopback = tmp_params.loopback; + info->params.flags = tmp_params.flags; + info->params.encoding = tmp_params.encoding; + info->params.clock_speed = tmp_params.clock_speed; + info->params.addr_filter = tmp_params.addr_filter; + info->params.crc_type = tmp_params.crc_type; + info->params.preamble_length = tmp_params.preamble_length; + info->params.preamble = tmp_params.preamble; + info->params.data_rate = tmp_params.data_rate; + info->params.data_bits = tmp_params.data_bits; + info->params.stop_bits = tmp_params.stop_bits; + info->params.parity = tmp_params.parity; + spin_unlock(&info->lock); + + change_params(info); + + return 0; +} + +static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct slgt_info *info = tty->driver_data; + int rc = -ENOIOCTLCMD; + + if (sanity_check(info, tty->name, "compat_ioctl")) + return -ENODEV; + DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd)); + + switch (cmd) { + + case MGSL_IOCSPARAMS32: + rc = set_params32(info, compat_ptr(arg)); + break; + + case MGSL_IOCGPARAMS32: + rc = get_params32(info, compat_ptr(arg)); + break; + + case MGSL_IOCGPARAMS: + case MGSL_IOCSPARAMS: + case MGSL_IOCGTXIDLE: + case MGSL_IOCGSTATS: + case MGSL_IOCWAITEVENT: + case MGSL_IOCGIF: + case MGSL_IOCSGPIO: + case MGSL_IOCGGPIO: + case MGSL_IOCWAITGPIO: + case TIOCGICOUNT: + rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg))); + break; + + case MGSL_IOCSTXIDLE: + case MGSL_IOCTXENABLE: + case MGSL_IOCRXENABLE: + case MGSL_IOCTXABORT: + case TIOCMIWAIT: + case MGSL_IOCSIF: + rc = ioctl(tty, file, cmd, arg); + break; + } + + DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc)); + return rc; +} +#else +#define slgt_compat_ioctl NULL +#endif /* ifdef CONFIG_COMPAT */ + +/* * proc fs support */ static inline int line_info(char *buf, struct slgt_info *info) @@ -3446,6 +3552,7 @@ static const struct tty_operations ops = { .chars_in_buffer = chars_in_buffer, .flush_buffer = flush_buffer, .ioctl = ioctl, + .compat_ioctl = slgt_compat_ioctl, .throttle = throttle, .unthrottle = unthrottle, .send_xchar = send_xchar, diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h index c912d8691cbd..9363bcf0a402 100644 --- a/drivers/char/tpm/tpm_atmel.h +++ b/drivers/char/tpm/tpm_atmel.h @@ -23,6 +23,9 @@ */ #ifdef CONFIG_PPC64 + +#include <asm/prom.h> + #define atmel_getb(chip, offset) readb(chip->vendor->iobase + offset); #define atmel_putb(val, chip, offset) writeb(val, chip->vendor->iobase + offset) #define atmel_request_region request_mem_region diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index fc662e4ce58a..75d2a46e106f 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -151,6 +151,12 @@ static int tty_open(struct inode *, struct file *); static int tty_release(struct inode *, struct file *); int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT +static long tty_compat_ioctl(struct file * file, unsigned int cmd, + unsigned long arg); +#else +#define tty_compat_ioctl NULL +#endif static int tty_fasync(int fd, struct file * filp, int on); static void release_tty(struct tty_struct *tty, int idx); static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); @@ -363,6 +369,29 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) } /** + * tty_buffer_flush - flush full tty buffers + * @tty: tty to flush + * + * flush all the buffers containing receive data + * + * Locking: none + */ + +static void tty_buffer_flush(struct tty_struct *tty) +{ + struct tty_buffer *thead; + unsigned long flags; + + spin_lock_irqsave(&tty->buf.lock, flags); + while((thead = tty->buf.head) != NULL) { + tty->buf.head = thead->next; + tty_buffer_free(tty, thead); + } + tty->buf.tail = NULL; + spin_unlock_irqrestore(&tty->buf.lock, flags); +} + +/** * tty_buffer_find - find a free tty buffer * @tty: tty owning the buffer * @size: characters wanted @@ -1143,8 +1172,8 @@ static unsigned int hung_up_tty_poll(struct file * filp, poll_table * wait) return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM; } -static int hung_up_tty_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) +static long hung_up_tty_ioctl(struct file * file, + unsigned int cmd, unsigned long arg) { return cmd == TIOCSPGRP ? -ENOTTY : -EIO; } @@ -1155,6 +1184,7 @@ static const struct file_operations tty_fops = { .write = tty_write, .poll = tty_poll, .ioctl = tty_ioctl, + .compat_ioctl = tty_compat_ioctl, .open = tty_open, .release = tty_release, .fasync = tty_fasync, @@ -1167,6 +1197,7 @@ static const struct file_operations ptmx_fops = { .write = tty_write, .poll = tty_poll, .ioctl = tty_ioctl, + .compat_ioctl = tty_compat_ioctl, .open = ptmx_open, .release = tty_release, .fasync = tty_fasync, @@ -1179,6 +1210,7 @@ static const struct file_operations console_fops = { .write = redirected_tty_write, .poll = tty_poll, .ioctl = tty_ioctl, + .compat_ioctl = tty_compat_ioctl, .open = tty_open, .release = tty_release, .fasync = tty_fasync, @@ -1189,7 +1221,8 @@ static const struct file_operations hung_up_tty_fops = { .read = hung_up_tty_read, .write = hung_up_tty_write, .poll = hung_up_tty_poll, - .ioctl = hung_up_tty_ioctl, + .unlocked_ioctl = hung_up_tty_ioctl, + .compat_ioctl = hung_up_tty_ioctl, .release = tty_release, }; @@ -1238,6 +1271,7 @@ void tty_ldisc_flush(struct tty_struct *tty) ld->flush_buffer(tty); tty_ldisc_deref(ld); } + tty_buffer_flush(tty); } EXPORT_SYMBOL_GPL(tty_ldisc_flush); @@ -3340,6 +3374,15 @@ int tty_ioctl(struct inode * inode, struct file * file, case TIOCMBIC: case TIOCMBIS: return tty_tiocmset(tty, file, cmd, p); + case TCFLSH: + switch (arg) { + case TCIFLUSH: + case TCIOFLUSH: + /* flush tty buffer and allow ldisc to process ioctl */ + tty_buffer_flush(tty); + break; + } + break; } if (tty->driver->ioctl) { retval = (tty->driver->ioctl)(tty, file, cmd, arg); @@ -3357,6 +3400,32 @@ int tty_ioctl(struct inode * inode, struct file * file, return retval; } +#ifdef CONFIG_COMPAT +static long tty_compat_ioctl(struct file * file, unsigned int cmd, + unsigned long arg) +{ + struct inode *inode = file->f_dentry->d_inode; + struct tty_struct *tty = file->private_data; + struct tty_ldisc *ld; + int retval = -ENOIOCTLCMD; + + if (tty_paranoia_check(tty, inode, "tty_ioctl")) + return -EINVAL; + + if (tty->driver->compat_ioctl) { + retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg); + if (retval != -ENOIOCTLCMD) + return retval; + } + + ld = tty_ldisc_ref_wait(tty); + if (ld->compat_ioctl) + retval = ld->compat_ioctl(tty, file, cmd, arg); + tty_ldisc_deref(ld); + + return retval; +} +#endif /* * This implements the "Secure Attention Key" --- the idea is to @@ -3689,6 +3758,7 @@ void tty_set_operations(struct tty_driver *driver, driver->write_room = op->write_room; driver->chars_in_buffer = op->chars_in_buffer; driver->ioctl = op->ioctl; + driver->compat_ioctl = op->compat_ioctl; driver->set_termios = op->set_termios; driver->throttle = op->throttle; driver->unthrottle = op->unthrottle; @@ -3843,6 +3913,7 @@ void proc_clear_tty(struct task_struct *p) p->signal->tty = NULL; spin_unlock_irq(&p->sighand->siglock); } +EXPORT_SYMBOL(proc_clear_tty); static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) { diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index 3c9684ccd2f9..eac4f9b9f007 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c @@ -571,7 +571,7 @@ static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, * ACPIBASE is bits [15:7] from 0x40-0x43 */ pci_read_config_dword(pdev, 0x40, &base_address); - base_address &= 0x00007f80; + base_address &= 0x0000ff80; if (base_address == 0x00000000) { /* Something's wrong here, ACPIBASE has to be set */ printk(KERN_ERR PFX "failed to get TCOBASE address\n"); diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index a19b65ed3119..7f817897b178 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -240,11 +240,94 @@ static inline void hidinput_pb_setup(struct input_dev *input) } #endif +static inline int match_scancode(int code, int scancode) +{ + if (scancode == 0) + return 1; + return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode); +} + +static inline int match_keycode(int code, int keycode) +{ + if (keycode == 0) + return 1; + return (code == keycode); +} + +static struct hid_usage *hidinput_find_key(struct hid_device *hid, + int scancode, int keycode) +{ + int i, j, k; + struct hid_report *report; + struct hid_usage *usage; + + for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { + list_for_each_entry(report, &hid->report_enum[k].report_list, list) { + for (i = 0; i < report->maxfield; i++) { + for ( j = 0; j < report->field[i]->maxusage; j++) { + usage = report->field[i]->usage + j; + if (usage->type == EV_KEY && + match_scancode(usage->hid, scancode) && + match_keycode(usage->code, keycode)) + return usage; + } + } + } + } + return NULL; +} + +static int hidinput_getkeycode(struct input_dev *dev, int scancode, + int *keycode) +{ + struct hid_device *hid = dev->private; + struct hid_usage *usage; + + usage = hidinput_find_key(hid, scancode, 0); + if (usage) { + *keycode = usage->code; + return 0; + } + return -EINVAL; +} + +static int hidinput_setkeycode(struct input_dev *dev, int scancode, + int keycode) +{ + struct hid_device *hid = dev->private; + struct hid_usage *usage; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + usage = hidinput_find_key(hid, scancode, 0); + if (usage) { + old_keycode = usage->code; + usage->code = keycode; + + clear_bit(old_keycode, dev->keybit); + set_bit(usage->code, dev->keybit); +#ifdef CONFIG_HID_DEBUG + printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); +#endif + /* Set the keybit for the old keycode if the old keycode is used + * by another key */ + if (hidinput_find_key (hid, 0, old_keycode)) + set_bit(old_keycode, dev->keybit); + + return 0; + } + + return -EINVAL; +} + + static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, struct hid_usage *usage) { struct input_dev *input = hidinput->input; - struct hid_device *device = input->private; + struct hid_device *device = input_get_drvdata(input); int max = 0, code; unsigned long *bit = NULL; @@ -553,6 +636,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x1015: map_key_clear(KEY_RECORD); break; case 0x1016: map_key_clear(KEY_PLAYER); break; case 0x1017: map_key_clear(KEY_EJECTCD); break; + case 0x1018: map_key_clear(KEY_MEDIA); break; case 0x1019: map_key_clear(KEY_PROG1); break; case 0x101a: map_key_clear(KEY_PROG2); break; case 0x101b: map_key_clear(KEY_PROG3); break; @@ -560,9 +644,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x1020: map_key_clear(KEY_ZOOMOUT); break; case 0x1021: map_key_clear(KEY_ZOOMRESET); break; case 0x1023: map_key_clear(KEY_CLOSE); break; + case 0x1027: map_key_clear(KEY_MENU); break; /* this one is marked as 'Rotate' */ case 0x1028: map_key_clear(KEY_ANGLE); break; case 0x1029: map_key_clear(KEY_SHUFFLE); break; + case 0x102a: map_key_clear(KEY_BACK); break; + case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break; case 0x1041: map_key_clear(KEY_BATTERY); break; case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break; case 0x1043: map_key_clear(KEY_SPREADSHEET); break; @@ -855,13 +942,15 @@ EXPORT_SYMBOL_GPL(hidinput_find_field); static int hidinput_open(struct input_dev *dev) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); + return hid->hid_open(hid); } static void hidinput_close(struct input_dev *dev) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); + hid->hid_close(hid); } @@ -909,10 +998,12 @@ int hidinput_connect(struct hid_device *hid) return -1; } - input_dev->private = hid; + input_set_drvdata(input_dev, hid); input_dev->event = hid->hidinput_input_event; input_dev->open = hidinput_open; input_dev->close = hidinput_close; + input_dev->setkeycode = hidinput_setkeycode; + input_dev->getkeycode = hidinput_getkeycode; input_dev->name = hid->name; input_dev->phys = hid->phys; @@ -921,7 +1012,7 @@ int hidinput_connect(struct hid_device *hid) input_dev->id.vendor = hid->vendor; input_dev->id.product = hid->product; input_dev->id.version = hid->version; - input_dev->cdev.dev = hid->dev; + input_dev->dev.parent = hid->dev; hidinput->input = input_dev; list_add_tail(&hidinput->list, &hid->inputs); } diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig index 7c87bdc538bc..1b4b572f899b 100644 --- a/drivers/hid/usbhid/Kconfig +++ b/drivers/hid/usbhid/Kconfig @@ -25,12 +25,12 @@ comment "Input core support is needed for USB HID input layer or HIDBP support" depends on USB_HID && INPUT=n config USB_HIDINPUT_POWERBOOK - bool "Enable support for iBook/PowerBook special keys" + bool "Enable support for iBook/PowerBook/MacBook/MacBookPro special keys" default n depends on USB_HID help Say Y here if you want support for the special keys (Fn, Numlock) on - Apple iBooks and PowerBooks. + Apple iBooks, PowerBooks, MacBooks and MacBook Pros. If unsure, say N. diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 91d610358d57..d91b9dac6dff 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -446,7 +446,7 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); struct hid_field *field; int offset; @@ -626,14 +626,10 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) { struct usbhid_device *usbhid = hid->driver_data; - if (usbhid->inbuf) - usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); - if (usbhid->outbuf) - usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); - if (usbhid->cr) - usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma); - if (usbhid->ctrlbuf) - usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); + usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); + usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); + usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma); + usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); } /* @@ -692,6 +688,30 @@ static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize) } } +/* + * Some USB barcode readers from cypress have usage min and usage max in + * the wrong order + */ +static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize) +{ + short fixed = 0; + int i; + + for (i = 0; i < rsize - 4; i++) { + if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) { + unsigned char tmp; + + rdesc[i] = 0x19; rdesc[i+2] = 0x29; + tmp = rdesc[i+3]; + rdesc[i+3] = rdesc[i+1]; + rdesc[i+1] = tmp; + } + } + + if (fixed) + info("Fixing up Cypress report descriptor"); +} + static struct hid_device *usb_hid_configure(struct usb_interface *intf) { struct usb_host_interface *interface = intf->cur_altsetting; @@ -758,6 +778,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR) hid_fixup_logitech_descriptor(rdesc, rsize); + if (quirks & HID_QUIRK_SWAPPED_MIN_MAX) + hid_fixup_cypress_descriptor(rdesc, rsize); + #ifdef CONFIG_HID_DEBUG printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); for (n = 0; n < rsize; n++) diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c index 92d2553f17b6..c5cd4107d6af 100644 --- a/drivers/hid/usbhid/hid-lgff.c +++ b/drivers/hid/usbhid/hid-lgff.c @@ -60,7 +60,7 @@ static const struct dev_type devices[] = { static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); int x, y; diff --git a/drivers/hid/usbhid/hid-plff.c b/drivers/hid/usbhid/hid-plff.c index 76d2e6e14db4..d6a8f2b49bd2 100644 --- a/drivers/hid/usbhid/hid-plff.c +++ b/drivers/hid/usbhid/hid-plff.c @@ -37,7 +37,7 @@ struct plff_device { static int hid_plff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); struct plff_device *plff = data; int left, right; diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 17a87555e32f..f6c4145dc202 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -92,6 +92,8 @@ #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 #define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 #define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417 +#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 +#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 #define USB_VENDOR_ID_DELL 0x413c #define USB_DEVICE_ID_DELL_W7658 0x2005 @@ -193,6 +195,7 @@ #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 +#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 #define USB_DEVICE_ID_S510_RECEIVER 0xc50c #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 #define USB_DEVICE_ID_MX3000_RECEIVER 0xc513 @@ -422,6 +425,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, @@ -445,6 +449,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS }, + { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX }, + { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX }, + { 0, 0 } }; diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c index ab67331620d0..ab5ba6ef891c 100644 --- a/drivers/hid/usbhid/hid-tmff.c +++ b/drivers/hid/usbhid/hid-tmff.c @@ -59,7 +59,7 @@ static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum) static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); struct tmff_device *tmff = data; int left, right; /* Rumbling */ diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c index 7bd8238ca212..a7fbffcdaf36 100644 --- a/drivers/hid/usbhid/hid-zpff.c +++ b/drivers/hid/usbhid/hid-zpff.c @@ -37,7 +37,7 @@ struct zpff_device { static int hid_zpff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); struct zpff_device *zpff = data; int left, right; diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index a8b3d66cd498..488d61bdbf2c 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -51,6 +51,7 @@ struct hiddev { wait_queue_head_t wait; struct hid_device *hid; struct list_head list; + spinlock_t list_lock; }; struct hiddev_list { @@ -161,7 +162,9 @@ static void hiddev_send_event(struct hid_device *hid, { struct hiddev *hiddev = hid->hiddev; struct hiddev_list *list; + unsigned long flags; + spin_lock_irqsave(&hiddev->list_lock, flags); list_for_each_entry(list, &hiddev->list, node) { if (uref->field_index != HID_FIELD_INDEX_NONE || (list->flags & HIDDEV_FLAG_REPORT) != 0) { @@ -171,6 +174,7 @@ static void hiddev_send_event(struct hid_device *hid, kill_fasync(&list->fasync, SIGIO, POLL_IN); } } + spin_unlock_irqrestore(&hiddev->list_lock, flags); wake_up_interruptible(&hiddev->wait); } @@ -235,9 +239,13 @@ static int hiddev_fasync(int fd, struct file *file, int on) static int hiddev_release(struct inode * inode, struct file * file) { struct hiddev_list *list = file->private_data; + unsigned long flags; hiddev_fasync(-1, file, 0); + + spin_lock_irqsave(&list->hiddev->list_lock, flags); list_del(&list->node); + spin_unlock_irqrestore(&list->hiddev->list_lock, flags); if (!--list->hiddev->open) { if (list->hiddev->exist) @@ -257,6 +265,7 @@ static int hiddev_release(struct inode * inode, struct file * file) static int hiddev_open(struct inode *inode, struct file *file) { struct hiddev_list *list; + unsigned long flags; int i = iminor(inode) - HIDDEV_MINOR_BASE; @@ -267,7 +276,11 @@ static int hiddev_open(struct inode *inode, struct file *file) return -ENOMEM; list->hiddev = hiddev_table[i]; + + spin_lock_irqsave(&list->hiddev->list_lock, flags); list_add_tail(&list->node, &hiddev_table[i]->list); + spin_unlock_irqrestore(&list->hiddev->list_lock, flags); + file->private_data = list; if (!list->hiddev->open++) @@ -773,6 +786,7 @@ int hiddev_connect(struct hid_device *hid) init_waitqueue_head(&hiddev->wait); INIT_LIST_HEAD(&hiddev->list); + spin_lock_init(&hiddev->list_lock); hiddev->hid = hid; hiddev->exist = 1; diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index 65aa12e8d7b3..130978780713 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c @@ -133,12 +133,11 @@ resubmit: static int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct usb_kbd *kbd = dev->private; + struct usb_kbd *kbd = input_get_drvdata(dev); if (type != EV_LED) return -1; - kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | (!!test_bit(LED_NUML, dev->led)); @@ -175,7 +174,7 @@ static void usb_kbd_led(struct urb *urb) static int usb_kbd_open(struct input_dev *dev) { - struct usb_kbd *kbd = dev->private; + struct usb_kbd *kbd = input_get_drvdata(dev); kbd->irq->dev = kbd->usbdev; if (usb_submit_urb(kbd->irq, GFP_KERNEL)) @@ -186,7 +185,7 @@ static int usb_kbd_open(struct input_dev *dev) static void usb_kbd_close(struct input_dev *dev) { - struct usb_kbd *kbd = dev->private; + struct usb_kbd *kbd = input_get_drvdata(dev); usb_kill_urb(kbd->irq); } @@ -211,12 +210,9 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) { usb_free_urb(kbd->irq); usb_free_urb(kbd->led); - if (kbd->new) - usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); - if (kbd->cr) - usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma); - if (kbd->leds) - usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); + usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); + usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma); + usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); } static int usb_kbd_probe(struct usb_interface *iface, @@ -274,8 +270,9 @@ static int usb_kbd_probe(struct usb_interface *iface, input_dev->name = kbd->name; input_dev->phys = kbd->phys; usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &iface->dev; - input_dev->private = kbd; + input_dev->dev.parent = &iface->dev; + + input_set_drvdata(input_dev, kbd); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c index 573776d865e1..5345c73bcf62 100644 --- a/drivers/hid/usbhid/usbmouse.c +++ b/drivers/hid/usbhid/usbmouse.c @@ -96,7 +96,7 @@ resubmit: static int usb_mouse_open(struct input_dev *dev) { - struct usb_mouse *mouse = dev->private; + struct usb_mouse *mouse = input_get_drvdata(dev); mouse->irq->dev = mouse->usbdev; if (usb_submit_urb(mouse->irq, GFP_KERNEL)) @@ -107,7 +107,7 @@ static int usb_mouse_open(struct input_dev *dev) static void usb_mouse_close(struct input_dev *dev) { - struct usb_mouse *mouse = dev->private; + struct usb_mouse *mouse = input_get_drvdata(dev); usb_kill_urb(mouse->irq); } @@ -171,7 +171,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i input_dev->name = mouse->name; input_dev->phys = mouse->phys; usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; + input_dev->dev.parent = &intf->dev; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); @@ -179,7 +179,8 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); input_dev->relbit[0] |= BIT(REL_WHEEL); - input_dev->private = mouse; + input_set_drvdata(input_dev, mouse); + input_dev->open = usb_mouse_open; input_dev->close = usb_mouse_close; diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 55a72592704c..b234729706be 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -336,7 +336,7 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit, if (compat) { len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t); - if (len < maxlen) + if (len > maxlen) len = maxlen; for (i = 0; i < len / sizeof(compat_long_t); i++) diff --git a/drivers/md/md.c b/drivers/md/md.c index 65814b0340cb..c10ce91b64e9 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5103,7 +5103,7 @@ static int is_mddev_idle(mddev_t *mddev) * * Note: the following is an unsigned comparison. */ - if ((curr_events - rdev->last_events + 4096) > 8192) { + if ((long)curr_events - (long)rdev->last_events > 4096) { rdev->last_events = curr_events; idle = 0; } diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 3a80e0cc7369..624b21cef5b3 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -87,6 +87,14 @@ config VIDEO_TVEEPROM tristate depends on I2C +config DAB + boolean "DAB adapters" + default y + ---help--- + Allow selecting support for for Digital Audio Broadcasting (DAB) + Receiver adapters. + +if DAB config USB_DABUSB tristate "DABUSB driver" depends on USB @@ -100,5 +108,6 @@ config USB_DABUSB To compile this driver as a module, choose M here: the module will be called dabusb. +endif # DAB endmenu diff --git a/drivers/media/Makefile b/drivers/media/Makefile index c578a529e7a8..8fa19939c2b6 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -5,4 +5,4 @@ obj-y := common/ obj-$(CONFIG_VIDEO_DEV) += video/ obj-$(CONFIG_VIDEO_DEV) += radio/ -obj-$(CONFIG_DVB) += dvb/ +obj-$(CONFIG_DVB_CORE) += dvb/ diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 86cbdbcf9d7d..ef3e54cd9407 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -136,28 +136,45 @@ char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa char *mem = vmalloc_32(length); int slen = 0; - if (NULL == mem) { - return NULL; - } + if (NULL == mem) + goto err_null; - if (!(pt->slist = vmalloc_to_sg(mem, pages))) { - vfree(mem); - return NULL; - } + if (!(pt->slist = vmalloc_to_sg(mem, pages))) + goto err_free_mem; - if (saa7146_pgtable_alloc(pci, pt)) { - kfree(pt->slist); - pt->slist = NULL; - vfree(mem); - return NULL; - } + if (saa7146_pgtable_alloc(pci, pt)) + goto err_free_slist; - slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE); - if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) { - return NULL; - } + pt->nents = pages; + slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE); + if (0 == slen) + goto err_free_pgtable; + + if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) + goto err_unmap_sg; return mem; + +err_unmap_sg: + pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE); +err_free_pgtable: + saa7146_pgtable_free(pci, pt); +err_free_slist: + kfree(pt->slist); + pt->slist = NULL; +err_free_mem: + vfree(mem); +err_null: + return NULL; +} + +void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt) +{ + pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE); + saa7146_pgtable_free(pci, pt); + kfree(pt->slist); + pt->slist = NULL; + vfree(mem); } void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) @@ -166,8 +183,6 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) return; pci_free_consistent(pci, pt->size, pt->cpu, pt->dma); pt->cpu = NULL; - kfree(pt->slist); - pt->slist = NULL; } int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) @@ -528,6 +543,7 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc); EXPORT_SYMBOL_GPL(saa7146_pgtable_free); EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single); EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable); +EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable); EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done); EXPORT_SYMBOL_GPL(saa7146_setgpio); diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index c18a5da64934..b4770aecc01d 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -307,7 +307,6 @@ static int fops_release(struct inode *inode, struct file *file) return 0; } -int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg); static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { /* diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index a97c8f5e9a5d..efd2b7468158 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -2,24 +2,16 @@ # Multimedia device configuration # -menu "Digital Video Broadcasting Devices" +source "drivers/media/dvb/dvb-core/Kconfig" -config DVB - bool "DVB For Linux" - depends on NET && INET +menuconfig DVB_CAPTURE_DRIVERS + bool "DVB/ATSC adapters" + depends on DVB_CORE + default y ---help--- - Support Digital Video Broadcasting hardware. Enable this if you - own a DVB adapter and want to use it or if you compile Linux for - a digital SetTopBox. - - API specs and user tools are available from <http://www.linuxtv.org/>. + Say Y to select Digital TV adapters - Please report problems regarding this driver to the LinuxDVB - mailing list. - - If unsure say N. - -source "drivers/media/dvb/dvb-core/Kconfig" +if DVB_CAPTURE_DRIVERS comment "Supported SAA7146 based PCI Adapters" depends on DVB_CORE && PCI && I2C @@ -48,4 +40,4 @@ comment "Supported DVB Frontends" depends on DVB_CORE source "drivers/media/dvb/frontends/Kconfig" -endmenu +endif # DVB_CAPTURE_DRIVERS diff --git a/drivers/media/dvb/dvb-core/Kconfig b/drivers/media/dvb/dvb-core/Kconfig index 1990eda10c46..e3e6839f8073 100644 --- a/drivers/media/dvb/dvb-core/Kconfig +++ b/drivers/media/dvb/dvb-core/Kconfig @@ -1,12 +1,22 @@ config DVB_CORE - tristate "DVB Core Support" - depends on DVB + tristate "DVB for Linux" + depends on NET && INET select CRC32 help + Support Digital Video Broadcasting hardware. Enable this if you + own a DVB adapter and want to use it or if you compile Linux for + a digital SetTopBox. + DVB core utility functions for device handling, software fallbacks etc. Say Y when you have a DVB card and want to use it. Say Y if your want to build your drivers outside the kernel, but need the DVB core. All in-kernel drivers will select this automatically if needed. + + API specs and user tools are available from <http://www.linuxtv.org/>. + + Please report problems regarding this driver to the LinuxDVB + mailing list. + If unsure say N. config DVB_CORE_ATTACH diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 97715f7514d6..403081689de1 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -19,6 +19,7 @@ #define USB_VID_COMPRO_UNK 0x145f #define USB_VID_CYPRESS 0x04b4 #define USB_VID_DIBCOM 0x10b8 +#define USB_VID_DPOSH 0x1498 #define USB_VID_DVICO 0x0fe9 #define USB_VID_EMPIA 0xeb1a #define USB_VID_GENPIX 0x09c0 @@ -61,6 +62,8 @@ #define USB_PID_DIBCOM_STK7700P 0x1e14 #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 +#define USB_PID_DPOSH_M9206_COLD 0x9206 +#define USB_PID_DPOSH_M9206_WARM 0xa090 #define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 @@ -145,6 +148,8 @@ #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 #define USB_PID_OPERA1_COLD 0x2830 #define USB_PID_OPERA1_WARM 0x3829 +#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 +#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 #endif diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 0d721731a524..6f824a569e14 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -119,7 +119,7 @@ struct usb_data_stream_properties { * @caps: capabilities of the DVB USB device. * @pid_filter_count: number of PID filter position in the optional hardware * PID-filter. - * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the + * @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the * device (not URB submitting/killing). * @pid_filter_ctrl: called to en/disable the PID filter, if any. * @pid_filter: called to set/unset a PID for filtering. diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index 45d7bc214c18..c546ddeda5d4 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c @@ -3,8 +3,8 @@ * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org) * * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 2. + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, version 2. * * see Documentation/dvb/README.dvb-usb for more information */ @@ -22,26 +22,7 @@ static int dvb_usb_m920x_debug; module_param_named(debug,dvb_usb_m920x_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); -static struct dvb_usb_rc_key megasky_rc_keys [] = { - { 0x0, 0x12, KEY_POWER }, - { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ - { 0x0, 0x02, KEY_CHANNELUP }, - { 0x0, 0x05, KEY_CHANNELDOWN }, - { 0x0, 0x03, KEY_VOLUMEUP }, - { 0x0, 0x06, KEY_VOLUMEDOWN }, - { 0x0, 0x04, KEY_MUTE }, - { 0x0, 0x07, KEY_OK }, /* TS */ - { 0x0, 0x08, KEY_STOP }, - { 0x0, 0x09, KEY_MENU }, /* swap */ - { 0x0, 0x0a, KEY_REWIND }, - { 0x0, 0x1b, KEY_PAUSE }, - { 0x0, 0x1f, KEY_FASTFORWARD }, - { 0x0, 0x0c, KEY_RECORD }, - { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ - { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ -}; - -static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ +static inline int m920x_read(struct usb_device *udev, u8 request, u16 value, u16 index, void *data, int size) { int ret; @@ -55,14 +36,14 @@ static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ } if (ret != size) { - deb_rc("m920x_read = no data\n"); + deb("m920x_read = no data\n"); return -EIO; } return 0; } -static inline int m9206_write(struct usb_device *udev, u8 request, +static inline int m920x_write(struct usb_device *udev, u8 request, u16 value, u16 index) { int ret; @@ -74,32 +55,40 @@ static inline int m9206_write(struct usb_device *udev, u8 request, return ret; } -static int m9206_init(struct dvb_usb_device *d) +static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq) { int ret = 0; /* Remote controller init. */ if (d->props.rc_query) { - if ((ret = m9206_write(d->udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0) - return ret; + deb("Initialising remote control\n"); + while (rc_seq->address) { + if ((ret = m920x_write(d->udev, M9206_CORE, + rc_seq->data, + rc_seq->address)) != 0) { + deb("Initialising remote control failed\n"); + return ret; + } - if ((ret = m9206_write(d->udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0) - return ret; + rc_seq++; + } + + deb("Initialising remote control success\n"); } return ret; } -static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - struct m9206_state *m = d->priv; + struct m920x_state *m = d->priv; int i, ret = 0; u8 rc_state[2]; - if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) + if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) goto unlock; - if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) + if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) goto unlock; for (i = 0; i < d->props.rc_key_map_size; i++) @@ -111,6 +100,14 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *state = REMOTE_NO_KEY_PRESSED; goto unlock; + case 0x88: /* framing error or "invalid code" */ + case 0x99: + case 0xc0: + case 0xd8: + *state = REMOTE_NO_KEY_PRESSED; + m->rep_count = 0; + goto unlock; + case 0x93: case 0x92: m->rep_count = 0; @@ -118,31 +115,32 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) goto unlock; case 0x91: - /* For comfort. */ + /* prevent immediate auto-repeat */ if (++m->rep_count > 2) *state = REMOTE_KEY_REPEAT; + else + *state = REMOTE_NO_KEY_PRESSED; goto unlock; default: - deb_rc("Unexpected rc response %x\n", rc_state[0]); + deb("Unexpected rc state %02x\n", rc_state[0]); *state = REMOTE_NO_KEY_PRESSED; goto unlock; } } if (rc_state[1] != 0) - deb_rc("Unknown rc key %x\n", rc_state[1]); + deb("Unknown rc key %02x\n", rc_state[1]); *state = REMOTE_NO_KEY_PRESSED; - unlock: + unlock: return ret; } /* I2C */ -static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) +static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i, j; @@ -155,33 +153,40 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], return -EAGAIN; for (i = 0; i < num; i++) { - if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN) || - msg[i].len == 0) { - /* For a 0 byte message, I think sending the address to index 0x80|0x40 - * would be the correct thing to do. However, zero byte messages are - * only used for probing, and since we don't know how to get the slave's - * ack, we can't probe. */ + if (msg[i].flags & (I2C_M_NO_RD_ACK | I2C_M_IGNORE_NAK | I2C_M_TEN) || msg[i].len == 0) { + /* For a 0 byte message, I think sending the address + * to index 0x80|0x40 would be the correct thing to + * do. However, zero byte messages are only used for + * probing, and since we don't know how to get the + * slave's ack, we can't probe. */ ret = -ENOTSUPP; goto unlock; } /* Send START & address/RW bit */ if (!(msg[i].flags & I2C_M_NOSTART)) { - if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), 0x80)) != 0) + if ((ret = m920x_write(d->udev, M9206_I2C, + (msg[i].addr << 1) | + (msg[i].flags & I2C_M_RD ? 0x01 : 0), 0x80)) != 0) goto unlock; /* Should check for ack here, if we knew how. */ } if (msg[i].flags & I2C_M_RD) { for (j = 0; j < msg[i].len; j++) { - /* Last byte of transaction? Send STOP, otherwise send ACK. */ - int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01; - if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0) + /* Last byte of transaction? + * Send STOP, otherwise send ACK. */ + int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x01; + + if ((ret = m920x_read(d->udev, M9206_I2C, 0x0, + 0x20 | stop, + &msg[i].buf[j], 1)) != 0) goto unlock; } } else { for (j = 0; j < msg[i].len; j++) { /* Last byte of transaction? Then send STOP. */ - int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00; - if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0) + int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x00; + + if ((ret = m920x_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0) goto unlock; /* Should check for ack here too. */ } @@ -189,25 +194,25 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], } ret = num; -unlock: + unlock: mutex_unlock(&d->i2c_mutex); return ret; } -static u32 m9206_i2c_func(struct i2c_adapter *adapter) +static u32 m920x_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; } -static struct i2c_algorithm m9206_i2c_algo = { - .master_xfer = m9206_i2c_xfer, - .functionality = m9206_i2c_func, +static struct i2c_algorithm m920x_i2c_algo = { + .master_xfer = m920x_i2c_xfer, + .functionality = m920x_i2c_func, }; - -static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, - int pid) +/* pid filter */ +static int m920x_set_filter(struct dvb_usb_adapter *adap, + int type, int idx, int pid) { int ret = 0; @@ -216,18 +221,18 @@ static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, pid |= 0x8000; - if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0) + if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0) return ret; - if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0) + if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0) return ret; return ret; } -static int m9206_update_filters(struct dvb_usb_adapter *adap) +static int m920x_update_filters(struct dvb_usb_adapter *adap) { - struct m9206_state *m = adap->dev->priv; + struct m920x_state *m = adap->dev->priv; int enabled = m->filtering_enabled; int i, ret = 0, filter = 0; @@ -236,14 +241,14 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap) enabled = 0; /* Disable all filters */ - if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0) + if ((ret = m920x_set_filter(adap, 0x81, 1, enabled)) != 0) return ret; for (i = 0; i < M9206_MAX_FILTERS; i++) - if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0) + if ((ret = m920x_set_filter(adap, 0x81, i + 2, 0)) != 0) return ret; - if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0) + if ((ret = m920x_set_filter(adap, 0x82, 0, 0x0)) != 0) return ret; /* Set */ @@ -252,40 +257,38 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap) if (m->filters[i] == 0) continue; - if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0) + if ((ret = m920x_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0) return ret; filter++; } } - if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0) + if ((ret = m920x_set_filter(adap, 0x82, 0, 0x02f5)) != 0) return ret; return ret; } -static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +static int m920x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { - struct m9206_state *m = adap->dev->priv; + struct m920x_state *m = adap->dev->priv; m->filtering_enabled = onoff ? 1 : 0; - return m9206_update_filters(adap); + return m920x_update_filters(adap); } -static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, - int onoff) +static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { - struct m9206_state *m = adap->dev->priv; + struct m920x_state *m = adap->dev->priv; m->filters[index] = onoff ? pid : 0; - return m9206_update_filters(adap); + return m920x_update_filters(adap); } -static int m9206_firmware_download(struct usb_device *udev, - const struct firmware *fw) +static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw) { u16 value, index, size; u8 read[4], *buff; @@ -293,13 +296,13 @@ static int m9206_firmware_download(struct usb_device *udev, buff = kmalloc(65536, GFP_KERNEL); - if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) + if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) goto done; - deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]); + deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]); - if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) + if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) goto done; - deb_rc("%x\n", read[0]); + deb("%x\n", read[0]); for (pass = 0; pass < 2; pass++) { for (i = 0; i + (sizeof(u16) * 3) < fw->size;) { @@ -317,11 +320,11 @@ static int m9206_firmware_download(struct usb_device *udev, memcpy(buff, fw->data + i, size); ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), - M9206_FW, - USB_TYPE_VENDOR | USB_DIR_OUT, - value, index, buff, size, 20); + M9206_FW, + USB_TYPE_VENDOR | USB_DIR_OUT, + value, index, buff, size, 20); if (ret != size) { - deb_rc("error while uploading fw!\n"); + deb("error while uploading fw!\n"); ret = -EIO; goto done; } @@ -330,7 +333,7 @@ static int m9206_firmware_download(struct usb_device *udev, i += size; } if (i != fw->size) { - deb_rc("bad firmware file!\n"); + deb("bad firmware file!\n"); ret = -EINVAL; goto done; } @@ -338,11 +341,11 @@ static int m9206_firmware_download(struct usb_device *udev, msleep(36); - /* m9206 will disconnect itself from the bus after this. */ - (void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO); - deb_rc("firmware uploaded!\n"); + /* m920x will disconnect itself from the bus after this. */ + (void) m920x_write(udev, M9206_CORE, 0x01, M9206_FW_GO); + deb("firmware uploaded!\n"); - done: + done: kfree(buff); return ret; @@ -362,7 +365,8 @@ static int m920x_identify_state(struct usb_device *udev, return 0; } -static int megasky_mt352_demod_init(struct dvb_frontend *fe) +/* demod configurations */ +static int m920x_mt352_demod_init(struct dvb_frontend *fe) { u8 config[] = { CONFIG, 0x3d }; u8 clock[] = { CLOCK_CTL, 0x30 }; @@ -382,74 +386,174 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe) mt352_write(fe, unk1, ARRAY_SIZE(unk1)); mt352_write(fe, unk2, ARRAY_SIZE(unk2)); - deb_rc("Demod init!\n"); + deb("Demod init!\n"); return 0; } -static struct mt352_config megasky_mt352_config = { +static struct mt352_config m920x_mt352_config = { .demod_address = 0x0f, .no_tuner = 1, - .demod_init = megasky_mt352_demod_init, + .demod_init = m920x_mt352_demod_init, +}; + +static struct tda1004x_config m920x_tda10046_08_config = { + .demod_address = 0x08, + .invert = 0, + .invert_oclk = 0, + .ts_mode = TDA10046_TS_SERIAL, + .xtal_freq = TDA10046_XTAL_16M, + .if_freq = TDA10046_FREQ_045, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GPTRI, + .request_firmware = NULL, +}; + +static struct tda1004x_config m920x_tda10046_0b_config = { + .demod_address = 0x0b, + .invert = 0, + .invert_oclk = 0, + .ts_mode = TDA10046_TS_SERIAL, + .xtal_freq = TDA10046_XTAL_16M, + .if_freq = TDA10046_FREQ_045, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GPTRI, + .request_firmware = NULL, /* uses firmware EEPROM */ +}; + +/* tuner configurations */ +static struct qt1010_config m920x_qt1010_config = { + .i2c_address = 0x62 }; -static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap) +/* Callbacks for DVB USB */ +static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap) { - deb_rc("megasky_frontend_attach!\n"); + deb("%s\n",__FUNCTION__); - if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL) + if ((adap->fe = dvb_attach(mt352_attach, + &m920x_mt352_config, + &adap->dev->i2c_adap)) == NULL) return -EIO; return 0; } -static struct qt1010_config megasky_qt1010_config = { - .i2c_address = 0x62 -}; - -static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap) +static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap) { - if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, - &megasky_qt1010_config) == NULL) - return -ENODEV; + deb("%s\n",__FUNCTION__); + + if ((adap->fe = dvb_attach(tda10046_attach, + &m920x_tda10046_08_config, + &adap->dev->i2c_adap)) == NULL) + return -EIO; return 0; } -static struct tda1004x_config digivox_tda10046_config = { - .demod_address = 0x08, - .invert = 0, - .invert_oclk = 0, - .ts_mode = TDA10046_TS_SERIAL, - .xtal_freq = TDA10046_XTAL_16M, - .if_freq = TDA10046_FREQ_045, - .agc_config = TDA10046_AGC_TDA827X, - .gpio_config = TDA10046_GPTRI, - .request_firmware = NULL, -}; - -static int digivox_tda10046_frontend_attach(struct dvb_usb_adapter *adap) +static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap) { - deb_rc("digivox_tda10046_frontend_attach!\n"); + deb("%s\n",__FUNCTION__); - if ((adap->fe = dvb_attach(tda10046_attach, &digivox_tda10046_config, + if ((adap->fe = dvb_attach(tda10046_attach, + &m920x_tda10046_0b_config, &adap->dev->i2c_adap)) == NULL) return -EIO; return 0; } -static int digivox_tda8275_tuner_attach(struct dvb_usb_adapter *adap) +static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap) { - if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, - NULL) == NULL) + deb("%s\n",__FUNCTION__); + + if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL) return -ENODEV; + return 0; } +static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap) +{ + deb("%s\n",__FUNCTION__); + + if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL) + return -ENODEV; + + return 0; +} + +static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap) +{ + deb("%s\n",__FUNCTION__); + + if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) + return -ENODEV; + + return 0; +} + +/* device-specific initialization */ +static struct m920x_inits megasky_rc_init [] = { + { M9206_RC_INIT2, 0xa8 }, + { M9206_RC_INIT1, 0x51 }, + { } /* terminating entry */ +}; + +static struct m920x_inits tvwalkertwin_rc_init [] = { + { M9206_RC_INIT2, 0x00 }, + { M9206_RC_INIT1, 0xef }, + { 0xff28, 0x00 }, + { 0xff23, 0x00 }, + { 0xff21, 0x30 }, + { } /* terminating entry */ +}; + +/* ir keymaps */ +static struct dvb_usb_rc_key megasky_rc_keys [] = { + { 0x0, 0x12, KEY_POWER }, + { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ + { 0x0, 0x02, KEY_CHANNELUP }, + { 0x0, 0x05, KEY_CHANNELDOWN }, + { 0x0, 0x03, KEY_VOLUMEUP }, + { 0x0, 0x06, KEY_VOLUMEDOWN }, + { 0x0, 0x04, KEY_MUTE }, + { 0x0, 0x07, KEY_OK }, /* TS */ + { 0x0, 0x08, KEY_STOP }, + { 0x0, 0x09, KEY_MENU }, /* swap */ + { 0x0, 0x0a, KEY_REWIND }, + { 0x0, 0x1b, KEY_PAUSE }, + { 0x0, 0x1f, KEY_FASTFORWARD }, + { 0x0, 0x0c, KEY_RECORD }, + { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ + { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ +}; + +static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = { + { 0x0, 0x01, KEY_ZOOM }, /* Full Screen */ + { 0x0, 0x02, KEY_CAMERA }, /* snapshot */ + { 0x0, 0x03, KEY_MUTE }, + { 0x0, 0x04, KEY_REWIND }, + { 0x0, 0x05, KEY_PLAYPAUSE }, /* Play/Pause */ + { 0x0, 0x06, KEY_FASTFORWARD }, + { 0x0, 0x07, KEY_RECORD }, + { 0x0, 0x08, KEY_STOP }, + { 0x0, 0x09, KEY_TIME }, /* Timeshift */ + { 0x0, 0x0c, KEY_COFFEE }, /* Recall */ + { 0x0, 0x0e, KEY_CHANNELUP }, + { 0x0, 0x12, KEY_POWER }, + { 0x0, 0x15, KEY_MENU }, /* source */ + { 0x0, 0x18, KEY_CYCLEWINDOWS }, /* TWIN PIP */ + { 0x0, 0x1a, KEY_CHANNELDOWN }, + { 0x0, 0x1b, KEY_VOLUMEDOWN }, + { 0x0, 0x1e, KEY_VOLUMEUP }, +}; + /* DVB USB Driver stuff */ static struct dvb_usb_device_properties megasky_properties; static struct dvb_usb_device_properties digivox_mini_ii_properties; +static struct dvb_usb_device_properties tvwalkertwin_properties; +static struct dvb_usb_device_properties dposh_properties; static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -457,19 +561,57 @@ static int m920x_probe(struct usb_interface *intf, struct dvb_usb_device *d; struct usb_host_interface *alt; int ret; + struct m920x_inits *rc_init_seq = NULL; + int bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber; - deb_rc("Probed!\n"); + deb("Probing for m920x device at interface %d\n", bInterfaceNumber); - if (((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) || - ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, THIS_MODULE, &d)) == 0)) - goto found; + if (bInterfaceNumber == 0) { + /* Single-tuner device, or first interface on + * multi-tuner device + */ - return ret; + if ((ret = dvb_usb_device_init(intf, &megasky_properties, + THIS_MODULE, &d)) == 0) { + rc_init_seq = megasky_rc_init; + goto found; + } + + if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, + THIS_MODULE, &d)) == 0) { + /* No remote control, so no rc_init_seq */ + goto found; + } + + /* This configures both tuners on the TV Walker Twin */ + if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties, + THIS_MODULE, &d)) == 0) { + rc_init_seq = tvwalkertwin_rc_init; + goto found; + } + + if ((ret = dvb_usb_device_init(intf, &dposh_properties, + THIS_MODULE, &d)) == 0) { + /* Remote controller not supported yet. */ + goto found; + } + + return ret; + } else { + /* Another interface on a multi-tuner device */ -found: + /* The LifeView TV Walker Twin gets here, but struct + * tvwalkertwin_properties already configured both + * tuners, so there is nothing for us to do here + */ + + return -ENODEV; + } + + found: alt = usb_altnum_to_altsetting(intf, 1); if (alt == NULL) { - deb_rc("No alt found!\n"); + deb("No alt found!\n"); return -ENODEV; } @@ -478,7 +620,7 @@ found: if (ret < 0) return ret; - if ((ret = m9206_init(d)) != 0) + if ((ret = m920x_init(d, rc_init_seq)) != 0) return ret; return ret; @@ -488,6 +630,12 @@ static struct usb_device_id m920x_table [] = { { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, USB_PID_MSI_DIGI_VOX_MINI_II) }, + { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, + USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD) }, + { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, + USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) }, + { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) }, + { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, m920x_table); @@ -497,14 +645,14 @@ static struct dvb_usb_device_properties megasky_properties = { .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-megasky-02.fw", - .download_firmware = m9206_firmware_download, + .download_firmware = m920x_firmware_download, .rc_interval = 100, .rc_key_map = megasky_rc_keys, .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys), - .rc_query = m9206_rc_query, + .rc_query = m920x_rc_query, - .size_of_priv = sizeof(struct m9206_state), + .size_of_priv = sizeof(struct m920x_state), .identify_state = m920x_identify_state, .num_adapters = 1, @@ -513,11 +661,11 @@ static struct dvb_usb_device_properties megasky_properties = { DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 8, - .pid_filter = m9206_pid_filter, - .pid_filter_ctrl = m9206_pid_filter_ctrl, + .pid_filter = m920x_pid_filter, + .pid_filter_ctrl = m920x_pid_filter_ctrl, - .frontend_attach = megasky_mt352_frontend_attach, - .tuner_attach = megasky_qt1010_tuner_attach, + .frontend_attach = m920x_mt352_frontend_attach, + .tuner_attach = m920x_qt1010_tuner_attach, .stream = { .type = USB_BULK, @@ -530,7 +678,7 @@ static struct dvb_usb_device_properties megasky_properties = { } }, }}, - .i2c_algo = &m9206_i2c_algo, + .i2c_algo = &m920x_i2c_algo, .num_device_descs = 1, .devices = { @@ -546,22 +694,22 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = { .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-digivox-02.fw", - .download_firmware = m9206_firmware_download, + .download_firmware = m920x_firmware_download, - .size_of_priv = sizeof(struct m9206_state), + .size_of_priv = sizeof(struct m920x_state), .identify_state = m920x_identify_state, .num_adapters = 1, .adapter = {{ .caps = DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 8, - .pid_filter = m9206_pid_filter, - .pid_filter_ctrl = m9206_pid_filter_ctrl, + .pid_filter = m920x_pid_filter, + .pid_filter_ctrl = m920x_pid_filter_ctrl, - .frontend_attach = digivox_tda10046_frontend_attach, - .tuner_attach = digivox_tda8275_tuner_attach, + .frontend_attach = m920x_tda10046_08_frontend_attach, + .tuner_attach = m920x_tda8275_60_tuner_attach, .stream = { .type = USB_BULK, @@ -574,7 +722,7 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = { } }, }}, - .i2c_algo = &m9206_i2c_algo, + .i2c_algo = &m920x_i2c_algo, .num_device_descs = 1, .devices = { @@ -585,6 +733,122 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = { } }; +/* LifeView TV Walker Twin support by Nick Andrew <nick@nick-andrew.net> + * + * LifeView TV Walker Twin has 1 x M9206, 2 x TDA10046, 2 x TDA8275A + * TDA10046 #0 is located at i2c address 0x08 + * TDA10046 #1 is located at i2c address 0x0b (presently disabled - not yet working) + * TDA8275A #0 is located at i2c address 0x60 + * TDA8275A #1 is located at i2c address 0x61 (presently disabled - not yet working) + */ +static struct dvb_usb_device_properties tvwalkertwin_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-tvwalkert.fw", + .download_firmware = m920x_firmware_download, + + .rc_interval = 100, + .rc_key_map = tvwalkertwin_rc_keys, + .rc_key_map_size = ARRAY_SIZE(tvwalkertwin_rc_keys), + .rc_query = m920x_rc_query, + + .size_of_priv = sizeof(struct m920x_state), + + .identify_state = m920x_identify_state, + .num_adapters = 1, + .adapter = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 8, + .pid_filter = m920x_pid_filter, + .pid_filter_ctrl = m920x_pid_filter_ctrl, + + .frontend_attach = m920x_tda10046_08_frontend_attach, + .tuner_attach = m920x_tda8275_60_tuner_attach, + + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 512, + } + } + }},{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 8, + .pid_filter = m920x_pid_filter, + .pid_filter_ctrl = m920x_pid_filter_ctrl, + + .frontend_attach = m920x_tda10046_0b_frontend_attach, + .tuner_attach = m920x_tda8275_61_tuner_attach, + + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, + }}, + .i2c_algo = &m920x_i2c_algo, + + .num_device_descs = 1, + .devices = { + { .name = "LifeView TV Walker Twin DVB-T USB2.0", + .cold_ids = { &m920x_table[2], NULL }, + .warm_ids = { &m920x_table[3], NULL }, + }, + } +}; + +static struct dvb_usb_device_properties dposh_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-dposh-01.fw", + .download_firmware = m920x_firmware_download, + + .size_of_priv = sizeof(struct m920x_state), + + .identify_state = m920x_identify_state, + .num_adapters = 1, + .adapter = {{ + /* Hardware pid filters don't work with this device/firmware */ + + .frontend_attach = m920x_mt352_frontend_attach, + .tuner_attach = m920x_qt1010_tuner_attach, + + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, + }}, + .i2c_algo = &m920x_i2c_algo, + + .num_device_descs = 1, + .devices = { + { .name = "Dposh DVB-T USB2.0", + .cold_ids = { &m920x_table[4], NULL }, + .warm_ids = { &m920x_table[5], NULL }, + }, + } +}; + static struct usb_driver m920x_driver = { .name = "dvb_usb_m920x", .probe = m920x_probe, @@ -615,6 +879,11 @@ module_init (m920x_module_init); module_exit (m920x_module_exit); MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>"); -MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x"); +MODULE_DESCRIPTION("DVB Driver for ULI M920x"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); + +/* + * Local variables: + * c-basic-offset: 8 + */ diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h index 7dd3db65c80e..2c8942d04222 100644 --- a/drivers/media/dvb/dvb-usb/m920x.h +++ b/drivers/media/dvb/dvb-usb/m920x.h @@ -4,7 +4,7 @@ #define DVB_USB_LOG_PREFIX "m920x" #include "dvb-usb.h" -#define deb_rc(args...) dprintk(dvb_usb_m920x_debug,0x01,args) +#define deb(args...) dprintk(dvb_usb_m920x_debug,0x01,args) #define M9206_CORE 0x22 #define M9206_RC_STATE 0xff51 @@ -59,9 +59,18 @@ What any other bits might mean, or how to get the slave's ACK/NACK response to a write, is unknown. */ -struct m9206_state { +struct m920x_state { u16 filters[M9206_MAX_FILTERS]; int filtering_enabled; int rep_count; }; + +/* Initialisation data for the m920x + */ + +struct m920x_inits { + u16 address; + u8 data; +}; + #endif diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c index 3ecb2e0ce80f..c3fdc7cd094e 100644 --- a/drivers/media/dvb/dvb-usb/vp702x-fe.c +++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c @@ -204,8 +204,8 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe, static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *m) { - //struct vp702x_fe_state *st = fe->demodulator_priv; - u8 cmd[8];//,ibuf[10]; + struct vp702x_fe_state *st = fe->demodulator_priv; + u8 cmd[8],ibuf[10]; memset(cmd,0,8); deb_fe("%s\n",__FUNCTION__); @@ -218,12 +218,12 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, memcpy(&cmd[3], m->msg, m->msg_len); cmd[7] = vp702x_chksum(cmd,0,7); -// vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100); + vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100); -// if (ibuf[2] == 0 && ibuf[3] == 0) -// deb_fe("diseqc cmd failed.\n"); -// else -// deb_fe("diseqc cmd succeeded.\n"); + if (ibuf[2] == 0 && ibuf[3] == 0) + deb_fe("diseqc cmd failed.\n"); + else + deb_fe("diseqc cmd succeeded.\n"); return 0; } diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index 058df5c10034..08a2599ed74a 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -293,12 +293,20 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets) * but no packets have been transfered. * [2] Sometimes (actually very often) NBPACKETS stays at zero * although one packet has been transfered. + * [3] Sometimes (actually rarely), the card gets into an erroneous + * mode where it continuously generates interrupts, claiming it + * has recieved nbpackets>TS_DMA_PACKETS packets, but no packet + * has been transfered. Only a reset seems to solve this */ if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) { unsigned int i = 0; while (pluto->dma_buf[i] == 0x47) i += 188; nbpackets = i / 188; + if (i == 0) { + pluto_reset_ts(pluto, 1); + dev_printk(KERN_DEBUG, &pluto->pdev->dev, "resetting TS because of invalid packet counter\n"); + } } dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets); diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 67becdd4db60..ef1108c0bf11 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -1246,6 +1246,9 @@ static void vpeirq(unsigned long data) if (!budget->feeding1 || (newdma == olddma)) return; + /* Ensure streamed PCI data is synced to CPU */ + pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE); + #if 0 /* track rps1 activity */ printk("vpeirq: %02x Event Counter 1 0x%04x\n", @@ -2679,8 +2682,8 @@ err_iobuf_vfree_6: err_pci_free_5: pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus); err_saa71466_vfree_4: - if (!av7110->grabbing) - saa7146_pgtable_free(pdev, &av7110->pt); + if (av7110->grabbing) + saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt); err_i2c_del_3: i2c_del_adapter(&av7110->i2c_adap); err_dvb_unregister_adapter_2: @@ -2710,7 +2713,7 @@ static int __devexit av7110_detach(struct saa7146_dev* saa) SAA7146_ISR_CLEAR(saa, MASK_10); msleep(50); tasklet_kill(&av7110->vpe_tasklet); - saa7146_pgtable_free(saa->pci, &av7110->pt); + saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt); } av7110_exit_v4l(av7110); diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 4ed4599ce816..9d42f88ebb0e 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -904,7 +904,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc band = 1; } else if (tuner_frequency < 200000000) { cp = 6; - band = 2; + band = 1; } else if (tuner_frequency < 290000000) { cp = 3; band = 2; diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 6b97dc1e6b65..2557ac9620d0 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -195,6 +195,9 @@ static void vpeirq(unsigned long data) u32 newdma = saa7146_read(budget->dev, PCI_VDP3); u32 count; + /* Ensure streamed PCI data is synced to CPU */ + pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE); + /* nearest lower position divisible by 188 */ newdma -= newdma % 188; @@ -504,16 +507,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, strcpy(budget->i2c_adap.name, budget->card->name); if (i2c_add_adapter(&budget->i2c_adap) < 0) { - dvb_unregister_adapter(&budget->dvb_adapter); - return -ENOMEM; + ret = -ENOMEM; + goto err_dvb_unregister; } ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac); - if (NULL == - (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt))) { + budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt); + if (NULL == budget->grabbing) { ret = -ENOMEM; - goto err; + goto err_del_i2c; } saa7146_write(dev, PCI_BT_V1, 0x001c0000); @@ -526,14 +529,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, if (bi->type != BUDGET_FS_ACTIVY) saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); - if (budget_register(budget) == 0) { - return 0; - } -err: - i2c_del_adapter(&budget->i2c_adap); + if (budget_register(budget) == 0) + return 0; /* Everything OK */ + + /* An error occurred, cleanup resources */ + saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt); - vfree(budget->grabbing); +err_del_i2c: + i2c_del_adapter(&budget->i2c_adap); +err_dvb_unregister: dvb_unregister_adapter(&budget->dvb_adapter); return ret; @@ -555,15 +560,13 @@ int ttpci_budget_deinit(struct budget *budget) budget_unregister(budget); - i2c_del_adapter(&budget->i2c_adap); - - dvb_unregister_adapter(&budget->dvb_adapter); - tasklet_kill(&budget->vpe_tasklet); - saa7146_pgtable_free(dev->pci, &budget->pt); + saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt); - vfree(budget->grabbing); + i2c_del_adapter(&budget->i2c_adap); + + dvb_unregister_adapter(&budget->dvb_adapter); return 0; } diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index af66a5d5ecd8..a6ac82a609d4 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -2,8 +2,14 @@ # Multimedia Video device configuration # -menu "Radio Adapters" +menuconfig RADIO_ADAPTERS + bool "Radio Adapters" depends on VIDEO_DEV + default y + ---help--- + Say Y here to enable selecting AM/FM radio adapters. + +if RADIO_ADAPTERS config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" @@ -328,4 +334,5 @@ config USB_DSBR To compile this driver as a module, choose M here: the module will be called dsbr100. -endmenu + +endif # RADIO_ADAPTERS diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 449df1bb00d3..3bd07f7e3774 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -33,6 +33,10 @@ History: + Version 0.42: + Converted dsbr100 to use video_ioctl2 + by Douglas Landgraf <dougsland@gmail.com> + Version 0.41-ac1: Alan Cox: Some cleanups and fixes @@ -121,8 +125,6 @@ devices, that would be 76 and 91. */ static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id); static void usb_dsbr100_disconnect(struct usb_interface *intf); -static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); static int usb_dsbr100_open(struct inode *inode, struct file *file); static int usb_dsbr100_close(struct inode *inode, struct file *file); @@ -142,26 +144,6 @@ struct dsbr100_device { }; -/* File system interface */ -static const struct file_operations usb_dsbr100_fops = { - .owner = THIS_MODULE, - .open = usb_dsbr100_open, - .release = usb_dsbr100_close, - .ioctl = usb_dsbr100_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, -}; - -/* V4L interface */ -static struct video_device dsbr100_videodev_template= -{ - .owner = THIS_MODULE, - .name = "D-Link DSB-R 100", - .type = VID_TYPE_TUNER, - .fops = &usb_dsbr100_fops, - .release = video_device_release, -}; - static struct usb_device_id usb_dsbr100_device_table [] = { { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, { } /* Terminating entry */ @@ -252,37 +234,6 @@ static void dsbr100_getstat(struct dsbr100_device *radio) /* USB subsystem interface begins here */ -/* check if the device is present and register with v4l and -usb if it is */ -static int usb_dsbr100_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct dsbr100_device *radio; - - if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL))) - return -ENOMEM; - if (!(radio->videodev = video_device_alloc())) { - kfree(radio); - return -ENOMEM; - } - memcpy(radio->videodev, &dsbr100_videodev_template, - sizeof(dsbr100_videodev_template)); - radio->removed = 0; - radio->users = 0; - radio->usbdev = interface_to_usbdev(intf); - radio->curfreq = FREQ_MIN*FREQ_MUL; - video_set_drvdata(radio->videodev, radio); - if (video_register_device(radio->videodev, VFL_TYPE_RADIO, - radio_nr)) { - warn("Could not register video device"); - video_device_release(radio->videodev); - kfree(radio); - return -EIO; - } - usb_set_intfdata(intf, radio); - return 0; -} - /* handle unplugging of the device, release data structures if nothing keeps us from doing it. If something is still keeping us busy, the release callback of v4l will take care @@ -307,133 +258,147 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf) } -/* Video for Linux interface */ +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + strlcpy(v->driver, "dsbr100", sizeof(v->driver)); + strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card)); + sprintf(v->bus_info, "ISA"); + v->version = RADIO_VERSION; + v->capabilities = V4L2_CAP_TUNER; + return 0; +} -static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) { - struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); + + if (v->index > 0) + return -EINVAL; + + dsbr100_getstat(radio); + strcpy(v->name, "FM"); + v->type = V4L2_TUNER_RADIO; + v->rangelow = FREQ_MIN*FREQ_MUL; + v->rangehigh = FREQ_MAX*FREQ_MUL; + v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + if(radio->stereo) + v->audmode = V4L2_TUNER_MODE_STEREO; + else + v->audmode = V4L2_TUNER_MODE_MONO; + v->signal = 0xffff; /* We can't get the signal strength */ + return 0; +} - if (!radio) - return -EIO; +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + if (v->index > 0) + return -EINVAL; - switch(cmd) { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *v = arg; - memset(v,0,sizeof(*v)); - strlcpy(v->driver, "dsbr100", sizeof (v->driver)); - strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card)); - sprintf(v->bus_info,"ISA"); - v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + return 0; +} - return 0; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *v = arg; +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); - if (v->index > 0) - return -EINVAL; + radio->curfreq = f->frequency; + if (dsbr100_setfreq(radio, radio->curfreq)==-1) + warn("Set frequency failed"); + return 0; +} - dsbr100_getstat(radio); +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); - memset(v,0,sizeof(*v)); - strcpy(v->name, "FM"); - v->type = V4L2_TUNER_RADIO; + f->type = V4L2_TUNER_RADIO; + f->frequency = radio->curfreq; + return 0; +} - v->rangelow = FREQ_MIN*FREQ_MUL; - v->rangehigh = FREQ_MAX*FREQ_MUL; - v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; - v->capability=V4L2_TUNER_CAP_LOW; - if(radio->stereo) - v->audmode = V4L2_TUNER_MODE_STEREO; - else - v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xFFFF; /* We can't get the signal strength */ +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; + for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { + if (qc->id && qc->id == radio_qctrl[i].id) { + memcpy(qc, &(radio_qctrl[i]), + sizeof(*qc)); return 0; } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *v = arg; - - if (v->index > 0) - return -EINVAL; + } + return -EINVAL; +} - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); - radio->curfreq = f->frequency; - if (dsbr100_setfreq(radio, radio->curfreq)==-1) - warn("Set frequency failed"); - return 0; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value = radio->muted; + return 0; + } + return -EINVAL; +} - f->type = V4L2_TUNER_RADIO; - f->frequency = radio->curfreq; +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); - return 0; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } - } - return -EINVAL; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl= arg; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - ctrl->value=radio->muted; - return 0; - } - return -EINVAL; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl= arg; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) { - if (dsbr100_stop(radio)==-1) - warn("Radio did not respond properly"); - } else { - if (dsbr100_start(radio)==-1) - warn("Radio did not respond properly"); - } - return 0; - } - return -EINVAL; + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) { + if (dsbr100_stop(radio)==-1) + warn("Radio did not respond properly"); + } else { + if (dsbr100_start(radio)==-1) + warn("Radio did not respond properly"); } - default: - return v4l_compat_translate_ioctl(inode,file,cmd,arg, - usb_dsbr100_do_ioctl); + return 0; } + return -EINVAL; } -static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) { - return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl); + if (a->index > 1) + return -EINVAL; + + strcpy(a->name, "Radio"); + a->capability = V4L2_AUDCAP_STEREO; + return 0; +} + +static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + if (i != 0) + return -EINVAL; + return 0; +} + +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index != 0) + return -EINVAL; + return 0; } static int usb_dsbr100_open(struct inode *inode, struct file *file) @@ -465,6 +430,68 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file) return 0; } +/* File system interface */ +static const struct file_operations usb_dsbr100_fops = { + .owner = THIS_MODULE, + .open = usb_dsbr100_open, + .release = usb_dsbr100_close, + .ioctl = video_ioctl2, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; + +/* V4L2 interface */ +static struct video_device dsbr100_videodev_template = +{ + .owner = THIS_MODULE, + .name = "D-Link DSB-R 100", + .type = VID_TYPE_TUNER, + .fops = &usb_dsbr100_fops, + .release = video_device_release, + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, +}; + +/* check if the device is present and register with v4l and +usb if it is */ +static int usb_dsbr100_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct dsbr100_device *radio; + + if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL))) + return -ENOMEM; + if (!(radio->videodev = video_device_alloc())) { + kfree(radio); + return -ENOMEM; + } + memcpy(radio->videodev, &dsbr100_videodev_template, + sizeof(dsbr100_videodev_template)); + radio->removed = 0; + radio->users = 0; + radio->usbdev = interface_to_usbdev(intf); + radio->curfreq = FREQ_MIN*FREQ_MUL; + video_set_drvdata(radio->videodev, radio); + if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) { + warn("Could not register video device"); + video_device_release(radio->videodev); + kfree(radio); + return -EIO; + } + usb_set_intfdata(intf, radio); + return 0; +} + static int __init dsbr100_init(void) { int retval = usb_register(&usb_dsbr100_driver); diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 8fbf0d8bd278..8cf2e9df5c8a 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -48,6 +48,25 @@ #define CADET_VERSION KERNEL_VERSION(0,3,3) +static struct v4l2_queryctrl radio_qctrl[] = { + { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0xff, + .type = V4L2_CTRL_TYPE_INTEGER, + } +}; + static int io=-1; /* default to isapnp activation */ static int radio_nr = -1; static int users=0; @@ -347,135 +366,165 @@ cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) } +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + v->capabilities = + V4L2_CAP_TUNER | + V4L2_CAP_READWRITE; + v->version = CADET_VERSION; + strcpy(v->driver, "ADS Cadet"); + strcpy(v->card, "ADS Cadet"); + return 0; +} -static int cadet_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) { - switch(cmd) - { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - memset(cap,0,sizeof(*cap)); - cap->capabilities = - V4L2_CAP_TUNER | - V4L2_CAP_READWRITE; - cap->version = CADET_VERSION; - strcpy(cap->driver, "ADS Cadet"); - strcpy(cap->card, "ADS Cadet"); - return 0; + v->type = V4L2_TUNER_RADIO; + switch (v->index) { + case 0: + strcpy(v->name, "FM"); + v->capability = V4L2_TUNER_CAP_STEREO; + v->rangelow = 1400; /* 87.5 MHz */ + v->rangehigh = 1728; /* 108.0 MHz */ + v->rxsubchans=cadet_getstereo(); + switch (v->rxsubchans){ + case V4L2_TUNER_SUB_MONO: + v->audmode = V4L2_TUNER_MODE_MONO; + break; + case V4L2_TUNER_SUB_STEREO: + v->audmode = V4L2_TUNER_MODE_STEREO; + break; + default: ; } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - memset(t,0,sizeof(*t)); - t->type = V4L2_TUNER_RADIO; - switch (t->index) - { - case 0: strcpy(t->name, "FM"); - t->capability = V4L2_TUNER_CAP_STEREO; - t->rangelow = 1400; /* 87.5 MHz */ - t->rangehigh = 1728; /* 108.0 MHz */ - t->rxsubchans=cadet_getstereo(); - switch (t->rxsubchans){ - case V4L2_TUNER_SUB_MONO: - t->audmode = V4L2_TUNER_MODE_MONO; - break; - case V4L2_TUNER_SUB_STEREO: - t->audmode = V4L2_TUNER_MODE_STEREO; - break; - default: ; - } - break; - case 1: strcpy(t->name, "AM"); - t->capability = V4L2_TUNER_CAP_LOW; - t->rangelow = 8320; /* 520 kHz */ - t->rangehigh = 26400; /* 1650 kHz */ - t->rxsubchans = V4L2_TUNER_SUB_MONO; - t->audmode = V4L2_TUNER_MODE_MONO; - break; - default: - return -EINVAL; - } + break; + case 1: + strcpy(v->name, "AM"); + v->capability = V4L2_TUNER_CAP_LOW; + v->rangelow = 8320; /* 520 kHz */ + v->rangehigh = 26400; /* 1650 kHz */ + v->rxsubchans = V4L2_TUNER_SUB_MONO; + v->audmode = V4L2_TUNER_MODE_MONO; + break; + default: + return -EINVAL; + } + v->signal = sigstrength; /* We might need to modify scaling of this */ + return 0; +} - t->signal = sigstrength; /* We might need to modify scaling of this */ - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *t = arg; - if((t->index != 0)&&(t->index != 1)) - return -EINVAL; +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + if((v->index != 0)&&(v->index != 1)) + return -EINVAL; + curtuner = v->index; + return 0; +} - curtuner = t->index; - return 0; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; - memset(f,0,sizeof(*f)); - f->tuner = curtuner; - f->type = V4L2_TUNER_RADIO; - f->frequency = cadet_getfreq(); - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - if (f->type != V4L2_TUNER_RADIO){ - return -EINVAL; - } - if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) { - return -EINVAL; - } - if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) { - return -EINVAL; - } - cadet_setfreq(f->frequency); - return 0; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *c = arg; - switch (c->id){ - case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ - c->value = (cadet_getvol() == 0); - break; - case V4L2_CID_AUDIO_VOLUME: - c->value = cadet_getvol(); - break; - default: - return -EINVAL; - } - return 0; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *c = arg; - switch (c->id){ - case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ - if (c->value) cadet_setvol(0); - else cadet_setvol(0xffff); - break; - case V4L2_CID_AUDIO_VOLUME: - cadet_setvol(c->value); - break; - default: - return -EINVAL; - } +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + f->tuner = curtuner; + f->type = V4L2_TUNER_RADIO; + f->frequency = cadet_getfreq(); + return 0; +} + + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + if (f->type != V4L2_TUNER_RADIO) + return -EINVAL; + if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) + return -EINVAL; + if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) + return -EINVAL; + cadet_setfreq(f->frequency); + return 0; +} + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { + if (qc->id && qc->id == radio_qctrl[i].id) { + memcpy(qc, &(radio_qctrl[i]), + sizeof(*qc)); return 0; } + } + return -EINVAL; +} - default: - return -ENOIOCTLCMD; +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + switch (ctrl->id){ + case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ + ctrl->value = (cadet_getvol() == 0); + break; + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = cadet_getvol(); + break; + default: + return -EINVAL; } + return 0; } -static int -cadet_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) { - return video_usercopy(inode, file, cmd, arg, cadet_do_ioctl); + switch (ctrl->id){ + case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ + if (ctrl->value) + cadet_setvol(0); + else + cadet_setvol(0xffff); + break; + case V4L2_CID_AUDIO_VOLUME: + cadet_setvol(ctrl->value); + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index > 1) + return -EINVAL; + strcpy(a->name, "Radio"); + a->capability = V4L2_AUDCAP_STEREO; + return 0; +} + +static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + if (i != 0) + return -EINVAL; + return 0; +} + +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index != 0) + return -EINVAL; + return 0; } static int @@ -512,7 +561,7 @@ static const struct file_operations cadet_fops = { .open = cadet_open, .release = cadet_release, .read = cadet_read, - .ioctl = cadet_ioctl, + .ioctl = video_ioctl2, .poll = cadet_poll, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, @@ -524,6 +573,18 @@ static struct video_device cadet_radio= .name = "Cadet radio", .type = VID_TYPE_TUNER, .fops = &cadet_fops, + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, }; static struct pnp_device_id cadet_pnp_devices[] = { diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 11f80cacd6ed..8e33a19a22a3 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -24,7 +24,6 @@ #include <linux/delay.h> #include <asm/io.h> #include <asm/uaccess.h> -#include <linux/mutex.h> #include <linux/pci.h> #include <linux/videodev2.h> #include <media/v4l2-common.h> @@ -110,7 +109,6 @@ struct radio_device { muted, /* VIDEO_AUDIO_MUTE */ stereo, /* VIDEO_TUNER_STEREO_ON */ tuned; /* signal strength (0 or 0xffff) */ - struct mutex lock; }; static u32 radio_bits_get(struct radio_device *dev) @@ -394,7 +392,6 @@ static int __devinit maestro_probe(struct pci_dev *pdev, } radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA; - mutex_init(&radio_unit->lock); maestro_radio_inst = video_device_alloc(); if (maestro_radio_inst == NULL) { diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index a4715901512d..203f4373eeb8 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -410,7 +410,6 @@ static struct video_device zoltrix_radio = .owner = THIS_MODULE, .name = "Zoltrix Radio Plus", .type = VID_TYPE_TUNER, - .hardware = 0, .fops = &zoltrix_fops, .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index bc773781993a..5cb3f54b548b 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -2,14 +2,19 @@ # Multimedia Video device configuration # -menu "Video Capture Adapters" +menuconfig VIDEO_CAPTURE_DRIVERS + bool "Video capture adapters" depends on VIDEO_DEV + default y + ---help--- + Say Y here to enable selecting the video adapters for + webcams, analog TV, and hybrid analog/digital TV. + Some of those devices also supports FM radio. -comment "Video Capture Adapters" +if VIDEO_CAPTURE_DRIVERS config VIDEO_ADV_DEBUG bool "Enable advanced debug functionality" - depends on VIDEO_DEV default n ---help--- Say Y here to enable advanced debugging functionality on some @@ -34,7 +39,7 @@ config VIDEO_HELPER_CHIPS_AUTO # menu "Encoders/decoders and other helper chips" - depends on VIDEO_DEV && !VIDEO_HELPER_CHIPS_AUTO + depends on !VIDEO_HELPER_CHIPS_AUTO comment "Audio decoders" @@ -61,7 +66,7 @@ config VIDEO_TDA7432 config VIDEO_TDA9840 tristate "Philips TDA9840 audio processor" - depends on VIDEO_DEV && I2C + depends on I2C ---help--- Support for tda9840 audio decoder chip found on some Zoran boards. @@ -79,7 +84,7 @@ config VIDEO_TDA9875 config VIDEO_TEA6415C tristate "Philips TEA6415C audio processor" - depends on VIDEO_DEV && I2C + depends on I2C ---help--- Support for tea6415c audio decoder chip found on some bt8xx boards. @@ -88,7 +93,7 @@ config VIDEO_TEA6415C config VIDEO_TEA6420 tristate "Philips TEA6420 audio processor" - depends on VIDEO_DEV && I2C + depends on I2C ---help--- Support for tea6420 audio decoder chip found on some bt8xx boards. @@ -469,7 +474,7 @@ config VIDEO_SAA5246A config VIDEO_SAA5249 tristate "SAA5249 Teletext processor" - depends on VIDEO_DEV && I2C && VIDEO_V4L2 + depends on I2C && VIDEO_V4L2 help Support for I2C bus based teletext using the SAA5249 chip. At the moment this is only useful on some European WinTV cards. @@ -479,7 +484,7 @@ config VIDEO_SAA5249 config TUNER_3036 tristate "SAB3036 tuner" - depends on VIDEO_DEV && I2C && VIDEO_V4L1 + depends on I2C && VIDEO_V4L1 help Say Y here to include support for Philips SAB3036 compatible tuners. If in doubt, say N. @@ -681,8 +686,12 @@ config VIDEO_CAFE_CCIC # USB Multimedia device configuration # -menu "V4L USB devices" - depends on USB && VIDEO_DEV +menuconfig V4L_USB_DRIVERS + bool "V4L USB devices" + depends on USB + default y + +if V4L_USB_DRIVERS source "drivers/media/video/pvrusb2/Kconfig" @@ -707,7 +716,7 @@ config VIDEO_OVCAMCHIP config USB_W9968CF tristate "USB W996[87]CF JPEG Dual Mode Camera support" - depends on USB && VIDEO_V4L1 && I2C + depends on VIDEO_V4L1 && I2C select VIDEO_OVCAMCHIP ---help--- Say Y here if you want support for cameras based on OV681 or @@ -725,7 +734,7 @@ config USB_W9968CF config USB_OV511 tristate "USB OV511 Camera support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See <file:Documentation/video4linux/ov511.txt> @@ -736,7 +745,7 @@ config USB_OV511 config USB_SE401 tristate "USB SE401 Camera support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See <file:Documentation/video4linux/se401.txt> @@ -749,7 +758,7 @@ source "drivers/media/video/sn9c102/Kconfig" config USB_STV680 tristate "USB STV680 (Pencam) Camera support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. This includes the Pencam line of cameras. @@ -765,7 +774,7 @@ source "drivers/media/video/pwc/Kconfig" config USB_ZR364XX tristate "USB ZR364XX Camera support" - depends on USB && VIDEO_V4L2 + depends on VIDEO_V4L2 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. @@ -775,6 +784,6 @@ config USB_ZR364XX To compile this driver as a module, choose M here: the module will be called zr364xx. -endmenu # V4L USB devices +endif # V4L_USB_DRIVERS -endmenu +endif # VIDEO_CAPTURE_DRIVERS diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 1757a588970f..67bda9f9a44b 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -555,7 +555,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) { struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; - int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); + int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -567,7 +567,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; - Vlines = pix->height + (is_pal ? 4 : 7); + Vlines = pix->height + (is_50Hz ? 4 : 7); if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 2ebde2fdbcbe..543b05ebc0e7 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -28,6 +28,7 @@ #include <linux/device.h> #include <linux/dma-mapping.h> #include <linux/interrupt.h> +#include <linux/dma-mapping.h> #include <asm/delay.h> #include "cx88.h" @@ -612,7 +613,7 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board } /* Driver asked for hardware access. */ -int cx8802_request_acquire(struct cx8802_driver *drv) +static int cx8802_request_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; @@ -632,7 +633,7 @@ int cx8802_request_acquire(struct cx8802_driver *drv) } /* Driver asked to release hardware. */ -int cx8802_request_release(struct cx8802_driver *drv) +static int cx8802_request_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index b94ef8ab28c1..98fa35421bdd 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -36,6 +36,7 @@ #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/kthread.h> +#include <linux/dma-mapping.h> #include <asm/div64.h> #include "cx88.h" diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c index 6068c9bf82cd..82bc3a28aa22 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -111,10 +111,6 @@ static struct i2c_adapter vp3054_i2c_adap_template = { .id = I2C_HW_B_CX2388x, }; -static struct i2c_client vp3054_i2c_client_template = { - .name = "VP-3054", -}; - int vp3054_i2c_probe(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; @@ -133,8 +129,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) sizeof(vp3054_i2c->adap)); memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, sizeof(vp3054_i2c->algo)); - memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template, - sizeof(vp3054_i2c->client)); vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL; @@ -144,7 +138,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) vp3054_i2c->algo.data = dev; i2c_set_adapdata(&vp3054_i2c->adap, dev); vp3054_i2c->adap.algo_data = &vp3054_i2c->algo; - vp3054_i2c->client.adapter = &vp3054_i2c->adap; vp3054_bit_setscl(dev,1); vp3054_bit_setsda(dev,1); diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h index b7a0a04d2423..637a7d232238 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.h +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h @@ -26,7 +26,6 @@ struct vp3054_i2c_state { struct i2c_adapter adap; struct i2c_algo_bit_data algo; - struct i2c_client client; u32 state; }; diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 9285a58e47aa..3823b62da4a4 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_EM28XX tristate "Empia EM2800/2820/2840 USB video capture support" - depends on VIDEO_V4L1 && USB && I2C + depends on VIDEO_V4L1 && I2C select VIDEO_BUF select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig index c6bff705688d..664676f44068 100644 --- a/drivers/media/video/et61x251/Kconfig +++ b/drivers/media/video/et61x251/Kconfig @@ -1,6 +1,6 @@ config USB_ET61X251 tristate "USB ET61X[12]51 PC Camera Controller support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on Etoms ET61X151 or ET61X251 PC Camera Controllers. diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 45b9328a538f..e29f949adf57 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -74,7 +74,7 @@ int ivtv_first_minor = 0; struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; /* Protects ivtv_cards_active */ -spinlock_t ivtv_cards_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(ivtv_cards_lock); /* add your revision and whatnot here */ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 1637097ddec7..8976487a65f3 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -804,7 +804,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) struct ivtv_open_id *item; struct ivtv *itv = NULL; struct ivtv_stream *s = NULL; - int minor = MINOR(inode->i_rdev); + int minor = iminor(inode); /* Find which card this open was on */ spin_lock(&ivtv_cards_lock); diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 5645c9318890..d0c2cd785430 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -1,6 +1,6 @@ config VIDEO_PVRUSB2 tristate "Hauppauge WinTV-PVR USB2 support" - depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && I2C && EXPERIMENTAL select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 5669c8ca9ca3..20b614436d2c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -391,22 +391,29 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) int pvr2_encoder_configure(struct pvr2_hdw *hdw) { int ret; + int val; pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure" " (cx2341x module)"); hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING; hdw->enc_ctl_state.width = hdw->res_hor_val; hdw->enc_ctl_state.height = hdw->res_ver_val; - hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & - (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ? + hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ? 0 : 1); ret = 0; ret |= pvr2_encoder_prep_config(hdw); + /* saa7115: 0xf0 */ + val = 0xf0; + if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { + /* ivtv cx25840: 0x140 */ + val = 0x140; + } + if (!ret) ret = pvr2_encoder_vcmd( hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, - 0xf0, 0xf0); + val, val); /* setup firmware to notify us about some events (don't know why...) */ if (!ret) ret = pvr2_encoder_vcmd( diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index acf651e01f94..1311891e7ee3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -83,7 +83,7 @@ static struct pvr2_string_table pvr2_client_lists[] = { }; static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; -static DECLARE_MUTEX(pvr2_unit_sem); +static DEFINE_MUTEX(pvr2_unit_mtx); static int ctlchg = 0; static int initusbreset = 1; @@ -2076,14 +2076,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); if (!hdw->ctl_read_urb) goto fail; - down(&pvr2_unit_sem); do { + mutex_lock(&pvr2_unit_mtx); do { for (idx = 0; idx < PVR_NUM; idx++) { if (unit_pointers[idx]) continue; hdw->unit_number = idx; unit_pointers[idx] = hdw; break; } - } while (0); up(&pvr2_unit_sem); + } while (0); mutex_unlock(&pvr2_unit_mtx); cnt1 = 0; cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2"); @@ -2186,13 +2186,13 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) } pvr2_i2c_core_done(hdw); pvr2_hdw_remove_usb_stuff(hdw); - down(&pvr2_unit_sem); do { + mutex_lock(&pvr2_unit_mtx); do { if ((hdw->unit_number >= 0) && (hdw->unit_number < PVR_NUM) && (unit_pointers[hdw->unit_number] == hdw)) { unit_pointers[hdw->unit_number] = NULL; } - } while (0); up(&pvr2_unit_sem); + } while (0); mutex_unlock(&pvr2_unit_mtx); kfree(hdw->controls); kfree(hdw->mpeg_ctrl_info); kfree(hdw->std_defs); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 58fc3c730fe1..6786d3c0c98b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -23,6 +23,7 @@ #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" +#include "pvrusb2.h" #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) @@ -38,6 +39,10 @@ static unsigned int i2c_scan = 0; module_param(i2c_scan, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); +static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 }; +module_param_array(ir_mode, int, NULL, 0444); +MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR"); + static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, unsigned int detail, char *buf,unsigned int maxlen); @@ -273,6 +278,15 @@ static int i2c_hack_wm8775(struct pvr2_hdw *hdw, return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen); } +/* This is an entry point designed to always fail any attempt to perform a + transfer. We use this to cause certain I2C addresses to not be + probed. */ +static int i2c_black_hole(struct pvr2_hdw *hdw, + u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) +{ + return -EIO; +} + /* This is a special entry point that is entered if an I2C operation is attempted to a cx25840 chip on model 24xxx hardware. This chip can sometimes wedge itself. Worse still, when this happens msp3400 can @@ -994,10 +1008,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) } /* However, deal with various special cases for 24xxx hardware. */ + if (ir_mode[hdw->unit_number] == 0) { + printk(KERN_INFO "%s: IR disabled\n",hdw->name); + hdw->i2c_func[0x18] = i2c_black_hole; + } else if (ir_mode[hdw->unit_number] == 1) { + if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { + hdw->i2c_func[0x18] = i2c_24xxx_ir; + } + } if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { hdw->i2c_func[0x1b] = i2c_hack_wm8775; hdw->i2c_func[0x44] = i2c_hack_cx25840; - hdw->i2c_func[0x18] = i2c_24xxx_ir; } // Configure the adapter and set up everything else related to it. diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index a741c556a39a..7ab79baa1c8c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -518,40 +518,32 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) } sfp->item_last = cip; - cip->attr_name.attr.owner = THIS_MODULE; cip->attr_name.attr.name = "name"; cip->attr_name.attr.mode = S_IRUGO; cip->attr_name.show = fp->show_name; - cip->attr_type.attr.owner = THIS_MODULE; cip->attr_type.attr.name = "type"; cip->attr_type.attr.mode = S_IRUGO; cip->attr_type.show = fp->show_type; - cip->attr_min.attr.owner = THIS_MODULE; cip->attr_min.attr.name = "min_val"; cip->attr_min.attr.mode = S_IRUGO; cip->attr_min.show = fp->show_min; - cip->attr_max.attr.owner = THIS_MODULE; cip->attr_max.attr.name = "max_val"; cip->attr_max.attr.mode = S_IRUGO; cip->attr_max.show = fp->show_max; - cip->attr_val.attr.owner = THIS_MODULE; cip->attr_val.attr.name = "cur_val"; cip->attr_val.attr.mode = S_IRUGO; - cip->attr_custom.attr.owner = THIS_MODULE; cip->attr_custom.attr.name = "custom_val"; cip->attr_custom.attr.mode = S_IRUGO; - cip->attr_enum.attr.owner = THIS_MODULE; cip->attr_enum.attr.name = "enum_val"; cip->attr_enum.attr.mode = S_IRUGO; cip->attr_enum.show = fp->show_enum; - cip->attr_bits.attr.owner = THIS_MODULE; cip->attr_bits.attr.name = "bit_val"; cip->attr_bits.attr.mode = S_IRUGO; cip->attr_bits.show = fp->show_bits; @@ -616,12 +608,10 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) dip = kzalloc(sizeof(*dip),GFP_KERNEL); if (!dip) return; - dip->attr_debugcmd.attr.owner = THIS_MODULE; dip->attr_debugcmd.attr.name = "debugcmd"; dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP; dip->attr_debugcmd.show = debugcmd_show; dip->attr_debugcmd.store = debugcmd_store; - dip->attr_debuginfo.attr.owner = THIS_MODULE; dip->attr_debuginfo.attr.name = "debuginfo"; dip->attr_debuginfo.attr.mode = S_IRUGO; dip->attr_debuginfo.show = debuginfo_show; @@ -811,7 +801,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, return; } - sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE; sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number"; sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_minor_number.show = v4l_minor_number_show; @@ -825,7 +814,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->v4l_minor_number_created_ok = !0; } - sfp->attr_v4l_radio_minor_number.attr.owner = THIS_MODULE; sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number"; sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show; @@ -839,7 +827,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->v4l_radio_minor_number_created_ok = !0; } - sfp->attr_unit_number.attr.owner = THIS_MODULE; sfp->attr_unit_number.attr.name = "unit_number"; sfp->attr_unit_number.attr.mode = S_IRUGO; sfp->attr_unit_number.show = unit_number_show; @@ -852,7 +839,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->unit_number_created_ok = !0; } - sfp->attr_bus_info.attr.owner = THIS_MODULE; sfp->attr_bus_info.attr.name = "bus_info_str"; sfp->attr_bus_info.attr.mode = S_IRUGO; sfp->attr_bus_info.show = bus_info_show; diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 8fdf7101d3bf..7298cf2e1650 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig @@ -1,6 +1,6 @@ config USB_PWC tristate "USB Philips Cameras" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y or M here if you want to use one of these Philips & OEM webcams: diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 4ea479baee74..50f15adfa7c8 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -1170,6 +1170,42 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }, }, + [SAA7134_BOARD_ECS_TVP3XP_4CB6] = { + /* Barry Scott <barry.scott@onelan.co.uk> */ + .name = "Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_PHILIPS_PAL_I, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = "CVid over SVid", + .vmux = 0, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, [SAA7134_BOARD_AVACSSMARTTV] = { /* Roman Pszonczenko <romka@kolos.math.uni.lodz.pl> */ .name = "AVACS SmartTV", @@ -2754,6 +2790,35 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_KWORLD_DVBT_210] = { + .name = "KWorld DVB-T 210", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 1 << 21, + .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 = TV, + .gpio = 0x0200000, + }, + }, [SAA7134_BOARD_KWORLD_ATSC110] = { .name = "Kworld ATSC110", .audio_clock = 0x00187de7, @@ -3407,6 +3472,36 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, + [SAA7134_BOARD_SABRENT_TV_PCB05] = { + .name = "Sabrent PCMCIA TV-PCB05", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_comp2, + .vmux = 0, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .mute = { + .name = name_mute, + .amux = TV, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3515,7 +3610,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5168, /* Animation Technologies (LifeView) */ - .subdevice = 0x0214, /* Standard PCI, LR214WF */ + .subdevice = 0x0214, /* Standard PCI, LR214 Rev E and earlier (SAA7135) */ + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5168, /* Animation Technologies (LifeView) */ + .subdevice = 0x5214, /* Standard PCI, LR214 Rev F onwards (SAA7131) */ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, },{ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3689,6 +3790,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1019, + .subdevice = 0x4cb6, + .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB6, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x12ab, .subdevice = 0x0800, @@ -3915,6 +4022,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_TEVION_DVBT_220RF, },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x17de, + .subdevice = 0x7250, + .driver_data = SAA7134_BOARD_KWORLD_DVBT_210, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ .subvendor = 0x17de, .subdevice = 0x7350, @@ -4100,6 +4213,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x4857, .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x0919, /* SinoVideo PCI 2309 Proteus (7134) */ + .subdevice = 0x2003, /* OEM cardbus */ + .driver_data = SAA7134_BOARD_SABRENT_TV_PCB05, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -4178,6 +4297,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_CINERGY600_MK3: case SAA7134_BOARD_ECS_TVP3XP: case SAA7134_BOARD_ECS_TVP3XP_4CB5: + case SAA7134_BOARD_ECS_TVP3XP_4CB6: case SAA7134_BOARD_MD2819: case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: case SAA7134_BOARD_KWORLD_XPERT: @@ -4426,6 +4546,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_PINNACLE_PCTV_310i: + case SAA7134_BOARD_KWORLD_DVBT_210: case SAA7134_BOARD_TEVION_DVBT_220RF: case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 65aec881bbde..e0eec80088c7 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -887,6 +887,20 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = { .antenna_switch= 2, .request_firmware = philips_tda1004x_request_firmware }; +static struct tda1004x_config kworld_dvb_t_210_config = { + .demod_address = 0x08, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, + .if_freq = TDA10046_FREQ_045, + .i2c_gate = 0x4b, + .tuner_address = 0x61, + .tuner_config = 2, + .antenna_switch= 1, + .request_firmware = philips_tda1004x_request_firmware +}; /* ------------------------------------------------------------------ * special case: this card uses saa713x GPIO22 for the mode switch */ @@ -1039,6 +1053,9 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; } break; + case SAA7134_BOARD_KWORLD_DVBT_210: + configure_tda827x_fe(dev, &kworld_dvb_t_210_config); + break; case SAA7134_BOARD_PHILIPS_TIGER: configure_tda827x_fe(dev, &philips_tiger_config); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 62224cc958f1..15623b27ad2e 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -235,6 +235,9 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_M102 110 #define SAA7134_BOARD_ASUS_P7131_4871 111 #define SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA 112 +#define SAA7134_BOARD_ECS_TVP3XP_4CB6 113 +#define SAA7134_BOARD_KWORLD_DVBT_210 114 +#define SAA7134_BOARD_SABRENT_TV_PCB05 115 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig index 19204f5686e1..f71f272776de 100644 --- a/drivers/media/video/sn9c102/Kconfig +++ b/drivers/media/video/sn9c102/Kconfig @@ -1,6 +1,6 @@ config USB_SN9C102 tristate "USB SN9C1xx PC Camera Controller support" - depends on USB && VIDEO_V4L2 + depends on VIDEO_V4L2 ---help--- Say Y here if you want support for cameras based on SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h index 680e74634527..11fcb49f5b99 100644 --- a/drivers/media/video/sn9c102/sn9c102.h +++ b/drivers/media/video/sn9c102/sn9c102.h @@ -141,7 +141,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) void sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + const struct sn9c102_sensor* sensor) { memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); } diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 89f83354de3b..74a204f8ebc8 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -48,8 +48,8 @@ #define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia" #define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" #define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.39" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 39) +#define SN9C102_MODULE_VERSION "1:1.44" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 44) /*****************************************************************************/ @@ -209,38 +209,41 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam) } /*****************************************************************************/ + /* - * Write a sequence of count value/register pairs. Returns -1 after the - * first failed write, or 0 for no errors. - */ + Write a sequence of count value/register pairs. Returns -1 after the first + failed write, or 0 for no errors. +*/ int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2], int count) { struct usb_device* udev = cam->usbdev; - u8* value = cam->control_buffer; /* Needed for DMA'able memory */ + u8* buff = cam->control_buffer; int i, res; for (i = 0; i < count; i++) { u8 index = valreg[i][1]; /* - * index is a u8, so it must be <256 and can't be out of range. - * If we put in a check anyway, gcc annoys us with a warning - * that our check is useless. People get all uppity when they - * see warnings in the kernel compile. - */ - - *value = valreg[i][0]; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x08, 0x41, index, 0, - value, 1, SN9C102_CTRL_TIMEOUT); + index is a u8, so it must be <256 and can't be out of range. + If we put in a check anyway, gcc annoys us with a warning + hat our check is useless. People get all uppity when they + see warnings in the kernel compile. + */ + + *buff = valreg[i][0]; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, + 0x41, index, 0, buff, 1, + SN9C102_CTRL_TIMEOUT); + if (res < 0) { DBG(3, "Failed to write a register (value 0x%02X, " - "index 0x%02X, error %d)", *value, index, res); + "index 0x%02X, error %d)", *buff, index, res); return -1; } - cam->reg[index] = *value; + cam->reg[index] = *buff; } return 0; @@ -272,8 +275,8 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index) } -/* NOTE: reading some registers always returns 0 */ -static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) +/* NOTE: with the SN9C10[123] reading some registers always returns 0 */ +int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) { struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; @@ -299,7 +302,8 @@ int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index) static int -sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) +sn9c102_i2c_wait(struct sn9c102_device* cam, + const struct sn9c102_sensor* sensor) { int i, r; @@ -320,7 +324,7 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) static int sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + const struct sn9c102_sensor* sensor) { int r , err = 0; @@ -342,7 +346,7 @@ sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, static int sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + const struct sn9c102_sensor* sensor) { int r; r = sn9c102_read_reg(cam, 0x08); @@ -352,12 +356,12 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, u8 data1, - u8 n, u8 buffer[]) + const struct sn9c102_sensor* sensor, u8 data0, + u8 data1, u8 n, u8 buffer[]) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; - int err = 0, res; + int i = 0, err = 0, res; /* Write cycle */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | @@ -402,7 +406,8 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, } if (buffer) - memcpy(buffer, data, sizeof(buffer)); + for (i = 0; i < n && i < 5; i++) + buffer[n-i-1] = data[4-i]; return (int)data[4]; } @@ -410,7 +415,7 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, u8 data0, + const struct sn9c102_sensor* sensor, u8 n, u8 data0, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5) { struct usb_device* udev = cam->usbdev; @@ -449,7 +454,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, int sn9c102_i2c_try_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address) + const struct sn9c102_sensor* sensor, u8 address) { return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, address, 1, NULL); @@ -458,7 +463,7 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam, int sn9c102_i2c_try_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address, u8 value) + const struct sn9c102_sensor* sensor, u8 address, u8 value) { return sn9c102_i2c_try_raw_write(cam, sensor, 3, sensor->i2c_slave_id, address, @@ -657,16 +662,6 @@ sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f) } -static void -sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f) -{ - static const u8 eoi_marker[2] = {0xff, 0xd9}; - - memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker)); - f->buf.bytesused += sizeof(eoi_marker); -} - - static void sn9c102_urb_complete(struct urb *urb) { struct sn9c102_device* cam = urb->context; @@ -3181,14 +3176,14 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, static const struct file_operations sn9c102_fops = { .owner = THIS_MODULE, - .open = sn9c102_open, + .open = sn9c102_open, .release = sn9c102_release, - .ioctl = sn9c102_ioctl, + .ioctl = sn9c102_ioctl, .compat_ioctl = v4l_compat_ioctl32, - .read = sn9c102_read, - .poll = sn9c102_poll, - .mmap = sn9c102_mmap, - .llseek = no_llseek, + .read = sn9c102_read, + .poll = sn9c102_poll, + .mmap = sn9c102_mmap, + .llseek = no_llseek, }; /*****************************************************************************/ @@ -3251,7 +3246,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) break; } - for (i = 0; sn9c102_sensor_table[i]; i++) { + for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) { err = sn9c102_sensor_table[i](cam); if (!err) break; @@ -3262,7 +3257,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(3, "Support for %s maintained by %s", cam->sensor.name, cam->sensor.maintainer); } else { - DBG(1, "No supported image sensor detected"); + DBG(1, "No supported image sensor detected for this bridge"); err = -ENODEV; goto fail; } diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index f49bd8c5b86e..916054faf9be 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -86,6 +86,8 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, /* SN9C105 */ + { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, + { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, @@ -100,6 +102,7 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, /* SN9C120 */ + { SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, @@ -148,7 +151,6 @@ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ - NULL, }; #endif /* _SN9C102_DEVTABLE_H_ */ diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index 28a861aed044..eaf9ad0dc8a6 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c @@ -144,7 +144,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor hv7131d = { +static const struct sn9c102_sensor hv7131d = { .name = "HV7131D", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, @@ -248,12 +248,10 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam) err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, {0x28, 0x17}); - if (err) - return -EIO; r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00); r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01); - if (r0 < 0 || r1 < 0) + if (err || r0 < 0 || r1 < 0) return -EIO; if (r0 != 0x00 || r1 != 0x04) diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c index 5a495baa5f95..0fc401223cfc 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131r.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c @@ -44,7 +44,6 @@ static int hv7131r_init(struct sn9c102_device* cam) {0xb0, 0x2b}, {0xc0, 0x2c}, {0xd0, 0x2d}, {0xe0, 0x2e}, {0xf0, 0x2f}, {0xff, 0x30}); - break; case BRIDGE_SN9C105: case BRIDGE_SN9C120: @@ -254,7 +253,7 @@ static int hv7131r_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor hv7131r = { +static const struct sn9c102_sensor hv7131r = { .name = "HV7131R", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120, @@ -350,11 +349,8 @@ int sn9c102_probe_hv7131r(struct sn9c102_device* cam) {0x34, 0x01}, {0x20, 0x17}, {0x34, 0x01}, {0x46, 0x01}); - if (err) - return -EIO; - devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00); - if (devid < 0) + if (err || devid < 0) return -EIO; if (devid != 0x02) diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c index 9200845d011b..00b134ca0a3d 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c @@ -55,45 +55,45 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { struct sn9c102_sensor* s = sn9c102_get_sensor(cam); - u8 data[5+1]; + u8 data[2]; switch (ctrl->id) { case V4L2_CID_EXPOSURE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2, + data) < 0) return -EIO; - ctrl->value = data[2]; + ctrl->value = data[0]; return 0; case V4L2_CID_GAIN: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2, + data) < 0) return -EIO; break; case V4L2_CID_HFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = data[3] & 0x20 ? 1 : 0; + ctrl->value = data[1] & 0x20 ? 1 : 0; return 0; case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = data[3] & 0x80 ? 1 : 0; + ctrl->value = data[1] & 0x80 ? 1 : 0; return 0; case V4L2_CID_RED_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2, + data) < 0) return -EIO; break; case V4L2_CID_BLUE_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2, + data) < 0) return -EIO; break; case SN9C102_V4L2_CID_GREEN_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2, + data) < 0) return -EIO; break; default: @@ -105,7 +105,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, case V4L2_CID_RED_BALANCE: case V4L2_CID_BLUE_BALANCE: case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = data[3] | (data[2] << 8); + ctrl->value = data[1] | (data[0] << 8); if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) ctrl->value -= 0x10; else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) @@ -223,7 +223,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor mi0343 = { +static const struct sn9c102_sensor mi0343 = { .name = "MI-0343", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, @@ -332,20 +332,17 @@ static struct sn9c102_sensor mi0343 = { int sn9c102_probe_mi0343(struct sn9c102_device* cam) { - u8 data[5+1]; - int err = 0; - - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17}); + u8 data[2]; - if (err) + if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17})) return -EIO; if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, 2, data) < 0) return -EIO; - if (data[4] != 0x32 || data[3] != 0xe3) + if (data[1] != 0x42 || data[0] != 0xe3) return -ENODEV; sn9c102_attach_sensor(cam, &mi0343); diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c index 64698acb0b15..f8d81d82e8d5 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0360.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c @@ -27,20 +27,105 @@ static int mi0360_init(struct sn9c102_device* cam) struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; - err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, - {0x0a, 0x14}, {0x40, 0x01}, - {0x20, 0x17}, {0x07, 0x18}, - {0xa0, 0x19}, {0x02, 0x1c}, - {0x03, 0x1d}, {0x0f, 0x1e}, - {0x0c, 0x1f}, {0x00, 0x20}, - {0x10, 0x21}, {0x20, 0x22}, - {0x30, 0x23}, {0x40, 0x24}, - {0x50, 0x25}, {0x60, 0x26}, - {0x70, 0x27}, {0x80, 0x28}, - {0x90, 0x29}, {0xa0, 0x2a}, - {0xb0, 0x2b}, {0xc0, 0x2c}, - {0xd0, 0x2d}, {0xe0, 0x2e}, - {0xf0, 0x2f}, {0xff, 0x30}); + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, + {0x0a, 0x14}, {0x40, 0x01}, + {0x20, 0x17}, {0x07, 0x18}, + {0xa0, 0x19}, {0x02, 0x1c}, + {0x03, 0x1d}, {0x0f, 0x1e}, + {0x0c, 0x1f}, {0x00, 0x20}, + {0x10, 0x21}, {0x20, 0x22}, + {0x30, 0x23}, {0x40, 0x24}, + {0x50, 0x25}, {0x60, 0x26}, + {0x70, 0x27}, {0x80, 0x28}, + {0x90, 0x29}, {0xa0, 0x2a}, + {0xb0, 0x2b}, {0xc0, 0x2c}, + {0xd0, 0x2d}, {0xe0, 0x2e}, + {0xf0, 0x2f}, {0xff, 0x30}); + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02}, + {0x00, 0x03}, {0x1a, 0x04}, + {0x50, 0x05}, {0x20, 0x06}, + {0x10, 0x07}, {0x03, 0x10}, + {0x08, 0x14}, {0xa2, 0x17}, + {0x47, 0x18}, {0x00, 0x19}, + {0x1d, 0x1a}, {0x10, 0x1b}, + {0x02, 0x1c}, {0x03, 0x1d}, + {0x0f, 0x1e}, {0x0c, 0x1f}, + {0x00, 0x20}, {0x29, 0x21}, + {0x40, 0x22}, {0x54, 0x23}, + {0x66, 0x24}, {0x76, 0x25}, + {0x85, 0x26}, {0x94, 0x27}, + {0xa1, 0x28}, {0xae, 0x29}, + {0xbb, 0x2a}, {0xc7, 0x2b}, + {0xd3, 0x2c}, {0xde, 0x2d}, + {0xea, 0x2e}, {0xf4, 0x2f}, + {0xff, 0x30}, {0x00, 0x3F}, + {0xC7, 0x40}, {0x01, 0x41}, + {0x44, 0x42}, {0x00, 0x43}, + {0x44, 0x44}, {0x00, 0x45}, + {0x44, 0x46}, {0x00, 0x47}, + {0xC7, 0x48}, {0x01, 0x49}, + {0xC7, 0x4A}, {0x01, 0x4B}, + {0xC7, 0x4C}, {0x01, 0x4D}, + {0x44, 0x4E}, {0x00, 0x4F}, + {0x44, 0x50}, {0x00, 0x51}, + {0x44, 0x52}, {0x00, 0x53}, + {0xC7, 0x54}, {0x01, 0x55}, + {0xC7, 0x56}, {0x01, 0x57}, + {0xC7, 0x58}, {0x01, 0x59}, + {0x44, 0x5A}, {0x00, 0x5B}, + {0x44, 0x5C}, {0x00, 0x5D}, + {0x44, 0x5E}, {0x00, 0x5F}, + {0xC7, 0x60}, {0x01, 0x61}, + {0xC7, 0x62}, {0x01, 0x63}, + {0xC7, 0x64}, {0x01, 0x65}, + {0x44, 0x66}, {0x00, 0x67}, + {0x44, 0x68}, {0x00, 0x69}, + {0x44, 0x6A}, {0x00, 0x6B}, + {0xC7, 0x6C}, {0x01, 0x6D}, + {0xC7, 0x6E}, {0x01, 0x6F}, + {0xC7, 0x70}, {0x01, 0x71}, + {0x44, 0x72}, {0x00, 0x73}, + {0x44, 0x74}, {0x00, 0x75}, + {0x44, 0x76}, {0x00, 0x77}, + {0xC7, 0x78}, {0x01, 0x79}, + {0xC7, 0x7A}, {0x01, 0x7B}, + {0xC7, 0x7C}, {0x01, 0x7D}, + {0x44, 0x7E}, {0x00, 0x7F}, + {0x14, 0x84}, {0x00, 0x85}, + {0x27, 0x86}, {0x00, 0x87}, + {0x07, 0x88}, {0x00, 0x89}, + {0xEC, 0x8A}, {0x0f, 0x8B}, + {0xD8, 0x8C}, {0x0f, 0x8D}, + {0x3D, 0x8E}, {0x00, 0x8F}, + {0x3D, 0x90}, {0x00, 0x91}, + {0xCD, 0x92}, {0x0f, 0x93}, + {0xf7, 0x94}, {0x0f, 0x95}, + {0x0C, 0x96}, {0x00, 0x97}, + {0x00, 0x98}, {0x66, 0x99}, + {0x05, 0x9A}, {0x00, 0x9B}, + {0x04, 0x9C}, {0x00, 0x9D}, + {0x08, 0x9E}, {0x00, 0x9F}, + {0x2D, 0xC0}, {0x2D, 0xC1}, + {0x3A, 0xC2}, {0x05, 0xC3}, + {0x04, 0xC4}, {0x3F, 0xC5}, + {0x00, 0xC6}, {0x00, 0xC7}, + {0x50, 0xC8}, {0x3C, 0xC9}, + {0x28, 0xCA}, {0xD8, 0xCB}, + {0x14, 0xCC}, {0xEC, 0xCD}, + {0x32, 0xCE}, {0xDD, 0xCF}, + {0x32, 0xD0}, {0xDD, 0xD1}, + {0x6A, 0xD2}, {0x50, 0xD3}, + {0x00, 0xD4}, {0x00, 0xD5}, + {0x00, 0xD6}); + break; + default: + break; + } err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, 0x00, 0x01, 0, 0); @@ -65,50 +150,50 @@ static int mi0360_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { struct sn9c102_sensor* s = sn9c102_get_sensor(cam); - u8 data[5+1]; + u8 data[2]; switch (ctrl->id) { case V4L2_CID_EXPOSURE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2, + data) < 0) return -EIO; - ctrl->value = data[2]; + ctrl->value = data[0]; return 0; case V4L2_CID_GAIN: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2, + data) < 0) return -EIO; - ctrl->value = data[3]; + ctrl->value = data[1]; return 0; case V4L2_CID_RED_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2, + data) < 0) return -EIO; - ctrl->value = data[3]; + ctrl->value = data[1]; return 0; case V4L2_CID_BLUE_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2, + data) < 0) return -EIO; - ctrl->value = data[3]; + ctrl->value = data[1]; return 0; case SN9C102_V4L2_CID_GREEN_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2, + data) < 0) return -EIO; - ctrl->value = data[3]; + ctrl->value = data[1]; return 0; case V4L2_CID_HFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = data[3] & 0x20 ? 1 : 0; + ctrl->value = data[1] & 0x20 ? 1 : 0; return 0; case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = data[3] & 0x80 ? 1 : 0; + ctrl->value = data[1] & 0x80 ? 1 : 0; return 0; default: return -EINVAL; @@ -178,8 +263,19 @@ static int mi0360_set_crop(struct sn9c102_device* cam, { struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0; + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1; + break; + default: + break; + } err += sn9c102_write_reg(cam, h_start, 0x12); err += sn9c102_write_reg(cam, v_start, 0x13); @@ -194,24 +290,30 @@ static int mi0360_set_pix_format(struct sn9c102_device* cam, struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x0a, 0x00, 0x02, 0, 0); - err += sn9c102_write_reg(cam, 0x20, 0x19); - } else { + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0a, 0x00, 0x05, 0, 0); err += sn9c102_write_reg(cam, 0x60, 0x19); + if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 || + sn9c102_get_bridge(cam) == BRIDGE_SN9C120) + err += sn9c102_write_reg(cam, 0xa6, 0x17); + } else { + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x0a, 0x00, 0x02, 0, 0); + err += sn9c102_write_reg(cam, 0x20, 0x19); + if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 || + sn9c102_get_bridge(cam) == BRIDGE_SN9C120) + err += sn9c102_write_reg(cam, 0xa2, 0x17); } return err; } -static struct sn9c102_sensor mi0360 = { +static const struct sn9c102_sensor mi0360 = { .name = "MI-0360", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, .i2c_slave_id = 0x5d, @@ -317,19 +419,31 @@ static struct sn9c102_sensor mi0360 = { int sn9c102_probe_mi0360(struct sn9c102_device* cam) { - u8 data[5+1]; - int err; - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17}); - if (err) - return -EIO; + u8 data[2]; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17})) + return -EIO; + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, + {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17})) + return -EIO; + break; + default: + break; + } if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00, - 2+1, data) < 0) + 2, data) < 0) return -EIO; - if (data[2] != 0x82 || data[3] != 0x43) + if (data[0] != 0x82 || data[1] != 0x43) return -ENODEV; sn9c102_attach_sensor(cam, &mi0360); diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c index 31b6080b0615..e6832347894f 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c @@ -29,9 +29,8 @@ static int ov7630_init(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x00, 0x14}, - {0x60, 0x17}, {0x0f, 0x18}, - {0x50, 0x19}); + err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, + {0x0f, 0x18}, {0x50, 0x19}); err += sn9c102_i2c_write(cam, 0x12, 0x8d); err += sn9c102_i2c_write(cam, 0x12, 0x0d); @@ -61,7 +60,6 @@ static int ov7630_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x71, 0x00); err += sn9c102_i2c_write(cam, 0x74, 0x21); err += sn9c102_i2c_write(cam, 0x7d, 0xf7); - break; case BRIDGE_SN9C103: err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03}, @@ -253,7 +251,7 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor ov7630 = { +static const struct sn9c102_sensor ov7630 = { .name = "OV7630", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, @@ -408,19 +406,16 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, - {0x00, 0x01}, {0x28, 0x17}); - + err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17}); break; case BRIDGE_SN9C103: /* do _not_ change anything! */ - err = sn9c102_write_const_regs(cam, {0x09, 0x01}, - {0x42, 0x01}, {0x28, 0x17}, - {0x44, 0x02}); + err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01}, + {0x28, 0x17}, {0x44, 0x02}); pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); - if (err || pid < 0) { /* try a different initialization */ - err = sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - } + if (err || pid < 0) /* try a different initialization */ + err += sn9c102_write_const_regs(cam, {0x01, 0x01}, + {0x00, 0x01}); break; default: break; diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c index c898e948fe8d..4b6474048a72 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c @@ -104,8 +104,8 @@ static int ov7660_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x12, 0x80); err += sn9c102_i2c_write(cam, 0x11, 0x09); err += sn9c102_i2c_write(cam, 0x00, 0x0A); - err += sn9c102_i2c_write(cam, 0x01, 0x78); - err += sn9c102_i2c_write(cam, 0x02, 0x90); + err += sn9c102_i2c_write(cam, 0x01, 0x80); + err += sn9c102_i2c_write(cam, 0x02, 0x80); err += sn9c102_i2c_write(cam, 0x03, 0x00); err += sn9c102_i2c_write(cam, 0x04, 0x00); err += sn9c102_i2c_write(cam, 0x05, 0x08); @@ -122,7 +122,7 @@ static int ov7660_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x10, 0x20); err += sn9c102_i2c_write(cam, 0x11, 0x03); err += sn9c102_i2c_write(cam, 0x12, 0x05); - err += sn9c102_i2c_write(cam, 0x13, 0xF8); + err += sn9c102_i2c_write(cam, 0x13, 0xC7); err += sn9c102_i2c_write(cam, 0x14, 0x2C); err += sn9c102_i2c_write(cam, 0x15, 0x00); err += sn9c102_i2c_write(cam, 0x16, 0x02); @@ -162,7 +162,7 @@ static int ov7660_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x38, 0x02); err += sn9c102_i2c_write(cam, 0x39, 0x43); err += sn9c102_i2c_write(cam, 0x3A, 0x00); - err += sn9c102_i2c_write(cam, 0x3B, 0x02); + err += sn9c102_i2c_write(cam, 0x3B, 0x0A); err += sn9c102_i2c_write(cam, 0x3C, 0x6C); err += sn9c102_i2c_write(cam, 0x3D, 0x99); err += sn9c102_i2c_write(cam, 0x3E, 0x0E); @@ -281,25 +281,34 @@ static int ov7660_get_ctrl(struct sn9c102_device* cam, return -EIO; break; case V4L2_CID_DO_WHITE_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x02); + if ((ctrl->value = sn9c102_read_reg(cam, 0x02)) < 0) + return -EIO; ctrl->value = (ctrl->value & 0x04) ? 1 : 0; break; case V4L2_CID_RED_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x05); + if ((ctrl->value = sn9c102_read_reg(cam, 0x05)) < 0) + return -EIO; ctrl->value &= 0x7f; break; case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x06); + if ((ctrl->value = sn9c102_read_reg(cam, 0x06)) < 0) + return -EIO; ctrl->value &= 0x7f; break; case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x07); + if ((ctrl->value = sn9c102_read_reg(cam, 0x07)) < 0) + return -EIO; ctrl->value &= 0x7f; break; + case SN9C102_V4L2_CID_BAND_FILTER: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x3b)) < 0) + return -EIO; + ctrl->value &= 0x08; + break; case V4L2_CID_GAIN: if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) return -EIO; - ctrl->value &= 0x7f; + ctrl->value &= 0x1f; break; case V4L2_CID_AUTOGAIN: if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0) @@ -335,12 +344,15 @@ static int ov7660_set_ctrl(struct sn9c102_device* cam, case SN9C102_V4L2_CID_GREEN_BALANCE: err += sn9c102_write_reg(cam, ctrl->value, 0x07); break; + case SN9C102_V4L2_CID_BAND_FILTER: + err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b); + break; case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x00, ctrl->value); + err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value); break; case V4L2_CID_AUTOGAIN: - err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value | - (ctrl->value << 1)); + err += sn9c102_i2c_write(cam, 0x13, 0xc0 | + (ctrl->value * 0x07)); break; default: return -EINVAL; @@ -386,7 +398,7 @@ static int ov7660_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor ov7660 = { +static const struct sn9c102_sensor ov7660 = { .name = "OV7660", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120, @@ -401,9 +413,9 @@ static struct sn9c102_sensor ov7660 = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "global gain", .minimum = 0x00, - .maximum = 0x7f, + .maximum = 0x1f, .step = 0x01, - .default_value = 0x0a, + .default_value = 0x09, .flags = 0, }, { @@ -413,7 +425,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0xff, .step = 0x01, - .default_value = 0x50, + .default_value = 0x27, .flags = 0, }, { @@ -433,7 +445,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x7f, .step = 0x01, - .default_value = 0x1f, + .default_value = 0x14, .flags = 0, }, { @@ -443,7 +455,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x7f, .step = 0x01, - .default_value = 0x1e, + .default_value = 0x14, .flags = 0, }, { @@ -453,7 +465,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x01, .step = 0x01, - .default_value = 0x00, + .default_value = 0x01, .flags = 0, }, { @@ -463,7 +475,17 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x7f, .step = 0x01, - .default_value = 0x20, + .default_value = 0x14, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_BAND_FILTER, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "band filter", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x00, .flags = 0, }, }, @@ -508,6 +530,7 @@ int sn9c102_probe_ov7660(struct sn9c102_device* cam) return -EIO; if (pid != 0x76 || ver != 0x60) return -ENODEV; + sn9c102_attach_sensor(cam, &ov7660); return 0; diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c index 67151964801f..360f2a848bc0 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c @@ -163,7 +163,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor pas106b = { +static const struct sn9c102_sensor pas106b = { .name = "PAS106B", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, @@ -273,23 +273,21 @@ static struct sn9c102_sensor pas106b = { int sn9c102_probe_pas106b(struct sn9c102_device* cam) { - int r0 = 0, r1 = 0, err; + int r0 = 0, r1 = 0; unsigned int pid = 0; /* Minimal initialization to enable the I2C communication NOTE: do NOT change the values! */ - err = sn9c102_write_const_regs(cam, - {0x01, 0x01}, /* sensor power down */ - {0x00, 0x01}, /* sensor power on */ - {0x28, 0x17});/* sensor clock 24 MHz */ - if (err) + if (sn9c102_write_const_regs(cam, + {0x01, 0x01}, /* sensor power down */ + {0x00, 0x01}, /* sensor power on */ + {0x28, 0x17})) /* sensor clock at 24 MHz */ return -EIO; r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00); r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01); - if (r0 < 0 || r1 < 0) return -EIO; diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c index c1b8d6b63b47..ca4a1506ed3d 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c @@ -35,29 +35,28 @@ static int pas202bcb_init(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x00, 0x10}, - {0x00, 0x11}, {0x00, 0x14}, - {0x20, 0x17}, {0x30, 0x19}, - {0x09, 0x18}); + err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, + {0x00, 0x14}, {0x20, 0x17}, + {0x30, 0x19}, {0x09, 0x18}); break; case BRIDGE_SN9C103: - err = sn9c102_write_const_regs(cam, {0x00, 0x02}, - {0x00, 0x03}, {0x1a, 0x04}, - {0x20, 0x05}, {0x20, 0x06}, - {0x20, 0x07}, {0x00, 0x10}, - {0x00, 0x11}, {0x00, 0x14}, - {0x20, 0x17}, {0x30, 0x19}, - {0x09, 0x18}, {0x02, 0x1c}, - {0x03, 0x1d}, {0x0f, 0x1e}, - {0x0c, 0x1f}, {0x00, 0x20}, - {0x10, 0x21}, {0x20, 0x22}, - {0x30, 0x23}, {0x40, 0x24}, - {0x50, 0x25}, {0x60, 0x26}, - {0x70, 0x27}, {0x80, 0x28}, - {0x90, 0x29}, {0xa0, 0x2a}, - {0xb0, 0x2b}, {0xc0, 0x2c}, - {0xd0, 0x2d}, {0xe0, 0x2e}, - {0xf0, 0x2f}, {0xff, 0x30}); + err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03}, + {0x1a, 0x04}, {0x20, 0x05}, + {0x20, 0x06}, {0x20, 0x07}, + {0x00, 0x10}, {0x00, 0x11}, + {0x00, 0x14}, {0x20, 0x17}, + {0x30, 0x19}, {0x09, 0x18}, + {0x02, 0x1c}, {0x03, 0x1d}, + {0x0f, 0x1e}, {0x0c, 0x1f}, + {0x00, 0x20}, {0x10, 0x21}, + {0x20, 0x22}, {0x30, 0x23}, + {0x40, 0x24}, {0x50, 0x25}, + {0x60, 0x26}, {0x70, 0x27}, + {0x80, 0x28}, {0x90, 0x29}, + {0xa0, 0x2a}, {0xb0, 0x2b}, + {0xc0, 0x2c}, {0xd0, 0x2d}, + {0xe0, 0x2e}, {0xf0, 0x2f}, + {0xff, 0x30}); break; default: break; @@ -197,7 +196,7 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam, } -static struct sn9c102_sensor pas202bcb = { +static const struct sn9c102_sensor pas202bcb = { .name = "PAS202BCB", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, @@ -313,9 +312,8 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) {0x28, 0x17});/* clock 24 MHz */ break; case BRIDGE_SN9C103: /* do _not_ change anything! */ - err = sn9c102_write_const_regs(cam, {0x09, 0x01}, - {0x44, 0x01}, {0x44, 0x02}, - {0x29, 0x17}); + err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01}, + {0x44, 0x02}, {0x29, 0x17}); break; default: break; diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 1bbf64c897a2..2d7d786b8430 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -22,7 +22,7 @@ #define _SN9C102_SENSOR_H_ #include <linux/usb.h> -#include <linux/videodev.h> +#include <linux/videodev2.h> #include <linux/device.h> #include <linux/stddef.h> #include <linux/errno.h> @@ -74,7 +74,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); /* Attach a probed sensor to the camera. */ extern void sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor); + const struct sn9c102_sensor* sensor); /* Read/write routines: they always return -1 on error, 0 or the read value @@ -85,10 +85,11 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, */ /* The "try" I2C I/O versions are used when probing the sensor */ -extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address, u8 value); -extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address); +extern int sn9c102_i2c_try_write(struct sn9c102_device*, + const struct sn9c102_sensor*, u8 address, + u8 value); +extern int sn9c102_i2c_try_read(struct sn9c102_device*, + const struct sn9c102_sensor*, u8 address); /* These must be used if and only if the sensor doesn't implement the standard @@ -102,29 +103,31 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, byte. */ extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, + const struct sn9c102_sensor* sensor, u8 n, u8 data0, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5); extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, - u8 data1, u8 n, u8 buffer[]); + const struct sn9c102_sensor* sensor, + u8 data0, u8 data1, u8 n, u8 buffer[]); /* To be used after the sensor struct has been attached to the camera struct */ extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value); extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address); /* I/O on registers in the bridge. Could be used by the sensor methods too */ +extern int sn9c102_read_reg(struct sn9c102_device*, u16 index); extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2], int count); /* - * Write multiple registers with constant values. For example: - * sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18}); - */ -#define sn9c102_write_const_regs(device, data...) \ - ({ const static u8 _data[][2] = {data}; \ - sn9c102_write_regs(device, _data, ARRAY_SIZE(_data)); }) + Write multiple registers with constant values. For example: + sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18}); + Register adresses must be < 256. +*/ +#define sn9c102_write_const_regs(sn9c102_device, data...) \ + ({ const static u8 _valreg[][2] = {data}; \ + sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); }) /*****************************************************************************/ diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c index 0e7ec8662c70..e7d2de2bace1 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c @@ -88,7 +88,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor tas5110c1b = { +static const struct sn9c102_sensor tas5110c1b = { .name = "TAS5110C1B", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c index 83a39e8b5e71..d32fdbccdc5e 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110d.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c @@ -68,7 +68,7 @@ static int tas5110d_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor tas5110d = { +static const struct sn9c102_sensor tas5110d = { .name = "TAS5110D", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c index 50406503fc40..56fb1d575a8a 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c @@ -89,7 +89,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor tas5130d1b = { +static const struct sn9c102_sensor tas5130d1b = { .name = "TAS5130D1B", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index a0fd82b924f2..e4cb99c1f94b 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVIDEO config USB_VICAM tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL + depends on VIDEO_V4L1 && EXPERIMENTAL select VIDEO_USBVIDEO ---help--- Say Y here if you have 3com homeconnect camera (vicam). @@ -13,7 +13,7 @@ config USB_VICAM config USB_IBMCAM tristate "USB IBM (Xirlink) C-it Camera support" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want to connect a IBM "C-It" camera, also known as @@ -28,7 +28,7 @@ config USB_IBMCAM config USB_KONICAWC tristate "USB Konica Webcam support" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want support for webcams based on a Konica @@ -39,7 +39,7 @@ config USB_KONICAWC config USB_QUICKCAM_MESSENGER tristate "USB Logitech Quickcam Messenger" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y or M here to enable support for the USB Logitech Quickcam diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig index c43a5d899091..fc24ef05b3f3 100644 --- a/drivers/media/video/usbvision/Kconfig +++ b/drivers/media/video/usbvision/Kconfig @@ -1,6 +1,6 @@ config VIDEO_USBVISION tristate "USB video devices based on Nogatech NT1003/1004/1005" - depends on I2C && VIDEO_V4L2 && USB + depends on I2C && VIDEO_V4L2 select VIDEO_TUNER select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO ---help--- diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index a861e150865e..ede8543818bf 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -127,7 +127,7 @@ set_v4l_control(struct inode *inode, /* ----------------------------------------------------------------- */ -static int palette2pixelformat[] = { +const static unsigned int palette2pixelformat[] = { [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY, [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555, [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565, @@ -145,7 +145,7 @@ static int palette2pixelformat[] = { [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P, }; -static unsigned int +static unsigned int __attribute_pure__ palette_to_pixelformat(unsigned int palette) { if (palette < ARRAY_SIZE(palette2pixelformat)) @@ -154,8 +154,8 @@ palette_to_pixelformat(unsigned int palette) return 0; } -static unsigned int -pixelformat_to_palette(int pixelformat) +static unsigned int __attribute_const__ +pixelformat_to_palette(unsigned int pixelformat) { int palette = 0; switch (pixelformat) @@ -616,6 +616,8 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCSPICT: /* set tone controls & partial capture format */ { struct video_picture *pict = arg; + int mem_err = 0, ovl_err = 0; + memset(&fbuf2, 0, sizeof(fbuf2)); set_v4l_control(inode, file, @@ -628,33 +630,59 @@ v4l_compat_translate_ioctl(struct inode *inode, V4L2_CID_SATURATION, pict->colour, drv); set_v4l_control(inode, file, V4L2_CID_WHITENESS, pict->whiteness, drv); + /* + * V4L1 uses this ioctl to set both memory capture and overlay + * pixel format, while V4L2 has two different ioctls for this. + * Some cards may not support one or the other, and may support + * different pixel formats for memory vs overlay. + */ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); - if (err < 0) + /* If VIDIOC_G_FMT failed, then the driver likely doesn't + support memory capture. Trying to set the memory capture + parameters would be pointless. */ + if (err < 0) { dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err); - if (fmt2->fmt.pix.pixelformat != - palette_to_pixelformat(pict->palette)) { + mem_err = -1000; /* didn't even try */ + } else if (fmt2->fmt.pix.pixelformat != + palette_to_pixelformat(pict->palette)) { fmt2->fmt.pix.pixelformat = palette_to_pixelformat( pict->palette); - err = drv(inode, file, VIDIOC_S_FMT, fmt2); - if (err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err); + mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2); + if (mem_err < 0) + dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", + mem_err); } err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); - if (err < 0) + /* If VIDIOC_G_FBUF failed, then the driver likely doesn't + support overlay. Trying to set the overlay parameters + would be quite pointless. */ + if (err < 0) { dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err); - if (fbuf2.fmt.pixelformat != - palette_to_pixelformat(pict->palette)) { + ovl_err = -1000; /* didn't even try */ + } else if (fbuf2.fmt.pixelformat != + palette_to_pixelformat(pict->palette)) { fbuf2.fmt.pixelformat = palette_to_pixelformat( pict->palette); - err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); - if (err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err); - err = 0; /* likely fails for non-root */ + ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); + if (ovl_err < 0) + dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", + ovl_err); } + if (ovl_err < 0 && mem_err < 0) + /* ioctl failed, couldn't set either parameter */ + if (mem_err != -1000) { + err = mem_err; + } else if (ovl_err == -EPERM) { + err = 0; + } else { + err = ovl_err; + } + else + err = 0; break; } case VIDIOCGTUNER: /* get tuner information */ diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 459786ff459a..a32dfbe0585a 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -702,9 +702,7 @@ videobuf_qbuf(struct videobuf_queue *q, dprintk(1,"qbuf: memory type is wrong.\n"); goto done; } - if (buf->state == STATE_QUEUED || - buf->state == STATE_PREPARED || - buf->state == STATE_ACTIVE) { + if (buf->state != STATE_NEEDS_INIT && buf->state != STATE_IDLE) { dprintk(1,"qbuf: buffer is already queued or active.\n"); goto done; } diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 5263b50463e1..b876aca69c73 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -433,13 +433,43 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, int ret = -EINVAL; if ( (vfd->debug & V4L2_DEBUG_IOCTL) && - !(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) { + !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { v4l_print_ioctl(vfd->name, cmd); } +#ifdef CONFIG_VIDEO_V4L1_COMPAT + /*********************************************************** + Handles calls to the obsoleted V4L1 API + Due to the nature of VIDIOCGMBUF, each driver that supports + V4L1 should implement its own handler for this ioctl. + ***********************************************************/ + + /* --- streaming capture ------------------------------------- */ + if (cmd == VIDIOCGMBUF) { + struct video_mbuf *p=arg; + + memset(p,0,sizeof(p)); + + if (!vfd->vidiocgmbuf) + return ret; + ret=vfd->vidiocgmbuf(file, fh, p); + if (!ret) + dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n", + p->size, p->frames, + (unsigned long)p->offsets); + return ret; + } + + /******************************************************** + All other V4L1 calls are handled by v4l1_compat module. + Those calls will be translated into V4L2 calls, and + __video_do_ioctl will be called again, with one or more + V4L2 ioctls. + ********************************************************/ if (_IOC_TYPE(cmd)=='v') return v4l_compat_translate_ioctl(inode,file,cmd,arg, __video_do_ioctl); +#endif switch(cmd) { /* --- capabilities ------------------------------------------ */ @@ -791,24 +821,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_overlay(file, fh, *i); break; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /* --- streaming capture ------------------------------------- */ - case VIDIOCGMBUF: - { - struct video_mbuf *p=arg; - - memset(p,0,sizeof(p)); - - if (!vfd->vidiocgmbuf) - break; - ret=vfd->vidiocgmbuf(file, fh, p); - if (!ret) - dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n", - p->size, p->frames, - (unsigned long)p->offsets); - break; - } -#endif case VIDIOC_G_FBUF: { struct v4l2_framebuffer *p=arg; diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index a859a6920189..47cd93f9c7de 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig @@ -1,6 +1,6 @@ config USB_ZC0301 tristate "USB ZC0301[P] Image Processor and Control Chip support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on the ZC0301 or ZC0301P Image Processors and Control Chips. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index fa489b10c38c..fb99cd445504 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1898,8 +1898,12 @@ endmenu # Gigabit Ethernet # -menu "Ethernet (1000 Mbit)" +menuconfig NETDEV_1000 + bool "Ethernet (1000 Mbit)" depends on !UML + default y + +if NETDEV_1000 config ACENIC tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support" @@ -2299,7 +2303,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "MV-643XX Ethernet support" - depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32) + depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MV64X60 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32) select MII help This driver supports the gigabit Ethernet on the Marvell MV643XX @@ -2326,14 +2330,18 @@ config ATL1 To compile this driver as a module, choose M here. The module will be called atl1. -endmenu +endif # NETDEV_1000 # # 10 Gigabit Ethernet # -menu "Ethernet (10000 Mbit)" +menuconfig NETDEV_10000 + bool "Ethernet (10000 Mbit)" depends on !UML + default y + +if NETDEV_10000 config CHELSIO_T1 tristate "Chelsio 10Gb Ethernet support" @@ -2507,7 +2515,7 @@ config MLX4_DEBUG debug_level module parameter (which can also be set after the driver is loaded through sysfs). -endmenu +endif # NETDEV_10000 source "drivers/net/tokenring/Kconfig" diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index 7c8ccc09b601..829da9a1d113 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -141,6 +141,20 @@ config ACT200L_DONGLE To activate support for ACTiSYS IR-200L dongle you will have to start irattach like this: "irattach -d act200l". +config KINGSUN_DONGLE + tristate "KingSun/DonShine DS-620 IrDA-USB dongle" + depends on IRDA && USB && EXPERIMENTAL + help + Say Y or M here if you want to build support for the KingSun/DonShine + DS-620 IrDA-USB bridge device driver. + + This USB bridge does not conform to the IrDA-USB device class + specification, and therefore needs its own specific driver. This + dongle supports SIR speed only (9600 bps). + + To compile it as a module, choose M here: the module will be called + kingsun-sir. + comment "Old SIR device drivers" config IRPORT_SIR diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index 5be09f1b9ee2..233a2f923730 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o +obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o # The SIR helper module sir-dev-objs := sir_dev.o sir_dongle.o diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c new file mode 100644 index 000000000000..217429122e79 --- /dev/null +++ b/drivers/net/irda/kingsun-sir.c @@ -0,0 +1,657 @@ +/***************************************************************************** +* +* Filename: kingsun-sir.c +* Version: 0.1.1 +* Description: Irda KingSun/DonShine USB Dongle +* Status: Experimental +* Author: Alex Villac�s Lasso <a_villacis@palosanto.com> +* +* Based on stir4200 and mcs7780 drivers, with (strange?) differences +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****************************************************************************/ + +/* + * This is my current (2007-04-25) understanding of how this dongle is supposed + * to work. This is based on reverse-engineering and examination of the packet + * data sent and received by the WinXP driver using USBSnoopy. Feel free to + * update here as more of this dongle is known: + * + * General: Unlike the other USB IrDA dongles, this particular dongle exposes, + * not two bulk (in and out) endpoints, but two *interrupt* ones. This dongle, + * like the bulk based ones (stir4200.c and mcs7780.c), requires polling in + * order to receive data. + * Transmission: Just like stir4200, this dongle uses a raw stream of data, + * which needs to be wrapped and escaped in a similar way as in stir4200.c. + * Reception: Poll-based, as in stir4200. Each read returns the contents of a + * 8-byte buffer, of which the first byte (LSB) indicates the number of bytes + * (1-7) of valid data contained within the remaining 7 bytes. For example, if + * the buffer had the following contents: + * 06 ff ff ff c0 01 04 aa + * This means that (06) there are 6 bytes of valid data. The byte 0xaa at the + * end is garbage (left over from a previous reception) and is discarded. + * If a read returns an "impossible" value as the length of valid data (such as + * 0x36) in the first byte, then the buffer is uninitialized (as is the case of + * first plug-in) and its contents should be discarded. There is currently no + * evidence that the top 5 bits of the 1st byte of the buffer can have values + * other than 0 once reception begins. + * Once valid bytes are collected, the assembled stream is a sequence of + * wrapped IrDA frames that is unwrapped and unescaped as in stir4200.c. + * BIG FAT WARNING: the dongle does *not* reset the RX buffer in any way after + * a successful read from the host, which means that in absence of further + * reception, repeated reads from the dongle will return the exact same + * contents repeatedly. Attempts to be smart and cache a previous read seem + * to result in corrupted packets, so this driver depends on the unwrap logic + * to sort out any repeated reads. + * Speed change: no commands observed so far to change speed, assumed fixed + * 9600bps (SIR). + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/kref.h> +#include <linux/usb.h> +#include <linux/device.h> +#include <linux/crc32.h> + +#include <asm/unaligned.h> +#include <asm/byteorder.h> +#include <asm/uaccess.h> + +#include <net/irda/irda.h> +#include <net/irda/wrapper.h> +#include <net/irda/crc.h> + +/* + * According to lsusb, 0x07c0 is assigned to + * "Code Mercenaries Hard- und Software GmbH" + */ +#define KING_VENDOR_ID 0x07c0 +#define KING_PRODUCT_ID 0x4200 + +/* These are the currently known USB ids */ +static struct usb_device_id dongles[] = { + /* KingSun Co,Ltd IrDA/USB Bridge */ + { USB_DEVICE(KING_VENDOR_ID, KING_PRODUCT_ID) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, dongles); + +#define KINGSUN_MTT 0x07 + +#define KINGSUN_FIFO_SIZE 4096 +#define KINGSUN_EP_IN 0 +#define KINGSUN_EP_OUT 1 + +struct kingsun_cb { + struct usb_device *usbdev; /* init: probe_irda */ + struct net_device *netdev; /* network layer */ + struct irlap_cb *irlap; /* The link layer we are binded to */ + struct net_device_stats stats; /* network statistics */ + struct qos_info qos; + + __u8 *in_buf; /* receive buffer */ + __u8 *out_buf; /* transmit buffer */ + __u8 max_rx; /* max. atomic read from dongle + (usually 8), also size of in_buf */ + __u8 max_tx; /* max. atomic write to dongle + (usually 8) */ + + iobuff_t rx_buff; /* receive unwrap state machine */ + struct timeval rx_time; + spinlock_t lock; + int receiving; + + __u8 ep_in; + __u8 ep_out; + + struct urb *tx_urb; + struct urb *rx_urb; +}; + +/* Callback transmission routine */ +static void kingsun_send_irq(struct urb *urb) +{ + struct kingsun_cb *kingsun = urb->context; + struct net_device *netdev = kingsun->netdev; + + /* in process of stopping, just drop data */ + if (!netif_running(kingsun->netdev)) { + err("kingsun_send_irq: Network not running!"); + return; + } + + /* unlink, shutdown, unplug, other nasties */ + if (urb->status != 0) { + err("kingsun_send_irq: urb asynchronously failed - %d", + urb->status); + } + netif_wake_queue(netdev); +} + +/* + * Called from net/core when new frame is available. + */ +static int kingsun_hard_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct kingsun_cb *kingsun; + int wraplen; + int ret = 0; + + if (skb == NULL || netdev == NULL) + return -EINVAL; + + netif_stop_queue(netdev); + + /* the IRDA wrapping routines don't deal with non linear skb */ + SKB_LINEAR_ASSERT(skb); + + kingsun = netdev_priv(netdev); + + spin_lock(&kingsun->lock); + + /* Append data to the end of whatever data remains to be transmitted */ + wraplen = async_wrap_skb(skb, + kingsun->out_buf, + KINGSUN_FIFO_SIZE); + + /* Calculate how much data can be transmitted in this urb */ + usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev, + usb_sndintpipe(kingsun->usbdev, kingsun->ep_out), + kingsun->out_buf, wraplen, kingsun_send_irq, + kingsun, 1); + + if ((ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC))) { + err("kingsun_hard_xmit: failed tx_urb submit: %d", ret); + switch (ret) { + case -ENODEV: + case -EPIPE: + break; + default: + kingsun->stats.tx_errors++; + netif_start_queue(netdev); + } + } else { + kingsun->stats.tx_packets++; + kingsun->stats.tx_bytes += skb->len; + } + + dev_kfree_skb(skb); + spin_unlock(&kingsun->lock); + + return ret; +} + +/* Receive callback function */ +static void kingsun_rcv_irq(struct urb *urb) +{ + struct kingsun_cb *kingsun = urb->context; + int ret; + + /* in process of stopping, just drop data */ + if (!netif_running(kingsun->netdev)) { + kingsun->receiving = 0; + return; + } + + /* unlink, shutdown, unplug, other nasties */ + if (urb->status != 0) { + err("kingsun_rcv_irq: urb asynchronously failed - %d", + urb->status); + kingsun->receiving = 0; + return; + } + + if (urb->actual_length == kingsun->max_rx) { + __u8 *bytes = urb->transfer_buffer; + int i; + + /* The very first byte in the buffer indicates the length of + valid data in the read. This byte must be in the range + 1..kingsun->max_rx -1 . Values outside this range indicate + an uninitialized Rx buffer when the dongle has just been + plugged in. */ + if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) { + for (i = 1; i <= bytes[0]; i++) { + async_unwrap_char(kingsun->netdev, + &kingsun->stats, + &kingsun->rx_buff, bytes[i]); + } + kingsun->netdev->last_rx = jiffies; + do_gettimeofday(&kingsun->rx_time); + kingsun->receiving = + (kingsun->rx_buff.state != OUTSIDE_FRAME) + ? 1 : 0; + } + } else if (urb->actual_length > 0) { + err("%s(): Unexpected response length, expected %d got %d", + __FUNCTION__, kingsun->max_rx, urb->actual_length); + } + /* This urb has already been filled in kingsun_net_open */ + ret = usb_submit_urb(urb, GFP_ATOMIC); +} + +/* + * Function kingsun_net_open (dev) + * + * Network device is taken up. Usually this is done by "ifconfig irda0 up" + */ +static int kingsun_net_open(struct net_device *netdev) +{ + struct kingsun_cb *kingsun = netdev_priv(netdev); + int err = -ENOMEM; + char hwname[16]; + + /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */ + kingsun->receiving = 0; + + /* Initialize for SIR to copy data directly into skb. */ + kingsun->rx_buff.in_frame = FALSE; + kingsun->rx_buff.state = OUTSIDE_FRAME; + kingsun->rx_buff.truesize = IRDA_SKB_MAX_MTU; + kingsun->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); + if (!kingsun->rx_buff.skb) + goto free_mem; + + skb_reserve(kingsun->rx_buff.skb, 1); + kingsun->rx_buff.head = kingsun->rx_buff.skb->data; + do_gettimeofday(&kingsun->rx_time); + + kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!kingsun->rx_urb) + goto free_mem; + + kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!kingsun->tx_urb) + goto free_mem; + + /* + * Now that everything should be initialized properly, + * Open new IrLAP layer instance to take care of us... + */ + sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); + kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); + if (!kingsun->irlap) { + err("kingsun-sir: irlap_open failed"); + goto free_mem; + } + + /* Start first reception */ + usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev, + usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in), + kingsun->in_buf, kingsun->max_rx, + kingsun_rcv_irq, kingsun, 1); + kingsun->rx_urb->status = 0; + err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); + if (err) { + err("kingsun-sir: first urb-submit failed: %d", err); + goto close_irlap; + } + + netif_start_queue(netdev); + + /* Situation at this point: + - all work buffers allocated + - urbs allocated and ready to fill + - max rx packet known (in max_rx) + - unwrap state machine initialized, in state outside of any frame + - receive request in progress + - IrLAP layer started, about to hand over packets to send + */ + + return 0; + + close_irlap: + irlap_close(kingsun->irlap); + free_mem: + if (kingsun->tx_urb) { + usb_free_urb(kingsun->tx_urb); + kingsun->tx_urb = NULL; + } + if (kingsun->rx_urb) { + usb_free_urb(kingsun->rx_urb); + kingsun->rx_urb = NULL; + } + if (kingsun->rx_buff.skb) { + kfree_skb(kingsun->rx_buff.skb); + kingsun->rx_buff.skb = NULL; + kingsun->rx_buff.head = NULL; + } + return err; +} + +/* + * Function kingsun_net_close (kingsun) + * + * Network device is taken down. Usually this is done by + * "ifconfig irda0 down" + */ +static int kingsun_net_close(struct net_device *netdev) +{ + struct kingsun_cb *kingsun = netdev_priv(netdev); + + /* Stop transmit processing */ + netif_stop_queue(netdev); + + /* Mop up receive && transmit urb's */ + usb_kill_urb(kingsun->tx_urb); + usb_kill_urb(kingsun->rx_urb); + + usb_free_urb(kingsun->tx_urb); + usb_free_urb(kingsun->rx_urb); + + kingsun->tx_urb = NULL; + kingsun->rx_urb = NULL; + + kfree_skb(kingsun->rx_buff.skb); + kingsun->rx_buff.skb = NULL; + kingsun->rx_buff.head = NULL; + kingsun->rx_buff.in_frame = FALSE; + kingsun->rx_buff.state = OUTSIDE_FRAME; + kingsun->receiving = 0; + + /* Stop and remove instance of IrLAP */ + if (kingsun->irlap) + irlap_close(kingsun->irlap); + + kingsun->irlap = NULL; + + return 0; +} + +/* + * IOCTLs : Extra out-of-band network commands... + */ +static int kingsun_net_ioctl(struct net_device *netdev, struct ifreq *rq, + int cmd) +{ + struct if_irda_req *irq = (struct if_irda_req *) rq; + struct kingsun_cb *kingsun = netdev_priv(netdev); + int ret = 0; + + switch (cmd) { + case SIOCSBANDWIDTH: /* Set bandwidth */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + /* Check if the device is still there */ + if (netif_device_present(kingsun->netdev)) + /* No observed commands for speed change */ + ret = -EOPNOTSUPP; + break; + + case SIOCSMEDIABUSY: /* Set media busy */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + /* Check if the IrDA stack is still there */ + if (netif_running(kingsun->netdev)) + irda_device_set_media_busy(kingsun->netdev, TRUE); + break; + + case SIOCGRECEIVING: + /* Only approximately true */ + irq->ifr_receiving = kingsun->receiving; + break; + + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +/* + * Get device stats (for /proc/net/dev and ifconfig) + */ +static struct net_device_stats * +kingsun_net_get_stats(struct net_device *netdev) +{ + struct kingsun_cb *kingsun = netdev_priv(netdev); + return &kingsun->stats; +} + +/* + * This routine is called by the USB subsystem for each new device + * in the system. We need to check if the device is ours, and in + * this case start handling it. + */ +static int kingsun_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_host_interface *interface; + struct usb_endpoint_descriptor *endpoint; + + struct usb_device *dev = interface_to_usbdev(intf); + struct kingsun_cb *kingsun = NULL; + struct net_device *net = NULL; + int ret = -ENOMEM; + int pipe, maxp_in, maxp_out; + __u8 ep_in; + __u8 ep_out; + + /* Check that there really are two interrupt endpoints. + Check based on the one in drivers/usb/input/usbmouse.c + */ + interface = intf->cur_altsetting; + if (interface->desc.bNumEndpoints != 2) { + err("kingsun-sir: expected 2 endpoints, found %d", + interface->desc.bNumEndpoints); + return -ENODEV; + } + endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; + if (!usb_endpoint_is_int_in(endpoint)) { + err("kingsun-sir: endpoint 0 is not interrupt IN"); + return -ENODEV; + } + + ep_in = endpoint->bEndpointAddress; + pipe = usb_rcvintpipe(dev, ep_in); + maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + if (maxp_in > 255 || maxp_in <= 1) { + err("%s: endpoint 0 has max packet size %d not in range", + __FILE__, maxp_in); + return -ENODEV; + } + + endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; + if (!usb_endpoint_is_int_out(endpoint)) { + err("kingsun-sir: endpoint 1 is not interrupt OUT"); + return -ENODEV; + } + + ep_out = endpoint->bEndpointAddress; + pipe = usb_sndintpipe(dev, ep_out); + maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + /* Allocate network device container. */ + net = alloc_irdadev(sizeof(*kingsun)); + if(!net) + goto err_out1; + + SET_MODULE_OWNER(net); + SET_NETDEV_DEV(net, &intf->dev); + kingsun = netdev_priv(net); + kingsun->irlap = NULL; + kingsun->tx_urb = NULL; + kingsun->rx_urb = NULL; + kingsun->ep_in = ep_in; + kingsun->ep_out = ep_out; + kingsun->in_buf = NULL; + kingsun->out_buf = NULL; + kingsun->max_rx = (__u8)maxp_in; + kingsun->max_tx = (__u8)maxp_out; + kingsun->netdev = net; + kingsun->usbdev = dev; + kingsun->rx_buff.in_frame = FALSE; + kingsun->rx_buff.state = OUTSIDE_FRAME; + kingsun->rx_buff.skb = NULL; + kingsun->receiving = 0; + spin_lock_init(&kingsun->lock); + + /* Allocate input buffer */ + kingsun->in_buf = (__u8 *)kmalloc(kingsun->max_rx, GFP_KERNEL); + if (!kingsun->in_buf) + goto free_mem; + + /* Allocate output buffer */ + kingsun->out_buf = (__u8 *)kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL); + if (!kingsun->out_buf) + goto free_mem; + + printk(KERN_INFO "KingSun/DonShine IRDA/USB found at address %d, " + "Vendor: %x, Product: %x\n", + dev->devnum, le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); + + /* Initialize QoS for this device */ + irda_init_max_qos_capabilies(&kingsun->qos); + + /* That's the Rx capability. */ + kingsun->qos.baud_rate.bits &= IR_9600; + kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; + irda_qos_bits_to_value(&kingsun->qos); + + /* Override the network functions we need to use */ + net->hard_start_xmit = kingsun_hard_xmit; + net->open = kingsun_net_open; + net->stop = kingsun_net_close; + net->get_stats = kingsun_net_get_stats; + net->do_ioctl = kingsun_net_ioctl; + + ret = register_netdev(net); + if (ret != 0) + goto free_mem; + + info("IrDA: Registered KingSun/DonShine device %s", net->name); + + usb_set_intfdata(intf, kingsun); + + /* Situation at this point: + - all work buffers allocated + - urbs not allocated, set to NULL + - max rx packet known (in max_rx) + - unwrap state machine (partially) initialized, but skb == NULL + */ + + return 0; + +free_mem: + if (kingsun->out_buf) kfree(kingsun->out_buf); + if (kingsun->in_buf) kfree(kingsun->in_buf); + free_netdev(net); +err_out1: + return ret; +} + +/* + * The current device is removed, the USB layer tell us to shut it down... + */ +static void kingsun_disconnect(struct usb_interface *intf) +{ + struct kingsun_cb *kingsun = usb_get_intfdata(intf); + + if (!kingsun) + return; + + unregister_netdev(kingsun->netdev); + + /* Mop up receive && transmit urb's */ + if (kingsun->tx_urb != NULL) { + usb_kill_urb(kingsun->tx_urb); + usb_free_urb(kingsun->tx_urb); + kingsun->tx_urb = NULL; + } + if (kingsun->rx_urb != NULL) { + usb_kill_urb(kingsun->rx_urb); + usb_free_urb(kingsun->rx_urb); + kingsun->rx_urb = NULL; + } + + kfree(kingsun->out_buf); + kfree(kingsun->in_buf); + free_netdev(kingsun->netdev); + + usb_set_intfdata(intf, NULL); +} + +#ifdef CONFIG_PM +/* USB suspend, so power off the transmitter/receiver */ +static int kingsun_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct kingsun_cb *kingsun = usb_get_intfdata(intf); + + netif_device_detach(kingsun->netdev); + if (kingsun->tx_urb != NULL) usb_kill_urb(kingsun->tx_urb); + if (kingsun->rx_urb != NULL) usb_kill_urb(kingsun->rx_urb); + return 0; +} + +/* Coming out of suspend, so reset hardware */ +static int kingsun_resume(struct usb_interface *intf) +{ + struct kingsun_cb *kingsun = usb_get_intfdata(intf); + + if (kingsun->rx_urb != NULL) + usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); + netif_device_attach(kingsun->netdev); + + return 0; +} +#endif + +/* + * USB device callbacks + */ +static struct usb_driver irda_driver = { + .name = "kingsun-sir", + .probe = kingsun_probe, + .disconnect = kingsun_disconnect, + .id_table = dongles, +#ifdef CONFIG_PM + .suspend = kingsun_suspend, + .resume = kingsun_resume, +#endif +}; + +/* + * Module insertion + */ +static int __init kingsun_init(void) +{ + return usb_register(&irda_driver); +} +module_init(kingsun_init); + +/* + * Module removal + */ +static void __exit kingsun_cleanup(void) +{ + /* Deregister the driver and remove all pending instances */ + usb_deregister(&irda_driver); +} +module_exit(kingsun_cleanup); + +MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>"); +MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index acf1c801a1b8..af016d0ea1c6 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c @@ -623,7 +623,7 @@ int __devinit mlx4_init_eq_table(struct mlx4_dev *dev) priv->eq_table.eq[MLX4_EQ_CATAS].have_irq = 1; } else { err = request_irq(dev->pdev->irq, mlx4_interrupt, - SA_SHIRQ, DRV_NAME, dev); + IRQF_SHARED, DRV_NAME, dev); if (err) goto err_out_async; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 4e32bb678ea9..2c5c6d20e6e9 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -735,7 +735,7 @@ static int netxen_nic_open(struct net_device *netdev) } adapter->irq = adapter->ahw.pdev->irq; err = request_irq(adapter->ahw.pdev->irq, netxen_intr, - SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name, + IRQF_SHARED|IRQF_SAMPLE_RANDOM, netdev->name, adapter); if (err) { printk(KERN_ERR "request_irq failed with: %d\n", err); diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig index 74f862001247..5d658bc9791c 100644 --- a/drivers/net/pcmcia/Kconfig +++ b/drivers/net/pcmcia/Kconfig @@ -2,11 +2,9 @@ # PCMCIA Network device configuration # -menu "PCMCIA network device support" - depends on NETDEVICES && PCMCIA!=n - -config NET_PCMCIA +menuconfig NET_PCMCIA bool "PCMCIA network device support" + depends on PCMCIA ---help--- Say Y if you would like to include support for any PCMCIA or CardBus network adapters, then say Y to the driver for your particular card @@ -21,9 +19,10 @@ config NET_PCMCIA If unsure, say N. +if NET_PCMCIA + config PCMCIA_3C589 tristate "3Com 3c589 PCMCIA support" - depends on NET_PCMCIA && PCMCIA help Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA (PC-card) Ethernet card to your computer. @@ -33,7 +32,6 @@ config PCMCIA_3C589 config PCMCIA_3C574 tristate "3Com 3c574 PCMCIA support" - depends on NET_PCMCIA && PCMCIA help Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA (PC-card) Fast Ethernet card to your computer. @@ -43,7 +41,6 @@ config PCMCIA_3C574 config PCMCIA_FMVJ18X tristate "Fujitsu FMV-J18x PCMCIA support" - depends on NET_PCMCIA && PCMCIA select CRC32 help Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible @@ -54,7 +51,6 @@ config PCMCIA_FMVJ18X config PCMCIA_PCNET tristate "NE2000 compatible PCMCIA support" - depends on NET_PCMCIA && PCMCIA select CRC32 help Say Y here if you intend to attach an NE2000 compatible PCMCIA @@ -65,7 +61,6 @@ config PCMCIA_PCNET config PCMCIA_NMCLAN tristate "New Media PCMCIA support" - depends on NET_PCMCIA && PCMCIA help Say Y here if you intend to attach a New Media Ethernet or LiveWire PCMCIA (PC-card) Ethernet card to your computer. @@ -75,7 +70,6 @@ config PCMCIA_NMCLAN config PCMCIA_SMC91C92 tristate "SMC 91Cxx PCMCIA support" - depends on NET_PCMCIA && PCMCIA select CRC32 select MII help @@ -87,7 +81,6 @@ config PCMCIA_SMC91C92 config PCMCIA_XIRC2PS tristate "Xircom 16-bit PCMCIA support" - depends on NET_PCMCIA && PCMCIA help Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card) Ethernet or Fast Ethernet card to your computer. @@ -97,7 +90,6 @@ config PCMCIA_XIRC2PS config PCMCIA_AXNET tristate "Asix AX88190 PCMCIA support" - depends on NET_PCMCIA && PCMCIA ---help--- Say Y here if you intend to attach an Asix AX88190-based PCMCIA (PC-card) Fast Ethernet card to your computer. These cards are @@ -109,7 +101,7 @@ config PCMCIA_AXNET config ARCNET_COM20020_CS tristate "COM20020 ARCnet PCMCIA support" - depends on NET_PCMCIA && ARCNET_COM20020 && PCMCIA + depends on ARCNET_COM20020 help Say Y here if you intend to attach this type of ARCnet PCMCIA card to your computer. @@ -119,7 +111,7 @@ config ARCNET_COM20020_CS config PCMCIA_IBMTR tristate "IBM PCMCIA tokenring adapter support" - depends on NET_PCMCIA && IBMTR!=y && TR && PCMCIA && !64BIT + depends on IBMTR!=y && TR && !64BIT help Say Y here if you intend to attach this type of Token Ring PCMCIA card to your computer. You then also need to say Y to "Token Ring @@ -128,5 +120,4 @@ config PCMCIA_IBMTR To compile this driver as a module, choose M here: the module will be called ibmtr_cs. -endmenu - +endif # NET_PCMCIA diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index c0d3101eb6a0..09b6f259eb92 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -2,70 +2,61 @@ # PHY Layer Configuration # -menu "PHY device support" - depends on !S390 - -config PHYLIB +menuconfig PHYLIB tristate "PHY Device support and infrastructure" + depends on !S390 depends on NET_ETHERNET && (BROKEN || !S390) help Ethernet controllers are usually attached to PHY devices. This option provides infrastructure for managing PHY devices. +if PHYLIB + comment "MII PHY device drivers" - depends on PHYLIB config MARVELL_PHY tristate "Drivers for Marvell PHYs" - depends on PHYLIB ---help--- Currently has a driver for the 88E1011S config DAVICOM_PHY tristate "Drivers for Davicom PHYs" - depends on PHYLIB ---help--- Currently supports dm9161e and dm9131 config QSEMI_PHY tristate "Drivers for Quality Semiconductor PHYs" - depends on PHYLIB ---help--- Currently supports the qs6612 config LXT_PHY tristate "Drivers for the Intel LXT PHYs" - depends on PHYLIB ---help--- Currently supports the lxt970, lxt971 config CICADA_PHY tristate "Drivers for the Cicada PHYs" - depends on PHYLIB ---help--- Currently supports the cis8204 + config VITESSE_PHY tristate "Drivers for the Vitesse PHYs" - depends on PHYLIB ---help--- Currently supports the vsc8244 config SMSC_PHY tristate "Drivers for SMSC PHYs" - depends on PHYLIB ---help--- Currently supports the LAN83C185 PHY config BROADCOM_PHY tristate "Drivers for Broadcom PHYs" - depends on PHYLIB ---help--- Currently supports the BCM5411, BCM5421 and BCM5461 PHYs. config FIXED_PHY tristate "Drivers for PHY emulation on fixed speed/link" - depends on PHYLIB ---help--- Adds the driver to PHY layer to cover the boards that do not have any PHY bound, but with the ability to manipulate the speed/link in software. The relevant MII @@ -80,5 +71,4 @@ config FIXED_MII_100_FDX bool "Emulation for 100M Fdx fixed PHY behavior" depends on FIXED_PHY -endmenu - +endif # PHYLIB diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c index 519baa38be8d..7ed632db00d7 100644 --- a/drivers/net/phy/davicom.c +++ b/drivers/net/phy/davicom.c @@ -139,7 +139,7 @@ static int dm9161_ack_interrupt(struct phy_device *phydev) return (err < 0) ? err : 0; } -static struct phy_driver dm9161_driver = { +static struct phy_driver dm9161e_driver = { .phy_id = 0x0181b880, .name = "Davicom DM9161E", .phy_id_mask = 0x0ffffff0, @@ -147,7 +147,18 @@ static struct phy_driver dm9161_driver = { .config_init = dm9161_config_init, .config_aneg = dm9161_config_aneg, .read_status = genphy_read_status, - .driver = { .owner = THIS_MODULE,}, + .driver = { .owner = THIS_MODULE,}, +}; + +static struct phy_driver dm9161a_driver = { + .phy_id = 0x0181b8a0, + .name = "Davicom DM9161A", + .phy_id_mask = 0x0ffffff0, + .features = PHY_BASIC_FEATURES, + .config_init = dm9161_config_init, + .config_aneg = dm9161_config_aneg, + .read_status = genphy_read_status, + .driver = { .owner = THIS_MODULE,}, }; static struct phy_driver dm9131_driver = { @@ -160,31 +171,38 @@ static struct phy_driver dm9131_driver = { .read_status = genphy_read_status, .ack_interrupt = dm9161_ack_interrupt, .config_intr = dm9161_config_intr, - .driver = { .owner = THIS_MODULE,}, + .driver = { .owner = THIS_MODULE,}, }; static int __init davicom_init(void) { int ret; - ret = phy_driver_register(&dm9161_driver); + ret = phy_driver_register(&dm9161e_driver); if (ret) goto err1; - ret = phy_driver_register(&dm9131_driver); + ret = phy_driver_register(&dm9161a_driver); if (ret) goto err2; + + ret = phy_driver_register(&dm9131_driver); + if (ret) + goto err3; return 0; - err2: - phy_driver_unregister(&dm9161_driver); + err3: + phy_driver_unregister(&dm9161a_driver); + err2: + phy_driver_unregister(&dm9161e_driver); err1: return ret; } static void __exit davicom_exit(void) { - phy_driver_unregister(&dm9161_driver); + phy_driver_unregister(&dm9161e_driver); + phy_driver_unregister(&dm9161a_driver); phy_driver_unregister(&dm9131_driver); } diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 290e1c1f30c6..e3e6d410d72c 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -84,7 +84,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.22.1" +#define DRV_VERSION "2.0.23.1" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -281,6 +281,28 @@ static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = { ("lro_out_of_sequence_pkts"), ("lro_flush_due_to_max_pkts"), ("lro_avg_aggr_pkts"), + ("mem_alloc_fail_cnt"), + ("watchdog_timer_cnt"), + ("mem_allocated"), + ("mem_freed"), + ("link_up_cnt"), + ("link_down_cnt"), + ("link_up_time"), + ("link_down_time"), + ("tx_tcode_buf_abort_cnt"), + ("tx_tcode_desc_abort_cnt"), + ("tx_tcode_parity_err_cnt"), + ("tx_tcode_link_loss_cnt"), + ("tx_tcode_list_proc_err_cnt"), + ("rx_tcode_parity_err_cnt"), + ("rx_tcode_abort_cnt"), + ("rx_tcode_parity_abort_cnt"), + ("rx_tcode_rda_fail_cnt"), + ("rx_tcode_unkn_prot_cnt"), + ("rx_tcode_fcs_err_cnt"), + ("rx_tcode_buf_size_err_cnt"), + ("rx_tcode_rxd_corrupt_cnt"), + ("rx_tcode_unkn_err_cnt") }; #define S2IO_XENA_STAT_LEN sizeof(ethtool_xena_stats_keys)/ ETH_GSTRING_LEN @@ -490,6 +512,7 @@ static int init_shared_mem(struct s2io_nic *nic) struct mac_info *mac_control; struct config_param *config; + unsigned long long mem_allocated = 0; mac_control = &nic->mac_control; config = &nic->config; @@ -519,6 +542,7 @@ static int init_shared_mem(struct s2io_nic *nic) "Malloc failed for list_info\n"); return -ENOMEM; } + mem_allocated += list_holder_size; memset(mac_control->fifos[i].list_info, 0, list_holder_size); } for (i = 0; i < config->tx_fifo_num; i++) { @@ -565,6 +589,7 @@ static int init_shared_mem(struct s2io_nic *nic) DBG_PRINT(INFO_DBG, "failed for TxDL\n"); return -ENOMEM; } + mem_allocated += PAGE_SIZE; } while (k < lst_per_page) { int l = (j * lst_per_page) + k; @@ -582,6 +607,7 @@ static int init_shared_mem(struct s2io_nic *nic) nic->ufo_in_band_v = kcalloc(size, sizeof(u64), GFP_KERNEL); if (!nic->ufo_in_band_v) return -ENOMEM; + mem_allocated += (size * sizeof(u64)); /* Allocation and initialization of RXDs in Rings */ size = 0; @@ -639,6 +665,7 @@ static int init_shared_mem(struct s2io_nic *nic) rx_blocks->block_virt_addr = tmp_v_addr; return -ENOMEM; } + mem_allocated += size; memset(tmp_v_addr, 0, size); rx_blocks->block_virt_addr = tmp_v_addr; rx_blocks->block_dma_addr = tmp_p_addr; @@ -647,6 +674,8 @@ static int init_shared_mem(struct s2io_nic *nic) GFP_KERNEL); if (!rx_blocks->rxds) return -ENOMEM; + mem_allocated += + (sizeof(struct rxd_info)* rxd_count[nic->rxd_mode]); for (l=0; l<rxd_count[nic->rxd_mode];l++) { rx_blocks->rxds[l].virt_addr = rx_blocks->block_virt_addr + @@ -689,6 +718,7 @@ static int init_shared_mem(struct s2io_nic *nic) GFP_KERNEL); if (!mac_control->rings[i].ba) return -ENOMEM; + mem_allocated +=(sizeof(struct buffAdd *) * blk_cnt); for (j = 0; j < blk_cnt; j++) { int k = 0; mac_control->rings[i].ba[j] = @@ -697,6 +727,8 @@ static int init_shared_mem(struct s2io_nic *nic) GFP_KERNEL); if (!mac_control->rings[i].ba[j]) return -ENOMEM; + mem_allocated += (sizeof(struct buffAdd) * \ + (rxd_count[nic->rxd_mode] + 1)); while (k != rxd_count[nic->rxd_mode]) { ba = &mac_control->rings[i].ba[j][k]; @@ -704,6 +736,8 @@ static int init_shared_mem(struct s2io_nic *nic) (BUF0_LEN + ALIGN_SIZE, GFP_KERNEL); if (!ba->ba_0_org) return -ENOMEM; + mem_allocated += + (BUF0_LEN + ALIGN_SIZE); tmp = (unsigned long)ba->ba_0_org; tmp += ALIGN_SIZE; tmp &= ~((unsigned long) ALIGN_SIZE); @@ -713,6 +747,8 @@ static int init_shared_mem(struct s2io_nic *nic) (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL); if (!ba->ba_1_org) return -ENOMEM; + mem_allocated + += (BUF1_LEN + ALIGN_SIZE); tmp = (unsigned long) ba->ba_1_org; tmp += ALIGN_SIZE; tmp &= ~((unsigned long) ALIGN_SIZE); @@ -736,6 +772,7 @@ static int init_shared_mem(struct s2io_nic *nic) */ return -ENOMEM; } + mem_allocated += size; mac_control->stats_mem_sz = size; tmp_v_addr = mac_control->stats_mem; @@ -743,7 +780,7 @@ static int init_shared_mem(struct s2io_nic *nic) memset(tmp_v_addr, 0, size); DBG_PRINT(INIT_DBG, "%s:Ring Mem PHY: 0x%llx\n", dev->name, (unsigned long long) tmp_p_addr); - + mac_control->stats_info->sw_stat.mem_allocated += mem_allocated; return SUCCESS; } @@ -757,12 +794,14 @@ static int init_shared_mem(struct s2io_nic *nic) static void free_shared_mem(struct s2io_nic *nic) { int i, j, blk_cnt, size; + u32 ufo_size = 0; void *tmp_v_addr; dma_addr_t tmp_p_addr; struct mac_info *mac_control; struct config_param *config; int lst_size, lst_per_page; struct net_device *dev = nic->dev; + int page_num = 0; if (!nic) return; @@ -774,8 +813,9 @@ static void free_shared_mem(struct s2io_nic *nic) lst_per_page = PAGE_SIZE / lst_size; for (i = 0; i < config->tx_fifo_num; i++) { - int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len, - lst_per_page); + ufo_size += config->tx_cfg[i].fifo_len; + page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len, + lst_per_page); for (j = 0; j < page_num; j++) { int mem_blks = (j * lst_per_page); if (!mac_control->fifos[i].list_info) @@ -790,6 +830,8 @@ static void free_shared_mem(struct s2io_nic *nic) mac_control->fifos[i]. list_info[mem_blks]. list_phy_addr); + nic->mac_control.stats_info->sw_stat.mem_freed + += PAGE_SIZE; } /* If we got a zero DMA address during allocation, * free the page now @@ -803,8 +845,12 @@ static void free_shared_mem(struct s2io_nic *nic) dev->name); DBG_PRINT(INIT_DBG, "Virtual address %p\n", mac_control->zerodma_virt_addr); + nic->mac_control.stats_info->sw_stat.mem_freed + += PAGE_SIZE; } kfree(mac_control->fifos[i].list_info); + nic->mac_control.stats_info->sw_stat.mem_freed += + (nic->config.tx_cfg[i].fifo_len *sizeof(struct list_info_hold)); } size = SIZE_OF_BLOCK; @@ -819,7 +865,10 @@ static void free_shared_mem(struct s2io_nic *nic) break; pci_free_consistent(nic->pdev, size, tmp_v_addr, tmp_p_addr); + nic->mac_control.stats_info->sw_stat.mem_freed += size; kfree(mac_control->rings[i].rx_blocks[j].rxds); + nic->mac_control.stats_info->sw_stat.mem_freed += + ( sizeof(struct rxd_info)* rxd_count[nic->rxd_mode]); } } @@ -836,12 +885,20 @@ static void free_shared_mem(struct s2io_nic *nic) struct buffAdd *ba = &mac_control->rings[i].ba[j][k]; kfree(ba->ba_0_org); + nic->mac_control.stats_info->sw_stat.\ + mem_freed += (BUF0_LEN + ALIGN_SIZE); kfree(ba->ba_1_org); + nic->mac_control.stats_info->sw_stat.\ + mem_freed += (BUF1_LEN + ALIGN_SIZE); k++; } kfree(mac_control->rings[i].ba[j]); + nic->mac_control.stats_info->sw_stat.mem_freed += (sizeof(struct buffAdd) * + (rxd_count[nic->rxd_mode] + 1)); } kfree(mac_control->rings[i].ba); + nic->mac_control.stats_info->sw_stat.mem_freed += + (sizeof(struct buffAdd *) * blk_cnt); } } @@ -850,9 +907,14 @@ static void free_shared_mem(struct s2io_nic *nic) mac_control->stats_mem_sz, mac_control->stats_mem, mac_control->stats_mem_phy); + nic->mac_control.stats_info->sw_stat.mem_freed += + mac_control->stats_mem_sz; } - if (nic->ufo_in_band_v) + if (nic->ufo_in_band_v) { kfree(nic->ufo_in_band_v); + nic->mac_control.stats_info->sw_stat.mem_freed + += (ufo_size * sizeof(u64)); + } } /** @@ -2122,10 +2184,12 @@ static void free_tx_buffers(struct s2io_nic *nic) for (i = 0; i < config->tx_fifo_num; i++) { for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) { - txdp = (struct TxD *) mac_control->fifos[i].list_info[j]. - list_virt_addr; + txdp = (struct TxD *) \ + mac_control->fifos[i].list_info[j].list_virt_addr; skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j); if (skb) { + nic->mac_control.stats_info->sw_stat.mem_freed + += skb->truesize; dev_kfree_skb(skb); cnt++; } @@ -2186,11 +2250,14 @@ static int fill_rxd_3buf(struct s2io_nic *nic, struct RxD_t *rxdp, struct \ /* skb_shinfo(skb)->frag_list will have L4 data payload */ skb_shinfo(skb)->frag_list = dev_alloc_skb(dev->mtu + ALIGN_SIZE); if (skb_shinfo(skb)->frag_list == NULL) { + nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; DBG_PRINT(INFO_DBG, "%s: dev_alloc_skb failed\n ", dev->name); return -ENOMEM ; } frag_list = skb_shinfo(skb)->frag_list; skb->truesize += frag_list->truesize; + nic->mac_control.stats_info->sw_stat.mem_allocated + += frag_list->truesize; frag_list->next = NULL; tmp = (void *)ALIGN((long)frag_list->data, ALIGN_SIZE + 1); frag_list->data = tmp; @@ -2319,8 +2386,12 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) wmb(); first_rxdp->Control_1 |= RXD_OWN_XENA; } + nic->mac_control.stats_info->sw_stat. \ + mem_alloc_fail_cnt++; return -ENOMEM ; } + nic->mac_control.stats_info->sw_stat.mem_allocated + += skb->truesize; if (nic->rxd_mode == RXD_MODE_1) { /* 1 buffer mode - normal operation mode */ memset(rxdp, 0, sizeof(struct RxD1)); @@ -2328,7 +2399,8 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) ((struct RxD1*)rxdp)->Buffer0_ptr = pci_map_single (nic->pdev, skb->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); - rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN); + rxdp->Control_2 = + SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN); } else if (nic->rxd_mode >= RXD_MODE_3A) { /* @@ -2342,7 +2414,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) * payload */ - /* save the buffer pointers to avoid frequent dma mapping */ + /* save buffer pointers to avoid frequent dma mapping */ Buffer0_ptr = ((struct RxD3*)rxdp)->Buffer0_ptr; Buffer1_ptr = ((struct RxD3*)rxdp)->Buffer1_ptr; memset(rxdp, 0, sizeof(struct RxD3)); @@ -2364,7 +2436,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) PCI_DMA_FROMDEVICE); else pci_dma_sync_single_for_device(nic->pdev, - (dma_addr_t) ((struct RxD3*)rxdp)->Buffer0_ptr, + (dma_addr_t) ((struct RxD3*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); if (nic->rxd_mode == RXD_MODE_3B) { @@ -2391,6 +2463,8 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) } else { /* 3 buffer mode */ if (fill_rxd_3buf(nic, rxdp, skb) == -ENOMEM) { + nic->mac_control.stats_info->sw_stat.\ + mem_freed += skb->truesize; dev_kfree_skb_irq(skb); if (first_rxdp) { wmb(); @@ -2491,6 +2565,7 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) PCI_DMA_FROMDEVICE); memset(rxdp, 0, sizeof(struct RxD3)); } + sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize; dev_kfree_skb(skb); atomic_dec(&sp->rx_bufs_left[ring_no]); } @@ -2820,13 +2895,35 @@ static void tx_intr_handler(struct fifo_info *fifo_data) nic->mac_control.stats_info->sw_stat. parity_err_cnt++; } - if ((err >> 48) == 0xA) { - DBG_PRINT(TX_DBG, "TxD returned due \ - to loss of link\n"); - } - else { - DBG_PRINT(ERR_DBG, "***TxD error %llx\n", err); - } + + /* update t_code statistics */ + err >>= 48; + switch(err) { + case 2: + nic->mac_control.stats_info->sw_stat. + tx_buf_abort_cnt++; + break; + + case 3: + nic->mac_control.stats_info->sw_stat. + tx_desc_abort_cnt++; + break; + + case 7: + nic->mac_control.stats_info->sw_stat. + tx_parity_err_cnt++; + break; + + case 10: + nic->mac_control.stats_info->sw_stat. + tx_link_loss_cnt++; + break; + + case 15: + nic->mac_control.stats_info->sw_stat. + tx_list_proc_err_cnt++; + break; + } } skb = s2io_txdl_getskb(fifo_data, txdlp, get_info.offset); @@ -2839,6 +2936,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data) /* Updating the statistics block */ nic->stats.tx_bytes += skb->len; + nic->mac_control.stats_info->sw_stat.mem_freed += skb->truesize; dev_kfree_skb_irq(skb); get_info.offset++; @@ -3314,7 +3412,9 @@ static void s2io_reset(struct s2io_nic * sp) u16 subid, pci_cmd; int i; u16 val16; - unsigned long long reset_cnt = 0; + unsigned long long up_cnt, down_cnt, up_time, down_time, reset_cnt; + unsigned long long mem_alloc_cnt, mem_free_cnt, watchdog_cnt; + DBG_PRINT(INIT_DBG,"%s - Resetting XFrame card %s\n", __FUNCTION__, sp->dev->name); @@ -3380,11 +3480,26 @@ new_way: /* Reset device statistics maintained by OS */ memset(&sp->stats, 0, sizeof (struct net_device_stats)); - /* save reset count */ + + up_cnt = sp->mac_control.stats_info->sw_stat.link_up_cnt; + down_cnt = sp->mac_control.stats_info->sw_stat.link_down_cnt; + up_time = sp->mac_control.stats_info->sw_stat.link_up_time; + down_time = sp->mac_control.stats_info->sw_stat.link_down_time; reset_cnt = sp->mac_control.stats_info->sw_stat.soft_reset_cnt; + mem_alloc_cnt = sp->mac_control.stats_info->sw_stat.mem_allocated; + mem_free_cnt = sp->mac_control.stats_info->sw_stat.mem_freed; + watchdog_cnt = sp->mac_control.stats_info->sw_stat.watchdog_timer_cnt; + /* save link up/down time/cnt, reset/memory/watchdog cnt */ memset(sp->mac_control.stats_info, 0, sizeof(struct stat_block)); - /* restore reset count */ + /* restore link up/down time/cnt, reset/memory/watchdog cnt */ + sp->mac_control.stats_info->sw_stat.link_up_cnt = up_cnt; + sp->mac_control.stats_info->sw_stat.link_down_cnt = down_cnt; + sp->mac_control.stats_info->sw_stat.link_up_time = up_time; + sp->mac_control.stats_info->sw_stat.link_down_time = down_time; sp->mac_control.stats_info->sw_stat.soft_reset_cnt = reset_cnt; + sp->mac_control.stats_info->sw_stat.mem_allocated = mem_alloc_cnt; + sp->mac_control.stats_info->sw_stat.mem_freed = mem_free_cnt; + sp->mac_control.stats_info->sw_stat.watchdog_timer_cnt = watchdog_cnt; /* SXE-002: Configure link and activity LED to turn it off */ subid = sp->pdev->subsystem_device; @@ -3672,19 +3787,29 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry), GFP_KERNEL); if (nic->entries == NULL) { - DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", __FUNCTION__); + DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", \ + __FUNCTION__); + nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; return -ENOMEM; } - memset(nic->entries, 0, MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); + nic->mac_control.stats_info->sw_stat.mem_allocated + += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); + memset(nic->entries, 0,MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); nic->s2io_entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry), GFP_KERNEL); if (nic->s2io_entries == NULL) { - DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", __FUNCTION__); + DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", + __FUNCTION__); + nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; kfree(nic->entries); + nic->mac_control.stats_info->sw_stat.mem_freed + += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); return -ENOMEM; } + nic->mac_control.stats_info->sw_stat.mem_allocated + += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); memset(nic->s2io_entries, 0, MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); @@ -3708,7 +3833,8 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) rx_mat = readq(&bar0->rx_mat); for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) { rx_mat |= RX_MAT_SET(j, msix_indx); - nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j]; + nic->s2io_entries[msix_indx].arg + = &nic->mac_control.rings[j]; nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE; nic->s2io_entries[msix_indx].in_use = MSIX_FLG; } @@ -3717,7 +3843,8 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) tx_mat = readq(&bar0->tx_mat0_n[7]); for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) { tx_mat |= TX_MAT_SET(i, msix_indx); - nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j]; + nic->s2io_entries[msix_indx].arg + = &nic->mac_control.rings[j]; nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE; nic->s2io_entries[msix_indx].in_use = MSIX_FLG; } @@ -3734,7 +3861,11 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) if (ret) { DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name); kfree(nic->entries); + nic->mac_control.stats_info->sw_stat.mem_freed + += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); kfree(nic->s2io_entries); + nic->mac_control.stats_info->sw_stat.mem_freed + += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); nic->entries = NULL; nic->s2io_entries = NULL; nic->avail_msix_vectors = 0; @@ -3802,10 +3933,16 @@ static int s2io_open(struct net_device *dev) hw_init_failed: if (sp->intr_type == MSI_X) { - if (sp->entries) + if (sp->entries) { kfree(sp->entries); - if (sp->s2io_entries) + sp->mac_control.stats_info->sw_stat.mem_freed + += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); + } + if (sp->s2io_entries) { kfree(sp->s2io_entries); + sp->mac_control.stats_info->sw_stat.mem_freed + += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); + } } return err; } @@ -3866,6 +4003,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) config = &sp->config; DBG_PRINT(TX_DBG, "%s: In Neterion Tx routine\n", dev->name); + + if (unlikely(skb->len <= 0)) { + DBG_PRINT(TX_DBG, "%s:Buffer has no data..\n", dev->name); + dev_kfree_skb_any(skb); + return 0; +} + spin_lock_irqsave(&sp->tx_lock, flags); if (atomic_read(&sp->card_state) == CARD_DOWN) { DBG_PRINT(TX_DBG, "%s: Card going down for reset\n", @@ -3876,7 +4020,6 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } queue = 0; - /* Get Fifo number to Transmit based on vlan priority */ if (sp->vlgrp && vlan_tx_tag_present(skb)) { vlan_tag = vlan_tx_tag_get(skb); @@ -3900,14 +4043,6 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - /* A buffer with no data will be dropped */ - if (!skb->len) { - DBG_PRINT(TX_DBG, "%s:Buffer has no data..\n", dev->name); - dev_kfree_skb(skb); - spin_unlock_irqrestore(&sp->tx_lock, flags); - return 0; - } - offload_type = s2io_offload_type(skb); if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { txdp->Control_1 |= TXD_TCP_LSO_EN; @@ -4003,7 +4138,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) put_off, get_off); netif_stop_queue(dev); } - + mac_control->stats_info->sw_stat.mem_allocated += skb->truesize; dev->trans_start = jiffies; spin_unlock_irqrestore(&sp->tx_lock, flags); @@ -4775,6 +4910,40 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data) return 0; } +static void s2io_ethtool_gringparam(struct net_device *dev, + struct ethtool_ringparam *ering) +{ + struct s2io_nic *sp = dev->priv; + int i,tx_desc_count=0,rx_desc_count=0; + + if (sp->rxd_mode == RXD_MODE_1) + ering->rx_max_pending = MAX_RX_DESC_1; + else if (sp->rxd_mode == RXD_MODE_3B) + ering->rx_max_pending = MAX_RX_DESC_2; + else if (sp->rxd_mode == RXD_MODE_3A) + ering->rx_max_pending = MAX_RX_DESC_3; + + ering->tx_max_pending = MAX_TX_DESC; + for (i = 0 ; i < sp->config.tx_fifo_num ; i++) { + tx_desc_count += sp->config.tx_cfg[i].fifo_len; + } + DBG_PRINT(INFO_DBG,"\nmax txds : %d\n",sp->config.max_txds); + ering->tx_pending = tx_desc_count; + rx_desc_count = 0; + for (i = 0 ; i < sp->config.rx_ring_num ; i++) { + rx_desc_count += sp->config.rx_cfg[i].num_rxd; + } + ering->rx_pending = rx_desc_count; + + ering->rx_mini_max_pending = 0; + ering->rx_mini_pending = 0; + if(sp->rxd_mode == RXD_MODE_1) + ering->rx_jumbo_max_pending = MAX_RX_DESC_1; + else if (sp->rxd_mode == RXD_MODE_3B) + ering->rx_jumbo_max_pending = MAX_RX_DESC_2; + ering->rx_jumbo_pending = rx_desc_count; +} + /** * s2io_ethtool_getpause_data -Pause frame frame generation and reception. * @sp : private member of the device structure, which is a pointer to the @@ -4981,8 +5150,11 @@ static void s2io_vpd_read(struct s2io_nic *nic) strcpy(nic->serial_num, "NOT AVAILABLE"); vpd_data = kmalloc(256, GFP_KERNEL); - if (!vpd_data) + if (!vpd_data) { + nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; return; + } + nic->mac_control.stats_info->sw_stat.mem_allocated += 256; for (i = 0; i < 256; i +=4 ) { pci_write_config_byte(nic->pdev, (vpd_addr + 2), i); @@ -5022,6 +5194,7 @@ static void s2io_vpd_read(struct s2io_nic *nic) memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); } kfree(vpd_data); + nic->mac_control.stats_info->sw_stat.mem_freed += 256; } /** @@ -5742,6 +5915,30 @@ static void s2io_get_ethtool_stats(struct net_device *dev, } else tmp_stats[i++] = 0; + tmp_stats[i++] = stat_info->sw_stat.mem_alloc_fail_cnt; + tmp_stats[i++] = stat_info->sw_stat.watchdog_timer_cnt; + tmp_stats[i++] = stat_info->sw_stat.mem_allocated; + tmp_stats[i++] = stat_info->sw_stat.mem_freed; + tmp_stats[i++] = stat_info->sw_stat.link_up_cnt; + tmp_stats[i++] = stat_info->sw_stat.link_down_cnt; + tmp_stats[i++] = stat_info->sw_stat.link_up_time; + tmp_stats[i++] = stat_info->sw_stat.link_down_time; + + tmp_stats[i++] = stat_info->sw_stat.tx_buf_abort_cnt; + tmp_stats[i++] = stat_info->sw_stat.tx_desc_abort_cnt; + tmp_stats[i++] = stat_info->sw_stat.tx_parity_err_cnt; + tmp_stats[i++] = stat_info->sw_stat.tx_link_loss_cnt; + tmp_stats[i++] = stat_info->sw_stat.tx_list_proc_err_cnt; + + tmp_stats[i++] = stat_info->sw_stat.rx_parity_err_cnt; + tmp_stats[i++] = stat_info->sw_stat.rx_abort_cnt; + tmp_stats[i++] = stat_info->sw_stat.rx_parity_abort_cnt; + tmp_stats[i++] = stat_info->sw_stat.rx_rda_fail_cnt; + tmp_stats[i++] = stat_info->sw_stat.rx_unkn_prot_cnt; + tmp_stats[i++] = stat_info->sw_stat.rx_fcs_err_cnt; + tmp_stats[i++] = stat_info->sw_stat.rx_buf_size_err_cnt; + tmp_stats[i++] = stat_info->sw_stat.rx_rxd_corrupt_cnt; + tmp_stats[i++] = stat_info->sw_stat.rx_unkn_err_cnt; } static int s2io_ethtool_get_regs_len(struct net_device *dev) @@ -5854,6 +6051,7 @@ static const struct ethtool_ops netdev_ethtool_ops = { .get_eeprom_len = s2io_get_eeprom_len, .get_eeprom = s2io_ethtool_geeprom, .set_eeprom = s2io_ethtool_seeprom, + .get_ringparam = s2io_ethtool_gringparam, .get_pauseparam = s2io_ethtool_getpause_data, .set_pauseparam = s2io_ethtool_setpause_data, .get_rx_csum = s2io_ethtool_get_rx_csum, @@ -5962,7 +6160,7 @@ static void s2io_tasklet(unsigned long dev_addr) if (ret == -ENOMEM) { DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name); - DBG_PRINT(ERR_DBG, "memory in tasklet\n"); + DBG_PRINT(INFO_DBG, "memory in tasklet\n"); break; } else if (ret == -EFILL) { DBG_PRINT(INFO_DBG, @@ -6077,9 +6275,14 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, *skb = dev_alloc_skb(size); if (!(*skb)) { DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name); - DBG_PRINT(INFO_DBG, "memory to allocate SKBs\n"); + DBG_PRINT(INFO_DBG, "memory to allocate "); + DBG_PRINT(INFO_DBG, "1 buf mode SKBs\n"); + sp->mac_control.stats_info->sw_stat. \ + mem_alloc_fail_cnt++; return -ENOMEM ; } + sp->mac_control.stats_info->sw_stat.mem_allocated + += (*skb)->truesize; /* storing the mapped addr in a temp variable * such it will be used for next rxd whose * Host Control is NULL @@ -6099,10 +6302,15 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, } else { *skb = dev_alloc_skb(size); if (!(*skb)) { - DBG_PRINT(INFO_DBG, "%s: dev_alloc_skb failed\n", - dev->name); + DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name); + DBG_PRINT(INFO_DBG, "memory to allocate "); + DBG_PRINT(INFO_DBG, "2 buf mode SKBs\n"); + sp->mac_control.stats_info->sw_stat. \ + mem_alloc_fail_cnt++; return -ENOMEM; } + sp->mac_control.stats_info->sw_stat.mem_allocated + += (*skb)->truesize; ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2 = pci_map_single(sp->pdev, (*skb)->data, dev->mtu + 4, @@ -6126,10 +6334,15 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, } else { *skb = dev_alloc_skb(size); if (!(*skb)) { - DBG_PRINT(INFO_DBG, "%s: dev_alloc_skb failed\n", - dev->name); + DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name); + DBG_PRINT(INFO_DBG, "memory to allocate "); + DBG_PRINT(INFO_DBG, "3 buf mode SKBs\n"); + sp->mac_control.stats_info->sw_stat. \ + mem_alloc_fail_cnt++; return -ENOMEM; } + sp->mac_control.stats_info->sw_stat.mem_allocated + += (*skb)->truesize; ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0 = pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); @@ -6147,10 +6360,14 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, if (skb_shinfo(*skb)->frag_list == NULL) { DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb \ failed\n ", dev->name); + sp->mac_control.stats_info->sw_stat. \ + mem_alloc_fail_cnt++; return -ENOMEM ; } frag_list = skb_shinfo(*skb)->frag_list; frag_list->next = NULL; + sp->mac_control.stats_info->sw_stat.mem_allocated + += frag_list->truesize; /* * Buffer-2 receives L4 data payload */ @@ -6566,6 +6783,7 @@ static void s2io_tx_watchdog(struct net_device *dev) struct s2io_nic *sp = dev->priv; if (netif_carrier_ok(dev)) { + sp->mac_control.stats_info->sw_stat.watchdog_timer_cnt++; schedule_work(&sp->rst_timer_task); sp->mac_control.stats_info->sw_stat.soft_reset_cnt++; } @@ -6606,7 +6824,53 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) if (err & 0x1) { sp->mac_control.stats_info->sw_stat.parity_err_cnt++; } + err >>= 48; + switch(err) { + case 1: + sp->mac_control.stats_info->sw_stat. + rx_parity_err_cnt++; + break; + case 2: + sp->mac_control.stats_info->sw_stat. + rx_abort_cnt++; + break; + + case 3: + sp->mac_control.stats_info->sw_stat. + rx_parity_abort_cnt++; + break; + + case 4: + sp->mac_control.stats_info->sw_stat. + rx_rda_fail_cnt++; + break; + + case 5: + sp->mac_control.stats_info->sw_stat. + rx_unkn_prot_cnt++; + break; + + case 6: + sp->mac_control.stats_info->sw_stat. + rx_fcs_err_cnt++; + break; + + case 7: + sp->mac_control.stats_info->sw_stat. + rx_buf_size_err_cnt++; + break; + + case 8: + sp->mac_control.stats_info->sw_stat. + rx_rxd_corrupt_cnt++; + break; + + case 15: + sp->mac_control.stats_info->sw_stat. + rx_unkn_err_cnt++; + break; + } /* * Drop the packet if bad transfer code. Exception being * 0x5, which could be due to unsupported IPv6 extension header. @@ -6614,10 +6878,12 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) * Note that in this case, since checksum will be incorrect, * stack will validate the same. */ - if (err && ((err >> 48) != 0x5)) { + if (err != 0x5) { DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n", dev->name, err); sp->stats.rx_crc_errors++; + sp->mac_control.stats_info->sw_stat.mem_freed + += skb->truesize; dev_kfree_skb(skb); atomic_dec(&sp->rx_bufs_left[ring_no]); rxdp->Host_Control = 0; @@ -6627,7 +6893,6 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) /* Updating statistics */ rxdp->Host_Control = 0; - sp->stats.rx_packets++; if (sp->rxd_mode == RXD_MODE_1) { int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2); @@ -6731,7 +6996,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) } else { skb->ip_summed = CHECKSUM_NONE; } - + sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize; if (!sp->lro) { skb->protocol = eth_type_trans(skb, dev); if ((sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2) && @@ -6780,12 +7045,21 @@ static void s2io_link(struct s2io_nic * sp, int link) if (link == LINK_DOWN) { DBG_PRINT(ERR_DBG, "%s: Link down\n", dev->name); netif_carrier_off(dev); + if(sp->mac_control.stats_info->sw_stat.link_up_cnt) + sp->mac_control.stats_info->sw_stat.link_up_time = + jiffies - sp->start_time; + sp->mac_control.stats_info->sw_stat.link_down_cnt++; } else { DBG_PRINT(ERR_DBG, "%s: Link Up\n", dev->name); + if (sp->mac_control.stats_info->sw_stat.link_down_cnt) + sp->mac_control.stats_info->sw_stat.link_down_time = + jiffies - sp->start_time; + sp->mac_control.stats_info->sw_stat.link_up_cnt++; netif_carrier_on(dev); } } sp->last_link_state = link; + sp->start_time = jiffies; } /** diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index a656d18b33df..54baa0b8ec7c 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -95,6 +95,32 @@ struct swStat { unsigned long long flush_max_pkts; unsigned long long sum_avg_pkts_aggregated; unsigned long long num_aggregations; + /* Other statistics */ + unsigned long long mem_alloc_fail_cnt; + unsigned long long watchdog_timer_cnt; + unsigned long long mem_allocated; + unsigned long long mem_freed; + unsigned long long link_up_cnt; + unsigned long long link_down_cnt; + unsigned long long link_up_time; + unsigned long long link_down_time; + + /* Transfer Code statistics */ + unsigned long long tx_buf_abort_cnt; + unsigned long long tx_desc_abort_cnt; + unsigned long long tx_parity_err_cnt; + unsigned long long tx_link_loss_cnt; + unsigned long long tx_list_proc_err_cnt; + + unsigned long long rx_parity_err_cnt; + unsigned long long rx_abort_cnt; + unsigned long long rx_parity_abort_cnt; + unsigned long long rx_rda_fail_cnt; + unsigned long long rx_unkn_prot_cnt; + unsigned long long rx_fcs_err_cnt; + unsigned long long rx_buf_size_err_cnt; + unsigned long long rx_rxd_corrupt_cnt; + unsigned long long rx_unkn_err_cnt; }; /* Xpak releated alarm and warnings */ @@ -308,6 +334,11 @@ struct stat_block { #define MAX_TX_FIFOS 8 #define MAX_RX_RINGS 8 +#define MAX_RX_DESC_1 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 127 ) +#define MAX_RX_DESC_2 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 ) +#define MAX_RX_DESC_3 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 ) +#define MAX_TX_DESC (MAX_AVAILABLE_TXDS) + /* FIFO mappings for all possible number of fifos configured */ static int fifo_map[][MAX_TX_FIFOS] = { {0, 0, 0, 0, 0, 0, 0, 0}, @@ -819,6 +850,7 @@ struct s2io_nic { #define LINK_UP 2 int task_flag; + unsigned long long start_time; #define CARD_DOWN 1 #define CARD_UP 2 atomic_t card_state; diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 1fc77300b055..2106becf6990 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -16,11 +16,13 @@ #include <linux/string.h> #include <linux/delay.h> #include <linux/netdevice.h> +#include <linux/platform_device.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> #include <asm/sgi/hpc3.h> #include <asm/sgi/ip22.h> +#include <asm/sgi/seeq.h> #include "sgiseeq.h" @@ -92,13 +94,9 @@ struct sgiseeq_private { struct net_device_stats stats; - struct net_device *next_module; spinlock_t tx_lock; }; -/* A list of all installed seeq devices, for removing the driver module. */ -static struct net_device *root_sgiseeq_dev; - static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs) { hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ; @@ -624,9 +622,12 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs) #define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf)) -static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom) +static int __init sgiseeq_probe(struct platform_device *pdev) { + struct sgiseeq_platform_data *pd = pdev->dev.platform_data; + struct hpc3_regs *hpcregs = pd->hpc; struct sgiseeq_init_block *sr; + unsigned int irq = pd->irq; struct sgiseeq_private *sp; struct net_device *dev; int err, i; @@ -637,6 +638,8 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom) err = -ENOMEM; goto err_out; } + + platform_set_drvdata(pdev, dev); sp = netdev_priv(dev); /* Make private data page aligned */ @@ -648,15 +651,7 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom) } sp->srings = sr; -#define EADDR_NVOFS 250 - for (i = 0; i < 3; i++) { - unsigned short tmp = has_eeprom ? - ip22_eeprom_read(&hpcregs->eeprom, EADDR_NVOFS / 2+i) : - ip22_nvram_read(EADDR_NVOFS / 2+i); - - dev->dev_addr[2 * i] = tmp >> 8; - dev->dev_addr[2 * i + 1] = tmp & 0xff; - } + memcpy(dev->dev_addr, pd->mac, ETH_ALEN); #ifdef DEBUG gpriv = sp; @@ -720,9 +715,6 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom) for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); - sp->next_module = root_sgiseeq_dev; - root_sgiseeq_dev = dev; - return 0; err_out_free_page: @@ -734,43 +726,42 @@ err_out: return err; } -static int __init sgiseeq_probe(void) +static void __exit sgiseeq_remove(struct platform_device *pdev) { - unsigned int tmp, ret1, ret2 = 0; - - /* On board adapter on 1st HPC is always present */ - ret1 = sgiseeq_init(hpc3c0, SGI_ENET_IRQ, 0); - /* Let's see if second HPC is there */ - if (!(ip22_is_fullhouse()) && - get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]) == 0) { - sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 | - SGIMC_GIOPAR_EXP164 | - SGIMC_GIOPAR_HPC264; - hpc3c1->pbus_piocfg[0][0] = 0x3ffff; - /* interrupt/config register on Challenge S Mezz board */ - hpc3c1->pbus_extregs[0][0] = 0x30; - ret2 = sgiseeq_init(hpc3c1, SGI_GIO_0_IRQ, 1); - } + struct net_device *dev = platform_get_drvdata(pdev); + struct sgiseeq_private *sp = netdev_priv(dev); - return (ret1 & ret2) ? ret1 : 0; + unregister_netdev(dev); + free_page((unsigned long) sp->srings); + free_netdev(dev); + platform_set_drvdata(pdev, NULL); } -static void __exit sgiseeq_exit(void) -{ - struct net_device *next, *dev; - struct sgiseeq_private *sp; +static struct platform_driver sgiseeq_driver = { + .probe = sgiseeq_probe, + .remove = __devexit_p(sgiseeq_remove), + .driver = { + .name = "sgiseeq" + } +}; - for (dev = root_sgiseeq_dev; dev; dev = next) { - sp = (struct sgiseeq_private *) netdev_priv(dev); - next = sp->next_module; - unregister_netdev(dev); - free_page((unsigned long) sp->srings); - free_netdev(dev); +static int __init sgiseeq_module_init(void) +{ + if (platform_driver_register(&sgiseeq_driver)) { + printk(KERN_ERR "Driver registration failed\n"); + return -ENODEV; } + + return 0; +} + +static void __exit sgiseeq_module_exit(void) +{ + platform_driver_unregister(&sgiseeq_driver); } -module_init(sgiseeq_probe); -module_exit(sgiseeq_exit); +module_init(sgiseeq_module_init); +module_exit(sgiseeq_module_exit); MODULE_DESCRIPTION("SGI Seeq 8003 driver"); MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>"); diff --git a/drivers/net/skge.c b/drivers/net/skge.c index e0489578945d..776692946562 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -3802,6 +3802,9 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state) struct skge_hw *hw = pci_get_drvdata(pdev); int i, err, wol = 0; + if (!hw) + return 0; + err = pci_save_state(pdev); if (err) return err; @@ -3830,6 +3833,9 @@ static int skge_resume(struct pci_dev *pdev) struct skge_hw *hw = pci_get_drvdata(pdev); int i, err; + if (!hw) + return 0; + err = pci_set_power_state(pdev, PCI_D0); if (err) goto out; @@ -3868,6 +3874,9 @@ static void skge_shutdown(struct pci_dev *pdev) struct skge_hw *hw = pci_get_drvdata(pdev); int i, wol = 0; + if (!hw) + return; + for (i = 0; i < hw->ports; i++) { struct net_device *dev = hw->dev[i]; struct skge_port *skge = netdev_priv(dev); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a307310f13f5..104e20456e6f 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -40,6 +40,7 @@ #include <linux/if_vlan.h> #include <linux/prefetch.h> #include <linux/mii.h> +#include <linux/dmi.h> #include <asm/irq.h> @@ -130,7 +131,7 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ +// { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ { 0 } }; @@ -150,6 +151,8 @@ static const char *yukon2_name[] = { "FE", /* 0xb7 */ }; +static int dmi_blacklisted; + /* Access to external PHY */ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) { @@ -2531,6 +2534,17 @@ static int __devinit sky2_init(struct sky2_hw *hw) return -EOPNOTSUPP; } + + /* Some Gigabyte motherboards have 88e8056 but cause problems + * There is some unresolved hardware related problem that causes + * descriptor errors and receive data corruption. + */ + if (hw->chip_id == CHIP_ID_YUKON_EC_U && dmi_blacklisted) { + dev_err(&hw->pdev->dev, + "88E8056 on this motherboard not supported\n"); + return -EOPNOTSUPP; + } + hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); hw->ports = 1; t8 = sky2_read8(hw, B2_Y2_HW_RES); @@ -3578,17 +3592,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out; } - /* Some Gigabyte motherboards have 88e8056 but cause problems - * There is some unresolved hardware related problem that causes - * descriptor errors and receive data corruption. - */ - if (pdev->vendor == PCI_VENDOR_ID_MARVELL && - pdev->device == 0x4364 && pdev->subsystem_vendor == 0x1458) { - dev_err(&pdev->dev, - "88E8056 on Gigabyte motherboards not supported\n"); - goto err_out_disable; - } - err = pci_request_regions(pdev, DRV_NAME); if (err) { dev_err(&pdev->dev, "cannot obtain PCI resources\n"); @@ -3732,6 +3735,7 @@ err_out_free_regions: err_out_disable: pci_disable_device(pdev); err_out: + pci_set_drvdata(pdev, NULL); return err; } @@ -3784,6 +3788,9 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) struct sky2_hw *hw = pci_get_drvdata(pdev); int i, wol = 0; + if (!hw) + return 0; + del_timer_sync(&hw->idle_timer); netif_poll_disable(hw->dev[0]); @@ -3815,6 +3822,9 @@ static int sky2_resume(struct pci_dev *pdev) struct sky2_hw *hw = pci_get_drvdata(pdev); int i, err; + if (!hw) + return 0; + err = pci_set_power_state(pdev, PCI_D0); if (err) goto out; @@ -3861,6 +3871,9 @@ static void sky2_shutdown(struct pci_dev *pdev) struct sky2_hw *hw = pci_get_drvdata(pdev); int i, wol = 0; + if (!hw) + return; + del_timer_sync(&hw->idle_timer); netif_poll_disable(hw->dev[0]); @@ -3897,8 +3910,24 @@ static struct pci_driver sky2_driver = { .shutdown = sky2_shutdown, }; +static struct dmi_system_id __initdata broken_dmi_table[] = { + { + .ident = "Gigabyte 965P-S3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Gigabyte Technology Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "965P-S3"), + + }, + }, + { } +}; + static int __init sky2_init_module(void) { + /* Look for sick motherboards */ + if (dmi_check_system(broken_dmi_table)) + dmi_blacklisted = 1; + return pci_register_driver(&sky2_driver); } diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index c15e97253ede..108adbf5b5eb 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -175,12 +175,10 @@ spider_net_setup_aneg(struct spider_net_card *card) { struct mii_phy *phy = &card->phy; u32 advertise = 0; - u16 bmcr, bmsr, stat1000, estat; + u16 bmsr, estat; - bmcr = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMCR); - bmsr = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR); - stat1000 = spider_net_read_phy(card->netdev, phy->mii_id, MII_STAT1000); - estat = spider_net_read_phy(card->netdev, phy->mii_id, MII_ESTATUS); + bmsr = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR); + estat = spider_net_read_phy(card->netdev, phy->mii_id, MII_ESTATUS); if (bmsr & BMSR_10HALF) advertise |= ADVERTISED_10baseT_Half; diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 8897f538a7c7..4fc8681bc110 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -2,10 +2,7 @@ # wan devices configuration # -menu "Wan interfaces" - depends on NETDEVICES - -config WAN +menuconfig WAN bool "Wan interfaces support" ---help--- Wide Area Networks (WANs), such as X.25, Frame Relay and leased @@ -23,10 +20,12 @@ config WAN If unsure, say N. +if WAN + # There is no way to detect a comtrol sv11 - force it modular for now. config HOSTESS_SV11 tristate "Comtrol Hostess SV-11 support" - depends on WAN && ISA && m && ISA_DMA_API && INET + depends on ISA && m && ISA_DMA_API && INET help Driver for Comtrol Hostess SV-11 network card which operates on low speed synchronous serial links at up to @@ -38,7 +37,7 @@ config HOSTESS_SV11 # The COSA/SRP driver has not been tested as non-modular yet. config COSA tristate "COSA/SRP sync serial boards support" - depends on WAN && ISA && m && ISA_DMA_API + depends on ISA && m && ISA_DMA_API ---help--- Driver for COSA and SRP synchronous serial boards. @@ -62,7 +61,7 @@ config COSA # config LANMEDIA tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards" - depends on WAN && PCI + depends on PCI ---help--- Driver for the following Lan Media family of serial boards: @@ -89,7 +88,7 @@ config LANMEDIA # There is no way to detect a Sealevel board. Force it modular config SEALEVEL_4021 tristate "Sealevel Systems 4021 support" - depends on WAN && ISA && m && ISA_DMA_API && INET + depends on ISA && m && ISA_DMA_API && INET help This is a driver for the Sealevel Systems ACB 56 serial I/O adapter. @@ -99,7 +98,6 @@ config SEALEVEL_4021 # Generic HDLC config HDLC tristate "Generic HDLC layer" - depends on WAN help Say Y to this option if your Linux box contains a WAN (Wide Area Network) card supported by this driver and you are planning to @@ -167,7 +165,7 @@ config HDLC_X25 If unsure, say N. comment "X.25/LAPB support is disabled" - depends on WAN && HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y + depends on HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y config PCI200SYN tristate "Goramo PCI200SYN support" @@ -230,10 +228,10 @@ config PC300_MLPPP Multilink PPP over the PC300 synchronous communication boards. comment "Cyclades-PC300 MLPPP support is disabled." - depends on WAN && HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP) + depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP) comment "Refer to the file README.mlppp, provided by PC300 package." - depends on WAN && HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP) + depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP) config PC300TOO tristate "Cyclades PC300 RSV/X21 alternative support" @@ -338,7 +336,6 @@ config DSCC4_PCI_RST config DLCI tristate "Frame Relay DLCI support" - depends on WAN ---help--- Support for the Frame Relay protocol. @@ -385,7 +382,7 @@ config SDLA # Wan router core. config WAN_ROUTER_DRIVERS tristate "WAN router drivers" - depends on WAN && WAN_ROUTER + depends on WAN_ROUTER ---help--- Connect LAN to WAN via Linux box. @@ -440,7 +437,7 @@ config CYCLOMX_X25 # X.25 network drivers config LAPBETHER tristate "LAPB over Ethernet driver (EXPERIMENTAL)" - depends on WAN && LAPB && X25 + depends on LAPB && X25 ---help--- Driver for a pseudo device (typically called /dev/lapb0) which allows you to open an LAPB point-to-point connection to some other computer @@ -456,7 +453,7 @@ config LAPBETHER config X25_ASY tristate "X.25 async driver (EXPERIMENTAL)" - depends on WAN && LAPB && X25 + depends on LAPB && X25 ---help--- Send and receive X.25 frames over regular asynchronous serial lines such as telephone lines equipped with ordinary modems. @@ -471,7 +468,7 @@ config X25_ASY config SBNI tristate "Granch SBNI12 Leased Line adapter support" - depends on WAN && X86 + depends on X86 ---help--- Driver for ISA SBNI12-xx cards which are low cost alternatives to leased line modems. @@ -497,5 +494,4 @@ config SBNI_MULTILINE If unsure, say N. -endmenu - +endif # WAN diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index 19c935071d8e..56a8ea1fbf04 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile @@ -1,5 +1,3 @@ -# EXTRA_CFLAGS += -Wpacked - usb8xxx-objs := main.o fw.o wext.o \ rx.o tx.o cmd.o \ cmdresp.o scan.o \ @@ -7,13 +5,6 @@ usb8xxx-objs := main.o fw.o wext.o \ ioctl.o debugfs.o \ ethtool.o assoc.o -ifeq ($(CONFIG_LIBERTAS_USB_DEBUG), y) -EXTRA_CFLAGS += -DDEBUG -DPROC_DEBUG -endif - - -# This is needed to support the newer boot2 bootloader (v >= 3104) -EXTRA_CFLAGS += -DSUPPORT_BOOT_COMMAND usb8xxx-objs += if_bootcmd.o usb8xxx-objs += if_usb.o diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index 688da4c784b1..378577200b56 100644 --- a/drivers/net/wireless/libertas/README +++ b/drivers/net/wireless/libertas/README @@ -40,64 +40,11 @@ NAME SYNOPSIS iwpriv <ethX> <command> [sub-command] ... - iwpriv ethX version - iwpriv ethX scantype [sub-command] - iwpriv ethX getSNR <n> - iwpriv ethX getNF <n> - iwpriv ethX getRSSI <n> - iwpriv ethX setrxant <n> - iwpriv ethX getrxant - iwpriv ethX settxant <n> - iwpriv ethX gettxant - iwpriv ethX authalgs <n> - iwpriv ethX pre-TBTT <n> - iwpriv ethX 8021xauthalgs <n> - iwpriv ethX encryptionmode <n> iwpriv ethX setregioncode <n> iwpriv ethX getregioncode - iwpriv ethX setbcnavg <n> - iwpriv ethX getbcnavg - iwpriv ethX setdataavg <n> - iwpriv ethX setlisteninter <n> - iwpriv ethX getlisteninter - iwpriv ethX setmultipledtim <n> - iwpriv ethX getmultipledtim - iwpriv ethX atimwindow <n> - iwpriv ethX deauth - iwpriv ethX adhocstop - iwpriv ethX radioon - iwpriv ethX radiooff - iwpriv ethX reasso-on - iwpriv ethX reasso-off - iwpriv ethX scanmode [sub-command] - iwpriv ethX setwpaie <n> - iwpriv ethX wlanidle-off - iwpriv ethX wlanidle-on - iwpriv ethX getcis - iwpriv ethX getlog - iwpriv ethX getadhocstatus - iwpriv ethX adhocgrate <n> - -Version 4 Command: - iwpriv ethX inactvityto <n> - iwpriv ethX sleeppd <n> - iwpriv ethX enable11d <n> - iwpriv ethX tpccfg <n> - iwpriv ethX powercfg <n> - iwpriv ethX setafc <n> - iwpriv ethX getafc Version 5 Command: iwpriv ethX ledgpio <n> - iwpriv ethX scanprobes <n> - iwpriv ethX lolisteninter <n> - iwpriv ethX rateadapt <n> <m> - iwpriv ethX txcontrol <n> - iwpriv ethX psnullinterval <n> - iwpriv ethX prescan <n> - iwpriv ethX getrxinfo - iwpriv ethX gettxrate - iwpriv ethX beaconinterval BT Commands: The blinding table (BT) contains a list of mac addresses that should be @@ -150,114 +97,6 @@ DESCRIPTION The ethX parameter specifies the network device that is to be used to perform this command on. it could be eth0, eth1 etc. -version - This is used to get the current version of the driver and the firmware. - -scantype - This command is used to set the scan type to be used by the driver in - the scan command. This setting will not be used while performing a scan - for a specific SSID, as it is always done with scan type being active. - - where the sub-commands are: - - active -- to set the scan type to active - passive -- to set the scan type to passive - get -- to get the scan type set in the driver - -getSNR - This command gets the average and non average value of Signal to Noise - Ratio of Beacon and Data. - - where value is:- - 0 -- Beacon non-average. - 1 -- Beacon average. - 2 -- Data non-average. - 3 -- Data average. - - If no value is given, all four values are returned in the order mentioned - above. - - Note: This command is available only when STA is connected. - -getRSSI - This command gets the average and non average value os Receive Signal - Strength of Beacon and Data. - - where value is:- - 0 -- Beacon non-average. - 1 -- Beacon average. - 2 -- Data non-average. - 3 -- Data average. - - Note: This command is available only when STA is connected. - -getNF - This command gets the average and non average value of Noise Floor of - Beacon and Data. - - where value is:- - 0 -- Beacon non-average. - 1 -- Beacon average. - 2 -- Data non-average. - 3 -- Data average. - - Note: This command is available only when STA is connected. - -setrxant - This command is used to set the mode for Rx antenna. - - The options that can be sent are:- - 1 -- Antenna 1. - 2 -- Antenna 2. - 0xFFFF -- Diversity. - - Usage: - iwpriv ethX setrxant 0x01: select Antenna 1. - -getrxant - This command is used to get the mode for Rx antenna. - - -settxant - This command is used to set the mode for Tx antenna. - The options that can be sent are:- - 1 -- Antenna 1. - 2 -- Antenna 2. - 0xFFFF -- Diversity. - Usage: - iwpriv ethX settxant 0x01: select Antenna 1. - -gettxant - This command is used to get the mode for Tx antenna. - -authalgs - This command is used by the WPA supplicant to set the authentication - algorithms in the station. - -8021xauthalgs - This command is used by the WPA supplicant to set the 8021.x authentication algorithm type - station. - - where values can be:- - 1 -- None - 2 -- LEAP - 4 -- TLS - 8 -- TTLs - 16 -- MD5 - - -encryptionmode - This command is used by the WPA supplicant to set the encryption algorithm. - - where values can be:- - 0 -- NONE - 1 -- WEP40 - 2 -- TKIP - 3 -- CCMP - 4 -- WEP104 - -pre-TBTT - This command is used to set pre-TBTT time period where value is in microseconds. - setregioncode This command is used to set the region code in the station. where value is 'region code' for various regions like @@ -270,114 +109,6 @@ getregioncode This command is used to get the region code information set in the station. -setbcnavg - Set the weighting factor for calculating RSSI. - -getbcnavg - Get weighting factor for calculating RSSI. - -setdataavg - Set the weighting factor for calculating SNR. - -setlisteninter - This command is used to set the listen interval in the - station. - - where the value ranges between 1 - 255 - -getlisteninter - This command is used to get the listen interval value set in the - station. - -setmultipledtim - This command is used to set the multiple dtim value in the - station. - where the value is 1,2,3,4,5,0xfffe - 0xfffe means the firmware will use listen interval in association - command for waking up - -getmultipledtim - This command is used to get the multiple dtim value set in the station. - -atimwindow - This command is used to set the atim value in the - station. - - where the value ranges between 0 - 50 - -deauth - This command is used to send the de-authentication to the AP with which - the station is associated. This command is valid only when - station is in Infrastructure mode. - - Note: This command is available only when STA is connected. - -adhocstop - This command is used to stop beacon transmission from the station and - go into idle state in ad-hoc mode. - - Note: This command is available only when STA is connected. - -radioon - This command is used to turn on the RF antenna. - -radiooff - This command is sued to turn off the RF antenna. - -scanmode - This command is used to set the station to scan for either IBSS - networks or BSS networks or both BSS and IBSS networks. This - command can be used with sub commands, - - where the value for - bss -- Scan All the BSS networks. - ibss -- Scan All the IBSS networks. - any -- Scan both BSS and IBSS networks. - - - -setwpaie - This command is used by WPA supplicant to send the WPA-IE to the driver. - -wlanidle-off - This command is used to get into idle state. - - Note: This command is available only when STA is connected. - -wlanidle-on - This command is used to get off the idle state. - - Note: This command is available only when STA is connected. - - -getlog - This command is used to get the 802.11 statistics available in the - station. - - Note: This command is available only when STA is connected. - -getadhocstatus - This command is used to get the ad-hoc Network Status. - - The various status codes are: - AdhocStarted - AdhocJoined - AdhocIdle - InfraMode - AutoUnknownMode - - Note: This command is available only when STA is connected. - -adhocgrate - This command is used to enable(1) g_rate, Disable(0) g_rate - and request(2) the status which g_rate is disabled/enabled, - for Ad-hoc creator. - - where value is:- - 0 -- Disabled - 1 -- Enabled - 2 -- Get - ledgpio This command is used to set/get LEDs. @@ -400,253 +131,6 @@ ledgpio Note: LED0 is invalid Note: Maximum Number of LEDs are 16. -inactivityto - This command is used by the host to set/get the inactivity timeout value, - which specifies when WLAN device is put to sleep. - - Usage: - iwpriv ethX inactivityto [<timeout>] - - where the parameter are: - timeout: timeout value in milliseconds. - - Example: - iwpriv eth1 inactivityto - "get the timeout value" - - iwpriv eth1 inactivityto X - "set timeout value to X ms" - - -sleeppd - This command is used to configure the sleep period of the WLAN device. - - Usage: - iwpriv ethX sleeppd [<sleep period>] - - where the parameter are: - Period: sleep period in milliseconds. Range 10~60. - - Example: - iwpriv eth1 sleeppd 10 - "set period as 10 ms" - iwpriv eth1 sleeppd - "get the sleep period configuration" - -enable11d - This command is used to control 11d - where value is:- - 1 -- Enabled - 0 -- Disabled - 2 -- Get - - - - -tpccfg - Enables or disables automatic transmit power control. - - The first parameter turns this feature on (1) or off (0). When turning - on, the user must also supply four more parameters in the following - order: - -UseSNR (Use SNR (in addition to PER) for TPC algorithm), - -P0 (P0 power level for TPC), - -P1 (P1 power level for TPC), - -P2 (P2 power level for TPC). - - Usage: - iwpriv ethX tpccfg: Get current configuration - iwpriv ethX tpccfg 0: disable auto TPC - iwpriv ethX tpccfg 0x01 0x00 0x05 0x0a 0x0d: enable auto TPC; do not use SNR; - P0=0x05; P1=0x0a; P2=0x0d; - iwpriv ethX tpccfg 0x01 0x01 0x05 0x0a 0x0d: enable auto TPC; use SNR; - P0=0x05; P1=0x0a; P2=0x0d. - -powercfg - Enables or disables power adaptation. - - The first parameter turns this feature on (1) or off (0). When turning - on, the user must also supply three more parameters in the following - order: - -P0 (P0 power level for Power Adaptation), - -P1 (P1 power level for Power Adaptation), - -P2 (P2 power level for Power Adaptation). - - Usage: - iwpriv ethX powercfg: Get current configuration - iwpriv ethX powercfg 0: disable power adaptation - iwpriv ethX powercfg 1 0x0d 0x0f 0x12: enable power adaptation; - P0=0x0d; P1=0x0f; P2=0x12. - -getafc - This command returns automatic frequency control parameters. It returns - three integers: - -P0: automatic is on (1), or off (0), - -P1: current timing offset in PPM (part per million), and - -P2: current frequency offset in PPM. - -setafc - Set automatic frequency control options. - - The first parameter turns automatic on (1) or off (0). - The user must supply two more parameters in either case, in the following - order: - - When auto is on: - - -P0 (automatic adjustment frequency threshold in PPM), - -P1 (automatic adjustment period in beacon period), - - When auto is off: - - -P0 (manual adjustment timing offset in PPM), and - -P1 (manual adjustment frequency offset in PPM). - - Usage: - iwpriv ethX setafc 0 10 10: manual adjustment, both timing and frequcncy - offset are 10 PPM. - - iwpriv ethX setafc 1 10 10 enable afc, automatic adjustment, - frequency threshold 10 PPM, for every 10 beacon periods. - - - -scanprobes - This command sets number of probe requests per channel. - - Usage: - iwpriv ethX scanprobes 3 (set scan probes to 3) - iwpriv ethX scanprobes (get scan probes) - -lolisteninter - This command sets the value of listen interval. - - Usage: - iwpriv ethX lolisteninter 234 (set the lolisteninter to 234) - iwpriv ethX lolisteninter (get the lolisteninter value) - -rateadapt - This command sets the data rates bitmap. - Where <n> - 0: Disable auto rate adapt - 1: Enable auto rate adapt - - <m> - data rate bitmap - Bit Data rate - 0 1 Mbps - 1 2 Mbps - 2 5.5 Mbps - 3 11 Mbps - 4 Reserved - 5 6 Mbps - 6 9 Mbps - 7 12 Mbps - 8 18 Mbps - 9 24 Mbps - 10 36 Mbps - 11 48 Mbps - 12 54 Mbps - 12-15 Reserved - - Usage: - iwpriv ethX rateadapt - read the currect data rate setting - iwpriv ethX rateadapt 1 0x07 - enable auto data rate adapt and - data rates are 1Mbps, 2Mbsp and 5.5Mbps - - -txcontrol - This command is used to set the Tx rate, ack policy, and retry limit on a per packet basis. - - Where value <n> is: - if bit[4] == 1: - bit[3:0] -- 0 1 2 3 4 5 6 7 8 9 10 11 12 13-16 - Data Rate(Mbps) -- 1 2 5.5 11 Rsv 6 9 12 18 24 36 48 54 Rsv - - bit[12:8] - if bit[12] == 1, bit[11:8] specifies the Tx retry limit. - - bit[14:13] specifies per packet ack policy: - bit[14:13] - 1 0 use immediate ack policy for this packet - 1 1 use no ack policy for this packet - 0 x use the per-packet ack policy setting - - Usage: - iwpriv ethX txcontrol 0x7513 - Use no-ack policy, 5 retires for Tx, 11Mbps rate - - - -psnullinterval - This command is used to set/request NULL package interval for Power Save - under infrastructure mode. - - where value is:- - -1 -- Disabled - n>0 -- Set interval as n (seconds) - -prescan - This command is used to enable (1)/disable(0) auto prescan before assoicate to the ap - - where value is:- - 0 -- Disabled - 1 -- Enabled - 2 -- Get - -getrxinfo - This command gets non average value of Signal to Noise Ratio of Data and rate index. - - The following table shows RateIndex and Rate - - RateIndex Data rate - 0 1 Mbps - 1 2 Mbps - 2 5.5 Mbps - 3 11 Mbps - 4 Reserved - 5 6 Mbps - 6 9 Mbps - 7 12 Mbps - 8 18 Mbps - 9 24 Mbps - 10 36 Mbps - 11 48 Mbps - 12 54 Mbps - 13-15 Reserved - -gettxrate - This command gets current Tx rate index of the first packet associated with Rate Adaptation. - - The following table shows RateIndex and Rate - - RateIndex Data rate - 0 1 Mbps - 1 2 Mbps - 2 5.5 Mbps - 3 11 Mbps - 4 Reserved - 5 6 Mbps - 6 9 Mbps - 7 12 Mbps - 8 18 Mbps - 9 24 Mbps - 10 36 Mbps - 11 48 Mbps - 12 54 Mbps - 13-15 Reserved - -bcninterval - This command is used to sets beacon interval in adhoc mode when an argument is given, and gets current adhoc - beacon interval when no argument is given. The valid beacon interval is between 20 - 1000, - default beacon interval is 100. - - Usage: - iwpriv ethX bcninterval 100 (set adhoc beacon interval to 100) - iwpriv ethX bcninterval (get adhoc beacon interval) - fwt_add This command is used to insert an entry into the FWT table. The list of parameters must follow the following structure: diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index b55c7f57aca8..c260bd1b3d46 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -23,13 +23,13 @@ static int assoc_helper_essid(wlan_private *priv, ENTER(); lbs_pr_debug(1, "New SSID requested: %s\n", assoc_req->ssid.ssid); - if (assoc_req->mode == wlan802_11infrastructure) { + if (assoc_req->mode == IW_MODE_INFRA) { if (adapter->prescan) { libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1); } i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, - NULL, wlan802_11infrastructure); + NULL, IW_MODE_INFRA); if (i >= 0) { lbs_pr_debug(1, "SSID found in scan list ... associating...\n"); @@ -44,7 +44,7 @@ static int assoc_helper_essid(wlan_private *priv, lbs_pr_debug(1, "SSID '%s' not found; cannot associate\n", assoc_req->ssid.ssid); } - } else if (assoc_req->mode == wlan802_11ibss) { + } else if (assoc_req->mode == IW_MODE_ADHOC) { /* Scan for the network, do not save previous results. Stale * scan data will cause us to join a non-existant adhoc network */ @@ -52,7 +52,7 @@ static int assoc_helper_essid(wlan_private *priv, /* Search for the requested SSID in the scan table */ i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL, - wlan802_11ibss); + IW_MODE_ADHOC); if (i >= 0) { lbs_pr_debug(1, "SSID found at %d in List, so join\n", ret); libertas_join_adhoc_network(priv, &adapter->scantable[i]); @@ -90,10 +90,10 @@ static int assoc_helper_bssid(wlan_private *priv, goto out; } - if (assoc_req->mode == wlan802_11infrastructure) { + if (assoc_req->mode == IW_MODE_INFRA) { ret = wlan_associate(priv, &adapter->scantable[i]); lbs_pr_debug(1, "ASSOC: return from wlan_associate(bssd) was %d\n", ret); - } else if (assoc_req->mode == wlan802_11ibss) { + } else if (assoc_req->mode == IW_MODE_ADHOC) { libertas_join_adhoc_network(priv, &adapter->scantable[i]); } memcpy(&assoc_req->ssid, &adapter->scantable[i].ssid, @@ -142,23 +142,23 @@ static int assoc_helper_mode(wlan_private *priv, ENTER(); - if (assoc_req->mode == adapter->inframode) { + if (assoc_req->mode == adapter->mode) { LEAVE(); return 0; } - if (assoc_req->mode == wlan802_11infrastructure) { + if (assoc_req->mode == IW_MODE_INFRA) { if (adapter->psstate != PS_STATE_FULL_POWER) libertas_ps_wakeup(priv, cmd_option_waitforrsp); adapter->psmode = wlan802_11powermodecam; } - adapter->inframode = assoc_req->mode; + adapter->mode = assoc_req->mode; ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib, 0, cmd_option_waitforrsp, OID_802_11_INFRASTRUCTURE_MODE, - (void *) assoc_req->mode); + (void *) (size_t) assoc_req->mode); LEAVE(); return ret; @@ -196,7 +196,7 @@ static int assoc_helper_wep_keys(wlan_private *priv, goto out; /* enable/disable the MAC's WEP packet filter */ - if (assoc_req->secinfo.WEPstatus == wlan802_11WEPenabled) + if (assoc_req->secinfo.wep_enabled) adapter->currentpacketfilter |= cmd_act_mac_wep_enable; else adapter->currentpacketfilter &= ~cmd_act_mac_wep_enable; @@ -300,8 +300,7 @@ static int should_deauth_infrastructure(wlan_adapter *adapter, } if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { - if (adapter->secinfo.authmode != - assoc_req->secinfo.authmode) { + if (adapter->secinfo.auth_mode != assoc_req->secinfo.auth_mode) { lbs_pr_debug(1, "Deauthenticating due to updated security " "info in configuration request.\n"); return 1; @@ -316,7 +315,7 @@ static int should_deauth_infrastructure(wlan_adapter *adapter, /* FIXME: deal with 'auto' mode somehow */ if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { - if (assoc_req->mode != wlan802_11infrastructure) + if (assoc_req->mode != IW_MODE_INFRA) return 1; } @@ -333,12 +332,12 @@ static int should_stop_adhoc(wlan_adapter *adapter, if (adapter->curbssparams.ssid.ssidlength != assoc_req->ssid.ssidlength) return 1; if (memcmp(adapter->curbssparams.ssid.ssid, assoc_req->ssid.ssid, - sizeof(struct WLAN_802_11_SSID))) + adapter->curbssparams.ssid.ssidlength)) return 1; /* FIXME: deal with 'auto' mode somehow */ if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { - if (assoc_req->mode != wlan802_11ibss) + if (assoc_req->mode != IW_MODE_ADHOC) return 1; } @@ -382,7 +381,7 @@ void wlan_association_worker(struct work_struct *work) } if (find_any_ssid) { - enum WLAN_802_11_NETWORK_INFRASTRUCTURE new_mode; + u8 new_mode; ret = libertas_find_best_network_SSID(priv, &assoc_req->ssid, assoc_req->mode, &new_mode); @@ -393,7 +392,7 @@ void wlan_association_worker(struct work_struct *work) } /* Ensure we switch to the mode of the AP */ - if (assoc_req->mode == wlan802_11autounknown) { + if (assoc_req->mode == IW_MODE_AUTO) { set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); assoc_req->mode = new_mode; } @@ -403,7 +402,7 @@ void wlan_association_worker(struct work_struct *work) * Check if the attributes being changing require deauthentication * from the currently associated infrastructure access point. */ - if (adapter->inframode == wlan802_11infrastructure) { + if (adapter->mode == IW_MODE_INFRA) { if (should_deauth_infrastructure(adapter, assoc_req)) { ret = libertas_send_deauthentication(priv); if (ret) { @@ -412,7 +411,7 @@ void wlan_association_worker(struct work_struct *work) ret); } } - } else if (adapter->inframode == wlan802_11ibss) { + } else if (adapter->mode == IW_MODE_ADHOC) { if (should_stop_adhoc(adapter, assoc_req)) { ret = libertas_stop_adhoc_network(priv); if (ret) { @@ -543,7 +542,7 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter) assoc_req->channel = adapter->curbssparams.channel; if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) - assoc_req->mode = adapter->inframode; + assoc_req->mode = adapter->mode; if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { memcpy(&assoc_req->bssid, adapter->curbssparams.bssid, diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index bfdac58b5c06..de9cb46a70ff 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -381,15 +381,16 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv, switch (cmd_oid) { case OID_802_11_INFRASTRUCTURE_MODE: { - enum WLAN_802_11_NETWORK_INFRASTRUCTURE mode = - (enum WLAN_802_11_NETWORK_INFRASTRUCTURE) pdata_buf; + u8 mode = (u8) (size_t) pdata_buf; pSNMPMIB->querytype = cpu_to_le16(cmd_act_set); pSNMPMIB->oid = cpu_to_le16((u16) desired_bsstype_i); pSNMPMIB->bufsize = sizeof(u8); - if (mode == wlan802_11infrastructure) - ucTemp = SNMP_MIB_VALUE_INFRA; - else + if (mode == IW_MODE_ADHOC) { ucTemp = SNMP_MIB_VALUE_ADHOC; + } else { + /* Infra and Auto modes */ + ucTemp = SNMP_MIB_VALUE_INFRA; + } memmove(pSNMPMIB->value, &ucTemp, sizeof(u8)); @@ -947,8 +948,8 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u spin_unlock_irqrestore(&adapter->driver_lock, flags); - lbs_pr_debug(1, "QUEUE_CMD: Inserted node=0x%x, cmd=0x%x in cmdpendingq\n", - (u32) cmdnode, + lbs_pr_debug(1, "QUEUE_CMD: Inserted node=%p, cmd=0x%x in cmdpendingq\n", + cmdnode, ((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command); done: @@ -976,8 +977,8 @@ static int DownloadcommandToStation(wlan_private * priv, ENTER(); if (!adapter || !cmdnode) { - lbs_pr_debug(1, "DNLD_CMD: adapter = %#x, cmdnode = %#x\n", - (int)adapter, (int)cmdnode); + lbs_pr_debug(1, "DNLD_CMD: adapter = %p, cmdnode = %p\n", + adapter, cmdnode); if (cmdnode) { spin_lock_irqsave(&adapter->driver_lock, flags); __libertas_cleanup_and_insert_cmd(priv, cmdnode); @@ -1174,8 +1175,8 @@ int libertas_prepare_and_send_command(wlan_private * priv, cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr; - lbs_pr_debug(1, "PREP_CMD: Val of cmd ptr =0x%x, command=0x%X\n", - (u32) cmdptr, cmd_no); + lbs_pr_debug(1, "PREP_CMD: Val of cmd ptr=%p, command=0x%X\n", + cmdptr, cmd_no); if (!cmdptr) { lbs_pr_debug(1, "PREP_CMD: bufvirtualaddr of cmdnode is NULL\n"); diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index cdb012c7e9cf..c86454034b58 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -72,8 +72,6 @@ void libertas_mac_event_disconnected(wlan_private * priv) adapter->secinfo.WPAenabled = 0; adapter->secinfo.WPA2enabled = 0; adapter->wpa_ie_len = 0; - adapter->secinfo.auth1xalg = WLAN_1X_AUTH_ALG_NONE; - adapter->secinfo.Encryptionmode = CIPHER_NONE; adapter->connect_status = libertas_disconnected; @@ -811,7 +809,7 @@ int libertas_process_rx_command(wlan_private * priv) if (result) { lbs_pr_debug(1, "CMD_RESP: PS command failed- %#x \n", resp->result); - if (adapter->inframode == wlan802_11ibss) { + if (adapter->mode == IW_MODE_ADHOC) { /* * We should not re-try enter-ps command in * ad-hoc mode. It takes place in diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 51dfd202f558..7d7bc5e86a56 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -7,6 +7,7 @@ #include "dev.h" #include "decl.h" #include "host.h" +#include "debugfs.h" static struct dentry *libertas_dir = NULL; static char *szStates[] = { @@ -276,7 +277,7 @@ static void libertas_parse_ssid(char *buf, size_t count, if (!end) end = buf + count - 1; - size = min(IW_ESSID_MAX_SIZE, end - hold); + size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold)); strncpy(scan_cfg->specificSSID, hold, size); return; @@ -1648,7 +1649,7 @@ struct libertas_debugfs_files { struct file_operations fops; }; -struct libertas_debugfs_files debugfs_files[] = { +static struct libertas_debugfs_files debugfs_files[] = { { "info", 0444, FOPS(libertas_dev_info, write_file_dummy), }, { "getscantable", 0444, FOPS(libertas_getscantable, write_file_dummy), }, @@ -1658,7 +1659,7 @@ struct libertas_debugfs_files debugfs_files[] = { { "setuserscan", 0600, FOPS(NULL, libertas_setuserscan), }, }; -struct libertas_debugfs_files debugfs_events_files[] = { +static struct libertas_debugfs_files debugfs_events_files[] = { {"low_rssi", 0644, FOPS(libertas_lowrssi_read, libertas_lowrssi_write), }, {"low_snr", 0644, FOPS(libertas_lowsnr_read, @@ -1673,7 +1674,7 @@ struct libertas_debugfs_files debugfs_events_files[] = { libertas_highsnr_write), }, }; -struct libertas_debugfs_files debugfs_regs_files[] = { +static struct libertas_debugfs_files debugfs_regs_files[] = { {"rdmac", 0644, FOPS(libertas_rdmac_read, libertas_rdmac_write), }, {"wrmac", 0600, FOPS(NULL, libertas_wrmac_write), }, {"rdbbp", 0644, FOPS(libertas_rdbbp_read, libertas_rdbbp_write), }, @@ -1778,7 +1779,7 @@ void libertas_debugfs_remove_one(wlan_private *priv) struct debug_data { char name[32]; u32 size; - u32 addr; + size_t addr; }; /* To debug any member of wlan_adapter, simply add one line here. @@ -1825,6 +1826,8 @@ static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf, val = *((u16 *) d[i].addr); else if (d[i].size == 4) val = *((u32 *) d[i].addr); + else if (d[i].size == 8) + val = *((u64 *) d[i].addr); pos += sprintf(p + pos, "%s=%d\n", d[i].name, val); } @@ -1844,7 +1847,7 @@ static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf, * @param data data to write * @return number of data */ -static int wlan_debugfs_write(struct file *f, const char __user *buf, +static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf, size_t cnt, loff_t *ppos) { int r, i; @@ -1886,12 +1889,14 @@ static int wlan_debugfs_write(struct file *f, const char __user *buf, *((u16 *) d[i].addr) = (u16) r; else if (d[i].size == 4) *((u32 *) d[i].addr) = (u32) r; + else if (d[i].size == 8) + *((u64 *) d[i].addr) = (u64) r; break; } while (1); } kfree(pdata); - return cnt; + return (ssize_t)cnt; } static struct file_operations libertas_debug_fops = { @@ -1916,20 +1921,10 @@ void libertas_debug_init(wlan_private * priv, struct net_device *dev) return; for (i = 0; i < num_of_items; i++) - items[i].addr += (u32) priv->adapter; + items[i].addr += (size_t) priv->adapter; priv->debugfs_debug = debugfs_create_file("debug", 0644, priv->debugfs_dir, &items[0], &libertas_debug_fops); } -/** - * @brief remove proc file - * - * @param priv pointer wlan_private - * @return N/A - */ -void libertas_debug_remove(wlan_private * priv) -{ - debugfs_remove(priv->debugfs_debug); -} diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index fb1478c1b87d..80dd9ea19c8e 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -9,6 +9,11 @@ extern unsigned int libertas_debug; +#ifdef CONFIG_LIBERTAS_DEBUG +#define DEBUG +#define PROC_DEBUG +#endif + #define DRV_NAME "usb8xxx" #define lbs_pr_info(format, args...) \ @@ -223,31 +228,6 @@ enum SNRNF_DATA { MAX_TYPE_AVG }; -/** WLAN_802_11_AUTH_ALG*/ -enum WLAN_802_11_AUTH_ALG { - AUTH_ALG_OPEN_SYSTEM = 1, - AUTH_ALG_SHARED_KEY = 2, - AUTH_ALG_NETWORK_EAP = 8, -}; - -/** WLAN_802_1X_AUTH_ALG */ -enum WLAN_802_1X_AUTH_ALG { - WLAN_1X_AUTH_ALG_NONE = 1, - WLAN_1X_AUTH_ALG_LEAP = 2, - WLAN_1X_AUTH_ALG_TLS = 4, - WLAN_1X_AUTH_ALG_TTLS = 8, - WLAN_1X_AUTH_ALG_MD5 = 16, -}; - -/** WLAN_802_11_ENCRYPTION_MODE */ -enum WLAN_802_11_ENCRYPTION_MODE { - CIPHER_NONE, - CIPHER_WEP40, - CIPHER_TKIP, - CIPHER_CCMP, - CIPHER_WEP104, -}; - /** WLAN_802_11_POWER_MODE */ enum WLAN_802_11_POWER_MODE { wlan802_11powermodecam, @@ -292,28 +272,6 @@ enum mv_ms_type { MVMS_EVENT }; -/** WLAN_802_11_NETWORK_INFRASTRUCTURE */ -enum WLAN_802_11_NETWORK_INFRASTRUCTURE { - wlan802_11ibss, - wlan802_11infrastructure, - wlan802_11autounknown, - /*defined as upper bound */ - wlan802_11infrastructuremax -}; - -/** WLAN_802_11_AUTHENTICATION_MODE */ -enum WLAN_802_11_AUTHENTICATION_MODE { - wlan802_11authmodeopen = 0x00, - wlan802_11authmodeshared = 0x01, - wlan802_11authmodenetworkEAP = 0x80, -}; - -/** WLAN_802_11_WEP_STATUS */ -enum WLAN_802_11_WEP_STATUS { - wlan802_11WEPenabled, - wlan802_11WEPdisabled, -}; - /** SNMP_MIB_INDEX_e */ enum SNMP_MIB_INDEX_e { desired_bsstype_i = 0, diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index b1f876f9693b..e8b9020f9bd6 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -10,6 +10,7 @@ #include <linux/wireless.h> #include <linux/ethtool.h> #include <linux/debugfs.h> +#include <net/ieee80211.h> #include "defs.h" #include "scan.h" @@ -56,10 +57,8 @@ struct region_channel { struct wlan_802_11_security { u8 WPAenabled; u8 WPA2enabled; - enum WLAN_802_11_WEP_STATUS WEPstatus; - enum WLAN_802_11_AUTHENTICATION_MODE authmode; - enum WLAN_802_1X_AUTH_ALG auth1xalg; - enum WLAN_802_11_ENCRYPTION_MODE Encryptionmode; + u8 wep_enabled; + u8 auth_mode; }; /** Current Basic Service Set State Structure */ @@ -184,7 +183,7 @@ struct assoc_request { struct WLAN_802_11_SSID ssid; u8 channel; - enum WLAN_802_11_NETWORK_INFRASTRUCTURE mode; + u8 mode; u8 bssid[ETH_ALEN]; /** WEP keys */ @@ -198,7 +197,6 @@ struct assoc_request { struct wlan_802_11_security secinfo; /** WPA Information Elements*/ -#define MAX_WPA_IE_LEN 64 u8 wpa_ie[MAX_WPA_IE_LEN]; u8 wpa_ie_len; }; @@ -254,7 +252,8 @@ struct _wlan_adapter { /** current ssid/bssid related parameters*/ struct current_bss_params curbssparams; - enum WLAN_802_11_NETWORK_INFRASTRUCTURE inframode; + /* IW_MODE_* */ + u8 mode; struct bss_descriptor *pattemptedbssdesc; @@ -339,7 +338,6 @@ struct _wlan_adapter { struct WLAN_802_11_KEY wpa_unicast_key; /** WPA Information Elements*/ -#define MAX_WPA_IE_LEN 64 u8 wpa_ie[MAX_WPA_IE_LEN]; u8 wpa_ie_len; diff --git a/drivers/net/wireless/libertas/fw.c b/drivers/net/wireless/libertas/fw.c index b194a4570791..441123c85e62 100644 --- a/drivers/net/wireless/libertas/fw.c +++ b/drivers/net/wireless/libertas/fw.c @@ -194,16 +194,13 @@ static void wlan_init_adapter(wlan_private * priv) adapter->scanmode = cmd_bss_type_any; /* 802.11 specific */ - adapter->secinfo.WEPstatus = wlan802_11WEPdisabled; + adapter->secinfo.wep_enabled = 0; for (i = 0; i < sizeof(adapter->wep_keys) / sizeof(adapter->wep_keys[0]); i++) memset(&adapter->wep_keys[i], 0, sizeof(struct WLAN_802_11_KEY)); adapter->wep_tx_keyidx = 0; - adapter->secinfo.WEPstatus = wlan802_11WEPdisabled; - adapter->secinfo.authmode = wlan802_11authmodeopen; - adapter->secinfo.auth1xalg = WLAN_1X_AUTH_ALG_NONE; - adapter->secinfo.Encryptionmode = CIPHER_NONE; - adapter->inframode = wlan802_11infrastructure; + adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; + adapter->mode = IW_MODE_INFRA; adapter->assoc_req = NULL; diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 695fb6a66ffe..ae6f72a6cdf3 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -388,7 +388,7 @@ static int __if_usb_submit_rx_urb(wlan_private * priv, usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, cardp->bulk_in_endpointAddr), - skb->tail + IPFIELD_ALIGN_OFFSET, + (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET), MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, rinfo); @@ -626,6 +626,7 @@ static void if_usb_receive(struct urb *urb) cardp->usb_event_cause); if (cardp->usb_event_cause & 0xffff0000) { libertas_send_tx_feedback(priv); + spin_unlock(&priv->adapter->driver_lock); break; } cardp->usb_event_cause = le32_to_cpu(cardp->usb_event_cause) << 3; @@ -775,7 +776,6 @@ restart: return -1; } -#ifdef SUPPORT_BOOT_COMMAND cardp->bootcmdresp = 0; do { int j = 0; @@ -796,7 +796,6 @@ restart: } return -1; } -#endif i = 0; priv->adapter->fw_ready = 0; diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index 785116720bc6..170dfe6809f5 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h @@ -12,7 +12,6 @@ #define USB8388_VID_2 0x05a3 #define USB8388_PID_2 0x8388 -#ifdef SUPPORT_BOOT_COMMAND #define BOOT_CMD_FW_BY_USB 0x01 #define BOOT_CMD_FW_IN_EEPROM 0x02 #define BOOT_CMD_UPDATE_BOOT2 0x03 @@ -36,7 +35,6 @@ struct bootcmdrespStr u8 u8result; u8 au8dumy[2]; }; -#endif /* SUPPORT_BOOT_COMMAND */ /* read callback private data */ struct read_cb_info { diff --git a/drivers/net/wireless/libertas/ioctl.c b/drivers/net/wireless/libertas/ioctl.c index 82b39642423a..a8f76c358992 100644 --- a/drivers/net/wireless/libertas/ioctl.c +++ b/drivers/net/wireless/libertas/ioctl.c @@ -27,95 +27,6 @@ #define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ) -static int setrxantenna(wlan_private * priv, int mode) -{ - int ret = 0; - wlan_adapter *adapter = priv->adapter; - - if (mode != RF_ANTENNA_1 && mode != RF_ANTENNA_2 - && mode != RF_ANTENNA_AUTO) { - return -EINVAL; - } - - adapter->rxantennamode = mode; - - lbs_pr_debug(1, "SET RX Antenna mode to 0x%04x\n", adapter->rxantennamode); - - ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna, - cmd_act_set_rx, - cmd_option_waitforrsp, 0, - &adapter->rxantennamode); - return ret; -} - -static int settxantenna(wlan_private * priv, int mode) -{ - int ret = 0; - wlan_adapter *adapter = priv->adapter; - - if ((mode != RF_ANTENNA_1) && (mode != RF_ANTENNA_2) - && (mode != RF_ANTENNA_AUTO)) { - return -EINVAL; - } - - adapter->txantennamode = mode; - - lbs_pr_debug(1, "SET TX Antenna mode to 0x%04x\n", adapter->txantennamode); - - ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna, - cmd_act_set_tx, - cmd_option_waitforrsp, 0, - &adapter->txantennamode); - - return ret; -} - -static int getrxantenna(wlan_private * priv, char *buf) -{ - int ret = 0; - wlan_adapter *adapter = priv->adapter; - - // clear it, so we will know if the value - // returned below is correct or not. - adapter->rxantennamode = 0; - - ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna, - cmd_act_get_rx, - cmd_option_waitforrsp, 0, NULL); - - if (ret) { - LEAVE(); - return ret; - } - - lbs_pr_debug(1, "Get Rx Antenna mode:0x%04x\n", adapter->rxantennamode); - - return sprintf(buf, "0x%04x", adapter->rxantennamode) + 1; -} - -static int gettxantenna(wlan_private * priv, char *buf) -{ - int ret = 0; - wlan_adapter *adapter = priv->adapter; - - // clear it, so we will know if the value - // returned below is correct or not. - adapter->txantennamode = 0; - - ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna, - cmd_act_get_tx, - cmd_option_waitforrsp, 0, NULL); - - if (ret) { - LEAVE(); - return ret; - } - - lbs_pr_debug(1, "Get Tx Antenna mode:0x%04x\n", adapter->txantennamode); - - return sprintf(buf, "0x%04x", adapter->txantennamode) + 1; -} - static int wlan_set_region(wlan_private * priv, u16 region_code) { int i; @@ -144,998 +55,6 @@ static int wlan_set_region(wlan_private * priv, u16 region_code) return 0; } -/** - * @brief Get/Set Firmware wakeup method - * - * @param priv A pointer to wlan_private structure - * @param wrq A pointer to user data - * @return 0--success, otherwise fail - */ -static int wlan_txcontrol(wlan_private * priv, struct iwreq *wrq) -{ - wlan_adapter *adapter = priv->adapter; - int data; - ENTER(); - - if ((int)wrq->u.data.length == 0) { - if (copy_to_user - (wrq->u.data.pointer, &adapter->pkttxctrl, sizeof(u32))) { - lbs_pr_alert("copy_to_user failed!\n"); - return -EFAULT; - } - } else { - if ((int)wrq->u.data.length > 1) { - lbs_pr_alert("ioctl too many args!\n"); - return -EFAULT; - } - if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) { - lbs_pr_alert("Copy from user failed\n"); - return -EFAULT; - } - - adapter->pkttxctrl = (u32) data; - } - - wrq->u.data.length = 1; - - LEAVE(); - return 0; -} - -/** - * @brief Get/Set NULL Package generation interval - * - * @param priv A pointer to wlan_private structure - * @param wrq A pointer to user data - * @return 0--success, otherwise fail - */ -static int wlan_null_pkt_interval(wlan_private * priv, struct iwreq *wrq) -{ - wlan_adapter *adapter = priv->adapter; - int data; - ENTER(); - - if ((int)wrq->u.data.length == 0) { - data = adapter->nullpktinterval; - - if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) { - lbs_pr_alert( "copy_to_user failed!\n"); - return -EFAULT; - } - } else { - if ((int)wrq->u.data.length > 1) { - lbs_pr_alert( "ioctl too many args!\n"); - return -EFAULT; - } - if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -EFAULT; - } - - adapter->nullpktinterval = data; - } - - wrq->u.data.length = 1; - - LEAVE(); - return 0; -} - -static int wlan_get_rxinfo(wlan_private * priv, struct iwreq *wrq) -{ - wlan_adapter *adapter = priv->adapter; - int data[2]; - ENTER(); - data[0] = adapter->SNR[TYPE_RXPD][TYPE_NOAVG]; - data[1] = adapter->rxpd_rate; - if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) { - lbs_pr_debug(1, "Copy to user failed\n"); - return -EFAULT; - } - wrq->u.data.length = 2; - LEAVE(); - return 0; -} - -static int wlan_get_snr(wlan_private * priv, struct iwreq *wrq) -{ - int ret = 0; - wlan_adapter *adapter = priv->adapter; - int data[4]; - - ENTER(); - memset(data, 0, sizeof(data)); - if (wrq->u.data.length) { - if (copy_from_user(data, wrq->u.data.pointer, - min_t(size_t, wrq->u.data.length, 4) * sizeof(int))) - return -EFAULT; - } - if ((wrq->u.data.length == 0) || (data[0] == 0) || (data[0] == 1)) { - if (adapter->connect_status == libertas_connected) { - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_rssi, - 0, - cmd_option_waitforrsp, - 0, NULL); - - if (ret) { - LEAVE(); - return ret; - } - } - } - - if (wrq->u.data.length == 0) { - data[0] = adapter->SNR[TYPE_BEACON][TYPE_NOAVG]; - data[1] = adapter->SNR[TYPE_BEACON][TYPE_AVG]; - data[2] = adapter->SNR[TYPE_RXPD][TYPE_NOAVG]; - data[3] = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; - if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 4)) - return -EFAULT; - wrq->u.data.length = 4; - } else if (data[0] == 0) { - data[0] = adapter->SNR[TYPE_BEACON][TYPE_NOAVG]; - if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) - return -EFAULT; - wrq->u.data.length = 1; - } else if (data[0] == 1) { - data[0] = adapter->SNR[TYPE_BEACON][TYPE_AVG]; - if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) - return -EFAULT; - wrq->u.data.length = 1; - } else if (data[0] == 2) { - data[0] = adapter->SNR[TYPE_RXPD][TYPE_NOAVG]; - if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) - return -EFAULT; - wrq->u.data.length = 1; - } else if (data[0] == 3) { - data[0] = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; - if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) - return -EFAULT; - wrq->u.data.length = 1; - } else - return -ENOTSUPP; - - LEAVE(); - return 0; -} - -static int wlan_beacon_interval(wlan_private * priv, struct iwreq *wrq) -{ - int data; - wlan_adapter *adapter = priv->adapter; - - if (wrq->u.data.length > 0) { - if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) - return -EFAULT; - - lbs_pr_debug(1, "WLAN SET BEACON INTERVAL: %d\n", data); - if ((data > MRVDRV_MAX_BEACON_INTERVAL) - || (data < MRVDRV_MIN_BEACON_INTERVAL)) - return -ENOTSUPP; - adapter->beaconperiod = data; - } - data = adapter->beaconperiod; - if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) - return -EFAULT; - - wrq->u.data.length = 1; - - return 0; -} - -static int wlan_get_rssi(wlan_private * priv, struct iwreq *wrq) -{ - int ret = 0; - wlan_adapter *adapter = priv->adapter; - int temp; - int data = 0; - int *val; - - ENTER(); - data = SUBCMD_DATA(wrq); - if ((data == 0) || (data == 1)) { - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_rssi, - 0, cmd_option_waitforrsp, - 0, NULL); - if (ret) { - LEAVE(); - return ret; - } - } - - switch (data) { - case 0: - - temp = CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG], - adapter->NF[TYPE_BEACON][TYPE_NOAVG]); - break; - case 1: - temp = CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG], - adapter->NF[TYPE_BEACON][TYPE_AVG]); - break; - case 2: - temp = CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_NOAVG], - adapter->NF[TYPE_RXPD][TYPE_NOAVG]); - break; - case 3: - temp = CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, - adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); - break; - default: - return -ENOTSUPP; - } - val = (int *)wrq->u.name; - *val = temp; - - LEAVE(); - return 0; -} - -static int wlan_get_nf(wlan_private * priv, struct iwreq *wrq) -{ - int ret = 0; - wlan_adapter *adapter = priv->adapter; - int temp; - int data = 0; - int *val; - - data = SUBCMD_DATA(wrq); - if ((data == 0) || (data == 1)) { - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_rssi, - 0, cmd_option_waitforrsp, - 0, NULL); - - if (ret) { - LEAVE(); - return ret; - } - } - - switch (data) { - case 0: - temp = adapter->NF[TYPE_BEACON][TYPE_NOAVG]; - break; - case 1: - temp = adapter->NF[TYPE_BEACON][TYPE_AVG]; - break; - case 2: - temp = adapter->NF[TYPE_RXPD][TYPE_NOAVG]; - break; - case 3: - temp = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; - break; - default: - return -ENOTSUPP; - } - - temp = CAL_NF(temp); - - lbs_pr_debug(1, "%s: temp = %d\n", __FUNCTION__, temp); - val = (int *)wrq->u.name; - *val = temp; - return 0; -} - -static int wlan_get_txrate_ioctl(wlan_private * priv, struct ifreq *req) -{ - wlan_adapter *adapter = priv->adapter; - int *pdata; - struct iwreq *wrq = (struct iwreq *)req; - int ret = 0; - adapter->txrate = 0; - lbs_pr_debug(1, "wlan_get_txrate_ioctl\n"); - ret = libertas_prepare_and_send_command(priv, cmd_802_11_tx_rate_query, - cmd_act_get, cmd_option_waitforrsp, - 0, NULL); - if (ret) - return ret; - - pdata = (int *)wrq->u.name; - *pdata = (int)adapter->txrate; - return 0; -} - -static int wlan_get_adhoc_status_ioctl(wlan_private * priv, struct iwreq *wrq) -{ - char status[64]; - wlan_adapter *adapter = priv->adapter; - - memset(status, 0, sizeof(status)); - - switch (adapter->inframode) { - case wlan802_11ibss: - if (adapter->connect_status == libertas_connected) { - if (adapter->adhoccreate) - memcpy(&status, "AdhocStarted", sizeof(status)); - else - memcpy(&status, "AdhocJoined", sizeof(status)); - } else { - memcpy(&status, "AdhocIdle", sizeof(status)); - } - break; - case wlan802_11infrastructure: - memcpy(&status, "Inframode", sizeof(status)); - break; - default: - memcpy(&status, "AutoUnknownmode", sizeof(status)); - break; - } - - lbs_pr_debug(1, "status = %s\n", status); - wrq->u.data.length = strlen(status) + 1; - - if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, - &status, wrq->u.data.length)) - return -EFAULT; - } - - LEAVE(); - return 0; -} - -/** - * @brief Set/Get WPA IE - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_setwpaie_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - wlan_adapter *adapter = priv->adapter; - int ret = 0; - - ENTER(); - - if (wrq->u.data.length) { - if (wrq->u.data.length > sizeof(adapter->wpa_ie)) { - lbs_pr_debug(1, "failed to copy WPA IE, too big \n"); - return -EFAULT; - } - if (copy_from_user(adapter->wpa_ie, wrq->u.data.pointer, - wrq->u.data.length)) { - lbs_pr_debug(1, "failed to copy WPA IE \n"); - return -EFAULT; - } - adapter->wpa_ie_len = wrq->u.data.length; - lbs_pr_debug(1, "Set wpa_ie_len=%d IE=%#x\n", adapter->wpa_ie_len, - adapter->wpa_ie[0]); - lbs_dbg_hex("wpa_ie", adapter->wpa_ie, adapter->wpa_ie_len); - if (adapter->wpa_ie[0] == WPA_IE) - adapter->secinfo.WPAenabled = 1; - else if (adapter->wpa_ie[0] == WPA2_IE) - adapter->secinfo.WPA2enabled = 1; - else { - adapter->secinfo.WPAenabled = 0; - adapter->secinfo.WPA2enabled = 0; - } - } else { - memset(adapter->wpa_ie, 0, sizeof(adapter->wpa_ie)); - adapter->wpa_ie_len = wrq->u.data.length; - lbs_pr_debug(1, "Reset wpa_ie_len=%d IE=%#x\n", - adapter->wpa_ie_len, adapter->wpa_ie[0]); - adapter->secinfo.WPAenabled = 0; - adapter->secinfo.WPA2enabled = 0; - } - - // enable/disable RSN in firmware if WPA is enabled/disabled - // depending on variable adapter->secinfo.WPAenabled is set or not - ret = libertas_prepare_and_send_command(priv, cmd_802_11_enable_rsn, - cmd_act_set, cmd_option_waitforrsp, - 0, NULL); - - LEAVE(); - return ret; -} - -/** - * @brief Set Auto prescan - * @param priv A pointer to wlan_private structure - * @param wrq A pointer to iwreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_subcmd_setprescan_ioctl(wlan_private * priv, struct iwreq *wrq) -{ - int data; - wlan_adapter *adapter = priv->adapter; - int *val; - - data = SUBCMD_DATA(wrq); - lbs_pr_debug(1, "WLAN_SUBCMD_SET_PRESCAN %d\n", data); - adapter->prescan = data; - - val = (int *)wrq->u.name; - *val = data; - return 0; -} - -static int wlan_set_multiple_dtim_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - u32 mdtim; - int idata; - int ret = -EINVAL; - - ENTER(); - - idata = SUBCMD_DATA(wrq); - mdtim = (u32) idata; - if (((mdtim >= MRVDRV_MIN_MULTIPLE_DTIM) - && (mdtim <= MRVDRV_MAX_MULTIPLE_DTIM)) - || (mdtim == MRVDRV_IGNORE_MULTIPLE_DTIM)) { - priv->adapter->multipledtim = mdtim; - ret = 0; - } - if (ret) - lbs_pr_debug(1, "Invalid parameter, multipledtim not changed.\n"); - - LEAVE(); - return ret; -} - -/** - * @brief Set authentication mode - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_setauthalg_ioctl(wlan_private * priv, struct ifreq *req) -{ - int alg; - struct iwreq *wrq = (struct iwreq *)req; - wlan_adapter *adapter = priv->adapter; - - if (wrq->u.data.flags == 0) { - //from iwpriv subcmd - alg = SUBCMD_DATA(wrq); - } else { - //from wpa_supplicant subcmd - if (copy_from_user(&alg, wrq->u.data.pointer, sizeof(alg))) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -EFAULT; - } - } - - lbs_pr_debug(1, "auth alg is %#x\n", alg); - - switch (alg) { - case AUTH_ALG_SHARED_KEY: - adapter->secinfo.authmode = wlan802_11authmodeshared; - break; - case AUTH_ALG_NETWORK_EAP: - adapter->secinfo.authmode = - wlan802_11authmodenetworkEAP; - break; - case AUTH_ALG_OPEN_SYSTEM: - default: - adapter->secinfo.authmode = wlan802_11authmodeopen; - break; - } - return 0; -} - -/** - * @brief Set 802.1x authentication mode - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_set8021xauthalg_ioctl(wlan_private * priv, struct ifreq *req) -{ - int alg; - struct iwreq *wrq = (struct iwreq *)req; - - if (wrq->u.data.flags == 0) { - //from iwpriv subcmd - alg = SUBCMD_DATA(wrq); - } else { - //from wpa_supplicant subcmd - if (copy_from_user(&alg, wrq->u.data.pointer, sizeof(int))) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -EFAULT; - } - } - lbs_pr_debug(1, "802.1x auth alg is %#x\n", alg); - priv->adapter->secinfo.auth1xalg = alg; - return 0; -} - -static int wlan_setencryptionmode_ioctl(wlan_private * priv, struct ifreq *req) -{ - int mode; - struct iwreq *wrq = (struct iwreq *)req; - - ENTER(); - - if (wrq->u.data.flags == 0) { - //from iwpriv subcmd - mode = SUBCMD_DATA(wrq); - } else { - //from wpa_supplicant subcmd - if (copy_from_user(&mode, wrq->u.data.pointer, sizeof(int))) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -EFAULT; - } - } - lbs_pr_debug(1, "encryption mode is %#x\n", mode); - priv->adapter->secinfo.Encryptionmode = mode; - - LEAVE(); - return 0; -} - -static void adjust_mtu(wlan_private * priv) -{ - int mtu_increment = 0; - - if (priv->adapter->linkmode == WLAN_LINKMODE_802_11) - mtu_increment += sizeof(struct ieee80211_hdr_4addr); - - if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) - mtu_increment += max(sizeof(struct tx_radiotap_hdr), - sizeof(struct rx_radiotap_hdr)); - priv->wlan_dev.netdev->mtu = ETH_FRAME_LEN - - sizeof(struct ethhdr) - + mtu_increment; -} - -/** - * @brief Set Link-Layer Layer mode - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_set_linkmode_ioctl(wlan_private * priv, struct ifreq *req) -{ - int mode; - - mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data; - - switch (mode) { - case WLAN_LINKMODE_802_3: - priv->adapter->linkmode = mode; - break; - case WLAN_LINKMODE_802_11: - priv->adapter->linkmode = mode; - break; - default: - lbs_pr_info("usb8388-5: invalid link-layer mode (%#x)\n", - mode); - return -EINVAL; - break; - } - lbs_pr_debug(1, "usb8388-5: link-layer mode is %#x\n", mode); - - adjust_mtu(priv); - - return 0; -} - -/** - * @brief Set Radio header mode - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_set_radiomode_ioctl(wlan_private * priv, struct ifreq *req) -{ - int mode; - - mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data; - - switch (mode) { - case WLAN_RADIOMODE_NONE: - priv->adapter->radiomode = mode; - break; - case WLAN_RADIOMODE_RADIOTAP: - priv->adapter->radiomode = mode; - break; - default: - lbs_pr_debug(1, "usb8388-5: invalid radio header mode (%#x)\n", - mode); - return -EINVAL; - } - lbs_pr_debug(1, "usb8388-5: radio-header mode is %#x\n", mode); - - adjust_mtu(priv); - return 0; -} - -/** - * @brief Set Debug header mode - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_set_debugmode_ioctl(wlan_private * priv, struct ifreq *req) -{ - priv->adapter->debugmode = (int)((struct ifreq *) - ((u8 *) req + 4))->ifr_data; - return 0; -} - -static int wlan_subcmd_getrxantenna_ioctl(wlan_private * priv, - struct ifreq *req) -{ - int len; - char buf[8]; - struct iwreq *wrq = (struct iwreq *)req; - - lbs_pr_debug(1, "WLAN_SUBCMD_GETRXANTENNA\n"); - len = getrxantenna(priv, buf); - - wrq->u.data.length = len; - if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, &buf, len)) { - lbs_pr_debug(1, "CopyToUser failed\n"); - return -EFAULT; - } - } - - return 0; -} - -static int wlan_subcmd_gettxantenna_ioctl(wlan_private * priv, - struct ifreq *req) -{ - int len; - char buf[8]; - struct iwreq *wrq = (struct iwreq *)req; - - lbs_pr_debug(1, "WLAN_SUBCMD_GETTXANTENNA\n"); - len = gettxantenna(priv, buf); - - wrq->u.data.length = len; - if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, &buf, len)) { - lbs_pr_debug(1, "CopyToUser failed\n"); - return -EFAULT; - } - } - return 0; -} - -/** - * @brief Get the MAC TSF value from the firmware - * - * @param priv A pointer to wlan_private structure - * @param wrq A pointer to iwreq structure containing buffer - * space to store a TSF value retrieved from the firmware - * - * @return 0 if successful; IOCTL error code otherwise - */ -static int wlan_get_tsf_ioctl(wlan_private * priv, struct iwreq *wrq) -{ - u64 tsfval; - int ret; - - ret = libertas_prepare_and_send_command(priv, - cmd_get_tsf, - 0, cmd_option_waitforrsp, 0, &tsfval); - - lbs_pr_debug(1, "IOCTL: Get TSF = 0x%016llx\n", tsfval); - - if (ret != 0) { - lbs_pr_debug(1, "IOCTL: Get TSF; command exec failed\n"); - ret = -EFAULT; - } else { - if (copy_to_user(wrq->u.data.pointer, - &tsfval, - min_t(size_t, wrq->u.data.length, - sizeof(tsfval))) != 0) { - - lbs_pr_debug(1, "IOCTL: Get TSF; Copy to user failed\n"); - ret = -EFAULT; - } else { - ret = 0; - } - } - return ret; -} - -/** - * @brief Get/Set adapt rate - * @param priv A pointer to wlan_private structure - * @param wrq A pointer to iwreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_adapt_rateset(wlan_private * priv, struct iwreq *wrq) -{ - int ret; - wlan_adapter *adapter = priv->adapter; - int data[2]; - - memset(data, 0, sizeof(data)); - if (!wrq->u.data.length) { - lbs_pr_debug(1, "Get ADAPT RATE SET\n"); - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_rate_adapt_rateset, - cmd_act_get, - cmd_option_waitforrsp, 0, NULL); - data[0] = adapter->enablehwauto; - data[1] = adapter->ratebitmap; - if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) { - lbs_pr_debug(1, "Copy to user failed\n"); - return -EFAULT; - } -#define GET_TWO_INT 2 - wrq->u.data.length = GET_TWO_INT; - } else { - lbs_pr_debug(1, "Set ADAPT RATE SET\n"); - if (wrq->u.data.length > 2) - return -EINVAL; - if (copy_from_user - (data, wrq->u.data.pointer, - sizeof(int) * wrq->u.data.length)) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -EFAULT; - } - - adapter->enablehwauto = data[0]; - adapter->ratebitmap = data[1]; - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_rate_adapt_rateset, - cmd_act_set, - cmd_option_waitforrsp, 0, NULL); - } - return ret; -} - -/** - * @brief Get/Set inactivity timeout - * @param priv A pointer to wlan_private structure - * @param wrq A pointer to iwreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_inactivity_timeout(wlan_private * priv, struct iwreq *wrq) -{ - int ret; - int data = 0; - u16 timeout = 0; - - ENTER(); - if (wrq->u.data.length > 1) - return -ENOTSUPP; - - if (wrq->u.data.length == 0) { - /* Get */ - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_inactivity_timeout, - cmd_act_get, - cmd_option_waitforrsp, 0, - &timeout); - data = timeout; - if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) { - lbs_pr_debug(1, "Copy to user failed\n"); - return -EFAULT; - } - } else { - /* Set */ - if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -EFAULT; - } - - timeout = data; - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_inactivity_timeout, - cmd_act_set, - cmd_option_waitforrsp, 0, - &timeout); - } - - wrq->u.data.length = 1; - - LEAVE(); - return ret; -} - -static int wlan_do_getlog_ioctl(wlan_private * priv, struct iwreq *wrq) -{ - int ret; - char buf[GETLOG_BUFSIZE - 1]; - wlan_adapter *adapter = priv->adapter; - - lbs_pr_debug(1, " GET STATS\n"); - - ret = libertas_prepare_and_send_command(priv, cmd_802_11_get_log, - 0, cmd_option_waitforrsp, 0, NULL); - - if (ret) { - return ret; - } - - if (wrq->u.data.pointer) { - sprintf(buf, "\n mcasttxframe %u failed %u retry %u " - "multiretry %u framedup %u " - "rtssuccess %u rtsfailure %u ackfailure %u\n" - "rxfrag %u mcastrxframe %u fcserror %u " - "txframe %u wepundecryptable %u ", - adapter->logmsg.mcasttxframe, - adapter->logmsg.failed, - adapter->logmsg.retry, - adapter->logmsg.multiretry, - adapter->logmsg.framedup, - adapter->logmsg.rtssuccess, - adapter->logmsg.rtsfailure, - adapter->logmsg.ackfailure, - adapter->logmsg.rxfrag, - adapter->logmsg.mcastrxframe, - adapter->logmsg.fcserror, - adapter->logmsg.txframe, - adapter->logmsg.wepundecryptable); - wrq->u.data.length = strlen(buf) + 1; - if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) { - lbs_pr_debug(1, "Copy to user failed\n"); - return -EFAULT; - } - } - - return 0; -} - -static int wlan_scan_type_ioctl(wlan_private * priv, struct iwreq *wrq) -{ - u8 buf[12]; - u8 *option[] = { "active", "passive", "get", }; - int i, max_options = (sizeof(option) / sizeof(option[0])); - int ret = 0; - wlan_adapter *adapter = priv->adapter; - - if (priv->adapter->enable11d) { - lbs_pr_debug(1, "11D: Cannot set scantype when 11D enabled\n"); - return -EFAULT; - } - - memset(buf, 0, sizeof(buf)); - - if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf), - wrq->u.data.length))) - return -EFAULT; - - lbs_pr_debug(1, "Scan type Option = %s\n", buf); - - buf[sizeof(buf) - 1] = '\0'; - - for (i = 0; i < max_options; i++) { - if (!strcmp(buf, option[i])) - break; - } - - switch (i) { - case 0: - adapter->scantype = cmd_scan_type_active; - break; - case 1: - adapter->scantype = cmd_scan_type_passive; - break; - case 2: - wrq->u.data.length = strlen(option[adapter->scantype]) + 1; - - if (copy_to_user(wrq->u.data.pointer, - option[adapter->scantype], - wrq->u.data.length)) { - lbs_pr_debug(1, "Copy to user failed\n"); - ret = -EFAULT; - } - - break; - default: - lbs_pr_debug(1, "Invalid Scan type Ioctl Option\n"); - ret = -EINVAL; - break; - } - - return ret; -} - -static int wlan_scan_mode_ioctl(wlan_private * priv, struct iwreq *wrq) -{ - wlan_adapter *adapter = priv->adapter; - u8 buf[12]; - u8 *option[] = { "bss", "ibss", "any", "get" }; - int i, max_options = (sizeof(option) / sizeof(option[0])); - int ret = 0; - - ENTER(); - - memset(buf, 0, sizeof(buf)); - - if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf), - wrq->u.data.length))) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -EFAULT; - } - - lbs_pr_debug(1, "Scan mode Option = %s\n", buf); - - buf[sizeof(buf) - 1] = '\0'; - - for (i = 0; i < max_options; i++) { - if (!strcmp(buf, option[i])) - break; - } - - switch (i) { - - case 0: - adapter->scanmode = cmd_bss_type_bss; - break; - case 1: - adapter->scanmode = cmd_bss_type_ibss; - break; - case 2: - adapter->scanmode = cmd_bss_type_any; - break; - case 3: - - wrq->u.data.length = strlen(option[adapter->scanmode - 1]) + 1; - - lbs_pr_debug(1, "Get Scan mode Option = %s\n", - option[adapter->scanmode - 1]); - - lbs_pr_debug(1, "Scan mode length %d\n", wrq->u.data.length); - - if (copy_to_user(wrq->u.data.pointer, - option[adapter->scanmode - 1], - wrq->u.data.length)) { - lbs_pr_debug(1, "Copy to user failed\n"); - ret = -EFAULT; - } - lbs_pr_debug(1, "GET Scan type Option after copy = %s\n", - (char *)wrq->u.data.pointer); - - break; - - default: - lbs_pr_debug(1, "Invalid Scan mode Ioctl Option\n"); - ret = -EINVAL; - break; - } - - LEAVE(); - return ret; -} - -/** - * @brief Get/Set Adhoc G Rate - * - * @param priv A pointer to wlan_private structure - * @param wrq A pointer to user data - * @return 0--success, otherwise fail - */ -static int wlan_do_set_grate_ioctl(wlan_private * priv, struct iwreq *wrq) -{ - wlan_adapter *adapter = priv->adapter; - int data, data1; - int *val; - - ENTER(); - - data1 = SUBCMD_DATA(wrq); - switch (data1) { - case 0: - adapter->adhoc_grate_enabled = 0; - break; - case 1: - adapter->adhoc_grate_enabled = 1; - break; - case 2: - break; - default: - return -EINVAL; - } - data = adapter->adhoc_grate_enabled; - val = (int *)wrq->u.name; - *val = data; - LEAVE(); - return 0; -} - static inline int hex2int(char c) { if (c >= '0' && c <= '9') @@ -1761,6 +680,7 @@ static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req) */ static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req) { + struct iwreq *wrq = (struct iwreq *)req; static struct cmd_ds_fwt_access fwt_access; int ret; @@ -1776,7 +696,7 @@ static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req) (void *)&fwt_access); if (ret == 0) - req->ifr_data = (char *)(le32_to_cpu(fwt_access.references)); + wrq->u.param.value = le32_to_cpu(fwt_access.references); else return -EFAULT; @@ -1792,6 +712,7 @@ static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req) */ static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req) { + struct iwreq *wrq = (struct iwreq *)req; static struct cmd_ds_fwt_access fwt_access; int ret; @@ -1807,7 +728,7 @@ static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req) (void *)&fwt_access); if (ret == 0) - req->ifr_data = (char *)(le32_to_cpu(fwt_access.references)); + wrq->u.param.value = le32_to_cpu(fwt_access.references); else return -EFAULT; @@ -1823,6 +744,7 @@ static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req) */ static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req) { + struct iwreq *wrq = (struct iwreq *)req; struct cmd_ds_mesh_access mesh_access; int ret; @@ -1835,9 +757,8 @@ static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req) cmd_option_waitforrsp, 0, (void *)&mesh_access); - if (ret == 0) { - req->ifr_data = (char *)(le32_to_cpu(mesh_access.data[0])); - } + if (ret == 0) + wrq->u.param.value = le32_to_cpu(mesh_access.data[0]); else return -EFAULT; @@ -1898,36 +819,8 @@ int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) lbs_pr_debug(1, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd); switch (cmd) { - case WLANSCAN_TYPE: - lbs_pr_debug(1, "Scan type Ioctl\n"); - ret = wlan_scan_type_ioctl(priv, wrq); - break; - case WLAN_SETNONE_GETNONE: /* set WPA mode on/off ioctl #20 */ switch (wrq->u.data.flags) { - case WLANDEAUTH: - lbs_pr_debug(1, "Deauth\n"); - libertas_send_deauth(priv); - break; - - case WLANADHOCSTOP: - lbs_pr_debug(1, "Adhoc stop\n"); - ret = libertas_do_adhocstop_ioctl(priv); - break; - - case WLANRADIOON: - wlan_radio_ioctl(priv, 1); - break; - - case WLANRADIOOFF: - wlan_radio_ioctl(priv, 0); - break; - case WLANWLANIDLEON: - libertas_idle_on(priv); - break; - case WLANWLANIDLEOFF: - libertas_idle_off(priv); - break; case WLAN_SUBCMD_BT_RESET: /* bt_reset */ wlan_bt_reset_ioctl(priv); break; @@ -1937,162 +830,19 @@ int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) } /* End of switch */ break; - case WLANSETWPAIE: - ret = wlan_setwpaie_ioctl(priv, req); - break; - case WLAN_SETINT_GETINT: - /* The first 4 bytes of req->ifr_data is sub-ioctl number - * after 4 bytes sits the payload. - */ - subcmd = (int)req->ifr_data; //from iwpriv subcmd - switch (subcmd) { - case WLANNF: - ret = wlan_get_nf(priv, wrq); - break; - case WLANRSSI: - ret = wlan_get_rssi(priv, wrq); - break; - case WLANENABLE11D: - ret = libertas_cmd_enable_11d(priv, wrq); - break; - case WLANADHOCGRATE: - ret = wlan_do_set_grate_ioctl(priv, wrq); - break; - case WLAN_SUBCMD_SET_PRESCAN: - ret = wlan_subcmd_setprescan_ioctl(priv, wrq); - break; - } - break; - - case WLAN_SETONEINT_GETONEINT: - switch (wrq->u.data.flags) { - case WLAN_BEACON_INTERVAL: - ret = wlan_beacon_interval(priv, wrq); - break; - - case WLAN_LISTENINTRVL: - if (!wrq->u.data.length) { - int data; - lbs_pr_debug(1, "Get locallisteninterval value\n"); -#define GET_ONE_INT 1 - data = adapter->locallisteninterval; - if (copy_to_user(wrq->u.data.pointer, - &data, sizeof(int))) { - lbs_pr_debug(1, "Copy to user failed\n"); - return -EFAULT; - } - - wrq->u.data.length = GET_ONE_INT; - } else { - int data; - if (copy_from_user - (&data, wrq->u.data.pointer, sizeof(int))) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -EFAULT; - } - - lbs_pr_debug(1, "Set locallisteninterval = %d\n", - data); -#define MAX_U16_VAL 65535 - if (data > MAX_U16_VAL) { - lbs_pr_debug(1, "Exceeds U16 value\n"); - return -EINVAL; - } - adapter->locallisteninterval = data; - } - break; - case WLAN_TXCONTROL: - ret = wlan_txcontrol(priv, wrq); //adds for txcontrol ioctl - break; - - case WLAN_NULLPKTINTERVAL: - ret = wlan_null_pkt_interval(priv, wrq); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - break; - case WLAN_SETONEINT_GETNONE: /* The first 4 bytes of req->ifr_data is sub-ioctl number * after 4 bytes sits the payload. */ - subcmd = wrq->u.data.flags; //from wpa_supplicant subcmd - + subcmd = wrq->u.data.flags; if (!subcmd) - subcmd = (int)req->ifr_data; //from iwpriv subcmd + subcmd = (int)wrq->u.param.value; switch (subcmd) { - case WLAN_SUBCMD_SETRXANTENNA: /* SETRXANTENNA */ - idata = SUBCMD_DATA(wrq); - ret = setrxantenna(priv, idata); - break; - case WLAN_SUBCMD_SETTXANTENNA: /* SETTXANTENNA */ - idata = SUBCMD_DATA(wrq); - ret = settxantenna(priv, idata); - break; - case WLAN_SET_ATIM_WINDOW: - adapter->atimwindow = SUBCMD_DATA(wrq); - adapter->atimwindow = min_t(__u16, adapter->atimwindow, 50); - break; - case WLANSETBCNAVG: - adapter->bcn_avg_factor = SUBCMD_DATA(wrq); - if (adapter->bcn_avg_factor == 0) - adapter->bcn_avg_factor = - DEFAULT_BCN_AVG_FACTOR; - if (adapter->bcn_avg_factor > DEFAULT_BCN_AVG_FACTOR) - adapter->bcn_avg_factor = - DEFAULT_BCN_AVG_FACTOR; - break; - case WLANSETDATAAVG: - adapter->data_avg_factor = SUBCMD_DATA(wrq); - if (adapter->data_avg_factor == 0) - adapter->data_avg_factor = - DEFAULT_DATA_AVG_FACTOR; - if (adapter->data_avg_factor > DEFAULT_DATA_AVG_FACTOR) - adapter->data_avg_factor = - DEFAULT_DATA_AVG_FACTOR; - break; case WLANSETREGION: idata = SUBCMD_DATA(wrq); ret = wlan_set_region(priv, (u16) idata); break; - - case WLAN_SET_LISTEN_INTERVAL: - idata = SUBCMD_DATA(wrq); - adapter->listeninterval = (u16) idata; - break; - - case WLAN_SET_MULTIPLE_DTIM: - ret = wlan_set_multiple_dtim_ioctl(priv, req); - break; - - case WLANSETAUTHALG: - ret = wlan_setauthalg_ioctl(priv, req); - break; - - case WLANSET8021XAUTHALG: - ret = wlan_set8021xauthalg_ioctl(priv, req); - break; - - case WLANSETENCRYPTIONMODE: - ret = wlan_setencryptionmode_ioctl(priv, req); - break; - - case WLAN_SET_LINKMODE: - ret = wlan_set_linkmode_ioctl(priv, req); - break; - - case WLAN_SET_RADIOMODE: - ret = wlan_set_radiomode_ioctl(priv, req); - break; - - case WLAN_SET_DEBUGMODE: - ret = wlan_set_debugmode_ioctl(priv, req); - break; - case WLAN_SUBCMD_MESH_SET_TTL: idata = SUBCMD_DATA(wrq); ret = wlan_mesh_set_ttl_ioctl(priv, idata); @@ -2105,38 +855,8 @@ int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) break; - case WLAN_SETNONE_GETTWELVE_CHAR: /* Get Antenna settings */ - /* - * We've not used IW_PRIV_TYPE_FIXED so sub-ioctl number is - * in flags of iwreq structure, otherwise it will be in - * mode member of iwreq structure. - */ - switch ((int)wrq->u.data.flags) { - case WLAN_SUBCMD_GETRXANTENNA: /* Get Rx Antenna */ - ret = wlan_subcmd_getrxantenna_ioctl(priv, req); - break; - - case WLAN_SUBCMD_GETTXANTENNA: /* Get Tx Antenna */ - ret = wlan_subcmd_gettxantenna_ioctl(priv, req); - break; - - case WLAN_GET_TSF: - ret = wlan_get_tsf_ioctl(priv, wrq); - break; - } - break; - case WLAN_SET128CHAR_GET128CHAR: switch ((int)wrq->u.data.flags) { - - case WLANSCAN_MODE: - lbs_pr_debug(1, "Scan mode Ioctl\n"); - ret = wlan_scan_mode_ioctl(priv, wrq); - break; - - case WLAN_GET_ADHOC_STATUS: - ret = wlan_get_adhoc_status_ioctl(priv, wrq); - break; case WLAN_SUBCMD_BT_ADD: ret = wlan_bt_add_ioctl(priv, req); break; @@ -2168,41 +888,11 @@ int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) break; case WLAN_SETNONE_GETONEINT: - switch ((int)req->ifr_data) { - case WLANGETBCNAVG: - pdata = (int *)wrq->u.name; - *pdata = (int)adapter->bcn_avg_factor; - break; - + switch (wrq->u.param.value) { case WLANGETREGION: pdata = (int *)wrq->u.name; *pdata = (int)adapter->regioncode; break; - - case WLAN_GET_LISTEN_INTERVAL: - pdata = (int *)wrq->u.name; - *pdata = (int)adapter->listeninterval; - break; - - case WLAN_GET_LINKMODE: - req->ifr_data = (char *)((u32) adapter->linkmode); - break; - - case WLAN_GET_RADIOMODE: - req->ifr_data = (char *)((u32) adapter->radiomode); - break; - - case WLAN_GET_DEBUGMODE: - req->ifr_data = (char *)((u32) adapter->debugmode); - break; - - case WLAN_GET_MULTIPLE_DTIM: - pdata = (int *)wrq->u.name; - *pdata = (int)adapter->multipledtim; - break; - case WLAN_GET_TX_RATE: - ret = wlan_get_txrate_ioctl(priv, req); - break; case WLAN_SUBCMD_FWT_CLEANUP: /* fwt_cleanup */ ret = wlan_fwt_cleanup_ioctl(priv, req); break; @@ -2222,196 +912,8 @@ int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) break; - case WLANGETLOG: - ret = wlan_do_getlog_ioctl(priv, wrq); - break; - case WLAN_SET_GET_SIXTEEN_INT: switch ((int)wrq->u.data.flags) { - case WLAN_TPCCFG: - { - int data[5]; - struct cmd_ds_802_11_tpc_cfg cfg; - memset(&cfg, 0, sizeof(cfg)); - if ((wrq->u.data.length > 1) - && (wrq->u.data.length != 5)) - return -1; - - if (wrq->u.data.length == 0) { - cfg.action = - cpu_to_le16 - (cmd_act_get); - } else { - if (copy_from_user - (data, wrq->u.data.pointer, - sizeof(int) * 5)) { - lbs_pr_debug(1, - "Copy from user failed\n"); - return -EFAULT; - } - - cfg.action = - cpu_to_le16 - (cmd_act_set); - cfg.enable = data[0]; - cfg.usesnr = data[1]; - cfg.P0 = data[2]; - cfg.P1 = data[3]; - cfg.P2 = data[4]; - } - - ret = - libertas_prepare_and_send_command(priv, - cmd_802_11_tpc_cfg, - 0, - cmd_option_waitforrsp, - 0, (void *)&cfg); - - data[0] = cfg.enable; - data[1] = cfg.usesnr; - data[2] = cfg.P0; - data[3] = cfg.P1; - data[4] = cfg.P2; - if (copy_to_user - (wrq->u.data.pointer, data, - sizeof(int) * 5)) { - lbs_pr_debug(1, "Copy to user failed\n"); - return -EFAULT; - } - - wrq->u.data.length = 5; - } - break; - - case WLAN_POWERCFG: - { - int data[4]; - struct cmd_ds_802_11_pwr_cfg cfg; - memset(&cfg, 0, sizeof(cfg)); - if ((wrq->u.data.length > 1) - && (wrq->u.data.length != 4)) - return -1; - if (wrq->u.data.length == 0) { - cfg.action = - cpu_to_le16 - (cmd_act_get); - } else { - if (copy_from_user - (data, wrq->u.data.pointer, - sizeof(int) * 4)) { - lbs_pr_debug(1, - "Copy from user failed\n"); - return -EFAULT; - } - - cfg.action = - cpu_to_le16 - (cmd_act_set); - cfg.enable = data[0]; - cfg.PA_P0 = data[1]; - cfg.PA_P1 = data[2]; - cfg.PA_P2 = data[3]; - } - ret = - libertas_prepare_and_send_command(priv, - cmd_802_11_pwr_cfg, - 0, - cmd_option_waitforrsp, - 0, (void *)&cfg); - data[0] = cfg.enable; - data[1] = cfg.PA_P0; - data[2] = cfg.PA_P1; - data[3] = cfg.PA_P2; - if (copy_to_user - (wrq->u.data.pointer, data, - sizeof(int) * 4)) { - lbs_pr_debug(1, "Copy to user failed\n"); - return -EFAULT; - } - - wrq->u.data.length = 4; - } - break; - case WLAN_AUTO_FREQ_SET: - { - int data[3]; - struct cmd_ds_802_11_afc afc; - memset(&afc, 0, sizeof(afc)); - if (wrq->u.data.length != 3) - return -1; - if (copy_from_user - (data, wrq->u.data.pointer, - sizeof(int) * 3)) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -EFAULT; - } - afc.afc_auto = data[0]; - - if (afc.afc_auto != 0) { - afc.threshold = data[1]; - afc.period = data[2]; - } else { - afc.timing_offset = data[1]; - afc.carrier_offset = data[2]; - } - ret = - libertas_prepare_and_send_command(priv, - cmd_802_11_set_afc, - 0, - cmd_option_waitforrsp, - 0, (void *)&afc); - } - break; - case WLAN_AUTO_FREQ_GET: - { - int data[3]; - struct cmd_ds_802_11_afc afc; - memset(&afc, 0, sizeof(afc)); - ret = - libertas_prepare_and_send_command(priv, - cmd_802_11_get_afc, - 0, - cmd_option_waitforrsp, - 0, (void *)&afc); - data[0] = afc.afc_auto; - data[1] = afc.timing_offset; - data[2] = afc.carrier_offset; - if (copy_to_user - (wrq->u.data.pointer, data, - sizeof(int) * 3)) { - lbs_pr_debug(1, "Copy to user failed\n"); - return -EFAULT; - } - - wrq->u.data.length = 3; - } - break; - case WLAN_SCANPROBES: - { - int data; - if (wrq->u.data.length > 0) { - if (copy_from_user - (&data, wrq->u.data.pointer, - sizeof(int))) { - lbs_pr_debug(1, - "Copy from user failed\n"); - return -EFAULT; - } - - adapter->scanprobes = data; - } else { - data = adapter->scanprobes; - if (copy_to_user - (wrq->u.data.pointer, &data, - sizeof(int))) { - lbs_pr_debug(1, - "Copy to user failed\n"); - return -EFAULT; - } - } - wrq->u.data.length = 1; - } - break; case WLAN_LED_GPIO_CTRL: { int i; @@ -2475,17 +977,6 @@ int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) wrq->u.data.length = gpio->header.len; } break; - case WLAN_ADAPT_RATESET: - ret = wlan_adapt_rateset(priv, wrq); - break; - case WLAN_INACTIVITY_TIMEOUT: - ret = wlan_inactivity_timeout(priv, wrq); - break; - case WLANSNR: - ret = wlan_get_snr(priv, wrq); - break; - case WLAN_GET_RXINFO: - ret = wlan_get_rxinfo(priv, wrq); } break; diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c index 11682cbe752b..d4926b83e145 100644 --- a/drivers/net/wireless/libertas/join.c +++ b/drivers/net/wireless/libertas/join.c @@ -15,6 +15,8 @@ #include "join.h" #include "dev.h" +#define AD_HOC_CAP_PRIVACY_ON 1 + /** * @brief This function finds out the common rates between rate1 and rate2. * @@ -85,7 +87,7 @@ int libertas_send_deauth(wlan_private * priv) wlan_adapter *adapter = priv->adapter; int ret = 0; - if (adapter->inframode == wlan802_11infrastructure && + if (adapter->mode == IW_MODE_INFRA && adapter->connect_status == libertas_connected) ret = libertas_send_deauthentication(priv); else @@ -94,20 +96,6 @@ int libertas_send_deauth(wlan_private * priv) return ret; } -int libertas_do_adhocstop_ioctl(wlan_private * priv) -{ - wlan_adapter *adapter = priv->adapter; - int ret = 0; - - if (adapter->inframode == wlan802_11ibss && - adapter->connect_status == libertas_connected) - ret = libertas_stop_adhoc_network(priv); - else - ret = -ENOTSUPP; - - return ret; -} - /** * @brief Associate to a specific BSS discovered in a scan * @@ -207,8 +195,7 @@ int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbs /* check if the requested SSID is already joined */ if (adapter->curbssparams.ssid.ssidlength && !libertas_SSID_cmp(&pbssdesc->ssid, &adapter->curbssparams.ssid) - && (adapter->curbssparams.bssdescriptor.inframode == - wlan802_11ibss)) { + && (adapter->mode == IW_MODE_ADHOC)) { lbs_pr_debug(1, "ADHOC_J_CMD: New ad-hoc SSID is the same as current, " @@ -261,130 +248,6 @@ int libertas_send_deauthentication(wlan_private * priv) } /** - * @brief Set Idle Off - * - * @param priv A pointer to wlan_private structure - * @return 0 --success, otherwise fail - */ -int libertas_idle_off(wlan_private * priv) -{ - wlan_adapter *adapter = priv->adapter; - int ret = 0; - const u8 zeromac[] = { 0, 0, 0, 0, 0, 0 }; - int i; - - ENTER(); - - if (adapter->connect_status == libertas_disconnected) { - if (adapter->inframode == wlan802_11infrastructure) { - if (memcmp(adapter->previousbssid, zeromac, - sizeof(zeromac)) != 0) { - - lbs_pr_debug(1, "Previous SSID = %s\n", - adapter->previousssid.ssid); - lbs_pr_debug(1, "Previous BSSID = " - "%02x:%02x:%02x:%02x:%02x:%02x:\n", - adapter->previousbssid[0], - adapter->previousbssid[1], - adapter->previousbssid[2], - adapter->previousbssid[3], - adapter->previousbssid[4], - adapter->previousbssid[5]); - - i = libertas_find_SSID_in_list(adapter, - &adapter->previousssid, - adapter->previousbssid, - adapter->inframode); - - if (i < 0) { - libertas_send_specific_BSSID_scan(priv, - adapter-> - previousbssid, - 1); - i = libertas_find_SSID_in_list(adapter, - &adapter-> - previousssid, - adapter-> - previousbssid, - adapter-> - inframode); - } - - if (i < 0) { - /* If the BSSID could not be found, try just the SSID */ - i = libertas_find_SSID_in_list(adapter, - &adapter-> - previousssid, NULL, - adapter-> - inframode); - } - - if (i < 0) { - libertas_send_specific_SSID_scan(priv, - &adapter-> - previousssid, - 1); - i = libertas_find_SSID_in_list(adapter, - &adapter-> - previousssid, NULL, - adapter-> - inframode); - } - - if (i >= 0) { - ret = - wlan_associate(priv, - &adapter-> - scantable[i]); - } - } - } else if (adapter->inframode == wlan802_11ibss) { - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_ad_hoc_start, - 0, - cmd_option_waitforrsp, - 0, &adapter->previousssid); - } - } - /* else it is connected */ - - lbs_pr_debug(1, "\nwlanidle is off"); - LEAVE(); - return ret; -} - -/** - * @brief Set Idle On - * - * @param priv A pointer to wlan_private structure - * @return 0 --success, otherwise fail - */ -int libertas_idle_on(wlan_private * priv) -{ - wlan_adapter *adapter = priv->adapter; - int ret = 0; - - if (adapter->connect_status == libertas_connected) { - if (adapter->inframode == wlan802_11infrastructure) { - lbs_pr_debug(1, "Previous SSID = %s\n", - adapter->previousssid.ssid); - memmove(&adapter->previousssid, - &adapter->curbssparams.ssid, - sizeof(struct WLAN_802_11_SSID)); - libertas_send_deauth(priv); - - } else if (adapter->inframode == wlan802_11ibss) { - ret = libertas_stop_adhoc_network(priv); - } - - } - - lbs_pr_debug(1, "\nwlanidle is on"); - - return ret; -} - -/** * @brief This function prepares command of authenticate. * * @param priv A pointer to wlan_private structure @@ -398,22 +261,39 @@ int libertas_cmd_80211_authenticate(wlan_private * priv, void *pdata_buf) { wlan_adapter *adapter = priv->adapter; - struct cmd_ds_802_11_authenticate *pauthenticate = - &cmd->params.auth; + struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth; + int ret = -1; u8 *bssid = pdata_buf; cmd->command = cpu_to_le16(cmd_802_11_authenticate); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate) - + S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate) + + S_DS_GEN); + + /* translate auth mode to 802.11 defined wire value */ + switch (adapter->secinfo.auth_mode) { + case IW_AUTH_ALG_OPEN_SYSTEM: + pauthenticate->authtype = 0x00; + break; + case IW_AUTH_ALG_SHARED_KEY: + pauthenticate->authtype = 0x01; + break; + case IW_AUTH_ALG_LEAP: + pauthenticate->authtype = 0x80; + break; + default: + lbs_pr_debug(1, "AUTH_CMD: invalid auth alg 0x%X\n", + adapter->secinfo.auth_mode); + goto out; + } - pauthenticate->authtype = adapter->secinfo.authmode; memcpy(pauthenticate->macaddr, bssid, ETH_ALEN); lbs_pr_debug(1, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + ret = 0; - return 0; +out: + return ret; } int libertas_cmd_80211_deauthenticate(wlan_private * priv, @@ -550,7 +430,7 @@ int libertas_cmd_80211_associate(wlan_private * priv, lbs_pr_debug(1, "ASSOC_CMD: rates->header.len = %d\n", rates->header.len); /* set IBSS field */ - if (pbssdesc->inframode == wlan802_11infrastructure) { + if (pbssdesc->mode == IW_MODE_INFRA) { #define CAPINFO_ESS_MODE 1 passo->capinfo.ess = CAPINFO_ESS_MODE; } @@ -624,7 +504,7 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, /* set the BSS type */ adhs->bsstype = cmd_bss_type_ibss; - pbssdesc->inframode = wlan802_11ibss; + pbssdesc->mode = IW_MODE_ADHOC; adhs->beaconperiod = adapter->beaconperiod; /* set Physical param set */ @@ -666,15 +546,12 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time); /* set up privacy in adapter->scantable[i] */ - if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) { - -#define AD_HOC_CAP_PRIVACY_ON 1 - lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus set, privacy to WEP\n"); + if (adapter->secinfo.wep_enabled) { + lbs_pr_debug(1, "ADHOC_S_CMD: WEP enabled, setting privacy on\n"); pbssdesc->privacy = wlan802_11privfilter8021xWEP; adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON; } else { - lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus NOT set, Setting " - "privacy to ACCEPT ALL\n"); + lbs_pr_debug(1, "ADHOC_S_CMD: WEP disabled, setting privacy off\n"); pbssdesc->privacy = wlan802_11privfilteracceptall; } @@ -786,9 +663,6 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv, padhocjoin->bssdescriptor.BSSID[5], padhocjoin->bssdescriptor.SSID); - lbs_pr_debug(1, "ADHOC_J_CMD: Data Rate = %x\n", - (u32) padhocjoin->bssdescriptor.datarates); - /* failtimeout */ padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); @@ -832,7 +706,7 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv, padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow = cpu_to_le16(pbssdesc->atimwindow); - if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) { + if (adapter->secinfo.wep_enabled) { padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON; } diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h index 8efa2455af9a..115f5a8ba346 100644 --- a/drivers/net/wireless/libertas/join.h +++ b/drivers/net/wireless/libertas/join.h @@ -1,6 +1,3 @@ -/* -*- mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ -/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */ - /** * Interface for the wlan infrastructure and adhoc join routines * @@ -40,10 +37,6 @@ extern int libertas_ret_80211_disassociate(wlan_private * priv, extern int libertas_ret_80211_associate(wlan_private * priv, struct cmd_ds_command *resp); -extern int libertas_idle_on(wlan_private * priv); -extern int libertas_idle_off(wlan_private * priv); - -extern int libertas_do_adhocstop_ioctl(wlan_private * priv); extern int libertas_reassociation_thread(void *data); struct WLAN_802_11_SSID; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index dcbf102a057e..b9b25ce65919 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -21,6 +21,13 @@ #include "debugfs.h" #include "assoc.h" +#define DRIVER_RELEASE_VERSION "320.p0" +const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION +#ifdef DEBUG + "-dbg" +#endif + ""; + #ifdef ENABLE_PM static struct pm_dev *wlan_pm_dev = NULL; #endif diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 7e3f78f092dc..d17924f764e5 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -210,7 +210,7 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb) goto done; } - lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n", + lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %zd = %zd\n", skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); lbs_dbg_hex("RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr, @@ -364,7 +364,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) priv->stats.rx_errors++; } - lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n", + lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %zd = %zd\n", skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); /* create the exported radio header */ diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index e18706238951..3c0b1a2a1727 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -1,6 +1,3 @@ -/* -*- mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ -/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */ - /** * Functions implementing wlan scan IOCTL and firmware command APIs * @@ -87,118 +84,95 @@ * * @return Index in scantable, or error code if negative */ -static int is_network_compatible(wlan_adapter * adapter, int index, int mode) +static int is_network_compatible(wlan_adapter * adapter, int index, u8 mode) { ENTER(); - if (adapter->scantable[index].inframode == mode) { - if (adapter->secinfo.WEPstatus == wlan802_11WEPdisabled + if (adapter->scantable[index].mode == mode) { + if ( !adapter->secinfo.wep_enabled && !adapter->secinfo.WPAenabled && !adapter->secinfo.WPA2enabled - && adapter->scantable[index].wpa_supplicant.wpa_ie[0] != - WPA_IE - && adapter->scantable[index].wpa2_supplicant.wpa_ie[0] != - WPA2_IE && adapter->secinfo.Encryptionmode == CIPHER_NONE + && adapter->scantable[index].wpa_ie[0] != WPA_IE + && adapter->scantable[index].rsn_ie[0] != WPA2_IE && !adapter->scantable[index].privacy) { /* no security */ LEAVE(); return index; - } else if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled + } else if ( adapter->secinfo.wep_enabled && !adapter->secinfo.WPAenabled && !adapter->secinfo.WPA2enabled && adapter->scantable[index].privacy) { /* static WEP enabled */ LEAVE(); return index; - } else if (adapter->secinfo.WEPstatus == wlan802_11WEPdisabled + } else if ( !adapter->secinfo.wep_enabled && adapter->secinfo.WPAenabled && !adapter->secinfo.WPA2enabled - && (adapter->scantable[index].wpa_supplicant. - wpa_ie[0] - == WPA_IE) + && (adapter->scantable[index].wpa_ie[0] == WPA_IE) /* privacy bit may NOT be set in some APs like LinkSys WRT54G && adapter->scantable[index].privacy */ ) { /* WPA enabled */ - lbs_pr_debug(1, + lbs_pr_debug(1, "is_network_compatible() WPA: index=%d wpa_ie=%#x " - "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s Encmode=%#x " + "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " "privacy=%#x\n", index, - adapter->scantable[index].wpa_supplicant. - wpa_ie[0], - adapter->scantable[index].wpa2_supplicant. - wpa_ie[0], - (adapter->secinfo.WEPstatus == - wlan802_11WEPenabled) ? "e" : "d", - (adapter->secinfo.WPAenabled) ? "e" : "d", - (adapter->secinfo.WPA2enabled) ? "e" : "d", - adapter->secinfo.Encryptionmode, + adapter->scantable[index].wpa_ie[0], + adapter->scantable[index].rsn_ie[0], + adapter->secinfo.wep_enabled ? "e" : "d", + adapter->secinfo.WPAenabled ? "e" : "d", + adapter->secinfo.WPA2enabled ? "e" : "d", adapter->scantable[index].privacy); LEAVE(); return index; - } else if (adapter->secinfo.WEPstatus == wlan802_11WEPdisabled + } else if ( !adapter->secinfo.wep_enabled && !adapter->secinfo.WPAenabled && adapter->secinfo.WPA2enabled - && (adapter->scantable[index].wpa2_supplicant. - wpa_ie[0] - == WPA2_IE) + && (adapter->scantable[index].rsn_ie[0] == WPA2_IE) /* privacy bit may NOT be set in some APs like LinkSys WRT54G && adapter->scantable[index].privacy */ ) { /* WPA2 enabled */ - lbs_pr_debug(1, + lbs_pr_debug(1, "is_network_compatible() WPA2: index=%d wpa_ie=%#x " - "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s Encmode=%#x " + "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " "privacy=%#x\n", index, - adapter->scantable[index].wpa_supplicant. - wpa_ie[0], - adapter->scantable[index].wpa2_supplicant. - wpa_ie[0], - (adapter->secinfo.WEPstatus == - wlan802_11WEPenabled) ? "e" : "d", - (adapter->secinfo.WPAenabled) ? "e" : "d", - (adapter->secinfo.WPA2enabled) ? "e" : "d", - adapter->secinfo.Encryptionmode, + adapter->scantable[index].wpa_ie[0], + adapter->scantable[index].rsn_ie[0], + adapter->secinfo.wep_enabled ? "e" : "d", + adapter->secinfo.WPAenabled ? "e" : "d", + adapter->secinfo.WPA2enabled ? "e" : "d", adapter->scantable[index].privacy); LEAVE(); return index; - } else if (adapter->secinfo.WEPstatus == wlan802_11WEPdisabled + } else if ( !adapter->secinfo.wep_enabled && !adapter->secinfo.WPAenabled && !adapter->secinfo.WPA2enabled - && (adapter->scantable[index].wpa_supplicant. - wpa_ie[0] - != WPA_IE) - && (adapter->scantable[index].wpa2_supplicant. - wpa_ie[0] - != WPA2_IE) - && adapter->secinfo.Encryptionmode != CIPHER_NONE + && (adapter->scantable[index].wpa_ie[0] != WPA_IE) + && (adapter->scantable[index].rsn_ie[0] != WPA2_IE) && adapter->scantable[index].privacy) { /* dynamic WEP enabled */ - lbs_pr_debug(1, + lbs_pr_debug(1, "is_network_compatible() dynamic WEP: index=%d " - "wpa_ie=%#x wpa2_ie=%#x Encmode=%#x privacy=%#x\n", + "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n", index, - adapter->scantable[index].wpa_supplicant. - wpa_ie[0], - adapter->scantable[index].wpa2_supplicant. - wpa_ie[0], adapter->secinfo.Encryptionmode, + adapter->scantable[index].wpa_ie[0], + adapter->scantable[index].rsn_ie[0], adapter->scantable[index].privacy); LEAVE(); return index; } /* security doesn't match */ - lbs_pr_debug(1, + lbs_pr_debug(1, "is_network_compatible() FAILED: index=%d wpa_ie=%#x " - "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s Encmode=%#x privacy=%#x\n", + "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n", index, - adapter->scantable[index].wpa_supplicant.wpa_ie[0], - adapter->scantable[index].wpa2_supplicant.wpa_ie[0], - (adapter->secinfo.WEPstatus == - wlan802_11WEPenabled) ? "e" : "d", - (adapter->secinfo.WPAenabled) ? "e" : "d", - (adapter->secinfo.WPA2enabled) ? "e" : "d", - adapter->secinfo.Encryptionmode, + adapter->scantable[index].wpa_ie[0], + adapter->scantable[index].rsn_ie[0], + adapter->secinfo.wep_enabled ? "e" : "d", + adapter->secinfo.WPAenabled ? "e" : "d", + adapter->secinfo.WPA2enabled ? "e" : "d", adapter->scantable[index].privacy); LEAVE(); return -ECONNREFUSED; @@ -924,8 +898,6 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, u8 founddatarateie; int bytesleftforcurrentbeacon; - struct WPA_SUPPLICANT *pwpa_supplicant; - struct WPA_SUPPLICANT *pwpa2_supplicant; struct IE_WPA *pIe; const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 }; @@ -962,9 +934,6 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, bytesleftforcurrentbeacon = beaconsize; - pwpa_supplicant = &pBSSEntry->wpa_supplicant; - pwpa2_supplicant = &pBSSEntry->wpa2_supplicant; - memcpy(pBSSEntry->macaddress, pcurrentptr, ETH_ALEN); lbs_pr_debug(1, "InterpretIE: AP MAC Addr-%x:%x:%x:%x:%x:%x\n", pBSSEntry->macaddress[0], pBSSEntry->macaddress[1], @@ -1027,9 +996,9 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, } if (pcap->ibss == 1) { - pBSSEntry->inframode = wlan802_11ibss; + pBSSEntry->mode = IW_MODE_ADHOC; } else { - pBSSEntry->inframode = wlan802_11infrastructure; + pBSSEntry->mode = IW_MODE_INFRA; } /* process variable IE */ @@ -1116,7 +1085,7 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, sizeof(pcountryinfo->countrycode) || pcountryinfo->len > 254) { lbs_pr_debug(1, "InterpretIE: 11D- Err " - "CountryInfo len =%d min=%d max=254\n", + "CountryInfo len =%d min=%zd max=254\n", pcountryinfo->len, sizeof(pcountryinfo->countrycode)); LEAVE(); @@ -1160,27 +1129,27 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, #define IE_ID_LEN_FIELDS_BYTES 2 pIe = (struct IE_WPA *)pcurrentptr; - if (!memcmp(pIe->oui, oui01, sizeof(oui01))) { - pwpa_supplicant->wpa_ie_len - = min_t(size_t, elemlen + IE_ID_LEN_FIELDS_BYTES, - sizeof(pwpa_supplicant->wpa_ie)); - memcpy(pwpa_supplicant->wpa_ie, - pcurrentptr, - pwpa_supplicant->wpa_ie_len); - lbs_dbg_hex("InterpretIE: Resp WPA_IE", - pwpa_supplicant->wpa_ie, elemlen); - } + if (memcmp(pIe->oui, oui01, sizeof(oui01))) + break; + + pBSSEntry->wpa_ie_len = min_t(size_t, + elemlen + IE_ID_LEN_FIELDS_BYTES, + sizeof(pBSSEntry->wpa_ie)); + memcpy(pBSSEntry->wpa_ie, pcurrentptr, + pBSSEntry->wpa_ie_len); + lbs_dbg_hex("InterpretIE: Resp WPA_IE", + pBSSEntry->wpa_ie, elemlen); break; case WPA2_IE: pIe = (struct IE_WPA *)pcurrentptr; - pwpa2_supplicant->wpa_ie_len - = min_t(size_t, elemlen + IE_ID_LEN_FIELDS_BYTES, - sizeof(pwpa2_supplicant->wpa_ie)); - memcpy(pwpa2_supplicant->wpa_ie, - pcurrentptr, pwpa2_supplicant->wpa_ie_len); + pBSSEntry->rsn_ie_len = min_t(size_t, + elemlen + IE_ID_LEN_FIELDS_BYTES, + sizeof(pBSSEntry->rsn_ie)); + memcpy(pBSSEntry->rsn_ie, pcurrentptr, + pBSSEntry->rsn_ie_len); lbs_dbg_hex("InterpretIE: Resp WPA2_IE", - pwpa2_supplicant->wpa_ie, elemlen); + pBSSEntry->rsn_ie, elemlen); break; case TIM: break; @@ -1227,7 +1196,7 @@ int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1, struct WLAN_802_11_SSID *s * * @return index in BSSID list, or error return code (< 0) */ -int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, int mode) +int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode) { int ret = -ENETUNREACH; int i; @@ -1247,8 +1216,8 @@ int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, int mode) for (i = 0; ret < 0 && i < adapter->numinscantable; i++) { if (!memcmp(adapter->scantable[i].macaddress, bssid, ETH_ALEN)) { switch (mode) { - case wlan802_11infrastructure: - case wlan802_11ibss: + case IW_MODE_INFRA: + case IW_MODE_ADHOC: ret = is_network_compatible(adapter, i, mode); break; default: @@ -1272,7 +1241,7 @@ int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, int mode) * @return index in BSSID list */ int libertas_find_SSID_in_list(wlan_adapter * adapter, - struct WLAN_802_11_SSID *ssid, u8 * bssid, int mode) + struct WLAN_802_11_SSID *ssid, u8 * bssid, u8 mode) { int net = -ENETUNREACH; u8 bestrssi = 0; @@ -1287,8 +1256,8 @@ int libertas_find_SSID_in_list(wlan_adapter * adapter, !memcmp(adapter->scantable[i]. macaddress, bssid, ETH_ALEN))) { switch (mode) { - case wlan802_11infrastructure: - case wlan802_11ibss: + case IW_MODE_INFRA: + case IW_MODE_ADHOC: j = is_network_compatible(adapter, i, mode); if (j >= 0) { @@ -1311,7 +1280,7 @@ int libertas_find_SSID_in_list(wlan_adapter * adapter, } } break; - case wlan802_11autounknown: + case IW_MODE_AUTO: default: if (SCAN_RSSI(adapter->scantable[i].rssi) > bestrssi) { @@ -1338,8 +1307,7 @@ int libertas_find_SSID_in_list(wlan_adapter * adapter, * * @return index in BSSID list */ -int libertas_find_best_SSID_in_list(wlan_adapter * adapter, - enum WLAN_802_11_NETWORK_INFRASTRUCTURE mode) +int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode) { int bestnet = -ENETUNREACH; u8 bestrssi = 0; @@ -1351,8 +1319,8 @@ int libertas_find_best_SSID_in_list(wlan_adapter * adapter, for (i = 0; i < adapter->numinscantable; i++) { switch (mode) { - case wlan802_11infrastructure: - case wlan802_11ibss: + case IW_MODE_INFRA: + case IW_MODE_ADHOC: if (is_network_compatible(adapter, i, mode) >= 0) { if (SCAN_RSSI(adapter->scantable[i].rssi) > bestrssi) { @@ -1363,7 +1331,7 @@ int libertas_find_best_SSID_in_list(wlan_adapter * adapter, } } break; - case wlan802_11autounknown: + case IW_MODE_AUTO: default: if (SCAN_RSSI(adapter->scantable[i].rssi) > bestrssi) { bestrssi = @@ -1388,8 +1356,7 @@ int libertas_find_best_SSID_in_list(wlan_adapter * adapter, */ int libertas_find_best_network_SSID(wlan_private * priv, struct WLAN_802_11_SSID *pSSID, - enum WLAN_802_11_NETWORK_INFRASTRUCTURE preferred_mode, - enum WLAN_802_11_NETWORK_INFRASTRUCTURE *out_mode) + u8 preferred_mode, u8 *out_mode) { wlan_adapter *adapter = priv->adapter; int ret = 0; @@ -1414,7 +1381,7 @@ int libertas_find_best_network_SSID(wlan_private * priv, preqbssid = &adapter->scantable[i]; memcpy(pSSID, &preqbssid->ssid, sizeof(struct WLAN_802_11_SSID)); - *out_mode = preqbssid->inframode; + *out_mode = preqbssid->mode; if (!pSSID->ssidlength) { ret = -1; @@ -1584,7 +1551,7 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, for (i = 0; i < adapter->numinscantable; i++) { if ((current_ev + MAX_SCAN_CELL_SIZE) >= end_buf) { lbs_pr_debug(1, "i=%d break out: current_ev=%p end_buf=%p " - "MAX_SCAN_CELL_SIZE=%d\n", + "MAX_SCAN_CELL_SIZE=%zd\n", i, current_ev, end_buf, MAX_SCAN_CELL_SIZE); break; } @@ -1632,7 +1599,7 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, //Add mode iwe.cmd = SIOCGIWMODE; - iwe.u.mode = adapter->scantable[i].inframode + 1; + iwe.u.mode = adapter->scantable[i].mode; iwe.len = IW_EV_UINT_LEN; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len); @@ -1666,7 +1633,7 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, iwe.u.qual.noise = CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]); } - if ((adapter->inframode == wlan802_11ibss) && + if ((adapter->mode == IW_MODE_ADHOC) && !libertas_SSID_cmp(&adapter->curbssparams.ssid, &adapter->scantable[i].ssid) && adapter->adhoccreate) { @@ -1731,7 +1698,7 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, end_buf, &iwe, iwe.len); } - if ((adapter->scantable[i].inframode == wlan802_11ibss) + if ((adapter->scantable[i].mode == IW_MODE_ADHOC) && !libertas_SSID_cmp(&adapter->curbssparams.ssid, &adapter->scantable[i].ssid) && adapter->adhoccreate) { @@ -1745,30 +1712,24 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, /* Add new value to event */ current_val = current_ev + IW_EV_LCP_LEN; - if (adapter->scantable[i].wpa2_supplicant.wpa_ie[0] == WPA2_IE) { + if (adapter->scantable[i].rsn_ie[0] == WPA2_IE) { memset(&iwe, 0, sizeof(iwe)); memset(buf, 0, sizeof(buf)); - memcpy(buf, adapter->scantable[i]. - wpa2_supplicant.wpa_ie, - adapter->scantable[i].wpa2_supplicant. - wpa_ie_len); + memcpy(buf, adapter->scantable[i].rsn_ie, + adapter->scantable[i].rsn_ie_len); iwe.cmd = IWEVGENIE; - iwe.u.data.length = adapter->scantable[i]. - wpa2_supplicant.wpa_ie_len; + iwe.u.data.length = adapter->scantable[i].rsn_ie_len; iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); } - if (adapter->scantable[i].wpa_supplicant.wpa_ie[0] == WPA_IE) { + if (adapter->scantable[i].wpa_ie[0] == WPA_IE) { memset(&iwe, 0, sizeof(iwe)); memset(buf, 0, sizeof(buf)); - memcpy(buf, adapter->scantable[i]. - wpa_supplicant.wpa_ie, - adapter->scantable[i].wpa_supplicant. - wpa_ie_len); + memcpy(buf, adapter->scantable[i].wpa_ie, + adapter->scantable[i].wpa_ie_len); iwe.cmd = IWEVGENIE; - iwe.u.data.length = adapter->scantable[i]. - wpa_supplicant.wpa_ie_len; + iwe.u.data.length = adapter->scantable[i].wpa_ie_len; iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index d93aa7fa44fd..405f4f0fe575 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h @@ -1,6 +1,3 @@ -/* -*- mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ -/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */ - /** * Interface for the wlan network scan routines * @@ -10,6 +7,7 @@ #ifndef _WLAN_SCAN_H #define _WLAN_SCAN_H +#include <net/ieee80211.h> #include "hostcmd.h" /** @@ -155,7 +153,7 @@ struct bss_descriptor { u32 atimwindow; - enum WLAN_802_11_NETWORK_INFRASTRUCTURE inframode; + u8 mode; u8 libertas_supported_rates[WLAN_SUPPORTED_RATES]; int extra_ie; @@ -170,22 +168,22 @@ struct bss_descriptor { struct ieeetypes_countryinfofullset countryinfo; - struct WPA_SUPPLICANT wpa_supplicant; - struct WPA_SUPPLICANT wpa2_supplicant; - + u8 wpa_ie[MAX_WPA_IE_LEN]; + size_t wpa_ie_len; + u8 rsn_ie[MAX_WPA_IE_LEN]; + size_t rsn_ie_len; }; extern int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1, struct WLAN_802_11_SSID *ssid2); extern int libertas_find_SSID_in_list(wlan_adapter * adapter, struct WLAN_802_11_SSID *ssid, - u8 * bssid, int mode); -int libertas_find_best_SSID_in_list(wlan_adapter * adapter, enum WLAN_802_11_NETWORK_INFRASTRUCTURE mode); -extern int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, int mode); + u8 * bssid, u8 mode); +int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode); +extern int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode); int libertas_find_best_network_SSID(wlan_private * priv, struct WLAN_802_11_SSID *pSSID, - enum WLAN_802_11_NETWORK_INFRASTRUCTURE preferred_mode, - enum WLAN_802_11_NETWORK_INFRASTRUCTURE *out_mode); + u8 preferred_mode, u8 *out_mode); extern int libertas_send_specific_SSID_scan(wlan_private * priv, struct WLAN_802_11_SSID *prequestedssid, diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 82d06223043e..d4b13478c9a7 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -78,7 +78,7 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb) min_t(unsigned int, skb->len, 100)); if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) { - lbs_pr_debug(1, "Tx error: Bad skb length %d : %d\n", + lbs_pr_debug(1, "Tx error: Bad skb length %d : %zd\n", skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE); ret = -1; goto done; diff --git a/drivers/net/wireless/libertas/version.h b/drivers/net/wireless/libertas/version.h index e86f65ae79b8..8b137891791f 100644 --- a/drivers/net/wireless/libertas/version.h +++ b/drivers/net/wireless/libertas/version.h @@ -1,8 +1 @@ -#define DRIVER_RELEASE_VERSION "320.p0" -const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION -#ifdef DEBUG - "-dbg" -#endif - ""; - diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 4a52336bc0f6..69f52b6e59c8 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -17,7 +17,6 @@ #include "defs.h" #include "dev.h" #include "join.h" -#include "version.h" #include "wext.h" #include "assoc.h" @@ -233,7 +232,7 @@ static int changeadhocchannel(wlan_private * priv, int channel) // find out the BSSID that matches the current SSID i = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL, - wlan802_11ibss); + IW_MODE_ADHOC); if (i >= 0) { lbs_pr_debug(1, "SSID found at %d in List," @@ -316,13 +315,11 @@ static int get_active_data_rates(wlan_adapter * adapter, ENTER(); if (adapter->connect_status != libertas_connected) { - if (adapter->inframode == wlan802_11infrastructure) { - //Infra. mode + if (adapter->mode == IW_MODE_INFRA) { lbs_pr_debug(1, "Infra\n"); k = copyrates(rates, k, libertas_supported_rates, sizeof(libertas_supported_rates)); } else { - //ad-hoc mode lbs_pr_debug(1, "Adhoc G\n"); k = copyrates(rates, k, libertas_adhoc_rates_g, sizeof(libertas_adhoc_rates_g)); @@ -586,20 +583,7 @@ static int wlan_get_mode(struct net_device *dev, ENTER(); - switch (adapter->inframode) { - case wlan802_11ibss: - *uwrq = IW_MODE_ADHOC; - break; - - case wlan802_11infrastructure: - *uwrq = IW_MODE_INFRA; - break; - - default: - case wlan802_11autounknown: - *uwrq = IW_MODE_AUTO; - break; - } + *uwrq = adapter->mode; LEAVE(); return 0; @@ -1002,149 +986,18 @@ static const struct iw_priv_args wlan_private_args[] = { /* * { cmd, set_args, get_args, name } */ - { - WLANSCAN_TYPE, - IW_PRIV_TYPE_CHAR | 8, - IW_PRIV_TYPE_CHAR | 8, - "scantype"}, - - { - WLAN_SETINT_GETINT, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - ""}, - { - WLANNF, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getNF"}, - { - WLANRSSI, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getRSSI"}, - { - WLANENABLE11D, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "enable11d"}, - { - WLANADHOCGRATE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "adhocgrate"}, - - { - WLAN_SUBCMD_SET_PRESCAN, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "prescan"}, - { - WLAN_SETONEINT_GETONEINT, - IW_PRIV_TYPE_INT | 1, - IW_PRIV_TYPE_INT | 1, - ""}, - { - WLAN_BEACON_INTERVAL, - IW_PRIV_TYPE_INT | 1, - IW_PRIV_TYPE_INT | 1, - "bcninterval"}, - { - WLAN_LISTENINTRVL, - IW_PRIV_TYPE_INT | 1, - IW_PRIV_TYPE_INT | 1, - "lolisteninter"}, - { - WLAN_TXCONTROL, - IW_PRIV_TYPE_INT | 1, - IW_PRIV_TYPE_INT | 1, - "txcontrol"}, - { - WLAN_NULLPKTINTERVAL, - IW_PRIV_TYPE_INT | 1, - IW_PRIV_TYPE_INT | 1, - "psnullinterval"}, /* Using iwpriv sub-command feature */ { WLAN_SETONEINT_GETNONE, /* IOCTL: 24 */ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, ""}, - - { - WLAN_SUBCMD_SETRXANTENNA, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "setrxant"}, - { - WLAN_SUBCMD_SETTXANTENNA, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "settxant"}, - { - WLANSETAUTHALG, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "authalgs", - }, - { - WLANSET8021XAUTHALG, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "8021xauthalgs", - }, - { - WLANSETENCRYPTIONMODE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "encryptionmode", - }, { WLANSETREGION, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, "setregioncode"}, { - WLAN_SET_LISTEN_INTERVAL, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "setlisteninter"}, - { - WLAN_SET_MULTIPLE_DTIM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "setmultipledtim"}, - { - WLAN_SET_ATIM_WINDOW, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "atimwindow"}, - { - WLANSETBCNAVG, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "setbcnavg"}, - { - WLANSETDATAAVG, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "setdataavg"}, - { - WLAN_SET_LINKMODE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "linkmode"}, - { - WLAN_SET_RADIOMODE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "radiomode"}, - { - WLAN_SET_DEBUGMODE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "debugmode"}, - { WLAN_SUBCMD_MESH_SET_TTL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, @@ -1160,41 +1013,6 @@ static const struct iw_priv_args wlan_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getregioncode"}, { - WLAN_GET_LISTEN_INTERVAL, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getlisteninter"}, - { - WLAN_GET_MULTIPLE_DTIM, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getmultipledtim"}, - { - WLAN_GET_TX_RATE, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "gettxrate"}, - { - WLANGETBCNAVG, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getbcnavg"}, - { - WLAN_GET_LINKMODE, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_linkmode"}, - { - WLAN_GET_RADIOMODE, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_radiomode"}, - { - WLAN_GET_DEBUGMODE, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_debugmode"}, - { WLAN_SUBCMD_FWT_CLEANUP, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, @@ -1210,61 +1028,11 @@ static const struct iw_priv_args wlan_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "mesh_get_ttl"}, { - WLAN_SETNONE_GETTWELVE_CHAR, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_CHAR | 12, - ""}, - { - WLAN_SUBCMD_GETRXANTENNA, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_CHAR | 12, - "getrxant"}, - { - WLAN_SUBCMD_GETTXANTENNA, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_CHAR | 12, - "gettxant"}, - { - WLAN_GET_TSF, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_CHAR | 12, - "gettsf"}, - { WLAN_SETNONE_GETNONE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, ""}, { - WLANDEAUTH, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "deauth"}, - { - WLANADHOCSTOP, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "adhocstop"}, - { - WLANRADIOON, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "radioon"}, - { - WLANRADIOOFF, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "radiooff"}, - { - WLANWLANIDLEON, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "wlanidle-on"}, - { - WLANWLANIDLEOFF, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "wlanidle-off"}, - { WLAN_SUBCMD_FWT_RESET, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, @@ -1327,90 +1095,15 @@ static const struct iw_priv_args wlan_private_args[] = { IW_PRIV_TYPE_CHAR | 128, "fwt_list_route"}, { - WLANSCAN_MODE, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "scanmode"}, - { - WLAN_GET_ADHOC_STATUS, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "getadhocstatus"}, - { - WLAN_SETNONE_GETWORDCHAR, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_CHAR | 128, - ""}, - { - WLANSETWPAIE, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 24, - IW_PRIV_TYPE_NONE, - "setwpaie"}, - { - WLANGETLOG, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_CHAR | GETLOG_BUFSIZE, - "getlog"}, - { WLAN_SET_GET_SIXTEEN_INT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, ""}, { - WLAN_TPCCFG, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "tpccfg"}, - { - WLAN_POWERCFG, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "powercfg"}, - { - WLAN_AUTO_FREQ_SET, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "setafc"}, - { - WLAN_AUTO_FREQ_GET, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "getafc"}, - { - WLAN_SCANPROBES, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "scanprobes"}, - { WLAN_LED_GPIO_CTRL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, "ledgpio"}, - { - WLAN_ADAPT_RATESET, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "rateadapt"}, - { - WLAN_INACTIVITY_TIMEOUT, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "inactivityto"}, - { - WLANSNR, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "getSNR"}, - { - WLAN_GET_RATE, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "getrate"}, - { - WLAN_GET_RXINFO, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "getrxinfo"}, }; static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) @@ -1434,7 +1127,7 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) ENTER(); - priv->wstats.status = adapter->inframode; + priv->wstats.status = adapter->mode; /* If we're not associated, all quality values are meaningless */ if (adapter->connect_status != libertas_connected) @@ -1568,13 +1261,12 @@ static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info, if (!cfp) { rc = -EINVAL; } else { - if (adapter->inframode == wlan802_11ibss) { + if (adapter->mode == IW_MODE_ADHOC) { rc = changeadhocchannel(priv, channel); /* If station is WEP enabled, send the * command to set WEP in firmware */ - if (adapter->secinfo.WEPstatus == - wlan802_11WEPenabled) { + if (adapter->secinfo.wep_enabled) { lbs_pr_debug(1, "set_freq: WEP enabled\n"); ret = libertas_prepare_and_send_command(priv, cmd_802_11_set_wep, @@ -1716,49 +1408,31 @@ static int wlan_set_mode(struct net_device *dev, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; struct assoc_request * assoc_req; - enum WLAN_802_11_NETWORK_INFRASTRUCTURE new_mode; ENTER(); - switch (*uwrq) { - case IW_MODE_ADHOC: - lbs_pr_debug(1, "Wanted mode is ad-hoc: current datarate=%#x\n", - adapter->datarate); - new_mode = wlan802_11ibss; - adapter->adhocchannel = DEFAULT_AD_HOC_CHANNEL; - break; - - case IW_MODE_INFRA: - lbs_pr_debug(1, "Wanted mode is Infrastructure\n"); - new_mode = wlan802_11infrastructure; - break; - - case IW_MODE_AUTO: - lbs_pr_debug(1, "Wanted mode is Auto\n"); - new_mode = wlan802_11autounknown; - break; - - default: - lbs_pr_debug(1, "Wanted mode is Unknown: 0x%x\n", *uwrq); - return -EINVAL; + if ( (*uwrq != IW_MODE_ADHOC) + && (*uwrq != IW_MODE_INFRA) + && (*uwrq != IW_MODE_AUTO)) { + lbs_pr_debug(1, "Invalid mode: 0x%x\n", *uwrq); + ret = -EINVAL; + goto out; } mutex_lock(&adapter->lock); assoc_req = wlan_get_association_request(adapter); if (!assoc_req) { ret = -ENOMEM; + wlan_cancel_association_work(priv); } else { - assoc_req->mode = new_mode; - } - - if (ret == 0) { + assoc_req->mode = *uwrq; set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); wlan_postpone_association_work(priv); - } else { - wlan_cancel_association_work(priv); + lbs_pr_debug(1, "Switching to mode: 0x%x\n", *uwrq); } mutex_unlock(&adapter->lock); +out: LEAVE(); return ret; } @@ -1789,13 +1463,13 @@ static int wlan_get_encode(struct net_device *dev, dwrq->flags = 0; /* Authentication method */ - switch (adapter->secinfo.authmode) { - case wlan802_11authmodeopen: + switch (adapter->secinfo.auth_mode) { + case IW_AUTH_ALG_OPEN_SYSTEM: dwrq->flags = IW_ENCODE_OPEN; break; - case wlan802_11authmodeshared: - case wlan802_11authmodenetworkEAP: + case IW_AUTH_ALG_SHARED_KEY: + case IW_AUTH_ALG_LEAP: dwrq->flags = IW_ENCODE_RESTRICTED; break; default: @@ -1803,8 +1477,9 @@ static int wlan_get_encode(struct net_device *dev, break; } - if ((adapter->secinfo.WEPstatus == wlan802_11WEPenabled) - || adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) { + if ( adapter->secinfo.wep_enabled + || adapter->secinfo.WPAenabled + || adapter->secinfo.WPA2enabled) { dwrq->flags &= ~IW_ENCODE_DISABLED; } else { dwrq->flags |= IW_ENCODE_DISABLED; @@ -1818,8 +1493,7 @@ static int wlan_get_encode(struct net_device *dev, if (index < 0) index = adapter->wep_tx_keyidx; - if ((adapter->wep_keys[index].len) && - (adapter->secinfo.WEPstatus == wlan802_11WEPenabled)) { + if ((adapter->wep_keys[index].len) && adapter->secinfo.wep_enabled) { memcpy(extra, adapter->wep_keys[index].key, adapter->wep_keys[index].len); dwrq->length = adapter->wep_keys[index].len; @@ -1903,7 +1577,7 @@ static int wlan_set_wep_key(struct assoc_request *assoc_req, assoc_req->wep_tx_keyidx = index; } - assoc_req->secinfo.WEPstatus = wlan802_11WEPenabled; + assoc_req->secinfo.wep_enabled = 1; LEAVE(); return 0; @@ -1932,10 +1606,10 @@ static void disable_wep(struct assoc_request *assoc_req) int i; /* Set Open System auth mode */ - assoc_req->secinfo.authmode = wlan802_11authmodeopen; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; /* Clear WEP keys and mark WEP as disabled */ - assoc_req->secinfo.WEPstatus = wlan802_11WEPdisabled; + assoc_req->secinfo.wep_enabled = 0; for (i = 0; i < 4; i++) assoc_req->wep_keys[i].len = 0; @@ -1987,8 +1661,7 @@ static int wlan_set_encode(struct net_device *dev, /* If WEP isn't enabled, or if there is no key data but a valid * index, set the TX key. */ - if ((assoc_req->secinfo.WEPstatus != wlan802_11WEPenabled) - || (dwrq->length == 0 && !is_default)) + if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default)) set_tx_key = 1; ret = wlan_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key); @@ -2001,9 +1674,9 @@ static int wlan_set_encode(struct net_device *dev, set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); if (dwrq->flags & IW_ENCODE_RESTRICTED) { - assoc_req->secinfo.authmode = wlan802_11authmodeshared; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; } else if (dwrq->flags & IW_ENCODE_OPEN) { - assoc_req->secinfo.authmode = wlan802_11authmodeopen; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; } out: @@ -2056,30 +1729,31 @@ static int wlan_get_encodeext(struct net_device *dev, if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY && ext->alg != IW_ENCODE_ALG_WEP) { - if (index != 0 || adapter->inframode != wlan802_11infrastructure) + if (index != 0 || adapter->mode != IW_MODE_INFRA) goto out; } dwrq->flags = index + 1; memset(ext, 0, sizeof(*ext)); - if ((adapter->secinfo.WEPstatus == wlan802_11WEPdisabled) - && !adapter->secinfo.WPAenabled && !adapter->secinfo.WPA2enabled) { + if ( !adapter->secinfo.wep_enabled + && !adapter->secinfo.WPAenabled + && !adapter->secinfo.WPA2enabled) { ext->alg = IW_ENCODE_ALG_NONE; ext->key_len = 0; dwrq->flags |= IW_ENCODE_DISABLED; } else { u8 *key = NULL; - if ((adapter->secinfo.WEPstatus == wlan802_11WEPenabled) + if ( adapter->secinfo.wep_enabled && !adapter->secinfo.WPAenabled && !adapter->secinfo.WPA2enabled) { ext->alg = IW_ENCODE_ALG_WEP; ext->key_len = adapter->wep_keys[index].len; key = &adapter->wep_keys[index].key[0]; - } else if ((adapter->secinfo.WEPstatus == wlan802_11WEPdisabled) && - (adapter->secinfo.WPAenabled || - adapter->secinfo.WPA2enabled)) { + } else if ( !adapter->secinfo.wep_enabled + && (adapter->secinfo.WPAenabled || + adapter->secinfo.WPA2enabled)) { /* WPA */ ext->alg = IW_ENCODE_ALG_TKIP; ext->key_len = 0; @@ -2149,7 +1823,7 @@ static int wlan_set_encodeext(struct net_device *dev, /* If WEP isn't enabled, or if there is no key data but a valid * index, or if the set-TX-key flag was passed, set the TX key. */ - if ((assoc_req->secinfo.WEPstatus != wlan802_11WEPenabled) + if ( !assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default) || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) set_tx_key = 1; @@ -2161,11 +1835,9 @@ static int wlan_set_encodeext(struct net_device *dev, goto out; if (dwrq->flags & IW_ENCODE_RESTRICTED) { - assoc_req->secinfo.authmode = - wlan802_11authmodeshared; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; } else if (dwrq->flags & IW_ENCODE_OPEN) { - assoc_req->secinfo.authmode = - wlan802_11authmodeopen; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; } /* Mark the various WEP bits as modified */ @@ -2350,15 +2022,13 @@ static int wlan_set_auth(struct net_device *dev, } if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) { assoc_req->secinfo.WPAenabled = 1; - assoc_req->secinfo.WEPstatus = wlan802_11WEPdisabled; - assoc_req->secinfo.authmode = - wlan802_11authmodeopen; + assoc_req->secinfo.wep_enabled = 0; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; } if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) { assoc_req->secinfo.WPA2enabled = 1; - assoc_req->secinfo.WEPstatus = wlan802_11WEPdisabled; - assoc_req->secinfo.authmode = - wlan802_11authmodeopen; + assoc_req->secinfo.wep_enabled = 0; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; } updated = 1; break; @@ -2376,14 +2046,11 @@ static int wlan_set_auth(struct net_device *dev, case IW_AUTH_80211_AUTH_ALG: if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) { - assoc_req->secinfo.authmode = - wlan802_11authmodeshared; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; } else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) { - assoc_req->secinfo.authmode = - wlan802_11authmodeopen; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; } else if (dwrq->value & IW_AUTH_ALG_LEAP) { - assoc_req->secinfo.authmode = - wlan802_11authmodenetworkEAP; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_LEAP; } else { ret = -EINVAL; } @@ -2396,9 +2063,8 @@ static int wlan_set_auth(struct net_device *dev, !assoc_req->secinfo.WPA2enabled) { assoc_req->secinfo.WPAenabled = 1; assoc_req->secinfo.WPA2enabled = 1; - assoc_req->secinfo.WEPstatus = wlan802_11WEPdisabled; - assoc_req->secinfo.authmode = - wlan802_11authmodeopen; + assoc_req->secinfo.wep_enabled = 0; + assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; } } else { assoc_req->secinfo.WPAenabled = 0; @@ -2455,19 +2121,7 @@ static int wlan_get_auth(struct net_device *dev, break; case IW_AUTH_80211_AUTH_ALG: - switch (adapter->secinfo.authmode) { - case wlan802_11authmodeshared: - dwrq->value = IW_AUTH_ALG_SHARED_KEY; - break; - case wlan802_11authmodeopen: - dwrq->value = IW_AUTH_ALG_OPEN_SYSTEM; - break; - case wlan802_11authmodenetworkEAP: - dwrq->value = IW_AUTH_ALG_LEAP; - break; - default: - break; - } + dwrq->value = adapter->secinfo.auth_mode; break; case IW_AUTH_WPA_ENABLED: diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h index 39f367c38d90..15cfaaf0797f 100644 --- a/drivers/net/wireless/libertas/wext.h +++ b/drivers/net/wireless/libertas/wext.h @@ -10,88 +10,22 @@ /** PRIVATE CMD ID */ #define WLANIOCTL SIOCIWFIRSTPRIV -#define WLANSETWPAIE (WLANIOCTL + 0) - -#define WLAN_SETINT_GETINT (WLANIOCTL + 7) -#define WLANNF 1 -#define WLANRSSI 2 -#define WLANENABLE11D 5 -#define WLANADHOCGRATE 6 -#define WLAN_SUBCMD_SET_PRESCAN 11 - #define WLAN_SETNONE_GETNONE (WLANIOCTL + 8) -#define WLANDEAUTH 1 -#define WLANRADIOON 2 -#define WLANRADIOOFF 3 -#define WLANREMOVEADHOCAES 4 -#define WLANADHOCSTOP 5 -#define WLANCIPHERTEST 6 -#define WLANCRYPTOTEST 7 - -#define WLANWLANIDLEON 10 -#define WLANWLANIDLEOFF 11 #define WLAN_SUBCMD_BT_RESET 13 #define WLAN_SUBCMD_FWT_RESET 14 -#define WLANGETLOG (WLANIOCTL + 9) -#define GETLOG_BUFSIZE 300 - -#define WLANSCAN_TYPE (WLANIOCTL + 11) - #define WLAN_SETNONE_GETONEINT (WLANIOCTL + 15) #define WLANGETREGION 1 -#define WLAN_GET_LISTEN_INTERVAL 2 -#define WLAN_GET_MULTIPLE_DTIM 3 -#define WLAN_GET_TX_RATE 4 -#define WLANGETBCNAVG 5 -#define WLAN_GET_LINKMODE 6 -#define WLAN_GET_RADIOMODE 7 -#define WLAN_GET_DEBUGMODE 8 #define WLAN_SUBCMD_FWT_CLEANUP 15 #define WLAN_SUBCMD_FWT_TIME 16 #define WLAN_SUBCMD_MESH_GET_TTL 17 -#define WLANREGCFRDWR (WLANIOCTL + 18) - -#define WLAN_SETNONE_GETTWELVE_CHAR (WLANIOCTL + 19) -#define WLAN_SUBCMD_GETRXANTENNA 1 -#define WLAN_SUBCMD_GETTXANTENNA 2 -#define WLAN_GET_TSF 3 - -#define WLAN_SETNONE_GETWORDCHAR (WLANIOCTL + 21) -#define WLANGETADHOCAES 1 - -#define WLAN_SETONEINT_GETONEINT (WLANIOCTL + 23) -#define WLAN_BEACON_INTERVAL 1 -#define WLAN_LISTENINTRVL 4 - -#define WLAN_TXCONTROL 6 -#define WLAN_NULLPKTINTERVAL 7 - #define WLAN_SETONEINT_GETNONE (WLANIOCTL + 24) -#define WLAN_SUBCMD_SETRXANTENNA 1 -#define WLAN_SUBCMD_SETTXANTENNA 2 -#define WLANSETAUTHALG 5 -#define WLANSET8021XAUTHALG 6 -#define WLANSETENCRYPTIONMODE 7 #define WLANSETREGION 8 -#define WLAN_SET_LISTEN_INTERVAL 9 - -#define WLAN_SET_MULTIPLE_DTIM 10 -#define WLAN_SET_ATIM_WINDOW 11 -#define WLANSETBCNAVG 13 -#define WLANSETDATAAVG 14 -#define WLAN_SET_LINKMODE 15 -#define WLAN_SET_RADIOMODE 16 -#define WLAN_SET_DEBUGMODE 17 #define WLAN_SUBCMD_MESH_SET_TTL 18 #define WLAN_SET128CHAR_GET128CHAR (WLANIOCTL + 25) -#define WLANSCAN_MODE 6 - -#define WLAN_GET_ADHOC_STATUS 9 - #define WLAN_SUBCMD_BT_ADD 18 #define WLAN_SUBCMD_BT_DEL 19 #define WLAN_SUBCMD_BT_LIST 20 @@ -103,27 +37,8 @@ #define WLAN_SUBCMD_FWT_LIST_ROUTE 26 #define WLAN_SET_GET_SIXTEEN_INT (WLANIOCTL + 29) -#define WLAN_TPCCFG 1 -#define WLAN_POWERCFG 2 - -#define WLAN_AUTO_FREQ_SET 3 -#define WLAN_AUTO_FREQ_GET 4 #define WLAN_LED_GPIO_CTRL 5 -#define WLAN_SCANPROBES 6 -#define WLAN_ADAPT_RATESET 8 -#define WLAN_INACTIVITY_TIMEOUT 9 -#define WLANSNR 10 -#define WLAN_GET_RATE 11 -#define WLAN_GET_RXINFO 12 - -#define WLANCMD52RDWR (WLANIOCTL + 30) -#define WLANCMD53RDWR (WLANIOCTL + 31) -#define CMD53BUFLEN 32 -#define REG_MAC 0x19 -#define REG_BBP 0x1a -#define REG_RF 0x1b -#define REG_EEPROM 0x59 #define WLAN_LINKMODE_802_3 0 #define WLAN_LINKMODE_802_11 2 #define WLAN_RADIOMODE_NONE 0 diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 78cf0711d1fa..ef07c36bccf7 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -249,19 +249,19 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, if (rc == PCI_SLOT_ALREADY_UP) { - dev_dbg(slot->pci_bus->self, "is already active\n"); + dev_dbg(&slot->pci_bus->self->dev, "is already active\n"); return 1; /* return 1 to user */ } if (rc == PCI_L1_ERR) { - dev_dbg(slot->pci_bus->self, + dev_dbg(&slot->pci_bus->self->dev, "L1 failure %d with message: %s", resp.resp_sub_errno, resp.resp_l1_msg); return -EPERM; } if (rc) { - dev_dbg(slot->pci_bus->self, + dev_dbg(&slot->pci_bus->self->dev, "insert failed with error %d sub-error %d\n", rc, resp.resp_sub_errno); return -EIO; @@ -287,25 +287,25 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_SLOT_ALREADY_DOWN)) { - dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n"); + dev_dbg(&slot->pci_bus->self->dev, "Slot %s already inactive\n", slot->physical_path); return 1; /* return 1 to user */ } if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_EMPTY_33MHZ)) { - dev_dbg(slot->pci_bus->self, + dev_dbg(&slot->pci_bus->self->dev, "Cannot remove last 33MHz card\n"); return -EPERM; } if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_L1_ERR)) { - dev_dbg(slot->pci_bus->self, + dev_dbg(&slot->pci_bus->self->dev, "L1 failure %d with message \n%s\n", resp.resp_sub_errno, resp.resp_l1_msg); return -EPERM; } if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) { - dev_dbg(slot->pci_bus->self, + dev_dbg(&slot->pci_bus->self->dev, "remove failed with error %d sub-error %d\n", rc, resp.resp_sub_errno); return -EIO; @@ -317,12 +317,12 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, if ((action == PCI_REQ_SLOT_DISABLE) && !rc) { pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); pcibus_info->pbi_enabled_devices &= ~(1 << device_num); - dev_dbg(slot->pci_bus->self, "remove successful\n"); + dev_dbg(&slot->pci_bus->self->dev, "remove successful\n"); return 0; } if ((action == PCI_REQ_SLOT_DISABLE) && rc) { - dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc); + dev_dbg(&slot->pci_bus->self->dev,"remove failed rc = %d\n", rc); } return rc; @@ -375,7 +375,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num + 1, 0)); if (!num_funcs) { - dev_dbg(slot->pci_bus->self, "no device in slot\n"); + dev_dbg(&slot->pci_bus->self->dev, "no device in slot\n"); mutex_unlock(&sn_hotplug_mutex); return -ENODEV; } @@ -427,7 +427,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle; if (acpi_bus_get_device(phandle, &pdevice)) { - dev_dbg(slot->pci_bus->self, + dev_dbg(&slot->pci_bus->self->dev, "no parent device, assuming NULL\n"); pdevice = NULL; } @@ -479,10 +479,10 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) mutex_unlock(&sn_hotplug_mutex); if (rc == 0) - dev_dbg(slot->pci_bus->self, + dev_dbg(&slot->pci_bus->self->dev, "insert operation successful\n"); else - dev_dbg(slot->pci_bus->self, + dev_dbg(&slot->pci_bus->self->dev, "insert operation failed rc = %d\n", rc); return rc; @@ -659,16 +659,16 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) if (rc) goto register_err; } - dev_dbg(pci_bus->self, "Registered bus with hotplug\n"); + dev_dbg(&pci_bus->self->dev, "Registered bus with hotplug\n"); return rc; register_err: - dev_dbg(pci_bus->self, "bus failed to register with err = %d\n", + dev_dbg(&pci_bus->self->dev, "bus failed to register with err = %d\n", rc); alloc_err: if (rc == -ENOMEM) - dev_dbg(pci_bus->self, "Memory allocation error\n"); + dev_dbg(&pci_bus->self->dev, "Memory allocation error\n"); /* destroy THIS element */ if (bss_hotplug_slot) @@ -701,10 +701,10 @@ static int sn_pci_hotplug_init(void) rc = sn_pci_bus_valid(pci_bus); if (rc != 1) { - dev_dbg(pci_bus->self, "not a valid hotplug bus\n"); + dev_dbg(&pci_bus->self->dev, "not a valid hotplug bus\n"); continue; } - dev_dbg(pci_bus->self, "valid hotplug bus\n"); + dev_dbg(&pci_bus->self->dev, "valid hotplug bus\n"); rc = sn_hotplug_slot_register(pci_bus); if (!rc) { diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index e6740d1a0824..d9cbd586ae4b 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -549,8 +549,10 @@ static int msi_free_irqs(struct pci_dev* dev) { struct msi_desc *entry, *tmp; - list_for_each_entry(entry, &dev->msi_list, list) - BUG_ON(irq_has_action(entry->irq)); + list_for_each_entry(entry, &dev->msi_list, list) { + if (entry->irq) + BUG_ON(irq_has_action(entry->irq)); + } arch_teardown_msi_irqs(dev); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 147d86f8edbf..6ccc2e95930a 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -875,6 +875,7 @@ static void __devinit quirk_sb600_sata(struct pci_dev *pdev) } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_sb600_sata); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_sb600_sata); /* * Serverworks CSB5 IDE does not fully support native mode diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 1759baad439c..95ce8f49e382 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -246,7 +246,7 @@ comment "Platform RTC drivers" config RTC_DRV_CMOS tristate "PC-style 'CMOS'" depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \ - || M32R || ATARI || POWERPC) + || M32R || ATARI || POWERPC || MIPS) help Say "yes" here to get direct support for the real time clock found in every PC or ACPI-based system, and some other boards. @@ -397,7 +397,7 @@ config RTC_DRV_BFIN config RTC_DRV_RS5C313 tristate "Ricoh RS5C313" - depends on RTC_CLASS && BROKEN + depends on RTC_CLASS && SH_LANDISK help If you say yes here you get support for the Ricoh RS5C313 RTC chips. diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index 9d6de371495b..66eb133bf5fd 100644 --- a/drivers/rtc/rtc-rs5c313.c +++ b/drivers/rtc/rtc-rs5c313.c @@ -126,7 +126,7 @@ static void rs5c313_write_data(unsigned char data) static unsigned char rs5c313_read_data(void) { int i; - unsigned char data; + unsigned char data = 0; for (i = 0; i < 8; i++) { ndelay(700); @@ -194,7 +194,7 @@ static void rs5c313_write_reg(unsigned char addr, unsigned char data) return; } -static inline unsigned char rs5c313_read_cntreg(unsigned char addr) +static inline unsigned char rs5c313_read_cntreg(void) { return rs5c313_read_reg(RS5C313_ADDR_CNTREG); } @@ -212,7 +212,9 @@ static inline void rs5c313_write_intintvreg(unsigned char data) static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) { int data; + int cnt; + cnt = 0; while (1) { RS5C313_CEENABLE; /* CE:H */ @@ -225,6 +227,10 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) RS5C313_CEDISABLE; ndelay(700); /* CE:L */ + if (cnt++ > 100) { + dev_err(dev, "%s: timeout error\n", __FUNCTION__); + return -EIO; + } } data = rs5c313_read_reg(RS5C313_ADDR_SEC); @@ -266,7 +272,9 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) { int data; + int cnt; + cnt = 0; /* busy check. */ while (1) { RS5C313_CEENABLE; /* CE:H */ @@ -279,6 +287,11 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) RS5C313_MISCOP; RS5C313_CEDISABLE; ndelay(700); /* CE:L */ + + if (cnt++ > 100) { + dev_err(dev, "%s: timeout error\n", __FUNCTION__); + return -EIO; + } } data = BIN2BCD(tm->tm_sec); @@ -317,6 +330,7 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) static void rs5c313_check_xstp_bit(void) { struct rtc_time tm; + int cnt; RS5C313_CEENABLE; /* CE:H */ if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) { @@ -326,12 +340,16 @@ static void rs5c313_check_xstp_bit(void) rs5c313_write_cntreg(0x07); /* busy check. */ - while (rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY) + for (cnt = 0; cnt < 100; cnt++) { + if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)) + break; RS5C313_MISCOP; + } memset(&tm, 0, sizeof(struct rtc_time)); tm.tm_mday = 1; - tm.tm_mon = 1; + tm.tm_mon = 1 - 1; + tm.tm_year = 2000 - 1900; rs5c313_rtc_set_time(NULL, &tm); printk(KERN_ERR "RICHO RS5C313: invalid value, resetting to " @@ -356,7 +374,7 @@ static int rs5c313_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); - return err; + return 0; } static int __devexit rs5c313_rtc_remove(struct platform_device *pdev) diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index f2be2ead8742..8328acab47fd 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -30,6 +30,7 @@ #include <asm/ebus.h> #include <asm/uaccess.h> #include <asm/envctrl.h> +#include <asm/io.h> #define ENVCTRL_MINOR 162 diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index a15752b37990..eef82758d047 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c @@ -6,87 +6,49 @@ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) * Copyright (C) 2001 Florian Lohoff (flo@rfc822.org) - * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org) * * (In all truth, Jed Schimmel wrote all this code.) */ -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/blkdev.h> + +#undef DEBUG + #include <linux/delay.h> #include <linux/dma-mapping.h> +#include <linux/gfp.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <linux/spinlock.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/sgialib.h> -#include <asm/sgi/sgi.h> -#include <asm/sgi/mc.h> #include <asm/sgi/hpc3.h> #include <asm/sgi/ip22.h> -#include <asm/irq.h> -#include <asm/io.h> +#include <asm/sgi/wd.h> #include "scsi.h" -#include <scsi/scsi_host.h> #include "wd33c93.h" -#include <linux/stat.h> - -#if 0 -#define DPRINTK(args...) printk(args) -#else -#define DPRINTK(args...) -#endif - -#define HDATA(ptr) ((struct ip22_hostdata *)((ptr)->hostdata)) - struct ip22_hostdata { struct WD33C93_hostdata wh; struct hpc_data { dma_addr_t dma; - void * cpu; + void *cpu; } hd; }; +#define host_to_hostdata(host) ((struct ip22_hostdata *)((host)->hostdata)) + struct hpc_chunk { struct hpc_dma_desc desc; u32 _padding; /* align to quadword boundary */ }; -struct Scsi_Host *sgiwd93_host; -struct Scsi_Host *sgiwd93_host1; - -/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */ -static inline void write_wd33c93_count(const wd33c93_regs regs, - unsigned long value) -{ - *regs.SASR = WD_TRANSFER_COUNT_MSB; - mb(); - *regs.SCMD = ((value >> 16) & 0xff); - *regs.SCMD = ((value >> 8) & 0xff); - *regs.SCMD = ((value >> 0) & 0xff); - mb(); -} - -static inline unsigned long read_wd33c93_count(const wd33c93_regs regs) -{ - unsigned long value; - - *regs.SASR = WD_TRANSFER_COUNT_MSB; - mb(); - value = ((*regs.SCMD & 0xff) << 16); - value |= ((*regs.SCMD & 0xff) << 8); - value |= ((*regs.SCMD & 0xff) << 0); - mb(); - return value; -} - static irqreturn_t sgiwd93_intr(int irq, void *dev_id) { - struct Scsi_Host * host = (struct Scsi_Host *) dev_id; + struct Scsi_Host * host = dev_id; unsigned long flags; spin_lock_irqsave(host->host_lock, flags); @@ -131,12 +93,12 @@ void fill_hpc_entries(struct hpc_chunk *hcp, struct scsi_cmnd *cmd, int datainp) static int dma_setup(struct scsi_cmnd *cmd, int datainp) { - struct ip22_hostdata *hdata = HDATA(cmd->device->host); + struct ip22_hostdata *hdata = host_to_hostdata(cmd->device->host); struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) cmd->device->host->base; struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->hd.cpu; - DPRINTK("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp); + pr_debug("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp); hdata->wh.dma_dir = datainp; @@ -151,7 +113,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int datainp) fill_hpc_entries(hcp, cmd, datainp); - DPRINTK(" HPCGO\n"); + pr_debug(" HPCGO\n"); /* Start up the HPC. */ hregs->ndptr = hdata->hd.dma; @@ -166,7 +128,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int datainp) static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { - struct ip22_hostdata *hdata = HDATA(instance); + struct ip22_hostdata *hdata = host_to_hostdata(instance); struct hpc3_scsiregs *hregs; if (!SCpnt) @@ -174,7 +136,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, hregs = (struct hpc3_scsiregs *) SCpnt->device->host->base; - DPRINTK("dma_stop: status<%d> ", status); + pr_debug("dma_stop: status<%d> ", status); /* First stop the HPC and flush it's FIFO. */ if (hdata->wh.dma_dir) { @@ -186,7 +148,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, dma_unmap_single(NULL, SCpnt->SCp.dma_handle, SCpnt->SCp.this_residual, SCpnt->sc_data_direction); - DPRINTK("\n"); + pr_debug("\n"); } void sgiwd93_reset(unsigned long base) @@ -216,29 +178,71 @@ static inline void init_hpc_chain(struct hpc_data *hd) hcp->desc.pnext = hd->dma; } -static struct Scsi_Host * __init sgiwd93_setup_scsi( - struct scsi_host_template *SGIblows, int unit, int irq, - struct hpc3_scsiregs *hregs, unsigned char *wdregs) +static int sgiwd93_bus_reset(struct scsi_cmnd *cmd) +{ + /* FIXME perform bus-specific reset */ + + /* FIXME 2: kill this function, and let midlayer fallback + to the same result, calling wd33c93_host_reset() */ + + spin_lock_irq(cmd->device->host->host_lock); + wd33c93_host_reset(cmd); + spin_unlock_irq(cmd->device->host->host_lock); + + return SUCCESS; +} + +/* + * Kludge alert - the SCSI code calls the abort and reset method with int + * arguments not with pointers. So this is going to blow up beautyfully + * on 64-bit systems with memory outside the compat address spaces. + */ +static struct scsi_host_template sgiwd93_template = { + .module = THIS_MODULE, + .proc_name = "SGIWD93", + .name = "SGI WD93", + .queuecommand = wd33c93_queuecommand, + .eh_abort_handler = wd33c93_abort, + .eh_bus_reset_handler = sgiwd93_bus_reset, + .eh_host_reset_handler = wd33c93_host_reset, + .can_queue = 16, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 8, + .use_clustering = DISABLE_CLUSTERING, +}; + +static int __init sgiwd93_probe(struct platform_device *pdev) { + struct sgiwd93_platform_data *pd = pdev->dev.platform_data; + unsigned char *wdregs = pd->wdregs; + struct hpc3_scsiregs *hregs = pd->hregs; struct ip22_hostdata *hdata; struct Scsi_Host *host; wd33c93_regs regs; - - host = scsi_register(SGIblows, sizeof(struct ip22_hostdata)); - if (!host) - return NULL; + unsigned int unit = pd->unit; + unsigned int irq = pd->irq; + int err; + + host = scsi_host_alloc(&sgiwd93_template, sizeof(struct ip22_hostdata)); + if (!host) { + err = -ENOMEM; + goto out; + } host->base = (unsigned long) hregs; host->irq = irq; - hdata = HDATA(host); - hdata->hd.cpu = dma_alloc_coherent(NULL, PAGE_SIZE, &hdata->hd.dma, - GFP_KERNEL); + hdata = host_to_hostdata(host); + hdata->hd.cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, + &hdata->hd.dma, GFP_KERNEL); if (!hdata->hd.cpu) { printk(KERN_WARNING "sgiwd93: Could not allocate memory for " "host %d buffer.\n", unit); - goto out_unregister; + err = -ENOMEM; + goto out_put; } + init_hpc_chain(&hdata->hd); regs.SASR = wdregs + 3; @@ -249,95 +253,67 @@ static struct Scsi_Host * __init sgiwd93_setup_scsi( if (hdata->wh.no_sync == 0xff) hdata->wh.no_sync = 0; - if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) { + err = request_irq(irq, sgiwd93_intr, 0, "SGI WD93", host); + if (err) { printk(KERN_WARNING "sgiwd93: Could not register irq %d " "for host %d.\n", irq, unit); goto out_free; } - return host; -out_free: - dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); - wd33c93_release(); + platform_set_drvdata(pdev, host); -out_unregister: - scsi_unregister(host); + err = scsi_add_host(host, NULL); + if (err) + goto out_irq; - return NULL; -} - -static int __init sgiwd93_detect(struct scsi_host_template *SGIblows) -{ - int found = 0; - - SGIblows->proc_name = "SGIWD93"; - sgiwd93_host = sgiwd93_setup_scsi(SGIblows, 0, SGI_WD93_0_IRQ, - &hpc3c0->scsi_chan0, - (unsigned char *)hpc3c0->scsi0_ext); - if (sgiwd93_host) - found++; - - /* Set up second controller on the Indigo2 */ - if (ip22_is_fullhouse()) { - sgiwd93_host1 = sgiwd93_setup_scsi(SGIblows, 1, SGI_WD93_1_IRQ, - &hpc3c0->scsi_chan1, - (unsigned char *)hpc3c0->scsi1_ext); - if (sgiwd93_host1) - found++; - } - - return found; -} + scsi_scan_host(host); -static int sgiwd93_release(struct Scsi_Host *instance) -{ - struct ip22_hostdata *hdata = HDATA(instance); - int irq = 0; - - if (sgiwd93_host && sgiwd93_host == instance) - irq = SGI_WD93_0_IRQ; - else if (sgiwd93_host1 && sgiwd93_host1 == instance) - irq = SGI_WD93_1_IRQ; + return 0; - free_irq(irq, sgiwd93_intr); +out_irq: + free_irq(irq, host); +out_free: dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); - wd33c93_release(); +out_put: + scsi_host_put(host); +out: - return 1; + return err; } -static int sgiwd93_bus_reset(struct scsi_cmnd *cmd) +static void __exit sgiwd93_remove(struct platform_device *pdev) { - /* FIXME perform bus-specific reset */ + struct Scsi_Host *host = platform_get_drvdata(pdev); + struct ip22_hostdata *hdata = (struct ip22_hostdata *) host->hostdata; + struct sgiwd93_platform_data *pd = pdev->dev.platform_data; + + scsi_remove_host(host); + free_irq(pd->irq, host); + dma_free_coherent(&pdev->dev, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); + scsi_host_put(host); +} - /* FIXME 2: kill this function, and let midlayer fallback - to the same result, calling wd33c93_host_reset() */ +static struct platform_driver sgiwd93_driver = { + .probe = sgiwd93_probe, + .remove = __devexit_p(sgiwd93_remove), + .driver = { + .name = "sgiwd93" + } +}; - spin_lock_irq(cmd->device->host->host_lock); - wd33c93_host_reset(cmd); - spin_unlock_irq(cmd->device->host->host_lock); +static int __init sgiwd93_module_init(void) +{ + return platform_driver_register(&sgiwd93_driver); +} - return SUCCESS; +static void __exit sgiwd93_module_exit(void) +{ + return platform_driver_unregister(&sgiwd93_driver); } -/* - * Kludge alert - the SCSI code calls the abort and reset method with int - * arguments not with pointers. So this is going to blow up beautyfully - * on 64-bit systems with memory outside the compat address spaces. - */ -static struct scsi_host_template driver_template = { - .proc_name = "SGIWD93", - .name = "SGI WD93", - .detect = sgiwd93_detect, - .release = sgiwd93_release, - .queuecommand = wd33c93_queuecommand, - .eh_abort_handler = wd33c93_abort, - .eh_bus_reset_handler = sgiwd93_bus_reset, - .eh_host_reset_handler = wd33c93_host_reset, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 8, - .use_clustering = DISABLE_CLUSTERING, -}; -#include "scsi_module.c" +module_init(sgiwd93_module_init); +module_exit(sgiwd93_module_exit); + +MODULE_DESCRIPTION("SGI WD33C93 driver"); +MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 7c9d37f651e3..5e3f748f2693 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -107,6 +107,13 @@ config SPI_IMX This enables using the Freescale iMX SPI controller in master mode. +config SPI_MPC52xx_PSC + tristate "Freescale MPC52xx PSC SPI controller" + depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL + help + This enables using the Freescale MPC52xx Programmable Serial + Controller in master SPI mode. + config SPI_MPC83xx tristate "Freescale MPC83xx SPI controller" depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 624b6363f490..5788d867de84 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o obj-$(CONFIG_SPI_IMX) += spi_imx.o obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o +obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c new file mode 100644 index 000000000000..052359fc41ee --- /dev/null +++ b/drivers/spi/mpc52xx_psc_spi.c @@ -0,0 +1,654 @@ +/* + * MPC52xx SPC in SPI mode driver. + * + * Maintainer: Dragos Carp + * + * Copyright (C) 2006 TOPTICA Photonics AG. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/interrupt.h> + +#if defined(CONFIG_PPC_MERGE) +#include <asm/of_platform.h> +#else +#include <linux/platform_device.h> +#endif + +#include <linux/workqueue.h> +#include <linux/completion.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/spi/spi.h> +#include <linux/fsl_devices.h> + +#include <asm/mpc52xx.h> +#include <asm/mpc52xx_psc.h> + +#define MCLK 20000000 /* PSC port MClk in hz */ + +struct mpc52xx_psc_spi { + /* fsl_spi_platform data */ + void (*activate_cs)(u8, u8); + void (*deactivate_cs)(u8, u8); + u32 sysclk; + + /* driver internal data */ + struct mpc52xx_psc __iomem *psc; + unsigned int irq; + u8 bits_per_word; + u8 busy; + + struct workqueue_struct *workqueue; + struct work_struct work; + + struct list_head queue; + spinlock_t lock; + + struct completion done; +}; + +/* controller state */ +struct mpc52xx_psc_spi_cs { + int bits_per_word; + int speed_hz; +}; + +/* set clock freq, clock ramp, bits per work + * if t is NULL then reset the values to the default values + */ +static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi, + struct spi_transfer *t) +{ + struct mpc52xx_psc_spi_cs *cs = spi->controller_state; + + cs->speed_hz = (t && t->speed_hz) + ? t->speed_hz : spi->max_speed_hz; + cs->bits_per_word = (t && t->bits_per_word) + ? t->bits_per_word : spi->bits_per_word; + cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8; + return 0; +} + +static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi) +{ + struct mpc52xx_psc_spi_cs *cs = spi->controller_state; + struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); + struct mpc52xx_psc __iomem *psc = mps->psc; + u32 sicr; + u16 ccr; + + sicr = in_be32(&psc->sicr); + + /* Set clock phase and polarity */ + if (spi->mode & SPI_CPHA) + sicr |= 0x00001000; + else + sicr &= ~0x00001000; + if (spi->mode & SPI_CPOL) + sicr |= 0x00002000; + else + sicr &= ~0x00002000; + + if (spi->mode & SPI_LSB_FIRST) + sicr |= 0x10000000; + else + sicr &= ~0x10000000; + out_be32(&psc->sicr, sicr); + + /* Set clock frequency and bits per word + * Because psc->ccr is defined as 16bit register instead of 32bit + * just set the lower byte of BitClkDiv + */ + ccr = in_be16(&psc->ccr); + ccr &= 0xFF00; + if (cs->speed_hz) + ccr |= (MCLK / cs->speed_hz - 1) & 0xFF; + else /* by default SPI Clk 1MHz */ + ccr |= (MCLK / 1000000 - 1) & 0xFF; + out_be16(&psc->ccr, ccr); + mps->bits_per_word = cs->bits_per_word; + + if (mps->activate_cs) + mps->activate_cs(spi->chip_select, + (spi->mode & SPI_CS_HIGH) ? 1 : 0); +} + +static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi) +{ + struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); + + if (mps->deactivate_cs) + mps->deactivate_cs(spi->chip_select, + (spi->mode & SPI_CS_HIGH) ? 1 : 0); +} + +#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1) +/* wake up when 80% fifo full */ +#define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100) + +static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, + struct spi_transfer *t) +{ + struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); + struct mpc52xx_psc __iomem *psc = mps->psc; + unsigned rb = 0; /* number of bytes receieved */ + unsigned sb = 0; /* number of bytes sent */ + unsigned char *rx_buf = (unsigned char *)t->rx_buf; + unsigned char *tx_buf = (unsigned char *)t->tx_buf; + unsigned rfalarm; + unsigned send_at_once = MPC52xx_PSC_BUFSIZE; + unsigned recv_at_once; + unsigned bpw = mps->bits_per_word / 8; + + if (!t->tx_buf && !t->rx_buf && t->len) + return -EINVAL; + + /* enable transmiter/receiver */ + out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); + while (rb < t->len) { + if (t->len - rb > MPC52xx_PSC_BUFSIZE) { + rfalarm = MPC52xx_PSC_RFALARM; + } else { + send_at_once = t->len - sb; + rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb); + } + + dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once); + if (tx_buf) { + for (; send_at_once; sb++, send_at_once--) { + /* set EOF flag */ + if (mps->bits_per_word + && (sb + 1) % bpw == 0) + out_8(&psc->ircr2, 0x01); + out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]); + } + } else { + for (; send_at_once; sb++, send_at_once--) { + /* set EOF flag */ + if (mps->bits_per_word + && ((sb + 1) % bpw) == 0) + out_8(&psc->ircr2, 0x01); + out_8(&psc->mpc52xx_psc_buffer_8, 0); + } + } + + + /* enable interupts and wait for wake up + * if just one byte is expected the Rx FIFO genererates no + * FFULL interrupt, so activate the RxRDY interrupt + */ + out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); + if (t->len - rb == 1) { + out_8(&psc->mode, 0); + } else { + out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL); + out_be16(&psc->rfalarm, rfalarm); + } + out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY); + wait_for_completion(&mps->done); + recv_at_once = in_be16(&psc->rfnum); + dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once); + + send_at_once = recv_at_once; + if (rx_buf) { + for (; recv_at_once; rb++, recv_at_once--) + rx_buf[rb] = in_8(&psc->mpc52xx_psc_buffer_8); + } else { + for (; recv_at_once; rb++, recv_at_once--) + in_8(&psc->mpc52xx_psc_buffer_8); + } + } + /* disable transmiter/receiver */ + out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); + + return 0; +} + +static void mpc52xx_psc_spi_work(struct work_struct *work) +{ + struct mpc52xx_psc_spi *mps = + container_of(work, struct mpc52xx_psc_spi, work); + + spin_lock_irq(&mps->lock); + mps->busy = 1; + while (!list_empty(&mps->queue)) { + struct spi_message *m; + struct spi_device *spi; + struct spi_transfer *t = NULL; + unsigned cs_change; + int status; + + m = container_of(mps->queue.next, struct spi_message, queue); + list_del_init(&m->queue); + spin_unlock_irq(&mps->lock); + + spi = m->spi; + cs_change = 1; + status = 0; + list_for_each_entry (t, &m->transfers, transfer_list) { + if (t->bits_per_word || t->speed_hz) { + status = mpc52xx_psc_spi_transfer_setup(spi, t); + if (status < 0) + break; + } + + if (cs_change) + mpc52xx_psc_spi_activate_cs(spi); + cs_change = t->cs_change; + + status = mpc52xx_psc_spi_transfer_rxtx(spi, t); + if (status) + break; + m->actual_length += t->len; + + if (t->delay_usecs) + udelay(t->delay_usecs); + + if (cs_change) + mpc52xx_psc_spi_deactivate_cs(spi); + } + + m->status = status; + m->complete(m->context); + + if (status || !cs_change) + mpc52xx_psc_spi_deactivate_cs(spi); + + mpc52xx_psc_spi_transfer_setup(spi, NULL); + + spin_lock_irq(&mps->lock); + } + mps->busy = 0; + spin_unlock_irq(&mps->lock); +} + +static int mpc52xx_psc_spi_setup(struct spi_device *spi) +{ + struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); + struct mpc52xx_psc_spi_cs *cs = spi->controller_state; + unsigned long flags; + + if (spi->bits_per_word%8) + return -EINVAL; + + if (!cs) { + cs = kzalloc(sizeof *cs, GFP_KERNEL); + if (!cs) + return -ENOMEM; + spi->controller_state = cs; + } + + cs->bits_per_word = spi->bits_per_word; + cs->speed_hz = spi->max_speed_hz; + + spin_lock_irqsave(&mps->lock, flags); + if (!mps->busy) + mpc52xx_psc_spi_deactivate_cs(spi); + spin_unlock_irqrestore(&mps->lock, flags); + + return 0; +} + +static int mpc52xx_psc_spi_transfer(struct spi_device *spi, + struct spi_message *m) +{ + struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); + unsigned long flags; + + m->actual_length = 0; + m->status = -EINPROGRESS; + + spin_lock_irqsave(&mps->lock, flags); + list_add_tail(&m->queue, &mps->queue); + queue_work(mps->workqueue, &mps->work); + spin_unlock_irqrestore(&mps->lock, flags); + + return 0; +} + +static void mpc52xx_psc_spi_cleanup(struct spi_device *spi) +{ + kfree(spi->controller_state); +} + +static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps) +{ + struct mpc52xx_cdm __iomem *cdm; + struct mpc52xx_gpio __iomem *gpio; + struct mpc52xx_psc __iomem *psc = mps->psc; + u32 ul; + u32 mclken_div; + int ret = 0; + +#if defined(CONFIG_PPC_MERGE) + cdm = mpc52xx_find_and_map("mpc52xx-cdm"); + gpio = mpc52xx_find_and_map("mpc52xx-gpio"); +#else + cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE); + gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE); +#endif + if (!cdm || !gpio) { + printk(KERN_ERR "Error mapping CDM/GPIO\n"); + ret = -EFAULT; + goto unmap_regs; + } + + /* default sysclk is 512MHz */ + mclken_div = 0x8000 | + (((mps->sysclk ? mps->sysclk : 512000000) / MCLK) & 0x1FF); + + switch (psc_id) { + case 1: + ul = in_be32(&gpio->port_config); + ul &= 0xFFFFFFF8; + ul |= 0x00000006; + out_be32(&gpio->port_config, ul); + out_be16(&cdm->mclken_div_psc1, mclken_div); + ul = in_be32(&cdm->clk_enables); + ul |= 0x00000020; + out_be32(&cdm->clk_enables, ul); + break; + case 2: + ul = in_be32(&gpio->port_config); + ul &= 0xFFFFFF8F; + ul |= 0x00000060; + out_be32(&gpio->port_config, ul); + out_be16(&cdm->mclken_div_psc2, mclken_div); + ul = in_be32(&cdm->clk_enables); + ul |= 0x00000040; + out_be32(&cdm->clk_enables, ul); + break; + case 3: + ul = in_be32(&gpio->port_config); + ul &= 0xFFFFF0FF; + ul |= 0x00000600; + out_be32(&gpio->port_config, ul); + out_be16(&cdm->mclken_div_psc3, mclken_div); + ul = in_be32(&cdm->clk_enables); + ul |= 0x00000080; + out_be32(&cdm->clk_enables, ul); + break; + case 6: + ul = in_be32(&gpio->port_config); + ul &= 0xFF8FFFFF; + ul |= 0x00700000; + out_be32(&gpio->port_config, ul); + out_be16(&cdm->mclken_div_psc6, mclken_div); + ul = in_be32(&cdm->clk_enables); + ul |= 0x00000010; + out_be32(&cdm->clk_enables, ul); + break; + default: + ret = -EINVAL; + goto unmap_regs; + } + + /* Reset the PSC into a known state */ + out_8(&psc->command, MPC52xx_PSC_RST_RX); + out_8(&psc->command, MPC52xx_PSC_RST_TX); + out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); + + /* Disable interrupts, interrupts are based on alarm level */ + out_be16(&psc->mpc52xx_psc_imr, 0); + out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); + out_8(&psc->rfcntl, 0); + out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL); + + /* Configure 8bit codec mode as a SPI master and use EOF flags */ + /* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */ + out_be32(&psc->sicr, 0x0180C800); + out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */ + + /* Set 2ms DTL delay */ + out_8(&psc->ctur, 0x00); + out_8(&psc->ctlr, 0x84); + + mps->bits_per_word = 8; + +unmap_regs: + if (cdm) + iounmap(cdm); + if (gpio) + iounmap(gpio); + + return ret; +} + +static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id) +{ + struct mpc52xx_psc_spi *mps = (struct mpc52xx_psc_spi *)dev_id; + struct mpc52xx_psc __iomem *psc = mps->psc; + + /* disable interrupt and wake up the work queue */ + if (in_be16(&psc->mpc52xx_psc_isr) & MPC52xx_PSC_IMR_RXRDY) { + out_be16(&psc->mpc52xx_psc_imr, 0); + complete(&mps->done); + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +/* bus_num is used only for the case dev->platform_data == NULL */ +static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, + u32 size, unsigned int irq, s16 bus_num) +{ + struct fsl_spi_platform_data *pdata = dev->platform_data; + struct mpc52xx_psc_spi *mps; + struct spi_master *master; + int ret; + + if (pdata == NULL) + return -ENODEV; + + master = spi_alloc_master(dev, sizeof *mps); + if (master == NULL) + return -ENOMEM; + + dev_set_drvdata(dev, master); + mps = spi_master_get_devdata(master); + + mps->irq = irq; + if (pdata == NULL) { + dev_warn(dev, "probe called without platform data, no " + "(de)activate_cs function will be called\n"); + mps->activate_cs = NULL; + mps->deactivate_cs = NULL; + mps->sysclk = 0; + master->bus_num = bus_num; + master->num_chipselect = 255; + } else { + mps->activate_cs = pdata->activate_cs; + mps->deactivate_cs = pdata->deactivate_cs; + mps->sysclk = pdata->sysclk; + master->bus_num = pdata->bus_num; + master->num_chipselect = pdata->max_chipselect; + } + master->setup = mpc52xx_psc_spi_setup; + master->transfer = mpc52xx_psc_spi_transfer; + master->cleanup = mpc52xx_psc_spi_cleanup; + + mps->psc = ioremap(regaddr, size); + if (!mps->psc) { + dev_err(dev, "could not ioremap I/O port range\n"); + ret = -EFAULT; + goto free_master; + } + + ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, "mpc52xx-psc-spi", + mps); + if (ret) + goto free_master; + + ret = mpc52xx_psc_spi_port_config(master->bus_num, mps); + if (ret < 0) + goto free_irq; + + spin_lock_init(&mps->lock); + init_completion(&mps->done); + INIT_WORK(&mps->work, mpc52xx_psc_spi_work); + INIT_LIST_HEAD(&mps->queue); + + mps->workqueue = create_singlethread_workqueue( + master->cdev.dev->bus_id); + if (mps->workqueue == NULL) { + ret = -EBUSY; + goto free_irq; + } + + ret = spi_register_master(master); + if (ret < 0) + goto unreg_master; + + return ret; + +unreg_master: + destroy_workqueue(mps->workqueue); +free_irq: + free_irq(mps->irq, mps); +free_master: + if (mps->psc) + iounmap(mps->psc); + spi_master_put(master); + + return ret; +} + +static int __exit mpc52xx_psc_spi_do_remove(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master); + + flush_workqueue(mps->workqueue); + destroy_workqueue(mps->workqueue); + spi_unregister_master(master); + free_irq(mps->irq, mps); + if (mps->psc) + iounmap(mps->psc); + + return 0; +} + +#if !defined(CONFIG_PPC_MERGE) +static int __init mpc52xx_psc_spi_probe(struct platform_device *dev) +{ + switch(dev->id) { + case 1: + case 2: + case 3: + case 6: + return mpc52xx_psc_spi_do_probe(&dev->dev, + MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)), + MPC52xx_PSC_SIZE, platform_get_irq(dev, 0), dev->id); + default: + return -EINVAL; + } +} + +static int __exit mpc52xx_psc_spi_remove(struct platform_device *dev) +{ + return mpc52xx_psc_spi_do_remove(&dev->dev); +} + +static struct platform_driver mpc52xx_psc_spi_platform_driver = { + .remove = __exit_p(mpc52xx_psc_spi_remove), + .driver = { + .name = "mpc52xx-psc-spi", + .owner = THIS_MODULE, + }, +}; + +static int __init mpc52xx_psc_spi_init(void) +{ + return platform_driver_probe(&mpc52xx_psc_spi_platform_driver, + mpc52xx_psc_spi_probe); +} +module_init(mpc52xx_psc_spi_init); + +static void __exit mpc52xx_psc_spi_exit(void) +{ + platform_driver_unregister(&mpc52xx_psc_spi_platform_driver); +} +module_exit(mpc52xx_psc_spi_exit); + +#else /* defined(CONFIG_PPC_MERGE) */ + +static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, + const struct of_device_id *match) +{ + const u32 *regaddr_p; + u64 regaddr64, size64; + s16 id = -1; + + regaddr_p = of_get_address(op->node, 0, &size64, NULL); + if (!regaddr_p) { + printk(KERN_ERR "Invalid PSC address\n"); + return -EINVAL; + } + regaddr64 = of_translate_address(op->node, regaddr_p); + + if (op->dev.platform_data == NULL) { + struct device_node *np; + int i = 0; + + for_each_node_by_type(np, "spi") { + if (of_find_device_by_node(np) == op) { + id = i; + break; + } + i++; + } + } + + return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64, + irq_of_parse_and_map(op->node, 0), id); +} + +static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op) +{ + return mpc52xx_psc_spi_do_remove(&op->dev); +} + +static struct of_device_id mpc52xx_psc_spi_of_match[] = { + { .type = "spi", .compatible = "mpc52xx-psc-spi", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match); + +static struct of_platform_driver mpc52xx_psc_spi_of_driver = { + .owner = THIS_MODULE, + .name = "mpc52xx-psc-spi", + .match_table = mpc52xx_psc_spi_of_match, + .probe = mpc52xx_psc_spi_of_probe, + .remove = __exit_p(mpc52xx_psc_spi_of_remove), + .driver = { + .name = "mpc52xx-psc-spi", + .owner = THIS_MODULE, + }, +}; + +static int __init mpc52xx_psc_spi_init(void) +{ + return of_register_platform_driver(&mpc52xx_psc_spi_of_driver); +} +module_init(mpc52xx_psc_spi_init); + +static void __exit mpc52xx_psc_spi_exit(void) +{ + of_unregister_platform_driver(&mpc52xx_psc_spi_of_driver); +} +module_exit(mpc52xx_psc_spi_exit); + +#endif /* defined(CONFIG_PPC_MERGE) */ + +MODULE_AUTHOR("Dragos Carp"); +MODULE_DESCRIPTION("MPC52xx PSC SPI Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index f54438828cb9..eebcb708cff1 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -748,6 +748,22 @@ config FB_S1D13XXX working with S1D13806). Product specs at <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm> +config FB_ATMEL + tristate "AT91/AT32 LCD Controller support" + depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || AVR32) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This enables support for the AT91/AT32 LCD Controller. + +config FB_INTSRAM + bool "Frame Buffer in internal SRAM" + depends on FB_ATMEL && ARCH_AT91SAM9261 + help + Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want + to let frame buffer in external SDRAM. + config FB_NVIDIA tristate "nVidia Framebuffer Support" depends on FB && PCI @@ -780,6 +796,15 @@ config FB_NVIDIA_I2C independently validate video mode parameters, you should say Y here. +config FB_NVIDIA_DEBUG + bool "Lots of debug output" + depends on FB_NVIDIA + default n + help + Say Y here if you want the nVidia driver to output all sorts + of debugging information to provide to the maintainer when + something goes wrong. + config FB_NVIDIA_BACKLIGHT bool "Support for backlight control" depends on FB_NVIDIA @@ -819,7 +844,7 @@ config FB_RIVA_I2C here. config FB_RIVA_DEBUG - bool "Lots of debug output from Riva(nVidia) driver" + bool "Lots of debug output" depends on FB_RIVA default n help @@ -1431,8 +1456,11 @@ config FB_ARK and ICS 5342 RAMDAC. config FB_PM3 - tristate "Permedia3 support" - depends on FB && PCI && BROKEN + tristate "Permedia3 support (EXPERIMENTAL)" + depends on FB && PCI && EXPERIMENTAL + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT help This is the frame buffer device driver for the 3DLabs Permedia3 chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 0b70567458fb..bd8b05229500 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_FB_G364) += g364fb.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o obj-$(CONFIG_FB_HIT) += hitfb.o obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o +obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c new file mode 100644 index 000000000000..e1d5bd0c98c4 --- /dev/null +++ b/drivers/video/atmel_lcdfb.c @@ -0,0 +1,752 @@ +/* + * Driver for AT91/AT32 LCD Controller + * + * Copyright (C) 2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/clk.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include <asm/arch/board.h> +#include <asm/arch/cpu.h> +#include <asm/arch/gpio.h> + +#include <video/atmel_lcdc.h> + +#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg)) +#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg)) + +/* configurable parameters */ +#define ATMEL_LCDC_CVAL_DEFAULT 0xc8 +#define ATMEL_LCDC_DMA_BURST_LEN 8 + +#if defined(CONFIG_ARCH_AT91SAM9263) +#define ATMEL_LCDC_FIFO_SIZE 2048 +#else +#define ATMEL_LCDC_FIFO_SIZE 512 +#endif + +#if defined(CONFIG_ARCH_AT91) +#define ATMEL_LCDFB_FBINFO_DEFAULT FBINFO_DEFAULT + +static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, + struct fb_var_screeninfo *var) +{ + +} +#elif defined(CONFIG_AVR32) +#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ + | FBINFO_PARTIAL_PAN_OK \ + | FBINFO_HWACCEL_XPAN \ + | FBINFO_HWACCEL_YPAN) + +static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, + struct fb_var_screeninfo *var) +{ + u32 dma2dcfg; + u32 pixeloff; + + pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f; + + dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8; + dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; + lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); + + /* Update configuration */ + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, + lcdc_readl(sinfo, ATMEL_LCDC_DMACON) + | ATMEL_LCDC_DMAUPDT); +} +#endif + + +static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + + +static void atmel_lcdfb_update_dma(struct fb_info *info, + struct fb_var_screeninfo *var) +{ + struct atmel_lcdfb_info *sinfo = info->par; + struct fb_fix_screeninfo *fix = &info->fix; + unsigned long dma_addr; + + dma_addr = (fix->smem_start + var->yoffset * fix->line_length + + var->xoffset * var->bits_per_pixel / 8); + + dma_addr &= ~3UL; + + /* Set framebuffer DMA base address and pixel offset */ + lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); + + atmel_lcdfb_update_dma2d(sinfo, var); +} + +static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) +{ + struct fb_info *info = sinfo->info; + + dma_free_writecombine(info->device, info->fix.smem_len, + info->screen_base, info->fix.smem_start); +} + +/** + * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory + * @sinfo: the frame buffer to allocate memory for + */ +static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) +{ + struct fb_info *info = sinfo->info; + struct fb_var_screeninfo *var = &info->var; + + info->fix.smem_len = (var->xres_virtual * var->yres_virtual + * ((var->bits_per_pixel + 7) / 8)); + + info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, + (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); + + if (!info->screen_base) { + return -ENOMEM; + } + + return 0; +} + +/** + * atmel_lcdfb_check_var - Validates a var passed in. + * @var: frame buffer variable screen structure + * @info: frame buffer structure that represents a single frame buffer + * + * Checks to see if the hardware supports the state requested by + * var passed in. This function does not alter the hardware + * state!!! This means the data stored in struct fb_info and + * struct atmel_lcdfb_info do not change. This includes the var + * inside of struct fb_info. Do NOT change these. This function + * can be called on its own if we intent to only test a mode and + * not actually set it. The stuff in modedb.c is a example of + * this. If the var passed in is slightly off by what the + * hardware can support then we alter the var PASSED in to what + * we can do. If the hardware doesn't support mode change a + * -EINVAL will be returned by the upper layers. You don't need + * to implement this function then. If you hardware doesn't + * support changing the resolution then this function is not + * needed. In this case the driver would just provide a var that + * represents the static state the screen is in. + * + * Returns negative errno on error, or zero on success. + */ +static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct device *dev = info->device; + struct atmel_lcdfb_info *sinfo = info->par; + unsigned long clk_value_khz; + + clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; + + dev_dbg(dev, "%s:\n", __func__); + dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); + dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock)); + dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); + dev_dbg(dev, " clk: %lu KHz\n", clk_value_khz); + + if ((PICOS2KHZ(var->pixclock) * var->bits_per_pixel / 8) > clk_value_khz) { + dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock)); + return -EINVAL; + } + + /* Force same alignment for each line */ + var->xres = (var->xres + 3) & ~3UL; + var->xres_virtual = (var->xres_virtual + 3) & ~3UL; + + var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0; + var->transp.msb_right = 0; + var->transp.offset = var->transp.length = 0; + var->xoffset = var->yoffset = 0; + + switch (var->bits_per_pixel) { + case 2: + case 4: + case 8: + var->red.offset = var->green.offset = var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length + = var->bits_per_pixel; + break; + case 15: + case 16: + var->red.offset = 0; + var->green.offset = 5; + var->blue.offset = 10; + var->red.length = var->green.length = var->blue.length = 5; + break; + case 24: + case 32: + var->red.offset = 0; + var->green.offset = 8; + var->blue.offset = 16; + var->red.length = var->green.length = var->blue.length = 8; + break; + default: + dev_err(dev, "color depth %d not supported\n", + var->bits_per_pixel); + return -EINVAL; + } + + return 0; +} + +/** + * atmel_lcdfb_set_par - Alters the hardware state. + * @info: frame buffer structure that represents a single frame buffer + * + * Using the fb_var_screeninfo in fb_info we set the resolution + * of the this particular framebuffer. This function alters the + * par AND the fb_fix_screeninfo stored in fb_info. It doesn't + * not alter var in fb_info since we are using that data. This + * means we depend on the data in var inside fb_info to be + * supported by the hardware. atmel_lcdfb_check_var is always called + * before atmel_lcdfb_set_par to ensure this. Again if you can't + * change the resolution you don't need this function. + * + */ +static int atmel_lcdfb_set_par(struct fb_info *info) +{ + struct atmel_lcdfb_info *sinfo = info->par; + unsigned long value; + unsigned long clk_value_khz; + + dev_dbg(info->device, "%s:\n", __func__); + dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", + info->var.xres, info->var.yres, + info->var.xres_virtual, info->var.yres_virtual); + + /* Turn off the LCD controller and the DMA controller */ + lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); + + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); + + if (info->var.bits_per_pixel <= 8) + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + else + info->fix.visual = FB_VISUAL_TRUECOLOR; + + info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8); + + /* Re-initialize the DMA engine... */ + dev_dbg(info->device, " * update DMA engine\n"); + atmel_lcdfb_update_dma(info, &info->var); + + /* ...set frame size and burst length = 8 words (?) */ + value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32; + value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET); + lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value); + + /* Now, the LCDC core... */ + + /* Set pixel clock */ + clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; + + value = clk_value_khz / PICOS2KHZ(info->var.pixclock); + + if (clk_value_khz % PICOS2KHZ(info->var.pixclock)) + value++; + + value = (value / 2) - 1; + + if (value <= 0) { + dev_notice(info->device, "Bypassing pixel clock divider\n"); + lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS); + } else + lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET); + + /* Initialize control register 2 */ + value = sinfo->default_lcdcon2; + + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) + value |= ATMEL_LCDC_INVLINE_INVERTED; + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) + value |= ATMEL_LCDC_INVFRAME_INVERTED; + + switch (info->var.bits_per_pixel) { + case 1: value |= ATMEL_LCDC_PIXELSIZE_1; break; + case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break; + case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break; + case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break; + case 15: /* fall through */ + case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break; + case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break; + case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break; + default: BUG(); break; + } + dev_dbg(info->device, " * LCDCON2 = %08lx\n", value); + lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value); + + /* Vertical timing */ + value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET; + value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET; + value |= info->var.lower_margin; + dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value); + lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value); + + /* Horizontal timing */ + value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET; + value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET; + value |= (info->var.left_margin - 1); + dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value); + lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); + + /* Display size */ + value = (info->var.xres - 1) << ATMEL_LCDC_HOZVAL_OFFSET; + value |= info->var.yres - 1; + lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value); + + /* FIFO Threshold: Use formula from data sheet */ + value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3); + lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value); + + /* Toggle LCD_MODE every frame */ + lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0); + + /* Disable all interrupts */ + lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); + + /* Set contrast */ + value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE; + lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value); + lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); + /* ...wait for DMA engine to become idle... */ + while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) + msleep(10); + + dev_dbg(info->device, " * re-enable DMA engine\n"); + /* ...and enable it with updated configuration */ + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); + + dev_dbg(info->device, " * re-enable LCDC core\n"); + lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, + (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); + + dev_dbg(info->device, " * DONE\n"); + + return 0; +} + +static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +/** + * atmel_lcdfb_setcolreg - Optional function. Sets a color register. + * @regno: Which register in the CLUT we are programming + * @red: The red value which can be up to 16 bits wide + * @green: The green value which can be up to 16 bits wide + * @blue: The blue value which can be up to 16 bits wide. + * @transp: If supported the alpha value which can be up to 16 bits wide. + * @info: frame buffer info structure + * + * Set a single color register. The values supplied have a 16 bit + * magnitude which needs to be scaled in this function for the hardware. + * Things to take into consideration are how many color registers, if + * any, are supported with the current color visual. With truecolor mode + * no color palettes are supported. Here a psuedo palette is created + * which we store the value in pseudo_palette in struct fb_info. For + * pseudocolor mode we have a limited color palette. To deal with this + * we can program what color is displayed for a particular pixel value. + * DirectColor is similar in that we can program each color field. If + * we have a static colormap we don't need to implement this function. + * + * Returns negative errno on error, or zero on success. In an + * ideal world, this would have been the case, but as it turns + * out, the other drivers return 1 on failure, so that's what + * we're going to do. + */ +static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) +{ + struct atmel_lcdfb_info *sinfo = info->par; + unsigned int val; + u32 *pal; + int ret = 1; + + if (info->var.grayscale) + red = green = blue = (19595 * red + 38470 * green + + 7471 * blue) >> 16; + + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + if (regno < 16) { + pal = info->pseudo_palette; + + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue, &info->var.blue); + + pal[regno] = val; + ret = 0; + } + break; + + case FB_VISUAL_PSEUDOCOLOR: + if (regno < 256) { + val = ((red >> 11) & 0x001f); + val |= ((green >> 6) & 0x03e0); + val |= ((blue >> 1) & 0x7c00); + + /* + * TODO: intensity bit. Maybe something like + * ~(red[10] ^ green[10] ^ blue[10]) & 1 + */ + + lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); + ret = 0; + } + break; + } + + return ret; +} + +static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + dev_dbg(info->device, "%s\n", __func__); + + atmel_lcdfb_update_dma(info, var); + + return 0; +} + +static struct fb_ops atmel_lcdfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = atmel_lcdfb_check_var, + .fb_set_par = atmel_lcdfb_set_par, + .fb_setcolreg = atmel_lcdfb_setcolreg, + .fb_pan_display = atmel_lcdfb_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id) +{ + struct fb_info *info = dev_id; + struct atmel_lcdfb_info *sinfo = info->par; + u32 status; + + status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); + lcdc_writel(sinfo, ATMEL_LCDC_IDR, status); + return IRQ_HANDLED; +} + +static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) +{ + struct fb_info *info = sinfo->info; + int ret = 0; + + memset_io(info->screen_base, 0, info->fix.smem_len); + info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; + + dev_info(info->device, + "%luKiB frame buffer at %08lx (mapped at %p)\n", + (unsigned long)info->fix.smem_len / 1024, + (unsigned long)info->fix.smem_start, + info->screen_base); + + /* Allocate colormap */ + ret = fb_alloc_cmap(&info->cmap, 256, 0); + if (ret < 0) + dev_err(info->device, "Alloc color map failed\n"); + + return ret; +} + +static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) +{ + if (sinfo->bus_clk) + clk_enable(sinfo->bus_clk); + clk_enable(sinfo->lcdc_clk); +} + +static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) +{ + if (sinfo->bus_clk) + clk_disable(sinfo->bus_clk); + clk_disable(sinfo->lcdc_clk); +} + + +static int __init atmel_lcdfb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct fb_info *info; + struct atmel_lcdfb_info *sinfo; + struct atmel_lcdfb_info *pdata_sinfo; + struct resource *regs = NULL; + struct resource *map = NULL; + int ret; + + dev_dbg(dev, "%s BEGIN\n", __func__); + + ret = -ENOMEM; + info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev); + if (!info) { + dev_err(dev, "cannot allocate memory\n"); + goto out; + } + + sinfo = info->par; + + if (dev->platform_data) { + pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data; + sinfo->default_bpp = pdata_sinfo->default_bpp; + sinfo->default_dmacon = pdata_sinfo->default_dmacon; + sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2; + sinfo->default_monspecs = pdata_sinfo->default_monspecs; + sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; + sinfo->guard_time = pdata_sinfo->guard_time; + } else { + dev_err(dev, "cannot get default configuration\n"); + goto free_info; + } + sinfo->info = info; + sinfo->pdev = pdev; + + strcpy(info->fix.id, sinfo->pdev->name); + info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; + info->pseudo_palette = sinfo->pseudo_palette; + info->fbops = &atmel_lcdfb_ops; + + memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs)); + info->fix = atmel_lcdfb_fix; + + /* Enable LCDC Clocks */ + if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) { + sinfo->bus_clk = clk_get(dev, "hck1"); + if (IS_ERR(sinfo->bus_clk)) { + ret = PTR_ERR(sinfo->bus_clk); + goto free_info; + } + } + sinfo->lcdc_clk = clk_get(dev, "lcdc_clk"); + if (IS_ERR(sinfo->lcdc_clk)) { + ret = PTR_ERR(sinfo->lcdc_clk); + goto put_bus_clk; + } + atmel_lcdfb_start_clock(sinfo); + + ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb, + info->monspecs.modedb_len, info->monspecs.modedb, + sinfo->default_bpp); + if (!ret) { + dev_err(dev, "no suitable video mode found\n"); + goto stop_clk; + } + + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(dev, "resources unusable\n"); + ret = -ENXIO; + goto stop_clk; + } + + sinfo->irq_base = platform_get_irq(pdev, 0); + if (sinfo->irq_base < 0) { + dev_err(dev, "unable to get irq\n"); + ret = sinfo->irq_base; + goto stop_clk; + } + + /* Initialize video memory */ + map = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (map) { + /* use a pre-allocated memory buffer */ + info->fix.smem_start = map->start; + info->fix.smem_len = map->end - map->start + 1; + if (!request_mem_region(info->fix.smem_start, + info->fix.smem_len, pdev->name)) { + ret = -EBUSY; + goto stop_clk; + } + + info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); + if (!info->screen_base) + goto release_intmem; + } else { + /* alocate memory buffer */ + ret = atmel_lcdfb_alloc_video_memory(sinfo); + if (ret < 0) { + dev_err(dev, "cannot allocate framebuffer: %d\n", ret); + goto stop_clk; + } + } + + /* LCDC registers */ + info->fix.mmio_start = regs->start; + info->fix.mmio_len = regs->end - regs->start + 1; + + if (!request_mem_region(info->fix.mmio_start, + info->fix.mmio_len, pdev->name)) { + ret = -EBUSY; + goto free_fb; + } + + sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); + if (!sinfo->mmio) { + dev_err(dev, "cannot map LCDC registers\n"); + goto release_mem; + } + + /* interrupt */ + ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); + if (ret) { + dev_err(dev, "request_irq failed: %d\n", ret); + goto unmap_mmio; + } + + ret = atmel_lcdfb_init_fbinfo(sinfo); + if (ret < 0) { + dev_err(dev, "init fbinfo failed: %d\n", ret); + goto unregister_irqs; + } + + /* + * This makes sure that our colour bitfield + * descriptors are correctly initialised. + */ + atmel_lcdfb_check_var(&info->var, info); + + ret = fb_set_var(info, &info->var); + if (ret) { + dev_warn(dev, "unable to set display parameters\n"); + goto free_cmap; + } + + dev_set_drvdata(dev, info); + + /* + * Tell the world that we're ready to go + */ + ret = register_framebuffer(info); + if (ret < 0) { + dev_err(dev, "failed to register framebuffer device: %d\n", ret); + goto free_cmap; + } + + /* Power up the LCDC screen */ + if (sinfo->atmel_lcdfb_power_control) + sinfo->atmel_lcdfb_power_control(1); + + dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n", + info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base); + + return 0; + + +free_cmap: + fb_dealloc_cmap(&info->cmap); +unregister_irqs: + free_irq(sinfo->irq_base, info); +unmap_mmio: + iounmap(sinfo->mmio); +release_mem: + release_mem_region(info->fix.mmio_start, info->fix.mmio_len); +free_fb: + if (map) + iounmap(info->screen_base); + else + atmel_lcdfb_free_video_memory(sinfo); + +release_intmem: + if (map) + release_mem_region(info->fix.smem_start, info->fix.smem_len); +stop_clk: + atmel_lcdfb_stop_clock(sinfo); + clk_put(sinfo->lcdc_clk); +put_bus_clk: + if (sinfo->bus_clk) + clk_put(sinfo->bus_clk); +free_info: + framebuffer_release(info); +out: + dev_dbg(dev, "%s FAILED\n", __func__); + return ret; +} + +static int __exit atmel_lcdfb_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct fb_info *info = dev_get_drvdata(dev); + struct atmel_lcdfb_info *sinfo = info->par; + + if (!sinfo) + return 0; + + if (sinfo->atmel_lcdfb_power_control) + sinfo->atmel_lcdfb_power_control(0); + unregister_framebuffer(info); + atmel_lcdfb_stop_clock(sinfo); + clk_put(sinfo->lcdc_clk); + if (sinfo->bus_clk) + clk_put(sinfo->bus_clk); + fb_dealloc_cmap(&info->cmap); + free_irq(sinfo->irq_base, info); + iounmap(sinfo->mmio); + release_mem_region(info->fix.mmio_start, info->fix.mmio_len); + if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) { + iounmap(info->screen_base); + release_mem_region(info->fix.smem_start, info->fix.smem_len); + } else { + atmel_lcdfb_free_video_memory(sinfo); + } + + dev_set_drvdata(dev, NULL); + framebuffer_release(info); + + return 0; +} + +static struct platform_driver atmel_lcdfb_driver = { + .remove = __exit_p(atmel_lcdfb_remove), + .driver = { + .name = "atmel_lcdfb", + .owner = THIS_MODULE, + }, +}; + +static int __init atmel_lcdfb_init(void) +{ + return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe); +} + +static void __exit atmel_lcdfb_exit(void) +{ + platform_driver_unregister(&atmel_lcdfb_driver); +} + +module_init(atmel_lcdfb_init); +module_exit(atmel_lcdfb_exit); + +MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); +MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@rfo.atmel.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index aa3935df852a..63b85bf81a65 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -19,13 +19,6 @@ config VGA_CONSOLE Say Y. -# if [ "$CONFIG_PCI" = "y" -a "$CONFIG_VGA_CONSOLE" = "y" ]; then -# bool ' Allow VGA on any bus?' CONFIG_VGA_HOSE -# if [ "$CONFIG_VGA_HOSE" = "y" ]; then -# define_bool CONFIG_DUMMY_CONSOLE y -# fi -# fi - config VGACON_SOFT_SCROLLBACK bool "Enable Scrollback Buffer in System RAM" depends on VGA_CONSOLE diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c index c627955aa124..aff11bbf59a7 100644 --- a/drivers/video/nvidia/nv_hw.c +++ b/drivers/video/nvidia/nv_hw.c @@ -149,7 +149,9 @@ static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk, pll = NV_RD32(par->PMC, 0x4024); M = pll & 0xFF; N = (pll >> 8) & 0xFF; - if (((par->Chipset & 0xfff0) == 0x0290) || ((par->Chipset & 0xfff0) == 0x0390) || ((par->Chipset & 0xfff0) == 0x02E0)) { + if (((par->Chipset & 0xfff0) == 0x0290) || + ((par->Chipset & 0xfff0) == 0x0390) || + ((par->Chipset & 0xfff0) == 0x02E0)) { MB = 1; NB = 1; } else { diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index f85edf084da3..41f63658572f 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -37,7 +37,6 @@ #include "nv_proto.h" #include "nv_dma.h" -#undef CONFIG_FB_NVIDIA_DEBUG #ifdef CONFIG_FB_NVIDIA_DEBUG #define NVTRACE printk #else diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 1ac5264bb2c1..ab5e66890e4e 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -204,17 +204,6 @@ static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a) } #endif -static void wait_pm2(struct pm2fb_par* par) { - - WAIT_FIFO(par, 1); - pm2_WR(par, PM2R_SYNC, 0); - mb(); - do { - while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0); - rmb(); - } while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC)); -} - /* * partial products for the supported horizontal resolutions. */ @@ -1050,13 +1039,30 @@ static int pm2fb_blank(int blank_mode, struct fb_info *info) return 0; } +static int pm2fb_sync(struct fb_info *info) +{ + struct pm2fb_par *par = info->par; + + WAIT_FIFO(par, 1); + pm2_WR(par, PM2R_SYNC, 0); + mb(); + do { + while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0) + udelay(10); + rmb(); + } while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC)); + + return 0; +} + /* * block operation. copy=0: rectangle fill, copy=1: rectangle copy. */ -static void pm2fb_block_op(struct pm2fb_par* par, int copy, +static void pm2fb_block_op(struct fb_info* info, int copy, s32 xsrc, s32 ysrc, s32 x, s32 y, s32 w, s32 h, u32 color) { + struct pm2fb_par *par = info->par; if (!w || !h) return; @@ -1076,13 +1082,11 @@ static void pm2fb_block_op(struct pm2fb_par* par, int copy, (x<xsrc ? PM2F_INCREASE_X : 0) | (y<ysrc ? PM2F_INCREASE_Y : 0) | (copy ? 0 : PM2F_RENDER_FASTFILL)); - wait_pm2(par); } static void pm2fb_fillrect (struct fb_info *info, const struct fb_fillrect *region) { - struct pm2fb_par *par = info->par; struct fb_fillrect modded; int vxres, vyres; u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ? @@ -1116,7 +1120,7 @@ static void pm2fb_fillrect (struct fb_info *info, color |= color << 16; if(info->var.bits_per_pixel != 24) - pm2fb_block_op(par, 0, 0, 0, + pm2fb_block_op(info, 0, 0, 0, modded.dx, modded.dy, modded.width, modded.height, color); else @@ -1126,7 +1130,6 @@ static void pm2fb_fillrect (struct fb_info *info, static void pm2fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { - struct pm2fb_par *par = info->par; struct fb_copyarea modded; u32 vxres, vyres; @@ -1156,7 +1159,7 @@ static void pm2fb_copyarea(struct fb_info *info, if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; - pm2fb_block_op(par, 1, modded.sx, modded.sy, + pm2fb_block_op(info, 1, modded.sx, modded.sy, modded.dx, modded.dy, modded.width, modded.height, 0); } @@ -1177,6 +1180,7 @@ static struct fb_ops pm2fb_ops = { .fb_fillrect = pm2fb_fillrect, .fb_copyarea = pm2fb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_sync = pm2fb_sync, }; /* diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index bd787e80177d..c77a1a1fd46b 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c @@ -1,55 +1,25 @@ /* * linux/drivers/video/pm3fb.c -- 3DLabs Permedia3 frame buffer device - * - * Copyright (C) 2001 Romain Dolbeau <dolbeau@irisa.fr> + * + * Copyright (C) 2001 Romain Dolbeau <romain@dolbeau.org>. + * + * Ported to 2.6 kernel on 1 May 2007 by Krzysztof Helt <krzysztof.h1@wp.pl> + * based on pm2fb.c + * * Based on code written by: - * Sven Luther, <luther@dpt-info.u-strasbg.fr> - * Alan Hourihane, <alanh@fairlite.demon.co.uk> - * Russell King, <rmk@arm.linux.org.uk> + * Sven Luther, <luther@dpt-info.u-strasbg.fr> + * Alan Hourihane, <alanh@fairlite.demon.co.uk> + * Russell King, <rmk@arm.linux.org.uk> * Based on linux/drivers/video/skeletonfb.c: * Copyright (C) 1997 Geert Uytterhoeven * Based on linux/driver/video/pm2fb.c: - * Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) - * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) + * Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) + * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. * - * $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $ - * - * CHANGELOG: - * Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update. - * Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2. - * Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16. - * Thu Sep 20 10:24:42 MET DST 2001, v 1.4.9: sync bug fix, preliminary flatpanel support, better timings. - * Tue Aug 28 10:13:01 MET DST 2001, v 1.4.8: memory timings check, minor bug fixes. - * Wed Jul 18 19:06:14 CEST 2001, v 1.4.7: Mode fix (800x600-100, 1024x768-100 changed), using HW panning + accel bug fix. - * Mon Jun 25 10:33:56 MET DST 2001, v 1.4.6: Depth 12 fix, chip reset ioctl, moved memory erase ioctl to DEBUG. - * Wed Jun 20 11:13:08 MET DST 2001, v 1.4.5: Fixed missing blinking cursor in 8bpp, code cleaning, memory erase IOCTL. - * Mon Jun 18 16:00:27 CEST 2001, v 1.4.4: Depth 12 (RGBA 4444) support, code cleaning. - * Fri Jun 15 13:53:01 CEST 2001, v 1.4.3: Removed warnings, depth 15 support, add 'depth' option. - * Thu Jun 14 10:13:52 MET DST 2001, v 1.4.2: Fixed depth switching bug, preliminary 15bpp (RGB5551) support. - * Thu Apr 12 11:16:45 MET DST 2001, v 1.4.1B: Doc updates. - * Fri Apr 6 11:12:53 MET DST 2001, v 1.4.1: Configure.help, minor cleanup - * Thu Mar 29 10:56:50 MET DST 2001, v 1.4.0: Module & module options support (note: linux patch changed, 2.2.19 added). - * Thu Mar 15 15:30:31 MET 2001, v 1.3.2: Fixed mirroring bug on little-endian. - * Wed Mar 14 21:25:54 CET 2001, v 1.3.1: Fixed bug in BlockMove (_bmov). - * Tue Mar 13 10:53:19 MET 2001, v 1.3.0: Character drawing hardware support (in all width between 1 and 16), fixes. - * Thu Mar 8 10:20:16 MET 2001, v 1.2.2: Better J2000 support, "font:" option. - * Tue Mar 6 21:25:04 CET 2001, v 1.2.1: Better acceleration support. - * Mon Mar 5 21:54:17 CET 2001, v 1.2.0: Partial acceleration support (clear & bmove) - * Mon Mar 5 12:52:15 CET 2001, v 1.1.3: Big pan_display fix. - * Sun Mar 4 22:21:50 CET 2001, v 1.1.2: (numerous) bug fixes. - * Fri Mar 2 15:54:07 CET 2001, v 1.1.1: Might have Appian J2000 support, resource mangement in 2.4 - * Wed Feb 28 18:21:35 CET 2001, v 1.1.0: Might have multiple boards support (added, but not yest tested) - * Tue Feb 27 17:31:12 CET 2001, v 1.0.6: fixes boot-time mode select, add more default mode - * Tue Feb 27 14:01:36 CET 2001, v 1.0.5: fixes (1.0.4 was broken for 2.2), cleaning up - * Mon Feb 26 23:17:36 CET 2001, v 1.0.4: preliminary 2.4.x support, dropped (useless on pm3) partial product, more OF fix - * Mon Feb 26 20:59:05 CET 2001, v 1.0.3: No more shadow register (and wasted memory), endianess fix, use OF-preset resolution by default - * Wed Feb 21 22:09:30 CET 2001, v 1.0.2: Code cleaning for future multiboard support, better OF support, bugs fix - * Wed Feb 21 19:58:56 CET 2001, v 1.0.1: OpenFirmware support, fixed memory detection, better debug support, code cleaning - * Wed Feb 21 14:47:06 CET 2001, v 1.0.0: First working version */ #include <linux/module.h> @@ -58,856 +28,155 @@ #include <linux/string.h> #include <linux/mm.h> #include <linux/slab.h> -#include <linux/vmalloc.h> #include <linux/delay.h> -#include <linux/interrupt.h> #include <linux/fb.h> #include <linux/init.h> #include <linux/pci.h> -#include <linux/ioport.h> -#include <linux/ctype.h> - -#include <video/fbcon.h> -#include <video/fbcon-mfb.h> -#include <video/fbcon-cfb2.h> -#include <video/fbcon-cfb4.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-cfb24.h> -#include <video/fbcon-cfb32.h> -#include <video/pm3fb.h> -#include <asm/io.h> -#include <asm/uaccess.h> +#include <video/pm3fb.h> -#ifdef CONFIG_FB_OF -#include <asm/prom.h> +#if !defined(CONFIG_PCI) +#error "Only generic PCI cards supported." #endif -/* ************************************* */ -/* ***** The various "global" data ***** */ -/* ************************************* */ - -/* those will need a rework for multiple board support */ -/* Driver name */ -static const char permedia3_name[16] = "Permedia3"; - -/* the fb_par struct, mandatory */ -struct pm3fb_par { - u32 pixclock; /* pixclock in KHz */ - - u32 width; /* width of virtual screen */ - u32 height; /* height of virtual screen */ - - u32 hsstart; /* horiz. sync start */ - u32 hsend; /* horiz. sync end */ - u32 hbend; /* horiz. blank end (also gate end) */ - u32 htotal; /* total width (w/ sync & blank) */ - - u32 vsstart; /* vert. sync start */ - u32 vsend; /* vert. sync end */ - u32 vbend; /* vert. blank end */ - u32 vtotal; /* total height (w/ sync & blank) */ - - u32 stride; /* screen stride */ - u32 base; /* screen base (xoffset+yoffset) in 128 bits unit */ - /* NOTE : unlike other pm3 stuff above, stored *after* shiftbpp. don't ask */ - u32 depth; /* screen depth (8, 12, 15, 16 or 32) */ - u32 video; /* video control (hsync,vsync) */ -}; - -/* memory timings */ -struct pm3fb_timings -{ - unsigned long caps; - unsigned long timings; - unsigned long control; - unsigned long refresh; - unsigned long powerdown; -}; -typedef enum pm3fb_timing_result { pm3fb_timing_ok, pm3fb_timing_problem, pm3fb_timing_retry } pm3fb_timing_result; -#define PM3FB_UNKNOWN_TIMING_VALUE ((unsigned long)-1) -#define PM3FB_UNKNOWN_TIMINGS { PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE } - -/* the fb_info struct, mandatory */ -struct pm3fb_info { - struct fb_info_gen gen; - unsigned long board_num; /* internal board number */ - unsigned long use_current; - struct pm3fb_par *current_par; - struct pci_dev *dev; /* PCI device */ - unsigned long board_type; /* index in the cardbase */ - unsigned char *fb_base; /* framebuffer memory base */ - u32 fb_size; /* framebuffer memory size */ - unsigned char *p_fb; /* physical address of frame buffer */ - unsigned char *v_fb; /* virtual address of frame buffer */ - unsigned char *pIOBase; /* physical address of registers region, must be rg_base or rg_base+PM2_REGS_SIZE depending on the host endianness */ - unsigned char *vIOBase; /* address of registers after ioremap() */ - struct { - u8 transp; - u8 red; - u8 green; - u8 blue; - } palette[256]; - union { -#ifdef FBCON_HAS_CFB16 - u16 cmap12[16]; /* RGBA 4444 */ - u16 cmap15[16]; /* RGBA 5551 */ - u16 cmap16[16]; /* RGBA 5650 */ -#endif -#ifdef FBCON_HAS_CFB32 - u32 cmap32[16]; +#undef PM3FB_MASTER_DEBUG +#ifdef PM3FB_MASTER_DEBUG +#define DPRINTK(a,b...) printk(KERN_DEBUG "pm3fb: %s: " a, __FUNCTION__ , ## b) +#else +#define DPRINTK(a,b...) #endif - } cmap; - struct pm3fb_timings memt; -}; -/* regular resolution database*/ -static struct { - char name[16]; - struct pm3fb_par user_mode; -} mode_base[] __initdata = { - { - "default-800x600", { - 49500, 800, 600, 16, 96, 256, 1056, 1, 4, 25, 625, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, { - "1024x768-74", { - 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38, - 806, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, { - "1024x768-74-32", { - 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38, - 806, 1024, 0, 32, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_32BIT}}, -/* Generated mode : "1600x1024", for the SGI 1600SW flat panel*/ - { - "SGI1600SW", { - 108000, 1600, 1024, 16, 56, 104, 1704, 3, 6, 32, - 1056, 1600, 0, 8, - PM3VideoControl_ENABLE| - PM3VideoControl_HSYNC_ACTIVE_LOW|PM3VideoControl_VSYNC_ACTIVE_LOW| - PM3VideoControl_PIXELSIZE_32BIT}}, -/* ##### auto-generated mode, by fbtimings2pm3 */ -/* Generated mode : "640x480-60" */ - { - "640x480-60", { - 25174, 640, 480, 16, 112, 160, 800, 10, 12, 45, - 525, 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "640x480-72" */ - { - "640x480-72", { - 31199, 640, 480, 24, 64, 192, 832, 9, 12, 40, 520, - 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "640x480-75" */ - { - "640x480-75", { - 31499, 640, 480, 16, 80, 200, 840, 1, 4, 20, 500, - 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "640x480-90" */ - { - "640x480-90", { - 39909, 640, 480, 32, 72, 192, 832, 25, 39, 53, 533, - 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "640x480-100" */ - { - "640x480-100", { - 44899, 640, 480, 32, 160, 208, 848, 22, 34, 51, - 531, 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-48-lace" */ -/* INTERLACED NOT SUPPORTED - {"800x600-48-lace", {35999, 800, 600, 80, 208, 264, 1064, 11, 23, 102, 702, 800, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "800x600-56" */ - { - "800x600-56", { - 35999, 800, 600, 24, 96, 224, 1024, 1, 3, 25, 625, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-60" */ - { - "800x600-60", { - 40000, 800, 600, 40, 168, 256, 1056, 1, 5, 28, 628, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-70" */ - { - "800x600-70", { - 44899, 800, 600, 24, 168, 208, 1008, 9, 21, 36, - 636, 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-72" */ - { - "800x600-72", { - 50000, 800, 600, 56, 176, 240, 1040, 37, 43, 66, - 666, 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-75" */ - { - "800x600-75", { - 49497, 800, 600, 16, 96, 256, 1056, 1, 4, 25, 625, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-90" */ - { - "800x600-90", { - 56637, 800, 600, 8, 72, 192, 992, 8, 19, 35, 635, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-100", from /etc/fb.modes */ -/* DISABLED, hsstart == 0 - { - "800x600-100", { - 67499, 800, 600, 0, 64, 280, 1080, 7, 11, 25, 625, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -*/ -/* Generated mode : "800x600-100", from ??? */ - { - "800x600-100", { - 69650, 800, 600, 64, 128, 288, 1088, 4, 10, 40, 640, 800, 0, 8, - PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_LOW| - PM3VideoControl_VSYNC_ACTIVE_LOW|PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-43-lace" */ -/* INTERLACED NOT SUPPORTED - {"1024x768-43-lace", {44899, 1024, 768, 8, 184, 240, 1264, 1, 9, 49, 817, 1024, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1024x768-60" */ - { - "1024x768-60", { - 64998, 1024, 768, 24, 160, 320, 1344, 3, 9, 38, - 806, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-70" */ - { - "1024x768-70", { - 74996, 1024, 768, 24, 160, 304, 1328, 3, 9, 38, - 806, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-72" */ - { - "1024x768-72", { - 74996, 10224, 768, 24, 160, 264, 10488, 3, 9, 38, - 806, 10224, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-75" */ - { - "1024x768-75", { - 78746, 1024, 768, 16, 112, 288, 1312, 1, 4, 32, - 800, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-90" */ - { - "1024x768-90", { - 100000, 1024, 768, 0, 96, 288, 1312, 21, 36, 77, - 845, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-100", from /etc/fb.modes */ -/* DISABLED, vsstart == 0 - { - "1024x768-100", { - 109998, 1024, 768, 0, 88, 368, 1392, 0, 8, 24, 792, - 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -*/ -/* Generated mode : "1024x768-100", from ??? */ - { - "1024x768-100", { - 115500, 1024, 768, 32, 224, 416, 1440, 3, 13, 34, 802, 1024, 0, 8, - PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_LOW| - PM3VideoControl_VSYNC_ACTIVE_LOW|PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1152x864-43-lace" */ -/* INTERLACED NOT SUPPORTED - {"1152x864-43-lace", {64998, 1152, 864, 72, 200, 264, 1416, 78, 87, 191, 1055, 1152, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1152x864-47-lace" */ -/* INTERLACED NOT SUPPORTED - {"1152x864-47-lace", {64998, 1152, 864, 88, 216, 296, 1448, 30, 39, 83, 947, 1152, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1152x864-60" */ - { - "1152x864-60", { - 80000, 1152, 864, 64, 176, 304, 1456, 6, 11, 52, - 916, 1152, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1152x864-70" */ - { - "1152x864-70", { - 100000, 1152, 864, 40, 192, 360, 1512, 13, 24, 81, - 945, 1152, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1152x864-75" */ - { - "1152x864-75", { - 109998, 1152, 864, 24, 168, 312, 1464, 45, 53, 138, - 1002, 1152, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1152x864-80" */ - { - "1152x864-80", { - 109998, 1152, 864, 16, 128, 288, 1440, 30, 37, 94, - 958, 1152, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1280x1024-43-lace" */ -/* INTERLACED NOT SUPPORTED - {"1280x1024-43-lace", {80000, 1024, 1024, 80, 160, 320, 1344, 50, 60, 125, 1149, 1024, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1280x1024-47-lace" */ -/* INTERLACED NOT SUPPORTED - {"1280x1024-47-lace", {80000, 1280, 1024, 80, 160, 320, 1600, 1, 11, 29, 1053, 1280, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1280x1024-60" */ - { - "1280x1024-60", { - 107991, 1280, 1024, 48, 160, 408, 1688, 1, 4, 42, - 1066, 1280, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1280x1024-70" */ - { - "1280x1024-70", { - 125992, 1280, 1024, 80, 192, 408, 1688, 1, 6, 42, - 1066, 1280, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1280x1024-74" */ - { - "1280x1024-74", { - 134989, 1280, 1024, 32, 176, 432, 1712, 0, 30, 40, - 1064, 1280, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1280x1024-75" */ - { - "1280x1024-75", { - 134989, 1280, 1024, 16, 160, 408, 1688, 1, 4, 42, - 1066, 1280, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1600x1200-60" */ - { - "1600x1200-60", { - 155981, 1600, 1200, 32, 192, 448, 2048, 10, 18, 70, - 1270, 1600, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1600x1200-66" */ - { - "1600x1200-66", { - 171998, 1600, 1200, 40, 176, 480, 2080, 3, 6, 53, - 1253, 1600, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1600x1200-76" */ - { - "1600x1200-76", { - 197980, 1600, 1200, 40, 176, 480, 2080, 3, 8, 50, - 1250, 1600, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* ##### end of auto-generated mode */ - { - "\0",} -}; - -/* more mandatory stuff (see skeletonfb.c + framebuffer driver HOWTO */ -static struct pm3fb_info fb_info[PM3_MAX_BOARD]; -static struct pm3fb_par current_par[PM3_MAX_BOARD]; -static int current_par_valid[PM3_MAX_BOARD]; -/* to allow explicit filtering of board */ -short bus[PM3_MAX_BOARD]; -short slot[PM3_MAX_BOARD]; -short func[PM3_MAX_BOARD]; -short disable[PM3_MAX_BOARD]; -short noaccel[PM3_MAX_BOARD]; -char fontn[PM3_MAX_BOARD][PM3_FONTNAME_SIZE]; -short depth[PM3_MAX_BOARD]; -short flatpanel[PM3_MAX_BOARD]; -static struct display disp[PM3_MAX_BOARD]; -static char g_options[PM3_OPTIONS_SIZE] __initdata = "pm3fb,dummy"; -short printtimings = 0; -short forcesize[PM3_MAX_BOARD]; - -/* ********************* */ -/* ***** prototype ***** */ -/* ********************* */ -/* card-specific */ -static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info); -/* permedia3-specific */ -static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info); -static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info); -static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info); -static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info, - unsigned long r); -static unsigned long pm3fb_CalculateClock(struct pm3fb_info *l_fb_info, unsigned long reqclock, /* In kHz units */ - unsigned long refclock, /* In kHz units */ - unsigned char *prescale, /* ClkPreScale */ - unsigned char *feedback, /* ClkFeedBackScale */ - unsigned char *postscale - /* ClkPostScale */ ); -static void pm3fb_clear_memory(struct pm3fb_info *l_fb_info, u32 cc); -static void pm3fb_clear_colormap(struct pm3fb_info *l_fb_info, unsigned char r, unsigned char g, unsigned char b); -static void pm3fb_common_init(struct pm3fb_info *l_fb_info); -static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info, - unsigned long depth, int v); -static int pm3fb_Unshiftbpp(struct pm3fb_info *l_fb_info, - unsigned long depth, int v); -static void pm3fb_mapIO(struct pm3fb_info *l_fb_info); -static void pm3fb_unmapIO(struct pm3fb_info *l_fb_info); -#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2) -static void pm3fb_show_cur_mode(struct pm3fb_info *l_fb_info); -#endif -static void pm3fb_show_cur_timing(struct pm3fb_info *l_fb_info); -static void pm3fb_write_mode(struct pm3fb_info *l_fb_info); -static void pm3fb_read_mode(struct pm3fb_info *l_fb_info, - struct pm3fb_par *curpar); -static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info); -/* accelerated permedia3-specific */ -#ifdef PM3FB_USE_ACCEL -static void pm3fb_wait_pm3(struct pm3fb_info *l_fb_info); -static void pm3fb_init_engine(struct pm3fb_info *l_fb_info); -#ifdef FBCON_HAS_CFB32 -static void pm3fb_cfb32_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width); -static void pm3fb_cfb32_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only); -#endif /* FBCON_HAS_CFB32 */ -#ifdef FBCON_HAS_CFB16 -static void pm3fb_cfb16_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width); -static void pm3fb_cfb16_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only); -#endif /* FBCON_HAS_CFB16 */ -#ifdef FBCON_HAS_CFB8 -static void pm3fb_cfb8_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width); -static void pm3fb_cfb8_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only); -#endif /* FBCON_HAS_CFB8 */ -#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) -static void pm3fb_cfbX_bmove(struct display *p, - int sy, int sx, - int dy, int dx, int height, int width); -static void pm3fb_cfbX_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx); -static void pm3fb_cfbX_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, - int xx); -static void pm3fb_cfbX_revc(struct display *p, int xx, int yy); -#endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */ -#endif /* PM3FB_USE_ACCEL */ -/* pre-init */ -static void pm3fb_mode_setup(char *mode, unsigned long board_num); -static void pm3fb_pciid_setup(char *pciid, unsigned long board_num); -static char *pm3fb_boardnum_setup(char *options, unsigned long *bn); -static void pm3fb_real_setup(char *options); -/* fbdev */ -static int pm3fb_encode_fix(struct fb_fix_screeninfo *fix, - const void *par, struct fb_info_gen *info); -static int pm3fb_decode_var(const struct fb_var_screeninfo *var, - void *par, struct fb_info_gen *info); -static void pm3fb_encode_depth(struct fb_var_screeninfo *var, long d); -static int pm3fb_encode_var(struct fb_var_screeninfo *var, - const void *par, struct fb_info_gen *info); -static void pm3fb_get_par(void *par, struct fb_info_gen *info); -static void pm3fb_set_par(const void *par, struct fb_info_gen *info); -static void pm3fb_set_color(struct pm3fb_info *l_fb_info, - unsigned char regno, unsigned char r, - unsigned char g, unsigned char b); -static int pm3fb_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info); -static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info); -static int pm3fb_blank(int blank_mode, struct fb_info_gen *info); -static void pm3fb_set_disp(const void *par, struct display *disp, - struct fb_info_gen *info); -static void pm3fb_detect(void); -static int pm3fb_pan_display(const struct fb_var_screeninfo *var, - struct fb_info_gen *info); -static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg); - - -/* the struct that hold them together */ -struct fbgen_hwswitch pm3fb_switch = { - pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var, - pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg, - pm3fb_pan_display, pm3fb_blank, pm3fb_set_disp -}; +/* + * Driver data + */ +static char *mode_option __devinitdata; -static struct fb_ops pm3fb_ops = { - .owner = THIS_MODULE, - .fb_get_fix = fbgen_get_fix, - .fb_get_var = fbgen_get_var, - .fb_set_var = fbgen_set_var, - .fb_get_cmap = fbgen_get_cmap, - .fb_set_cmap = fbgen_set_cmap, - .fb_setcolreg = pm3fb_setcolreg, - .fb_pan_display =fbgen_pan_display, - .fb_blank = fbgen_blank, - .fb_ioctl = pm3fb_ioctl, -}; +/* + * If your driver supports multiple boards, you should make the + * below data types arrays, or allocate them dynamically (using kmalloc()). + */ -#ifdef PM3FB_USE_ACCEL -#ifdef FBCON_HAS_CFB32 -static struct display_switch pm3fb_cfb32 = { - fbcon_cfb32_setup, pm3fb_cfbX_bmove, pm3fb_cfb32_clear, - pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc, - NULL /* cursor() */ , NULL /* set_font() */ , - pm3fb_cfb32_clear_margins, - FONTWIDTHRANGE(1, 16) /* true only if accelerated... */ -}; -#endif /* FBCON_HAS_CFB32 */ -#ifdef FBCON_HAS_CFB16 -static struct display_switch pm3fb_cfb16 = { - fbcon_cfb16_setup, pm3fb_cfbX_bmove, pm3fb_cfb16_clear, - pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc, - NULL /* cursor() */ , NULL /* set_font() */ , - pm3fb_cfb16_clear_margins, - FONTWIDTHRANGE(1, 16) /* true only if accelerated... */ -}; -#endif /* FBCON_HAS_CFB16 */ -#ifdef FBCON_HAS_CFB8 -static struct display_switch pm3fb_cfb8 = { - fbcon_cfb8_setup, pm3fb_cfbX_bmove, pm3fb_cfb8_clear, - pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc, - NULL /* cursor() */ , NULL /* set_font() */ , - pm3fb_cfb8_clear_margins, - FONTWIDTHRANGE(1, 16) /* true only if accelerated... */ -}; -#endif /* FBCON_HAS_CFB8 */ -#endif /* PM3FB_USE_ACCEL */ - -/* ****************************** */ -/* ***** card-specific data ***** */ -/* ****************************** */ -struct pm3fb_card_timings { - unsigned long memsize; /* 0 for last value (i.e. default) */ - struct pm3fb_timings memt; +/* + * This structure defines the hardware state of the graphics card. Normally + * you place this in a header file in linux/include/video. This file usually + * also includes register information. That allows other driver subsystems + * and userland applications the ability to use the same header file to + * avoid duplicate work and easy porting of software. + */ +struct pm3_par { + unsigned char __iomem *v_regs;/* virtual address of p_regs */ + u32 video; /* video flags before blanking */ + u32 base; /* screen base (xoffset+yoffset) in 128 bits unit */ + u32 palette[16]; }; -static struct pm3fb_card_timings t_FormacProFormance3[] = { - { 16, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} }, - { 0, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} } /* from 16 MB PF3 */ +/* + * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo + * if we don't use modedb. If we do use modedb see pm3fb_init how to use it + * to get a fb_var_screeninfo. Otherwise define a default var as well. + */ +static struct fb_fix_screeninfo pm3fb_fix __devinitdata = { + .id = "Permedia3", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .xpanstep = 1, + .ypanstep = 1, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, }; -static struct pm3fb_card_timings t_AppianJeronimo2000[] = { - { 32, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} }, - { 0, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} } /* from 32MB J2000 */ -}; +/* + * Utility functions + */ -static struct pm3fb_card_timings t_3DLabsOxygenVX1[] = { - { 32, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} }, - { 0, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} } /* from 32MB VX1 */ -}; +static inline u32 PM3_READ_REG(struct pm3_par *par, s32 off) +{ + return fb_readl(par->v_regs + off); +} -static struct { - char cardname[32]; /* recognized card name */ - u16 subvendor; /* subvendor of the card */ - u16 subdevice; /* subdevice of the card */ - u8 func; /* function of the card to which the extra init apply */ - void (*specific_setup)(struct pm3fb_info *l_fb_info); /* card/func specific setup, done before _any_ FB access */ - struct pm3fb_card_timings *c_memt; /* defauls timings for the boards */ -} cardbase[] = { - { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, NULL }, - { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL, - t_AppianJeronimo2000 - }, - { "Appian Jeronimo 2000 head 2", 0x1097, 0x3d32, 2, pm3fb_j2000_setup, - t_AppianJeronimo2000 - }, - { "Formac ProFormance 3", PCI_VENDOR_ID_3DLABS, 0x000a, 0, NULL, /* Formac use 3DLabs ID ?!? */ - t_FormacProFormance3 - }, - { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, NULL }, - { "3DLabs Oxygen VX1 PCI", PCI_VENDOR_ID_3DLABS, 0x0121, 0, NULL, - t_3DLabsOxygenVX1 - }, - { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, NULL }, - { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, NULL }, - { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, NULL }, - { "\0", 0x0, 0x0, 0, NULL, NULL } -}; +static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v) +{ + fb_writel(v, par->v_regs + off); +} -/* ********************************** */ -/* ***** card-specific function ***** */ -/* ********************************** */ -static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info) -{ /* the appian j2000 require more initialization of the second head */ - /* l_fb_info must point to the _second_ head of the J2000 */ - - DTRACE; - - l_fb_info->memt = t_AppianJeronimo2000[0].memt; /* 32 MB, first and only j2000 ? */ - - pm3fb_write_memory_timings(l_fb_info); +static inline void PM3_WAIT(struct pm3_par *par, u32 n) +{ + while (PM3_READ_REG(par, PM3InFIFOSpace) < n); } -/* *************************************** */ -/* ***** permedia3-specific function ***** */ -/* *************************************** */ -static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info) +static inline void PM3_SLOW_WRITE_REG(struct pm3_par *par, s32 off, u32 v) { - l_fb_info->memt.caps = PM3_READ_REG(PM3LocalMemCaps); - l_fb_info->memt.timings = PM3_READ_REG(PM3LocalMemTimings); - l_fb_info->memt.control = PM3_READ_REG(PM3LocalMemControl); - l_fb_info->memt.refresh = PM3_READ_REG(PM3LocalMemRefresh); - l_fb_info->memt.powerdown = PM3_READ_REG(PM3LocalMemPowerDown); - - if ((l_fb_info->memt.caps == PM3FB_UNKNOWN_TIMING_VALUE) || - (l_fb_info->memt.timings == PM3FB_UNKNOWN_TIMING_VALUE) || - (l_fb_info->memt.control == PM3FB_UNKNOWN_TIMING_VALUE) || - (l_fb_info->memt.refresh == PM3FB_UNKNOWN_TIMING_VALUE) || - (l_fb_info->memt.powerdown == PM3FB_UNKNOWN_TIMING_VALUE)) - { - printk(KERN_ERR "pm3fb: invalid memory timings in permedia3 board #%ld\n", l_fb_info->board_num); - return(pm3fb_try_memory_timings(l_fb_info)); + if (par->v_regs) { + mb(); + PM3_WAIT(par, 1); + wmb(); + PM3_WRITE_REG(par, off, v); } - return(pm3fb_timing_ok); } -static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info) +static inline void PM3_SET_INDEX(struct pm3_par *par, unsigned index) { - if (cardbase[l_fb_info->board_type].c_memt) - { - int i = 0, done = 0; - while (!done) - { - if ((cardbase[l_fb_info->board_type].c_memt[i].memsize == l_fb_info->fb_size) - || !(cardbase[l_fb_info->board_type].c_memt[i].memsize)) - { /* will use the 0-sized timings by default */ - done = 1; - l_fb_info->memt = cardbase[l_fb_info->board_type].c_memt[i].memt; - printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s, %ld MB)\n", - l_fb_info->board_num, - cardbase[l_fb_info->board_type].cardname, - cardbase[l_fb_info->board_type].c_memt[i].memsize); - pm3fb_write_memory_timings(l_fb_info); - return(pm3fb_timing_retry); - } - i++; - } - } else - return(pm3fb_timing_problem); - return(pm3fb_timing_ok); + PM3_SLOW_WRITE_REG(par, PM3RD_IndexHigh, (index >> 8) & 0xff); + PM3_SLOW_WRITE_REG(par, PM3RD_IndexLow, index & 0xff); +} + +static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v) +{ + PM3_SET_INDEX(par, r); + wmb(); + PM3_WRITE_REG(par, PM3RD_IndexedData, v); } -static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info) +static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno, + unsigned char r, unsigned char g, unsigned char b) { - unsigned char m, n, p; - unsigned long clockused; - - PM3_SLOW_WRITE_REG(PM3LocalMemCaps, l_fb_info->memt.caps); - PM3_SLOW_WRITE_REG(PM3LocalMemTimings, l_fb_info->memt.timings); - PM3_SLOW_WRITE_REG(PM3LocalMemControl, l_fb_info->memt.control); - PM3_SLOW_WRITE_REG(PM3LocalMemRefresh, l_fb_info->memt.refresh); - PM3_SLOW_WRITE_REG(PM3LocalMemPowerDown, l_fb_info->memt.powerdown); - - clockused = - pm3fb_CalculateClock(l_fb_info, 2 * 105000, PM3_REF_CLOCK, &m, - &n, &p); - - PM3_WRITE_DAC_REG(PM3RD_KClkPreScale, m); - PM3_WRITE_DAC_REG(PM3RD_KClkFeedbackScale, n); - PM3_WRITE_DAC_REG(PM3RD_KClkPostScale, p); - PM3_WRITE_DAC_REG(PM3RD_KClkControl, - PM3RD_KClkControl_STATE_RUN | - PM3RD_KClkControl_SOURCE_PLL | - PM3RD_KClkControl_ENABLE); - PM3_WRITE_DAC_REG(PM3RD_MClkControl, - PM3RD_MClkControl_STATE_RUN | - PM3RD_MClkControl_SOURCE_KCLK | - PM3RD_MClkControl_ENABLE); - PM3_WRITE_DAC_REG(PM3RD_SClkControl, - PM3RD_SClkControl_STATE_RUN | - PM3RD_SClkControl_SOURCE_PCLK | - PM3RD_SClkControl_ENABLE); + PM3_SLOW_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno); + PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, r); + PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, g); + PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, b); } -static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info, - unsigned long r) +static void pm3fb_clear_colormap(struct pm3_par *par, + unsigned char r, unsigned char g, unsigned char b) { - DASSERT((l_fb_info->vIOBase != (unsigned char *) (-1)), - "l_fb_info->vIOBase mapped in read dac reg\n"); - PM3_SET_INDEX(r); - mb(); - return (PM3_READ_REG(PM3RD_IndexedData)); + int i; + + for (i = 0; i < 256 ; i++) /* fill color map with white */ + pm3fb_set_color(par, i, r, g, b); + } /* Calculating various clock parameter */ -static unsigned long pm3fb_CalculateClock(struct pm3fb_info *l_fb_info, unsigned long reqclock, /* In kHz units */ - unsigned long refclock, /* In kHz units */ - unsigned char *prescale, /* ClkPreScale */ - unsigned char *feedback, /* ClkFeedBackScale */ - unsigned char *postscale - /* ClkPostScale */ ) +static void pm3fb_calculate_clock(unsigned long reqclock, + unsigned char *prescale, + unsigned char *feedback, + unsigned char *postscale) { int f, pre, post; unsigned long freq; long freqerr = 1000; - unsigned long actualclock = 0; - - DTRACE; + long currerr; for (f = 1; f < 256; f++) { for (pre = 1; pre < 256; pre++) { for (post = 0; post < 5; post++) { - freq = - ((2 * refclock * f) / - (pre * (1 << post))); - if ((reqclock > freq - freqerr) - && (reqclock < freq + freqerr)) { - freqerr = - (reqclock > - freq) ? reqclock - - freq : freq - reqclock; + freq = ((2*PM3_REF_CLOCK * f) >> post) / pre; + currerr = (reqclock > freq) + ? reqclock - freq + : freq - reqclock; + if (currerr < freqerr) { + freqerr = currerr; *feedback = f; *prescale = pre; *postscale = post; - actualclock = freq; } } } } - - return (actualclock); } -static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info, - unsigned long depth, int v) +static inline int pm3fb_shift_bpp(unsigned long depth, int v) { - DTRACE; - switch (depth) { case 8: return (v >> 4); @@ -918,181 +187,59 @@ static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info, case 32: return (v >> 2); } - DPRINTK(1, "Unsupported depth %ld\n", depth); - return (0); -} - -static int pm3fb_Unshiftbpp(struct pm3fb_info *l_fb_info, - unsigned long depth, int v) -{ - DTRACE; - - switch (depth) { - case 8: - return (v << 4); - case 12: - case 15: - case 16: - return (v << 3); - case 32: - return (v << 2); - } - DPRINTK(1, "Unsupported depth %ld\n", depth); - return (0); -} - -static void pm3fb_mapIO(struct pm3fb_info *l_fb_info) -{ - DTRACE; - - l_fb_info->vIOBase = - ioremap((unsigned long) l_fb_info->pIOBase, PM3_REGS_SIZE); - l_fb_info->v_fb = - ioremap((unsigned long) l_fb_info->p_fb, l_fb_info->fb_size); - DPRINTK(2, "IO mapping : IOBase %lx / %lx, fb %lx / %lx\n", - (unsigned long) l_fb_info->pIOBase, - (unsigned long) l_fb_info->vIOBase, - (unsigned long) l_fb_info->p_fb, - (unsigned long) l_fb_info->v_fb); -} - -static void pm3fb_unmapIO(struct pm3fb_info *l_fb_info) -{ - DTRACE; - - iounmap(l_fb_info->vIOBase); - iounmap(l_fb_info->v_fb); - l_fb_info->vIOBase = (unsigned char *) -1; - l_fb_info->v_fb = (unsigned char *) -1; -} - -#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2) -static void pm3fb_show_cur_mode(struct pm3fb_info *l_fb_info) -{ - DPRINTK(2, "PM3Aperture0: 0x%08x\n", PM3_READ_REG(PM3Aperture0)); - DPRINTK(2, "PM3Aperture1: 0x%08x\n", PM3_READ_REG(PM3Aperture1)); - DPRINTK(2, "PM3ByAperture1Mode: 0x%08x\n", - PM3_READ_REG(PM3ByAperture1Mode)); - DPRINTK(2, "PM3ByAperture2Mode: 0x%08x\n", - PM3_READ_REG(PM3ByAperture2Mode)); - DPRINTK(2, "PM3ChipConfig: 0x%08x\n", PM3_READ_REG(PM3ChipConfig)); - DPRINTK(2, "PM3FIFODis: 0x%08x\n", PM3_READ_REG(PM3FIFODis)); - DPRINTK(2, "PM3HTotal: 0x%08x\n", PM3_READ_REG(PM3HTotal)); - DPRINTK(2, "PM3HbEnd: 0x%08x\n", PM3_READ_REG(PM3HbEnd)); - DPRINTK(2, "PM3HgEnd: 0x%08x\n", PM3_READ_REG(PM3HgEnd)); - DPRINTK(2, "PM3HsEnd: 0x%08x\n", PM3_READ_REG(PM3HsEnd)); - DPRINTK(2, "PM3HsStart: 0x%08x\n", PM3_READ_REG(PM3HsStart)); - DPRINTK(2, "PM3MemBypassWriteMask: 0x%08x\n", - PM3_READ_REG(PM3MemBypassWriteMask)); - DPRINTK(2, "PM3RD_IndexControl: 0x%08x\n", - PM3_READ_REG(PM3RD_IndexControl)); - DPRINTK(2, "PM3ScreenBase: 0x%08x\n", PM3_READ_REG(PM3ScreenBase)); - DPRINTK(2, "PM3ScreenStride: 0x%08x\n", - PM3_READ_REG(PM3ScreenStride)); - DPRINTK(2, "PM3VClkCtl: 0x%08x\n", PM3_READ_REG(PM3VClkCtl)); - DPRINTK(2, "PM3VTotal: 0x%08x\n", PM3_READ_REG(PM3VTotal)); - DPRINTK(2, "PM3VbEnd: 0x%08x\n", PM3_READ_REG(PM3VbEnd)); - DPRINTK(2, "PM3VideoControl: 0x%08x\n", - PM3_READ_REG(PM3VideoControl)); - DPRINTK(2, "PM3VsEnd: 0x%08x\n", PM3_READ_REG(PM3VsEnd)); - DPRINTK(2, "PM3VsStart: 0x%08x\n", PM3_READ_REG(PM3VsStart)); - - DPRINTK(2, "PM3RD_ColorFormat: %ld\n", - PM3_READ_DAC_REG(PM3RD_ColorFormat)); - DPRINTK(2, "PM3RD_DACControl: %ld\n", - PM3_READ_DAC_REG(PM3RD_DACControl)); - DPRINTK(2, "PM3RD_DClk0FeedbackScale: %ld\n", - PM3_READ_DAC_REG(PM3RD_DClk0FeedbackScale)); - DPRINTK(2, "PM3RD_DClk0PostScale: %ld\n", - PM3_READ_DAC_REG(PM3RD_DClk0PostScale)); - DPRINTK(2, "PM3RD_DClk0PreScale: %ld\n", - PM3_READ_DAC_REG(PM3RD_DClk0PreScale)); - DPRINTK(2, "[not set] PM3RD_IndexControl: %ld\n", - PM3_READ_DAC_REG(PM3RD_IndexControl)); - DPRINTK(2, "PM3RD_MiscControl: %ld\n", - PM3_READ_DAC_REG(PM3RD_MiscControl)); - DPRINTK(2, "PM3RD_PixelSize: %ld\n", - PM3_READ_DAC_REG(PM3RD_PixelSize)); - DPRINTK(2, "PM3RD_SyncControl: %ld\n", - PM3_READ_DAC_REG(PM3RD_SyncControl)); -} - -#endif /* defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2) */ -static void pm3fb_show_cur_timing(struct pm3fb_info *l_fb_info) -{ - u16 subvendor, subdevice; - - if ((!pci_read_config_word - (l_fb_info->dev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor)) - && - (!pci_read_config_word - (l_fb_info->dev, PCI_SUBSYSTEM_ID, &subdevice))) { - /* well, nothing... */ - } else { - subvendor = subdevice = (u16)-1; - } - - printk(KERN_INFO "pm3fb: memory timings for board #%ld (subvendor: 0x%hx, subdevice: 0x%hx)\n", l_fb_info->board_num, subvendor, subdevice); - printk(KERN_INFO " PM3LocalMemCaps: 0x%08x\n", - PM3_READ_REG(PM3LocalMemCaps)); - printk(KERN_INFO " PM3LocalMemTimings: 0x%08x\n", - PM3_READ_REG(PM3LocalMemTimings)); - printk(KERN_INFO " PM3LocalMemControl: 0x%08x\n", - PM3_READ_REG(PM3LocalMemControl)); - printk(KERN_INFO " PM3LocalMemRefresh: 0x%08x\n", - PM3_READ_REG(PM3LocalMemRefresh)); - printk(KERN_INFO " PM3LocalMemPowerDown: 0x%08x\n", - PM3_READ_REG(PM3LocalMemPowerDown)); + DPRINTK("Unsupported depth %ld\n", depth); + return 0; } /* write the mode to registers */ -static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) +static void pm3fb_write_mode(struct fb_info *info) { + struct pm3_par *par = info->par; char tempsync = 0x00, tempmisc = 0x00; - DTRACE; - - PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xffffffff); - PM3_SLOW_WRITE_REG(PM3Aperture0, 0x00000000); - PM3_SLOW_WRITE_REG(PM3Aperture1, 0x00000000); - PM3_SLOW_WRITE_REG(PM3FIFODis, 0x00000007); - - PM3_SLOW_WRITE_REG(PM3HTotal, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->htotal - - 1)); - PM3_SLOW_WRITE_REG(PM3HsEnd, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->hsend)); - PM3_SLOW_WRITE_REG(PM3HsStart, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par-> + const u32 hsstart = info->var.right_margin; + const u32 hsend = hsstart + info->var.hsync_len; + const u32 hbend = hsend + info->var.left_margin; + const u32 xres = (info->var.xres + 31) & ~31; + const u32 htotal = xres + hbend; + const u32 vsstart = info->var.lower_margin; + const u32 vsend = vsstart + info->var.vsync_len; + const u32 vbend = vsend + info->var.upper_margin; + const u32 vtotal = info->var.yres + vbend; + const u32 width = (info->var.xres_virtual + 7) & ~7; + + PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff); + PM3_SLOW_WRITE_REG(par, PM3Aperture0, 0x00000000); + PM3_SLOW_WRITE_REG(par, PM3Aperture1, 0x00000000); + PM3_SLOW_WRITE_REG(par, PM3FIFODis, 0x00000007); + + PM3_SLOW_WRITE_REG(par, PM3HTotal, + pm3fb_shift_bpp(info->var.bits_per_pixel, + htotal - 1)); + PM3_SLOW_WRITE_REG(par, PM3HsEnd, + pm3fb_shift_bpp(info->var.bits_per_pixel, + hsend)); + PM3_SLOW_WRITE_REG(par, PM3HsStart, + pm3fb_shift_bpp(info->var.bits_per_pixel, hsstart)); - PM3_SLOW_WRITE_REG(PM3HbEnd, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->hbend)); - PM3_SLOW_WRITE_REG(PM3HgEnd, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->hbend)); - PM3_SLOW_WRITE_REG(PM3ScreenStride, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->stride)); - PM3_SLOW_WRITE_REG(PM3VTotal, l_fb_info->current_par->vtotal - 1); - PM3_SLOW_WRITE_REG(PM3VsEnd, l_fb_info->current_par->vsend - 1); - PM3_SLOW_WRITE_REG(PM3VsStart, - l_fb_info->current_par->vsstart - 1); - PM3_SLOW_WRITE_REG(PM3VbEnd, l_fb_info->current_par->vbend); - - switch (l_fb_info->current_par->depth) { + PM3_SLOW_WRITE_REG(par, PM3HbEnd, + pm3fb_shift_bpp(info->var.bits_per_pixel, + hbend)); + PM3_SLOW_WRITE_REG(par, PM3HgEnd, + pm3fb_shift_bpp(info->var.bits_per_pixel, + hbend)); + PM3_SLOW_WRITE_REG(par, PM3ScreenStride, + pm3fb_shift_bpp(info->var.bits_per_pixel, + width)); + PM3_SLOW_WRITE_REG(par, PM3VTotal, vtotal - 1); + PM3_SLOW_WRITE_REG(par, PM3VsEnd, vsend - 1); + PM3_SLOW_WRITE_REG(par, PM3VsStart, vsstart - 1); + PM3_SLOW_WRITE_REG(par, PM3VbEnd, vbend); + + switch (info->var.bits_per_pixel) { case 8: - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_8BIT); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_8BIT); break; @@ -1100,15 +247,15 @@ static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) case 15: case 16: #ifndef __BIG_ENDIAN - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT); #else - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT | PM3ByApertureMode_BYTESWAP_BADC); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT | PM3ByApertureMode_BYTESWAP_BADC); #endif /* ! __BIG_ENDIAN */ @@ -1116,23 +263,23 @@ static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) case 32: #ifndef __BIG_ENDIAN - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT); #else - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT | PM3ByApertureMode_BYTESWAP_DCBA); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT | PM3ByApertureMode_BYTESWAP_DCBA); #endif /* ! __BIG_ENDIAN */ break; default: - DPRINTK(1, "Unsupported depth %d\n", - l_fb_info->current_par->depth); + DPRINTK("Unsupported depth %d\n", + info->var.bits_per_pixel); break; } @@ -1143,95 +290,86 @@ static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) * sync options in PM3RD_SyncControl. --rmk */ { - unsigned int video = l_fb_info->current_par->video; + unsigned int video = par->video; video &= ~(PM3VideoControl_HSYNC_MASK | PM3VideoControl_VSYNC_MASK); video |= PM3VideoControl_HSYNC_ACTIVE_HIGH | PM3VideoControl_VSYNC_ACTIVE_HIGH; - PM3_SLOW_WRITE_REG(PM3VideoControl, video); + PM3_SLOW_WRITE_REG(par, PM3VideoControl, video); } - PM3_SLOW_WRITE_REG(PM3VClkCtl, - (PM3_READ_REG(PM3VClkCtl) & 0xFFFFFFFC)); - PM3_SLOW_WRITE_REG(PM3ScreenBase, l_fb_info->current_par->base); - PM3_SLOW_WRITE_REG(PM3ChipConfig, - (PM3_READ_REG(PM3ChipConfig) & 0xFFFFFFFD)); + PM3_SLOW_WRITE_REG(par, PM3VClkCtl, + (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC)); + PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base); + PM3_SLOW_WRITE_REG(par, PM3ChipConfig, + (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD)); { - unsigned char m; /* ClkPreScale */ - unsigned char n; /* ClkFeedBackScale */ - unsigned char p; /* ClkPostScale */ - (void)pm3fb_CalculateClock(l_fb_info, l_fb_info->current_par->pixclock, PM3_REF_CLOCK, &m, &n, &p); - - DPRINTK(2, - "Pixclock: %d, Pre: %d, Feedback: %d, Post: %d\n", - l_fb_info->current_par->pixclock, (int) m, (int) n, - (int) p); - - PM3_WRITE_DAC_REG(PM3RD_DClk0PreScale, m); - PM3_WRITE_DAC_REG(PM3RD_DClk0FeedbackScale, n); - PM3_WRITE_DAC_REG(PM3RD_DClk0PostScale, p); + unsigned char uninitialized_var(m); /* ClkPreScale */ + unsigned char uninitialized_var(n); /* ClkFeedBackScale */ + unsigned char uninitialized_var(p); /* ClkPostScale */ + unsigned long pixclock = PICOS2KHZ(info->var.pixclock); + + (void)pm3fb_calculate_clock(pixclock, &m, &n, &p); + + DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n", + pixclock, (int) m, (int) n, (int) p); + + PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m); + PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n); + PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p); } /* - PM3_WRITE_DAC_REG(PM3RD_IndexControl, 0x00); + PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00); */ /* - PM3_SLOW_WRITE_REG(PM3RD_IndexControl, 0x00); + PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00); */ - if ((l_fb_info->current_par->video & PM3VideoControl_HSYNC_MASK) == + if ((par->video & PM3VideoControl_HSYNC_MASK) == PM3VideoControl_HSYNC_ACTIVE_HIGH) tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH; - if ((l_fb_info->current_par->video & PM3VideoControl_VSYNC_MASK) == + if ((par->video & PM3VideoControl_VSYNC_MASK) == PM3VideoControl_VSYNC_ACTIVE_HIGH) tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH; - - PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync); - DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync); - - if (flatpanel[l_fb_info->board_num]) - { - PM3_WRITE_DAC_REG(PM3RD_DACControl, PM3RD_DACControl_BLANK_PEDESTAL_ENABLE); - PM3_WAIT(2); - PM3_WRITE_REG(PM3VSConfiguration, 0x06); - PM3_WRITE_REG(0x5a00, 1 << 14); /* black magic... */ - tempmisc = PM3RD_MiscControl_VSB_OUTPUT_ENABLE; - } - else - PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00); - switch (l_fb_info->current_par->depth) { + PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync); + DPRINTK("PM3RD_SyncControl: %d\n", tempsync); + + PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00); + + switch (info->var.bits_per_pixel) { case 8: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_8_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_CI8_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW); tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; case 12: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_16_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_4444_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; - break; + break; case 15: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_16_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_5551_FRONT_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; - break; + break; case 16: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_16_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_565_FRONT_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); @@ -1239,1936 +377,280 @@ static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; case 32: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_32_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_8888_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; } - PM3_WRITE_DAC_REG(PM3RD_MiscControl, tempmisc); - - PM3_SHOW_CUR_MODE; + PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc); } -static void pm3fb_read_mode(struct pm3fb_info *l_fb_info, - struct pm3fb_par *curpar) -{ - unsigned long pixsize1, pixsize2, clockused; - unsigned long pre, feedback, post; - - DTRACE; - - clockused = PM3_READ_REG(PM3VClkCtl); +/* + * hardware independent functions + */ +int pm3fb_init(void); +int pm3fb_setup(char*); - switch (clockused) { - case 3: - pre = PM3_READ_DAC_REG(PM3RD_DClk3PreScale); - feedback = PM3_READ_DAC_REG(PM3RD_DClk3FeedbackScale); - post = PM3_READ_DAC_REG(PM3RD_DClk3PostScale); +static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + u32 lpitch; - DPRINTK(2, - "DClk3 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n", - pre, feedback, post, PM3_SCALE_TO_CLOCK(pre, - feedback, - post)); + var->transp.offset = 0; + var->transp.length = 0; + switch(var->bits_per_pixel) { + case 8: + var->red.length = var->green.length = var->blue.length = 8; + var->red.offset = var->green.offset = var->blue.offset = 0; break; - case 2: - pre = PM3_READ_DAC_REG(PM3RD_DClk2PreScale); - feedback = PM3_READ_DAC_REG(PM3RD_DClk2FeedbackScale); - post = PM3_READ_DAC_REG(PM3RD_DClk2PostScale); - - DPRINTK(2, - "DClk2 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n", - pre, feedback, post, PM3_SCALE_TO_CLOCK(pre, - feedback, - post)); + case 12: + var->red.offset = 8; + var->red.length = 4; + var->green.offset = 4; + var->green.length = 4; + var->blue.offset = 0; + var->blue.length = 4; + var->transp.offset = 12; + var->transp.length = 4; + case 15: + var->red.offset = 10; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 15; + var->transp.length = 1; break; - case 1: - pre = PM3_READ_DAC_REG(PM3RD_DClk1PreScale); - feedback = PM3_READ_DAC_REG(PM3RD_DClk1FeedbackScale); - post = PM3_READ_DAC_REG(PM3RD_DClk1PostScale); - - DPRINTK(2, - "DClk1 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n", - pre, feedback, post, PM3_SCALE_TO_CLOCK(pre, - feedback, - post)); + case 16: + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; break; - case 0: - pre = PM3_READ_DAC_REG(PM3RD_DClk0PreScale); - feedback = PM3_READ_DAC_REG(PM3RD_DClk0FeedbackScale); - post = PM3_READ_DAC_REG(PM3RD_DClk0PostScale); - - DPRINTK(2, - "DClk0 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n", - pre, feedback, post, PM3_SCALE_TO_CLOCK(pre, - feedback, - post)); + case 32: + var->transp.offset = 24; + var->transp.length = 8; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 8; break; default: - pre = feedback = post = 0; - DPRINTK(1, "Unknowk D clock used : %ld\n", clockused); - break; - } - - curpar->pixclock = PM3_SCALE_TO_CLOCK(pre, feedback, post); - - pixsize1 = - PM3ByApertureMode_PIXELSIZE_MASK & - (PM3_READ_REG(PM3ByAperture1Mode)); - pixsize2 = - PM3ByApertureMode_PIXELSIZE_MASK & - (PM3_READ_REG(PM3ByAperture2Mode)); - - DASSERT((pixsize1 == pixsize2), - "pixsize the same in both aperture\n"); - - if (pixsize1 & PM3ByApertureMode_PIXELSIZE_32BIT) - curpar->depth = 32; - else if (pixsize1 & PM3ByApertureMode_PIXELSIZE_16BIT) - { - curpar->depth = 16; - } - else - curpar->depth = 8; - - /* not sure if I need to add one on the next ; it give better result with */ - curpar->htotal = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - 1 + PM3_READ_REG(PM3HTotal)); - curpar->hsend = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - PM3_READ_REG(PM3HsEnd)); - curpar->hsstart = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - PM3_READ_REG(PM3HsStart)); - curpar->hbend = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - PM3_READ_REG(PM3HbEnd)); - - curpar->stride = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - PM3_READ_REG(PM3ScreenStride)); - - curpar->vtotal = 1 + PM3_READ_REG(PM3VTotal); - curpar->vsend = 1 + PM3_READ_REG(PM3VsEnd); - curpar->vsstart = 1 + PM3_READ_REG(PM3VsStart); - curpar->vbend = PM3_READ_REG(PM3VbEnd); - - curpar->video = PM3_READ_REG(PM3VideoControl); - - curpar->base = PM3_READ_REG(PM3ScreenBase); - curpar->width = curpar->htotal - curpar->hbend; /* make virtual == displayed resolution */ - curpar->height = curpar->vtotal - curpar->vbend; - - DPRINTK(2, "Found : %d * %d, %d Khz, stride is %08x\n", - curpar->width, curpar->height, curpar->pixclock, - curpar->stride); -} - -static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info) -{ - unsigned long memsize = 0, tempBypass, i, temp1, temp2; - u16 subvendor, subdevice; - pm3fb_timing_result ptr; - - DTRACE; - - l_fb_info->fb_size = 64 * 1024 * 1024; /* pm3 aperture always 64 MB */ - pm3fb_mapIO(l_fb_info); /* temporary map IO */ - - DASSERT((l_fb_info->vIOBase != NULL), - "IO successfully mapped before mem detect\n"); - DASSERT((l_fb_info->v_fb != NULL), - "FB successfully mapped before mem detect\n"); - - /* card-specific stuff, *before* accessing *any* FB memory */ - if ((!pci_read_config_word - (l_fb_info->dev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor)) - && - (!pci_read_config_word - (l_fb_info->dev, PCI_SUBSYSTEM_ID, &subdevice))) { - i = 0; l_fb_info->board_type = 0; - while ((cardbase[i].cardname[0]) && !(l_fb_info->board_type)) { - if ((cardbase[i].subvendor == subvendor) && - (cardbase[i].subdevice == subdevice) && - (cardbase[i].func == PCI_FUNC(l_fb_info->dev->devfn))) { - DPRINTK(2, "Card #%ld is an %s\n", - l_fb_info->board_num, - cardbase[i].cardname); - if (cardbase[i].specific_setup) - cardbase[i].specific_setup(l_fb_info); - l_fb_info->board_type = i; - } - i++; - } - if (!l_fb_info->board_type) { - DPRINTK(1, "Card #%ld is an unknown 0x%04x / 0x%04x\n", - l_fb_info->board_num, subvendor, subdevice); - } - } else { - printk(KERN_ERR "pm3fb: Error: pci_read_config_word failed, board #%ld\n", - l_fb_info->board_num); - } - - if (printtimings) - pm3fb_show_cur_timing(l_fb_info); - - /* card-specific setup is done, we preserve the final - memory timing for future reference */ - if ((ptr = pm3fb_preserve_memory_timings(l_fb_info)) == pm3fb_timing_problem) { /* memory timings were wrong ! oops.... */ - return(0); - } - - tempBypass = PM3_READ_REG(PM3MemBypassWriteMask); - - DPRINTK(2, "PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass); - - PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xFFFFFFFF); - - /* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */ - for (i = 0; i < 32; i++) { - fb_writel(i * 0x00345678, - (l_fb_info->v_fb + (i * 1048576))); - mb(); - temp1 = fb_readl((l_fb_info->v_fb + (i * 1048576))); - - /* Let's check for wrapover, write will fail at 16MB boundary */ - if (temp1 == (i * 0x00345678)) - memsize = i; - else - break; - } - - DPRINTK(2, "First detect pass already got %ld MB\n", memsize + 1); - - if (memsize == i) { - for (i = 0; i < 32; i++) { - /* Clear first 32MB ; 0 is 0, no need to byteswap */ - writel(0x0000000, - (l_fb_info->v_fb + (i * 1048576))); - mb(); - } - - for (i = 32; i < 64; i++) { - fb_writel(i * 0x00345678, - (l_fb_info->v_fb + (i * 1048576))); - mb(); - temp1 = - fb_readl((l_fb_info->v_fb + (i * 1048576))); - temp2 = - fb_readl((l_fb_info->v_fb + - ((i - 32) * 1048576))); - if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) /* different value, different RAM... */ - memsize = i; - else - break; - } - } - - DPRINTK(2, "Second detect pass got %ld MB\n", memsize + 1); - - PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, tempBypass); - - pm3fb_unmapIO(l_fb_info); - memsize = 1048576 * (memsize + 1); - - DPRINTK(2, "Returning 0x%08lx bytes\n", memsize); - - if (forcesize[l_fb_info->board_num] && ((forcesize[l_fb_info->board_num] * 1048576) != memsize)) - { - printk(KERN_WARNING "pm3fb: mismatch between probed (%ld MB) and specified (%hd MB) memory size, using SPECIFIED !\n", memsize, forcesize[l_fb_info->board_num]); - memsize = 1048576 * forcesize[l_fb_info->board_num]; - } - - l_fb_info->fb_size = memsize; - - if (ptr == pm3fb_timing_retry) - { - printk(KERN_WARNING "pm3fb: retrying memory timings check"); - if (pm3fb_try_memory_timings(l_fb_info) == pm3fb_timing_problem) - return(0); - } - - return (memsize); -} - -static void pm3fb_clear_memory(struct pm3fb_info *l_fb_info, u32 cc) -{ - int i; - - DTRACE; - - for (i = 0; i < (l_fb_info->fb_size / sizeof(u32)) ; i++) /* clear entire FB memory to black */ - { - fb_writel(cc, (l_fb_info->v_fb + (i * sizeof(u32)))); + DPRINTK("depth not supported: %u\n", var->bits_per_pixel); + return -EINVAL; } -} - -static void pm3fb_clear_colormap(struct pm3fb_info *l_fb_info, unsigned char r, unsigned char g, unsigned char b) -{ - int i; - - DTRACE; - - for (i = 0; i < 256 ; i++) /* fill color map with white */ - pm3fb_set_color(l_fb_info, i, r, g, b); - -} - -/* common initialisation */ -static void pm3fb_common_init(struct pm3fb_info *l_fb_info) -{ - DTRACE; - - DPRINTK(2, "Initializing board #%ld @ %lx\n", l_fb_info->board_num, - (unsigned long) l_fb_info); - - strcpy(l_fb_info->gen.info.modename, permedia3_name); - disp[l_fb_info->board_num].scrollmode = 0; /* SCROLL_YNOMOVE; *//* 0 means "let fbcon choose" */ - l_fb_info->gen.parsize = sizeof(struct pm3fb_par); - l_fb_info->gen.info.changevar = NULL; - l_fb_info->gen.info.fbops = &pm3fb_ops; - l_fb_info->gen.info.disp = &(disp[l_fb_info->board_num]); - if (fontn[l_fb_info->board_num][0]) - strcpy(l_fb_info->gen.info.fontname, - fontn[l_fb_info->board_num]); - l_fb_info->gen.info.switch_con = &fbgen_switch; - l_fb_info->gen.info.updatevar = &fbgen_update_var; /* */ - l_fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT; - - pm3fb_mapIO(l_fb_info); - - pm3fb_clear_memory(l_fb_info, 0); - pm3fb_clear_colormap(l_fb_info, 0, 0, 0); - - (void) fbgen_get_var(&(disp[l_fb_info->board_num]).var, -1, - &l_fb_info->gen.info); + var->height = var->width = -1; - if (depth[l_fb_info->board_num]) /* override mode-defined depth */ - { - pm3fb_encode_depth(&(disp[l_fb_info->board_num]).var, depth[l_fb_info->board_num]); - (disp[l_fb_info->board_num]).var.bits_per_pixel = depth2bpp(depth[l_fb_info->board_num]); + if (var->xres != var->xres_virtual) { + DPRINTK("virtual x resolution != physical x resolution not supported\n"); + return -EINVAL; } - (void) fbgen_do_set_var(&(disp[l_fb_info->board_num]).var, 1, - &l_fb_info->gen); - - fbgen_set_disp(-1, &l_fb_info->gen); - - do_install_cmap(0, &l_fb_info->gen.info); - - if (register_framebuffer(&l_fb_info->gen.info) < 0) { - DPRINTK(1, "Couldn't register framebuffer\n"); - return; + if (var->yres > var->yres_virtual) { + DPRINTK("virtual y resolution < physical y resolution not possible\n"); + return -EINVAL; } - PM3_WRITE_DAC_REG(PM3RD_CursorMode, - PM3RD_CursorMode_CURSOR_DISABLE); - - PM3_SHOW_CUR_MODE; - - pm3fb_write_mode(l_fb_info); - - printk("fb%d: %s, using %uK of video memory (%s)\n", - l_fb_info->gen.info.node, - permedia3_name, (u32) (l_fb_info->fb_size >> 10), - cardbase[l_fb_info->board_type].cardname); -} - -/* **************************************************** */ -/* ***** accelerated permedia3-specific functions ***** */ -/* **************************************************** */ -#ifdef PM3FB_USE_ACCEL -static void pm3fb_wait_pm3(struct pm3fb_info *l_fb_info) -{ - DTRACE; - - PM3_SLOW_WRITE_REG(PM3FilterMode, PM3FilterModeSync); - PM3_SLOW_WRITE_REG(PM3Sync, 0); - mb(); - do { - while ((PM3_READ_REG(PM3OutFIFOWords)) == 0); - rmb(); - } while ((PM3_READ_REG(PM3OutputFifo)) != PM3Sync_Tag); -} - -static void pm3fb_init_engine(struct pm3fb_info *l_fb_info) -{ - PM3_SLOW_WRITE_REG(PM3FilterMode, PM3FilterModeSync); - PM3_SLOW_WRITE_REG(PM3StatisticMode, 0x0); - PM3_SLOW_WRITE_REG(PM3DeltaMode, 0x0); - PM3_SLOW_WRITE_REG(PM3RasterizerMode, 0x0); - PM3_SLOW_WRITE_REG(PM3ScissorMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LineStippleMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AreaStippleMode, 0x0); - PM3_SLOW_WRITE_REG(PM3GIDMode, 0x0); - PM3_SLOW_WRITE_REG(PM3DepthMode, 0x0); - PM3_SLOW_WRITE_REG(PM3StencilMode, 0x0); - PM3_SLOW_WRITE_REG(PM3StencilData, 0x0); - PM3_SLOW_WRITE_REG(PM3ColorDDAMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCoordMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureIndexMode0, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureIndexMode1, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureReadMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LUTMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureFilterMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureApplicationMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeColorMode1, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeAlphaMode1, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeColorMode0, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeAlphaMode0, 0x0); - PM3_SLOW_WRITE_REG(PM3FogMode, 0x0); - PM3_SLOW_WRITE_REG(PM3ChromaTestMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AlphaTestMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AntialiasMode, 0x0); - PM3_SLOW_WRITE_REG(PM3YUVMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AlphaBlendColorMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AlphaBlendAlphaMode, 0x0); - PM3_SLOW_WRITE_REG(PM3DitherMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LogicalOpMode, 0x0); - PM3_SLOW_WRITE_REG(PM3RouterMode, 0x0); - PM3_SLOW_WRITE_REG(PM3Window, 0x0); - - PM3_SLOW_WRITE_REG(PM3Config2D, 0x0); - - PM3_SLOW_WRITE_REG(PM3SpanColorMask, 0xffffffff); - - PM3_SLOW_WRITE_REG(PM3XBias, 0x0); - PM3_SLOW_WRITE_REG(PM3YBias, 0x0); - PM3_SLOW_WRITE_REG(PM3DeltaControl, 0x0); - - PM3_SLOW_WRITE_REG(PM3BitMaskPattern, 0xffffffff); - - PM3_SLOW_WRITE_REG(PM3FBDestReadEnables, - PM3FBDestReadEnables_E(0xff) | - PM3FBDestReadEnables_R(0xff) | - PM3FBDestReadEnables_ReferenceAlpha(0xff)); - PM3_SLOW_WRITE_REG(PM3FBDestReadBufferAddr0, 0x0); - PM3_SLOW_WRITE_REG(PM3FBDestReadBufferOffset0, 0x0); - PM3_SLOW_WRITE_REG(PM3FBDestReadBufferWidth0, - PM3FBDestReadBufferWidth_Width(l_fb_info-> - current_par-> - width)); - - PM3_SLOW_WRITE_REG(PM3FBDestReadMode, - PM3FBDestReadMode_ReadEnable | - PM3FBDestReadMode_Enable0); - PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferAddr, 0x0); - PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferOffset, 0x0); - PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferWidth, - PM3FBSourceReadBufferWidth_Width(l_fb_info-> - current_par-> - width)); - PM3_SLOW_WRITE_REG(PM3FBSourceReadMode, - PM3FBSourceReadMode_Blocking | - PM3FBSourceReadMode_ReadEnable); - - { - unsigned long rm = 1; - switch (l_fb_info->current_par->depth) { - case 8: - PM3_SLOW_WRITE_REG(PM3PixelSize, - PM3PixelSize_GLOBAL_8BIT); - break; - case 12: - case 15: - case 16: - PM3_SLOW_WRITE_REG(PM3PixelSize, - PM3PixelSize_GLOBAL_16BIT); - break; - case 32: - PM3_SLOW_WRITE_REG(PM3PixelSize, - PM3PixelSize_GLOBAL_32BIT); - break; - default: - DPRINTK(1, "Unsupported depth %d\n", - l_fb_info->current_par->depth); - break; - } - PM3_SLOW_WRITE_REG(PM3RasterizerMode, rm); + if (var->xoffset) { + DPRINTK("xoffset not supported\n"); + return -EINVAL; } - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xffffffff); - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff); - PM3_SLOW_WRITE_REG(PM3FBWriteMode, - PM3FBWriteMode_WriteEnable | - PM3FBWriteMode_OpaqueSpan | - PM3FBWriteMode_Enable0); - PM3_SLOW_WRITE_REG(PM3FBWriteBufferAddr0, 0x0); - PM3_SLOW_WRITE_REG(PM3FBWriteBufferOffset0, 0x0); - PM3_SLOW_WRITE_REG(PM3FBWriteBufferWidth0, - PM3FBWriteBufferWidth_Width(l_fb_info-> - current_par-> - width)); - - PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 0x0); - { - unsigned long sofb = (8UL * l_fb_info->fb_size) / - ((depth2bpp(l_fb_info->current_par->depth)) - * l_fb_info->current_par->width); /* size in lines of FB */ - if (sofb > 4095) - PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 4095); - else - PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, sofb); - - switch (l_fb_info->current_par->depth) { - case 8: - PM3_SLOW_WRITE_REG(PM3DitherMode, - (1 << 10) | (2 << 3)); - break; - case 12: - case 15: - case 16: - PM3_SLOW_WRITE_REG(PM3DitherMode, - (1 << 10) | (1 << 3)); - break; - case 32: - PM3_SLOW_WRITE_REG(PM3DitherMode, - (1 << 10) | (0 << 3)); - break; - default: - DPRINTK(1, "Unsupported depth %d\n", - l_fb_info->current_par->depth); - break; - } + if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + DPRINTK("interlace not supported\n"); + return -EINVAL; } - PM3_SLOW_WRITE_REG(PM3dXDom, 0x0); - PM3_SLOW_WRITE_REG(PM3dXSub, 0x0); - PM3_SLOW_WRITE_REG(PM3dY, (1 << 16)); - PM3_SLOW_WRITE_REG(PM3StartXDom, 0x0); - PM3_SLOW_WRITE_REG(PM3StartXSub, 0x0); - PM3_SLOW_WRITE_REG(PM3StartY, 0x0); - PM3_SLOW_WRITE_REG(PM3Count, 0x0); - -/* Disable LocalBuffer. better safe than sorry */ - PM3_SLOW_WRITE_REG(PM3LBDestReadMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LBDestReadEnables, 0x0); - PM3_SLOW_WRITE_REG(PM3LBSourceReadMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LBWriteMode, 0x0); - - pm3fb_wait_pm3(l_fb_info); -} + var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */ + lpitch = var->xres * ((var->bits_per_pixel + 7)>>3); -#ifdef FBCON_HAS_CFB32 -static void pm3fb_cfb32_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u32 c; - - DTRACE; - - sx = sx * fontwidth(p); - width = width * fontwidth(p); - sy = sy * fontheight(p); - height = height * fontheight(p); - c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - /* block fills in 32bpp are hard, but in low res (width <= 1600 :-) - we can use 16bpp operations, but not if NoWriteMask is on (SDRAM) */ - if ((l_fb_info->current_par->width > 1600) || - (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)) { - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(width)) | - (PM3Render2D_Height(height))); - } else { - PM3_WAIT(8); - - PM3_WRITE_REG(PM3FBBlockColor, c); - - PM3_WRITE_REG(PM3PixelSize, PM3PixelSize_GLOBAL_16BIT); - - PM3_WRITE_REG(PM3FBWriteBufferWidth0, - PM3FBWriteBufferWidth_Width(l_fb_info-> - current_par-> - width << 1)); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx << 1)) | - (PM3RectanglePosition_YOffset(sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - (PM3Render2D_Width(width << 1)) | - (PM3Render2D_Height(height))); - - PM3_WRITE_REG(PM3FBWriteBufferWidth0, - PM3FBWriteBufferWidth_Width(l_fb_info-> - current_par-> - width)); - - PM3_WRITE_REG(PM3PixelSize, PM3PixelSize_GLOBAL_32BIT); + if (var->xres < 200 || var->xres > 2048) { + DPRINTK("width not supported: %u\n", var->xres); + return -EINVAL; } - pm3fb_wait_pm3(l_fb_info); -} - -static void pm3fb_cfb32_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - int sx, sy; - u32 c; - - DTRACE; - - sx = conp->vc_cols * fontwidth(p); /* right margin */ - sy = conp->vc_rows * fontheight(p); /* bottom margin */ - c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - if (!bottom_only) { /* right margin top->bottom */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset - (p->var.xoffset + - sx)) | (PM3RectanglePosition_YOffset(p-> - var. - yoffset))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres - sx)) | - (PM3Render2D_Height(p->var.yres))); + if (var->yres < 200 || var->yres > 4095) { + DPRINTK("height not supported: %u\n", var->yres); + return -EINVAL; } - /* bottom margin left -> right */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(p->var.xoffset)) | - (PM3RectanglePosition_YOffset(p->var.yoffset + sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres)) | - (PM3Render2D_Height(p->var.yres - sy))); - - pm3fb_wait_pm3(l_fb_info); -} -#endif /* FBCON_HAS_CFB32 */ -#ifdef FBCON_HAS_CFB16 -static void pm3fb_cfb16_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u32 c; - - DTRACE; - - sx = sx * fontwidth(p); - width = width * fontwidth(p); - sy = sy * fontheight(p); - height = height * fontheight(p); - c = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)]; - c = c | (c << 16); - - PM3_WAIT(4); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3ForegroundColor, c); - else - PM3_WRITE_REG(PM3FBBlockColor, c); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(width)) | - (PM3Render2D_Height(height))); - else - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - (PM3Render2D_Width(width)) | - (PM3Render2D_Height(height))); - - pm3fb_wait_pm3(l_fb_info); -} - -static void pm3fb_cfb16_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - int sx, sy; - u32 c; - - DTRACE; - - sx = conp->vc_cols * fontwidth(p); /* right margin */ - sy = conp->vc_rows * fontheight(p); /* bottom margin */ - c = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)]; - c = c | (c << 16); - - if (!bottom_only) { /* right margin top->bottom */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3ForegroundColor, c); - else - PM3_WRITE_REG(PM3FBBlockColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset - (p->var.xoffset + - sx)) | (PM3RectanglePosition_YOffset(p-> - var. - yoffset))); - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres - sx)) | - (PM3Render2D_Height(p->var.yres))); - else - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - (PM3Render2D_Width(p->var.xres - sx)) | - (PM3Render2D_Height(p->var.yres))); + if (lpitch * var->yres_virtual > info->fix.smem_len) { + DPRINTK("no memory for screen (%ux%ux%u)\n", + var->xres, var->yres_virtual, var->bits_per_pixel); + return -EINVAL; } - - /* bottom margin left -> right */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3ForegroundColor, c); - else - PM3_WRITE_REG(PM3FBBlockColor, c); - - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(p->var.xoffset)) | - (PM3RectanglePosition_YOffset(p->var.yoffset + sy))); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres)) | - (PM3Render2D_Height(p->var.yres - sy))); - else - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - (PM3Render2D_Width(p->var.xres)) | - (PM3Render2D_Height(p->var.yres - sy))); - - pm3fb_wait_pm3(l_fb_info); -} -#endif /* FBCON_HAS_CFB16 */ -#ifdef FBCON_HAS_CFB8 -static void pm3fb_cfb8_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u32 c; - - DTRACE; - - sx = sx * fontwidth(p); - width = width * fontwidth(p); - sy = sy * fontheight(p); - height = height * fontheight(p); - - c = attr_bgcol_ec(p, conp); - c |= c << 8; - c |= c << 16; - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(width)) | - (PM3Render2D_Height(height))); - - pm3fb_wait_pm3(l_fb_info); -} - -static void pm3fb_cfb8_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - int sx, sy; - u32 c; - - DTRACE; - - sx = conp->vc_cols * fontwidth(p); /* right margin */ - sy = conp->vc_rows * fontheight(p); /* bottom margin */ - c = attr_bgcol_ec(p, conp); - c |= c << 8; - c |= c << 16; - - if (!bottom_only) { /* right margin top->bottom */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset - (p->var.xoffset + - sx)) | (PM3RectanglePosition_YOffset(p-> - var. - yoffset))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres - sx)) | - (PM3Render2D_Height(p->var.yres))); + if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) { + DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock)); + return -EINVAL; } - /* bottom margin left -> right */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); + var->accel_flags = 0; /* Can't mmap if this is on */ - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(p->var.xoffset)) | - (PM3RectanglePosition_YOffset(p->var.yoffset + sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres)) | - (PM3Render2D_Height(p->var.yres - sy))); - - pm3fb_wait_pm3(l_fb_info); -} -#endif /* FBCON_HAS_CFB8 */ -#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) -static void pm3fb_cfbX_bmove(struct display *p, - int sy, int sx, - int dy, int dx, int height, int width) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - int x_align, o_x, o_y; - - DTRACE; - - sx = sx * fontwidth(p); - dx = dx * fontwidth(p); - width = width * fontwidth(p); - sy = sy * fontheight(p); - dy = dy * fontheight(p); - height = height * fontheight(p); - - o_x = sx - dx; /*(sx > dx ) ? (sx - dx) : (dx - sx); */ - o_y = sy - dy; /*(sy > dy ) ? (sy - dy) : (dy - sy); */ - - x_align = (sx & 0x1f); - - PM3_WAIT(6); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UserScissorEnable | - PM3Config2D_ForegroundROPEnable | - PM3Config2D_Blocking | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ScissorMinXY, - ((dy & 0x0fff) << 16) | (dx & 0x0fff)); - PM3_WRITE_REG(PM3ScissorMaxXY, - (((dy + height) & 0x0fff) << 16) | - ((dx + width) & 0x0fff)); - - PM3_WRITE_REG(PM3FBSourceReadBufferOffset, - PM3FBSourceReadBufferOffset_XOffset(o_x) | - PM3FBSourceReadBufferOffset_YOffset(o_y)); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(dx - x_align)) | - (PM3RectanglePosition_YOffset(dy))); - - PM3_WRITE_REG(PM3Render2D, - ((sx > dx) ? PM3Render2D_XPositive : 0) | - ((sy > dy) ? PM3Render2D_YPositive : 0) | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - PM3Render2D_FBSourceReadEnable | - (PM3Render2D_Width(width + x_align)) | - (PM3Render2D_Height(height))); - - pm3fb_wait_pm3(l_fb_info); + DPRINTK("Checking graphics mode at %dx%d depth %d\n", + var->xres, var->yres, var->bits_per_pixel); + return 0; } -static void pm3fb_cfbX_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx) +static int pm3fb_set_par(struct fb_info *info) { - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0; - u32 fgx, bgx, ldat; - int sx, sy, i; - - DTRACE; - - if (l_fb_info->current_par->depth == 8) - fgx = attr_fgcol(p, c); - else if (depth2bpp(l_fb_info->current_par->depth) == 16) - fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, c)]; - else - fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, c)]; - - PM3_COLOR(fgx); - - if (l_fb_info->current_par->depth == 8) - bgx = attr_bgcol(p, c); - else if (depth2bpp(l_fb_info->current_par->depth) == 16) - bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, c)]; - else - bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, c)]; - - PM3_COLOR(bgx); - - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable | PM3Config2D_OpaqueSpan); - - PM3_WRITE_REG(PM3ForegroundColor, fgx); - PM3_WRITE_REG(PM3FillBackgroundColor, bgx); - - /* WARNING : address select X need to specify 8 bits for fontwidth <= 8 */ - /* and 16 bits for fontwidth <= 16 */ - /* same in _putcs, same for Y and fontheight */ - if (fontwidth(p) <= 8) - asx = 2; - else if (fontwidth(p) <= 16) - asx = 3; /* look OK */ - if (fontheight(p) <= 8) - asy = 2; - else if (fontheight(p) <= 16) - asy = 3; /* look OK */ - else if (fontheight(p) <= 32) - asy = 4; /* look OK */ - - sx = xx * fontwidth(p); - sy = yy * fontheight(p); - - if (fontwidth(p) <= 8) - o_x = (8 - (sx & 0x7)) & 0x7; - else if (fontwidth(p) <= 16) - o_x = (16 - (sx & 0xF)) & 0xF; - if (fontheight(p) <= 8) - o_y = (8 - (sy & 0x7)) & 0x7; - else if (fontheight(p) <= 16) - o_y = (16 - (sy & 0xF)) & 0xF; - else if (fontheight(p) <= 32) - o_y = (32 - (sy & 0x1F)) & 0x1F; - - PM3_WRITE_REG(PM3AreaStippleMode, (o_x << 7) | (o_y << 12) | /* x_offset, y_offset in pattern */ - (1 << 18) | /* BE */ - 1 | (asx << 1) | (asy << 4) | /* address select x/y */ - (1 << 20)); /* OpaqueSpan */ - - if (fontwidth(p) <= 8) { - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - } else { - cdat = - p->fontdata + - ((c & p->charmask) * (fontheight(p) << 1)); - } - - PM3_WAIT(2 + fontheight(p)); - - for (i = 0; i < fontheight(p); i++) { /* assume fontheight <= 32 */ - if (fontwidth(p) <= 8) { - ldat = *cdat++; - } else { /* assume fontwidth <= 16 ATM */ - - ldat = ((*cdat++) << 8); - ldat |= *cdat++; - } - PM3_WRITE_REG(AreaStipplePattern_indexed(i), ldat); - } + struct pm3_par *par = info->par; + const u32 xres = (info->var.xres + 31) & ~31; + const int depth = (info->var.bits_per_pixel + 7) & ~7; - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); + par->base = pm3fb_shift_bpp(info->var.bits_per_pixel, + (info->var.yoffset * xres) + + info->var.xoffset); + par->video = 0; - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_AreaStippleEnable | - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(fontwidth(p))) | - (PM3Render2D_Height(fontheight(p)))); - - pm3fb_wait_pm3(l_fb_info); -} - -static void pm3fb_cfbX_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, - int xx) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0; - u32 fgx, bgx, ldat; - int sx, sy, i, j; - u16 sc; - - DTRACE; - - sc = scr_readw(s); - if (l_fb_info->current_par->depth == 8) - fgx = attr_fgcol(p, sc); - else if (depth2bpp(l_fb_info->current_par->depth) == 16) - fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, sc)]; - else - fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, sc)]; - - PM3_COLOR(fgx); - - if (l_fb_info->current_par->depth == 8) - bgx = attr_bgcol(p, sc); - else if (depth2bpp(l_fb_info->current_par->depth) == 16) - bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, sc)]; + if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) + par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH; else - bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, sc)]; - - PM3_COLOR(bgx); - - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable | - PM3Config2D_OpaqueSpan); - - PM3_WRITE_REG(PM3ForegroundColor, fgx); - PM3_WRITE_REG(PM3FillBackgroundColor, bgx); - - /* WARNING : address select X need to specify 8 bits for fontwidth <= 8 */ - /* and 16 bits for fontwidth <= 16 */ - /* same in _putc, same for Y and fontheight */ - if (fontwidth(p) <= 8) - asx = 2; - else if (fontwidth(p) <= 16) - asx = 3; /* look OK */ - if (fontheight(p) <= 8) - asy = 2; - else if (fontheight(p) <= 16) - asy = 3; /* look OK */ - else if (fontheight(p) <= 32) - asy = 4; /* look OK */ - - sy = yy * fontheight(p); - - if (fontheight(p) <= 8) - o_y = (8 - (sy & 0x7)) & 0x7; - else if (fontheight(p) <= 16) - o_y = (16 - (sy & 0xF)) & 0xF; - else if (fontheight(p) <= 32) - o_y = (32 - (sy & 0x1F)) & 0x1F; - - for (j = 0; j < count; j++) { - sc = scr_readw(s + j); - if (fontwidth(p) <= 8) - cdat = p->fontdata + - (sc & p->charmask) * fontheight(p); - else - cdat = p->fontdata + - ((sc & p->charmask) * fontheight(p) << 1); - - sx = (xx + j) * fontwidth(p); - - if (fontwidth(p) <= 8) - o_x = (8 - (sx & 0x7)) & 0x7; - else if (fontwidth(p) <= 16) - o_x = (16 - (sx & 0xF)) & 0xF; - - PM3_WAIT(3 + fontheight(p)); - - PM3_WRITE_REG(PM3AreaStippleMode, (o_x << 7) | (o_y << 12) | /* x_offset, y_offset in pattern */ - (1 << 18) | /* BE */ - 1 | (asx << 1) | (asy << 4) | /* address select x/y */ - (1 << 20)); /* OpaqueSpan */ - - for (i = 0; i < fontheight(p); i++) { /* assume fontheight <= 32 */ - if (fontwidth(p) <= 8) { - ldat = *cdat++; - } else { /* assume fontwidth <= 16 ATM */ - ldat = ((*cdat++) << 8); - ldat |= *cdat++; - } - PM3_WRITE_REG(AreaStipplePattern_indexed(i), ldat); - } - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_AreaStippleEnable | - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(fontwidth(p))) | - (PM3Render2D_Height(fontheight(p)))); - } - pm3fb_wait_pm3(l_fb_info); -} - -static void pm3fb_cfbX_revc(struct display *p, int xx, int yy) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - - xx = xx * fontwidth(p); - yy = yy * fontheight(p); - - if (l_fb_info->current_par->depth == 8) - { - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0x0F0F0F0F); - else - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F); - } - - PM3_WAIT(3); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0xa)) | /* Oxa is GXinvert */ - PM3Config2D_FBDestReadEnable | - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(xx)) | - (PM3RectanglePosition_YOffset(yy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(fontwidth(p))) | - (PM3Render2D_Height(fontheight(p)))); - - pm3fb_wait_pm3(l_fb_info); - - if (l_fb_info->current_par->depth == 8) - { - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xFFFFFFFF); - else - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF); - } -} - -#endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */ -#endif /* PM3FB_USE_ACCEL */ -/* *********************************** */ -/* ***** pre-init board(s) setup ***** */ -/* *********************************** */ - -static void pm3fb_mode_setup(char *mode, unsigned long board_num) -{ - struct pm3fb_info *l_fb_info = &(fb_info[board_num]); - struct pm3fb_par *l_fb_par = &(current_par[board_num]); - unsigned long i = 0; - - current_par_valid[board_num] = 0; - - if (!strncmp(mode, "current", 7)) { - l_fb_info->use_current = 1; /* default w/ OpenFirmware */ - } else { - while ((mode_base[i].name[0]) - && (!current_par_valid[board_num])) { - if (! - (strncmp - (mode, mode_base[i].name, - strlen(mode_base[i].name)))) { - memcpy(l_fb_par, &(mode_base[i].user_mode), - sizeof(struct pm3fb_par)); - current_par_valid[board_num] = 1; - DPRINTK(2, "Mode set to %s\n", - mode_base[i].name); - } - i++; - } - DASSERT(current_par_valid[board_num], - "Valid mode on command line\n"); - } -} - -static void pm3fb_pciid_setup(char *pciid, unsigned long board_num) -{ - short l_bus = -1, l_slot = -1, l_func = -1; - char *next; - - if (pciid) { - l_bus = simple_strtoul(pciid, &next, 10); - if (next && (next[0] == ':')) { - pciid = next + 1; - l_slot = simple_strtoul(pciid, &next, 10); - if (next && (next[0] == ':')) { - pciid = next + 1; - l_func = - simple_strtoul(pciid, (char **) NULL, - 10); - } - } - } else - return; - - if ((l_bus >= 0) && (l_slot >= 0) && (l_func >= 0)) { - bus[board_num] = l_bus; - slot[board_num] = l_slot; - func[board_num] = l_func; - DPRINTK(2, "Board #%ld will be PciId: %hd:%hd:%hd\n", - board_num, l_bus, l_slot, l_func); - } else { - DPRINTK(1, "Invalid PciId: %hd:%hd:%hd for board #%ld\n", - l_bus, l_slot, l_func, board_num); - } -} - -static void pm3fb_font_setup(char *lf, unsigned long board_num) -{ - unsigned long lfs = strlen(lf); - - if (lfs > (PM3_FONTNAME_SIZE - 1)) { - DPRINTK(1, "Fontname %s too long\n", lf); - return; - } - strlcpy(fontn[board_num], lf, lfs + 1); -} - -static void pm3fb_bootdepth_setup(char *bds, unsigned long board_num) -{ - unsigned long bd = simple_strtoul(bds, (char **) NULL, 10); - - if (!(depth_supported(bd))) { - printk(KERN_WARNING "pm3fb: ignoring invalid depth %s for board #%ld\n", - bds, board_num); - return; - } - depth[board_num] = bd; -} - -static void pm3fb_forcesize_setup(char *bds, unsigned long board_num) -{ - unsigned long bd = simple_strtoul(bds, (char **) NULL, 10); - - if (bd > 64) { - printk(KERN_WARNING "pm3fb: ignoring invalid memory size %s for board #%ld\n", - bds, board_num); - return; - } - forcesize[board_num] = bd; -} - -static char *pm3fb_boardnum_setup(char *options, unsigned long *bn) -{ - char *next; - - if (!(isdigit(options[0]))) { - (*bn) = 0; - return (options); - } - - (*bn) = simple_strtoul(options, &next, 10); + par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW; - if (next && (next[0] == ':') && ((*bn) >= 0) - && ((*bn) <= PM3_MAX_BOARD)) { - DPRINTK(2, "Board_num seen as %ld\n", (*bn)); - return (next + 1); - } else { - (*bn) = 0; - DPRINTK(2, "Board_num default to %ld\n", (*bn)); - return (options); - } -} - -static void pm3fb_real_setup(char *options) -{ - char *next; - unsigned long i, bn; - struct pm3fb_info *l_fb_info; - - DTRACE; - - DPRINTK(2, "Options : %s\n", options); - - for (i = 0; i < PM3_MAX_BOARD; i++) { - l_fb_info = &(fb_info[i]); - memset(l_fb_info, 0, sizeof(struct pm3fb_info)); - l_fb_info->gen.fbhw = &pm3fb_switch; - l_fb_info->board_num = i; - current_par_valid[i] = 0; - slot[i] = -1; - func[i] = -1; - bus[i] = -1; - disable[i] = 0; - noaccel[i] = 0; - fontn[i][0] = '\0'; - depth[i] = 0; - l_fb_info->current_par = &(current_par[i]); - } - - /* eat up prefix pm3fb and whatever is used as separator i.e. :,= */ - if (!strncmp(options, "pm3fb", 5)) { - options += 5; - while (((*options) == ',') || ((*options) == ':') - || ((*options) == '=')) - options++; - } - - while (options) { - bn = 0; - if ((next = strchr(options, ','))) { - (*next) = '\0'; - next++; - } - - if (!strncmp(options, "mode:", 5)) { - options = pm3fb_boardnum_setup(options + 5, &bn); - DPRINTK(2, "Setting mode for board #%ld\n", bn); - pm3fb_mode_setup(options, bn); - } else if (!strncmp(options, "off:", 4)) { - options = pm3fb_boardnum_setup(options + 4, &bn); - DPRINTK(2, "Disabling board #%ld\n", bn); - disable[bn] = 1; - } else if (!strncmp(options, "off", 3)) { /* disable everything */ - for (i = 0; i < PM3_MAX_BOARD; i++) - disable[i] = 1; - } else if (!strncmp(options, "disable:", 8)) { - options = pm3fb_boardnum_setup(options + 8, &bn); - DPRINTK(2, "Disabling board #%ld\n", bn); - disable[bn] = 1; - } else if (!strncmp(options, "pciid:", 6)) { - options = pm3fb_boardnum_setup(options + 6, &bn); - DPRINTK(2, "Setting PciID for board #%ld\n", bn); - pm3fb_pciid_setup(options, bn); - } else if (!strncmp(options, "noaccel:", 8)) { - options = pm3fb_boardnum_setup(options + 8, &bn); - noaccel[bn] = 1; - } else if (!strncmp(options, "font:", 5)) { - options = pm3fb_boardnum_setup(options + 5, &bn); - pm3fb_font_setup(options, bn); - } else if (!strncmp(options, "depth:", 6)) { - options = pm3fb_boardnum_setup(options + 6, &bn); - pm3fb_bootdepth_setup(options, bn); - } else if (!strncmp(options, "printtimings", 12)) { - printtimings = 1; - } else if (!strncmp(options, "flatpanel:", 10)) { - options = pm3fb_boardnum_setup(options + 10, &bn); - flatpanel[bn] = 1; - } else if (!strncmp(options, "forcesize:", 10)) { - options = pm3fb_boardnum_setup(options + 10, &bn); - pm3fb_forcesize_setup(options, bn); - } - options = next; - } -} - -/* ********************************************** */ -/* ***** framebuffer API standard functions ***** */ -/* ********************************************** */ - -static int pm3fb_encode_fix(struct fb_fix_screeninfo *fix, - const void *par, struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - struct pm3fb_par *p = (struct pm3fb_par *) par; - - DTRACE; - - strcpy(fix->id, permedia3_name); - fix->smem_start = (unsigned long)l_fb_info->p_fb; - fix->smem_len = l_fb_info->fb_size; - fix->mmio_start = (unsigned long)l_fb_info->pIOBase; - fix->mmio_len = PM3_REGS_SIZE; -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - fix->accel = FB_ACCEL_3DLABS_PERMEDIA3; - else -#endif /* PM3FB_USE_ACCEL */ - fix->accel = FB_ACCEL_NONE; - fix->type = FB_TYPE_PACKED_PIXELS; - fix->visual = - (p->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - if (current_par_valid[l_fb_info->board_num]) - fix->line_length = - l_fb_info->current_par->width * - depth2ByPP(l_fb_info->current_par->depth); + if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) + par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH; else - fix->line_length = 0; - fix->xpanstep = 64 / depth2bpp(p->depth); - fix->ypanstep = 1; - fix->ywrapstep = 0; - return (0); -} - -static int pm3fb_decode_var(const struct fb_var_screeninfo *var, - void *par, struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - struct pm3fb_par *p = (struct pm3fb_par *) par; - struct pm3fb_par temp_p; - u32 xres; - - DTRACE; - - DASSERT((var != NULL), "fb_var_screeninfo* not NULL"); - DASSERT((p != NULL), "pm3fb_par* not NULL"); - DASSERT((l_fb_info != NULL), "pm3fb_info* not NULL"); + par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW; - memset(&temp_p, 0, sizeof(struct pm3fb_par)); - temp_p.width = (var->xres_virtual + 7) & ~7; - temp_p.height = var->yres_virtual; - - if (!(depth_supported(var->bits_per_pixel))) /* round unsupported up to a multiple of 8 */ - temp_p.depth = depth2bpp(var->bits_per_pixel); + if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) + par->video |= PM3VideoControl_LINE_DOUBLE_ON; else - temp_p.depth = var->bits_per_pixel; - - temp_p.depth = (temp_p.depth > 32) ? 32 : temp_p.depth; /* max 32 */ - temp_p.depth = (temp_p.depth == 24) ? 32 : temp_p.depth; /* 24 unsupported, round-up to 32 */ - - if ((temp_p.depth == 16) && (var->red.length == 5) && (var->green.length == 5) && (var->blue.length == 5)) - temp_p.depth = 15; /* RGBA 5551 is stored as depth 15 */ - - if ((temp_p.depth == 16) && (var->red.length == 4) && (var->green.length == 4) && (var->blue.length == 4)) - temp_p.depth = 12; /* RGBA 4444 is stored as depth 12 */ - - - DPRINTK(2, - "xres: %d, yres: %d, vxres: %d, vyres: %d ; xoffset:%d, yoffset: %d\n", - var->xres, var->yres, var->xres_virtual, var->yres_virtual, - var->xoffset, var->yoffset); - - xres = (var->xres + 31) & ~31; - if (temp_p.width < xres + var->xoffset) - temp_p.width = xres + var->xoffset; - if (temp_p.height < var->yres + var->yoffset) - temp_p.height = var->yres + var->yoffset; - - if (temp_p.width > 2048) { - DPRINTK(1, "virtual width not supported: %u\n", - temp_p.width); - return (-EINVAL); - } - if (var->yres < 200) { - DPRINTK(1, "height not supported: %u\n", (u32) var->yres); - return (-EINVAL); - } - if (temp_p.height < 200 || temp_p.height > 4095) { - DPRINTK(1, "virtual height not supported: %u\n", - temp_p.height); - return (-EINVAL); - } - if (!(depth_supported(temp_p.depth))) { - DPRINTK(1, "depth not supported: %u\n", temp_p.depth); - return (-EINVAL); - } - if ((temp_p.width * temp_p.height * depth2ByPP(temp_p.depth)) > - l_fb_info->fb_size) { - DPRINTK(1, "no memory for screen (%ux%ux%u)\n", - temp_p.width, temp_p.height, temp_p.depth); - return (-EINVAL); - } - - if ((!var->pixclock) || - (!var->right_margin) || - (!var->hsync_len) || - (!var->left_margin) || - (!var->lower_margin) || - (!var->vsync_len) || (!var->upper_margin) - ) { - unsigned long i = 0, done = 0; - printk(KERN_WARNING "pm3fb: refusing to use a likely wrong timing\n"); - - while ((mode_base[i].user_mode.width) && !done) { - if ((mode_base[i].user_mode.width == temp_p.width) - && (mode_base[i].user_mode.height == - temp_p.height)) { - printk(KERN_NOTICE "pm3fb: using close match %s\n", - mode_base[i].name); - temp_p = mode_base[i].user_mode; - done = 1; - } - i++; - } - if (!done) - return (-EINVAL); - } else { - temp_p.pixclock = PICOS2KHZ(var->pixclock); - if (temp_p.pixclock > PM3_MAX_PIXCLOCK) { - DPRINTK(1, "pixclock too high (%uKHz)\n", - temp_p.pixclock); - return (-EINVAL); - } - - temp_p.hsstart = var->right_margin; - temp_p.hsend = var->right_margin + var->hsync_len; - temp_p.hbend = - var->right_margin + var->hsync_len + var->left_margin; - temp_p.htotal = xres + temp_p.hbend; - - temp_p.vsstart = var->lower_margin; - temp_p.vsend = var->lower_margin + var->vsync_len; - temp_p.vbend = - var->lower_margin + var->vsync_len + var->upper_margin; - temp_p.vtotal = var->yres + temp_p.vbend; - - temp_p.stride = temp_p.width; - - DPRINTK(2, "Using %d * %d, %d Khz, stride is %08x\n", - temp_p.width, temp_p.height, temp_p.pixclock, - temp_p.stride); - - temp_p.base = - pm3fb_Shiftbpp(l_fb_info, temp_p.depth, - (var->yoffset * xres) + var->xoffset); + par->video |= PM3VideoControl_LINE_DOUBLE_OFF; - temp_p.video = 0; - - if (var->sync & FB_SYNC_HOR_HIGH_ACT) - temp_p.video |= PM3VideoControl_HSYNC_ACTIVE_HIGH; - else - temp_p.video |= PM3VideoControl_HSYNC_ACTIVE_LOW; - - if (var->sync & FB_SYNC_VERT_HIGH_ACT) - temp_p.video |= PM3VideoControl_VSYNC_ACTIVE_HIGH; - else - temp_p.video |= PM3VideoControl_VSYNC_ACTIVE_LOW; - - if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { - DPRINTK(1, "Interlaced mode not supported\n\n"); - return (-EINVAL); - } - - if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) - temp_p.video |= PM3VideoControl_LINE_DOUBLE_ON; - else - temp_p.video |= PM3VideoControl_LINE_DOUBLE_OFF; - - if (var->activate == FB_ACTIVATE_NOW) - temp_p.video |= PM3VideoControl_ENABLE; - else { - temp_p.video |= PM3VideoControl_DISABLE; - DPRINTK(2, "PM3Video disabled\n"); - } - - switch (temp_p.depth) { - case 8: - temp_p.video |= PM3VideoControl_PIXELSIZE_8BIT; - break; - case 12: - case 15: - case 16: - temp_p.video |= PM3VideoControl_PIXELSIZE_16BIT; - break; - case 32: - temp_p.video |= PM3VideoControl_PIXELSIZE_32BIT; - break; - default: - DPRINTK(1, "Unsupported depth\n"); - break; - } + if (info->var.activate == FB_ACTIVATE_NOW) + par->video |= PM3VideoControl_ENABLE; + else { + par->video |= PM3VideoControl_DISABLE; + DPRINTK("PM3Video disabled\n"); } - (*p) = temp_p; - -#ifdef PM3FB_USE_ACCEL - if (var->accel_flags & FB_ACCELF_TEXT) - noaccel[l_fb_info->board_num] = 0; - else - noaccel[l_fb_info->board_num] = 1; -#endif /* PM3FB_USE_ACCEL */ - - return (0); -} - -static void pm3fb_encode_depth(struct fb_var_screeninfo *var, long d) -{ - switch (d) { + switch (depth) { case 8: - var->red.length = var->green.length = var->blue.length = 8; - var->red.offset = var->green.offset = var->blue.offset = 0; - var->transp.offset = var->transp.length = 0; + par->video |= PM3VideoControl_PIXELSIZE_8BIT; break; - case 12: - var->red.offset = 8; - var->red.length = 4; - var->green.offset = 4; - var->green.length = 4; - var->blue.offset = 0; - var->blue.length = 4; - var->transp.offset = 12; - var->transp.length = 4; - break; - case 15: - var->red.offset = 10; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 5; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 15; - var->transp.length = 1; - break; - case 16: - var->red.offset = 11; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = var->transp.length = 0; + par->video |= PM3VideoControl_PIXELSIZE_16BIT; break; - case 32: - var->transp.offset = 24; - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; - var->red.length = var->green.length = - var->blue.length = var->transp.length = 8; + par->video |= PM3VideoControl_PIXELSIZE_32BIT; break; - default: - DPRINTK(1, "Unsupported depth %ld\n", d); + DPRINTK("Unsupported depth\n"); break; } -} - -static int pm3fb_encode_var(struct fb_var_screeninfo *var, - const void *par, struct fb_info_gen *info) -{ - struct pm3fb_par *p = (struct pm3fb_par *) par; - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - u32 base; - - DTRACE; - - DASSERT((var != NULL), "fb_var_screeninfo* not NULL"); - DASSERT((p != NULL), "pm3fb_par* not NULL"); - DASSERT((info != NULL), "fb_info_gen* not NULL"); - - memset(var, 0, sizeof(struct fb_var_screeninfo)); - -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - var->accel_flags |= FB_ACCELF_TEXT; -#endif /* PM3FB_USE_ACCEL */ - - var->xres_virtual = p->width; - var->yres_virtual = p->height; - var->xres = p->htotal - p->hbend; - var->yres = p->vtotal - p->vbend; - - DPRINTK(2, "xres = %d, yres : %d\n", var->xres, var->yres); - - var->right_margin = p->hsstart; - var->hsync_len = p->hsend - p->hsstart; - var->left_margin = p->hbend - p->hsend; - var->lower_margin = p->vsstart; - var->vsync_len = p->vsend - p->vsstart; - var->upper_margin = p->vbend - p->vsend; - var->bits_per_pixel = depth2bpp(p->depth); - - pm3fb_encode_depth(var, p->depth); - - base = pm3fb_Unshiftbpp(l_fb_info, p->depth, p->base); - - var->xoffset = base % var->xres; - var->yoffset = base / var->xres; - - var->height = var->width = -1; - - var->pixclock = KHZ2PICOS(p->pixclock); - - if ((p->video & PM3VideoControl_HSYNC_MASK) == - PM3VideoControl_HSYNC_ACTIVE_HIGH) - var->sync |= FB_SYNC_HOR_HIGH_ACT; - if ((p->video & PM3VideoControl_VSYNC_MASK) == - PM3VideoControl_VSYNC_ACTIVE_HIGH) - var->sync |= FB_SYNC_VERT_HIGH_ACT; - if (p->video & PM3VideoControl_LINE_DOUBLE_ON) - var->vmode = FB_VMODE_DOUBLE; - - return (0); -} - -static void pm3fb_get_par(void *par, struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - DTRACE; - - if (!current_par_valid[l_fb_info->board_num]) { - if (l_fb_info->use_current) - pm3fb_read_mode(l_fb_info, l_fb_info->current_par); - else - memcpy(l_fb_info->current_par, - &(mode_base[0].user_mode), - sizeof(struct pm3fb_par)); - current_par_valid[l_fb_info->board_num] = 1; - } - *((struct pm3fb_par *) par) = *(l_fb_info->current_par); -} - -static void pm3fb_set_par(const void *par, struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - DTRACE; - *(l_fb_info->current_par) = *((struct pm3fb_par *) par); - current_par_valid[l_fb_info->board_num] = 1; + info->fix.visual = + (depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + info->fix.line_length = ((info->var.xres_virtual + 7) & ~7) + * depth / 8; - pm3fb_write_mode(l_fb_info); - -#ifdef PM3FB_USE_ACCEL - pm3fb_init_engine(l_fb_info); -#endif /* PM3FB_USE_ACCEL */ -} - -static void pm3fb_set_color(struct pm3fb_info *l_fb_info, - unsigned char regno, unsigned char r, - unsigned char g, unsigned char b) -{ - DTRACE; - - PM3_SLOW_WRITE_REG(PM3RD_PaletteWriteAddress, regno); - PM3_SLOW_WRITE_REG(PM3RD_PaletteData, r); - PM3_SLOW_WRITE_REG(PM3RD_PaletteData, g); - PM3_SLOW_WRITE_REG(PM3RD_PaletteData, b); -} - -static int pm3fb_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - DTRACE; - - if (regno < 256) { - *red = - l_fb_info->palette[regno].red << 8 | l_fb_info-> - palette[regno].red; - *green = - l_fb_info->palette[regno].green << 8 | l_fb_info-> - palette[regno].green; - *blue = - l_fb_info->palette[regno].blue << 8 | l_fb_info-> - palette[regno].blue; - *transp = - l_fb_info->palette[regno].transp << 8 | l_fb_info-> - palette[regno].transp; - } - return (regno > 255); +/* pm3fb_clear_memory(info, 0);*/ + pm3fb_clear_colormap(par, 0, 0, 0); + PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, + PM3RD_CursorMode_CURSOR_DISABLE); + pm3fb_write_mode(info); + return 0; } static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - DTRACE; + struct pm3_par *par = info->par; + + if (regno >= 256) /* no. of hw registers */ + return -EINVAL; + + /* grayscale works only partially under directcolor */ + if (info->var.grayscale) { + /* grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; + } + + /* Directcolor: + * var->{color}.offset contains start of bitfield + * var->{color}.length contains length of bitfield + * {hardwarespecific} contains width of DAC + * pseudo_palette[X] is programmed to (X << red.offset) | + * (X << green.offset) | + * (X << blue.offset) + * RAMDAC[X] is programmed to (red, green, blue) + * color depth = SUM(var->{color}.length) + * + * Pseudocolor: + * var->{color}.offset is 0 + * var->{color}.length contains width of DAC or the number of unique + * colors available (color depth) + * pseudo_palette is not used + * RAMDAC[X] is programmed to (red, green, blue) + * color depth = var->{color}.length + */ - if (regno < 16) { - switch (l_fb_info->current_par->depth) { -#ifdef FBCON_HAS_CFB8 + /* + * This is the point where the color is converted to something that + * is acceptable by the hardware. + */ +#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) + red = CNVT_TOHW(red, info->var.red.length); + green = CNVT_TOHW(green, info->var.green.length); + blue = CNVT_TOHW(blue, info->var.blue.length); + transp = CNVT_TOHW(transp, info->var.transp.length); +#undef CNVT_TOHW + + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + u32 v; + + if (regno >= 16) + return -EINVAL; + + v = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + + switch (info->var.bits_per_pixel) { case 8: break; -#endif -#ifdef FBCON_HAS_CFB16 - case 12: - l_fb_info->cmap.cmap12[regno] = - (((u32) red & 0xf000) >> 4) | - (((u32) green & 0xf000) >> 8) | - (((u32) blue & 0xf000) >> 12); - break; - - case 15: - l_fb_info->cmap.cmap15[regno] = - (((u32) red & 0xf800) >> 1) | - (((u32) green & 0xf800) >> 6) | - (((u32) blue & 0xf800) >> 11); - break; - case 16: - l_fb_info->cmap.cmap16[regno] = - ((u32) red & 0xf800) | - (((u32) green & 0xfc00) >> 5) | - (((u32) blue & 0xf800) >> 11); - break; -#endif -#ifdef FBCON_HAS_CFB32 + case 24: case 32: - l_fb_info->cmap.cmap32[regno] = - (((u32) transp & 0xff00) << 16) | - (((u32) red & 0xff00) << 8) | - (((u32) green & 0xff00)) | - (((u32) blue & 0xff00) >> 8); - break; -#endif - default: - DPRINTK(1, "bad depth %u\n", - l_fb_info->current_par->depth); + ((u32*)(info->pseudo_palette))[regno] = v; break; } + return 0; } - if (regno < 256) { - l_fb_info->palette[regno].red = red >> 8; - l_fb_info->palette[regno].green = green >> 8; - l_fb_info->palette[regno].blue = blue >> 8; - l_fb_info->palette[regno].transp = transp >> 8; - if (l_fb_info->current_par->depth == 8) - pm3fb_set_color(l_fb_info, regno, red >> 8, - green >> 8, blue >> 8); - } - return (regno > 255); + else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) + pm3fb_set_color(par, regno, red, green, blue); + + return 0; } -static int pm3fb_blank(int blank_mode, struct fb_info_gen *info) +static int pm3fb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) { - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - u32 video; - - DTRACE; + struct pm3_par *par = info->par; + const u32 xres = (var->xres + 31) & ~31; - if (!current_par_valid[l_fb_info->board_num]) - return (1); + par->base = pm3fb_shift_bpp(var->bits_per_pixel, + (var->yoffset * xres) + + var->xoffset); + PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base); + return 0; +} - video = l_fb_info->current_par->video; +static int pm3fb_blank(int blank_mode, struct fb_info *info) +{ + struct pm3_par *par = info->par; + u32 video = par->video; /* * Oxygen VX1 - it appears that setting PM3VideoControl and @@ -3181,454 +663,345 @@ static int pm3fb_blank(int blank_mode, struct fb_info_gen *info) video |= PM3VideoControl_HSYNC_ACTIVE_HIGH | PM3VideoControl_VSYNC_ACTIVE_HIGH; - if (blank_mode > 0) { - switch (blank_mode - 1) { - - case VESA_NO_BLANKING: /* FIXME */ - video = video & ~(PM3VideoControl_ENABLE); - break; - - case VESA_HSYNC_SUSPEND: - video = video & ~(PM3VideoControl_HSYNC_MASK | - PM3VideoControl_BLANK_ACTIVE_LOW); - break; - case VESA_VSYNC_SUSPEND: - video = video & ~(PM3VideoControl_VSYNC_MASK | - PM3VideoControl_BLANK_ACTIVE_LOW); - break; - case VESA_POWERDOWN: - video = video & ~(PM3VideoControl_HSYNC_MASK | - PM3VideoControl_VSYNC_MASK | - PM3VideoControl_BLANK_ACTIVE_LOW); - break; - default: - DPRINTK(1, "Unsupported blanking %d\n", - blank_mode); - return (1); - break; - } - } - - PM3_SLOW_WRITE_REG(PM3VideoControl, video); - - return (0); -} - -static void pm3fb_set_disp(const void *par, struct display *disp, - struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - struct pm3fb_par *p = (struct pm3fb_par *) par; - u32 flags; - - DTRACE; - - local_irq_save(flags); - info->info.screen_base = l_fb_info->v_fb; - switch (p->depth) { -#ifdef FBCON_HAS_CFB8 - case 8: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb8; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb8; + switch (blank_mode) { + case FB_BLANK_UNBLANK: + video = video | PM3VideoControl_ENABLE; break; -#endif -#ifdef FBCON_HAS_CFB16 - case 12: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb16; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = l_fb_info->cmap.cmap12; + case FB_BLANK_NORMAL: /* FIXME */ + video = video & ~(PM3VideoControl_ENABLE); break; - case 15: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb16; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = l_fb_info->cmap.cmap15; + case FB_BLANK_HSYNC_SUSPEND: + video = video & ~(PM3VideoControl_HSYNC_MASK | + PM3VideoControl_BLANK_ACTIVE_LOW); break; - case 16: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb16; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = l_fb_info->cmap.cmap16; + case FB_BLANK_VSYNC_SUSPEND: + video = video & ~(PM3VideoControl_VSYNC_MASK | + PM3VideoControl_BLANK_ACTIVE_LOW); break; -#endif -#ifdef FBCON_HAS_CFB32 - case 32: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb32; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb32; - disp->dispsw_data = l_fb_info->cmap.cmap32; + case FB_BLANK_POWERDOWN: + video = video & ~(PM3VideoControl_HSYNC_MASK | + PM3VideoControl_VSYNC_MASK | + PM3VideoControl_BLANK_ACTIVE_LOW); break; -#endif /* FBCON_HAS_CFB32 */ default: - disp->dispsw = &fbcon_dummy; - DPRINTK(1, "Invalid depth, using fbcon_dummy\n"); - break; + DPRINTK("Unsupported blanking %d\n", blank_mode); + return 1; } - local_irq_restore(flags); + + PM3_SLOW_WRITE_REG(par,PM3VideoControl, video); + + return 0; } -/* */ -static void pm3fb_detect(void) -{ - struct pci_dev *dev_array[PM3_MAX_BOARD]; - struct pci_dev *dev = NULL; - struct pm3fb_info *l_fb_info = &(fb_info[0]); - unsigned long i, j, done; + /* + * Frame buffer operations + */ - DTRACE; +static struct fb_ops pm3fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = pm3fb_check_var, + .fb_set_par = pm3fb_set_par, + .fb_setcolreg = pm3fb_setcolreg, + .fb_pan_display = pm3fb_pan_display, + .fb_fillrect = cfb_fillrect, /* Needed !!! */ + .fb_copyarea = cfb_copyarea, /* Needed !!! */ + .fb_imageblit = cfb_imageblit, /* Needed !!! */ + .fb_blank = pm3fb_blank, +}; - for (i = 0; i < PM3_MAX_BOARD; i++) { - dev_array[i] = NULL; - fb_info[i].dev = NULL; - } +/* ------------------------------------------------------------------------- */ - dev = pci_get_device(PCI_VENDOR_ID_3DLABS, - PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev); + /* + * Initialization + */ - for (i = 0; ((i < PM3_MAX_BOARD) && dev); i++) { - dev_array[i] = dev; - dev = pci_get_device(PCI_VENDOR_ID_3DLABS, - PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev); - } +/* mmio register are already mapped when this function is called */ +/* the pm3fb_fix.smem_start is also set */ +static unsigned long pm3fb_size_memory(struct pm3_par *par) +{ + unsigned long memsize = 0, tempBypass, i, temp1, temp2; + unsigned char __iomem *screen_mem; - if (dev) { /* more than PM3_MAX_BOARD */ - printk(KERN_WARNING "pm3fb: Warning: more than %d boards found\n", - PM3_MAX_BOARD); + pm3fb_fix.smem_len = 64 * 1024 * 1024; /* request full aperture size */ + /* Linear frame buffer - request region and map it. */ + if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len, + "pm3fb smem")) { + printk(KERN_WARNING "pm3fb: Can't reserve smem.\n"); + return 0; } - - if (!dev_array[0]) { /* not a single board, abort */ - return; + screen_mem = + ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + if (!screen_mem) { + printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n"); + release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + return 0; } - /* allocate user-defined boards */ - for (i = 0; i < PM3_MAX_BOARD; i++) { - if ((bus[i] >= 0) && (slot[i] >= 0) && (func[i] >= 0)) { - for (j = 0; j < PM3_MAX_BOARD; j++) { - if ((dev_array[j] != NULL) && - (dev_array[j]->bus->number == bus[i]) - && (PCI_SLOT(dev_array[j]->devfn) == - slot[i]) - && (PCI_FUNC(dev_array[j]->devfn) == - func[i])) { - fb_info[i].dev = dev_array[j]; - dev_array[j] = NULL; - } - } - } + /* TODO: card-specific stuff, *before* accessing *any* FB memory */ + /* For Appian Jeronimo 2000 board second head */ + + tempBypass = PM3_READ_REG(par, PM3MemBypassWriteMask); + + DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass); + + PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF); + + /* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */ + for (i = 0; i < 32; i++) { + fb_writel(i * 0x00345678, + (screen_mem + (i * 1048576))); + mb(); + temp1 = fb_readl((screen_mem + (i * 1048576))); + + /* Let's check for wrapover, write will fail at 16MB boundary */ + if (temp1 == (i * 0x00345678)) + memsize = i; + else + break; } - /* allocate remaining boards */ - for (i = 0; i < PM3_MAX_BOARD; i++) { - if (fb_info[i].dev == NULL) { - done = 0; - for (j = 0; ((j < PM3_MAX_BOARD) && (!done)); j++) { - if (dev_array[j] != NULL) { - fb_info[i].dev = dev_array[j]; - dev_array[j] = NULL; - done = 1; - } - } + + DPRINTK("First detect pass already got %ld MB\n", memsize + 1); + + if (memsize + 1 == i) { + for (i = 0; i < 32; i++) { + /* Clear first 32MB ; 0 is 0, no need to byteswap */ + writel(0x0000000, + (screen_mem + (i * 1048576))); + mb(); } - } - /* at that point, all PCI Permedia3 are detected and allocated */ - /* now, initialize... or not */ - for (i = 0; i < PM3_MAX_BOARD; i++) { - l_fb_info = &(fb_info[i]); - if (l_fb_info->dev && !disable[i]) { /* PCI device was found and not disabled by user */ - DPRINTK(2, - "found @%lx Vendor %lx Device %lx ; base @ : %lx - %lx - %lx - %lx - %lx - %lx, irq %ld\n", - (unsigned long) l_fb_info->dev, - (unsigned long) l_fb_info->dev->vendor, - (unsigned long) l_fb_info->dev->device, - (unsigned long) - pci_resource_start(l_fb_info->dev, 0), - (unsigned long) - pci_resource_start(l_fb_info->dev, 1), - (unsigned long) - pci_resource_start(l_fb_info->dev, 2), - (unsigned long) - pci_resource_start(l_fb_info->dev, 3), - (unsigned long) - pci_resource_start(l_fb_info->dev, 4), - (unsigned long) - pci_resource_start(l_fb_info->dev, 5), - (unsigned long) l_fb_info->dev->irq); - - l_fb_info->pIOBase = - (unsigned char *) - pci_resource_start(l_fb_info->dev, 0); -#ifdef __BIG_ENDIAN - l_fb_info->pIOBase += PM3_REGS_SIZE; -#endif - l_fb_info->vIOBase = (unsigned char *) -1; - l_fb_info->p_fb = - (unsigned char *) - pci_resource_start(l_fb_info->dev, 1); - l_fb_info->v_fb = (unsigned char *) -1; - - if (!request_mem_region - ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */ - "pm3fb")) { - printk - (KERN_ERR "pm3fb: Error: couldn't request framebuffer memory, board #%ld\n", - l_fb_info->board_num); - continue; - } - if (!request_mem_region - ((unsigned long)l_fb_info->pIOBase, PM3_REGS_SIZE, - "pm3fb I/O regs")) { - printk - (KERN_ERR "pm3fb: Error: couldn't request IObase memory, board #%ld\n", - l_fb_info->board_num); - continue; - } - if (forcesize[l_fb_info->board_num]) - l_fb_info->fb_size = forcesize[l_fb_info->board_num]; - - l_fb_info->fb_size = - pm3fb_size_memory(l_fb_info); - if (l_fb_info->fb_size) { - (void) pci_enable_device(l_fb_info->dev); - pm3fb_common_init(l_fb_info); - } else - printk(KERN_ERR "pm3fb: memory problem, not enabling board #%ld\n", l_fb_info->board_num); + for (i = 32; i < 64; i++) { + fb_writel(i * 0x00345678, + (screen_mem + (i * 1048576))); + mb(); + temp1 = + fb_readl((screen_mem + (i * 1048576))); + temp2 = + fb_readl((screen_mem + ((i - 32) * 1048576))); + /* different value, different RAM... */ + if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) + memsize = i; + else + break; } } -} + DPRINTK("Second detect pass got %ld MB\n", memsize + 1); -static int pm3fb_pan_display(const struct fb_var_screeninfo *var, - struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; + PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass); - DTRACE; + iounmap(screen_mem); + release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + memsize = 1048576 * (memsize + 1); - if (!current_par_valid[l_fb_info->board_num]) - return -EINVAL; + DPRINTK("Returning 0x%08lx bytes\n", memsize); - l_fb_info->current_par->base = /* in 128 bits chunk - i.e. AFTER Shiftbpp */ - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - (var->yoffset * l_fb_info->current_par->width) + - var->xoffset); - PM3_SLOW_WRITE_REG(PM3ScreenBase, l_fb_info->current_par->base); - return 0; + return memsize; } -static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) +static int __devinit pm3fb_probe(struct pci_dev *dev, + const struct pci_device_id *ent) { - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - u32 cm, i; -#ifdef PM3FB_MASTER_DEBUG - char cc[3]; -#endif /* PM3FB_MASTER_DEBUG */ + struct fb_info *info; + struct pm3_par *par; + struct device* device = &dev->dev; /* for pci drivers */ + int err, retval = -ENXIO; - switch(cmd) - { -#ifdef PM3FB_MASTER_DEBUG - case PM3FBIO_CLEARMEMORY: - if (copy_from_user(&cm, (void *)arg, sizeof(u32))) - return(-EFAULT); - pm3fb_clear_memory(l_fb_info, cm); - return(0); - break; + err = pci_enable_device(dev); + if (err) { + printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err); + return err; + } + /* + * Dynamically allocate info and par + */ + info = framebuffer_alloc(sizeof(struct pm3_par), device); - case PM3FBIO_CLEARCMAP: - if (copy_from_user(cc, (void*)arg, 3 * sizeof(char))) - return(-EFAULT); - pm3fb_clear_colormap(l_fb_info, cc[0], cc[1], cc[2]); - return(0); - break; -#endif /* PM3FB_MASTER_DEBUG */ - - case PM3FBIO_RESETCHIP: - cm = 1; - PM3_SLOW_WRITE_REG(PM3ResetStatus, 1); - for (i = 0 ; (i < 10000) && cm ; i++) - { - PM3_DELAY(10); - cm = PM3_READ_REG(PM3ResetStatus); - } - if (cm) - { - printk(KERN_ERR "pm3fb: chip reset failed with status 0x%x\n", cm); - return(-EIO); - } - /* first thing first, reload memory timings */ - pm3fb_write_memory_timings(l_fb_info); -#ifdef PM3FB_USE_ACCEL - pm3fb_init_engine(l_fb_info); -#endif /* PM3FB_USE_ACCEL */ - pm3fb_write_mode(l_fb_info); - return(0); - break; + if (!info) + return -ENOMEM; + par = info->par; - default: - DPRINTK(2, "unknown ioctl: %d (%x)\n", cmd, cmd); - return(-EINVAL); + /* + * Here we set the screen_base to the virtual memory address + * for the framebuffer. + */ + pm3fb_fix.mmio_start = pci_resource_start(dev, 0); + pm3fb_fix.mmio_len = PM3_REGS_SIZE; + + /* Registers - request region and map it. */ + if (!request_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len, + "pm3fb regbase")) { + printk(KERN_WARNING "pm3fb: Can't reserve regbase.\n"); + goto err_exit_neither; + } + par->v_regs = + ioremap_nocache(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); + if (!par->v_regs) { + printk(KERN_WARNING "pm3fb: Can't remap %s register area.\n", + pm3fb_fix.id); + release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); + goto err_exit_neither; + } + +#if defined(__BIG_ENDIAN) + pm3fb_fix.mmio_start += PM3_REGS_SIZE; + DPRINTK("Adjusting register base for big-endian.\n"); +#endif + /* Linear frame buffer - request region and map it. */ + pm3fb_fix.smem_start = pci_resource_start(dev, 1); + pm3fb_fix.smem_len = pm3fb_size_memory(par); + if (!pm3fb_fix.smem_len) + { + printk(KERN_WARNING "pm3fb: Can't find memory on board.\n"); + goto err_exit_mmio; } -} + if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len, + "pm3fb smem")) { + printk(KERN_WARNING "pm3fb: Can't reserve smem.\n"); + goto err_exit_mmio; + } + info->screen_base = + ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + if (!info->screen_base) { + printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n"); + release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + goto err_exit_mmio; + } + info->screen_size = pm3fb_fix.smem_len; -/* ****************************************** */ -/* ***** standard FB API init functions ***** */ -/* ****************************************** */ + info->fbops = &pm3fb_ops; -int __init pm3fb_setup(char *options) -{ - long opsi = strlen(options); + par->video = PM3_READ_REG(par, PM3VideoControl); - DTRACE; + info->fix = pm3fb_fix; + info->pseudo_palette = par->palette; + info->flags = FBINFO_DEFAULT;/* | FBINFO_HWACCEL_YPAN;*/ - memcpy(g_options, options, - ((opsi + 1) > - PM3_OPTIONS_SIZE) ? PM3_OPTIONS_SIZE : (opsi + 1)); - g_options[PM3_OPTIONS_SIZE - 1] = 0; + /* + * This should give a reasonable default video mode. The following is + * done when we can set a video mode. + */ + if (!mode_option) + mode_option = "640x480@60"; + + retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); + + if (!retval || retval == 4) { + retval = -EINVAL; + goto err_exit_both; + } + + /* This has to been done !!! */ + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + retval = -ENOMEM; + goto err_exit_both; + } - return (0); + /* + * For drivers that can... + */ + pm3fb_check_var(&info->var, info); + + if (register_framebuffer(info) < 0) { + retval = -EINVAL; + goto err_exit_all; + } + printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, + info->fix.id); + pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */ + return 0; + + err_exit_all: + fb_dealloc_cmap(&info->cmap); + err_exit_both: + iounmap(info->screen_base); + release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + err_exit_mmio: + iounmap(par->v_regs); + release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); + err_exit_neither: + framebuffer_release(info); + return retval; } -int __init pm3fb_init(void) + /* + * Cleanup + */ +static void __devexit pm3fb_remove(struct pci_dev *dev) { - DTRACE; + struct fb_info *info = pci_get_drvdata(dev); - DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $"); + if (info) { + struct fb_fix_screeninfo *fix = &info->fix; + struct pm3_par *par = info->par; - pm3fb_real_setup(g_options); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - pm3fb_detect(); + iounmap(info->screen_base); + release_mem_region(fix->smem_start, fix->smem_len); + iounmap(par->v_regs); + release_mem_region(fix->mmio_start, fix->mmio_len); - if (!fb_info[0].dev) { /* not even one board ??? */ - DPRINTK(1, "No PCI Permedia3 board detected\n"); + pci_set_drvdata(dev, NULL); + framebuffer_release(info); } - return (0); } -/* ************************* */ -/* **** Module support ***** */ -/* ************************* */ - -#ifdef MODULE -MODULE_AUTHOR("Romain Dolbeau"); -MODULE_DESCRIPTION("Permedia3 framebuffer device driver"); -static char *mode[PM3_MAX_BOARD]; -module_param_array(mode, charp, NULL, 0); -MODULE_PARM_DESC(mode,"video mode"); -module_param_array(disable, short, NULL, 0); -MODULE_PARM_DESC(disable,"disable board"); -static short off[PM3_MAX_BOARD]; -module_param_array(off, short, NULL, 0); -MODULE_PARM_DESC(off,"disable board"); -static char *pciid[PM3_MAX_BOARD]; -module_param_array(pciid, charp, NULL, 0); -MODULE_PARM_DESC(pciid,"board PCI Id"); -module_param_array(noaccel, short, NULL, 0); -MODULE_PARM_DESC(noaccel,"disable accel"); -static char *font[PM3_MAX_BOARD]; -module_param_array(font, charp, NULL, 0); -MODULE_PARM_DESC(font,"choose font"); -module_param(depth, short, NULL, 0); -MODULE_PARM_DESC(depth,"boot-time depth"); -module_param(printtimings, short, NULL, 0); -MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)"); -module_param(forcesize, short, NULL, 0); -MODULE_PARM_DESC(forcesize, "force specified memory size"); -/* -MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards") -MODULE_GENERIC_TABLE(gtype,name) -MODULE_DEVICE_TABLE(type,name) -*/ +static struct pci_device_id pm3fb_id_table[] = { + { PCI_VENDOR_ID_3DLABS, 0x0a, + PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, + 0xff0000, 0 }, + { 0, } +}; -void pm3fb_build_options(void) -{ - int i; - char ts[128]; +/* For PCI drivers */ +static struct pci_driver pm3fb_driver = { + .name = "pm3fb", + .id_table = pm3fb_id_table, + .probe = pm3fb_probe, + .remove = __devexit_p(pm3fb_remove), +}; - strcpy(g_options, "pm3fb"); - for (i = 0; i < PM3_MAX_BOARD ; i++) - { - if (mode[i]) - { - sprintf(ts, ",mode:%d:%s", i, mode[i]); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (disable[i] || off[i]) - { - sprintf(ts, ",disable:%d:", i); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (pciid[i]) - { - sprintf(ts, ",pciid:%d:%s", i, pciid[i]); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (noaccel[i]) - { - sprintf(ts, ",noaccel:%d:", i); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (font[i]) - { - sprintf(ts, ",font:%d:%s", i, font[i]); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (depth[i]) - { - sprintf(ts, ",depth:%d:%d", i, depth[i]); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - } - g_options[PM3_OPTIONS_SIZE - 1] = '\0'; - DPRINTK(1, "pm3fb use options: %s\n", g_options); -} +MODULE_DEVICE_TABLE(pci, pm3fb_id_table); -int init_module(void) +int __init pm3fb_init(void) { - DTRACE; + /* + * For kernel boot options (in 'video=pm3fb:<options>' format) + */ +#ifndef MODULE + char *option = NULL; - pm3fb_build_options(); + if (fb_get_options("pm3fb", &option)) + return -ENODEV; + pm3fb_setup(option); +#endif - pm3fb_init(); + return pci_register_driver(&pm3fb_driver); +} - return 0; +static void __exit pm3fb_exit(void) +{ + pci_unregister_driver(&pm3fb_driver); } -void cleanup_module(void) +#ifndef MODULE + /* + * Setup + */ + +/* + * Only necessary if your driver takes special options, + * otherwise we fall back on the generic fb_setup(). + */ +int __init pm3fb_setup(char *options) { - DTRACE; - { - unsigned long i; - struct pm3fb_info *l_fb_info; - for (i = 0; i < PM3_MAX_BOARD; i++) { - l_fb_info = &(fb_info[i]); - pci_dev_put(l_fb_info->dev); - if (l_fb_info->dev != NULL && !(disable[l_fb_info->board_num])) { - if (l_fb_info->vIOBase != (unsigned char *) -1) { - pm3fb_unmapIO(l_fb_info); - release_mem_region(l_fb_info->p_fb, - l_fb_info->fb_size); - release_mem_region(l_fb_info->pIOBase, - PM3_REGS_SIZE); - } - unregister_framebuffer(&l_fb_info->gen.info); - } - } - } + /* Parse user speficied options (`video=pm3fb:') */ + return 0; } #endif /* MODULE */ + +module_init(pm3fb_init); +module_exit(pm3fb_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c index 76e6ce353c8e..a0e22ac483a3 100644 --- a/drivers/video/riva/rivafb-i2c.c +++ b/drivers/video/riva/rivafb-i2c.c @@ -70,8 +70,6 @@ static int riva_gpio_getscl(void* data) if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x04) val = 1; - val = VGA_RD08(par->riva.PCIO, 0x3d5); - return val; } diff --git a/fs/Makefile b/fs/Makefile index 9edf4112bee0..720c29d57a62 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -22,6 +22,10 @@ endif obj-$(CONFIG_INOTIFY) += inotify.o obj-$(CONFIG_INOTIFY_USER) += inotify_user.o obj-$(CONFIG_EPOLL) += eventpoll.o +obj-$(CONFIG_ANON_INODES) += anon_inodes.o +obj-$(CONFIG_SIGNALFD) += signalfd.o +obj-$(CONFIG_TIMERFD) += timerfd.o +obj-$(CONFIG_EVENTFD) += eventfd.o obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o nfsd-$(CONFIG_NFSD) := nfsctl.o diff --git a/fs/afs/afs.h b/fs/afs/afs.h index 52d0752265b8..245257948140 100644 --- a/fs/afs/afs.h +++ b/fs/afs/afs.h @@ -16,6 +16,9 @@ #define AFS_MAXCELLNAME 64 /* maximum length of a cell name */ #define AFS_MAXVOLNAME 64 /* maximum length of a volume name */ +#define AFSNAMEMAX 256 /* maximum length of a filename plus NUL */ +#define AFSPATHMAX 1024 /* maximum length of a pathname plus NUL */ +#define AFSOPAQUEMAX 1024 /* maximum length of an opaque field */ typedef unsigned afs_volid_t; typedef unsigned afs_vnodeid_t; @@ -143,4 +146,24 @@ struct afs_volsync { time_t creation; /* volume creation time */ }; +/* + * AFS volume status record + */ +struct afs_volume_status { + u32 vid; /* volume ID */ + u32 parent_id; /* parent volume ID */ + u8 online; /* true if volume currently online and available */ + u8 in_service; /* true if volume currently in service */ + u8 blessed; /* same as in_service */ + u8 needs_salvage; /* true if consistency checking required */ + u32 type; /* volume type (afs_voltype_t) */ + u32 min_quota; /* minimum space set aside (blocks) */ + u32 max_quota; /* maximum space this volume may occupy (blocks) */ + u32 blocks_in_use; /* space this volume currently occupies (blocks) */ + u32 part_blocks_avail; /* space available in volume's partition */ + u32 part_max_blocks; /* size of volume's partition */ +}; + +#define AFS_BLOCK_SIZE 1024 + #endif /* AFS_H */ diff --git a/fs/afs/afs_fs.h b/fs/afs/afs_fs.h index d963ef4daee8..a18c374ebe08 100644 --- a/fs/afs/afs_fs.h +++ b/fs/afs/afs_fs.h @@ -28,7 +28,8 @@ enum AFS_FS_Operations { FSMAKEDIR = 141, /* AFS Create a directory */ FSREMOVEDIR = 142, /* AFS Remove a directory */ FSGIVEUPCALLBACKS = 147, /* AFS Discard callback promises */ - FSGETVOLUMEINFO = 148, /* AFS Get root volume information */ + FSGETVOLUMEINFO = 148, /* AFS Get information about a volume */ + FSGETVOLUMESTATUS = 149, /* AFS Get volume status information */ FSGETROOTVOLUME = 151, /* AFS Get root volume name */ FSLOOKUP = 161, /* AFS lookup file in directory */ FSFETCHDATA64 = 65537, /* AFS Fetch file data */ diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 2fb31276196b..719af4fb15dc 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -497,7 +497,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, ASSERTCMP(dentry->d_inode, ==, NULL); - if (dentry->d_name.len > 255) { + if (dentry->d_name.len >= AFSNAMEMAX) { _leave(" = -ENAMETOOLONG"); return ERR_PTR(-ENAMETOOLONG); } @@ -736,7 +736,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode) dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode); ret = -ENAMETOOLONG; - if (dentry->d_name.len > 255) + if (dentry->d_name.len >= AFSNAMEMAX) goto error; key = afs_request_key(dvnode->volume->cell); @@ -801,7 +801,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name); ret = -ENAMETOOLONG; - if (dentry->d_name.len > 255) + if (dentry->d_name.len >= AFSNAMEMAX) goto error; key = afs_request_key(dvnode->volume->cell); @@ -847,7 +847,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name); ret = -ENAMETOOLONG; - if (dentry->d_name.len > 255) + if (dentry->d_name.len >= AFSNAMEMAX) goto error; key = afs_request_key(dvnode->volume->cell); @@ -921,7 +921,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, int mode, dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode); ret = -ENAMETOOLONG; - if (dentry->d_name.len > 255) + if (dentry->d_name.len >= AFSNAMEMAX) goto error; key = afs_request_key(dvnode->volume->cell); @@ -990,7 +990,7 @@ static int afs_link(struct dentry *from, struct inode *dir, dentry->d_name.name); ret = -ENAMETOOLONG; - if (dentry->d_name.len > 255) + if (dentry->d_name.len >= AFSNAMEMAX) goto error; key = afs_request_key(dvnode->volume->cell); @@ -1038,11 +1038,11 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry, content); ret = -ENAMETOOLONG; - if (dentry->d_name.len > 255) + if (dentry->d_name.len >= AFSNAMEMAX) goto error; ret = -EINVAL; - if (strlen(content) > 1023) + if (strlen(content) >= AFSPATHMAX) goto error; key = afs_request_key(dvnode->volume->cell); @@ -1112,7 +1112,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, new_dentry->d_name.name); ret = -ENAMETOOLONG; - if (new_dentry->d_name.len > 255) + if (new_dentry->d_name.len >= AFSNAMEMAX) goto error; key = afs_request_key(orig_dvnode->volume->cell); diff --git a/fs/afs/file.c b/fs/afs/file.c index 3e25795e5a42..9c0e721d9fc2 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -236,7 +236,7 @@ static void afs_invalidatepage(struct page *page, unsigned long offset) { int ret = 1; - kenter("{%lu},%lu", page->index, offset); + _enter("{%lu},%lu", page->index, offset); BUG_ON(!PageLocked(page)); diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 56cc0efa2a0c..5dff1308b6f0 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -202,6 +202,29 @@ static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr) } /* + * decode an AFSFetchVolumeStatus block + */ +static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp, + struct afs_volume_status *vs) +{ + const __be32 *bp = *_bp; + + vs->vid = ntohl(*bp++); + vs->parent_id = ntohl(*bp++); + vs->online = ntohl(*bp++); + vs->in_service = ntohl(*bp++); + vs->blessed = ntohl(*bp++); + vs->needs_salvage = ntohl(*bp++); + vs->type = ntohl(*bp++); + vs->min_quota = ntohl(*bp++); + vs->max_quota = ntohl(*bp++); + vs->blocks_in_use = ntohl(*bp++); + vs->part_blocks_avail = ntohl(*bp++); + vs->part_max_blocks = ntohl(*bp++); + *_bp = bp; +} + +/* * deliver reply data to an FS.FetchStatus */ static int afs_deliver_fs_fetch_status(struct afs_call *call, @@ -1450,3 +1473,278 @@ int afs_fs_setattr(struct afs_server *server, struct key *key, return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); } + +/* + * deliver reply data to an FS.GetVolumeStatus + */ +static int afs_deliver_fs_get_volume_status(struct afs_call *call, + struct sk_buff *skb, bool last) +{ + const __be32 *bp; + char *p; + int ret; + + _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); + + switch (call->unmarshall) { + case 0: + call->offset = 0; + call->unmarshall++; + + /* extract the returned status record */ + case 1: + _debug("extract status"); + ret = afs_extract_data(call, skb, last, call->buffer, + 12 * 4); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + + bp = call->buffer; + xdr_decode_AFSFetchVolumeStatus(&bp, call->reply2); + call->offset = 0; + call->unmarshall++; + + /* extract the volume name length */ + case 2: + ret = afs_extract_data(call, skb, last, &call->tmp, 4); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + + call->count = ntohl(call->tmp); + _debug("volname length: %u", call->count); + if (call->count >= AFSNAMEMAX) + return -EBADMSG; + call->offset = 0; + call->unmarshall++; + + /* extract the volume name */ + case 3: + _debug("extract volname"); + if (call->count > 0) { + ret = afs_extract_data(call, skb, last, call->reply3, + call->count); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + } + + p = call->reply3; + p[call->count] = 0; + _debug("volname '%s'", p); + + call->offset = 0; + call->unmarshall++; + + /* extract the volume name padding */ + if ((call->count & 3) == 0) { + call->unmarshall++; + goto no_volname_padding; + } + call->count = 4 - (call->count & 3); + + case 4: + ret = afs_extract_data(call, skb, last, call->buffer, + call->count); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + + call->offset = 0; + call->unmarshall++; + no_volname_padding: + + /* extract the offline message length */ + case 5: + ret = afs_extract_data(call, skb, last, &call->tmp, 4); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + + call->count = ntohl(call->tmp); + _debug("offline msg length: %u", call->count); + if (call->count >= AFSNAMEMAX) + return -EBADMSG; + call->offset = 0; + call->unmarshall++; + + /* extract the offline message */ + case 6: + _debug("extract offline"); + if (call->count > 0) { + ret = afs_extract_data(call, skb, last, call->reply3, + call->count); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + } + + p = call->reply3; + p[call->count] = 0; + _debug("offline '%s'", p); + + call->offset = 0; + call->unmarshall++; + + /* extract the offline message padding */ + if ((call->count & 3) == 0) { + call->unmarshall++; + goto no_offline_padding; + } + call->count = 4 - (call->count & 3); + + case 7: + ret = afs_extract_data(call, skb, last, call->buffer, + call->count); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + + call->offset = 0; + call->unmarshall++; + no_offline_padding: + + /* extract the message of the day length */ + case 8: + ret = afs_extract_data(call, skb, last, &call->tmp, 4); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + + call->count = ntohl(call->tmp); + _debug("motd length: %u", call->count); + if (call->count >= AFSNAMEMAX) + return -EBADMSG; + call->offset = 0; + call->unmarshall++; + + /* extract the message of the day */ + case 9: + _debug("extract motd"); + if (call->count > 0) { + ret = afs_extract_data(call, skb, last, call->reply3, + call->count); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + } + + p = call->reply3; + p[call->count] = 0; + _debug("motd '%s'", p); + + call->offset = 0; + call->unmarshall++; + + /* extract the message of the day padding */ + if ((call->count & 3) == 0) { + call->unmarshall++; + goto no_motd_padding; + } + call->count = 4 - (call->count & 3); + + case 10: + ret = afs_extract_data(call, skb, last, call->buffer, + call->count); + switch (ret) { + case 0: break; + case -EAGAIN: return 0; + default: return ret; + } + + call->offset = 0; + call->unmarshall++; + no_motd_padding: + + case 11: + _debug("trailer %d", skb->len); + if (skb->len != 0) + return -EBADMSG; + break; + } + + if (!last) + return 0; + + _leave(" = 0 [done]"); + return 0; +} + +/* + * destroy an FS.GetVolumeStatus call + */ +static void afs_get_volume_status_call_destructor(struct afs_call *call) +{ + kfree(call->reply3); + call->reply3 = NULL; + afs_flat_call_destructor(call); +} + +/* + * FS.GetVolumeStatus operation type + */ +static const struct afs_call_type afs_RXFSGetVolumeStatus = { + .name = "FS.GetVolumeStatus", + .deliver = afs_deliver_fs_get_volume_status, + .abort_to_error = afs_abort_to_error, + .destructor = afs_get_volume_status_call_destructor, +}; + +/* + * fetch the status of a volume + */ +int afs_fs_get_volume_status(struct afs_server *server, + struct key *key, + struct afs_vnode *vnode, + struct afs_volume_status *vs, + const struct afs_wait_mode *wait_mode) +{ + struct afs_call *call; + __be32 *bp; + void *tmpbuf; + + _enter(""); + + tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL); + if (!tmpbuf) + return -ENOMEM; + + call = afs_alloc_flat_call(&afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4); + if (!call) { + kfree(tmpbuf); + return -ENOMEM; + } + + call->key = key; + call->reply = vnode; + call->reply2 = vs; + call->reply3 = tmpbuf; + call->service_id = FS_SERVICE; + call->port = htons(AFS_FS_PORT); + + /* marshall the parameters */ + bp = call->request; + bp[0] = htonl(FSGETVOLUMESTATUS); + bp[1] = htonl(vnode->fid.vid); + + return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); +} diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 515a5d12d8fb..47f5fed7195d 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -209,11 +209,15 @@ bad_inode: */ void afs_zap_data(struct afs_vnode *vnode) { - _enter("zap data {%x:%u}", vnode->fid.vid, vnode->fid.vnode); + _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); /* nuke all the non-dirty pages that aren't locked, mapped or being - * written back */ - invalidate_remote_inode(&vnode->vfs_inode); + * written back in a regular file and completely discard the pages in a + * directory or symlink */ + if (S_ISREG(vnode->vfs_inode.i_mode)) + invalidate_remote_inode(&vnode->vfs_inode); + else + invalidate_inode_pages2(vnode->vfs_inode.i_mapping); } /* diff --git a/fs/afs/internal.h b/fs/afs/internal.h index a30d4fa768e3..4953ba5a6f44 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -506,6 +506,10 @@ extern int afs_fs_store_data(struct afs_server *, struct afs_writeback *, extern int afs_fs_setattr(struct afs_server *, struct key *, struct afs_vnode *, struct iattr *, const struct afs_wait_mode *); +extern int afs_fs_get_volume_status(struct afs_server *, struct key *, + struct afs_vnode *, + struct afs_volume_status *, + const struct afs_wait_mode *); /* * inode.c @@ -672,6 +676,8 @@ extern int afs_vnode_rename(struct afs_vnode *, struct afs_vnode *, extern int afs_vnode_store_data(struct afs_writeback *, pgoff_t, pgoff_t, unsigned, unsigned); extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *); +extern int afs_vnode_get_volume_status(struct afs_vnode *, struct key *, + struct afs_volume_status *); /* * volume.c diff --git a/fs/afs/super.c b/fs/afs/super.c index d24be334b608..579af632c8e8 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -21,22 +21,20 @@ #include <linux/fs.h> #include <linux/pagemap.h> #include <linux/parser.h> +#include <linux/statfs.h> #include "internal.h" #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ static void afs_i_init_once(void *foo, struct kmem_cache *cachep, unsigned long flags); - static int afs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt); - static struct inode *afs_alloc_inode(struct super_block *sb); - static void afs_put_super(struct super_block *sb); - static void afs_destroy_inode(struct inode *inode); +static int afs_statfs(struct dentry *dentry, struct kstatfs *buf); struct file_system_type afs_fs_type = { .owner = THIS_MODULE, @@ -47,7 +45,7 @@ struct file_system_type afs_fs_type = { }; static const struct super_operations afs_super_ops = { - .statfs = simple_statfs, + .statfs = afs_statfs, .alloc_inode = afs_alloc_inode, .drop_inode = generic_delete_inode, .write_inode = afs_write_inode, @@ -488,6 +486,7 @@ static struct inode *afs_alloc_inode(struct super_block *sb) vnode->flags = 1 << AFS_VNODE_UNSET; vnode->cb_promised = false; + _leave(" = %p", &vnode->vfs_inode); return &vnode->vfs_inode; } @@ -498,7 +497,7 @@ static void afs_destroy_inode(struct inode *inode) { struct afs_vnode *vnode = AFS_FS_I(inode); - _enter("{%lu}", inode->i_ino); + _enter("%p{%x:%u}", inode, vnode->fid.vid, vnode->fid.vnode); _debug("DESTROY INODE %p", inode); @@ -507,3 +506,36 @@ static void afs_destroy_inode(struct inode *inode) kmem_cache_free(afs_inode_cachep, vnode); atomic_dec(&afs_count_active_inodes); } + +/* + * return information about an AFS volume + */ +static int afs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct afs_volume_status vs; + struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode); + struct key *key; + int ret; + + key = afs_request_key(vnode->volume->cell); + if (IS_ERR(key)) + return PTR_ERR(key); + + ret = afs_vnode_get_volume_status(vnode, key, &vs); + key_put(key); + if (ret < 0) { + _leave(" = %d", ret); + return ret; + } + + buf->f_type = dentry->d_sb->s_magic; + buf->f_bsize = AFS_BLOCK_SIZE; + buf->f_namelen = AFSNAMEMAX - 1; + + if (vs.max_quota == 0) + buf->f_blocks = vs.part_max_blocks; + else + buf->f_blocks = vs.max_quota; + buf->f_bavail = buf->f_bfree = buf->f_blocks - vs.blocks_in_use; + return 0; +} diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c index ec814660209f..c36c98ce2c3c 100644 --- a/fs/afs/vnode.c +++ b/fs/afs/vnode.c @@ -175,24 +175,33 @@ static void afs_vnode_deleted_remotely(struct afs_vnode *vnode) { struct afs_server *server; + _enter("{%p}", vnode->server); + set_bit(AFS_VNODE_DELETED, &vnode->flags); server = vnode->server; - if (vnode->cb_promised) { - spin_lock(&server->cb_lock); + if (server) { if (vnode->cb_promised) { - rb_erase(&vnode->cb_promise, &server->cb_promises); - vnode->cb_promised = false; + spin_lock(&server->cb_lock); + if (vnode->cb_promised) { + rb_erase(&vnode->cb_promise, + &server->cb_promises); + vnode->cb_promised = false; + } + spin_unlock(&server->cb_lock); } - spin_unlock(&server->cb_lock); - } - spin_lock(&vnode->server->fs_lock); - rb_erase(&vnode->server_rb, &vnode->server->fs_vnodes); - spin_unlock(&vnode->server->fs_lock); + spin_lock(&server->fs_lock); + rb_erase(&vnode->server_rb, &server->fs_vnodes); + spin_unlock(&server->fs_lock); - vnode->server = NULL; - afs_put_server(server); + vnode->server = NULL; + afs_put_server(server); + } else { + ASSERT(!vnode->cb_promised); + } + + _leave(""); } /* @@ -225,7 +234,7 @@ void afs_vnode_finalise_status_update(struct afs_vnode *vnode, */ static void afs_vnode_status_update_failed(struct afs_vnode *vnode, int ret) { - _enter("%p,%d", vnode, ret); + _enter("{%x:%u},%d", vnode->fid.vid, vnode->fid.vnode, ret); spin_lock(&vnode->lock); @@ -860,3 +869,55 @@ no_server: spin_unlock(&vnode->lock); return PTR_ERR(server); } + +/* + * get the status of a volume + */ +int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key, + struct afs_volume_status *vs) +{ + struct afs_server *server; + int ret; + + _enter("%s{%x:%u.%u},%x,", + vnode->volume->vlocation->vldb.name, + vnode->fid.vid, + vnode->fid.vnode, + vnode->fid.unique, + key_serial(key)); + + /* this op will fetch the status */ + spin_lock(&vnode->lock); + vnode->update_cnt++; + spin_unlock(&vnode->lock); + + do { + /* pick a server to query */ + server = afs_volume_pick_fileserver(vnode); + if (IS_ERR(server)) + goto no_server; + + _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); + + ret = afs_fs_get_volume_status(server, key, vnode, vs, &afs_sync_call); + + } while (!afs_volume_release_fileserver(vnode, server, ret)); + + /* adjust the flags */ + if (ret == 0) { + afs_vnode_finalise_status_update(vnode, server); + afs_put_server(server); + } else { + afs_vnode_status_update_failed(vnode, ret); + } + + _leave(" = %d", ret); + return ret; + +no_server: + spin_lock(&vnode->lock); + vnode->update_cnt--; + ASSERTCMP(vnode->update_cnt, >=, 0); + spin_unlock(&vnode->lock); + return PTR_ERR(server); +} diff --git a/fs/afs/write.c b/fs/afs/write.c index 67ae4dbf66b3..28f37516c126 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -395,8 +395,9 @@ static int afs_write_back_from_locked_page(struct afs_writeback *wb, if (n == 0) goto no_more; if (pages[0]->index != start) { - for (n--; n >= 0; n--) - put_page(pages[n]); + do { + put_page(pages[--n]); + } while (n > 0); goto no_more; } @@ -30,6 +30,7 @@ #include <linux/highmem.h> #include <linux/workqueue.h> #include <linux/security.h> +#include <linux/eventfd.h> #include <asm/kmap_types.h> #include <asm/uaccess.h> @@ -417,6 +418,7 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx) req->private = NULL; req->ki_iovec = NULL; INIT_LIST_HEAD(&req->ki_run_list); + req->ki_eventfd = ERR_PTR(-EINVAL); /* Check if the completion queue has enough free space to * accept an event from this io. @@ -458,6 +460,8 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) { assert_spin_locked(&ctx->ctx_lock); + if (!IS_ERR(req->ki_eventfd)) + fput(req->ki_eventfd); if (req->ki_dtor) req->ki_dtor(req); if (req->ki_iovec != &req->ki_inline_vec) @@ -942,6 +946,14 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2) return 1; } + /* + * Check if the user asked us to deliver the result through an + * eventfd. The eventfd_signal() function is safe to be called + * from IRQ context. + */ + if (!IS_ERR(iocb->ki_eventfd)) + eventfd_signal(iocb->ki_eventfd, 1); + info = &ctx->ring_info; /* add a completion event to the ring buffer. @@ -1526,8 +1538,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, ssize_t ret; /* enforce forwards compatibility on users */ - if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 || - iocb->aio_reserved3)) { + if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2)) { pr_debug("EINVAL: io_submit: reserve field set\n"); return -EINVAL; } @@ -1551,6 +1562,19 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, fput(file); return -EAGAIN; } + if (iocb->aio_flags & IOCB_FLAG_RESFD) { + /* + * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an + * instance of the file* now. The file descriptor must be + * an eventfd() fd, and will be signaled for each completed + * event using the eventfd_signal() function. + */ + req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd); + if (unlikely(IS_ERR(req->ki_eventfd))) { + ret = PTR_ERR(req->ki_eventfd); + goto out_put_req; + } + } req->ki_filp = file; ret = put_user(req->ki_key, &user_iocb->aio_key); diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c new file mode 100644 index 000000000000..40fe3a3222e4 --- /dev/null +++ b/fs/anon_inodes.c @@ -0,0 +1,200 @@ +/* + * fs/anon_inodes.c + * + * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> + * + * Thanks to Arnd Bergmann for code review and suggestions. + * More changes for Thomas Gleixner suggestions. + * + */ + +#include <linux/file.h> +#include <linux/poll.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/mount.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/magic.h> +#include <linux/anon_inodes.h> + +#include <asm/uaccess.h> + +static struct vfsmount *anon_inode_mnt __read_mostly; +static struct inode *anon_inode_inode; +static const struct file_operations anon_inode_fops; + +static int anon_inodefs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) +{ + return get_sb_pseudo(fs_type, "anon_inode:", NULL, ANON_INODE_FS_MAGIC, + mnt); +} + +static int anon_inodefs_delete_dentry(struct dentry *dentry) +{ + /* + * We faked vfs to believe the dentry was hashed when we created it. + * Now we restore the flag so that dput() will work correctly. + */ + dentry->d_flags |= DCACHE_UNHASHED; + return 1; +} + +static struct file_system_type anon_inode_fs_type = { + .name = "anon_inodefs", + .get_sb = anon_inodefs_get_sb, + .kill_sb = kill_anon_super, +}; +static struct dentry_operations anon_inodefs_dentry_operations = { + .d_delete = anon_inodefs_delete_dentry, +}; + +/** + * anon_inode_getfd - creates a new file instance by hooking it up to and + * anonymous inode, and a dentry that describe the "class" + * of the file + * + * @pfd: [out] pointer to the file descriptor + * @dpinode: [out] pointer to the inode + * @pfile: [out] pointer to the file struct + * @name: [in] name of the "class" of the new file + * @fops [in] file operations for the new file + * @priv [in] private data for the new file (will be file's private_data) + * + * Creates a new file by hooking it on a single inode. This is useful for files + * that do not need to have a full-fledged inode in order to operate correctly. + * All the files created with anon_inode_getfd() will share a single inode, by + * hence saving memory and avoiding code duplication for the file/inode/dentry + * setup. + */ +int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, + const char *name, const struct file_operations *fops, + void *priv) +{ + struct qstr this; + struct dentry *dentry; + struct inode *inode; + struct file *file; + int error, fd; + + if (IS_ERR(anon_inode_inode)) + return -ENODEV; + file = get_empty_filp(); + if (!file) + return -ENFILE; + + inode = igrab(anon_inode_inode); + if (IS_ERR(inode)) { + error = PTR_ERR(inode); + goto err_put_filp; + } + + error = get_unused_fd(); + if (error < 0) + goto err_iput; + fd = error; + + /* + * Link the inode to a directory entry by creating a unique name + * using the inode sequence number. + */ + error = -ENOMEM; + this.name = name; + this.len = strlen(name); + this.hash = 0; + dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this); + if (!dentry) + goto err_put_unused_fd; + dentry->d_op = &anon_inodefs_dentry_operations; + /* Do not publish this dentry inside the global dentry hash table */ + dentry->d_flags &= ~DCACHE_UNHASHED; + d_instantiate(dentry, inode); + + file->f_path.mnt = mntget(anon_inode_mnt); + file->f_path.dentry = dentry; + file->f_mapping = inode->i_mapping; + + file->f_pos = 0; + file->f_flags = O_RDWR; + file->f_op = fops; + file->f_mode = FMODE_READ | FMODE_WRITE; + file->f_version = 0; + file->private_data = priv; + + fd_install(fd, file); + + *pfd = fd; + *pinode = inode; + *pfile = file; + return 0; + +err_put_unused_fd: + put_unused_fd(fd); +err_iput: + iput(inode); +err_put_filp: + put_filp(file); + return error; +} + +/* + * A single inode exist for all anon_inode files. Contrary to pipes, + * anon_inode inodes has no per-instance data associated, so we can avoid + * the allocation of multiple of them. + */ +static struct inode *anon_inode_mkinode(void) +{ + struct inode *inode = new_inode(anon_inode_mnt->mnt_sb); + + if (!inode) + return ERR_PTR(-ENOMEM); + + inode->i_fop = &anon_inode_fops; + + /* + * Mark the inode dirty from the very beginning, + * that way it will never be moved to the dirty + * list because mark_inode_dirty() will think + * that it already _is_ on the dirty list. + */ + inode->i_state = I_DIRTY; + inode->i_mode = S_IRUSR | S_IWUSR; + inode->i_uid = current->fsuid; + inode->i_gid = current->fsgid; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + return inode; +} + +static int __init anon_inode_init(void) +{ + int error; + + error = register_filesystem(&anon_inode_fs_type); + if (error) + goto err_exit; + anon_inode_mnt = kern_mount(&anon_inode_fs_type); + if (IS_ERR(anon_inode_mnt)) { + error = PTR_ERR(anon_inode_mnt); + goto err_unregister_filesystem; + } + anon_inode_inode = anon_inode_mkinode(); + if (IS_ERR(anon_inode_inode)) { + error = PTR_ERR(anon_inode_inode); + goto err_mntput; + } + + return 0; + +err_mntput: + mntput(anon_inode_mnt); +err_unregister_filesystem: + unregister_filesystem(&anon_inode_fs_type); +err_exit: + panic(KERN_ERR "anon_inode_init() failed (%d)\n", error); +} + +fs_initcall(anon_inode_init); + diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 4ef544434b51..8b4cca3c4705 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -101,7 +101,7 @@ struct autofs_symlink { struct autofs_sb_info { u32 magic; struct file *pipe; - pid_t oz_pgrp; + struct pid *oz_pgrp; int catatonic; struct super_block *sb; unsigned long exp_timeout; @@ -122,7 +122,7 @@ static inline struct autofs_sb_info *autofs_sbi(struct super_block *sb) filesystem without "magic".) */ static inline int autofs_oz_mode(struct autofs_sb_info *sbi) { - return sbi->catatonic || process_group(current) == sbi->oz_pgrp; + return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp; } /* Hash operations */ diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index aa0b61ff8270..e7204d71acc9 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -34,12 +34,14 @@ void autofs_kill_sb(struct super_block *sb) if (!sbi) goto out_kill_sb; - if ( !sbi->catatonic ) + if (!sbi->catatonic) autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ + put_pid(sbi->oz_pgrp); + autofs_hash_nuke(sbi); - for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) { - if ( test_bit(n, sbi->symlink_bitmap) ) + for (n = 0; n < AUTOFS_MAX_SYMLINKS; n++) { + if (test_bit(n, sbi->symlink_bitmap)) kfree(sbi->symlink[n].data); } @@ -69,7 +71,8 @@ static match_table_t autofs_tokens = { {Opt_err, NULL} }; -static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, pid_t *pgrp, int *minproto, int *maxproto) +static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, + pid_t *pgrp, int *minproto, int *maxproto) { char *p; substring_t args[MAX_OPT_ARGS]; @@ -138,9 +141,10 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) int pipefd; struct autofs_sb_info *sbi; int minproto, maxproto; + pid_t pgid; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if ( !sbi ) + if (!sbi) goto fail_unlock; DPRINTK(("autofs: starting up, sbi = %p\n",sbi)); @@ -149,7 +153,6 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) sbi->pipe = NULL; sbi->catatonic = 1; sbi->exp_timeout = 0; - sbi->oz_pgrp = process_group(current); autofs_initialize_hash(&sbi->dirhash); sbi->queues = NULL; memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN); @@ -169,26 +172,36 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) goto fail_iput; /* Can this call block? - WTF cares? s is locked. */ - if ( parse_options(data,&pipefd,&root_inode->i_uid,&root_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) { + if (parse_options(data, &pipefd, &root_inode->i_uid, + &root_inode->i_gid, &pgid, &minproto, + &maxproto)) { printk("autofs: called with bogus options\n"); goto fail_dput; } /* Couldn't this be tested earlier? */ - if ( minproto > AUTOFS_PROTO_VERSION || - maxproto < AUTOFS_PROTO_VERSION ) { + if (minproto > AUTOFS_PROTO_VERSION || + maxproto < AUTOFS_PROTO_VERSION) { printk("autofs: kernel does not match daemon version\n"); goto fail_dput; } - DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, sbi->oz_pgrp)); + DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, pgid)); + sbi->oz_pgrp = find_get_pid(pgid); + + if (!sbi->oz_pgrp) { + printk("autofs: could not find process group %d\n", pgid); + goto fail_dput; + } + pipe = fget(pipefd); - if ( !pipe ) { + if (!pipe) { printk("autofs: could not open pipe file descriptor\n"); - goto fail_dput; + goto fail_put_pid; } - if ( !pipe->f_op || !pipe->f_op->write ) + + if (!pipe->f_op || !pipe->f_op->write) goto fail_fput; sbi->pipe = pipe; sbi->catatonic = 0; @@ -202,6 +215,8 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) fail_fput: printk("autofs: pipe file descriptor does not contain proper ops\n"); fput(pipe); +fail_put_pid: + put_pid(sbi->oz_pgrp); fail_dput: dput(root); goto fail_free; @@ -230,7 +245,7 @@ static void autofs_read_inode(struct inode *inode) inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = 0; - if ( ino == AUTOFS_ROOT_INO ) { + if (ino == AUTOFS_ROOT_INO) { inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; inode->i_op = &autofs_root_inode_operations; inode->i_fop = &autofs_root_operations; @@ -241,12 +256,12 @@ static void autofs_read_inode(struct inode *inode) inode->i_uid = inode->i_sb->s_root->d_inode->i_uid; inode->i_gid = inode->i_sb->s_root->d_inode->i_gid; - if ( ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO ) { + if (ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO) { /* Symlink inode - should be in symlink list */ struct autofs_symlink *sl; n = ino - AUTOFS_FIRST_SYMLINK; - if ( n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) { + if (n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) { printk("autofs: Looking for bad symlink inode %u\n", (unsigned int) ino); return; } diff --git a/fs/autofs/root.c b/fs/autofs/root.c index f2597205939d..c1489533277a 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -67,8 +67,8 @@ static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldi filp->f_pos = ++nr; /* fall through */ default: - while ( onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent) ) { - if ( !ent->dentry || d_mountpoint(ent->dentry) ) { + while (onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent)) { + if (!ent->dentry || d_mountpoint(ent->dentry)) { if (filldir(dirent,ent->name,ent->len,onr,ent->ino,DT_UNKNOWN) < 0) goto out; filp->f_pos = nr; @@ -88,10 +88,10 @@ static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, str struct autofs_dir_ent *ent; int status = 0; - if ( !(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)) ) { + if (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name))) { do { - if ( status && dentry->d_inode ) { - if ( status != -ENOENT ) + if (status && dentry->d_inode) { + if (status != -ENOENT) printk("autofs warning: lookup failure on positive dentry, status = %d, name = %s\n", status, dentry->d_name.name); return 0; /* Try to get the kernel to invalidate this dentry */ } @@ -106,7 +106,7 @@ static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, str return 1; } status = autofs_wait(sbi, &dentry->d_name); - } while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)) ); + } while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name))); } /* Abuse this field as a pointer to the directory entry, used to @@ -124,13 +124,13 @@ static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, str /* If this is a directory that isn't a mount point, bitch at the daemon and fix it in user space */ - if ( S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) ) { + if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) { return !autofs_wait(sbi, &dentry->d_name); } /* We don't update the usages for the autofs daemon itself, this is necessary for recursive autofs mounts */ - if ( !autofs_oz_mode(sbi) ) { + if (!autofs_oz_mode(sbi)) { autofs_update_usage(&sbi->dirhash,ent); } @@ -157,7 +157,7 @@ static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd) sbi = autofs_sbi(dir->i_sb); /* Pending dentry */ - if ( dentry->d_flags & DCACHE_AUTOFS_PENDING ) { + if (dentry->d_flags & DCACHE_AUTOFS_PENDING) { if (autofs_oz_mode(sbi)) res = 1; else @@ -173,7 +173,7 @@ static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd) } /* Check for a non-mountpoint directory */ - if ( S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) ) { + if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) { if (autofs_oz_mode(sbi)) res = 1; else @@ -183,9 +183,9 @@ static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd) } /* Update the usage list */ - if ( !autofs_oz_mode(sbi) ) { + if (!autofs_oz_mode(sbi)) { ent = (struct autofs_dir_ent *) dentry->d_time; - if ( ent ) + if (ent) autofs_update_usage(&sbi->dirhash,ent); } unlock_kernel(); @@ -213,8 +213,10 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr sbi = autofs_sbi(dir->i_sb); oz_mode = autofs_oz_mode(sbi); - DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", - current->pid, process_group(current), sbi->catatonic, oz_mode)); + DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, " + "oz_mode = %d\n", pid_nr(task_pid(current)), + process_group(current), sbi->catatonic, + oz_mode)); /* * Mark the dentry incomplete, but add it. This is needed so @@ -258,7 +260,7 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr * doesn't do the right thing for all system calls, but it should * be OK for the operations we permit from an autofs. */ - if ( dentry->d_inode && d_unhashed(dentry) ) + if (dentry->d_inode && d_unhashed(dentry)) return ERR_PTR(-ENOENT); return NULL; @@ -277,18 +279,18 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c autofs_say(dentry->d_name.name,dentry->d_name.len); lock_kernel(); - if ( !autofs_oz_mode(sbi) ) { + if (!autofs_oz_mode(sbi)) { unlock_kernel(); return -EACCES; } - if ( autofs_hash_lookup(dh, &dentry->d_name) ) { + if (autofs_hash_lookup(dh, &dentry->d_name)) { unlock_kernel(); return -EEXIST; } n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS); - if ( n >= AUTOFS_MAX_SYMLINKS ) { + if (n >= AUTOFS_MAX_SYMLINKS) { unlock_kernel(); return -ENOSPC; } @@ -297,14 +299,14 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c sl = &sbi->symlink[n]; sl->len = strlen(symname); sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL); - if ( !sl->data ) { + if (!sl->data) { clear_bit(n,sbi->symlink_bitmap); unlock_kernel(); return -ENOSPC; } ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL); - if ( !ent ) { + if (!ent) { kfree(sl->data); clear_bit(n,sbi->symlink_bitmap); unlock_kernel(); @@ -312,7 +314,7 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c } ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL); - if ( !ent->name ) { + if (!ent->name) { kfree(sl->data); kfree(ent); clear_bit(n,sbi->symlink_bitmap); @@ -354,23 +356,23 @@ static int autofs_root_unlink(struct inode *dir, struct dentry *dentry) /* This allows root to remove symlinks */ lock_kernel(); - if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) { + if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) { unlock_kernel(); return -EACCES; } ent = autofs_hash_lookup(dh, &dentry->d_name); - if ( !ent ) { + if (!ent) { unlock_kernel(); return -ENOENT; } n = ent->ino - AUTOFS_FIRST_SYMLINK; - if ( n >= AUTOFS_MAX_SYMLINKS ) { + if (n >= AUTOFS_MAX_SYMLINKS) { unlock_kernel(); return -EISDIR; /* It's a directory, dummy */ } - if ( !test_bit(n,sbi->symlink_bitmap) ) { + if (!test_bit(n,sbi->symlink_bitmap)) { unlock_kernel(); return -EINVAL; /* Nonexistent symlink? Shouldn't happen */ } @@ -392,23 +394,23 @@ static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry) struct autofs_dir_ent *ent; lock_kernel(); - if ( !autofs_oz_mode(sbi) ) { + if (!autofs_oz_mode(sbi)) { unlock_kernel(); return -EACCES; } ent = autofs_hash_lookup(dh, &dentry->d_name); - if ( !ent ) { + if (!ent) { unlock_kernel(); return -ENOENT; } - if ( (unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO ) { + if ((unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO) { unlock_kernel(); return -ENOTDIR; /* Not a directory */ } - if ( ent->dentry != dentry ) { + if (ent->dentry != dentry) { printk("autofs_rmdir: odentry != dentry for entry %s\n", dentry->d_name.name); } @@ -429,18 +431,18 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode) ino_t ino; lock_kernel(); - if ( !autofs_oz_mode(sbi) ) { + if (!autofs_oz_mode(sbi)) { unlock_kernel(); return -EACCES; } ent = autofs_hash_lookup(dh, &dentry->d_name); - if ( ent ) { + if (ent) { unlock_kernel(); return -EEXIST; } - if ( sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO ) { + if (sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO) { printk("autofs: Out of inode numbers -- what the heck did you do??\n"); unlock_kernel(); return -ENOSPC; @@ -448,13 +450,13 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode) ino = sbi->next_dir_ino++; ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL); - if ( !ent ) { + if (!ent) { unlock_kernel(); return -ENOSPC; } ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL); - if ( !ent->name ) { + if (!ent->name) { kfree(ent); unlock_kernel(); return -ENOSPC; @@ -483,7 +485,7 @@ static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi, put_user(sbi->exp_timeout / HZ, p)) return -EFAULT; - if ( ntimeout > ULONG_MAX/HZ ) + if (ntimeout > ULONG_MAX/HZ) sbi->exp_timeout = 0; else sbi->exp_timeout = ntimeout * HZ; @@ -511,15 +513,14 @@ static inline int autofs_expire_run(struct super_block *sb, pkt.hdr.proto_version = AUTOFS_PROTO_VERSION; pkt.hdr.type = autofs_ptype_expire; - if ( !sbi->exp_timeout || - !(ent = autofs_expire(sb,sbi,mnt)) ) + if (!sbi->exp_timeout || !(ent = autofs_expire(sb,sbi,mnt))) return -EAGAIN; pkt.len = ent->len; memcpy(pkt.name, ent->name, pkt.len); pkt.name[pkt.len] = '\0'; - if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) ) + if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire))) return -EFAULT; return 0; @@ -537,11 +538,11 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp, DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,process_group(current))); - if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || - _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT ) + if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || + _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT) return -ENOTTY; - if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) + if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) return -EPERM; switch(cmd) { diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 5769a2f9ad60..692364e8ffc3 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -218,8 +218,7 @@ static match_table_t tokens = { }; static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, - pid_t *pgrp, unsigned int *type, - int *minproto, int *maxproto) + pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto) { char *p; substring_t args[MAX_OPT_ARGS]; @@ -314,7 +313,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) struct autofs_info *ino; sbi = kmalloc(sizeof(*sbi), GFP_KERNEL); - if ( !sbi ) + if (!sbi) goto fail_unlock; DPRINTK("starting up, sbi = %p",sbi); @@ -363,10 +362,9 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) root->d_fsdata = ino; /* Can this call block? */ - if (parse_options(data, &pipefd, - &root_inode->i_uid, &root_inode->i_gid, - &sbi->oz_pgrp, &sbi->type, - &sbi->min_proto, &sbi->max_proto)) { + if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid, + &sbi->oz_pgrp, &sbi->type, &sbi->min_proto, + &sbi->max_proto)) { printk("autofs: called with bogus options\n"); goto fail_dput; } @@ -396,11 +394,11 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp); pipe = fget(pipefd); - if ( !pipe ) { + if (!pipe) { printk("autofs: could not open pipe file descriptor\n"); goto fail_dput; } - if ( !pipe->f_op || !pipe->f_op->write ) + if (!pipe->f_op || !pipe->f_op->write) goto fail_fput; sbi->pipe = pipe; sbi->pipefd = pipefd; diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 15170f4e13a7..2d4c8a3e604e 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -759,7 +759,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) struct autofs_info *p_ino; /* This allows root to remove symlinks */ - if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) + if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) return -EACCES; if (atomic_dec_and_test(&ino->count)) { @@ -833,7 +833,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) struct autofs_info *p_ino; struct inode *inode; - if ( !autofs4_oz_mode(sbi) ) + if (!autofs4_oz_mode(sbi)) return -EACCES; DPRINTK("dentry %p, creating %.*s", @@ -871,11 +871,11 @@ static inline int autofs4_get_set_timeout(struct autofs_sb_info *sbi, int rv; unsigned long ntimeout; - if ( (rv = get_user(ntimeout, p)) || - (rv = put_user(sbi->exp_timeout/HZ, p)) ) + if ((rv = get_user(ntimeout, p)) || + (rv = put_user(sbi->exp_timeout/HZ, p))) return rv; - if ( ntimeout > ULONG_MAX/HZ ) + if (ntimeout > ULONG_MAX/HZ) sbi->exp_timeout = 0; else sbi->exp_timeout = ntimeout * HZ; @@ -906,7 +906,7 @@ static inline int autofs4_ask_reghost(struct autofs_sb_info *sbi, int __user *p) DPRINTK("returning %d", sbi->needs_reghost); status = put_user(sbi->needs_reghost, p); - if ( status ) + if (status) return status; sbi->needs_reghost = 0; @@ -975,11 +975,11 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp, DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u", cmd,arg,sbi,process_group(current)); - if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || - _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT ) + if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || + _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT) return -ENOTTY; - if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) + if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) return -EPERM; switch(cmd) { diff --git a/fs/compat.c b/fs/compat.c index 9cf75df9b2bb..7b21b0a82596 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -46,6 +46,7 @@ #include <linux/tsacct_kern.h> #include <linux/security.h> #include <linux/highmem.h> +#include <linux/signal.h> #include <linux/poll.h> #include <linux/mm.h> #include <linux/eventpoll.h> @@ -2199,3 +2200,51 @@ asmlinkage long compat_sys_epoll_pwait(int epfd, #endif /* TIF_RESTORE_SIGMASK */ #endif /* CONFIG_EPOLL */ + +#ifdef CONFIG_SIGNALFD + +asmlinkage long compat_sys_signalfd(int ufd, + const compat_sigset_t __user *sigmask, + compat_size_t sigsetsize) +{ + compat_sigset_t ss32; + sigset_t tmp; + sigset_t __user *ksigmask; + + if (sigsetsize != sizeof(compat_sigset_t)) + return -EINVAL; + if (copy_from_user(&ss32, sigmask, sizeof(ss32))) + return -EFAULT; + sigset_from_compat(&tmp, &ss32); + ksigmask = compat_alloc_user_space(sizeof(sigset_t)); + if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t))) + return -EFAULT; + + return sys_signalfd(ufd, ksigmask, sizeof(sigset_t)); +} + +#endif /* CONFIG_SIGNALFD */ + +#ifdef CONFIG_TIMERFD + +asmlinkage long compat_sys_timerfd(int ufd, int clockid, int flags, + const struct compat_itimerspec __user *utmr) +{ + long res; + struct itimerspec t; + struct itimerspec __user *ut; + + res = -EFAULT; + if (get_compat_itimerspec(&t, utmr)) + goto err_exit; + ut = compat_alloc_user_space(sizeof(*ut)); + if (copy_to_user(ut, &t, sizeof(t)) ) + goto err_exit; + + res = sys_timerfd(ufd, clockid, flags, ut); +err_exit: + return res; +} + +#endif /* CONFIG_TIMERFD */ + diff --git a/fs/eventfd.c b/fs/eventfd.c new file mode 100644 index 000000000000..480e2b3c4166 --- /dev/null +++ b/fs/eventfd.c @@ -0,0 +1,228 @@ +/* + * fs/eventfd.c + * + * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> + * + */ + +#include <linux/file.h> +#include <linux/poll.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/anon_inodes.h> +#include <linux/eventfd.h> + +struct eventfd_ctx { + spinlock_t lock; + wait_queue_head_t wqh; + /* + * Every time that a write(2) is performed on an eventfd, the + * value of the __u64 being written is added to "count" and a + * wakeup is performed on "wqh". A read(2) will return the "count" + * value to userspace, and will reset "count" to zero. The kernel + * size eventfd_signal() also, adds to the "count" counter and + * issue a wakeup. + */ + __u64 count; +}; + +/* + * Adds "n" to the eventfd counter "count". Returns "n" in case of + * success, or a value lower then "n" in case of coutner overflow. + * This function is supposed to be called by the kernel in paths + * that do not allow sleeping. In this function we allow the counter + * to reach the ULLONG_MAX value, and we signal this as overflow + * condition by returining a POLLERR to poll(2). + */ +int eventfd_signal(struct file *file, int n) +{ + struct eventfd_ctx *ctx = file->private_data; + unsigned long flags; + + if (n < 0) + return -EINVAL; + spin_lock_irqsave(&ctx->lock, flags); + if (ULLONG_MAX - ctx->count < n) + n = (int) (ULLONG_MAX - ctx->count); + ctx->count += n; + if (waitqueue_active(&ctx->wqh)) + wake_up_locked(&ctx->wqh); + spin_unlock_irqrestore(&ctx->lock, flags); + + return n; +} + +static int eventfd_release(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + return 0; +} + +static unsigned int eventfd_poll(struct file *file, poll_table *wait) +{ + struct eventfd_ctx *ctx = file->private_data; + unsigned int events = 0; + unsigned long flags; + + poll_wait(file, &ctx->wqh, wait); + + spin_lock_irqsave(&ctx->lock, flags); + if (ctx->count > 0) + events |= POLLIN; + if (ctx->count == ULLONG_MAX) + events |= POLLERR; + if (ULLONG_MAX - 1 > ctx->count) + events |= POLLOUT; + spin_unlock_irqrestore(&ctx->lock, flags); + + return events; +} + +static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct eventfd_ctx *ctx = file->private_data; + ssize_t res; + __u64 ucnt; + DECLARE_WAITQUEUE(wait, current); + + if (count < sizeof(ucnt)) + return -EINVAL; + spin_lock_irq(&ctx->lock); + res = -EAGAIN; + ucnt = ctx->count; + if (ucnt > 0) + res = sizeof(ucnt); + else if (!(file->f_flags & O_NONBLOCK)) { + __add_wait_queue(&ctx->wqh, &wait); + for (res = 0;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (ctx->count > 0) { + ucnt = ctx->count; + res = sizeof(ucnt); + break; + } + if (signal_pending(current)) { + res = -ERESTARTSYS; + break; + } + spin_unlock_irq(&ctx->lock); + schedule(); + spin_lock_irq(&ctx->lock); + } + __remove_wait_queue(&ctx->wqh, &wait); + __set_current_state(TASK_RUNNING); + } + if (res > 0) { + ctx->count = 0; + if (waitqueue_active(&ctx->wqh)) + wake_up_locked(&ctx->wqh); + } + spin_unlock_irq(&ctx->lock); + if (res > 0 && put_user(ucnt, (__u64 __user *) buf)) + return -EFAULT; + + return res; +} + +static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count, + loff_t *ppos) +{ + struct eventfd_ctx *ctx = file->private_data; + ssize_t res; + __u64 ucnt; + DECLARE_WAITQUEUE(wait, current); + + if (count < sizeof(ucnt)) + return -EINVAL; + if (copy_from_user(&ucnt, buf, sizeof(ucnt))) + return -EFAULT; + if (ucnt == ULLONG_MAX) + return -EINVAL; + spin_lock_irq(&ctx->lock); + res = -EAGAIN; + if (ULLONG_MAX - ctx->count > ucnt) + res = sizeof(ucnt); + else if (!(file->f_flags & O_NONBLOCK)) { + __add_wait_queue(&ctx->wqh, &wait); + for (res = 0;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (ULLONG_MAX - ctx->count > ucnt) { + res = sizeof(ucnt); + break; + } + if (signal_pending(current)) { + res = -ERESTARTSYS; + break; + } + spin_unlock_irq(&ctx->lock); + schedule(); + spin_lock_irq(&ctx->lock); + } + __remove_wait_queue(&ctx->wqh, &wait); + __set_current_state(TASK_RUNNING); + } + if (res > 0) { + ctx->count += ucnt; + if (waitqueue_active(&ctx->wqh)) + wake_up_locked(&ctx->wqh); + } + spin_unlock_irq(&ctx->lock); + + return res; +} + +static const struct file_operations eventfd_fops = { + .release = eventfd_release, + .poll = eventfd_poll, + .read = eventfd_read, + .write = eventfd_write, +}; + +struct file *eventfd_fget(int fd) +{ + struct file *file; + + file = fget(fd); + if (!file) + return ERR_PTR(-EBADF); + if (file->f_op != &eventfd_fops) { + fput(file); + return ERR_PTR(-EINVAL); + } + + return file; +} + +asmlinkage long sys_eventfd(unsigned int count) +{ + int error, fd; + struct eventfd_ctx *ctx; + struct file *file; + struct inode *inode; + + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + init_waitqueue_head(&ctx->wqh); + spin_lock_init(&ctx->lock); + ctx->count = count; + + /* + * When we call this, the initialization must be complete, since + * anon_inode_getfd() will install the fd. + */ + error = anon_inode_getfd(&fd, &inode, &file, "[eventfd]", + &eventfd_fops, ctx); + if (!error) + return fd; + + kfree(ctx); + return error; +} + diff --git a/fs/eventpoll.c b/fs/eventpoll.c index b5c7ca584939..1aad34ea61a4 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -11,7 +11,6 @@ * */ -#include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -34,6 +33,7 @@ #include <linux/mount.h> #include <linux/bitops.h> #include <linux/mutex.h> +#include <linux/anon_inodes.h> #include <asm/uaccess.h> #include <asm/system.h> #include <asm/io.h> @@ -41,7 +41,6 @@ #include <asm/atomic.h> #include <asm/semaphore.h> - /* * LOCKING: * There are three level of locking required by epoll : @@ -74,9 +73,6 @@ * a greater scalability. */ - -#define EVENTPOLLFS_MAGIC 0x03111965 /* My birthday should work for this :) */ - #define DEBUG_EPOLL 0 #if DEBUG_EPOLL > 0 @@ -106,7 +102,6 @@ #define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event)) - struct epoll_filefd { struct file *file; int fd; @@ -224,43 +219,6 @@ struct ep_pqueue { struct epitem *epi; }; - - -static void ep_poll_safewake_init(struct poll_safewake *psw); -static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq); -static int ep_getfd(int *efd, struct inode **einode, struct file **efile, - struct eventpoll *ep); -static int ep_alloc(struct eventpoll **pep); -static void ep_free(struct eventpoll *ep); -static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd); -static void ep_use_epitem(struct epitem *epi); -static void ep_release_epitem(struct epitem *epi); -static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, - poll_table *pt); -static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi); -static int ep_insert(struct eventpoll *ep, struct epoll_event *event, - struct file *tfile, int fd); -static int ep_modify(struct eventpoll *ep, struct epitem *epi, - struct epoll_event *event); -static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi); -static int ep_unlink(struct eventpoll *ep, struct epitem *epi); -static int ep_remove(struct eventpoll *ep, struct epitem *epi); -static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key); -static int ep_eventpoll_close(struct inode *inode, struct file *file); -static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait); -static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, - struct epoll_event __user *events, int maxevents); -static int ep_events_transfer(struct eventpoll *ep, - struct epoll_event __user *events, - int maxevents); -static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, - int maxevents, long timeout); -static int eventpollfs_delete_dentry(struct dentry *dentry); -static struct inode *ep_eventpoll_inode(void); -static int eventpollfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data, struct vfsmount *mnt); - /* * This semaphore is used to serialize ep_free() and eventpoll_release_file(). */ @@ -275,37 +233,6 @@ static struct kmem_cache *epi_cache __read_mostly; /* Slab cache used to allocate "struct eppoll_entry" */ static struct kmem_cache *pwq_cache __read_mostly; -/* Virtual fs used to allocate inodes for eventpoll files */ -static struct vfsmount *eventpoll_mnt __read_mostly; - -/* File callbacks that implement the eventpoll file behaviour */ -static const struct file_operations eventpoll_fops = { - .release = ep_eventpoll_close, - .poll = ep_eventpoll_poll -}; - -/* - * This is used to register the virtual file system from where - * eventpoll inodes are allocated. - */ -static struct file_system_type eventpoll_fs_type = { - .name = "eventpollfs", - .get_sb = eventpollfs_get_sb, - .kill_sb = kill_anon_super, -}; - -/* Very basic directory entry operations for the eventpoll virtual file system */ -static struct dentry_operations eventpollfs_dentry_operations = { - .d_delete = eventpollfs_delete_dentry, -}; - - - -/* Fast test to see if the file is an evenpoll file */ -static inline int is_file_epoll(struct file *f) -{ - return f->f_op == &eventpoll_fops; -} /* Setup the structure that is used as key for the rb-tree */ static inline void ep_set_ffd(struct epoll_filefd *ffd, @@ -374,7 +301,6 @@ static void ep_poll_safewake_init(struct poll_safewake *psw) spin_lock_init(&psw->lock); } - /* * Perform a safe wake up of the poll wait list. The problem is that * with the new callback'd wake up system, it is possible that the @@ -429,399 +355,144 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq) spin_unlock_irqrestore(&psw->lock, flags); } - /* - * This is called from eventpoll_release() to unlink files from the eventpoll - * interface. We need to have this facility to cleanup correctly files that are - * closed without being removed from the eventpoll interface. + * This function unregister poll callbacks from the associated file descriptor. + * Since this must be called without holding "ep->lock" the atomic exchange trick + * will protect us from multiple unregister. */ -void eventpoll_release_file(struct file *file) +static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) { - struct list_head *lsthead = &file->f_ep_links; - struct eventpoll *ep; - struct epitem *epi; + int nwait; + struct list_head *lsthead = &epi->pwqlist; + struct eppoll_entry *pwq; - /* - * We don't want to get "file->f_ep_lock" because it is not - * necessary. It is not necessary because we're in the "struct file" - * cleanup path, and this means that noone is using this file anymore. - * The only hit might come from ep_free() but by holding the semaphore - * will correctly serialize the operation. We do need to acquire - * "ep->sem" after "epmutex" because ep_remove() requires it when called - * from anywhere but ep_free(). - */ - mutex_lock(&epmutex); + /* This is called without locks, so we need the atomic exchange */ + nwait = xchg(&epi->nwait, 0); - while (!list_empty(lsthead)) { - epi = list_first_entry(lsthead, struct epitem, fllink); + if (nwait) { + while (!list_empty(lsthead)) { + pwq = list_first_entry(lsthead, struct eppoll_entry, llink); - ep = epi->ep; - list_del_init(&epi->fllink); - down_write(&ep->sem); - ep_remove(ep, epi); - up_write(&ep->sem); + list_del_init(&pwq->llink); + remove_wait_queue(pwq->whead, &pwq->wait); + kmem_cache_free(pwq_cache, pwq); + } } - - mutex_unlock(&epmutex); } - /* - * It opens an eventpoll file descriptor by suggesting a storage of "size" - * file descriptors. The size parameter is just an hint about how to size - * data structures. It won't prevent the user to store more than "size" - * file descriptors inside the epoll interface. It is the kernel part of - * the userspace epoll_create(2). + * Unlink the "struct epitem" from all places it might have been hooked up. + * This function must be called with write IRQ lock on "ep->lock". */ -asmlinkage long sys_epoll_create(int size) +static int ep_unlink(struct eventpoll *ep, struct epitem *epi) { - int error, fd = -1; - struct eventpoll *ep; - struct inode *inode; - struct file *file; - - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n", - current, size)); - - /* - * Sanity check on the size parameter, and create the internal data - * structure ( "struct eventpoll" ). - */ - error = -EINVAL; - if (size <= 0 || (error = ep_alloc(&ep)) != 0) - goto eexit_1; + int error; /* - * Creates all the items needed to setup an eventpoll file. That is, - * a file structure, and inode and a free file descriptor. + * It can happen that this one is called for an item already unlinked. + * The check protect us from doing a double unlink ( crash ). */ - error = ep_getfd(&fd, &inode, &file, ep); - if (error) - goto eexit_2; - - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", - current, size, fd)); - - return fd; - -eexit_2: - ep_free(ep); - kfree(ep); -eexit_1: - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", - current, size, error)); - return error; -} - - -/* - * The following function implements the controller interface for - * the eventpoll file that enables the insertion/removal/change of - * file descriptors inside the interest set. It represents - * the kernel part of the user space epoll_ctl(2). - */ -asmlinkage long -sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event) -{ - int error; - struct file *file, *tfile; - struct eventpoll *ep; - struct epitem *epi; - struct epoll_event epds; - - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)\n", - current, epfd, op, fd, event)); - - error = -EFAULT; - if (ep_op_has_event(op) && - copy_from_user(&epds, event, sizeof(struct epoll_event))) - goto eexit_1; - - /* Get the "struct file *" for the eventpoll file */ - error = -EBADF; - file = fget(epfd); - if (!file) - goto eexit_1; - - /* Get the "struct file *" for the target file */ - tfile = fget(fd); - if (!tfile) - goto eexit_2; - - /* The target file descriptor must support poll */ - error = -EPERM; - if (!tfile->f_op || !tfile->f_op->poll) - goto eexit_3; + error = -ENOENT; + if (!ep_rb_linked(&epi->rbn)) + goto error_return; /* - * We have to check that the file structure underneath the file descriptor - * the user passed to us _is_ an eventpoll file. And also we do not permit - * adding an epoll file descriptor inside itself. + * Clear the event mask for the unlinked item. This will avoid item + * notifications to be sent after the unlink operation from inside + * the kernel->userspace event transfer loop. */ - error = -EINVAL; - if (file == tfile || !is_file_epoll(file)) - goto eexit_3; + epi->event.events = 0; /* - * At this point it is safe to assume that the "private_data" contains - * our own data structure. + * At this point is safe to do the job, unlink the item from our rb-tree. + * This operation togheter with the above check closes the door to + * double unlinks. */ - ep = file->private_data; - - down_write(&ep->sem); - - /* Try to lookup the file inside our RB tree */ - epi = ep_find(ep, tfile, fd); - - error = -EINVAL; - switch (op) { - case EPOLL_CTL_ADD: - if (!epi) { - epds.events |= POLLERR | POLLHUP; - - error = ep_insert(ep, &epds, tfile, fd); - } else - error = -EEXIST; - break; - case EPOLL_CTL_DEL: - if (epi) - error = ep_remove(ep, epi); - else - error = -ENOENT; - break; - case EPOLL_CTL_MOD: - if (epi) { - epds.events |= POLLERR | POLLHUP; - error = ep_modify(ep, epi, &epds); - } else - error = -ENOENT; - break; - } + ep_rb_erase(&epi->rbn, &ep->rbr); /* - * The function ep_find() increments the usage count of the structure - * so, if this is not NULL, we need to release it. + * If the item we are going to remove is inside the ready file descriptors + * we want to remove it from this list to avoid stale events. */ - if (epi) - ep_release_epitem(epi); + if (ep_is_linked(&epi->rdllink)) + list_del_init(&epi->rdllink); - up_write(&ep->sem); + error = 0; +error_return: -eexit_3: - fput(tfile); -eexit_2: - fput(file); -eexit_1: - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p) = %d\n", - current, epfd, op, fd, event, error)); + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %p) = %d\n", + current, ep, epi->ffd.file, error)); return error; } - /* - * Implement the event wait interface for the eventpoll file. It is the kernel - * part of the user space epoll_wait(2). + * Increment the usage count of the "struct epitem" making it sure + * that the user will have a valid pointer to reference. */ -asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, - int maxevents, int timeout) +static void ep_use_epitem(struct epitem *epi) { - int error; - struct file *file; - struct eventpoll *ep; - - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d)\n", - current, epfd, events, maxevents, timeout)); - - /* The maximum number of event must be greater than zero */ - if (maxevents <= 0 || maxevents > EP_MAX_EVENTS) - return -EINVAL; - - /* Verify that the area passed by the user is writeable */ - if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event))) { - error = -EFAULT; - goto eexit_1; - } - - /* Get the "struct file *" for the eventpoll file */ - error = -EBADF; - file = fget(epfd); - if (!file) - goto eexit_1; - - /* - * We have to check that the file structure underneath the fd - * the user passed to us _is_ an eventpoll file. - */ - error = -EINVAL; - if (!is_file_epoll(file)) - goto eexit_2; - - /* - * At this point it is safe to assume that the "private_data" contains - * our own data structure. - */ - ep = file->private_data; - - /* Time to fish for events ... */ - error = ep_poll(ep, events, maxevents, timeout); - -eexit_2: - fput(file); -eexit_1: - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d) = %d\n", - current, epfd, events, maxevents, timeout, error)); - - return error; + atomic_inc(&epi->usecnt); } - -#ifdef TIF_RESTORE_SIGMASK - /* - * Implement the event wait interface for the eventpoll file. It is the kernel - * part of the user space epoll_pwait(2). + * Decrement ( release ) the usage count by signaling that the user + * has finished using the structure. It might lead to freeing the + * structure itself if the count goes to zero. */ -asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, - int maxevents, int timeout, const sigset_t __user *sigmask, - size_t sigsetsize) +static void ep_release_epitem(struct epitem *epi) { - int error; - sigset_t ksigmask, sigsaved; - - /* - * If the caller wants a certain signal mask to be set during the wait, - * we apply it here. - */ - if (sigmask) { - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask))) - return -EFAULT; - sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); - sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); - } - - error = sys_epoll_wait(epfd, events, maxevents, timeout); - - /* - * If we changed the signal mask, we need to restore the original one. - * In case we've got a signal while waiting, we do not restore the - * signal mask yet, and we allow do_signal() to deliver the signal on - * the way back to userspace, before the signal mask is restored. - */ - if (sigmask) { - if (error == -EINTR) { - memcpy(¤t->saved_sigmask, &sigsaved, - sizeof(sigsaved)); - set_thread_flag(TIF_RESTORE_SIGMASK); - } else - sigprocmask(SIG_SETMASK, &sigsaved, NULL); - } - - return error; + if (atomic_dec_and_test(&epi->usecnt)) + kmem_cache_free(epi_cache, epi); } -#endif /* #ifdef TIF_RESTORE_SIGMASK */ - - /* - * Creates the file descriptor to be used by the epoll interface. + * Removes a "struct epitem" from the eventpoll RB tree and deallocates + * all the associated resources. */ -static int ep_getfd(int *efd, struct inode **einode, struct file **efile, - struct eventpoll *ep) +static int ep_remove(struct eventpoll *ep, struct epitem *epi) { - struct qstr this; - char name[32]; - struct dentry *dentry; - struct inode *inode; - struct file *file; - int error, fd; - - /* Get an ready to use file */ - error = -ENFILE; - file = get_empty_filp(); - if (!file) - goto eexit_1; - - /* Allocates an inode from the eventpoll file system */ - inode = ep_eventpoll_inode(); - if (IS_ERR(inode)) { - error = PTR_ERR(inode); - goto eexit_2; - } - - /* Allocates a free descriptor to plug the file onto */ - error = get_unused_fd(); - if (error < 0) - goto eexit_3; - fd = error; + int error; + unsigned long flags; + struct file *file = epi->ffd.file; /* - * Link the inode to a directory entry by creating a unique name - * using the inode number. + * Removes poll wait queue hooks. We _have_ to do this without holding + * the "ep->lock" otherwise a deadlock might occur. This because of the + * sequence of the lock acquisition. Here we do "ep->lock" then the wait + * queue head lock when unregistering the wait queue. The wakeup callback + * will run by holding the wait queue head lock and will call our callback + * that will try to get "ep->lock". */ - error = -ENOMEM; - sprintf(name, "[%lu]", inode->i_ino); - this.name = name; - this.len = strlen(name); - this.hash = inode->i_ino; - dentry = d_alloc(eventpoll_mnt->mnt_sb->s_root, &this); - if (!dentry) - goto eexit_4; - dentry->d_op = &eventpollfs_dentry_operations; - d_add(dentry, inode); - file->f_path.mnt = mntget(eventpoll_mnt); - file->f_path.dentry = dentry; - file->f_mapping = inode->i_mapping; - - file->f_pos = 0; - file->f_flags = O_RDONLY; - file->f_op = &eventpoll_fops; - file->f_mode = FMODE_READ; - file->f_version = 0; - file->private_data = ep; - - /* Install the new setup file into the allocated fd. */ - fd_install(fd, file); - - *efd = fd; - *einode = inode; - *efile = file; - return 0; + ep_unregister_pollwait(ep, epi); -eexit_4: - put_unused_fd(fd); -eexit_3: - iput(inode); -eexit_2: - put_filp(file); -eexit_1: - return error; -} + /* Remove the current item from the list of epoll hooks */ + spin_lock(&file->f_ep_lock); + if (ep_is_linked(&epi->fllink)) + list_del_init(&epi->fllink); + spin_unlock(&file->f_ep_lock); + /* We need to acquire the write IRQ lock before calling ep_unlink() */ + write_lock_irqsave(&ep->lock, flags); -static int ep_alloc(struct eventpoll **pep) -{ - struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL); + /* Really unlink the item from the RB tree */ + error = ep_unlink(ep, epi); - if (!ep) - return -ENOMEM; + write_unlock_irqrestore(&ep->lock, flags); - rwlock_init(&ep->lock); - init_rwsem(&ep->sem); - init_waitqueue_head(&ep->wq); - init_waitqueue_head(&ep->poll_wait); - INIT_LIST_HEAD(&ep->rdllist); - ep->rbr = RB_ROOT; + if (error) + goto error_return; - *pep = ep; + /* At this point it is safe to free the eventpoll item */ + ep_release_epitem(epi); - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n", - current, ep)); - return 0; -} + error = 0; +error_return: + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p) = %d\n", + current, ep, file, error)); + return error; +} static void ep_free(struct eventpoll *ep) { @@ -865,6 +536,104 @@ static void ep_free(struct eventpoll *ep) mutex_unlock(&epmutex); } +static int ep_eventpoll_release(struct inode *inode, struct file *file) +{ + struct eventpoll *ep = file->private_data; + + if (ep) { + ep_free(ep); + kfree(ep); + } + + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: close() ep=%p\n", current, ep)); + return 0; +} + +static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) +{ + unsigned int pollflags = 0; + unsigned long flags; + struct eventpoll *ep = file->private_data; + + /* Insert inside our poll wait queue */ + poll_wait(file, &ep->poll_wait, wait); + + /* Check our condition */ + read_lock_irqsave(&ep->lock, flags); + if (!list_empty(&ep->rdllist)) + pollflags = POLLIN | POLLRDNORM; + read_unlock_irqrestore(&ep->lock, flags); + + return pollflags; +} + +/* File callbacks that implement the eventpoll file behaviour */ +static const struct file_operations eventpoll_fops = { + .release = ep_eventpoll_release, + .poll = ep_eventpoll_poll +}; + +/* Fast test to see if the file is an evenpoll file */ +static inline int is_file_epoll(struct file *f) +{ + return f->f_op == &eventpoll_fops; +} + +/* + * This is called from eventpoll_release() to unlink files from the eventpoll + * interface. We need to have this facility to cleanup correctly files that are + * closed without being removed from the eventpoll interface. + */ +void eventpoll_release_file(struct file *file) +{ + struct list_head *lsthead = &file->f_ep_links; + struct eventpoll *ep; + struct epitem *epi; + + /* + * We don't want to get "file->f_ep_lock" because it is not + * necessary. It is not necessary because we're in the "struct file" + * cleanup path, and this means that noone is using this file anymore. + * The only hit might come from ep_free() but by holding the semaphore + * will correctly serialize the operation. We do need to acquire + * "ep->sem" after "epmutex" because ep_remove() requires it when called + * from anywhere but ep_free(). + */ + mutex_lock(&epmutex); + + while (!list_empty(lsthead)) { + epi = list_first_entry(lsthead, struct epitem, fllink); + + ep = epi->ep; + list_del_init(&epi->fllink); + down_write(&ep->sem); + ep_remove(ep, epi); + up_write(&ep->sem); + } + + mutex_unlock(&epmutex); +} + +static int ep_alloc(struct eventpoll **pep) +{ + struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL); + + if (!ep) + return -ENOMEM; + + rwlock_init(&ep->lock); + init_rwsem(&ep->sem); + init_waitqueue_head(&ep->wq); + init_waitqueue_head(&ep->poll_wait); + INIT_LIST_HEAD(&ep->rdllist); + ep->rbr = RB_ROOT; + + *pep = ep; + + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n", + current, ep)); + return 0; +} /* * Search the file inside the eventpoll tree. It add usage count to @@ -902,30 +671,58 @@ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd) return epir; } - /* - * Increment the usage count of the "struct epitem" making it sure - * that the user will have a valid pointer to reference. + * This is the callback that is passed to the wait queue wakeup + * machanism. It is called by the stored file descriptors when they + * have events to report. */ -static void ep_use_epitem(struct epitem *epi) +static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key) { + int pwake = 0; + unsigned long flags; + struct epitem *epi = ep_item_from_wait(wait); + struct eventpoll *ep = epi->ep; - atomic_inc(&epi->usecnt); -} + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n", + current, epi->ffd.file, epi, ep)); + write_lock_irqsave(&ep->lock, flags); -/* - * Decrement ( release ) the usage count by signaling that the user - * has finished using the structure. It might lead to freeing the - * structure itself if the count goes to zero. - */ -static void ep_release_epitem(struct epitem *epi) -{ + /* + * If the event mask does not contain any poll(2) event, we consider the + * descriptor to be disabled. This condition is likely the effect of the + * EPOLLONESHOT bit that disables the descriptor when an event is received, + * until the next EPOLL_CTL_MOD will be issued. + */ + if (!(epi->event.events & ~EP_PRIVATE_BITS)) + goto is_disabled; - if (atomic_dec_and_test(&epi->usecnt)) - kmem_cache_free(epi_cache, epi); -} + /* If this file is already in the ready list we exit soon */ + if (ep_is_linked(&epi->rdllink)) + goto is_linked; + list_add_tail(&epi->rdllink, &ep->rdllist); + +is_linked: + /* + * Wake up ( if active ) both the eventpoll wait list and the ->poll() + * wait list. + */ + if (waitqueue_active(&ep->wq)) + __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | + TASK_INTERRUPTIBLE); + if (waitqueue_active(&ep->poll_wait)) + pwake++; + +is_disabled: + write_unlock_irqrestore(&ep->lock, flags); + + /* We have to call this outside the lock */ + if (pwake) + ep_poll_safewake(&psw, &ep->poll_wait); + + return 1; +} /* * This is the callback that is used to add our wait queue to the @@ -950,7 +747,6 @@ static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, } } - static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) { int kcmp; @@ -970,7 +766,6 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) rb_insert_color(&epi->rbn, &ep->rbr); } - static int ep_insert(struct eventpoll *ep, struct epoll_event *event, struct file *tfile, int fd) { @@ -981,7 +776,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, error = -ENOMEM; if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL))) - goto eexit_1; + goto error_return; /* Item initialization follow here ... */ ep_rb_initnode(&epi->rbn); @@ -1011,7 +806,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, * high memory pressure. */ if (epi->nwait < 0) - goto eexit_2; + goto error_unregister; /* Add the current item to the list of active epoll hook for this file */ spin_lock(&tfile->f_ep_lock); @@ -1046,7 +841,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, return 0; -eexit_2: +error_unregister: ep_unregister_pollwait(ep, epi); /* @@ -1059,11 +854,10 @@ eexit_2: write_unlock_irqrestore(&ep->lock, flags); kmem_cache_free(epi_cache, epi); -eexit_1: +error_return: return error; } - /* * Modify the interest event mask by dropping an event if the new mask * has a match in the current file status. @@ -1126,216 +920,6 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even return 0; } - -/* - * This function unregister poll callbacks from the associated file descriptor. - * Since this must be called without holding "ep->lock" the atomic exchange trick - * will protect us from multiple unregister. - */ -static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) -{ - int nwait; - struct list_head *lsthead = &epi->pwqlist; - struct eppoll_entry *pwq; - - /* This is called without locks, so we need the atomic exchange */ - nwait = xchg(&epi->nwait, 0); - - if (nwait) { - while (!list_empty(lsthead)) { - pwq = list_first_entry(lsthead, struct eppoll_entry, llink); - - list_del_init(&pwq->llink); - remove_wait_queue(pwq->whead, &pwq->wait); - kmem_cache_free(pwq_cache, pwq); - } - } -} - - -/* - * Unlink the "struct epitem" from all places it might have been hooked up. - * This function must be called with write IRQ lock on "ep->lock". - */ -static int ep_unlink(struct eventpoll *ep, struct epitem *epi) -{ - int error; - - /* - * It can happen that this one is called for an item already unlinked. - * The check protect us from doing a double unlink ( crash ). - */ - error = -ENOENT; - if (!ep_rb_linked(&epi->rbn)) - goto eexit_1; - - /* - * Clear the event mask for the unlinked item. This will avoid item - * notifications to be sent after the unlink operation from inside - * the kernel->userspace event transfer loop. - */ - epi->event.events = 0; - - /* - * At this point is safe to do the job, unlink the item from our rb-tree. - * This operation togheter with the above check closes the door to - * double unlinks. - */ - ep_rb_erase(&epi->rbn, &ep->rbr); - - /* - * If the item we are going to remove is inside the ready file descriptors - * we want to remove it from this list to avoid stale events. - */ - if (ep_is_linked(&epi->rdllink)) - list_del_init(&epi->rdllink); - - error = 0; -eexit_1: - - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %p) = %d\n", - current, ep, epi->ffd.file, error)); - - return error; -} - - -/* - * Removes a "struct epitem" from the eventpoll RB tree and deallocates - * all the associated resources. - */ -static int ep_remove(struct eventpoll *ep, struct epitem *epi) -{ - int error; - unsigned long flags; - struct file *file = epi->ffd.file; - - /* - * Removes poll wait queue hooks. We _have_ to do this without holding - * the "ep->lock" otherwise a deadlock might occur. This because of the - * sequence of the lock acquisition. Here we do "ep->lock" then the wait - * queue head lock when unregistering the wait queue. The wakeup callback - * will run by holding the wait queue head lock and will call our callback - * that will try to get "ep->lock". - */ - ep_unregister_pollwait(ep, epi); - - /* Remove the current item from the list of epoll hooks */ - spin_lock(&file->f_ep_lock); - if (ep_is_linked(&epi->fllink)) - list_del_init(&epi->fllink); - spin_unlock(&file->f_ep_lock); - - /* We need to acquire the write IRQ lock before calling ep_unlink() */ - write_lock_irqsave(&ep->lock, flags); - - /* Really unlink the item from the RB tree */ - error = ep_unlink(ep, epi); - - write_unlock_irqrestore(&ep->lock, flags); - - if (error) - goto eexit_1; - - /* At this point it is safe to free the eventpoll item */ - ep_release_epitem(epi); - - error = 0; -eexit_1: - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p) = %d\n", - current, ep, file, error)); - - return error; -} - - -/* - * This is the callback that is passed to the wait queue wakeup - * machanism. It is called by the stored file descriptors when they - * have events to report. - */ -static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key) -{ - int pwake = 0; - unsigned long flags; - struct epitem *epi = ep_item_from_wait(wait); - struct eventpoll *ep = epi->ep; - - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n", - current, epi->ffd.file, epi, ep)); - - write_lock_irqsave(&ep->lock, flags); - - /* - * If the event mask does not contain any poll(2) event, we consider the - * descriptor to be disabled. This condition is likely the effect of the - * EPOLLONESHOT bit that disables the descriptor when an event is received, - * until the next EPOLL_CTL_MOD will be issued. - */ - if (!(epi->event.events & ~EP_PRIVATE_BITS)) - goto is_disabled; - - /* If this file is already in the ready list we exit soon */ - if (ep_is_linked(&epi->rdllink)) - goto is_linked; - - list_add_tail(&epi->rdllink, &ep->rdllist); - -is_linked: - /* - * Wake up ( if active ) both the eventpoll wait list and the ->poll() - * wait list. - */ - if (waitqueue_active(&ep->wq)) - __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | - TASK_INTERRUPTIBLE); - if (waitqueue_active(&ep->poll_wait)) - pwake++; - -is_disabled: - write_unlock_irqrestore(&ep->lock, flags); - - /* We have to call this outside the lock */ - if (pwake) - ep_poll_safewake(&psw, &ep->poll_wait); - - return 1; -} - - -static int ep_eventpoll_close(struct inode *inode, struct file *file) -{ - struct eventpoll *ep = file->private_data; - - if (ep) { - ep_free(ep); - kfree(ep); - } - - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: close() ep=%p\n", current, ep)); - return 0; -} - - -static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) -{ - unsigned int pollflags = 0; - unsigned long flags; - struct eventpoll *ep = file->private_data; - - /* Insert inside our poll wait queue */ - poll_wait(file, &ep->poll_wait, wait); - - /* Check our condition */ - read_lock_irqsave(&ep->lock, flags); - if (!list_empty(&ep->rdllist)) - pollflags = POLLIN | POLLRDNORM; - read_unlock_irqrestore(&ep->lock, flags); - - return pollflags; -} - - /* * This function is called without holding the "ep->lock" since the call to * __copy_to_user() might sleep, and also f_op->poll() might reenable the IRQ @@ -1447,7 +1031,6 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, return eventcnt == 0 ? error: eventcnt; } - /* * Perform the transfer of events to user space. */ @@ -1483,7 +1066,6 @@ static int ep_events_transfer(struct eventpoll *ep, return eventcnt; } - static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, int maxevents, long timeout) { @@ -1553,52 +1135,262 @@ retry: return res; } -static int eventpollfs_delete_dentry(struct dentry *dentry) +/* + * It opens an eventpoll file descriptor by suggesting a storage of "size" + * file descriptors. The size parameter is just an hint about how to size + * data structures. It won't prevent the user to store more than "size" + * file descriptors inside the epoll interface. It is the kernel part of + * the userspace epoll_create(2). + */ +asmlinkage long sys_epoll_create(int size) { + int error, fd = -1; + struct eventpoll *ep; + struct inode *inode; + struct file *file; - return 1; + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n", + current, size)); + + /* + * Sanity check on the size parameter, and create the internal data + * structure ( "struct eventpoll" ). + */ + error = -EINVAL; + if (size <= 0 || (error = ep_alloc(&ep)) != 0) + goto error_return; + + /* + * Creates all the items needed to setup an eventpoll file. That is, + * a file structure, and inode and a free file descriptor. + */ + error = anon_inode_getfd(&fd, &inode, &file, "[eventpoll]", + &eventpoll_fops, ep); + if (error) + goto error_free; + + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", + current, size, fd)); + + return fd; + +error_free: + ep_free(ep); + kfree(ep); +error_return: + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", + current, size, error)); + return error; } -static struct inode *ep_eventpoll_inode(void) +/* + * The following function implements the controller interface for + * the eventpoll file that enables the insertion/removal/change of + * file descriptors inside the interest set. It represents + * the kernel part of the user space epoll_ctl(2). + */ +asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, + struct epoll_event __user *event) { - int error = -ENOMEM; - struct inode *inode = new_inode(eventpoll_mnt->mnt_sb); + int error; + struct file *file, *tfile; + struct eventpoll *ep; + struct epitem *epi; + struct epoll_event epds; + + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)\n", + current, epfd, op, fd, event)); + + error = -EFAULT; + if (ep_op_has_event(op) && + copy_from_user(&epds, event, sizeof(struct epoll_event))) + goto error_return; + + /* Get the "struct file *" for the eventpoll file */ + error = -EBADF; + file = fget(epfd); + if (!file) + goto error_return; + + /* Get the "struct file *" for the target file */ + tfile = fget(fd); + if (!tfile) + goto error_fput; + + /* The target file descriptor must support poll */ + error = -EPERM; + if (!tfile->f_op || !tfile->f_op->poll) + goto error_tgt_fput; + + /* + * We have to check that the file structure underneath the file descriptor + * the user passed to us _is_ an eventpoll file. And also we do not permit + * adding an epoll file descriptor inside itself. + */ + error = -EINVAL; + if (file == tfile || !is_file_epoll(file)) + goto error_tgt_fput; - if (!inode) - goto eexit_1; + /* + * At this point it is safe to assume that the "private_data" contains + * our own data structure. + */ + ep = file->private_data; + + down_write(&ep->sem); - inode->i_fop = &eventpoll_fops; + /* Try to lookup the file inside our RB tree */ + epi = ep_find(ep, tfile, fd); + + error = -EINVAL; + switch (op) { + case EPOLL_CTL_ADD: + if (!epi) { + epds.events |= POLLERR | POLLHUP; + error = ep_insert(ep, &epds, tfile, fd); + } else + error = -EEXIST; + break; + case EPOLL_CTL_DEL: + if (epi) + error = ep_remove(ep, epi); + else + error = -ENOENT; + break; + case EPOLL_CTL_MOD: + if (epi) { + epds.events |= POLLERR | POLLHUP; + error = ep_modify(ep, epi, &epds); + } else + error = -ENOENT; + break; + } /* - * Mark the inode dirty from the very beginning, - * that way it will never be moved to the dirty - * list because mark_inode_dirty() will think - * that it already _is_ on the dirty list. + * The function ep_find() increments the usage count of the structure + * so, if this is not NULL, we need to release it. */ - inode->i_state = I_DIRTY; - inode->i_mode = S_IRUSR | S_IWUSR; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - return inode; - -eexit_1: - return ERR_PTR(error); + if (epi) + ep_release_epitem(epi); + up_write(&ep->sem); + +error_tgt_fput: + fput(tfile); +error_fput: + fput(file); +error_return: + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p) = %d\n", + current, epfd, op, fd, event, error)); + + return error; } -static int -eventpollfs_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data, struct vfsmount *mnt) +/* + * Implement the event wait interface for the eventpoll file. It is the kernel + * part of the user space epoll_wait(2). + */ +asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, + int maxevents, int timeout) { - return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC, - mnt); + int error; + struct file *file; + struct eventpoll *ep; + + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d)\n", + current, epfd, events, maxevents, timeout)); + + /* The maximum number of event must be greater than zero */ + if (maxevents <= 0 || maxevents > EP_MAX_EVENTS) + return -EINVAL; + + /* Verify that the area passed by the user is writeable */ + if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event))) { + error = -EFAULT; + goto error_return; + } + + /* Get the "struct file *" for the eventpoll file */ + error = -EBADF; + file = fget(epfd); + if (!file) + goto error_return; + + /* + * We have to check that the file structure underneath the fd + * the user passed to us _is_ an eventpoll file. + */ + error = -EINVAL; + if (!is_file_epoll(file)) + goto error_fput; + + /* + * At this point it is safe to assume that the "private_data" contains + * our own data structure. + */ + ep = file->private_data; + + /* Time to fish for events ... */ + error = ep_poll(ep, events, maxevents, timeout); + +error_fput: + fput(file); +error_return: + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d) = %d\n", + current, epfd, events, maxevents, timeout, error)); + + return error; } +#ifdef TIF_RESTORE_SIGMASK -static int __init eventpoll_init(void) +/* + * Implement the event wait interface for the eventpoll file. It is the kernel + * part of the user space epoll_pwait(2). + */ +asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, + int maxevents, int timeout, const sigset_t __user *sigmask, + size_t sigsetsize) { int error; + sigset_t ksigmask, sigsaved; + + /* + * If the caller wants a certain signal mask to be set during the wait, + * we apply it here. + */ + if (sigmask) { + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask))) + return -EFAULT; + sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); + sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); + } + + error = sys_epoll_wait(epfd, events, maxevents, timeout); + + /* + * If we changed the signal mask, we need to restore the original one. + * In case we've got a signal while waiting, we do not restore the + * signal mask yet, and we allow do_signal() to deliver the signal on + * the way back to userspace, before the signal mask is restored. + */ + if (sigmask) { + if (error == -EINTR) { + memcpy(¤t->saved_sigmask, &sigsaved, + sizeof(sigsaved)); + set_thread_flag(TIF_RESTORE_SIGMASK); + } else + sigprocmask(SIG_SETMASK, &sigsaved, NULL); + } + + return error; +} +#endif /* #ifdef TIF_RESTORE_SIGMASK */ + +static int __init eventpoll_init(void) +{ mutex_init(&epmutex); /* Initialize the structure used to perform safe poll wait head wake ups */ @@ -1614,39 +1406,7 @@ static int __init eventpoll_init(void) sizeof(struct eppoll_entry), 0, EPI_SLAB_DEBUG|SLAB_PANIC, NULL, NULL); - /* - * Register the virtual file system that will be the source of inodes - * for the eventpoll files - */ - error = register_filesystem(&eventpoll_fs_type); - if (error) - goto epanic; - - /* Mount the above commented virtual file system */ - eventpoll_mnt = kern_mount(&eventpoll_fs_type); - error = PTR_ERR(eventpoll_mnt); - if (IS_ERR(eventpoll_mnt)) - goto epanic; - - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: successfully initialized.\n", - current)); return 0; - -epanic: - panic("eventpoll_init() failed\n"); } +fs_initcall(eventpoll_init); - -static void __exit eventpoll_exit(void) -{ - /* Undo all operations done inside eventpoll_init() */ - unregister_filesystem(&eventpoll_fs_type); - mntput(eventpoll_mnt); - kmem_cache_destroy(pwq_cache); - kmem_cache_destroy(epi_cache); -} - -module_init(eventpoll_init); -module_exit(eventpoll_exit); - -MODULE_LICENSE("GPL"); diff --git a/fs/exec.c b/fs/exec.c index 1ba85c7fc6af..70fa36554c14 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -50,6 +50,7 @@ #include <linux/tsacct_kern.h> #include <linux/cn_proc.h> #include <linux/audit.h> +#include <linux/signalfd.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -582,6 +583,13 @@ static int de_thread(struct task_struct *tsk) int count; /* + * Tell all the sighand listeners that this sighand has + * been detached. The signalfd_detach() function grabs the + * sighand lock, if signal listeners are present on the sighand. + */ + signalfd_detach(tsk); + + /* * If we don't share sighandlers, then we aren't sharing anything * and we can just re-use it all. */ @@ -702,7 +710,7 @@ static int de_thread(struct task_struct *tsk) */ detach_pid(tsk, PIDTYPE_PID); tsk->pid = leader->pid; - attach_pid(tsk, PIDTYPE_PID, tsk->pid); + attach_pid(tsk, PIDTYPE_PID, find_pid(tsk->pid)); transfer_pid(leader, tsk, PIDTYPE_PGID); transfer_pid(leader, tsk, PIDTYPE_SID); list_replace_rcu(&leader->tasks, &tsk->tasks); @@ -757,8 +765,7 @@ no_thread_group: spin_unlock(&oldsighand->siglock); write_unlock_irq(&tasklist_lock); - if (atomic_dec_and_test(&oldsighand->count)) - kmem_cache_free(sighand_cachep, oldsighand); + __cleanup_sighand(oldsighand); } BUG_ON(!thread_group_leader(tsk)); @@ -1488,6 +1495,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) int flag = 0; int ispipe = 0; + audit_core_dumps(signr); + binfmt = current->binfmt; if (!binfmt || !binfmt->core_dump) goto fail; diff --git a/fs/mpage.c b/fs/mpage.c index 0fb914fc2ee0..c1698f2291aa 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -454,11 +454,18 @@ EXPORT_SYMBOL(mpage_readpage); * written, so it can intelligently allocate a suitably-sized BIO. For now, * just allocate full-size (16-page) BIOs. */ -static struct bio * -__mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, - sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc, - writepage_t writepage_fn) +struct mpage_data { + struct bio *bio; + sector_t last_block_in_bio; + get_block_t *get_block; + unsigned use_writepage; +}; + +static int __mpage_writepage(struct page *page, struct writeback_control *wbc, + void *data) { + struct mpage_data *mpd = data; + struct bio *bio = mpd->bio; struct address_space *mapping = page->mapping; struct inode *inode = page->mapping->host; const unsigned blkbits = inode->i_blkbits; @@ -476,6 +483,7 @@ __mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, int length; struct buffer_head map_bh; loff_t i_size = i_size_read(inode); + int ret = 0; if (page_has_buffers(page)) { struct buffer_head *head = page_buffers(page); @@ -538,7 +546,7 @@ __mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, map_bh.b_state = 0; map_bh.b_size = 1 << blkbits; - if (get_block(inode, block_in_file, &map_bh, 1)) + if (mpd->get_block(inode, block_in_file, &map_bh, 1)) goto confused; if (buffer_new(&map_bh)) unmap_underlying_metadata(map_bh.b_bdev, @@ -584,7 +592,7 @@ page_is_mapped: /* * This page will go to BIO. Do we need to send this BIO off first? */ - if (bio && *last_block_in_bio != blocks[0] - 1) + if (bio && mpd->last_block_in_bio != blocks[0] - 1) bio = mpage_bio_submit(WRITE, bio); alloc_new: @@ -641,7 +649,7 @@ alloc_new: boundary_block, 1 << blkbits); } } else { - *last_block_in_bio = blocks[blocks_per_page - 1]; + mpd->last_block_in_bio = blocks[blocks_per_page - 1]; } goto out; @@ -649,18 +657,19 @@ confused: if (bio) bio = mpage_bio_submit(WRITE, bio); - if (writepage_fn) { - *ret = (*writepage_fn)(page, wbc); + if (mpd->use_writepage) { + ret = mapping->a_ops->writepage(page, wbc); } else { - *ret = -EAGAIN; + ret = -EAGAIN; goto out; } /* * The caller has a ref on the inode, so *mapping is stable */ - mapping_set_error(mapping, *ret); + mapping_set_error(mapping, ret); out: - return bio; + mpd->bio = bio; + return ret; } /** @@ -683,120 +692,27 @@ out: * the call was made get new I/O started against them. If wbc->sync_mode is * WB_SYNC_ALL then we were called for data integrity and we must wait for * existing IO to complete. - * - * If you fix this you should check generic_writepages() also! */ int mpage_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block) { - struct backing_dev_info *bdi = mapping->backing_dev_info; - struct bio *bio = NULL; - sector_t last_block_in_bio = 0; - int ret = 0; - int done = 0; - int (*writepage)(struct page *page, struct writeback_control *wbc); - struct pagevec pvec; - int nr_pages; - pgoff_t index; - pgoff_t end; /* Inclusive */ - int scanned = 0; - int range_whole = 0; - - if (wbc->nonblocking && bdi_write_congested(bdi)) { - wbc->encountered_congestion = 1; - return 0; - } - - writepage = NULL; - if (get_block == NULL) - writepage = mapping->a_ops->writepage; - - pagevec_init(&pvec, 0); - if (wbc->range_cyclic) { - index = mapping->writeback_index; /* Start from prev offset */ - end = -1; - } else { - index = wbc->range_start >> PAGE_CACHE_SHIFT; - end = wbc->range_end >> PAGE_CACHE_SHIFT; - if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) - range_whole = 1; - scanned = 1; + int ret; + + if (!get_block) + ret = generic_writepages(mapping, wbc); + else { + struct mpage_data mpd = { + .bio = NULL, + .last_block_in_bio = 0, + .get_block = get_block, + .use_writepage = 1, + }; + + ret = write_cache_pages(mapping, wbc, __mpage_writepage, &mpd); + if (mpd.bio) + mpage_bio_submit(WRITE, mpd.bio); } -retry: - while (!done && (index <= end) && - (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, - PAGECACHE_TAG_DIRTY, - min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) { - unsigned i; - - scanned = 1; - for (i = 0; i < nr_pages; i++) { - struct page *page = pvec.pages[i]; - - /* - * At this point we hold neither mapping->tree_lock nor - * lock on the page itself: the page may be truncated or - * invalidated (changing page->mapping to NULL), or even - * swizzled back from swapper_space to tmpfs file - * mapping - */ - - lock_page(page); - - if (unlikely(page->mapping != mapping)) { - unlock_page(page); - continue; - } - - if (!wbc->range_cyclic && page->index > end) { - done = 1; - unlock_page(page); - continue; - } - - if (wbc->sync_mode != WB_SYNC_NONE) - wait_on_page_writeback(page); - - if (PageWriteback(page) || - !clear_page_dirty_for_io(page)) { - unlock_page(page); - continue; - } - - if (writepage) { - ret = (*writepage)(page, wbc); - mapping_set_error(mapping, ret); - } else { - bio = __mpage_writepage(bio, page, get_block, - &last_block_in_bio, &ret, wbc, - page->mapping->a_ops->writepage); - } - if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) - unlock_page(page); - if (ret || (--(wbc->nr_to_write) <= 0)) - done = 1; - if (wbc->nonblocking && bdi_write_congested(bdi)) { - wbc->encountered_congestion = 1; - done = 1; - } - } - pagevec_release(&pvec); - cond_resched(); - } - if (!scanned && !done) { - /* - * We hit the last page and there is more work to be done: wrap - * back to the start of the file - */ - scanned = 1; - index = 0; - goto retry; - } - if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) - mapping->writeback_index = index; - if (bio) - mpage_bio_submit(WRITE, bio); return ret; } EXPORT_SYMBOL(mpage_writepages); @@ -804,15 +720,15 @@ EXPORT_SYMBOL(mpage_writepages); int mpage_writepage(struct page *page, get_block_t get_block, struct writeback_control *wbc) { - int ret = 0; - struct bio *bio; - sector_t last_block_in_bio = 0; - - bio = __mpage_writepage(NULL, page, get_block, - &last_block_in_bio, &ret, wbc, NULL); - if (bio) - mpage_bio_submit(WRITE, bio); - + struct mpage_data mpd = { + .bio = NULL, + .last_block_in_bio = 0, + .get_block = get_block, + .use_writepage = 0, + }; + int ret = __mpage_writepage(page, wbc, &mpd); + if (mpd.bio) + mpage_bio_submit(WRITE, mpd.bio); return ret; } EXPORT_SYMBOL(mpage_writepage); diff --git a/fs/namei.c b/fs/namei.c index b3780e3fc88e..5e2d98d10c5d 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1719,7 +1719,7 @@ do_last: * It already exists. */ mutex_unlock(&dir->d_inode->i_mutex); - audit_inode_update(path.dentry->d_inode); + audit_inode(pathname, path.dentry->d_inode); error = -EEXIST; if (flag & O_EXCL) diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 629e7abdd840..6e5c2534f4bc 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -86,19 +86,15 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) } /* Check for the current buffer head overflowing. */ if (unlikely(file_ofs + bh->b_size > init_size)) { - u8 *kaddr; int ofs; ofs = 0; if (file_ofs < init_size) ofs = init_size - file_ofs; local_irq_save(flags); - kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ); - memset(kaddr + bh_offset(bh) + ofs, 0, - bh->b_size - ofs); - kunmap_atomic(kaddr, KM_BIO_SRC_IRQ); + zero_user_page(page, bh_offset(bh) + ofs, + bh->b_size - ofs, KM_BIO_SRC_IRQ); local_irq_restore(flags); - flush_dcache_page(page); } } else { clear_buffer_uptodate(bh); @@ -245,8 +241,7 @@ static int ntfs_read_block(struct page *page) rl = NULL; nr = i = 0; do { - u8 *kaddr; - int err; + int err = 0; if (unlikely(buffer_uptodate(bh))) continue; @@ -254,7 +249,6 @@ static int ntfs_read_block(struct page *page) arr[nr++] = bh; continue; } - err = 0; bh->b_bdev = vol->sb->s_bdev; /* Is the block within the allowed limits? */ if (iblock < lblock) { @@ -340,10 +334,7 @@ handle_hole: bh->b_blocknr = -1UL; clear_buffer_mapped(bh); handle_zblock: - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + i * blocksize, 0, blocksize); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, i * blocksize, blocksize, KM_USER0); if (likely(!err)) set_buffer_uptodate(bh); } while (i++, iblock++, (bh = bh->b_this_page) != head); @@ -460,10 +451,7 @@ retry_readpage: * ok to ignore the compressed flag here. */ if (unlikely(page->index > 0)) { - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr, 0, PAGE_CACHE_SIZE); - flush_dcache_page(page); - kunmap_atomic(kaddr, KM_USER0); + zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); goto done; } if (!NInoAttr(ni)) @@ -790,14 +778,10 @@ lock_retry_remap: * uptodate so it can get discarded by the VM. */ if (err == -ENOENT || lcn == LCN_ENOENT) { - u8 *kaddr; - bh->b_blocknr = -1; clear_buffer_dirty(bh); - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + bh_offset(bh), 0, blocksize); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, bh_offset(bh), blocksize, + KM_USER0); set_buffer_uptodate(bh); err = 0; continue; @@ -1422,10 +1406,8 @@ retry_writepage: if (page->index >= (i_size >> PAGE_CACHE_SHIFT)) { /* The page straddles i_size. */ unsigned int ofs = i_size & ~PAGE_CACHE_MASK; - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + ofs, 0, PAGE_CACHE_SIZE - ofs); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, ofs, PAGE_CACHE_SIZE - ofs, + KM_USER0); } /* Handle mst protected attributes. */ if (NInoMstProtected(ni)) diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 621de369e6f8..39a1669506bd 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -606,11 +606,8 @@ do_next_page: ntfs_submit_bh_for_read(bh); *wait_bh++ = bh; } else { - u8 *kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + bh_offset(bh), 0, - blocksize); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, bh_offset(bh), + blocksize, KM_USER0); set_buffer_uptodate(bh); } } @@ -685,12 +682,9 @@ map_buffer_cached: ntfs_submit_bh_for_read(bh); *wait_bh++ = bh; } else { - u8 *kaddr = kmap_atomic(page, - KM_USER0); - memset(kaddr + bh_offset(bh), - 0, blocksize); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, + bh_offset(bh), + blocksize, KM_USER0); set_buffer_uptodate(bh); } } @@ -708,11 +702,8 @@ map_buffer_cached: */ if (bh_end <= pos || bh_pos >= end) { if (!buffer_uptodate(bh)) { - u8 *kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + bh_offset(bh), 0, - blocksize); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, bh_offset(bh), + blocksize, KM_USER0); set_buffer_uptodate(bh); } mark_buffer_dirty(bh); @@ -751,10 +742,8 @@ map_buffer_cached: if (!buffer_uptodate(bh)) set_buffer_uptodate(bh); } else if (!buffer_uptodate(bh)) { - u8 *kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + bh_offset(bh), 0, blocksize); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, bh_offset(bh), blocksize, + KM_USER0); set_buffer_uptodate(bh); } continue; @@ -878,11 +867,8 @@ rl_not_mapped_enoent: if (!buffer_uptodate(bh)) set_buffer_uptodate(bh); } else if (!buffer_uptodate(bh)) { - u8 *kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + bh_offset(bh), 0, - blocksize); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, bh_offset(bh), + blocksize, KM_USER0); set_buffer_uptodate(bh); } continue; @@ -1137,16 +1123,12 @@ rl_not_mapped_enoent: * to zero the overflowing region. */ if (unlikely(bh_pos + blocksize > initialized_size)) { - u8 *kaddr; int ofs = 0; if (likely(bh_pos < initialized_size)) ofs = initialized_size - bh_pos; - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + bh_offset(bh) + ofs, 0, - blocksize - ofs); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, bh_offset(bh) + ofs, + blocksize - ofs, KM_USER0); } } else /* if (unlikely(!buffer_uptodate(bh))) */ err = -EIO; @@ -1286,11 +1268,8 @@ rl_not_mapped_enoent: if (PageUptodate(page)) set_buffer_uptodate(bh); else { - u8 *kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + bh_offset(bh), 0, - blocksize); - kunmap_atomic(kaddr, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, bh_offset(bh), + blocksize, KM_USER0); set_buffer_uptodate(bh); } } @@ -1350,9 +1329,7 @@ err_out: len = PAGE_CACHE_SIZE; if (len > bytes) len = bytes; - kaddr = kmap_atomic(*pages, KM_USER0); - memset(kaddr, 0, len); - kunmap_atomic(kaddr, KM_USER0); + zero_user_page(*pages, 0, len, KM_USER0); } goto out; } @@ -1473,9 +1450,7 @@ err_out: len = PAGE_CACHE_SIZE; if (len > bytes) len = bytes; - kaddr = kmap_atomic(*pages, KM_USER0); - memset(kaddr, 0, len); - kunmap_atomic(kaddr, KM_USER0); + zero_user_page(*pages, 0, len, KM_USER0); } goto out; } diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig index 01207042048b..7638a1c42a7d 100644 --- a/fs/partitions/Kconfig +++ b/fs/partitions/Kconfig @@ -239,7 +239,7 @@ config EFI_PARTITION config SYSV68_PARTITION bool "SYSV68 partition table support" if PARTITION_ADVANCED - default y if M68K + default y if VME help Say Y here if you would like to be able to read the hard disk partition table format used by Motorola Delta machines (using diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c index 1bea610078b3..e7b07006bc41 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c @@ -152,7 +152,7 @@ last_lba(struct block_device *bdev) } static inline int -pmbr_part_valid(struct partition *part, u64 lastlba) +pmbr_part_valid(struct partition *part) { if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT && le32_to_cpu(part->start_sect) == 1UL) @@ -163,7 +163,6 @@ pmbr_part_valid(struct partition *part, u64 lastlba) /** * is_pmbr_valid(): test Protective MBR for validity * @mbr: pointer to a legacy mbr structure - * @lastlba: last_lba for the whole device * * Description: Returns 1 if PMBR is valid, 0 otherwise. * Validity depends on two things: @@ -171,13 +170,13 @@ pmbr_part_valid(struct partition *part, u64 lastlba) * 2) One partition of type 0xEE is found */ static int -is_pmbr_valid(legacy_mbr *mbr, u64 lastlba) +is_pmbr_valid(legacy_mbr *mbr) { int i; if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) return 0; for (i = 0; i < 4; i++) - if (pmbr_part_valid(&mbr->partition_record[i], lastlba)) + if (pmbr_part_valid(&mbr->partition_record[i])) return 1; return 0; } @@ -516,7 +515,7 @@ find_valid_gpt(struct block_device *bdev, gpt_header **gpt, gpt_entry **ptes) int good_pgpt = 0, good_agpt = 0, good_pmbr = 0; gpt_header *pgpt = NULL, *agpt = NULL; gpt_entry *pptes = NULL, *aptes = NULL; - legacy_mbr *legacymbr = NULL; + legacy_mbr *legacymbr; u64 lastlba; if (!bdev || !gpt || !ptes) return 0; @@ -528,9 +527,8 @@ find_valid_gpt(struct block_device *bdev, gpt_header **gpt, gpt_entry **ptes) if (legacymbr) { read_lba(bdev, 0, (u8 *) legacymbr, sizeof (*legacymbr)); - good_pmbr = is_pmbr_valid(legacymbr, lastlba); + good_pmbr = is_pmbr_valid(legacymbr); kfree(legacymbr); - legacymbr=NULL; } if (!good_pmbr) goto fail; diff --git a/fs/signalfd.c b/fs/signalfd.c new file mode 100644 index 000000000000..7cfeab412b45 --- /dev/null +++ b/fs/signalfd.c @@ -0,0 +1,349 @@ +/* + * fs/signalfd.c + * + * Copyright (C) 2003 Linus Torvalds + * + * Mon Mar 5, 2007: Davide Libenzi <davidel@xmailserver.org> + * Changed ->read() to return a siginfo strcture instead of signal number. + * Fixed locking in ->poll(). + * Added sighand-detach notification. + * Added fd re-use in sys_signalfd() syscall. + * Now using anonymous inode source. + * Thanks to Oleg Nesterov for useful code review and suggestions. + * More comments and suggestions from Arnd Bergmann. + */ + +#include <linux/file.h> +#include <linux/poll.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/signal.h> +#include <linux/list.h> +#include <linux/anon_inodes.h> +#include <linux/signalfd.h> + +struct signalfd_ctx { + struct list_head lnk; + wait_queue_head_t wqh; + sigset_t sigmask; + struct task_struct *tsk; +}; + +struct signalfd_lockctx { + struct task_struct *tsk; + unsigned long flags; +}; + +/* + * Tries to acquire the sighand lock. We do not increment the sighand + * use count, and we do not even pin the task struct, so we need to + * do it inside an RCU read lock, and we must be prepared for the + * ctx->tsk going to NULL (in signalfd_deliver()), and for the sighand + * being detached. We return 0 if the sighand has been detached, or + * 1 if we were able to pin the sighand lock. + */ +static int signalfd_lock(struct signalfd_ctx *ctx, struct signalfd_lockctx *lk) +{ + struct sighand_struct *sighand = NULL; + + rcu_read_lock(); + lk->tsk = rcu_dereference(ctx->tsk); + if (likely(lk->tsk != NULL)) + sighand = lock_task_sighand(lk->tsk, &lk->flags); + rcu_read_unlock(); + + if (sighand && !ctx->tsk) { + unlock_task_sighand(lk->tsk, &lk->flags); + sighand = NULL; + } + + return sighand != NULL; +} + +static void signalfd_unlock(struct signalfd_lockctx *lk) +{ + unlock_task_sighand(lk->tsk, &lk->flags); +} + +/* + * This must be called with the sighand lock held. + */ +void signalfd_deliver(struct task_struct *tsk, int sig) +{ + struct sighand_struct *sighand = tsk->sighand; + struct signalfd_ctx *ctx, *tmp; + + BUG_ON(!sig); + list_for_each_entry_safe(ctx, tmp, &sighand->signalfd_list, lnk) { + /* + * We use a negative signal value as a way to broadcast that the + * sighand has been orphaned, so that we can notify all the + * listeners about this. Remember the ctx->sigmask is inverted, + * so if the user is interested in a signal, that corresponding + * bit will be zero. + */ + if (sig < 0) { + if (ctx->tsk == tsk) { + ctx->tsk = NULL; + list_del_init(&ctx->lnk); + wake_up(&ctx->wqh); + } + } else { + if (!sigismember(&ctx->sigmask, sig)) + wake_up(&ctx->wqh); + } + } +} + +static void signalfd_cleanup(struct signalfd_ctx *ctx) +{ + struct signalfd_lockctx lk; + + /* + * This is tricky. If the sighand is gone, we do not need to remove + * context from the list, the list itself won't be there anymore. + */ + if (signalfd_lock(ctx, &lk)) { + list_del(&ctx->lnk); + signalfd_unlock(&lk); + } + kfree(ctx); +} + +static int signalfd_release(struct inode *inode, struct file *file) +{ + signalfd_cleanup(file->private_data); + return 0; +} + +static unsigned int signalfd_poll(struct file *file, poll_table *wait) +{ + struct signalfd_ctx *ctx = file->private_data; + unsigned int events = 0; + struct signalfd_lockctx lk; + + poll_wait(file, &ctx->wqh, wait); + + /* + * Let the caller get a POLLIN in this case, ala socket recv() when + * the peer disconnects. + */ + if (signalfd_lock(ctx, &lk)) { + if (next_signal(&lk.tsk->pending, &ctx->sigmask) > 0 || + next_signal(&lk.tsk->signal->shared_pending, + &ctx->sigmask) > 0) + events |= POLLIN; + signalfd_unlock(&lk); + } else + events |= POLLIN; + + return events; +} + +/* + * Copied from copy_siginfo_to_user() in kernel/signal.c + */ +static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, + siginfo_t const *kinfo) +{ + long err; + + BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128); + + /* + * Unused memebers should be zero ... + */ + err = __clear_user(uinfo, sizeof(*uinfo)); + + /* + * If you change siginfo_t structure, please be sure + * this code is fixed accordingly. + */ + err |= __put_user(kinfo->si_signo, &uinfo->signo); + err |= __put_user(kinfo->si_errno, &uinfo->err); + err |= __put_user((short)kinfo->si_code, &uinfo->code); + switch (kinfo->si_code & __SI_MASK) { + case __SI_KILL: + err |= __put_user(kinfo->si_pid, &uinfo->pid); + err |= __put_user(kinfo->si_uid, &uinfo->uid); + break; + case __SI_TIMER: + err |= __put_user(kinfo->si_tid, &uinfo->tid); + err |= __put_user(kinfo->si_overrun, &uinfo->overrun); + err |= __put_user((long)kinfo->si_ptr, &uinfo->svptr); + break; + case __SI_POLL: + err |= __put_user(kinfo->si_band, &uinfo->band); + err |= __put_user(kinfo->si_fd, &uinfo->fd); + break; + case __SI_FAULT: + err |= __put_user((long)kinfo->si_addr, &uinfo->addr); +#ifdef __ARCH_SI_TRAPNO + err |= __put_user(kinfo->si_trapno, &uinfo->trapno); +#endif + break; + case __SI_CHLD: + err |= __put_user(kinfo->si_pid, &uinfo->pid); + err |= __put_user(kinfo->si_uid, &uinfo->uid); + err |= __put_user(kinfo->si_status, &uinfo->status); + err |= __put_user(kinfo->si_utime, &uinfo->utime); + err |= __put_user(kinfo->si_stime, &uinfo->stime); + break; + case __SI_RT: /* This is not generated by the kernel as of now. */ + case __SI_MESGQ: /* But this is */ + err |= __put_user(kinfo->si_pid, &uinfo->pid); + err |= __put_user(kinfo->si_uid, &uinfo->uid); + err |= __put_user((long)kinfo->si_ptr, &uinfo->svptr); + break; + default: /* this is just in case for now ... */ + err |= __put_user(kinfo->si_pid, &uinfo->pid); + err |= __put_user(kinfo->si_uid, &uinfo->uid); + break; + } + + return err ? -EFAULT: sizeof(*uinfo); +} + +/* + * Returns either the size of a "struct signalfd_siginfo", or zero if the + * sighand we are attached to, has been orphaned. The "count" parameter + * must be at least the size of a "struct signalfd_siginfo". + */ +static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct signalfd_ctx *ctx = file->private_data; + ssize_t res = 0; + int locked, signo; + siginfo_t info; + struct signalfd_lockctx lk; + DECLARE_WAITQUEUE(wait, current); + + if (count < sizeof(struct signalfd_siginfo)) + return -EINVAL; + locked = signalfd_lock(ctx, &lk); + if (!locked) + return 0; + res = -EAGAIN; + signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info); + if (signo == 0 && !(file->f_flags & O_NONBLOCK)) { + add_wait_queue(&ctx->wqh, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info); + if (signo != 0) + break; + if (signal_pending(current)) { + res = -ERESTARTSYS; + break; + } + signalfd_unlock(&lk); + schedule(); + locked = signalfd_lock(ctx, &lk); + if (unlikely(!locked)) { + /* + * Let the caller read zero byte, ala socket + * recv() when the peer disconnect. This test + * must be done before doing a dequeue_signal(), + * because if the sighand has been orphaned, + * the dequeue_signal() call is going to crash. + */ + res = 0; + break; + } + } + remove_wait_queue(&ctx->wqh, &wait); + __set_current_state(TASK_RUNNING); + } + if (likely(locked)) + signalfd_unlock(&lk); + if (likely(signo)) + res = signalfd_copyinfo((struct signalfd_siginfo __user *) buf, + &info); + + return res; +} + +static const struct file_operations signalfd_fops = { + .release = signalfd_release, + .poll = signalfd_poll, + .read = signalfd_read, +}; + +/* + * Create a file descriptor that is associated with our signal + * state. We can pass it around to others if we want to, but + * it will always be _our_ signal state. + */ +asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) +{ + int error; + sigset_t sigmask; + struct signalfd_ctx *ctx; + struct sighand_struct *sighand; + struct file *file; + struct inode *inode; + struct signalfd_lockctx lk; + + if (sizemask != sizeof(sigset_t) || + copy_from_user(&sigmask, user_mask, sizeof(sigmask))) + return error = -EINVAL; + sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); + signotset(&sigmask); + + if (ufd == -1) { + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + init_waitqueue_head(&ctx->wqh); + ctx->sigmask = sigmask; + ctx->tsk = current; + + sighand = current->sighand; + /* + * Add this fd to the list of signal listeners. + */ + spin_lock_irq(&sighand->siglock); + list_add_tail(&ctx->lnk, &sighand->signalfd_list); + spin_unlock_irq(&sighand->siglock); + + /* + * When we call this, the initialization must be complete, since + * anon_inode_getfd() will install the fd. + */ + error = anon_inode_getfd(&ufd, &inode, &file, "[signalfd]", + &signalfd_fops, ctx); + if (error) + goto err_fdalloc; + } else { + file = fget(ufd); + if (!file) + return -EBADF; + ctx = file->private_data; + if (file->f_op != &signalfd_fops) { + fput(file); + return -EINVAL; + } + /* + * We need to be prepared of the fact that the sighand this fd + * is attached to, has been detched. In that case signalfd_lock() + * will return 0, and we'll just skip setting the new mask. + */ + if (signalfd_lock(ctx, &lk)) { + ctx->sigmask = sigmask; + signalfd_unlock(&lk); + } + wake_up(&ctx->wqh); + fput(file); + } + + return ufd; + +err_fdalloc: + signalfd_cleanup(ctx); + return error; +} + diff --git a/fs/timerfd.c b/fs/timerfd.c new file mode 100644 index 000000000000..e329e37f15a8 --- /dev/null +++ b/fs/timerfd.c @@ -0,0 +1,227 @@ +/* + * fs/timerfd.c + * + * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> + * + * + * Thanks to Thomas Gleixner for code reviews and useful comments. + * + */ + +#include <linux/file.h> +#include <linux/poll.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/time.h> +#include <linux/hrtimer.h> +#include <linux/anon_inodes.h> +#include <linux/timerfd.h> + +struct timerfd_ctx { + struct hrtimer tmr; + ktime_t tintv; + spinlock_t lock; + wait_queue_head_t wqh; + int expired; +}; + +/* + * This gets called when the timer event triggers. We set the "expired" + * flag, but we do not re-arm the timer (in case it's necessary, + * tintv.tv64 != 0) until the timer is read. + */ +static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) +{ + struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr); + unsigned long flags; + + spin_lock_irqsave(&ctx->lock, flags); + ctx->expired = 1; + wake_up_locked(&ctx->wqh); + spin_unlock_irqrestore(&ctx->lock, flags); + + return HRTIMER_NORESTART; +} + +static void timerfd_setup(struct timerfd_ctx *ctx, int clockid, int flags, + const struct itimerspec *ktmr) +{ + enum hrtimer_mode htmode; + ktime_t texp; + + htmode = (flags & TFD_TIMER_ABSTIME) ? + HRTIMER_MODE_ABS: HRTIMER_MODE_REL; + + texp = timespec_to_ktime(ktmr->it_value); + ctx->expired = 0; + ctx->tintv = timespec_to_ktime(ktmr->it_interval); + hrtimer_init(&ctx->tmr, clockid, htmode); + ctx->tmr.expires = texp; + ctx->tmr.function = timerfd_tmrproc; + if (texp.tv64 != 0) + hrtimer_start(&ctx->tmr, texp, htmode); +} + +static int timerfd_release(struct inode *inode, struct file *file) +{ + struct timerfd_ctx *ctx = file->private_data; + + hrtimer_cancel(&ctx->tmr); + kfree(ctx); + return 0; +} + +static unsigned int timerfd_poll(struct file *file, poll_table *wait) +{ + struct timerfd_ctx *ctx = file->private_data; + unsigned int events = 0; + unsigned long flags; + + poll_wait(file, &ctx->wqh, wait); + + spin_lock_irqsave(&ctx->lock, flags); + if (ctx->expired) + events |= POLLIN; + spin_unlock_irqrestore(&ctx->lock, flags); + + return events; +} + +static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct timerfd_ctx *ctx = file->private_data; + ssize_t res; + u32 ticks = 0; + DECLARE_WAITQUEUE(wait, current); + + if (count < sizeof(ticks)) + return -EINVAL; + spin_lock_irq(&ctx->lock); + res = -EAGAIN; + if (!ctx->expired && !(file->f_flags & O_NONBLOCK)) { + __add_wait_queue(&ctx->wqh, &wait); + for (res = 0;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (ctx->expired) { + res = 0; + break; + } + if (signal_pending(current)) { + res = -ERESTARTSYS; + break; + } + spin_unlock_irq(&ctx->lock); + schedule(); + spin_lock_irq(&ctx->lock); + } + __remove_wait_queue(&ctx->wqh, &wait); + __set_current_state(TASK_RUNNING); + } + if (ctx->expired) { + ctx->expired = 0; + if (ctx->tintv.tv64 != 0) { + /* + * If tintv.tv64 != 0, this is a periodic timer that + * needs to be re-armed. We avoid doing it in the timer + * callback to avoid DoS attacks specifying a very + * short timer period. + */ + ticks = (u32) + hrtimer_forward(&ctx->tmr, + hrtimer_cb_get_time(&ctx->tmr), + ctx->tintv); + hrtimer_restart(&ctx->tmr); + } else + ticks = 1; + } + spin_unlock_irq(&ctx->lock); + if (ticks) + res = put_user(ticks, buf) ? -EFAULT: sizeof(ticks); + return res; +} + +static const struct file_operations timerfd_fops = { + .release = timerfd_release, + .poll = timerfd_poll, + .read = timerfd_read, +}; + +asmlinkage long sys_timerfd(int ufd, int clockid, int flags, + const struct itimerspec __user *utmr) +{ + int error; + struct timerfd_ctx *ctx; + struct file *file; + struct inode *inode; + struct itimerspec ktmr; + + if (copy_from_user(&ktmr, utmr, sizeof(ktmr))) + return -EFAULT; + + if (clockid != CLOCK_MONOTONIC && + clockid != CLOCK_REALTIME) + return -EINVAL; + if (!timespec_valid(&ktmr.it_value) || + !timespec_valid(&ktmr.it_interval)) + return -EINVAL; + + if (ufd == -1) { + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + init_waitqueue_head(&ctx->wqh); + spin_lock_init(&ctx->lock); + + timerfd_setup(ctx, clockid, flags, &ktmr); + + /* + * When we call this, the initialization must be complete, since + * anon_inode_getfd() will install the fd. + */ + error = anon_inode_getfd(&ufd, &inode, &file, "[timerfd]", + &timerfd_fops, ctx); + if (error) + goto err_tmrcancel; + } else { + file = fget(ufd); + if (!file) + return -EBADF; + ctx = file->private_data; + if (file->f_op != &timerfd_fops) { + fput(file); + return -EINVAL; + } + /* + * We need to stop the existing timer before reprogramming + * it to the new values. + */ + for (;;) { + spin_lock_irq(&ctx->lock); + if (hrtimer_try_to_cancel(&ctx->tmr) >= 0) + break; + spin_unlock_irq(&ctx->lock); + cpu_relax(); + } + /* + * Re-program the timer to the new value ... + */ + timerfd_setup(ctx, clockid, flags, &ktmr); + + spin_unlock_irq(&ctx->lock); + fput(file); + } + + return ufd; + +err_tmrcancel: + hrtimer_cancel(&ctx->tmr); + kfree(ctx); + return error; +} + diff --git a/fs/xattr.c b/fs/xattr.c index 9f4568b55b0f..4523aca79659 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -350,6 +350,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size) f = fget(fd); if (!f) return error; + audit_inode(NULL, f->f_path.dentry->d_inode); error = getxattr(f->f_path.dentry, name, value, size); fput(f); return error; @@ -422,6 +423,7 @@ sys_flistxattr(int fd, char __user *list, size_t size) f = fget(fd); if (!f) return error; + audit_inode(NULL, f->f_path.dentry->d_inode); error = listxattr(f->f_path.dentry, list, size); fput(f); return error; diff --git a/include/asm-alpha/poll.h b/include/asm-alpha/poll.h index 76f89356b6a7..c98509d3149e 100644 --- a/include/asm-alpha/poll.h +++ b/include/asm-alpha/poll.h @@ -1,25 +1 @@ -#ifndef __ALPHA_POLL_H -#define __ALPHA_POLL_H - -#define POLLIN (1 << 0) -#define POLLPRI (1 << 1) -#define POLLOUT (1 << 2) -#define POLLERR (1 << 3) -#define POLLHUP (1 << 4) -#define POLLNVAL (1 << 5) -#define POLLRDNORM (1 << 6) -#define POLLRDBAND (1 << 7) -#define POLLWRNORM (1 << 8) -#define POLLWRBAND (1 << 9) -#define POLLMSG (1 << 10) -#define POLLREMOVE (1 << 12) -#define POLLRDHUP (1 << 13) - - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif +#include <asm-generic/poll.h> diff --git a/include/asm-arm/poll.h b/include/asm-arm/poll.h index 5030b2b232a3..c98509d3149e 100644 --- a/include/asm-arm/poll.h +++ b/include/asm-arm/poll.h @@ -1,27 +1 @@ -#ifndef __ASMARM_POLL_H -#define __ASMARM_POLL_H - -/* These are specified by iBCS2 */ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif +#include <asm-generic/poll.h> diff --git a/include/asm-arm26/poll.h b/include/asm-arm26/poll.h index 9ccb7f4190ca..1170e7065f6a 100644 --- a/include/asm-arm26/poll.h +++ b/include/asm-arm26/poll.h @@ -1,26 +1,8 @@ #ifndef __ASMARM_POLL_H #define __ASMARM_POLL_H -/* These are specified by iBCS2 */ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 +#include <asm-generic/poll.h> -/* The rest seem to be more-or-less nonstandard. Check them! */ -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; +#undef POLLREMOVE #endif diff --git a/include/asm-avr32/poll.h b/include/asm-avr32/poll.h index 736e29755dfc..c98509d3149e 100644 --- a/include/asm-avr32/poll.h +++ b/include/asm-avr32/poll.h @@ -1,27 +1 @@ -#ifndef __ASM_AVR32_POLL_H -#define __ASM_AVR32_POLL_H - -/* These are specified by iBCS2 */ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif /* __ASM_AVR32_POLL_H */ +#include <asm-generic/poll.h> diff --git a/include/asm-cris/poll.h b/include/asm-cris/poll.h index 1b25d4cf498c..c98509d3149e 100644 --- a/include/asm-cris/poll.h +++ b/include/asm-cris/poll.h @@ -1,26 +1 @@ -#ifndef __ASM_CRIS_POLL_H -#define __ASM_CRIS_POLL_H - -/* taken from asm-alpha */ - -#define POLLIN 1 -#define POLLPRI 2 -#define POLLOUT 4 -#define POLLERR 8 -#define POLLHUP 16 -#define POLLNVAL 32 -#define POLLRDNORM 64 -#define POLLRDBAND 128 -#define POLLWRNORM 256 -#define POLLWRBAND 512 -#define POLLMSG 1024 -#define POLLREMOVE 4096 -#define POLLRDHUP 8192 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif +#include <asm-generic/poll.h> diff --git a/include/asm-frv/poll.h b/include/asm-frv/poll.h index c8fe8801d075..0d01479ccc56 100644 --- a/include/asm-frv/poll.h +++ b/include/asm-frv/poll.h @@ -1,24 +1,12 @@ #ifndef _ASM_POLL_H #define _ASM_POLL_H -#define POLLIN 1 -#define POLLPRI 2 -#define POLLOUT 4 -#define POLLERR 8 -#define POLLHUP 16 -#define POLLNVAL 32 -#define POLLRDNORM 64 #define POLLWRNORM POLLOUT -#define POLLRDBAND 128 #define POLLWRBAND 256 -#define POLLMSG 0x0400 -#define POLLRDHUP 0x2000 -struct pollfd { - int fd; - short events; - short revents; -}; +#include <asm-generic/poll.h> + +#undef POLLREMOVE #endif diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild index fa14f8cd30c5..5bfeef761649 100644 --- a/include/asm-generic/Kbuild +++ b/include/asm-generic/Kbuild @@ -4,6 +4,7 @@ header-y += fcntl.h header-y += ioctl.h header-y += ipc.h header-y += mman.h +header-y += poll.h header-y += signal.h header-y += statfs.h diff --git a/include/asm-generic/audit_signal.h b/include/asm-generic/audit_signal.h new file mode 100644 index 000000000000..6feab7f18a53 --- /dev/null +++ b/include/asm-generic/audit_signal.h @@ -0,0 +1,3 @@ +__NR_kill, +__NR_tgkill, +__NR_tkill, diff --git a/include/asm-generic/poll.h b/include/asm-generic/poll.h new file mode 100644 index 000000000000..44bce836d350 --- /dev/null +++ b/include/asm-generic/poll.h @@ -0,0 +1,37 @@ +#ifndef __ASM_GENERIC_POLL_H +#define __ASM_GENERIC_POLL_H + +/* These are specified by iBCS2 */ +#define POLLIN 0x0001 +#define POLLPRI 0x0002 +#define POLLOUT 0x0004 +#define POLLERR 0x0008 +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 + +/* The rest seem to be more-or-less nonstandard. Check them! */ +#define POLLRDNORM 0x0040 +#define POLLRDBAND 0x0080 +#ifndef POLLWRNORM +#define POLLWRNORM 0x0100 +#endif +#ifndef POLLWRBAND +#define POLLWRBAND 0x0200 +#endif +#ifndef POLLMSG +#define POLLMSG 0x0400 +#endif +#ifndef POLLREMOVE +#define POLLREMOVE 0x1000 +#endif +#ifndef POLLRDHUP +#define POLLRDHUP 0x2000 +#endif + +struct pollfd { + int fd; + short events; + short revents; +}; + +#endif /* __ASM_GENERIC_POLL_H */ diff --git a/include/asm-h8300/poll.h b/include/asm-h8300/poll.h index fc52103b276a..f61540c22d94 100644 --- a/include/asm-h8300/poll.h +++ b/include/asm-h8300/poll.h @@ -1,23 +1,11 @@ #ifndef __H8300_POLL_H #define __H8300_POLL_H -#define POLLIN 1 -#define POLLPRI 2 -#define POLLOUT 4 -#define POLLERR 8 -#define POLLHUP 16 -#define POLLNVAL 32 -#define POLLRDNORM 64 #define POLLWRNORM POLLOUT -#define POLLRDBAND 128 #define POLLWRBAND 256 -#define POLLMSG 0x0400 -#define POLLRDHUP 0x2000 -struct pollfd { - int fd; - short events; - short revents; -}; +#include <asm-generic/poll.h> + +#undef POLLREMOVE #endif diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h index 7ddd414f8d16..99f3c3561ecb 100644 --- a/include/asm-h8300/unistd.h +++ b/include/asm-h8300/unistd.h @@ -21,7 +21,7 @@ #define __NR_time 13 #define __NR_mknod 14 #define __NR_chmod 15 -#define __NR_chown 16 +#define __NR_lchown 16 #define __NR_break 17 #define __NR_oldstat 18 #define __NR_lseek 19 @@ -115,10 +115,10 @@ #define __NR_lstat 107 #define __NR_fstat 108 #define __NR_olduname 109 -#define __NR_iopl /* 110 */ not supported +#define __NR_iopl 110 #define __NR_vhangup 111 -#define __NR_idle /* 112 */ Obsolete -#define __NR_vm86 /* 113 */ not supported +#define __NR_idle 112 +#define __NR_vm86old 113 #define __NR_wait4 114 #define __NR_swapoff 115 #define __NR_sysinfo 116 @@ -128,7 +128,7 @@ #define __NR_clone 120 #define __NR_setdomainname 121 #define __NR_uname 122 -#define __NR_cacheflush 123 +#define __NR_modify_ldt 123 #define __NR_adjtimex 124 #define __NR_mprotect 125 #define __NR_sigprocmask 126 @@ -171,7 +171,7 @@ #define __NR_mremap 163 #define __NR_setresuid 164 #define __NR_getresuid 165 -#define __NR_getpagesize 166 +#define __NR_vm86 166 #define __NR_query_module 167 #define __NR_poll 168 #define __NR_nfsservctl 169 @@ -187,7 +187,7 @@ #define __NR_rt_sigsuspend 179 #define __NR_pread64 180 #define __NR_pwrite64 181 -#define __NR_lchown 182 +#define __NR_chown 182 #define __NR_getcwd 183 #define __NR_capget 184 #define __NR_capset 185 @@ -203,7 +203,7 @@ #define __NR_stat64 195 #define __NR_lstat64 196 #define __NR_fstat64 197 -#define __NR_chown32 198 +#define __NR_lchown32 198 #define __NR_getuid32 199 #define __NR_getgid32 200 #define __NR_geteuid32 201 @@ -217,15 +217,18 @@ #define __NR_getresuid32 209 #define __NR_setresgid32 210 #define __NR_getresgid32 211 -#define __NR_lchown32 212 +#define __NR_chown32 212 #define __NR_setuid32 213 #define __NR_setgid32 214 #define __NR_setfsuid32 215 #define __NR_setfsgid32 216 #define __NR_pivot_root 217 +#define __NR_mincore 218 +#define __NR_madvise 219 +#define __NR_madvise1 219 #define __NR_getdents64 220 #define __NR_fcntl64 221 -#define __NR_security 223 +/* 223 is unused */ #define __NR_gettid 224 #define __NR_readahead 225 #define __NR_setxattr 226 @@ -252,13 +255,13 @@ #define __NR_io_getevents 247 #define __NR_io_submit 248 #define __NR_io_cancel 249 -#define __NR_alloc_hugepages 250 -#define __NR_free_hugepages 251 +#define __NR_fadvise64 250 +/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */ #define __NR_exit_group 252 #define __NR_lookup_dcookie 253 -#define __NR_sys_epoll_create 254 -#define __NR_sys_epoll_ctl 255 -#define __NR_sys_epoll_wait 256 +#define __NR_epoll_create 254 +#define __NR_epoll_ctl 255 +#define __NR_epoll_wait 256 #define __NR_remap_file_pages 257 #define __NR_set_tid_address 258 #define __NR_timer_create 259 @@ -291,10 +294,41 @@ #define __NR_add_key 286 #define __NR_request_key 287 #define __NR_keyctl 288 +#define __NR_ioprio_set 289 +#define __NR_ioprio_get 290 +#define __NR_inotify_init 291 +#define __NR_inotify_add_watch 292 +#define __NR_inotify_rm_watch 293 +#define __NR_migrate_pages 294 +#define __NR_openat 295 +#define __NR_mkdirat 296 +#define __NR_mknodat 297 +#define __NR_fchownat 298 +#define __NR_futimesat 299 +#define __NR_fstatat64 300 +#define __NR_unlinkat 301 +#define __NR_renameat 302 +#define __NR_linkat 303 +#define __NR_symlinkat 304 +#define __NR_readlinkat 305 +#define __NR_fchmodat 306 +#define __NR_faccessat 307 +#define __NR_pselect6 308 +#define __NR_ppoll 309 +#define __NR_unshare 310 +#define __NR_set_robust_list 311 +#define __NR_get_robust_list 312 +#define __NR_splice 313 +#define __NR_sync_file_range 314 +#define __NR_tee 315 +#define __NR_vmsplice 316 +#define __NR_move_pages 317 +#define __NR_getcpu 318 +#define __NR_epoll_pwait 319 #ifdef __KERNEL__ -#define NR_syscalls 289 +#define NR_syscalls 320 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h index 0f70b379b029..eb7da5402bfa 100644 --- a/include/asm-i386/alternative.h +++ b/include/asm-i386/alternative.h @@ -98,6 +98,12 @@ static inline void alternatives_smp_switch(int smp) {} ".previous" : output : [feat] "i" (feature), ##input) /* + * use this macro(s) if you need more than one output parameter + * in alternative_io + */ +#define ASM_OUTPUT2(a, b) a, b + +/* * Alternative inline assembly for SMP. * * The LOCK_PREFIX macro defined here replaces the LOCK and diff --git a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h index 47430175b75f..d07b7afc2692 100644 --- a/include/asm-i386/pgalloc.h +++ b/include/asm-i386/pgalloc.h @@ -65,6 +65,4 @@ do { \ #define pud_populate(mm, pmd, pte) BUG() #endif -#define check_pgt_cache() do { } while (0) - #endif /* _I386_PGALLOC_H */ diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index edce9d51a676..2394589786ba 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -35,17 +35,16 @@ struct vm_area_struct; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) extern unsigned long empty_zero_page[1024]; extern pgd_t swapper_pg_dir[1024]; -extern struct kmem_cache *pgd_cache; extern struct kmem_cache *pmd_cache; extern spinlock_t pgd_lock; extern struct page *pgd_list; +void check_pgt_cache(void); void pmd_ctor(void *, struct kmem_cache *, unsigned long); -void pgd_ctor(void *, struct kmem_cache *, unsigned long); -void pgd_dtor(void *, struct kmem_cache *, unsigned long); void pgtable_cache_init(void); void paging_init(void); + /* * The Linux x86 paging architecture is 'compile-time dual-mode', it * implements both the traditional 2-level x86 page tables and the diff --git a/include/asm-i386/poll.h b/include/asm-i386/poll.h index 2cd4929abd40..c98509d3149e 100644 --- a/include/asm-i386/poll.h +++ b/include/asm-i386/poll.h @@ -1,27 +1 @@ -#ifndef __i386_POLL_H -#define __i386_POLL_H - -/* These are specified by iBCS2 */ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif +#include <asm-generic/poll.h> diff --git a/include/asm-i386/tsc.h b/include/asm-i386/tsc.h index 3f3c1fa000b4..62c091ffcccc 100644 --- a/include/asm-i386/tsc.h +++ b/include/asm-i386/tsc.h @@ -35,14 +35,16 @@ static inline cycles_t get_cycles(void) static __always_inline cycles_t get_cycles_sync(void) { unsigned long long ret; - unsigned eax; + unsigned eax, edx; /* * Use RDTSCP if possible; it is guaranteed to be synchronous * and doesn't cause a VMEXIT on Hypervisors */ alternative_io(ASM_NOP3, ".byte 0x0f,0x01,0xf9", X86_FEATURE_RDTSCP, - "=A" (ret), "0" (0ULL) : "ecx", "memory"); + ASM_OUTPUT2("=a" (eax), "=d" (edx)), + "a" (0U), "d" (0U) : "ecx", "memory"); + ret = (((unsigned long long)edx) << 32) | ((unsigned long long)eax); if (ret) return ret; diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index bd21e795197c..e84ace1ec8bf 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -326,10 +326,13 @@ #define __NR_getcpu 318 #define __NR_epoll_pwait 319 #define __NR_utimensat 320 +#define __NR_signalfd 321 +#define __NR_timerfd 322 +#define __NR_eventfd 323 #ifdef __KERNEL__ -#define NR_syscalls 321 +#define NR_syscalls 324 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h index 79479e2c6966..67221615e317 100644 --- a/include/asm-ia64/irq.h +++ b/include/asm-ia64/irq.h @@ -11,6 +11,9 @@ * 02/29/00 D.Mosberger moved most things into hw_irq.h */ +#include <linux/types.h> +#include <linux/cpumask.h> + #define NR_IRQS 256 #define NR_IRQ_VECTORS NR_IRQS @@ -29,5 +32,8 @@ extern void disable_irq (unsigned int); extern void disable_irq_nosync (unsigned int); extern void enable_irq (unsigned int); extern void set_irq_affinity_info (unsigned int irq, int dest, int redir); +bool is_affinity_mask_valid(cpumask_t cpumask); + +#define is_affinity_mask_valid is_affinity_mask_valid #endif /* _ASM_IA64_IRQ_H */ diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h index 828ae00e47c1..2abc98b336f3 100644 --- a/include/asm-ia64/kprobes.h +++ b/include/asm-ia64/kprobes.h @@ -71,13 +71,15 @@ struct prev_kprobe { #define MAX_PARAM_RSE_SIZE (0x60+0x60/0x3f) /* per-cpu kprobe control block */ +#define ARCH_PREV_KPROBE_SZ 2 struct kprobe_ctlblk { unsigned long kprobe_status; struct pt_regs jprobe_saved_regs; unsigned long jprobes_saved_stacked_regs[MAX_PARAM_RSE_SIZE]; unsigned long *bsp; unsigned long cfm; - struct prev_kprobe prev_kprobe; + atomic_t prev_kprobe_index; + struct prev_kprobe prev_kprobe[ARCH_PREV_KPROBE_SZ]; }; #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h index 560c287b1233..67552cad5173 100644 --- a/include/asm-ia64/pgalloc.h +++ b/include/asm-ia64/pgalloc.h @@ -18,71 +18,18 @@ #include <linux/mm.h> #include <linux/page-flags.h> #include <linux/threads.h> +#include <linux/quicklist.h> #include <asm/mmu_context.h> -DECLARE_PER_CPU(unsigned long *, __pgtable_quicklist); -#define pgtable_quicklist __ia64_per_cpu_var(__pgtable_quicklist) -DECLARE_PER_CPU(long, __pgtable_quicklist_size); -#define pgtable_quicklist_size __ia64_per_cpu_var(__pgtable_quicklist_size) - -static inline long pgtable_quicklist_total_size(void) -{ - long ql_size = 0; - int cpuid; - - for_each_online_cpu(cpuid) { - ql_size += per_cpu(__pgtable_quicklist_size, cpuid); - } - return ql_size; -} - -static inline void *pgtable_quicklist_alloc(void) -{ - unsigned long *ret = NULL; - - preempt_disable(); - - ret = pgtable_quicklist; - if (likely(ret != NULL)) { - pgtable_quicklist = (unsigned long *)(*ret); - ret[0] = 0; - --pgtable_quicklist_size; - preempt_enable(); - } else { - preempt_enable(); - ret = (unsigned long *)__get_free_page(GFP_KERNEL | __GFP_ZERO); - } - - return ret; -} - -static inline void pgtable_quicklist_free(void *pgtable_entry) -{ -#ifdef CONFIG_NUMA - int nid = page_to_nid(virt_to_page(pgtable_entry)); - - if (unlikely(nid != numa_node_id())) { - free_page((unsigned long)pgtable_entry); - return; - } -#endif - - preempt_disable(); - *(unsigned long *)pgtable_entry = (unsigned long)pgtable_quicklist; - pgtable_quicklist = (unsigned long *)pgtable_entry; - ++pgtable_quicklist_size; - preempt_enable(); -} - static inline pgd_t *pgd_alloc(struct mm_struct *mm) { - return pgtable_quicklist_alloc(); + return quicklist_alloc(0, GFP_KERNEL, NULL); } static inline void pgd_free(pgd_t * pgd) { - pgtable_quicklist_free(pgd); + quicklist_free(0, NULL, pgd); } #ifdef CONFIG_PGTABLE_4 @@ -94,12 +41,12 @@ pgd_populate(struct mm_struct *mm, pgd_t * pgd_entry, pud_t * pud) static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) { - return pgtable_quicklist_alloc(); + return quicklist_alloc(0, GFP_KERNEL, NULL); } static inline void pud_free(pud_t * pud) { - pgtable_quicklist_free(pud); + quicklist_free(0, NULL, pud); } #define __pud_free_tlb(tlb, pud) pud_free(pud) #endif /* CONFIG_PGTABLE_4 */ @@ -112,12 +59,12 @@ pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd) static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) { - return pgtable_quicklist_alloc(); + return quicklist_alloc(0, GFP_KERNEL, NULL); } static inline void pmd_free(pmd_t * pmd) { - pgtable_quicklist_free(pmd); + quicklist_free(0, NULL, pmd); } #define __pmd_free_tlb(tlb, pmd) pmd_free(pmd) @@ -137,28 +84,31 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte) static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr) { - void *pg = pgtable_quicklist_alloc(); + void *pg = quicklist_alloc(0, GFP_KERNEL, NULL); return pg ? virt_to_page(pg) : NULL; } static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) { - return pgtable_quicklist_alloc(); + return quicklist_alloc(0, GFP_KERNEL, NULL); } static inline void pte_free(struct page *pte) { - pgtable_quicklist_free(page_address(pte)); + quicklist_free_page(0, NULL, pte); } static inline void pte_free_kernel(pte_t * pte) { - pgtable_quicklist_free(pte); + quicklist_free(0, NULL, pte); } -#define __pte_free_tlb(tlb, pte) pte_free(pte) +static inline void check_pgt_cache(void) +{ + quicklist_trim(0, NULL, 25, 16); +} -extern void check_pgt_cache(void); +#define __pte_free_tlb(tlb, pte) pte_free(pte) #endif /* _ASM_IA64_PGALLOC_H */ diff --git a/include/asm-ia64/poll.h b/include/asm-ia64/poll.h index bcaf9f140242..c98509d3149e 100644 --- a/include/asm-ia64/poll.h +++ b/include/asm-ia64/poll.h @@ -1,32 +1 @@ -#ifndef _ASM_IA64_POLL_H -#define _ASM_IA64_POLL_H - -/* - * poll(2) bit definitions. Based on <asm-i386/poll.h>. - * - * Modified 1998, 1999, 2002 - * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co - */ - -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif /* _ASM_IA64_POLL_H */ +#include <asm-generic/poll.h> diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index 861c8ec87b09..f049bc40ca7d 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h @@ -294,11 +294,13 @@ #define __NR_vmsplice 1302 /* 1303 reserved for move_pages */ #define __NR_getcpu 1304 +#define __NR_epoll_pwait 1305 +#define __NR_utimensat 1306 #ifdef __KERNEL__ -#define NR_syscalls 281 /* length of syscall table */ +#define NR_syscalls 283 /* length of syscall table */ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND diff --git a/include/asm-m32r/pgtable-2level.h b/include/asm-m32r/pgtable-2level.h index 750925726a10..bca3475f9595 100644 --- a/include/asm-m32r/pgtable-2level.h +++ b/include/asm-m32r/pgtable-2level.h @@ -71,8 +71,8 @@ static inline pmd_t *pmd_offset(pgd_t * dir, unsigned long address) #define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) #define PTE_FILE_MAX_BITS 29 -#define pte_to_pgoff(pte) (((pte_val(pte) >> 2) & 0xef) | (((pte_val(pte) >> 10)) << 7)) -#define pgoff_to_pte(off) ((pte_t) { (((off) & 0xef) << 2) | (((off) >> 7) << 10) | _PAGE_FILE }) +#define pte_to_pgoff(pte) (((pte_val(pte) >> 2) & 0x7f) | (((pte_val(pte) >> 10)) << 7)) +#define pgoff_to_pte(off) ((pte_t) { (((off) & 0x7f) << 2) | (((off) >> 7) << 10) | _PAGE_FILE }) #endif /* __KERNEL__ */ #endif /* _ASM_M32R_PGTABLE_2LEVEL_H */ diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h index 8b2a2f17e695..6604303fc47c 100644 --- a/include/asm-m32r/pgtable.h +++ b/include/asm-m32r/pgtable.h @@ -366,7 +366,7 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep) #define pte_unmap_nested(pte) do { } while (0) /* Encode and de-code a swap entry */ -#define __swp_type(x) (((x).val >> 2) & 0x3f) +#define __swp_type(x) (((x).val >> 2) & 0x1f) #define __swp_offset(x) ((x).val >> 10) #define __swp_entry(type, offset) \ ((swp_entry_t) { ((type) << 2) | ((offset) << 10) }) diff --git a/include/asm-m32r/poll.h b/include/asm-m32r/poll.h index 9e0e700e727c..c98509d3149e 100644 --- a/include/asm-m32r/poll.h +++ b/include/asm-m32r/poll.h @@ -1,32 +1 @@ -#ifndef _ASM_M32R_POLL_H -#define _ASM_M32R_POLL_H - -/* - * poll(2) bit definitions. Based on <asm-i386/poll.h>. - * - * Modified 2004 - * Hirokazu Takata <takata at linux-m32r.org> - */ - -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif /* _ASM_M32R_POLL_H */ +#include <asm-generic/poll.h> diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h index f62f5c9abba6..b291b2f72954 100644 --- a/include/asm-m32r/system.h +++ b/include/asm-m32r/system.h @@ -21,12 +21,22 @@ * `next' and `prev' should be struct task_struct, but it isn't always defined */ +#if defined(CONFIG_FRAME_POINTER) || \ + !defined(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER) +#define M32R_PUSH_FP " push fp\n" +#define M32R_POP_FP " pop fp\n" +#else +#define M32R_PUSH_FP "" +#define M32R_POP_FP "" +#endif + #define switch_to(prev, next, last) do { \ __asm__ __volatile__ ( \ " seth lr, #high(1f) \n" \ " or3 lr, lr, #low(1f) \n" \ " st lr, @%4 ; store old LR \n" \ " ld lr, @%5 ; load new LR \n" \ + M32R_PUSH_FP \ " st sp, @%2 ; store old SP \n" \ " ld sp, @%3 ; load new SP \n" \ " push %1 ; store `prev' on new stack \n" \ @@ -34,6 +44,7 @@ " .fillinsn \n" \ "1: \n" \ " pop %0 ; restore `__last' from new stack \n" \ + M32R_POP_FP \ : "=r" (last) \ : "0" (prev), \ "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \ diff --git a/include/asm-m68k/atarihw.h b/include/asm-m68k/atarihw.h index 6211363a345f..ecf007df7743 100644 --- a/include/asm-m68k/atarihw.h +++ b/include/asm-m68k/atarihw.h @@ -2,7 +2,7 @@ ** linux/atarihw.h -- This header defines some macros and pointers for ** the various Atari custom hardware registers. ** -** Copyright 1994 by Bj”rn Brauel +** Copyright 1994 by Björn Brauel ** ** 5/1/94 Roman Hodek: ** Added definitions for TT specific chips. diff --git a/include/asm-m68k/atariints.h b/include/asm-m68k/atariints.h index ce6c445805bd..5748e99f4e26 100644 --- a/include/asm-m68k/atariints.h +++ b/include/asm-m68k/atariints.h @@ -1,7 +1,7 @@ /* ** atariints.h -- Atari Linux interrupt handling structs and prototypes ** -** Copyright 1994 by Bj”rn Brauel +** Copyright 1994 by Björn Brauel ** ** 5/2/94 Roman Hodek: ** TT interrupt definitions added. diff --git a/include/asm-m68k/poll.h b/include/asm-m68k/poll.h index 0fb8843647f8..f080fcdb61bf 100644 --- a/include/asm-m68k/poll.h +++ b/include/asm-m68k/poll.h @@ -1,24 +1,9 @@ #ifndef __m68k_POLL_H #define __m68k_POLL_H -#define POLLIN 1 -#define POLLPRI 2 -#define POLLOUT 4 -#define POLLERR 8 -#define POLLHUP 16 -#define POLLNVAL 32 -#define POLLRDNORM 64 #define POLLWRNORM POLLOUT -#define POLLRDBAND 128 #define POLLWRBAND 256 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 -struct pollfd { - int fd; - short events; - short revents; -}; +#include <asm-generic/poll.h> #endif diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h index 62daa746a9c9..1b60624dab7e 100644 --- a/include/asm-mips/atomic.h +++ b/include/asm-mips/atomic.h @@ -689,7 +689,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) } #define atomic64_cmpxchg(v, o, n) \ - (((__typeof__((v)->counter)))cmpxchg(&((v)->counter), (o), (n))) + ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n))) #define atomic64_xchg(v, new) (xchg(&((v)->counter), (new))) /** diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h index dbf834f4dac4..b0c329783ac5 100644 --- a/include/asm-mips/bootinfo.h +++ b/include/asm-mips/bootinfo.h @@ -119,9 +119,9 @@ */ #define MACH_GROUP_MOMENCO 12 /* Momentum Boards */ #define MACH_MOMENCO_OCELOT 0 -#define MACH_MOMENCO_OCELOT_G 1 +#define MACH_MOMENCO_OCELOT_G 1 /* no more supported (may 2007) */ #define MACH_MOMENCO_OCELOT_C 2 -#define MACH_MOMENCO_JAGUAR_ATX 3 +#define MACH_MOMENCO_JAGUAR_ATX 3 /* no more supported (may 2007) */ #define MACH_MOMENCO_OCELOT_3 4 /* diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h index b414a7d9db43..483685b1592e 100644 --- a/include/asm-mips/fpu.h +++ b/include/asm-mips/fpu.h @@ -16,6 +16,7 @@ #include <asm/mipsregs.h> #include <asm/cpu.h> #include <asm/cpu-features.h> +#include <asm/hazards.h> #include <asm/bitops.h> #include <asm/processor.h> #include <asm/current.h> @@ -38,34 +39,16 @@ extern void _init_fpu(void); extern void _save_fp(struct task_struct *); extern void _restore_fp(struct task_struct *); -#if defined(CONFIG_CPU_SB1) -#define __enable_fpu_hazard() \ -do { \ - asm(".set push \n\t" \ - ".set mips64 \n\t" \ - ".set noreorder \n\t" \ - "ssnop \n\t" \ - "bnezl $0, .+4 \n\t" \ - "ssnop \n\t" \ - ".set pop"); \ -} while (0) -#else -#define __enable_fpu_hazard() \ -do { \ - asm("nop;nop;nop;nop"); /* max. hazard */ \ -} while (0) -#endif - #define __enable_fpu() \ do { \ set_c0_status(ST0_CU1); \ - __enable_fpu_hazard(); \ + enable_fpu_hazard(); \ } while (0) #define __disable_fpu() \ do { \ clear_c0_status(ST0_CU1); \ - /* We don't care about the c0 hazard here */ \ + disable_fpu_hazard(); \ } while (0) #define enable_fpu() \ diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h index e50c77e69cb5..d9119f43f9aa 100644 --- a/include/asm-mips/hazards.h +++ b/include/asm-mips/hazards.h @@ -178,4 +178,36 @@ ASMMACRO(back_to_back_c0_hazard, #endif + +/* FPU hazards */ + +#if defined(CONFIG_CPU_SB1) +ASMMACRO(enable_fpu_hazard, + .set push; + .set mips64; + .set noreorder; + _ssnop; + bnezl $0,.+4; + _ssnop; + .set pop +) +ASMMACRO(disable_fpu_hazard, +) + +#elif defined(CONFIG_CPU_MIPSR2) +ASMMACRO(enable_fpu_hazard, + _ehb +) +ASMMACRO(disable_fpu_hazard, + _ehb +) +#else +ASMMACRO(enable_fpu_hazard, + nop; nop; nop; nop +) +ASMMACRO(disable_fpu_hazard, + _ehb +) +#endif + #endif /* _ASM_HAZARDS_H */ diff --git a/include/asm-mips/highmem.h b/include/asm-mips/highmem.h index f8c8182f7f2e..4d6bd5c31c7b 100644 --- a/include/asm-mips/highmem.h +++ b/include/asm-mips/highmem.h @@ -48,46 +48,6 @@ extern pte_t *pkmap_page_table; extern void * kmap_high(struct page *page); extern void kunmap_high(struct page *page); -/* - * CONFIG_LIMITED_DMA is for systems with DMA limitations such as Momentum's - * Jaguar ATX. This option exploits the highmem code in the kernel so is - * always enabled together with CONFIG_HIGHMEM but at this time doesn't - * actually add highmem functionality. - */ - -#ifdef CONFIG_LIMITED_DMA - -/* - * These are the default functions for the no-highmem case from - * <linux/highmem.h> - */ -static inline void *kmap(struct page *page) -{ - might_sleep(); - return page_address(page); -} - -#define kunmap(page) do { (void) (page); } while (0) - -static inline void *kmap_atomic(struct page *page, enum km_type type) -{ - pagefault_disable(); - return page_address(page); -} - -static inline void kunmap_atomic(void *kvaddr, enum km_type type) -{ - pagefault_enable(); -} - -#define kmap_atomic_pfn(pfn, idx) kmap_atomic(pfn_to_page(pfn), (idx)) - -#define kmap_atomic_to_page(ptr) virt_to_page(ptr) - -#define flush_cache_kmaps() do { } while (0) - -#else /* LIMITED_DMA */ - extern void *__kmap(struct page *page); extern void __kunmap(struct page *page); extern void *__kmap_atomic(struct page *page, enum km_type type); @@ -103,8 +63,6 @@ extern struct page *__kmap_atomic_to_page(void *ptr); #define flush_cache_kmaps() flush_cache_all() -#endif /* LIMITED_DMA */ - #endif /* __KERNEL__ */ #endif /* _ASM_HIGHMEM_H */ diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h index 24a8d51a55a3..684a501c04cf 100644 --- a/include/asm-mips/mach-cobalt/cobalt.h +++ b/include/asm-mips/mach-cobalt/cobalt.h @@ -69,6 +69,8 @@ #define COBALT_BRD_ID_QUBE2 0x5 #define COBALT_BRD_ID_RAQ2 0x6 +extern int cobalt_board_id; + #define PCI_CFG_SET(devfn,where) \ GT_WRITE(GT_PCI0_CFGADDR_OFS, (0x80000000 | (PCI_SLOT (devfn) << 11) | \ (PCI_FUNC (devfn) << 8) | (where))) diff --git a/include/asm-mips/mach-ja/cpu-feature-overrides.h b/include/asm-mips/mach-ja/cpu-feature-overrides.h deleted file mode 100644 index 84b6dead0e8a..000000000000 --- a/include/asm-mips/mach-ja/cpu-feature-overrides.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2003, 2004 Ralf Baechle - */ -#ifndef __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H -#define __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H - -/* - * Momentum Jaguar ATX always has the RM9000 processor. - */ -#define cpu_has_watch 1 -#define cpu_has_mips16 0 -#define cpu_has_divec 0 -#define cpu_has_vce 0 -#define cpu_has_cache_cdex_p 0 -#define cpu_has_cache_cdex_s 0 -#define cpu_has_prefetch 1 -#define cpu_has_mcheck 0 -#define cpu_has_ejtag 0 - -#define cpu_has_llsc 1 -#define cpu_has_vtag_icache 0 -#define cpu_has_dc_aliases 0 -#define cpu_has_ic_fills_f_dc 0 -#define cpu_has_dsp 0 -#define cpu_icache_snoops_remote_store 0 - -#define cpu_has_nofpuex 0 -#define cpu_has_64bits 1 - -#define cpu_has_inclusive_pcaches 0 - -#define cpu_dcache_line_size() 32 -#define cpu_icache_line_size() 32 -#define cpu_scache_line_size() 32 - -#define cpu_has_mips32r1 0 -#define cpu_has_mips32r2 0 -#define cpu_has_mips64r1 0 -#define cpu_has_mips64r2 0 - -#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */ diff --git a/include/asm-mips/mach-ja/spaces.h b/include/asm-mips/mach-ja/spaces.h deleted file mode 100644 index 8466a0e69c79..000000000000 --- a/include/asm-mips/mach-ja/spaces.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle - * Copyright (C) 2000, 2002 Maciej W. Rozycki - * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. - */ -#ifndef __ASM_MACH_JA_SPACES_H -#define __ASM_MACH_JA_SPACES_H - -/* - * Memory above this physical address will be considered highmem. - */ -#define HIGHMEM_START 0x08000000UL - -#include_next <spaces.h> - -#endif /* __ASM_MACH_JA_SPACES_H */ diff --git a/include/asm-mips/mips-boards/malta.h b/include/asm-mips/mips-boards/malta.h index b0ba3c5a921e..eec91001bb65 100644 --- a/include/asm-mips/mips-boards/malta.h +++ b/include/asm-mips/mips-boards/malta.h @@ -25,6 +25,10 @@ #include <asm/mips-boards/msc01_pci.h> #include <asm/gt64120.h> +/* Mips interrupt controller found in SOCit variations */ +#define MIPS_MSC01_IC_REG_BASE 0x1bc40000 +#define MIPS_SOCITSC_IC_REG_BASE 0x1ffa0000 + /* * Malta I/O ports base address for the Galileo GT64120 and Algorithmics * Bonito system controllers. diff --git a/include/asm-mips/msc01_ic.h b/include/asm-mips/msc01_ic.h index aa7ad9a71762..7989b9ffc1d2 100644 --- a/include/asm-mips/msc01_ic.h +++ b/include/asm-mips/msc01_ic.h @@ -94,10 +94,7 @@ /* * MIPS System controller interrupt register base. * - * FIXME - are these macros specific to Malta and co or to the MSC? If the - * latter, they should be moved elsewhere. */ -#define MIPS_MSC01_IC_REG_BASE 0x1bc40000 /***************************************************************************** * Absolute register addresses @@ -144,7 +141,7 @@ typedef struct msc_irqmap { #define MSC01_IRQ_LEVEL 0 #define MSC01_IRQ_EDGE 1 -extern void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq); +extern void __init init_msc_irqs(unsigned long icubase, unsigned int base, msc_irqmap_t *imp, int nirq); extern void ll_msc_irq(void); #endif /* __ASM_MIPS_BOARDS_MSC01_IC_H */ diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index d3fbd83ff545..5c3239dad0f2 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h @@ -190,10 +190,6 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) #define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) -#ifdef CONFIG_LIMITED_DMA -#define WANT_PAGE_VIRTUAL -#endif - #include <asm-generic/memory_model.h> #include <asm-generic/page.h> diff --git a/include/asm-mips/poll.h b/include/asm-mips/poll.h index 70881f8c5c50..47b952080431 100644 --- a/include/asm-mips/poll.h +++ b/include/asm-mips/poll.h @@ -1,28 +1,9 @@ #ifndef __ASM_POLL_H #define __ASM_POLL_H -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 - -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 #define POLLWRNORM POLLOUT #define POLLWRBAND 0x0100 -/* These seem to be more or less nonstandard ... */ -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; +#include <asm-generic/poll.h> #endif /* __ASM_POLL_H */ diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h index d7a65135d837..ce51213d84f9 100644 --- a/include/asm-mips/serial.h +++ b/include/asm-mips/serial.h @@ -81,25 +81,6 @@ #define STD_SERIAL_PORT_DEFNS #endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */ -#ifdef CONFIG_MOMENCO_JAGUAR_ATX -/* Ordinary NS16552 duart with a 20MHz crystal. */ -#define JAGUAR_ATX_UART_CLK 20000000 -#define JAGUAR_ATX_BASE_BAUD (JAGUAR_ATX_UART_CLK / 16) - -#define JAGUAR_ATX_SERIAL1_IRQ 6 -#define JAGUAR_ATX_SERIAL1_BASE 0xfd000023L - -#define _JAGUAR_ATX_SERIAL_INIT(int, base) \ - { .baud_base = JAGUAR_ATX_BASE_BAUD, irq: int, \ - .flags = (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ - .iomem_base = (u8 *) base, iomem_reg_shift: 2, \ - io_type: SERIAL_IO_MEM } -#define MOMENCO_JAGUAR_ATX_SERIAL_PORT_DEFNS \ - _JAGUAR_ATX_SERIAL_INIT(JAGUAR_ATX_SERIAL1_IRQ, JAGUAR_ATX_SERIAL1_BASE) -#else -#define MOMENCO_JAGUAR_ATX_SERIAL_PORT_DEFNS -#endif - #ifdef CONFIG_MOMENCO_OCELOT_3 #define OCELOT_3_BASE_BAUD ( 20000000 / 16 ) #define OCELOT_3_SERIAL_IRQ 6 @@ -134,27 +115,6 @@ #define MOMENCO_OCELOT_SERIAL_PORT_DEFNS #endif -#ifdef CONFIG_MOMENCO_OCELOT_G -/* Ordinary NS16552 duart with a 20MHz crystal. */ -#define OCELOT_G_BASE_BAUD ( 20000000 / 16 ) - -#define OCELOT_G_SERIAL1_IRQ 4 -#if 0 -#define OCELOT_G_SERIAL1_BASE 0xe0001020 -#else -#define OCELOT_G_SERIAL1_BASE 0xfd000020 -#endif - -#define _OCELOT_G_SERIAL_INIT(int, base) \ - { .baud_base = OCELOT_G_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS,\ - .iomem_base = (u8 *) base, .iomem_reg_shift = 2, \ - .io_type = SERIAL_IO_MEM } -#define MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \ - _OCELOT_G_SERIAL_INIT(OCELOT_G_SERIAL1_IRQ, OCELOT_G_SERIAL1_BASE) -#else -#define MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS -#endif - #ifdef CONFIG_MOMENCO_OCELOT_C /* Ordinary NS16552 duart with a 20MHz crystal. */ #define OCELOT_C_BASE_BAUD ( 20000000 / 16 ) @@ -210,7 +170,6 @@ IP32_SERIAL_PORT_DEFNS \ JAZZ_SERIAL_PORT_DEFNS \ STD_SERIAL_PORT_DEFNS \ - MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \ MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \ MOMENCO_OCELOT_SERIAL_PORT_DEFNS \ MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS diff --git a/include/asm-mips/sgi/seeq.h b/include/asm-mips/sgi/seeq.h new file mode 100644 index 000000000000..af0ffd76899d --- /dev/null +++ b/include/asm-mips/sgi/seeq.h @@ -0,0 +1,21 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 by Ralf Baechle + */ +#ifndef __ASM_SGI_SEEQ_H +#define __ASM_SGI_SEEQ_H + +#include <linux/if_ether.h> + +#include <asm/sgi/hpc3.h> + +struct sgiseeq_platform_data { + struct hpc3_regs *hpc; + unsigned int irq; + unsigned char mac[ETH_ALEN]; +}; + +#endif /* __ASM_SGI_SEEQ_H */ diff --git a/include/asm-mips/sgi/wd.h b/include/asm-mips/sgi/wd.h new file mode 100644 index 000000000000..0d6c3a4da891 --- /dev/null +++ b/include/asm-mips/sgi/wd.h @@ -0,0 +1,20 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 by Ralf Baechle + */ +#ifndef __ASM_SGI_WD_H +#define __ASM_SGI_WD_H + +#include <asm/sgi/hpc3.h> + +struct sgiwd93_platform_data { + unsigned int unit; + unsigned int irq; + struct hpc3_scsiregs *hregs; + unsigned char *wdregs; +}; + +#endif /* __ASM_SGI_WD_H */ diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 3713d256d369..bb0b289dbc9e 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -464,7 +464,10 @@ static inline unsigned long __cmpxchg_local(volatile void * ptr, extern void set_handler (unsigned long offset, void *addr, unsigned long len); extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len); -extern void *set_vi_handler (int n, void *addr); + +typedef void (*vi_handler_t)(void); +extern void *set_vi_handler (int n, vi_handler_t addr); + extern void *set_except_vector(int n, void *addr); extern unsigned long ebase; extern void per_cpu_trap_init(void); diff --git a/include/asm-parisc/poll.h b/include/asm-parisc/poll.h index 20e4d03c74cb..c98509d3149e 100644 --- a/include/asm-parisc/poll.h +++ b/include/asm-parisc/poll.h @@ -1,27 +1 @@ -#ifndef __PARISC_POLL_H -#define __PARISC_POLL_H - -/* These are specified by iBCS2 */ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif +#include <asm-generic/poll.h> diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index 9e4dd98eb220..a7b60bf639e0 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h @@ -48,8 +48,15 @@ extern void iseries_handle_interrupts(void); #define irqs_disabled() (local_get_flags() == 0) -#define hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) -#define hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) +#define __hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) +#define __hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) + +#define hard_irq_disable() \ + do { \ + __hard_irq_disable(); \ + get_paca()->soft_enabled = 0; \ + get_paca()->hard_enabled = 0; \ + } while(0) #else diff --git a/include/asm-powerpc/poll.h b/include/asm-powerpc/poll.h index 9c7d12631033..c98509d3149e 100644 --- a/include/asm-powerpc/poll.h +++ b/include/asm-powerpc/poll.h @@ -1,24 +1 @@ -#ifndef _ASM_POWERPC_POLL_H -#define _ASM_POWERPC_POLL_H - -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif /* _ASM_POWERPC_POLL_H */ +#include <asm-generic/poll.h> diff --git a/include/asm-s390/poll.h b/include/asm-s390/poll.h index 6f7f65ac7d27..c98509d3149e 100644 --- a/include/asm-s390/poll.h +++ b/include/asm-s390/poll.h @@ -1,35 +1 @@ -/* - * include/asm-s390/poll.h - * - * S390 version - * - * Derived from "include/asm-i386/poll.h" - */ - -#ifndef __S390_POLL_H -#define __S390_POLL_H - -/* These are specified by iBCS2 */ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif +#include <asm-generic/poll.h> diff --git a/include/asm-sh/poll.h b/include/asm-sh/poll.h index dbca9b32f4a6..c98509d3149e 100644 --- a/include/asm-sh/poll.h +++ b/include/asm-sh/poll.h @@ -1,27 +1 @@ -#ifndef __ASM_SH_POLL_H -#define __ASM_SH_POLL_H - -/* These are specified by iBCS2 */ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif /* __ASM_SH_POLL_H */ +#include <asm-generic/poll.h> diff --git a/include/asm-sh64/poll.h b/include/asm-sh64/poll.h index 3a6cbad08d28..ca2950267c53 100644 --- a/include/asm-sh64/poll.h +++ b/include/asm-sh64/poll.h @@ -1,37 +1,8 @@ #ifndef __ASM_SH64_POLL_H #define __ASM_SH64_POLL_H -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/poll.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ +#include <asm-generic/poll.h> -/* These are specified by iBCS2 */ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; +#undef POLLREMOVE #endif /* __ASM_SH64_POLL_H */ diff --git a/include/asm-sparc/poll.h b/include/asm-sparc/poll.h index 26f13fb35497..091d3ad2e830 100644 --- a/include/asm-sparc/poll.h +++ b/include/asm-sparc/poll.h @@ -1,24 +1,12 @@ #ifndef __SPARC_POLL_H #define __SPARC_POLL_H -#define POLLIN 1 -#define POLLPRI 2 -#define POLLOUT 4 -#define POLLERR 8 -#define POLLHUP 16 -#define POLLNVAL 32 -#define POLLRDNORM 64 #define POLLWRNORM POLLOUT -#define POLLRDBAND 128 #define POLLWRBAND 256 #define POLLMSG 512 #define POLLREMOVE 1024 #define POLLRDHUP 2048 -struct pollfd { - int fd; - short events; - short revents; -}; +#include <asm-generic/poll.h> #endif diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h index da9bdc5e5526..64471bcd96f9 100644 --- a/include/asm-sparc/unistd.h +++ b/include/asm-sparc/unistd.h @@ -327,8 +327,11 @@ #define __NR_getcpu 308 #define __NR_epoll_pwait 309 #define __NR_utimensat 310 +#define __NR_signalfd 311 +#define __NR_timerfd 312 +#define __NR_eventfd 313 -#define NR_SYSCALLS 311 +#define NR_SYSCALLS 314 #ifdef __KERNEL__ #define __ARCH_WANT_IPC_PARSE_VERSION diff --git a/include/asm-sparc64/poll.h b/include/asm-sparc64/poll.h index ab6b0d1bb4ad..ebeeb3816c40 100644 --- a/include/asm-sparc64/poll.h +++ b/include/asm-sparc64/poll.h @@ -1,24 +1,12 @@ #ifndef __SPARC64_POLL_H #define __SPARC64_POLL_H -#define POLLIN 1 -#define POLLPRI 2 -#define POLLOUT 4 -#define POLLERR 8 -#define POLLHUP 16 -#define POLLNVAL 32 -#define POLLRDNORM 64 #define POLLWRNORM POLLOUT -#define POLLRDBAND 128 #define POLLWRBAND 256 #define POLLMSG 512 #define POLLREMOVE 1024 #define POLLRDHUP 2048 -struct pollfd { - int fd; - short events; - short revents; -}; +#include <asm-generic/poll.h> #endif diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h index fcd627594f4c..53e96ed9c024 100644 --- a/include/asm-sparc64/unistd.h +++ b/include/asm-sparc64/unistd.h @@ -329,8 +329,11 @@ #define __NR_getcpu 308 #define __NR_epoll_pwait 309 #define __NR_utimensat 310 +#define __NR_signalfd 311 +#define __NR_timerfd 312 +#define __NR_eventfd 313 -#define NR_SYSCALLS 311 +#define NR_SYSCALLS 314 #ifdef __KERNEL__ /* sysconf options, for SunOS compatibility */ diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h index 261e2f4528f6..18a13ba74605 100644 --- a/include/asm-um/thread_info.h +++ b/include/asm-um/thread_info.h @@ -22,6 +22,7 @@ struct thread_info { 0-0xBFFFFFFF for user 0-0xFFFFFFFF for kernel */ struct restart_block restart_block; + struct thread_info *real_thread; /* Points to non-IRQ stack */ }; #define INIT_THREAD_INFO(tsk) \ @@ -35,6 +36,7 @@ struct thread_info { .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ + .real_thread = NULL, \ } #define init_thread_info (init_thread_union.thread_info) diff --git a/include/asm-v850/poll.h b/include/asm-v850/poll.h index c10176c2c28f..803cad0b9b59 100644 --- a/include/asm-v850/poll.h +++ b/include/asm-v850/poll.h @@ -1,24 +1,9 @@ #ifndef __V850_POLL_H__ #define __V850_POLL_H__ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 -#define POLLRDNORM 0x0040 #define POLLWRNORM POLLOUT -#define POLLRDBAND 0x0080 #define POLLWRBAND 0x0100 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 -struct pollfd { - int fd; - short events; - short revents; -}; +#include <asm-generic/poll.h> #endif /* __V850_POLL_H__ */ diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h index a09fe85c268e..a09427640764 100644 --- a/include/asm-x86_64/alternative.h +++ b/include/asm-x86_64/alternative.h @@ -103,6 +103,12 @@ static inline void alternatives_smp_switch(int smp) {} ".previous" : output : [feat] "i" (feature), ##input) /* + * use this macro(s) if you need more than one output parameter + * in alternative_io + */ +#define ASM_OUTPUT2(a, b) a, b + +/* * Alternative inline assembly for SMP. * * The LOCK_PREFIX macro defined here replaces the LOCK and diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h index dee632fa457d..e327c830da0c 100644 --- a/include/asm-x86_64/page.h +++ b/include/asm-x86_64/page.h @@ -80,6 +80,15 @@ extern unsigned long phys_base; #define __PHYSICAL_START CONFIG_PHYSICAL_START #define __KERNEL_ALIGN 0x200000 +/* + * Make sure kernel is aligned to 2MB address. Catching it at compile + * time is better. Change your config file and compile the kernel + * for a 2MB aligned address (CONFIG_PHYSICAL_START) + */ +#if (CONFIG_PHYSICAL_START % __KERNEL_ALIGN) != 0 +#error "CONFIG_PHYSICAL_START must be a multiple of 2MB" +#endif + #define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START) #define __START_KERNEL_map _AC(0xffffffff80000000, UL) #define __PAGE_OFFSET _AC(0xffff810000000000, UL) diff --git a/include/asm-x86_64/poll.h b/include/asm-x86_64/poll.h index c0475a9d8bb8..c98509d3149e 100644 --- a/include/asm-x86_64/poll.h +++ b/include/asm-x86_64/poll.h @@ -1,27 +1 @@ -#ifndef __x86_64_POLL_H -#define __x86_64_POLL_H - -/* These are specified by iBCS2 */ -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 -#define POLLWRNORM 0x0100 -#define POLLWRBAND 0x0200 -#define POLLMSG 0x0400 -#define POLLREMOVE 0x1000 -#define POLLRDHUP 0x2000 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif +#include <asm-generic/poll.h> diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index 595703949df3..ae1ed05f2814 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -621,6 +621,15 @@ __SYSCALL(__NR_vmsplice, sys_vmsplice) __SYSCALL(__NR_move_pages, sys_move_pages) #define __NR_utimensat 280 __SYSCALL(__NR_utimensat, sys_utimensat) +#define __IGNORE_getcpu /* implemented as a vsyscall */ +#define __NR_epoll_pwait 281 +__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait) +#define __NR_signalfd 282 +__SYSCALL(__NR_signalfd, sys_signalfd) +#define __NR_timerfd 282 +__SYSCALL(__NR_timerfd, sys_timerfd) +#define __NR_eventfd 283 +__SYSCALL(__NR_eventfd, sys_eventfd) #ifndef __NO_STUBS #define __ARCH_WANT_OLD_READDIR diff --git a/include/asm-xtensa/poll.h b/include/asm-xtensa/poll.h index 6fd94773e866..9d2d5993f068 100644 --- a/include/asm-xtensa/poll.h +++ b/include/asm-xtensa/poll.h @@ -11,28 +11,10 @@ #ifndef _XTENSA_POLL_H #define _XTENSA_POLL_H - -#define POLLIN 0x0001 -#define POLLPRI 0x0002 -#define POLLOUT 0x0004 - -#define POLLERR 0x0008 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 - -#define POLLRDNORM 0x0040 -#define POLLRDBAND 0x0080 #define POLLWRNORM POLLOUT #define POLLWRBAND 0x0100 - -#define POLLMSG 0x0400 #define POLLREMOVE 0x0800 -#define POLLRDHUP 0x2000 -struct pollfd { - int fd; - short events; - short revents; -}; +#include <asm-generic/poll.h> #endif /* _XTENSA_POLL_H */ diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 94cc04a143f2..bcd01f269f60 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -140,7 +140,6 @@ header-y += snmp.h header-y += sockios.h header-y += som.h header-y += sound.h -header-y += synclink.h header-y += taskstats.h header-y += telephony.h header-y += termios.h @@ -191,6 +190,7 @@ unifdef-y += errno.h unifdef-y += errqueue.h unifdef-y += ethtool.h unifdef-y += eventpoll.h +unifdef-y += signalfd.h unifdef-y += ext2_fs.h unifdef-y += ext3_fs.h unifdef-y += fb.h @@ -320,6 +320,7 @@ unifdef-y += sonypi.h unifdef-y += soundcard.h unifdef-y += stat.h unifdef-y += stddef.h +unifdef-y += synclink.h unifdef-y += sysctl.h unifdef-y += tcp.h unifdef-y += time.h diff --git a/include/linux/aio.h b/include/linux/aio.h index 43dc2ebfaa0e..b903fc02bdb7 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -119,6 +119,12 @@ struct kiocb { struct list_head ki_list; /* the aio core uses this * for cancellation */ + + /* + * If the aio_resfd field of the userspace iocb is not zero, + * this is the underlying file* to deliver event to. + */ + struct file *ki_eventfd; }; #define is_sync_kiocb(iocb) ((iocb)->ki_key == KIOCB_SYNC_KEY) diff --git a/include/linux/aio_abi.h b/include/linux/aio_abi.h index e3ca0a485cc6..9e0172931315 100644 --- a/include/linux/aio_abi.h +++ b/include/linux/aio_abi.h @@ -45,6 +45,14 @@ enum { IOCB_CMD_PWRITEV = 8, }; +/* + * Valid flags for the "aio_flags" member of the "struct iocb". + * + * IOCB_FLAG_RESFD - Set if the "aio_resfd" member of the "struct iocb" + * is valid. + */ +#define IOCB_FLAG_RESFD (1 << 0) + /* read() from /dev/aio returns these structures. */ struct io_event { __u64 data; /* the data field from the iocb */ @@ -84,7 +92,15 @@ struct iocb { /* extra parameters */ __u64 aio_reserved2; /* TODO: use this for a (struct sigevent *) */ - __u64 aio_reserved3; + + /* flags for the "struct iocb" */ + __u32 aio_flags; + + /* + * if the IOCB_FLAG_RESFD flag of "aio_flags" is set, this is an + * eventfd to signal AIO readiness to + */ + __u32 aio_resfd; }; /* 64 bytes */ #undef IFBIG diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h new file mode 100644 index 000000000000..b2e1ba325b9a --- /dev/null +++ b/include/linux/anon_inodes.h @@ -0,0 +1,16 @@ +/* + * include/linux/anon_inodes.h + * + * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> + * + */ + +#ifndef _LINUX_ANON_INODES_H +#define _LINUX_ANON_INODES_H + +int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, + const char *name, const struct file_operations *fops, + void *priv); + +#endif /* _LINUX_ANON_INODES_H */ + diff --git a/include/linux/audit.h b/include/linux/audit.h index 773e30df11ee..fccc6e50298a 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -91,6 +91,7 @@ #define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */ #define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */ #define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */ +#define AUDIT_OBJ_PID 1318 /* ptrace target */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ @@ -111,6 +112,7 @@ #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG 1799 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ +#define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ #define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */ @@ -148,6 +150,8 @@ #define AUDIT_CLASS_READ_32 5 #define AUDIT_CLASS_WRITE 6 #define AUDIT_CLASS_WRITE_32 7 +#define AUDIT_CLASS_SIGNAL 8 +#define AUDIT_CLASS_SIGNAL_32 9 /* This bitmask is used to validate user input. It represents all bits that * are currently used in an audit field constant understood by the kernel. @@ -337,6 +341,7 @@ struct mqstat; #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) extern int __init audit_register_class(int class, unsigned *list); extern int audit_classify_syscall(int abi, unsigned syscall); +extern int audit_classify_arch(int arch); #ifdef CONFIG_AUDITSYSCALL /* These are defined in auditsc.c */ /* Public API */ @@ -351,7 +356,8 @@ extern void audit_putname(const char *name); extern void __audit_inode(const char *name, const struct inode *inode); extern void __audit_inode_child(const char *dname, const struct inode *inode, const struct inode *parent); -extern void __audit_inode_update(const struct inode *inode); +extern void __audit_ptrace(struct task_struct *t); + static inline int audit_dummy_context(void) { void *p = current->audit_context; @@ -372,9 +378,12 @@ static inline void audit_inode_child(const char *dname, if (unlikely(!audit_dummy_context())) __audit_inode_child(dname, inode, parent); } -static inline void audit_inode_update(const struct inode *inode) { +void audit_core_dumps(long signr); + +static inline void audit_ptrace(struct task_struct *t) +{ if (unlikely(!audit_dummy_context())) - __audit_inode_update(inode); + __audit_ptrace(t); } /* Private API (for audit.c only) */ @@ -447,6 +456,7 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) return 0; } extern int audit_n_rules; +extern int audit_signals; #else #define audit_alloc(t) ({ 0; }) #define audit_free(t) do { ; } while (0) @@ -457,10 +467,9 @@ extern int audit_n_rules; #define audit_putname(n) do { ; } while (0) #define __audit_inode(n,i) do { ; } while (0) #define __audit_inode_child(d,i,p) do { ; } while (0) -#define __audit_inode_update(i) do { ; } while (0) #define audit_inode(n,i) do { ; } while (0) #define audit_inode_child(d,i,p) do { ; } while (0) -#define audit_inode_update(i) do { ; } while (0) +#define audit_core_dumps(i) do { ; } while (0) #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) #define audit_get_loginuid(c) ({ -1; }) #define audit_log_task_context(b) do { ; } while (0) @@ -477,7 +486,9 @@ extern int audit_n_rules; #define audit_mq_timedreceive(d,l,p,t) ({ 0; }) #define audit_mq_notify(d,n) ({ 0; }) #define audit_mq_getsetattr(d,s) ({ 0; }) +#define audit_ptrace(t) ((void)0) #define audit_n_rules 0 +#define audit_signals 0 #endif #ifdef CONFIG_AUDIT diff --git a/include/linux/compat.h b/include/linux/compat.h index 70a157a130bb..636502c02734 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -225,6 +225,11 @@ static inline int compat_timespec_compare(struct compat_timespec *lhs, return lhs->tv_nsec - rhs->tv_nsec; } +extern int get_compat_itimerspec(struct itimerspec *dst, + const struct compat_itimerspec __user *src); +extern int put_compat_itimerspec(struct compat_itimerspec __user *dst, + const struct itimerspec *src); + asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); extern int compat_printk(const char *fmt, ...); diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h new file mode 100644 index 000000000000..0d6ecc60b94d --- /dev/null +++ b/include/linux/eventfd.h @@ -0,0 +1,29 @@ +/* + * include/linux/eventfd.h + * + * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> + * + */ + +#ifndef _LINUX_EVENTFD_H +#define _LINUX_EVENTFD_H + + +#ifdef __KERNEL__ + +#ifdef CONFIG_EVENTFD + +struct file *eventfd_fget(int fd); +int eventfd_signal(struct file *file, int n); + +#else /* CONFIG_EVENTFD */ + +#define eventfd_fget(fd) ERR_PTR(-ENOSYS) +#define eventfd_signal(f, n) 0 + +#endif /* CONFIG_EVENTFD */ + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_EVENTFD_H */ + diff --git a/include/linux/genhd.h b/include/linux/genhd.h index f589559cf070..4c03ee353e78 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -434,6 +434,10 @@ static inline struct block_device *bdget_disk(struct gendisk *disk, int index) #endif -#endif +#else /* CONFIG_BLOCK */ + +static inline void printk_all_partitions(void) { } + +#endif /* CONFIG_BLOCK */ #endif diff --git a/include/linux/hid.h b/include/linux/hid.h index 37076b116ed0..827ee748fd4c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -275,6 +275,7 @@ struct hid_item { #define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000 #define HID_QUIRK_DUPLICATE_USAGES 0x00200000 #define HID_QUIRK_RESET_LEDS 0x00400000 +#define HID_QUIRK_SWAPPED_MIN_MAX 0x00800000 /* * This is the global environment of the parser. This information is diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 0e8da684ce68..aa83d4163096 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -117,6 +117,7 @@ #define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */ #define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */ #define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */ +#define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */ #define I2C_DRIVERID_I2CDEV 900 #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 45170b2fa253..276ccaa2670c 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -65,9 +65,9 @@ .posix_timers = LIST_HEAD_INIT(sig.posix_timers), \ .cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers), \ .rlim = INIT_RLIMITS, \ - .pgrp = 1, \ + .pgrp = 0, \ .tty_old_pgrp = NULL, \ - { .__session = 1}, \ + { .__session = 0}, \ } extern struct nsproxy init_nsproxy; @@ -84,10 +84,33 @@ extern struct nsproxy init_nsproxy; .count = ATOMIC_INIT(1), \ .action = { { { .sa_handler = NULL, } }, }, \ .siglock = __SPIN_LOCK_UNLOCKED(sighand.siglock), \ + .signalfd_list = LIST_HEAD_INIT(sighand.signalfd_list), \ } extern struct group_info init_groups; +#define INIT_STRUCT_PID { \ + .count = ATOMIC_INIT(1), \ + .nr = 0, \ + /* Don't put this struct pid in pid_hash */ \ + .pid_chain = { .next = NULL, .pprev = NULL }, \ + .tasks = { \ + { .first = &init_task.pids[PIDTYPE_PID].node }, \ + { .first = &init_task.pids[PIDTYPE_PGID].node }, \ + { .first = &init_task.pids[PIDTYPE_SID].node }, \ + }, \ + .rcu = RCU_HEAD_INIT, \ +} + +#define INIT_PID_LINK(type) \ +{ \ + .node = { \ + .next = NULL, \ + .pprev = &init_struct_pid.tasks[type].first, \ + }, \ + .pid = &init_struct_pid, \ +} + /* * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) @@ -139,6 +162,11 @@ extern struct group_info init_groups; .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ .fs_excl = ATOMIC_INIT(0), \ .pi_lock = __SPIN_LOCK_UNLOCKED(tsk.pi_lock), \ + .pids = { \ + [PIDTYPE_PID] = INIT_PID_LINK(PIDTYPE_PID), \ + [PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID), \ + [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \ + }, \ INIT_TRACE_IRQFLAGS \ INIT_LOCKDEP \ } diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index f7b01b9a35b3..5323f6275854 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -241,6 +241,16 @@ static inline void __deprecated save_and_cli(unsigned long *x) #define save_and_cli(x) save_and_cli(&x) #endif /* CONFIG_SMP */ +/* Some architectures might implement lazy enabling/disabling of + * interrupts. In some cases, such as stop_machine, we might want + * to ensure that after a local_irq_disable(), interrupts have + * really been disabled in hardware. Such architectures need to + * implement the following hook. + */ +#ifndef hard_irq_disable +#define hard_irq_disable() do { } while(0) +#endif + /* PLEASE, avoid to allocate new softirqs, if you need not _really_ high frequency threaded job scheduling. For almost all the purposes tasklets are more than enough. F.e. all serial device BHs et diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 8645181fca0f..45353d757cd0 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -213,6 +213,17 @@ extern enum system_states { extern void dump_stack(void); +enum { + DUMP_PREFIX_NONE, + DUMP_PREFIX_ADDRESS, + DUMP_PREFIX_OFFSET +}; +extern void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf, + size_t linebuflen); +extern void print_hex_dump(const char *level, int prefix_type, + void *buf, size_t len); +#define hex_asc(x) "0123456789abcdef"[x] + #ifdef DEBUG /* If you are writing a driver, please use dev_dbg instead */ #define pr_debug(fmt,arg...) \ @@ -299,8 +310,8 @@ static inline int __attribute__ ((format (printf, 1, 2))) pr_debug(const char * * */ #define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) /* * Check at compile time that something is of a particular type. diff --git a/include/linux/libata.h b/include/linux/libata.h index 7906d750aa77..27d936279574 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -140,7 +140,6 @@ enum { ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */ ATA_DFLAG_NCQ_OFF = (1 << 9), /* device limited to non-NCQ mode */ - ATA_DFLAG_SUSPENDED = (1 << 10), /* device suspended */ ATA_DFLAG_INIT_MASK = (1 << 16) - 1, ATA_DFLAG_DETACH = (1 << 16), @@ -191,6 +190,7 @@ enum { ATA_PFLAG_LOADING = (1 << 4), /* boot/loading probe */ ATA_PFLAG_UNLOADING = (1 << 5), /* module is unloading */ ATA_PFLAG_SCSI_HOTPLUG = (1 << 6), /* SCSI hotplug scheduled */ + ATA_PFLAG_INITIALIZING = (1 << 7), /* being initialized, don't touch */ ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */ ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */ @@ -254,10 +254,6 @@ enum { ATA_DMA_PAD_SZ = 4, ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE, - /* masks for port functions */ - ATA_PORT_PRIMARY = (1 << 0), - ATA_PORT_SECONDARY = (1 << 1), - /* ering size */ ATA_ERING_SIZE = 32, @@ -268,13 +264,9 @@ enum { ATA_EH_REVALIDATE = (1 << 0), ATA_EH_SOFTRESET = (1 << 1), ATA_EH_HARDRESET = (1 << 2), - ATA_EH_SUSPEND = (1 << 3), - ATA_EH_RESUME = (1 << 4), - ATA_EH_PM_FREEZE = (1 << 5), ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, - ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_SUSPEND | - ATA_EH_RESUME | ATA_EH_PM_FREEZE, + ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE, /* ata_eh_info->flags */ ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ @@ -466,7 +458,7 @@ struct ata_device { struct ata_ering ering; int spdn_cnt; unsigned int horkage; /* List of broken features */ -#ifdef CONFIG_SATA_ACPI +#ifdef CONFIG_ATA_ACPI /* ACPI objects info */ acpi_handle obj_handle; #endif @@ -693,8 +685,8 @@ extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI -extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, - unsigned int n_ports); +extern int ata_pci_init_one (struct pci_dev *pdev, + const struct ata_port_info * const * ppi); extern void ata_pci_remove_one (struct pci_dev *pdev); #ifdef CONFIG_PM extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg); @@ -736,8 +728,6 @@ extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val); extern int ata_port_online(struct ata_port *ap); extern int ata_port_offline(struct ata_port *ap); #ifdef CONFIG_PM -extern int ata_scsi_device_resume(struct scsi_device *); -extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t mesg); extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg); extern void ata_host_resume(struct ata_host *host); #endif @@ -861,11 +851,11 @@ struct pci_bits { unsigned long val; }; -extern int ata_pci_init_native_host(struct ata_host *host, - unsigned int port_mask); +extern int ata_pci_init_native_host(struct ata_host *host); +extern int ata_pci_init_bmdma(struct ata_host *host); extern int ata_pci_prepare_native_host(struct pci_dev *pdev, const struct ata_port_info * const * ppi, - int n_ports, struct ata_host **r_host); + struct ata_host **r_host); extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits); extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long); #endif /* CONFIG_PCI */ @@ -1008,11 +998,6 @@ static inline unsigned int ata_dev_absent(const struct ata_device *dev) return ata_class_absent(dev->class); } -static inline unsigned int ata_dev_ready(const struct ata_device *dev) -{ - return ata_dev_enabled(dev) && !(dev->flags & ATA_DFLAG_SUSPENDED); -} - /* * port helpers */ diff --git a/include/linux/list.h b/include/linux/list.h index 9202703be2a4..f29fc9c1a964 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -264,8 +264,8 @@ static inline void list_del_init(struct list_head *entry) */ static inline void list_move(struct list_head *list, struct list_head *head) { - __list_del(list->prev, list->next); - list_add(list, head); + __list_del(list->prev, list->next); + list_add(list, head); } /** @@ -276,8 +276,8 @@ static inline void list_move(struct list_head *list, struct list_head *head) static inline void list_move_tail(struct list_head *list, struct list_head *head) { - __list_del(list->prev, list->next); - list_add_tail(list, head); + __list_del(list->prev, list->next); + list_add_tail(list, head); } /** diff --git a/include/linux/magic.h b/include/linux/magic.h index a9c6567fe70c..9d713c03e3da 100644 --- a/include/linux/magic.h +++ b/include/linux/magic.h @@ -14,6 +14,7 @@ #define ISOFS_SUPER_MAGIC 0x9660 #define JFFS2_SUPER_MAGIC 0x72b6 #define KVMFS_SUPER_MAGIC 0x19700426 +#define ANON_INODE_FS_MAGIC 0x09041934 #define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ #define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ diff --git a/include/linux/module.h b/include/linux/module.h index 792d483c9af7..e6e0f86ef5fc 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -124,7 +124,7 @@ extern struct module __this_module; */ #define MODULE_LICENSE(_license) MODULE_INFO(license, _license) -/* Author, ideally of form NAME <EMAIL>[, NAME <EMAIL>]*[ and NAME <EMAIL>] */ +/* Author, ideally of form NAME[, NAME]*[ and NAME] */ #define MODULE_AUTHOR(_author) MODULE_INFO(author, _author) /* What your module does. */ diff --git a/include/linux/mpage.h b/include/linux/mpage.h index cc5fb75af78a..068a0c9946af 100644 --- a/include/linux/mpage.h +++ b/include/linux/mpage.h @@ -12,7 +12,6 @@ #ifdef CONFIG_BLOCK struct writeback_control; -typedef int (writepage_t)(struct page *page, struct writeback_control *wbc); int mpage_readpages(struct address_space *mapping, struct list_head *pages, unsigned nr_pages, get_block_t get_block); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 30446222b396..f671cd2f133f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -467,6 +467,8 @@ struct net_device /* device index hash chain */ struct hlist_node index_hlist; + struct net_device *link_watch_next; + /* register/unregister state machine */ enum { NETREG_UNINITIALIZED=0, NETREG_REGISTERED, /* completed register_netdevice */ diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 022edfa97ed9..7e733a6ba4f6 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -54,6 +54,14 @@ struct xt_entry_target unsigned char data[0]; }; +#define XT_TARGET_INIT(__name, __size) \ +{ \ + .target.u.user = { \ + .target_size = XT_ALIGN(__size), \ + .name = __name, \ + }, \ +} + struct xt_standard_target { struct xt_entry_target target; diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index 24c8786d12e9..584cd1b18f12 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -238,6 +238,47 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e */ #ifdef __KERNEL__ +/* Standard entry. */ +struct arpt_standard +{ + struct arpt_entry entry; + struct arpt_standard_target target; +}; + +struct arpt_error_target +{ + struct arpt_entry_target target; + char errorname[ARPT_FUNCTION_MAXNAMELEN]; +}; + +struct arpt_error +{ + struct arpt_entry entry; + struct arpt_error_target target; +}; + +#define ARPT_ENTRY_INIT(__size) \ +{ \ + .target_offset = sizeof(struct arpt_entry), \ + .next_offset = (__size), \ +} + +#define ARPT_STANDARD_INIT(__verdict) \ +{ \ + .entry = ARPT_ENTRY_INIT(sizeof(struct arpt_standard)), \ + .target = XT_TARGET_INIT(ARPT_STANDARD_TARGET, \ + sizeof(struct arpt_standard_target)), \ + .target.verdict = -(__verdict) - 1, \ +} + +#define ARPT_ERROR_INIT \ +{ \ + .entry = ARPT_ENTRY_INIT(sizeof(struct arpt_error)), \ + .target = XT_TARGET_INIT(ARPT_ERROR_TARGET, \ + sizeof(struct arpt_error_target)), \ + .target.errorname = "ERROR", \ +} + #define arpt_register_target(tgt) \ ({ (tgt)->family = NF_ARP; \ xt_register_target(tgt); }) diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 9527296595cd..2f46dd728ee1 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -295,6 +295,28 @@ struct ipt_error struct ipt_error_target target; }; +#define IPT_ENTRY_INIT(__size) \ +{ \ + .target_offset = sizeof(struct ipt_entry), \ + .next_offset = (__size), \ +} + +#define IPT_STANDARD_INIT(__verdict) \ +{ \ + .entry = IPT_ENTRY_INIT(sizeof(struct ipt_standard)), \ + .target = XT_TARGET_INIT(IPT_STANDARD_TARGET, \ + sizeof(struct xt_standard_target)), \ + .target.verdict = -(__verdict) - 1, \ +} + +#define IPT_ERROR_INIT \ +{ \ + .entry = IPT_ENTRY_INIT(sizeof(struct ipt_error)), \ + .target = XT_TARGET_INIT(IPT_ERROR_TARGET, \ + sizeof(struct ipt_error_target)), \ + .target.errorname = "ERROR", \ +} + extern unsigned int ipt_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 61aa10412fc8..4686f8342cbd 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -123,6 +123,28 @@ struct ip6t_error struct ip6t_error_target target; }; +#define IP6T_ENTRY_INIT(__size) \ +{ \ + .target_offset = sizeof(struct ip6t_entry), \ + .next_offset = (__size), \ +} + +#define IP6T_STANDARD_INIT(__verdict) \ +{ \ + .entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)), \ + .target = XT_TARGET_INIT(IP6T_STANDARD_TARGET, \ + sizeof(struct ip6t_standard_target)), \ + .target.verdict = -(__verdict) - 1, \ +} + +#define IP6T_ERROR_INIT \ +{ \ + .entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_error)), \ + .target = XT_TARGET_INIT(IP6T_ERROR_TARGET, \ + sizeof(struct ip6t_error_target)), \ + .target.errorname = "ERROR", \ +} + /* * New IP firewall options for [gs]etsockopt at the RAW IP level. * Unlike BSD Linux inherits IP options so you don't have to use diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ae849f0d4430..ccd85e4d3b8f 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -370,6 +370,7 @@ #define PCI_DEVICE_ID_ATI_IXP600_SATA 0x4380 #define PCI_DEVICE_ID_ATI_IXP600_SMBUS 0x4385 #define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c +#define PCI_DEVICE_ID_ATI_IXP700_SATA 0x4390 #define PCI_VENDOR_ID_VLSI 0x1004 #define PCI_DEVICE_ID_VLSI_82C592 0x0005 diff --git a/include/linux/pid.h b/include/linux/pid.h index 2ac27f9997dd..1e0e4e3423a6 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -51,6 +51,8 @@ struct pid struct rcu_head rcu; }; +extern struct pid init_struct_pid; + struct pid_link { struct hlist_node node; @@ -76,8 +78,7 @@ extern struct pid *get_task_pid(struct task_struct *task, enum pid_type type); * write-held. */ extern int FASTCALL(attach_pid(struct task_struct *task, - enum pid_type type, int nr)); - + enum pid_type type, struct pid *pid)); extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type)); extern void FASTCALL(transfer_pid(struct task_struct *old, struct task_struct *new, enum pid_type)); diff --git a/include/linux/sched.h b/include/linux/sched.h index 17b72d88c4cb..a81897e2a244 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -88,6 +88,7 @@ struct sched_param { struct exec_domain; struct futex_pi_state; +struct bio; /* * List of flags we want to share for kernel threads, @@ -391,6 +392,7 @@ struct sighand_struct { atomic_t count; struct k_sigaction action[_NSIG]; spinlock_t siglock; + struct list_head signalfd_list; }; struct pacct_struct { @@ -469,6 +471,7 @@ struct signal_struct { cputime_t utime, stime, cutime, cstime; unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; + unsigned long inblock, oublock, cinblock, coublock; /* * Cumulative ns of scheduled CPU time for dead threads in the @@ -1014,6 +1017,9 @@ struct task_struct { /* journalling filesystem info */ void *journal_info; +/* stacked block device info */ + struct bio *bio_list, **bio_tail; + /* VM state */ struct reclaim_state *reclaim_state; diff --git a/include/linux/signal.h b/include/linux/signal.h index 3fa0fab4a04b..9a5eac508e5e 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -233,6 +233,7 @@ static inline int valid_signal(unsigned long sig) return sig <= _NSIG ? 1 : 0; } +extern int next_signal(struct sigpending *pending, sigset_t *mask); extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p); extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *); extern long do_sigpending(void __user *, unsigned long); diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h new file mode 100644 index 000000000000..510429495690 --- /dev/null +++ b/include/linux/signalfd.h @@ -0,0 +1,97 @@ +/* + * include/linux/signalfd.h + * + * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> + * + */ + +#ifndef _LINUX_SIGNALFD_H +#define _LINUX_SIGNALFD_H + + +struct signalfd_siginfo { + __u32 signo; + __s32 err; + __s32 code; + __u32 pid; + __u32 uid; + __s32 fd; + __u32 tid; + __u32 band; + __u32 overrun; + __u32 trapno; + __s32 status; + __s32 svint; + __u64 svptr; + __u64 utime; + __u64 stime; + __u64 addr; + + /* + * Pad strcture to 128 bytes. Remember to update the + * pad size when you add new memebers. We use a fixed + * size structure to avoid compatibility problems with + * future versions, and we leave extra space for additional + * members. We use fixed size members because this strcture + * comes out of a read(2) and we really don't want to have + * a compat on read(2). + */ + __u8 __pad[48]; +}; + + +#ifdef __KERNEL__ + +#ifdef CONFIG_SIGNALFD + +/* + * Deliver the signal to listening signalfd. This must be called + * with the sighand lock held. Same are the following that end up + * calling signalfd_deliver(). + */ +void signalfd_deliver(struct task_struct *tsk, int sig); + +/* + * No need to fall inside signalfd_deliver() if no signal listeners + * are available. + */ +static inline void signalfd_notify(struct task_struct *tsk, int sig) +{ + if (unlikely(!list_empty(&tsk->sighand->signalfd_list))) + signalfd_deliver(tsk, sig); +} + +/* + * The signal -1 is used to notify the signalfd that the sighand + * is on its way to be detached. + */ +static inline void signalfd_detach_locked(struct task_struct *tsk) +{ + if (unlikely(!list_empty(&tsk->sighand->signalfd_list))) + signalfd_deliver(tsk, -1); +} + +static inline void signalfd_detach(struct task_struct *tsk) +{ + struct sighand_struct *sighand = tsk->sighand; + + if (unlikely(!list_empty(&sighand->signalfd_list))) { + spin_lock_irq(&sighand->siglock); + signalfd_deliver(tsk, -1); + spin_unlock_irq(&sighand->siglock); + } +} + +#else /* CONFIG_SIGNALFD */ + +#define signalfd_deliver(t, s) do { } while (0) +#define signalfd_notify(t, s) do { } while (0) +#define signalfd_detach_locked(t) do { } while (0) +#define signalfd_detach(t) do { } while (0) + +#endif /* CONFIG_SIGNALFD */ + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_SIGNALFD_H */ + diff --git a/include/linux/synclink.h b/include/linux/synclink.h index c8b042667af1..5562fbf72095 100644 --- a/include/linux/synclink.h +++ b/include/linux/synclink.h @@ -291,4 +291,28 @@ struct gpio_desc { #define MGSL_IOCGGPIO _IOR(MGSL_MAGIC_IOC,17,struct gpio_desc) #define MGSL_IOCWAITGPIO _IOWR(MGSL_MAGIC_IOC,18,struct gpio_desc) +#ifdef __KERNEL__ +/* provide 32 bit ioctl compatibility on 64 bit systems */ +#ifdef CONFIG_COMPAT +#include <linux/compat.h> +struct MGSL_PARAMS32 { + compat_ulong_t mode; + unsigned char loopback; + unsigned short flags; + unsigned char encoding; + compat_ulong_t clock_speed; + unsigned char addr_filter; + unsigned short crc_type; + unsigned char preamble_length; + unsigned char preamble; + compat_ulong_t data_rate; + unsigned char data_bits; + unsigned char stop_bits; + unsigned char parity; +}; +#define MGSL_IOCSPARAMS32 _IOW(MGSL_MAGIC_IOC,0,struct MGSL_PARAMS32) +#define MGSL_IOCGPARAMS32 _IOR(MGSL_MAGIC_IOC,1,struct MGSL_PARAMS32) +#endif +#endif + #endif /* _SYNCLINK_H_ */ diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 3139f4412297..b02070eac422 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -604,6 +604,10 @@ asmlinkage long sys_get_robust_list(int pid, asmlinkage long sys_set_robust_list(struct robust_list_head __user *head, size_t len); asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache); +asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask); +asmlinkage long sys_timerfd(int ufd, int clockid, int flags, + const struct itimerspec __user *utmr); +asmlinkage long sys_eventfd(unsigned int count); int kernel_execve(const char *filename, char *const argv[], char *const envp[]); diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h index df2a319106b2..1218733ec6b5 100644 --- a/include/linux/task_io_accounting_ops.h +++ b/include/linux/task_io_accounting_ops.h @@ -10,11 +10,29 @@ static inline void task_io_account_read(size_t bytes) current->ioac.read_bytes += bytes; } +/* + * We approximate number of blocks, because we account bytes only. + * A 'block' is 512 bytes + */ +static inline unsigned long task_io_get_inblock(const struct task_struct *p) +{ + return p->ioac.read_bytes >> 9; +} + static inline void task_io_account_write(size_t bytes) { current->ioac.write_bytes += bytes; } +/* + * We approximate number of blocks, because we account bytes only. + * A 'block' is 512 bytes + */ +static inline unsigned long task_io_get_oublock(const struct task_struct *p) +{ + return p->ioac.write_bytes >> 9; +} + static inline void task_io_account_cancelled_write(size_t bytes) { current->ioac.cancelled_write_bytes += bytes; @@ -31,10 +49,20 @@ static inline void task_io_account_read(size_t bytes) { } +static inline unsigned long task_io_get_inblock(const struct task_struct *p) +{ + return 0; +} + static inline void task_io_account_write(size_t bytes) { } +static inline unsigned long task_io_get_oublock(const struct task_struct *p) +{ + return 0; +} + static inline void task_io_account_cancelled_write(size_t bytes) { } diff --git a/include/linux/timerfd.h b/include/linux/timerfd.h new file mode 100644 index 000000000000..cf2b10d75731 --- /dev/null +++ b/include/linux/timerfd.h @@ -0,0 +1,17 @@ +/* + * include/linux/timerfd.h + * + * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> + * + */ + +#ifndef _LINUX_TIMERFD_H +#define _LINUX_TIMERFD_H + + +#define TFD_TIMER_ABSTIME (1 << 0) + + + +#endif /* _LINUX_TIMERFD_H */ + diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 659487e3ebeb..85c95cd39bc3 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -52,6 +52,11 @@ * This routine allows the tty driver to implement * device-specific ioctl's. If the ioctl number passed in cmd * is not recognized by the driver, it should return ENOIOCTLCMD. + * + * long (*compat_ioctl)(struct tty_struct *tty, struct file * file, + * unsigned int cmd, unsigned long arg); + * + * implement ioctl processing for 32 bit process on 64 bit system * * void (*set_termios)(struct tty_struct *tty, struct ktermios * old); * @@ -132,6 +137,8 @@ struct tty_operations { int (*chars_in_buffer)(struct tty_struct *tty); int (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); + long (*compat_ioctl)(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg); void (*set_termios)(struct tty_struct *tty, struct ktermios * old); void (*throttle)(struct tty_struct * tty); void (*unthrottle)(struct tty_struct * tty); @@ -193,6 +200,8 @@ struct tty_driver { int (*chars_in_buffer)(struct tty_struct *tty); int (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); + long (*compat_ioctl)(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg); void (*set_termios)(struct tty_struct *tty, struct ktermios * old); void (*throttle)(struct tty_struct * tty); void (*unthrottle)(struct tty_struct * tty); diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index d75932e27710..6226504d9108 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -59,6 +59,11 @@ * low-level driver can "grab" an ioctl request before the line * discpline has a chance to see it. * + * long (*compat_ioctl)(struct tty_struct * tty, struct file * file, + * unsigned int cmd, unsigned long arg); + * + * Process ioctl calls from 32-bit process on 64-bit system + * * void (*set_termios)(struct tty_struct *tty, struct ktermios * old); * * This function notifies the line discpline that a change has @@ -118,6 +123,8 @@ struct tty_ldisc { const unsigned char * buf, size_t nr); int (*ioctl)(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); + long (*compat_ioctl)(struct tty_struct * tty, struct file * file, + unsigned int cmd, unsigned long arg); void (*set_termios)(struct tty_struct *tty, struct ktermios * old); unsigned int (*poll)(struct tty_struct *, struct file *, struct poll_table_struct *); diff --git a/include/linux/writeback.h b/include/linux/writeback.h index daa6c125f66e..050915b59576 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -111,9 +111,15 @@ balance_dirty_pages_ratelimited(struct address_space *mapping) balance_dirty_pages_ratelimited_nr(mapping, 1); } +typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc, + void *data); + int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); -extern int generic_writepages(struct address_space *mapping, - struct writeback_control *wbc); +int generic_writepages(struct address_space *mapping, + struct writeback_control *wbc); +int write_cache_pages(struct address_space *mapping, + struct writeback_control *wbc, writepage_t writepage, + void *data); int do_writepages(struct address_space *mapping, struct writeback_control *wbc); int sync_page_range(struct inode *inode, struct address_space *mapping, loff_t pos, loff_t count); diff --git a/include/media/saa7146.h b/include/media/saa7146.h index 796bcf151a3a..d3f4f5a38214 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h @@ -58,6 +58,7 @@ struct saa7146_pgtable { unsigned long offset; /* used for custom pagetables (used for example by budget dvb cards) */ struct scatterlist *slist; + int nents; }; struct saa7146_pci_extension_data { @@ -157,6 +158,7 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt); void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt); int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length ); char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt); +void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt); void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data); int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop); diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index 50e33b0e9349..cce20ed5cf6c 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -216,6 +216,8 @@ void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data); extern struct saa7146_use_ops saa7146_video_uops; int saa7146_start_preview(struct saa7146_fh *fh); int saa7146_stop_preview(struct saa7146_fh *fh); +int saa7146_video_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg); /* from saa7146_vbi.c */ extern struct saa7146_use_ops saa7146_vbi_uops; diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 1c6b8bd09b9a..4732432f8eb0 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -183,13 +183,6 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct); extern void nf_conntrack_flush(void); -extern struct nf_conntrack_helper * -nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple); -extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); - -extern struct nf_conntrack_helper * -__nf_conntrack_helper_find_byname(const char *name); - extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig); diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index f32f714e5d92..96a58d8e1d3f 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -56,9 +56,6 @@ struct nf_conntrack_l3proto */ int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb); - /* Called when a conntrack entry is destroyed */ - void (*destroy)(struct nf_conn *conntrack); - /* * Called before tracking. * *dataoff: offset of protocol header (TCP, UDP,...) in *pskb diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h index e76565459ad9..f9743187d57f 100644 --- a/include/net/netfilter/nf_nat_rule.h +++ b/include/net/netfilter/nf_nat_rule.h @@ -10,16 +10,11 @@ extern int nf_nat_rule_find(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, const struct net_device *out, - struct nf_conn *ct, - struct nf_nat_info *info); + struct nf_conn *ct); extern unsigned int -alloc_null_binding(struct nf_conn *ct, - struct nf_nat_info *info, - unsigned int hooknum); +alloc_null_binding(struct nf_conn *ct, unsigned int hooknum); extern unsigned int -alloc_null_binding_confirmed(struct nf_conn *ct, - struct nf_nat_info *info, - unsigned int hooknum); +alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum); #endif /* _NF_NAT_RULE_H */ diff --git a/include/net/udp.h b/include/net/udp.h index 98755ebaf163..496f89d45c8b 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -119,9 +119,16 @@ static inline void udp_lib_close(struct sock *sk, long timeout) } +struct udp_get_port_ops { + int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2); + int (*saddr_any)(const struct sock *sk); + unsigned int (*hash_port_and_rcv_saddr)(__u16 port, + const struct sock *sk); +}; + /* net/ipv4/udp.c */ extern int udp_get_port(struct sock *sk, unsigned short snum, - int (*saddr_cmp)(const struct sock *, const struct sock *)); + const struct udp_get_port_ops *ops); extern void udp_err(struct sk_buff *, u32); extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, diff --git a/include/net/udplite.h b/include/net/udplite.h index 635b0eafca95..50b4b424d1ca 100644 --- a/include/net/udplite.h +++ b/include/net/udplite.h @@ -120,5 +120,5 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb) extern void udplite4_register(void); extern int udplite_get_port(struct sock *sk, unsigned short snum, - int (*scmp)(const struct sock *, const struct sock *)); + const struct udp_get_port_ops *ops); #endif /* _UDPLITE_H */ diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h index c149d3b2558b..d647dae912b9 100644 --- a/include/sound/ak4114.h +++ b/include/sound/ak4114.h @@ -73,7 +73,7 @@ /* AK4114_REQ_FORMAT bits */ #define AK4114_MONO (1<<7) /* Double Sampling Frequency Mode: 0 = stereo, 1 = mono */ -#define AK4114_DIF2 (1<<5) /* Audio Data Control */ +#define AK4114_DIF2 (1<<6) /* Audio Data Control */ #define AK4114_DIF1 (1<<5) /* Audio Data Control */ #define AK4114_DIF0 (1<<4) /* Audio Data Control */ #define AK4114_DIF_16R (0) /* STDO: 16-bit, right justified */ @@ -158,7 +158,7 @@ #define AK4114_CHECK_NO_STAT (1<<0) /* no statistics */ #define AK4114_CHECK_NO_RATE (1<<1) /* no rate check */ -#define AK4114_CONTROLS 14 +#define AK4114_CONTROLS 15 typedef void (ak4114_write_t)(void *private_data, unsigned char addr, unsigned char data); typedef unsigned char (ak4114_read_t)(void *private_data, unsigned char addr); diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h index 8c88267e9bea..d5c1396c4c9e 100644 --- a/include/sound/mpu401.h +++ b/include/sound/mpu401.h @@ -50,6 +50,7 @@ #define MPU401_INFO_INTEGRATED (1 << 2) /* integrated h/w port */ #define MPU401_INFO_MMIO (1 << 3) /* MMIO access */ #define MPU401_INFO_TX_IRQ (1 << 4) /* independent TX irq */ +#define MPU401_INFO_UART_ONLY (1 << 5) /* No ENTER_UART cmd needed */ #define MPU401_MODE_BIT_INPUT 0 #define MPU401_MODE_BIT_OUTPUT 1 diff --git a/include/sound/pcm.h b/include/sound/pcm.h index deff5a92efa6..73334e0f823f 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -603,11 +603,8 @@ do { \ read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \ } while (0) -#define snd_pcm_group_for_each(pos, substream) \ - list_for_each(pos, &substream->group->substreams) - -#define snd_pcm_group_substream_entry(pos) \ - list_entry(pos, struct snd_pcm_substream, link_list) +#define snd_pcm_group_for_each_entry(s, substream) \ + list_for_each_entry(s, &substream->group->substreams, link_list) static inline int snd_pcm_running(struct snd_pcm_substream *substream) { diff --git a/include/sound/version.h b/include/sound/version.h index 42a18cc95f38..e820f0e7bdd3 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by alsa/ksync script. */ -#define CONFIG_SND_VERSION "1.0.14rc3" -#define CONFIG_SND_DATE " (Wed Mar 14 07:25:50 2007 UTC)" +#define CONFIG_SND_VERSION "1.0.14rc4" +#define CONFIG_SND_DATE " (Wed May 09 09:51:39 2007 UTC)" diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h new file mode 100644 index 000000000000..4eea63761a3f --- /dev/null +++ b/include/video/atmel_lcdc.h @@ -0,0 +1,196 @@ +/* + * Header file for AT91/AT32 LCD Controller + * + * Data structure and register user interface + * + * Copyright (C) 2007 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ATMEL_LCDC_H__ +#define __ATMEL_LCDC_H__ + + /* LCD Controller info data structure */ +struct atmel_lcdfb_info { + spinlock_t lock; + struct fb_info *info; + void __iomem *mmio; + unsigned long irq_base; + + unsigned int guard_time; + struct platform_device *pdev; + struct clk *bus_clk; + struct clk *lcdc_clk; + unsigned int default_bpp; + unsigned int default_lcdcon2; + unsigned int default_dmacon; + void (*atmel_lcdfb_power_control)(int on); + struct fb_monspecs *default_monspecs; + u32 pseudo_palette[16]; +}; + +#define ATMEL_LCDC_DMABADDR1 0x00 +#define ATMEL_LCDC_DMABADDR2 0x04 +#define ATMEL_LCDC_DMAFRMPT1 0x08 +#define ATMEL_LCDC_DMAFRMPT2 0x0c +#define ATMEL_LCDC_DMAFRMADD1 0x10 +#define ATMEL_LCDC_DMAFRMADD2 0x14 + +#define ATMEL_LCDC_DMAFRMCFG 0x18 +#define ATMEL_LCDC_FRSIZE (0x7fffff << 0) +#define ATMEL_LCDC_BLENGTH_OFFSET 24 +#define ATMEL_LCDC_BLENGTH (0x7f << ATMEL_LCDC_BLENGTH_OFFSET) + +#define ATMEL_LCDC_DMACON 0x1c +#define ATMEL_LCDC_DMAEN (0x1 << 0) +#define ATMEL_LCDC_DMARST (0x1 << 1) +#define ATMEL_LCDC_DMABUSY (0x1 << 2) +#define ATMEL_LCDC_DMAUPDT (0x1 << 3) +#define ATMEL_LCDC_DMA2DEN (0x1 << 4) + +#define ATMEL_LCDC_DMA2DCFG 0x20 +#define ATMEL_LCDC_ADDRINC_OFFSET 0 +#define ATMEL_LCDC_ADDRINC (0xffff) +#define ATMEL_LCDC_PIXELOFF_OFFSET 24 +#define ATMEL_LCDC_PIXELOFF (0x1f << 24) + +#define ATMEL_LCDC_LCDCON1 0x0800 +#define ATMEL_LCDC_BYPASS (1 << 0) +#define ATMEL_LCDC_CLKVAL_OFFSET 12 +#define ATMEL_LCDC_CLKVAL (0x1ff << ATMEL_LCDC_CLKVAL_OFFSET) +#define ATMEL_LCDC_LINCNT (0x7ff << 21) + +#define ATMEL_LCDC_LCDCON2 0x0804 +#define ATMEL_LCDC_DISTYPE (3 << 0) +#define ATMEL_LCDC_DISTYPE_STNMONO (0 << 0) +#define ATMEL_LCDC_DISTYPE_STNCOLOR (1 << 0) +#define ATMEL_LCDC_DISTYPE_TFT (2 << 0) +#define ATMEL_LCDC_SCANMOD (1 << 2) +#define ATMEL_LCDC_SCANMOD_SINGLE (0 << 2) +#define ATMEL_LCDC_SCANMOD_DUAL (1 << 2) +#define ATMEL_LCDC_IFWIDTH (3 << 3) +#define ATMEL_LCDC_IFWIDTH_4 (0 << 3) +#define ATMEL_LCDC_IFWIDTH_8 (1 << 3) +#define ATMEL_LCDC_IFWIDTH_16 (2 << 3) +#define ATMEL_LCDC_PIXELSIZE (7 << 5) +#define ATMEL_LCDC_PIXELSIZE_1 (0 << 5) +#define ATMEL_LCDC_PIXELSIZE_2 (1 << 5) +#define ATMEL_LCDC_PIXELSIZE_4 (2 << 5) +#define ATMEL_LCDC_PIXELSIZE_8 (3 << 5) +#define ATMEL_LCDC_PIXELSIZE_16 (4 << 5) +#define ATMEL_LCDC_PIXELSIZE_24 (5 << 5) +#define ATMEL_LCDC_PIXELSIZE_32 (6 << 5) +#define ATMEL_LCDC_INVVD (1 << 8) +#define ATMEL_LCDC_INVVD_NORMAL (0 << 8) +#define ATMEL_LCDC_INVVD_INVERTED (1 << 8) +#define ATMEL_LCDC_INVFRAME (1 << 9 ) +#define ATMEL_LCDC_INVFRAME_NORMAL (0 << 9) +#define ATMEL_LCDC_INVFRAME_INVERTED (1 << 9) +#define ATMEL_LCDC_INVLINE (1 << 10) +#define ATMEL_LCDC_INVLINE_NORMAL (0 << 10) +#define ATMEL_LCDC_INVLINE_INVERTED (1 << 10) +#define ATMEL_LCDC_INVCLK (1 << 11) +#define ATMEL_LCDC_INVCLK_NORMAL (0 << 11) +#define ATMEL_LCDC_INVCLK_INVERTED (1 << 11) +#define ATMEL_LCDC_INVDVAL (1 << 12) +#define ATMEL_LCDC_INVDVAL_NORMAL (0 << 12) +#define ATMEL_LCDC_INVDVAL_INVERTED (1 << 12) +#define ATMEL_LCDC_CLKMOD (1 << 15) +#define ATMEL_LCDC_CLKMOD_ACTIVEDISPLAY (0 << 15) +#define ATMEL_LCDC_CLKMOD_ALWAYSACTIVE (1 << 15) +#define ATMEL_LCDC_MEMOR (1 << 31) +#define ATMEL_LCDC_MEMOR_BIG (0 << 31) +#define ATMEL_LCDC_MEMOR_LITTLE (1 << 31) + +#define ATMEL_LCDC_TIM1 0x0808 +#define ATMEL_LCDC_VFP (0xff << 0) +#define ATMEL_LCDC_VBP_OFFSET 8 +#define ATMEL_LCDC_VBP (0xff << ATMEL_LCDC_VBP_OFFSET) +#define ATMEL_LCDC_VPW_OFFSET 16 +#define ATMEL_LCDC_VPW (0x3f << ATMEL_LCDC_VPW_OFFSET) +#define ATMEL_LCDC_VHDLY_OFFSET 24 +#define ATMEL_LCDC_VHDLY (0xf << ATMEL_LCDC_VHDLY_OFFSET) + +#define ATMEL_LCDC_TIM2 0x080c +#define ATMEL_LCDC_HBP (0xff << 0) +#define ATMEL_LCDC_HPW_OFFSET 8 +#define ATMEL_LCDC_HPW (0x3f << ATMEL_LCDC_HPW_OFFSET) +#define ATMEL_LCDC_HFP_OFFSET 21 +#define ATMEL_LCDC_HFP (0x7ff << ATMEL_LCDC_HFP_OFFSET) + +#define ATMEL_LCDC_LCDFRMCFG 0x0810 +#define ATMEL_LCDC_LINEVAL (0x7ff << 0) +#define ATMEL_LCDC_HOZVAL_OFFSET 21 +#define ATMEL_LCDC_HOZVAL (0x7ff << ATMEL_LCDC_HOZVAL_OFFSET) + +#define ATMEL_LCDC_FIFO 0x0814 +#define ATMEL_LCDC_FIFOTH (0xffff) + +#define ATMEL_LCDC_MVAL 0x0818 + +#define ATMEL_LCDC_DP1_2 0x081c +#define ATMEL_LCDC_DP4_7 0x0820 +#define ATMEL_LCDC_DP3_5 0x0824 +#define ATMEL_LCDC_DP2_3 0x0828 +#define ATMEL_LCDC_DP5_7 0x082c +#define ATMEL_LCDC_DP3_4 0x0830 +#define ATMEL_LCDC_DP4_5 0x0834 +#define ATMEL_LCDC_DP6_7 0x0838 +#define ATMEL_LCDC_DP1_2_VAL (0xff) +#define ATMEL_LCDC_DP4_7_VAL (0xfffffff) +#define ATMEL_LCDC_DP3_5_VAL (0xfffff) +#define ATMEL_LCDC_DP2_3_VAL (0xfff) +#define ATMEL_LCDC_DP5_7_VAL (0xfffffff) +#define ATMEL_LCDC_DP3_4_VAL (0xffff) +#define ATMEL_LCDC_DP4_5_VAL (0xfffff) +#define ATMEL_LCDC_DP6_7_VAL (0xfffffff) + +#define ATMEL_LCDC_PWRCON 0x083c +#define ATMEL_LCDC_PWR (1 << 0) +#define ATMEL_LCDC_GUARDT_OFFSET 1 +#define ATMEL_LCDC_GUARDT (0x7f << ATMEL_LCDC_GUARDT_OFFSET) +#define ATMEL_LCDC_BUSY (1 << 31) + +#define ATMEL_LCDC_CONTRAST_CTR 0x0840 +#define ATMEL_LCDC_PS (3 << 0) +#define ATMEL_LCDC_PS_DIV1 (0 << 0) +#define ATMEL_LCDC_PS_DIV2 (1 << 0) +#define ATMEL_LCDC_PS_DIV4 (2 << 0) +#define ATMEL_LCDC_PS_DIV8 (3 << 0) +#define ATMEL_LCDC_POL (1 << 2) +#define ATMEL_LCDC_POL_NEGATIVE (0 << 2) +#define ATMEL_LCDC_POL_POSITIVE (1 << 2) +#define ATMEL_LCDC_ENA (1 << 3) +#define ATMEL_LCDC_ENA_PWMDISABLE (0 << 3) +#define ATMEL_LCDC_ENA_PWMENABLE (1 << 3) + +#define ATMEL_LCDC_CONTRAST_VAL 0x0844 +#define ATMEL_LCDC_CVAL (0xff) + +#define ATMEL_LCDC_IER 0x0848 +#define ATMEL_LCDC_IDR 0x084c +#define ATMEL_LCDC_IMR 0x0850 +#define ATMEL_LCDC_ISR 0x0854 +#define ATMEL_LCDC_ICR 0x0858 +#define ATMEL_LCDC_LNI (1 << 0) +#define ATMEL_LCDC_LSTLNI (1 << 1) +#define ATMEL_LCDC_EOFI (1 << 2) +#define ATMEL_LCDC_UFLWI (1 << 4) +#define ATMEL_LCDC_OWRI (1 << 5) +#define ATMEL_LCDC_MERI (1 << 6) + +#define ATMEL_LCDC_LUT(n) (0x0c00 + ((n)*4)) + +#endif /* __ATMEL_LCDC_H__ */ diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h index 94c7d2da90ea..d52e45a1e9b8 100644 --- a/include/video/pm3fb.h +++ b/include/video/pm3fb.h @@ -7,9 +7,6 @@ * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. - * - * $Header: /cvsroot/linux/drivers/video/pm3fb.h,v 1.1 2002/02/25 19:11:06 marcelo Exp $ - * */ #ifndef PM3FB_H @@ -1119,117 +1116,10 @@ /* ***** pm3fb useful define and macro ***** */ /* ***************************************** */ -/* permedia3 -specific definitions */ -#define PM3_SCALE_TO_CLOCK(pr, fe, po) ((2 * PM3_REF_CLOCK * fe) / (pr * (1 << (po)))) - -/* in case it's not in linux/pci.h */ -#ifndef PCI_DEVICE_ID_3DLABS_PERMEDIA3 -#define PCI_DEVICE_ID_3DLABS_PERMEDIA3 0x000a -#endif - -/* max number of simultaneous board */ -#define PM3_MAX_BOARD 4 - /* max size of options */ #define PM3_OPTIONS_SIZE 256 /* max size of font name */ #define PM3_FONTNAME_SIZE 40 -/* do we want accelerated console */ -#define PM3FB_USE_ACCEL 1 - -/* for driver debugging ONLY */ -/* 0 = assert only, 1 = error, 2 = info, 3+ = verbose */ -/* define PM3FB_MASTER_DEBUG 1 */ -#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 3) -#define PM3FB_TRACE -#endif /* defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 3) */ - -#ifdef PM3FB_MASTER_DEBUG -#define DPRINTK(l,a,b...) do { if ((l) <= PM3FB_MASTER_DEBUG) printk("pm3fb: %s: " a, __FUNCTION__ , ## b); } while (0) -#define DASSERT(t,a,b...) do { if (!(t)) printk("pm3fb: _assert failed: %s: " a, __FUNCTION__ , ## b); } while (0) -#ifdef PM3FB_TRACE -#define DTRACE printk("pm3fb: _enter %s\n", __FUNCTION__) -#else /* PM3FB_TRACE */ -#define DTRACE -#endif /* PM3FB_TRACE */ -#else /* PM3FB_MASTER_DEBUG */ -#define DPRINTK(l,a,b...) -#define DASSERT(t,a,b...) -#define DTRACE -#endif /* PM3FB_MASTER_DEBUG */ - -#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2) -#define PM3_SHOW_CUR_MODE pm3fb_show_cur_mode(l_fb_info) -#else -#define PM3_SHOW_CUR_MODE /* pm3fb_show_cur_mode() */ -#endif - -/* ******************************************** */ -/* ***** A bunch of register-access macro ***** */ -/* ******************************************** */ - -#define PM3_WRITE_REG(r, v) fb_writel(v, (l_fb_info->vIOBase + r)) -#define PM3_READ_REG(r) fb_readl((l_fb_info->vIOBase + r)) - - -#define depth2bpp(d) ((d + 7L) & ~7L) -#define depth2ByPP(d) (depth2bpp(d) / 8) - -#define depth_supported(d) ((d == 8) || (d == 12) || (d == 15) || (d == 16) || (d==32)) - - -#define PM3_WAIT(n) \ -do{ \ - while(PM3_READ_REG(PM3InFIFOSpace)<(n)); \ -} while(0) - -#define PM3_DELAY(x) do { \ - int delay = x; \ - unsigned char tmp; \ - while(delay--){tmp = PM3_READ_REG(PM3InFIFOSpace);}; \ -} while(0) - -#define PM3_SLOW_WRITE_REG(r,v) \ -do{ \ - DASSERT((l_fb_info->vIOBase != (unsigned char*)(-1)), "l_fb_info->vIOBase mapped in slow write\n"); \ - mb(); \ - PM3_WAIT(1); \ - mb(); \ - PM3_WRITE_REG(r,v); \ -} while(0) - -#define PM3_SET_INDEX(index) \ -do{ \ - PM3_SLOW_WRITE_REG(PM3RD_IndexHigh,(((index)>>8)&0xff)); \ - PM3_SLOW_WRITE_REG(PM3RD_IndexLow,((index)&0xff)); \ -} while(0) - -#define PM3_WRITE_DAC_REG(r, v) \ -do { \ - DASSERT((l_fb_info->vIOBase != (unsigned char*)(-1)), "l_fb_info->vIOBase mapped in write dac reg\n"); \ - PM3_SET_INDEX(r); \ - mb(); \ - PM3_WRITE_REG(PM3RD_IndexedData, v); \ -} while (0) - -/* next one is really a function, added as a macro to be consistent */ -#define PM3_READ_DAC_REG(r) pm3fb_read_dac_reg(l_fb_info, r) - - -#define PM3_COLOR(c) \ -do { \ - if (l_fb_info->current_par->depth == 8) \ - { \ - c = (c & 0xFF); \ - c = c | (c << 8); \ - } \ - if ((l_fb_info->current_par->depth == 8) || (depth2bpp(l_fb_info->current_par->depth) == 16)) \ - { \ - c = (c & 0xFFFF); \ - c = c | (c << 16); \ - } \ -} while (0) - #endif /* PM3FB_H */ diff --git a/init/Kconfig b/init/Kconfig index 322b1f8c21b3..4e009fde4b69 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -475,13 +475,53 @@ config FUTEX support for "fast userspace mutexes". The resulting kernel may not run glibc-based applications correctly. +config ANON_INODES + bool "Enable anonymous inode source" if EMBEDDED + default y + help + Anonymous inode source for pseudo-files like epoll, signalfd, + timerfd and eventfd. + + If unsure, say Y. + config EPOLL bool "Enable eventpoll support" if EMBEDDED default y + depends on ANON_INODES help Disabling this option will cause the kernel to be built without support for epoll family of system calls. +config SIGNALFD + bool "Enable signalfd() system call" if EMBEDDED + depends on ANON_INODES + default y + help + Enable the signalfd() system call that allows to receive signals + on a file descriptor. + + If unsure, say Y. + +config TIMERFD + bool "Enable timerfd() system call" if EMBEDDED + depends on ANON_INODES + default y + help + Enable the timerfd() system call that allows to receive timer + events on a file descriptor. + + If unsure, say Y. + +config EVENTFD + bool "Enable eventfd() system call" if EMBEDDED + depends on ANON_INODES + default y + help + Enable the eventfd() system call that allows to receive both + kernel notification (ie. KAIO) or userspace notifications. + + If unsure, say Y. + config SHMEM bool "Use full shmem filesystem" if EMBEDDED default y diff --git a/init/main.c b/init/main.c index e8d080cab443..1940fa75e82e 100644 --- a/init/main.c +++ b/init/main.c @@ -801,6 +801,7 @@ static int __init kernel_init(void * unused) */ init_pid_ns.child_reaper = current; + __set_special_pids(1, 1); cad_pid = task_pid(current); smp_prepare_cpus(max_cpus); diff --git a/ipc/mqueue.c b/ipc/mqueue.c index d17821d3f483..fab5707cb5f7 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -681,6 +681,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, if (oflag & O_CREAT) { if (dentry->d_inode) { /* entry already exists */ + audit_inode(name, dentry->d_inode); error = -EEXIST; if (oflag & O_EXCL) goto out; @@ -693,6 +694,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, error = -ENOENT; if (!dentry->d_inode) goto out; + audit_inode(name, dentry->d_inode); filp = do_open(dentry, oflag); } @@ -840,6 +842,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, if (unlikely(filp->f_op != &mqueue_file_operations)) goto out_fput; info = MQUEUE_I(inode); + audit_inode(NULL, inode); if (unlikely(!(filp->f_mode & FMODE_WRITE))) goto out_fput; @@ -923,6 +926,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, if (unlikely(filp->f_op != &mqueue_file_operations)) goto out_fput; info = MQUEUE_I(inode); + audit_inode(NULL, inode); if (unlikely(!(filp->f_mode & FMODE_READ))) goto out_fput; diff --git a/kernel/audit.h b/kernel/audit.h index a3370232a390..815d6f5c04ee 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -83,6 +83,7 @@ struct audit_krule { u32 field_count; char *filterkey; /* ties events to rules */ struct audit_field *fields; + struct audit_field *arch_f; /* quick access to arch field */ struct audit_field *inode_f; /* quick access to an inode field */ struct audit_watch *watch; /* associated watch */ struct list_head rlist; /* entry in audit_watch.rules list */ @@ -131,17 +132,19 @@ extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32, extern int selinux_audit_rule_update(void); #ifdef CONFIG_AUDITSYSCALL -extern void __audit_signal_info(int sig, struct task_struct *t); -static inline void audit_signal_info(int sig, struct task_struct *t) +extern int __audit_signal_info(int sig, struct task_struct *t); +static inline int audit_signal_info(int sig, struct task_struct *t) { - if (unlikely(audit_pid && t->tgid == audit_pid)) - __audit_signal_info(sig, t); + if (unlikely((audit_pid && t->tgid == audit_pid) || + (audit_signals && !audit_dummy_context()))) + return __audit_signal_info(sig, t); + return 0; } extern enum audit_state audit_filter_inodes(struct task_struct *, struct audit_context *); extern void audit_set_auditable(struct audit_context *); #else -#define audit_signal_info(s,t) +#define audit_signal_info(s,t) AUDIT_DISABLED #define audit_filter_inodes(t,c) AUDIT_DISABLED #define audit_set_auditable(c) #endif diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 3749193aed8c..6c61263ff96d 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -311,6 +311,43 @@ int audit_match_class(int class, unsigned syscall) return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall); } +static inline int audit_match_class_bits(int class, u32 *mask) +{ + int i; + + if (classes[class]) { + for (i = 0; i < AUDIT_BITMASK_SIZE; i++) + if (mask[i] & classes[class][i]) + return 0; + } + return 1; +} + +static int audit_match_signal(struct audit_entry *entry) +{ + struct audit_field *arch = entry->rule.arch_f; + + if (!arch) { + /* When arch is unspecified, we must check both masks on biarch + * as syscall number alone is ambiguous. */ + return (audit_match_class_bits(AUDIT_CLASS_SIGNAL, + entry->rule.mask) && + audit_match_class_bits(AUDIT_CLASS_SIGNAL_32, + entry->rule.mask)); + } + + switch(audit_classify_arch(arch->val)) { + case 0: /* native */ + return (audit_match_class_bits(AUDIT_CLASS_SIGNAL, + entry->rule.mask)); + case 1: /* 32bit on biarch */ + return (audit_match_class_bits(AUDIT_CLASS_SIGNAL_32, + entry->rule.mask)); + default: + return 1; + } +} + /* Common user-space to kernel rule translation. */ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) { @@ -429,6 +466,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) err = -EINVAL; goto exit_free; } + entry->rule.arch_f = f; break; case AUDIT_PERM: if (f->val & ~15) @@ -519,7 +557,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_FSGID: case AUDIT_LOGINUID: case AUDIT_PERS: - case AUDIT_ARCH: case AUDIT_MSGTYPE: case AUDIT_PPID: case AUDIT_DEVMAJOR: @@ -531,6 +568,9 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_ARG2: case AUDIT_ARG3: break; + case AUDIT_ARCH: + entry->rule.arch_f = f; + break; case AUDIT_SUBJ_USER: case AUDIT_SUBJ_ROLE: case AUDIT_SUBJ_TYPE: @@ -1221,6 +1261,9 @@ static inline int audit_add_rule(struct audit_entry *entry, #ifdef CONFIG_AUDITSYSCALL if (!dont_count) audit_n_rules++; + + if (!audit_match_signal(entry)) + audit_signals++; #endif mutex_unlock(&audit_filter_mutex); @@ -1294,6 +1337,9 @@ static inline int audit_del_rule(struct audit_entry *entry, #ifdef CONFIG_AUDITSYSCALL if (!dont_count) audit_n_rules--; + + if (!audit_match_signal(entry)) + audit_signals--; #endif mutex_unlock(&audit_filter_mutex); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 628c7ac590a0..e36481ed61b4 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -78,17 +78,15 @@ extern int audit_enabled; * for saving names from getname(). */ #define AUDIT_NAMES 20 -/* AUDIT_NAMES_RESERVED is the number of slots we reserve in the - * audit_context from being used for nameless inodes from - * path_lookup. */ -#define AUDIT_NAMES_RESERVED 7 - /* Indicates that audit should log the full pathname. */ #define AUDIT_NAME_FULL -1 /* number of audit rules */ int audit_n_rules; +/* determines whether we collect data for signals sent */ +int audit_signals; + /* When fs/namei.c:getname() is called, we store the pointer in name and * we don't let putname() free it (instead we free all of the saved * pointers at syscall exit time). @@ -114,6 +112,9 @@ struct audit_aux_data { #define AUDIT_AUX_IPCPERM 0 +/* Number of target pids per aux struct. */ +#define AUDIT_AUX_PIDS 16 + struct audit_aux_data_mq_open { struct audit_aux_data d; int oflag; @@ -181,6 +182,13 @@ struct audit_aux_data_path { struct vfsmount *mnt; }; +struct audit_aux_data_pids { + struct audit_aux_data d; + pid_t target_pid[AUDIT_AUX_PIDS]; + u32 target_sid[AUDIT_AUX_PIDS]; + int pid_count; +}; + /* The per-task audit context. */ struct audit_context { int dummy; /* must be the first element */ @@ -201,6 +209,7 @@ struct audit_context { struct vfsmount * pwdmnt; struct audit_context *previous; /* For nested syscalls */ struct audit_aux_data *aux; + struct audit_aux_data *aux_pids; /* Save things to print about task_struct */ pid_t pid, ppid; @@ -209,6 +218,9 @@ struct audit_context { unsigned long personality; int arch; + pid_t target_pid; + u32 target_sid; + #if AUDIT_DEBUG int put_count; int ino_count; @@ -654,6 +666,10 @@ static inline void audit_free_aux(struct audit_context *context) context->aux = aux->next; kfree(aux); } + while ((aux = context->aux_pids)) { + context->aux_pids = aux->next; + kfree(aux); + } } static inline void audit_zero_context(struct audit_context *context, @@ -795,6 +811,29 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk audit_log_task_context(ab); } +static int audit_log_pid_context(struct audit_context *context, pid_t pid, + u32 sid) +{ + struct audit_buffer *ab; + char *s = NULL; + u32 len; + int rc = 0; + + ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); + if (!ab) + return 1; + + if (selinux_sid_to_string(sid, &s, &len)) { + audit_log_format(ab, "opid=%d obj=(none)", pid); + rc = 1; + } else + audit_log_format(ab, "opid=%d obj=%s", pid, s); + audit_log_end(ab); + kfree(s); + + return rc; +} + static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) { int i, call_panic = 0; @@ -973,6 +1012,21 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts audit_log_end(ab); } + for (aux = context->aux_pids; aux; aux = aux->next) { + struct audit_aux_data_pids *axs = (void *)aux; + int i; + + for (i = 0; i < axs->pid_count; i++) + if (audit_log_pid_context(context, axs->target_pid[i], + axs->target_sid[i])) + call_panic = 1; + } + + if (context->target_pid && + audit_log_pid_context(context, context->target_pid, + context->target_sid)) + call_panic = 1; + if (context->pwd && context->pwdmnt) { ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); if (ab) { @@ -1193,6 +1247,10 @@ void audit_syscall_exit(int valid, long return_code) } else { audit_free_names(context); audit_free_aux(context); + context->aux = NULL; + context->aux_pids = NULL; + context->target_pid = 0; + context->target_sid = 0; kfree(context->filterkey); context->filterkey = NULL; tsk->audit_context = context; @@ -1226,6 +1284,7 @@ void __audit_getname(const char *name) context->names[context->name_count].name_len = AUDIT_NAME_FULL; context->names[context->name_count].name_put = 1; context->names[context->name_count].ino = (unsigned long)-1; + context->names[context->name_count].osid = 0; ++context->name_count; if (!context->pwd) { read_lock(¤t->fs->lock); @@ -1279,6 +1338,28 @@ void audit_putname(const char *name) #endif } +static int audit_inc_name_count(struct audit_context *context, + const struct inode *inode) +{ + if (context->name_count >= AUDIT_NAMES) { + if (inode) + printk(KERN_DEBUG "name_count maxed, losing inode data: " + "dev=%02x:%02x, inode=%lu", + MAJOR(inode->i_sb->s_dev), + MINOR(inode->i_sb->s_dev), + inode->i_ino); + + else + printk(KERN_DEBUG "name_count maxed, losing inode data"); + return 1; + } + context->name_count++; +#if AUDIT_DEBUG + context->ino_count++; +#endif + return 0; +} + /* Copy inode data into an audit_names. */ static void audit_copy_inode(struct audit_names *name, const struct inode *inode) { @@ -1316,13 +1397,10 @@ void __audit_inode(const char *name, const struct inode *inode) else { /* FIXME: how much do we care about inodes that have no * associated name? */ - if (context->name_count >= AUDIT_NAMES - AUDIT_NAMES_RESERVED) + if (audit_inc_name_count(context, inode)) return; - idx = context->name_count++; + idx = context->name_count - 1; context->names[idx].name = NULL; -#if AUDIT_DEBUG - ++context->ino_count; -#endif } audit_copy_inode(&context->names[idx], inode); } @@ -1346,7 +1424,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, { int idx; struct audit_context *context = current->audit_context; - const char *found_name = NULL; + const char *found_parent = NULL, *found_child = NULL; int dirlen = 0; if (!context->in_syscall) @@ -1354,88 +1432,73 @@ void __audit_inode_child(const char *dname, const struct inode *inode, /* determine matching parent */ if (!dname) - goto update_context; - for (idx = 0; idx < context->name_count; idx++) - if (context->names[idx].ino == parent->i_ino) { - const char *name = context->names[idx].name; + goto add_names; - if (!name) - continue; + /* parent is more likely, look for it first */ + for (idx = 0; idx < context->name_count; idx++) { + struct audit_names *n = &context->names[idx]; - if (audit_compare_dname_path(dname, name, &dirlen) == 0) { - context->names[idx].name_len = dirlen; - found_name = name; - break; - } + if (!n->name) + continue; + + if (n->ino == parent->i_ino && + !audit_compare_dname_path(dname, n->name, &dirlen)) { + n->name_len = dirlen; /* update parent data in place */ + found_parent = n->name; + goto add_names; } + } -update_context: - idx = context->name_count; - if (context->name_count == AUDIT_NAMES) { - printk(KERN_DEBUG "name_count maxed and losing %s\n", - found_name ?: "(null)"); - return; + /* no matching parent, look for matching child */ + for (idx = 0; idx < context->name_count; idx++) { + struct audit_names *n = &context->names[idx]; + + if (!n->name) + continue; + + /* strcmp() is the more likely scenario */ + if (!strcmp(dname, n->name) || + !audit_compare_dname_path(dname, n->name, &dirlen)) { + if (inode) + audit_copy_inode(n, inode); + else + n->ino = (unsigned long)-1; + found_child = n->name; + goto add_names; + } } - context->name_count++; -#if AUDIT_DEBUG - context->ino_count++; -#endif - /* Re-use the name belonging to the slot for a matching parent directory. - * All names for this context are relinquished in audit_free_names() */ - context->names[idx].name = found_name; - context->names[idx].name_len = AUDIT_NAME_FULL; - context->names[idx].name_put = 0; /* don't call __putname() */ - - if (!inode) - context->names[idx].ino = (unsigned long)-1; - else - audit_copy_inode(&context->names[idx], inode); - - /* A parent was not found in audit_names, so copy the inode data for the - * provided parent. */ - if (!found_name) { - idx = context->name_count; - if (context->name_count == AUDIT_NAMES) { - printk(KERN_DEBUG - "name_count maxed and losing parent inode data: dev=%02x:%02x, inode=%lu", - MAJOR(parent->i_sb->s_dev), - MINOR(parent->i_sb->s_dev), - parent->i_ino); + +add_names: + if (!found_parent) { + if (audit_inc_name_count(context, parent)) return; - } - context->name_count++; -#if AUDIT_DEBUG - context->ino_count++; -#endif + idx = context->name_count - 1; + context->names[idx].name = NULL; audit_copy_inode(&context->names[idx], parent); } -} -/** - * audit_inode_update - update inode info for last collected name - * @inode: inode being audited - * - * When open() is called on an existing object with the O_CREAT flag, the inode - * data audit initially collects is incorrect. This additional hook ensures - * audit has the inode data for the actual object to be opened. - */ -void __audit_inode_update(const struct inode *inode) -{ - struct audit_context *context = current->audit_context; - int idx; + if (!found_child) { + if (audit_inc_name_count(context, inode)) + return; + idx = context->name_count - 1; - if (!context->in_syscall || !inode) - return; + /* Re-use the name belonging to the slot for a matching parent + * directory. All names for this context are relinquished in + * audit_free_names() */ + if (found_parent) { + context->names[idx].name = found_parent; + context->names[idx].name_len = AUDIT_NAME_FULL; + /* don't call __putname() */ + context->names[idx].name_put = 0; + } else { + context->names[idx].name = NULL; + } - if (context->name_count == 0) { - context->name_count++; -#if AUDIT_DEBUG - context->ino_count++; -#endif + if (inode) + audit_copy_inode(&context->names[idx], inode); + else + context->names[idx].ino = (unsigned long)-1; } - idx = context->name_count - 1; - - audit_copy_inode(&context->names[idx], inode); } /** @@ -1880,6 +1943,14 @@ int audit_sockaddr(int len, void *a) return 0; } +void __audit_ptrace(struct task_struct *t) +{ + struct audit_context *context = current->audit_context; + + context->target_pid = t->pid; + selinux_get_task_sid(t, &context->target_sid); +} + /** * audit_avc_path - record the granting or denial of permissions * @dentry: dentry to record @@ -1918,15 +1989,17 @@ int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt) * If the audit subsystem is being terminated, record the task (pid) * and uid that is doing that. */ -void __audit_signal_info(int sig, struct task_struct *t) +int __audit_signal_info(int sig, struct task_struct *t) { + struct audit_aux_data_pids *axp; + struct task_struct *tsk = current; + struct audit_context *ctx = tsk->audit_context; extern pid_t audit_sig_pid; extern uid_t audit_sig_uid; extern u32 audit_sig_sid; - if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { - struct task_struct *tsk = current; - struct audit_context *ctx = tsk->audit_context; + if (audit_pid && t->tgid == audit_pid && + (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1)) { audit_sig_pid = tsk->pid; if (ctx) audit_sig_uid = ctx->loginuid; @@ -1934,4 +2007,72 @@ void __audit_signal_info(int sig, struct task_struct *t) audit_sig_uid = tsk->uid; selinux_get_task_sid(tsk, &audit_sig_sid); } + + if (!audit_signals) /* audit_context checked in wrapper */ + return 0; + + /* optimize the common case by putting first signal recipient directly + * in audit_context */ + if (!ctx->target_pid) { + ctx->target_pid = t->tgid; + selinux_get_task_sid(t, &ctx->target_sid); + return 0; + } + + axp = (void *)ctx->aux_pids; + if (!axp || axp->pid_count == AUDIT_AUX_PIDS) { + axp = kzalloc(sizeof(*axp), GFP_ATOMIC); + if (!axp) + return -ENOMEM; + + axp->d.type = AUDIT_OBJ_PID; + axp->d.next = ctx->aux_pids; + ctx->aux_pids = (void *)axp; + } + BUG_ON(axp->pid_count > AUDIT_AUX_PIDS); + + axp->target_pid[axp->pid_count] = t->tgid; + selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]); + axp->pid_count++; + + return 0; +} + +/** + * audit_core_dumps - record information about processes that end abnormally + * @sig: signal value + * + * If a process ends with a core dump, something fishy is going on and we + * should record the event for investigation. + */ +void audit_core_dumps(long signr) +{ + struct audit_buffer *ab; + u32 sid; + + if (!audit_enabled) + return; + + if (signr == SIGQUIT) /* don't care for those */ + return; + + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); + audit_log_format(ab, "auid=%u uid=%u gid=%u", + audit_get_loginuid(current->audit_context), + current->uid, current->gid); + selinux_get_task_sid(current, &sid); + if (sid) { + char *ctx = NULL; + u32 len; + + if (selinux_sid_to_string(sid, &ctx, &len)) + audit_log_format(ab, " ssid=%u", sid); + else + audit_log_format(ab, " subj=%s", ctx); + kfree(ctx); + } + audit_log_format(ab, " pid=%d comm=", current->pid); + audit_log_untrustedstring(ab, current->comm); + audit_log_format(ab, " sig=%ld", signr); + audit_log_end(ab); } diff --git a/kernel/compat.c b/kernel/compat.c index cebb4c28c039..3bae3742c2aa 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -475,8 +475,8 @@ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len, return min_length; } -static int get_compat_itimerspec(struct itimerspec *dst, - struct compat_itimerspec __user *src) +int get_compat_itimerspec(struct itimerspec *dst, + const struct compat_itimerspec __user *src) { if (get_compat_timespec(&dst->it_interval, &src->it_interval) || get_compat_timespec(&dst->it_value, &src->it_value)) @@ -484,8 +484,8 @@ static int get_compat_itimerspec(struct itimerspec *dst, return 0; } -static int put_compat_itimerspec(struct compat_itimerspec __user *dst, - struct itimerspec *src) +int put_compat_itimerspec(struct compat_itimerspec __user *dst, + const struct itimerspec *src) { if (put_compat_timespec(&src->it_interval, &dst->it_interval) || put_compat_timespec(&src->it_value, &dst->it_value)) diff --git a/kernel/exit.c b/kernel/exit.c index b0c6f0c3a2df..c6d14b8008dd 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -24,6 +24,7 @@ #include <linux/pid_namespace.h> #include <linux/ptrace.h> #include <linux/profile.h> +#include <linux/signalfd.h> #include <linux/mount.h> #include <linux/proc_fs.h> #include <linux/kthread.h> @@ -42,6 +43,7 @@ #include <linux/audit.h> /* for audit_free() */ #include <linux/resource.h> #include <linux/blkdev.h> +#include <linux/task_io_accounting_ops.h> #include <asm/uaccess.h> #include <asm/unistd.h> @@ -82,6 +84,14 @@ static void __exit_signal(struct task_struct *tsk) sighand = rcu_dereference(tsk->sighand); spin_lock(&sighand->siglock); + /* + * Notify that this sighand has been detached. This must + * be called with the tsk->sighand lock held. Also, this + * access tsk->sighand internally, so it must be called + * before tsk->sighand is reset. + */ + signalfd_detach_locked(tsk); + posix_cpu_timers_exit(tsk); if (atomic_dec_and_test(&sig->count)) posix_cpu_timers_exit_group(tsk); @@ -113,6 +123,8 @@ static void __exit_signal(struct task_struct *tsk) sig->nvcsw += tsk->nvcsw; sig->nivcsw += tsk->nivcsw; sig->sched_time += tsk->sched_time; + sig->inblock += task_io_get_inblock(tsk); + sig->oublock += task_io_get_oublock(tsk); sig = NULL; /* Marker for below. */ } @@ -299,12 +311,12 @@ void __set_special_pids(pid_t session, pid_t pgrp) if (process_session(curr) != session) { detach_pid(curr, PIDTYPE_SID); set_signal_session(curr->signal, session); - attach_pid(curr, PIDTYPE_SID, session); + attach_pid(curr, PIDTYPE_SID, find_pid(session)); } if (process_group(curr) != pgrp) { detach_pid(curr, PIDTYPE_PGID); curr->signal->pgrp = pgrp; - attach_pid(curr, PIDTYPE_PGID, pgrp); + attach_pid(curr, PIDTYPE_PGID, find_pid(pgrp)); } } @@ -1193,6 +1205,12 @@ static int wait_task_zombie(struct task_struct *p, int noreap, p->nvcsw + sig->nvcsw + sig->cnvcsw; psig->cnivcsw += p->nivcsw + sig->nivcsw + sig->cnivcsw; + psig->cinblock += + task_io_get_inblock(p) + + sig->inblock + sig->cinblock; + psig->coublock += + task_io_get_oublock(p) + + sig->oublock + sig->coublock; spin_unlock_irq(&p->parent->sighand->siglock); } diff --git a/kernel/fork.c b/kernel/fork.c index 5dd3979747f5..49530e40ea8b 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -875,6 +875,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; + sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; sig->sched_time = 0; INIT_LIST_HEAD(&sig->cpu_timers[0]); INIT_LIST_HEAD(&sig->cpu_timers[1]); @@ -955,7 +956,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr, - int pid) + struct pid *pid) { int retval; struct task_struct *p = NULL; @@ -1022,7 +1023,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->did_exec = 0; delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ copy_flags(clone_flags, p); - p->pid = pid; + p->pid = pid_nr(pid); retval = -EFAULT; if (clone_flags & CLONE_PARENT_SETTID) if (put_user(p->pid, parent_tidptr)) @@ -1251,13 +1252,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->signal->tty = current->signal->tty; p->signal->pgrp = process_group(current); set_signal_session(p->signal, process_session(current)); - attach_pid(p, PIDTYPE_PGID, process_group(p)); - attach_pid(p, PIDTYPE_SID, process_session(p)); + attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); + attach_pid(p, PIDTYPE_SID, task_session(current)); list_add_tail_rcu(&p->tasks, &init_task.tasks); __get_cpu_var(process_counts)++; } - attach_pid(p, PIDTYPE_PID, p->pid); + attach_pid(p, PIDTYPE_PID, pid); nr_threads++; } @@ -1321,7 +1322,8 @@ struct task_struct * __cpuinit fork_idle(int cpu) struct task_struct *task; struct pt_regs regs; - task = copy_process(CLONE_VM, 0, idle_regs(®s), 0, NULL, NULL, 0); + task = copy_process(CLONE_VM, 0, idle_regs(®s), 0, NULL, NULL, + &init_struct_pid); if (!IS_ERR(task)) init_idle(task, cpu); @@ -1371,7 +1373,7 @@ long do_fork(unsigned long clone_flags, clone_flags |= CLONE_PTRACE; } - p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, nr); + p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid); /* * Do this prior waking up the new thread - the thread pointer * might get invalid after that point, if the thread exits quickly. @@ -1420,12 +1422,15 @@ long do_fork(unsigned long clone_flags, #define ARCH_MIN_MMSTRUCT_ALIGN 0 #endif -static void sighand_ctor(void *data, struct kmem_cache *cachep, unsigned long flags) +static void sighand_ctor(void *data, struct kmem_cache *cachep, + unsigned long flags) { struct sighand_struct *sighand = data; - if (flags & SLAB_CTOR_CONSTRUCTOR) + if (flags & SLAB_CTOR_CONSTRUCTOR) { spin_lock_init(&sighand->siglock); + INIT_LIST_HEAD(&sighand->signalfd_list); + } } void __init proc_caches_init(void) @@ -1451,7 +1456,6 @@ void __init proc_caches_init(void) SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); } - /* * Check constraints on flags passed to the unshare system call and * force unsharing of additional process context as appropriate. diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index ddde0ef9ccdc..b4f1674fca79 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -27,6 +27,10 @@ static int irq_affinity_read_proc(char *page, char **start, off_t off, return len; } +#ifndef is_affinity_mask_valid +#define is_affinity_mask_valid(val) 1 +#endif + int no_irq_affinity; static int irq_affinity_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) @@ -42,6 +46,9 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer, if (err) return err; + if (!is_affinity_mask_valid(new_value)) + return -EINVAL; + /* * Do not allow disabling IRQs completely - it's a too easy * way to make the system unusable accidentally :-) At least diff --git a/kernel/pid.c b/kernel/pid.c index d3ad724afa83..eb66bd2953ab 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -27,11 +27,13 @@ #include <linux/bootmem.h> #include <linux/hash.h> #include <linux/pid_namespace.h> +#include <linux/init_task.h> #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) static struct hlist_head *pid_hash; static int pidhash_shift; static struct kmem_cache *pid_cachep; +struct pid init_struct_pid = INIT_STRUCT_PID; int pid_max = PID_MAX_DEFAULT; @@ -247,13 +249,16 @@ struct pid * fastcall find_pid(int nr) } EXPORT_SYMBOL_GPL(find_pid); -int fastcall attach_pid(struct task_struct *task, enum pid_type type, int nr) +/* + * attach_pid() must be called with the tasklist_lock write-held. + */ +int fastcall attach_pid(struct task_struct *task, enum pid_type type, + struct pid *pid) { struct pid_link *link; - struct pid *pid; link = &task->pids[type]; - link->pid = pid = find_pid(nr); + link->pid = pid; hlist_add_head_rcu(&link->node, &pid->tasks[type]); return 0; diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 4d50e06fd745..ad7949a589dd 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -18,6 +18,7 @@ #include <linux/ptrace.h> #include <linux/security.h> #include <linux/signal.h> +#include <linux/audit.h> #include <asm/pgtable.h> #include <asm/uaccess.h> @@ -161,6 +162,8 @@ int ptrace_attach(struct task_struct *task) { int retval; + audit_ptrace(task); + retval = -EPERM; if (task->pid <= 1) goto out; diff --git a/kernel/signal.c b/kernel/signal.c index 2ac3a668d9dd..364fc95bf97c 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -21,6 +21,7 @@ #include <linux/syscalls.h> #include <linux/ptrace.h> #include <linux/signal.h> +#include <linux/signalfd.h> #include <linux/capability.h> #include <linux/freezer.h> #include <linux/pid_namespace.h> @@ -113,8 +114,7 @@ void recalc_sigpending(void) /* Given the mask, find the first available signal that should be serviced. */ -static int -next_signal(struct sigpending *pending, sigset_t *mask) +int next_signal(struct sigpending *pending, sigset_t *mask) { unsigned long i, *s, *m, x; int sig = 0; @@ -497,6 +497,11 @@ static int check_kill_permission(int sig, struct siginfo *info, int error = -EINVAL; if (!valid_signal(sig)) return error; + + error = audit_signal_info(sig, t); /* Let audit system see the signal */ + if (error) + return error; + error = -EPERM; if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) && ((sig != SIGCONT) || @@ -506,10 +511,7 @@ static int check_kill_permission(int sig, struct siginfo *info, && !capable(CAP_KILL)) return error; - error = security_task_kill(t, info, sig, 0); - if (!error) - audit_signal_info(sig, t); /* Let audit system see the signal */ - return error; + return security_task_kill(t, info, sig, 0); } /* forward decl */ @@ -630,6 +632,12 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, int ret = 0; /* + * Deliver the signal to listening signalfds. This must be called + * with the sighand lock held. + */ + signalfd_notify(t, sig); + + /* * fast-pathed signals for kernel-internal things like SIGSTOP * or SIGKILL. */ @@ -1280,6 +1288,11 @@ int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) ret = 1; goto out; } + /* + * Deliver the signal to listening signalfds. This must be called + * with the sighand lock held. + */ + signalfd_notify(p, sig); list_add_tail(&q->list, &p->pending.list); sigaddset(&p->pending.signal, sig); @@ -1323,6 +1336,11 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) q->info.si_overrun++; goto out; } + /* + * Deliver the signal to listening signalfds. This must be called + * with the sighand lock held. + */ + signalfd_notify(p, sig); /* * Put this signal on the shared-pending queue. @@ -1983,6 +2001,8 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from) /* * If you change siginfo_t structure, please be sure * this code is fixed accordingly. + * Please remember to update the signalfd_copyinfo() function + * inside fs/signalfd.c too, in case siginfo_t changes. * It should never copy any pad contained in the structure * to avoid security leaks, but must copy the generic * 3 ints plus the relevant union member. diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index daabb74ee0bc..fcee2a8e6da3 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -8,6 +8,8 @@ #include <linux/sched.h> #include <linux/stop_machine.h> #include <linux/syscalls.h> +#include <linux/interrupt.h> + #include <asm/atomic.h> #include <asm/semaphore.h> #include <asm/uaccess.h> @@ -45,6 +47,7 @@ static int stopmachine(void *cpu) if (stopmachine_state == STOPMACHINE_DISABLE_IRQ && !irqs_disabled) { local_irq_disable(); + hard_irq_disable(); irqs_disabled = 1; /* Ack: irqs disabled. */ smp_mb(); /* Must read state first. */ @@ -124,6 +127,7 @@ static int stop_machine(void) /* Make them disable irqs. */ local_irq_disable(); + hard_irq_disable(); stopmachine_set_state(STOPMACHINE_DISABLE_IRQ); return 0; diff --git a/kernel/sys.c b/kernel/sys.c index cdb7e9457ba6..872271ccc384 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -14,6 +14,7 @@ #include <linux/prctl.h> #include <linux/highuid.h> #include <linux/fs.h> +#include <linux/resource.h> #include <linux/kernel.h> #include <linux/kexec.h> #include <linux/workqueue.h> @@ -29,6 +30,7 @@ #include <linux/signal.h> #include <linux/cn_proc.h> #include <linux/getcpu.h> +#include <linux/task_io_accounting_ops.h> #include <linux/compat.h> #include <linux/syscalls.h> @@ -658,7 +660,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval) int error = -EINVAL; struct pid *pgrp; - if (which > 2 || which < 0) + if (which > PRIO_USER || which < PRIO_PROCESS) goto out; /* normalize: avoid signed division (rounding problems) */ @@ -722,7 +724,7 @@ asmlinkage long sys_getpriority(int which, int who) long niceval, retval = -ESRCH; struct pid *pgrp; - if (which > 2 || which < 0) + if (which > PRIO_USER || which < PRIO_PROCESS) return -EINVAL; read_lock(&tasklist_lock); @@ -1486,7 +1488,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) if (process_group(p) != pgid) { detach_pid(p, PIDTYPE_PGID); p->signal->pgrp = pgid; - attach_pid(p, PIDTYPE_PGID, pgid); + attach_pid(p, PIDTYPE_PGID, find_pid(pgid)); } err = 0; @@ -2082,6 +2084,8 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) r->ru_nivcsw = p->signal->cnivcsw; r->ru_minflt = p->signal->cmin_flt; r->ru_majflt = p->signal->cmaj_flt; + r->ru_inblock = p->signal->cinblock; + r->ru_oublock = p->signal->coublock; if (who == RUSAGE_CHILDREN) break; @@ -2093,6 +2097,8 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) r->ru_nivcsw += p->signal->nivcsw; r->ru_minflt += p->signal->min_flt; r->ru_majflt += p->signal->maj_flt; + r->ru_inblock += p->signal->inblock; + r->ru_oublock += p->signal->oublock; t = p; do { utime = cputime_add(utime, t->utime); @@ -2101,6 +2107,8 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) r->ru_nivcsw += t->nivcsw; r->ru_minflt += t->min_flt; r->ru_majflt += t->maj_flt; + r->ru_inblock += task_io_get_inblock(t); + r->ru_oublock += task_io_get_oublock(t); t = next_thread(t); } while (t != p); break; diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index d7306d0f3dfc..7e11e2c98bf9 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -141,3 +141,10 @@ cond_syscall(compat_sys_migrate_pages); cond_syscall(sys_bdflush); cond_syscall(sys_ioprio_set); cond_syscall(sys_ioprio_get); + +/* New file descriptors */ +cond_syscall(sys_signalfd); +cond_syscall(sys_timerfd); +cond_syscall(compat_sys_signalfd); +cond_syscall(compat_sys_timerfd); +cond_syscall(sys_eventfd); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ee05b8a061b5..fbc5c622acb0 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -438,6 +438,7 @@ config FAULT_INJECTION_DEBUG_FS config FAULT_INJECTION_STACKTRACE_FILTER bool "stacktrace filter for fault-injection capabilities" depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT + depends on !X86_64 select STACKTRACE select FRAME_POINTER help diff --git a/lib/Makefile b/lib/Makefile index 1f65b4613e09..c8c8e20784ce 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -13,7 +13,7 @@ lib-$(CONFIG_SMP) += cpumask.o lib-y += kobject.o kref.o kobject_uevent.o klist.o obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ - bust_spinlocks.o + bust_spinlocks.o hexdump.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/audit.c b/lib/audit.c index 3b1289fadf06..8e7dc1c63aa9 100644 --- a/lib/audit.c +++ b/lib/audit.c @@ -23,6 +23,16 @@ static unsigned chattr_class[] = { ~0U }; +static unsigned signal_class[] = { +#include <asm-generic/audit_signal.h> +~0U +}; + +int audit_classify_arch(int arch) +{ + return 0; +} + int audit_classify_syscall(int abi, unsigned syscall) { switch(syscall) { @@ -49,6 +59,7 @@ static int __init audit_classes_init(void) audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + audit_register_class(AUDIT_CLASS_SIGNAL, signal_class); return 0; } diff --git a/lib/hexdump.c b/lib/hexdump.c new file mode 100644 index 000000000000..e6da5b7fc29a --- /dev/null +++ b/lib/hexdump.c @@ -0,0 +1,104 @@ +/* + * lib/hexdump.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + */ + +#include <linux/types.h> +#include <linux/ctype.h> +#include <linux/kernel.h> +#include <linux/module.h> + +/** + * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory + * @buf: data blob to dump + * @len: number of bytes in the @buf + * @linebuf: where to put the converted data + * @linebuflen: total size of @linebuf, including space for terminating NUL + * + * hex_dump_to_buffer() works on one "line" of output at a time, i.e., + * 16 bytes of input data converted to hex + ASCII output. + * + * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data + * to a hex + ASCII dump at the supplied memory location. + * The converted output is always NUL-terminated. + * + * E.g.: + * hex_dump_to_buffer(frame->data, frame->len, linebuf, sizeof(linebuf)); + * + * example output buffer: + * 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO + */ +void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf, + size_t linebuflen) +{ + const u8 *ptr = buf; + u8 ch; + int j, lx = 0; + + for (j = 0; (j < 16) && (j < len) && (lx + 3) < linebuflen; j++) { + if (j && !(j % 4)) + linebuf[lx++] = ' '; + ch = ptr[j]; + linebuf[lx++] = hex_asc(ch >> 4); + linebuf[lx++] = hex_asc(ch & 0x0f); + } + if ((lx + 2) < linebuflen) { + linebuf[lx++] = ' '; + linebuf[lx++] = ' '; + } + for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++) + linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.'; + linebuf[lx++] = '\0'; +} +EXPORT_SYMBOL(hex_dump_to_buffer); + +/** + * print_hex_dump - print a text hex dump to syslog for a binary blob of data + * @level: kernel log level (e.g. KERN_DEBUG) + * @prefix_type: controls whether prefix of an offset, address, or none + * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE) + * @buf: data blob to dump + * @len: number of bytes in the @buf + * + * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump + * to the kernel log at the specified kernel log level, with an optional + * leading prefix. + * + * E.g.: + * print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len); + * + * Example output using %DUMP_PREFIX_OFFSET: + * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO + * Example output using %DUMP_PREFIX_ADDRESS: + * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f pqrstuvwxyz{|}~. + */ +void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len) +{ + u8 *ptr = buf; + int i, linelen, remaining = len; + unsigned char linebuf[100]; + + for (i = 0; i < len; i += 16) { + linelen = min(remaining, 16); + remaining -= 16; + hex_dump_to_buffer(ptr + i, linelen, linebuf, sizeof(linebuf)); + + switch (prefix_type) { + case DUMP_PREFIX_ADDRESS: + printk("%s%*p: %s\n", level, + (int)(2 * sizeof(void *)), ptr + i, linebuf); + break; + case DUMP_PREFIX_OFFSET: + printk("%s%.8x: %s\n", level, i, linebuf); + break; + default: + printk("%s%s\n", level, linebuf); + break; + } + } +} +EXPORT_SYMBOL(print_hex_dump); diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 63cd88840eb2..eec1481ba44f 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -588,31 +588,27 @@ void __init page_writeback_init(void) } /** - * generic_writepages - walk the list of dirty pages of the given address space and writepage() all of them. + * write_cache_pages - walk the list of dirty pages of the given address space and write all of them. * @mapping: address space structure to write * @wbc: subtract the number of written pages from *@wbc->nr_to_write + * @writepage: function called for each page + * @data: data passed to writepage function * - * This is a library function, which implements the writepages() - * address_space_operation. - * - * If a page is already under I/O, generic_writepages() skips it, even + * If a page is already under I/O, write_cache_pages() skips it, even * if it's dirty. This is desirable behaviour for memory-cleaning writeback, * but it is INCORRECT for data-integrity system calls such as fsync(). fsync() * and msync() need to guarantee that all the data which was dirty at the time * the call was made get new I/O started against them. If wbc->sync_mode is * WB_SYNC_ALL then we were called for data integrity and we must wait for * existing IO to complete. - * - * Derived from mpage_writepages() - if you fix this you should check that - * also! */ -int generic_writepages(struct address_space *mapping, - struct writeback_control *wbc) +int write_cache_pages(struct address_space *mapping, + struct writeback_control *wbc, writepage_t writepage, + void *data) { struct backing_dev_info *bdi = mapping->backing_dev_info; int ret = 0; int done = 0; - int (*writepage)(struct page *page, struct writeback_control *wbc); struct pagevec pvec; int nr_pages; pgoff_t index; @@ -625,12 +621,6 @@ int generic_writepages(struct address_space *mapping, return 0; } - writepage = mapping->a_ops->writepage; - - /* deal with chardevs and other special file */ - if (!writepage) - return 0; - pagevec_init(&pvec, 0); if (wbc->range_cyclic) { index = mapping->writeback_index; /* Start from prev offset */ @@ -682,8 +672,7 @@ retry: continue; } - ret = (*writepage)(page, wbc); - mapping_set_error(mapping, ret); + ret = (*writepage)(page, wbc, data); if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) unlock_page(page); @@ -710,6 +699,38 @@ retry: mapping->writeback_index = index; return ret; } +EXPORT_SYMBOL(write_cache_pages); + +/* + * Function used by generic_writepages to call the real writepage + * function and set the mapping flags on error + */ +static int __writepage(struct page *page, struct writeback_control *wbc, + void *data) +{ + struct address_space *mapping = data; + int ret = mapping->a_ops->writepage(page, wbc); + mapping_set_error(mapping, ret); + return ret; +} + +/** + * generic_writepages - walk the list of dirty pages of the given address space and writepage() all of them. + * @mapping: address space structure to write + * @wbc: subtract the number of written pages from *@wbc->nr_to_write + * + * This is a library function, which implements the writepages() + * address_space_operation. + */ +int generic_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + /* deal with chardevs and other special file */ + if (!mapping->a_ops->writepage) + return 0; + + return write_cache_pages(mapping, wbc, __writepage, mapping); +} EXPORT_SYMBOL(generic_writepages); diff --git a/mm/thrash.c b/mm/thrash.c index 9ef9071f99bc..c4c5205a9c35 100644 --- a/mm/thrash.c +++ b/mm/thrash.c @@ -48,9 +48,8 @@ void grab_swap_token(void) if (current_interval < current->mm->last_interval) current->mm->token_priority++; else { - current->mm->token_priority--; - if (unlikely(current->mm->token_priority < 0)) - current->mm->token_priority = 0; + if (likely(current->mm->token_priority > 0)) + current->mm->token_priority--; } /* Check if we deserve the token */ if (current->mm->token_priority > diff --git a/mm/vmstat.c b/mm/vmstat.c index 9832d9a41d8c..8faf27e5aa98 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -698,7 +698,7 @@ static void __devinit start_cpu_timer(int cpu) { struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu); - INIT_DELAYED_WORK(vmstat_work, vmstat_update); + INIT_DELAYED_WORK_DEFERRABLE(vmstat_work, vmstat_update); schedule_delayed_work_on(cpu, vmstat_work, HZ + cpu); } diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index d342e89b8bdd..ceadfcf457c1 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -174,7 +174,7 @@ static inline int hidp_queue_event(struct hidp_session *session, struct input_de static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); struct hidp_session *session = hid->driver_data; return hidp_queue_event(session, dev, type, code, value); @@ -182,7 +182,7 @@ static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigne static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct hidp_session *session = dev->private; + struct hidp_session *session = input_get_drvdata(dev); return hidp_queue_event(session, dev, type, code, value); } @@ -630,7 +630,7 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co struct input_dev *input = session->input; int i; - input->private = session; + input_set_drvdata(input, session); input->name = "Bluetooth HID Boot Protocol Device"; @@ -663,7 +663,7 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co input->relbit[0] |= BIT(REL_WHEEL); } - input->cdev.dev = hidp_get_device(session); + input->dev.parent = hidp_get_device(session); input->event = hidp_input_event; @@ -737,10 +737,8 @@ static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_conn list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) hidp_send_report(session, report); - if (hidinput_connect(hid) == 0) { + if (hidinput_connect(hid) == 0) hid->claimed |= HID_CLAIMED_INPUT; - hid_ff_init(hid); - } } int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) @@ -864,7 +862,7 @@ failed: if (session->hid) hid_free_device(session->hid); - kfree(session->input); + input_free_device(session->input); kfree(session); return err; } diff --git a/net/core/link_watch.c b/net/core/link_watch.c index e3c26a9ccad6..a5e372b9ec4d 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -19,7 +19,6 @@ #include <linux/rtnetlink.h> #include <linux/jiffies.h> #include <linux/spinlock.h> -#include <linux/list.h> #include <linux/slab.h> #include <linux/workqueue.h> #include <linux/bitops.h> @@ -27,8 +26,7 @@ enum lw_bits { - LW_RUNNING = 0, - LW_SE_USED + LW_URGENT = 0, }; static unsigned long linkwatch_flags; @@ -37,17 +35,9 @@ static unsigned long linkwatch_nextevent; static void linkwatch_event(struct work_struct *dummy); static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event); -static LIST_HEAD(lweventlist); +static struct net_device *lweventlist; static DEFINE_SPINLOCK(lweventlist_lock); -struct lw_event { - struct list_head list; - struct net_device *dev; -}; - -/* Avoid kmalloc() for most systems */ -static struct lw_event singleevent; - static unsigned char default_operstate(const struct net_device *dev) { if (!netif_carrier_ok(dev)) @@ -87,25 +77,102 @@ static void rfc2863_policy(struct net_device *dev) } -/* Must be called with the rtnl semaphore held */ -void linkwatch_run_queue(void) +static int linkwatch_urgent_event(struct net_device *dev) { - struct list_head head, *n, *next; + return netif_running(dev) && netif_carrier_ok(dev) && + dev->qdisc != dev->qdisc_sleeping; +} + + +static void linkwatch_add_event(struct net_device *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&lweventlist_lock, flags); + dev->link_watch_next = lweventlist; + lweventlist = dev; + spin_unlock_irqrestore(&lweventlist_lock, flags); +} + + +static void linkwatch_schedule_work(int urgent) +{ + unsigned long delay = linkwatch_nextevent - jiffies; + + if (test_bit(LW_URGENT, &linkwatch_flags)) + return; + + /* Minimise down-time: drop delay for up event. */ + if (urgent) { + if (test_and_set_bit(LW_URGENT, &linkwatch_flags)) + return; + delay = 0; + } + + /* If we wrap around we'll delay it by at most HZ. */ + if (delay > HZ) + delay = 0; + + /* + * This is true if we've scheduled it immeditately or if we don't + * need an immediate execution and it's already pending. + */ + if (schedule_delayed_work(&linkwatch_work, delay) == !delay) + return; + + /* Don't bother if there is nothing urgent. */ + if (!test_bit(LW_URGENT, &linkwatch_flags)) + return; + + /* It's already running which is good enough. */ + if (!cancel_delayed_work(&linkwatch_work)) + return; + + /* Otherwise we reschedule it again for immediate exection. */ + schedule_delayed_work(&linkwatch_work, 0); +} + + +static void __linkwatch_run_queue(int urgent_only) +{ + struct net_device *next; + + /* + * Limit the number of linkwatch events to one + * per second so that a runaway driver does not + * cause a storm of messages on the netlink + * socket. This limit does not apply to up events + * while the device qdisc is down. + */ + if (!urgent_only) + linkwatch_nextevent = jiffies + HZ; + /* Limit wrap-around effect on delay. */ + else if (time_after(linkwatch_nextevent, jiffies + HZ)) + linkwatch_nextevent = jiffies; + + clear_bit(LW_URGENT, &linkwatch_flags); spin_lock_irq(&lweventlist_lock); - list_replace_init(&lweventlist, &head); + next = lweventlist; + lweventlist = NULL; spin_unlock_irq(&lweventlist_lock); - list_for_each_safe(n, next, &head) { - struct lw_event *event = list_entry(n, struct lw_event, list); - struct net_device *dev = event->dev; + while (next) { + struct net_device *dev = next; - if (event == &singleevent) { - clear_bit(LW_SE_USED, &linkwatch_flags); - } else { - kfree(event); + next = dev->link_watch_next; + + if (urgent_only && !linkwatch_urgent_event(dev)) { + linkwatch_add_event(dev); + continue; } + /* + * Make sure the above read is complete since it can be + * rewritten as soon as we clear the bit below. + */ + smp_mb__before_clear_bit(); + /* We are about to handle this device, * so new events can be accepted */ @@ -124,58 +191,39 @@ void linkwatch_run_queue(void) dev_put(dev); } + + if (lweventlist) + linkwatch_schedule_work(0); } -static void linkwatch_event(struct work_struct *dummy) +/* Must be called with the rtnl semaphore held */ +void linkwatch_run_queue(void) { - /* Limit the number of linkwatch events to one - * per second so that a runaway driver does not - * cause a storm of messages on the netlink - * socket - */ - linkwatch_nextevent = jiffies + HZ; - clear_bit(LW_RUNNING, &linkwatch_flags); + __linkwatch_run_queue(0); +} + +static void linkwatch_event(struct work_struct *dummy) +{ rtnl_lock(); - linkwatch_run_queue(); + __linkwatch_run_queue(time_after(linkwatch_nextevent, jiffies)); rtnl_unlock(); } void linkwatch_fire_event(struct net_device *dev) { - if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) { - unsigned long flags; - struct lw_event *event; - - if (test_and_set_bit(LW_SE_USED, &linkwatch_flags)) { - event = kmalloc(sizeof(struct lw_event), GFP_ATOMIC); - - if (unlikely(event == NULL)) { - clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state); - return; - } - } else { - event = &singleevent; - } + int urgent = linkwatch_urgent_event(dev); + if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) { dev_hold(dev); - event->dev = dev; - - spin_lock_irqsave(&lweventlist_lock, flags); - list_add_tail(&event->list, &lweventlist); - spin_unlock_irqrestore(&lweventlist_lock, flags); - if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) { - unsigned long delay = linkwatch_nextevent - jiffies; + linkwatch_add_event(dev); + } else if (!urgent) + return; - /* If we wrap around we'll delay it by at most HZ. */ - if (delay > HZ) - delay = 0; - schedule_delayed_work(&linkwatch_work, delay); - } - } + linkwatch_schedule_work(urgent); } EXPORT_SYMBOL(linkwatch_fire_event); diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 7edea2a1696c..75c023062533 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -15,128 +15,34 @@ MODULE_DESCRIPTION("arptables filter table"); #define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \ (1 << NF_ARP_FORWARD)) -/* Standard entry. */ -struct arpt_standard -{ - struct arpt_entry entry; - struct arpt_standard_target target; -}; - -struct arpt_error_target -{ - struct arpt_entry_target target; - char errorname[ARPT_FUNCTION_MAXNAMELEN]; -}; - -struct arpt_error -{ - struct arpt_entry entry; - struct arpt_error_target target; -}; - static struct { struct arpt_replace repl; struct arpt_standard entries[3]; struct arpt_error term; -} initial_table __initdata -= { { "filter", FILTER_VALID_HOOKS, 4, - sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error), - { [NF_ARP_IN] = 0, - [NF_ARP_OUT] = sizeof(struct arpt_standard), - [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), }, - { [NF_ARP_IN] = 0, - [NF_ARP_OUT] = sizeof(struct arpt_standard), - [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), }, - 0, NULL, { } }, - { - /* ARP_IN */ - { - { - { - { 0 }, { 0 }, { 0 }, { 0 }, - 0, 0, - { { 0, }, { 0, } }, - { { 0, }, { 0, } }, - 0, 0, - 0, 0, - 0, 0, - "", "", { 0 }, { 0 }, - 0, 0 - }, - sizeof(struct arpt_entry), - sizeof(struct arpt_standard), - 0, - { 0, 0 }, { } }, - { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } - }, - /* ARP_OUT */ - { - { - { - { 0 }, { 0 }, { 0 }, { 0 }, - 0, 0, - { { 0, }, { 0, } }, - { { 0, }, { 0, } }, - 0, 0, - 0, 0, - 0, 0, - "", "", { 0 }, { 0 }, - 0, 0 - }, - sizeof(struct arpt_entry), - sizeof(struct arpt_standard), - 0, - { 0, 0 }, { } }, - { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } - }, - /* ARP_FORWARD */ - { - { - { - { 0 }, { 0 }, { 0 }, { 0 }, - 0, 0, - { { 0, }, { 0, } }, - { { 0, }, { 0, } }, - 0, 0, - 0, 0, - 0, 0, - "", "", { 0 }, { 0 }, - 0, 0 - }, - sizeof(struct arpt_entry), - sizeof(struct arpt_standard), - 0, - { 0, 0 }, { } }, - { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } - } - }, - /* ERROR */ - { - { - { - { 0 }, { 0 }, { 0 }, { 0 }, - 0, 0, - { { 0, }, { 0, } }, - { { 0, }, { 0, } }, - 0, 0, - 0, 0, - 0, 0, - "", "", { 0 }, { 0 }, - 0, 0 - }, - sizeof(struct arpt_entry), - sizeof(struct arpt_error), - 0, - { 0, 0 }, { } }, - { { { { ARPT_ALIGN(sizeof(struct arpt_error_target)), ARPT_ERROR_TARGET } }, - { } }, - "ERROR" - } - } +} initial_table __initdata = { + .repl = { + .name = "filter", + .valid_hooks = FILTER_VALID_HOOKS, + .num_entries = 4, + .size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error), + .hook_entry = { + [NF_ARP_IN] = 0, + [NF_ARP_OUT] = sizeof(struct arpt_standard), + [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), + }, + .underflow = { + [NF_ARP_IN] = 0, + [NF_ARP_OUT] = sizeof(struct arpt_standard), + [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), + }, + }, + .entries = { + ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_IN */ + ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_OUT */ + ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_FORWARD */ + }, + .term = ARPT_ERROR_INIT, }; static struct arpt_table packet_filter = { diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 42728909eba0..4f51c1d7d2d6 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -26,53 +26,29 @@ static struct struct ipt_replace repl; struct ipt_standard entries[3]; struct ipt_error term; -} initial_table __initdata -= { { "filter", FILTER_VALID_HOOKS, 4, - sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), - { [NF_IP_LOCAL_IN] = 0, - [NF_IP_FORWARD] = sizeof(struct ipt_standard), - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, - { [NF_IP_LOCAL_IN] = 0, - [NF_IP_FORWARD] = sizeof(struct ipt_standard), - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, - 0, NULL, { } }, - { - /* LOCAL_IN */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* FORWARD */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* LOCAL_OUT */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } } - }, - /* ERROR */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_error), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, - { } }, - "ERROR" - } - } +} initial_table __initdata = { + .repl = { + .name = "filter", + .valid_hooks = FILTER_VALID_HOOKS, + .num_entries = 4, + .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), + .hook_entry = { + [NF_IP_LOCAL_IN] = 0, + [NF_IP_FORWARD] = sizeof(struct ipt_standard), + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, + }, + .underflow = { + [NF_IP_LOCAL_IN] = 0, + [NF_IP_FORWARD] = sizeof(struct ipt_standard), + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, + }, + }, + .entries = { + IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ + IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ + IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ + }, + .term = IPT_ERROR_INIT, /* ERROR */ }; static struct xt_table packet_filter = { @@ -105,7 +81,8 @@ ipt_local_out_hook(unsigned int hook, if ((*pskb)->len < sizeof(struct iphdr) || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { if (net_ratelimit()) - printk("ipt_hook: happy cracking.\n"); + printk("iptable_filter: ignoring short SOCK_RAW " + "packet.\n"); return NF_ACCEPT; } diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 9278802f2742..902446f7cbca 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -33,73 +33,35 @@ static struct struct ipt_replace repl; struct ipt_standard entries[5]; struct ipt_error term; -} initial_table __initdata -= { { "mangle", MANGLE_VALID_HOOKS, 6, - sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error), - { [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), - [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, - [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 }, - { [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), - [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, - [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 }, - 0, NULL, { } }, - { - /* PRE_ROUTING */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* LOCAL_IN */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* FORWARD */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* LOCAL_OUT */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* POST_ROUTING */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_standard), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - }, - /* ERROR */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ipt_entry), - sizeof(struct ipt_error), - 0, { 0, 0 }, { } }, - { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, - { } }, - "ERROR" - } - } +} initial_table __initdata = { + .repl = { + .name = "mangle", + .valid_hooks = MANGLE_VALID_HOOKS, + .num_entries = 6, + .size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error), + .hook_entry = { + [NF_IP_PRE_ROUTING] = 0, + [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), + [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, + [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4, + }, + .underflow = { + [NF_IP_PRE_ROUTING] = 0, + [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard), + [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2, + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, + [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4, + }, + }, + .entries = { + IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ + IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ + IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ + IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ + IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */ + }, + .term = IPT_ERROR_INIT, /* ERROR */ }; static struct xt_table packet_mangler = { @@ -138,7 +100,8 @@ ipt_local_hook(unsigned int hook, if ((*pskb)->len < sizeof(struct iphdr) || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { if (net_ratelimit()) - printk("ipt_hook: happy cracking.\n"); + printk("iptable_mangle: ignoring short SOCK_RAW " + "packet.\n"); return NF_ACCEPT; } diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 18c3d4c9ff51..d6e503395684 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -5,6 +5,7 @@ */ #include <linux/module.h> #include <linux/netfilter_ipv4/ip_tables.h> +#include <net/ip.h> #define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT)) @@ -21,62 +22,18 @@ static struct .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error), .hook_entry = { [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) }, + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) + }, .underflow = { [NF_IP_PRE_ROUTING] = 0, - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) }, + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) + }, }, .entries = { - /* PRE_ROUTING */ - { - .entry = { - .target_offset = sizeof(struct ipt_entry), - .next_offset = sizeof(struct ipt_standard), - }, - .target = { - .target = { - .u = { - .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)), - }, - }, - .verdict = -NF_ACCEPT - 1, - }, - }, - - /* LOCAL_OUT */ - { - .entry = { - .target_offset = sizeof(struct ipt_entry), - .next_offset = sizeof(struct ipt_standard), - }, - .target = { - .target = { - .u = { - .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)), - }, - }, - .verdict = -NF_ACCEPT - 1, - }, - }, + IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ + IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ }, - /* ERROR */ - .term = { - .entry = { - .target_offset = sizeof(struct ipt_entry), - .next_offset = sizeof(struct ipt_error), - }, - .target = { - .target = { - .u = { - .user = { - .target_size = IPT_ALIGN(sizeof(struct ipt_error_target)), - .name = IPT_ERROR_TARGET, - }, - }, - }, - .errorname = "ERROR", - }, - } + .term = IPT_ERROR_INIT, /* ERROR */ }; static struct xt_table packet_raw = { @@ -98,6 +55,24 @@ ipt_hook(unsigned int hook, return ipt_do_table(pskb, hook, in, out, &packet_raw); } +static unsigned int +ipt_local_hook(unsigned int hook, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) || + ip_hdrlen(*pskb) < sizeof(struct iphdr)) { + if (net_ratelimit()) + printk("iptable_raw: ignoring short SOCK_RAW" + "packet.\n"); + return NF_ACCEPT; + } + return ipt_do_table(pskb, hook, in, out, &packet_raw); +} + /* 'raw' is the very first table. */ static struct nf_hook_ops ipt_ops[] = { { @@ -108,7 +83,7 @@ static struct nf_hook_ops ipt_ops[] = { .owner = THIS_MODULE, }, { - .hook = ipt_hook, + .hook = ipt_local_hook, .pf = PF_INET, .hooknum = NF_IP_LOCAL_OUT, .priority = NF_IP_PRI_RAW, diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 2534f718ab92..6740736c5e79 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -46,77 +46,20 @@ static struct .hook_entry = { [NF_IP_PRE_ROUTING] = 0, [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard), - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 + }, .underflow = { [NF_IP_PRE_ROUTING] = 0, [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard), - [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 }, + [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 + }, }, .entries = { - /* PRE_ROUTING */ - { - .entry = { - .target_offset = sizeof(struct ipt_entry), - .next_offset = sizeof(struct ipt_standard), - }, - .target = { - .target = { - .u = { - .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)), - }, - }, - .verdict = -NF_ACCEPT - 1, - }, - }, - /* POST_ROUTING */ - { - .entry = { - .target_offset = sizeof(struct ipt_entry), - .next_offset = sizeof(struct ipt_standard), - }, - .target = { - .target = { - .u = { - .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)), - }, - }, - .verdict = -NF_ACCEPT - 1, - }, - }, - /* LOCAL_OUT */ - { - .entry = { - .target_offset = sizeof(struct ipt_entry), - .next_offset = sizeof(struct ipt_standard), - }, - .target = { - .target = { - .u = { - .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)), - }, - }, - .verdict = -NF_ACCEPT - 1, - }, - }, + IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ + IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */ + IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ }, - /* ERROR */ - .term = { - .entry = { - .target_offset = sizeof(struct ipt_entry), - .next_offset = sizeof(struct ipt_error), - }, - .target = { - .target = { - .u = { - .user = { - .target_size = IPT_ALIGN(sizeof(struct ipt_error_target)), - .name = IPT_ERROR_TARGET, - }, - }, - }, - .errorname = "ERROR", - }, - } + .term = IPT_ERROR_INIT, /* ERROR */ }; static struct xt_table nat_table = { @@ -230,9 +173,7 @@ static int ipt_dnat_checkentry(const char *tablename, } inline unsigned int -alloc_null_binding(struct nf_conn *ct, - struct nf_nat_info *info, - unsigned int hooknum) +alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) { /* Force range to this IP; let proto decide mapping for per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). @@ -251,9 +192,7 @@ alloc_null_binding(struct nf_conn *ct, } unsigned int -alloc_null_binding_confirmed(struct nf_conn *ct, - struct nf_nat_info *info, - unsigned int hooknum) +alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum) { __be32 ip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC @@ -275,8 +214,7 @@ int nf_nat_rule_find(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, const struct net_device *out, - struct nf_conn *ct, - struct nf_nat_info *info) + struct nf_conn *ct) { int ret; @@ -285,7 +223,7 @@ int nf_nat_rule_find(struct sk_buff **pskb, if (ret == NF_ACCEPT) { if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) /* NUL mapping */ - ret = alloc_null_binding(ct, info, hooknum); + ret = alloc_null_binding(ct, hooknum); } return ret; } diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 64bbed2ba780..55dac36dbc85 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -80,7 +80,6 @@ nf_nat_fn(unsigned int hooknum, struct nf_conn *ct; enum ip_conntrack_info ctinfo; struct nf_conn_nat *nat; - struct nf_nat_info *info; /* maniptype == SRC for postrouting. */ enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); @@ -129,7 +128,6 @@ nf_nat_fn(unsigned int hooknum, } /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ case IP_CT_NEW: - info = &nat->info; /* Seen it before? This can happen for loopback, retrans, or local packets.. */ @@ -138,14 +136,13 @@ nf_nat_fn(unsigned int hooknum, if (unlikely(nf_ct_is_confirmed(ct))) /* NAT module was loaded late */ - ret = alloc_null_binding_confirmed(ct, info, - hooknum); + ret = alloc_null_binding_confirmed(ct, hooknum); else if (hooknum == NF_IP_LOCAL_IN) /* LOCAL_IN hook doesn't have a chain! */ - ret = alloc_null_binding(ct, info, hooknum); + ret = alloc_null_binding(ct, hooknum); else ret = nf_nat_rule_find(pskb, hooknum, in, out, - ct, info); + ct); if (ret != NF_ACCEPT) { return ret; @@ -160,10 +157,8 @@ nf_nat_fn(unsigned int hooknum, /* ESTABLISHED */ NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); - info = &nat->info; } - NF_CT_ASSERT(info); return nf_nat_packet(ct, ctinfo, hooknum, pskb); } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 66026df1cc76..4c7e95fa090d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -118,15 +118,15 @@ static int udp_port_rover; * Note about this hash function : * Typical use is probably daddr = 0, only dport is going to vary hash */ -static inline unsigned int hash_port_and_addr(__u16 port, __be32 addr) +static inline unsigned int udp_hash_port(__u16 port) { - addr ^= addr >> 16; - addr ^= addr >> 8; - return port ^ addr; + return port; } static inline int __udp_lib_port_inuse(unsigned int hash, int port, - __be32 daddr, struct hlist_head udptable[]) + const struct sock *this_sk, + struct hlist_head udptable[], + const struct udp_get_port_ops *ops) { struct sock *sk; struct hlist_node *node; @@ -138,7 +138,10 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port, inet = inet_sk(sk); if (inet->num != port) continue; - if (inet->rcv_saddr == daddr) + if (this_sk) { + if (ops->saddr_cmp(sk, this_sk)) + return 1; + } else if (ops->saddr_any(sk)) return 1; } return 0; @@ -151,12 +154,11 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port, * @snum: port number to look up * @udptable: hash list table, must be of UDP_HTABLE_SIZE * @port_rover: pointer to record of last unallocated port - * @saddr_comp: AF-dependent comparison of bound local IP addresses + * @ops: AF-dependent address operations */ int __udp_lib_get_port(struct sock *sk, unsigned short snum, struct hlist_head udptable[], int *port_rover, - int (*saddr_comp)(const struct sock *sk1, - const struct sock *sk2 ) ) + const struct udp_get_port_ops *ops) { struct hlist_node *node; struct hlist_head *head; @@ -176,8 +178,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { int size; - hash = hash_port_and_addr(result, - inet_sk(sk)->rcv_saddr); + hash = ops->hash_port_and_rcv_saddr(result, sk); head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; if (hlist_empty(head)) { if (result > sysctl_local_port_range[1]) @@ -203,17 +204,16 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, result = sysctl_local_port_range[0] + ((result - sysctl_local_port_range[0]) & (UDP_HTABLE_SIZE - 1)); - hash = hash_port_and_addr(result, 0); + hash = udp_hash_port(result); if (__udp_lib_port_inuse(hash, result, - 0, udptable)) + NULL, udptable, ops)) continue; - if (!inet_sk(sk)->rcv_saddr) + if (ops->saddr_any(sk)) break; - hash = hash_port_and_addr(result, - inet_sk(sk)->rcv_saddr); + hash = ops->hash_port_and_rcv_saddr(result, sk); if (! __udp_lib_port_inuse(hash, result, - inet_sk(sk)->rcv_saddr, udptable)) + sk, udptable, ops)) break; } if (i >= (1 << 16) / UDP_HTABLE_SIZE) @@ -221,7 +221,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, gotit: *port_rover = snum = result; } else { - hash = hash_port_and_addr(snum, 0); + hash = udp_hash_port(snum); head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; sk_for_each(sk2, node, head) @@ -231,12 +231,11 @@ gotit: (!sk2->sk_reuse || !sk->sk_reuse) && (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && - (*saddr_comp)(sk, sk2)) + ops->saddr_cmp(sk, sk2)) goto fail; - if (inet_sk(sk)->rcv_saddr) { - hash = hash_port_and_addr(snum, - inet_sk(sk)->rcv_saddr); + if (!ops->saddr_any(sk)) { + hash = ops->hash_port_and_rcv_saddr(snum, sk); head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; sk_for_each(sk2, node, head) @@ -248,7 +247,7 @@ gotit: !sk->sk_bound_dev_if || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && - (*saddr_comp)(sk, sk2)) + ops->saddr_cmp(sk, sk2)) goto fail; } } @@ -266,12 +265,12 @@ fail: } int udp_get_port(struct sock *sk, unsigned short snum, - int (*scmp)(const struct sock *, const struct sock *)) + const struct udp_get_port_ops *ops) { - return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp); + return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, ops); } -int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) +static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) { struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); @@ -280,9 +279,33 @@ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) inet1->rcv_saddr == inet2->rcv_saddr )); } +static int ipv4_rcv_saddr_any(const struct sock *sk) +{ + return !inet_sk(sk)->rcv_saddr; +} + +static inline unsigned int ipv4_hash_port_and_addr(__u16 port, __be32 addr) +{ + addr ^= addr >> 16; + addr ^= addr >> 8; + return port ^ addr; +} + +static unsigned int ipv4_hash_port_and_rcv_saddr(__u16 port, + const struct sock *sk) +{ + return ipv4_hash_port_and_addr(port, inet_sk(sk)->rcv_saddr); +} + +const struct udp_get_port_ops udp_ipv4_ops = { + .saddr_cmp = ipv4_rcv_saddr_equal, + .saddr_any = ipv4_rcv_saddr_any, + .hash_port_and_rcv_saddr = ipv4_hash_port_and_rcv_saddr, +}; + static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) { - return udp_get_port(sk, snum, ipv4_rcv_saddr_equal); + return udp_get_port(sk, snum, &udp_ipv4_ops); } /* UDP is nearly always wildcards out the wazoo, it makes no sense to try @@ -297,8 +320,8 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, unsigned int hash, hashwild; int score, best = -1, hport = ntohs(dport); - hash = hash_port_and_addr(hport, daddr); - hashwild = hash_port_and_addr(hport, 0); + hash = ipv4_hash_port_and_addr(hport, daddr); + hashwild = udp_hash_port(hport); read_lock(&udp_hash_lock); @@ -1198,8 +1221,8 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb, struct sock *sk, *skw, *sknext; int dif; int hport = ntohs(uh->dest); - unsigned int hash = hash_port_and_addr(hport, daddr); - unsigned int hashwild = hash_port_and_addr(hport, 0); + unsigned int hash = ipv4_hash_port_and_addr(hport, daddr); + unsigned int hashwild = udp_hash_port(hport); dif = skb->dev->ifindex; diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h index 820a477cfaa6..06d94195e644 100644 --- a/net/ipv4/udp_impl.h +++ b/net/ipv4/udp_impl.h @@ -5,14 +5,14 @@ #include <net/protocol.h> #include <net/inet_common.h> +extern const struct udp_get_port_ops udp_ipv4_ops; + extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int ); extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []); extern int __udp_lib_get_port(struct sock *sk, unsigned short snum, struct hlist_head udptable[], int *port_rover, - int (*)(const struct sock*,const struct sock*)); -extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *); - + const struct udp_get_port_ops *ops); extern int udp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen); diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index f34fd686a8f1..3653b32dce2d 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -19,14 +19,15 @@ struct hlist_head udplite_hash[UDP_HTABLE_SIZE]; static int udplite_port_rover; int udplite_get_port(struct sock *sk, unsigned short p, - int (*c)(const struct sock *, const struct sock *)) + const struct udp_get_port_ops *ops) { - return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c); + return __udp_lib_get_port(sk, p, udplite_hash, + &udplite_port_rover, ops); } static int udplite_v4_get_port(struct sock *sk, unsigned short snum) { - return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal); + return udplite_get_port(sk, snum, &udp_ipv4_ops); } static int udplite_rcv(struct sk_buff *skb) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d02685c6bc69..c7ea248fae2e 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4204,6 +4204,10 @@ int __init addrconf_init(void) return err; ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev); +#ifdef CONFIG_IPV6_MULTIPLE_TABLES + ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev); + ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev); +#endif register_netdevice_notifier(&ipv6_dev_notf); diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 6d8e4ac7bdad..14be0b9b77a5 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -660,6 +660,14 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr); Hop-by-hop options. **********************************/ +/* + * Note: we cannot rely on skb->dst before we assign it in ip6_route_input(). + */ +static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) +{ + return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev); +} + /* Router Alert as of RFC 2711 */ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) @@ -688,25 +696,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", nh[optoff+1]); - IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); goto drop; } pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); if (pkt_len <= IPV6_MAXPLEN) { - IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); return 0; } if (ipv6_hdr(skb)->payload_len) { - IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); return 0; } if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { - IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS); + IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index f508171bab73..4704b5fc3085 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -463,10 +463,17 @@ int ip6_forward(struct sk_buff *skb) */ if (xrlim_allow(dst, 1*HZ)) ndisc_send_redirect(skb, n, target); - } else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK - |IPV6_ADDR_LINKLOCAL)) { + } else { + int addrtype = ipv6_addr_type(&hdr->saddr); + /* This check is security critical. */ - goto error; + if (addrtype & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK)) + goto error; + if (addrtype & IPV6_ADDR_LINKLOCAL) { + icmpv6_send(skb, ICMPV6_DEST_UNREACH, + ICMPV6_NOT_NEIGHBOUR, 0, skb->dev); + goto error; + } } if (skb->len > dst_mtu(dst)) { diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 76f0cf66f95c..7e32e2aaf7f7 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -24,53 +24,29 @@ static struct struct ip6t_replace repl; struct ip6t_standard entries[3]; struct ip6t_error term; -} initial_table __initdata -= { { "filter", FILTER_VALID_HOOKS, 4, - sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), - { [NF_IP6_LOCAL_IN] = 0, - [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, - { [NF_IP6_LOCAL_IN] = 0, - [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, - 0, NULL, { } }, - { - /* LOCAL_IN */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_standard), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* FORWARD */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_standard), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* LOCAL_OUT */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_standard), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } } - }, - /* ERROR */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_error), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } }, - { } }, - "ERROR" - } - } +} initial_table __initdata = { + .repl = { + .name = "filter", + .valid_hooks = FILTER_VALID_HOOKS, + .num_entries = 4, + .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), + .hook_entry = { + [NF_IP6_LOCAL_IN] = 0, + [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), + [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 + }, + .underflow = { + [NF_IP6_LOCAL_IN] = 0, + [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), + [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 + }, + }, + .entries = { + IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ + IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ + IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ + }, + .term = IP6T_ERROR_INIT, /* ERROR */ }; static struct xt_table packet_filter = { diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index a9f10e32c163..f2d26495f413 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -32,73 +32,35 @@ static struct struct ip6t_replace repl; struct ip6t_standard entries[5]; struct ip6t_error term; -} initial_table __initdata -= { { "mangle", MANGLE_VALID_HOOKS, 6, - sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error), - { [NF_IP6_PRE_ROUTING] = 0, - [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), - [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, - [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4}, - { [NF_IP6_PRE_ROUTING] = 0, - [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), - [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, - [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, - [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4}, - 0, NULL, { } }, - { - /* PRE_ROUTING */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_standard), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* LOCAL_IN */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_standard), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* FORWARD */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_standard), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* LOCAL_OUT */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_standard), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } }, - /* POST_ROUTING */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_standard), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, - -NF_ACCEPT - 1 } } - }, - /* ERROR */ - { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, - 0, - sizeof(struct ip6t_entry), - sizeof(struct ip6t_error), - 0, { 0, 0 }, { } }, - { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } }, - { } }, - "ERROR" - } - } +} initial_table __initdata = { + .repl = { + .name = "mangle", + .valid_hooks = MANGLE_VALID_HOOKS, + .num_entries = 6, + .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error), + .hook_entry = { + [NF_IP6_PRE_ROUTING] = 0, + [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), + [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, + [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, + [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, + }, + .underflow = { + [NF_IP6_PRE_ROUTING] = 0, + [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), + [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, + [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, + [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, + }, + }, + .entries = { + IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ + IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ + IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ + IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ + IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */ + }, + .term = IP6T_ERROR_INIT, /* ERROR */ }; static struct xt_table packet_mangler = { diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index a3eb5b8ce18d..0acda45d455d 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -35,56 +35,10 @@ static struct }, }, .entries = { - /* PRE_ROUTING */ - { - .entry = { - .target_offset = sizeof(struct ip6t_entry), - .next_offset = sizeof(struct ip6t_standard), - }, - .target = { - .target = { - .u = { - .target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)), - }, - }, - .verdict = -NF_ACCEPT - 1, - }, - }, - - /* LOCAL_OUT */ - { - .entry = { - .target_offset = sizeof(struct ip6t_entry), - .next_offset = sizeof(struct ip6t_standard), - }, - .target = { - .target = { - .u = { - .target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)), - }, - }, - .verdict = -NF_ACCEPT - 1, - }, - }, + IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ + IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ }, - /* ERROR */ - .term = { - .entry = { - .target_offset = sizeof(struct ip6t_entry), - .next_offset = sizeof(struct ip6t_error), - }, - .target = { - .target = { - .u = { - .user = { - .target_size = IP6T_ALIGN(sizeof(struct ip6t_error_target)), - .name = IP6T_ERROR_TARGET, - }, - }, - }, - .errorname = "ERROR", - }, - } + .term = IP6T_ERROR_INIT, /* ERROR */ }; static struct xt_table packet_raw = { diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b083c09e3d2d..a7ae59c954d5 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -52,9 +52,28 @@ DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; +static int ipv6_rcv_saddr_any(const struct sock *sk) +{ + struct ipv6_pinfo *np = inet6_sk(sk); + + return ipv6_addr_any(&np->rcv_saddr); +} + +static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port, + const struct sock *sk) +{ + return port; +} + +const struct udp_get_port_ops udp_ipv6_ops = { + .saddr_cmp = ipv6_rcv_saddr_equal, + .saddr_any = ipv6_rcv_saddr_any, + .hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr, +}; + static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) { - return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); + return udp_get_port(sk, snum, &udp_ipv6_ops); } static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index 6e252f318f7c..36b0c11a28a3 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h @@ -6,6 +6,8 @@ #include <net/addrconf.h> #include <net/inet_common.h> +extern const struct udp_get_port_ops udp_ipv6_ops; + extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, int , int , int , __be32 , struct hlist_head []); diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index f54016a55004..c40a51362f89 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -37,7 +37,7 @@ static struct inet6_protocol udplitev6_protocol = { static int udplite_v6_get_port(struct sock *sk, unsigned short snum) { - return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); + return udplite_get_port(sk, snum, &udp_ipv6_ops); } struct proto udplitev6_prot = { diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 822917debeff..3e07e9d6fa42 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -17,6 +17,7 @@ * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, * SSID) */ +#include <linux/delay.h> #include <linux/if_ether.h> #include <linux/skbuff.h> #include <linux/netdevice.h> @@ -27,7 +28,6 @@ #include <linux/rtnetlink.h> #include <net/iw_handler.h> #include <asm/types.h> -#include <asm/delay.h> #include <net/mac80211.h> #include "ieee80211_i.h" diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index e132c8ae8784..e8b5c2d7db62 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -299,7 +299,6 @@ destroy_conntrack(struct nf_conntrack *nfct) { struct nf_conn *ct = (struct nf_conn *)nfct; struct nf_conn_help *help = nfct_help(ct); - struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; typeof(nf_conntrack_destroyed) destroyed; @@ -317,10 +316,6 @@ destroy_conntrack(struct nf_conntrack *nfct) * destroy_conntrack() MUST NOT be called with a write lock * to nf_conntrack_lock!!! -HW */ rcu_read_lock(); - l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num); - if (l3proto && l3proto->destroy) - l3proto->destroy(ct); - l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum); if (l4proto && l4proto->destroy) @@ -893,8 +888,13 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, NF_CT_DUMP_TUPLE(newreply); ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; - if (!ct->master && help && help->expecting == 0) - help->helper = __nf_ct_helper_find(newreply); + if (!ct->master && help && help->expecting == 0) { + struct nf_conntrack_helper *helper; + helper = __nf_ct_helper_find(newreply); + if (helper) + memset(&help->help, 0, sizeof(help->help)); + help->helper = helper; + } write_unlock_bh(&nf_conntrack_lock); } EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index aa1a97ee514b..d6d39e241327 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -830,11 +830,6 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) char *helpname; int err; - if (!help) { - /* FIXME: we need to reallocate and rehash */ - return -EBUSY; - } - /* don't change helper of sibling connections */ if (ct->master) return -EINVAL; @@ -843,25 +838,34 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[]) if (err < 0) return err; - helper = __nf_conntrack_helper_find_byname(helpname); - if (!helper) { - if (!strcmp(helpname, "")) - helper = NULL; - else - return -EINVAL; - } - - if (help->helper) { - if (!helper) { + if (!strcmp(helpname, "")) { + if (help && help->helper) { /* we had a helper before ... */ nf_ct_remove_expectations(ct); help->helper = NULL; - } else { - /* need to zero data of old helper */ - memset(&help->help, 0, sizeof(help->help)); } + + return 0; } + if (!help) { + /* FIXME: we need to reallocate and rehash */ + return -EBUSY; + } + + helper = __nf_conntrack_helper_find_byname(helpname); + if (helper == NULL) + return -EINVAL; + + if (help->helper == helper) + return 0; + + if (help->helper) + /* we had a helper before ... */ + nf_ct_remove_expectations(ct); + + /* need to zero data of old helper */ + memset(&help->help, 0, sizeof(help->help)); help->helper = helper; return 0; diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index f4ea8fe07a53..189ded5f378b 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c @@ -134,12 +134,66 @@ static void destroy(const struct xt_match *match, void *matchinfo) nf_ct_l3proto_module_put(match->family); } +#ifdef CONFIG_COMPAT +struct compat_xt_conntrack_info +{ + compat_uint_t statemask; + compat_uint_t statusmask; + struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; + struct in_addr sipmsk[IP_CT_DIR_MAX]; + struct in_addr dipmsk[IP_CT_DIR_MAX]; + compat_ulong_t expires_min; + compat_ulong_t expires_max; + u_int8_t flags; + u_int8_t invflags; +}; + +static void compat_from_user(void *dst, void *src) +{ + struct compat_xt_conntrack_info *cm = src; + struct xt_conntrack_info m = { + .statemask = cm->statemask, + .statusmask = cm->statusmask, + .expires_min = cm->expires_min, + .expires_max = cm->expires_max, + .flags = cm->flags, + .invflags = cm->invflags, + }; + memcpy(m.tuple, cm->tuple, sizeof(m.tuple)); + memcpy(m.sipmsk, cm->sipmsk, sizeof(m.sipmsk)); + memcpy(m.dipmsk, cm->dipmsk, sizeof(m.dipmsk)); + memcpy(dst, &m, sizeof(m)); +} + +static int compat_to_user(void __user *dst, void *src) +{ + struct xt_conntrack_info *m = src; + struct compat_xt_conntrack_info cm = { + .statemask = m->statemask, + .statusmask = m->statusmask, + .expires_min = m->expires_min, + .expires_max = m->expires_max, + .flags = m->flags, + .invflags = m->invflags, + }; + memcpy(cm.tuple, m->tuple, sizeof(cm.tuple)); + memcpy(cm.sipmsk, m->sipmsk, sizeof(cm.sipmsk)); + memcpy(cm.dipmsk, m->dipmsk, sizeof(cm.dipmsk)); + return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; +} +#endif + static struct xt_match conntrack_match = { .name = "conntrack", .match = match, .checkentry = checkentry, .destroy = destroy, .matchsize = sizeof(struct xt_conntrack_info), +#ifdef CONFIG_COMPAT + .compatsize = sizeof(struct compat_xt_conntrack_info), + .compat_from_user = compat_from_user, + .compat_to_user = compat_to_user, +#endif .family = AF_INET, .me = THIS_MODULE, }; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 3385ee592541..f28bb2dc58d0 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -71,12 +71,9 @@ void qdisc_unlock_tree(struct net_device *dev) /* Kick device. - Note, that this procedure can be called by a watchdog timer, so that - we do not check dev->tbusy flag here. - Returns: 0 - queue is empty. - >0 - queue is not empty, but throttled. - <0 - queue is not empty. Device is throttled, if dev->tbusy != 0. + Returns: 0 - queue is empty or throttled. + >0 - queue is not empty. NOTE: Called under dev->queue_lock with locally disabled BH. */ @@ -115,7 +112,7 @@ static inline int qdisc_restart(struct net_device *dev) kfree_skb(skb); if (net_ratelimit()) printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name); - return -1; + goto out; } __get_cpu_var(netdev_rx_stat).cpu_collision++; goto requeue; @@ -135,10 +132,12 @@ static inline int qdisc_restart(struct net_device *dev) netif_tx_unlock(dev); } spin_lock(&dev->queue_lock); - return -1; + q = dev->qdisc; + goto out; } if (ret == NETDEV_TX_LOCKED && nolock) { spin_lock(&dev->queue_lock); + q = dev->qdisc; goto collision; } } @@ -163,26 +162,28 @@ static inline int qdisc_restart(struct net_device *dev) */ requeue: - if (skb->next) + if (unlikely(q == &noop_qdisc)) + kfree_skb(skb); + else if (skb->next) dev->gso_skb = skb; else q->ops->requeue(skb, q); netif_schedule(dev); - return 1; + return 0; } + +out: BUG_ON((int) q->q.qlen < 0); return q->q.qlen; } void __qdisc_run(struct net_device *dev) { - if (unlikely(dev->qdisc == &noop_qdisc)) - goto out; - - while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) - /* NOTHING */; + do { + if (!qdisc_restart(dev)) + break; + } while (!netif_queue_stopped(dev)); -out: clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); } @@ -544,6 +545,7 @@ void dev_activate(struct net_device *dev) void dev_deactivate(struct net_device *dev) { struct Qdisc *qdisc; + struct sk_buff *skb; spin_lock_bh(&dev->queue_lock); qdisc = dev->qdisc; @@ -551,8 +553,12 @@ void dev_deactivate(struct net_device *dev) qdisc_reset(qdisc); + skb = dev->gso_skb; + dev->gso_skb = NULL; spin_unlock_bh(&dev->queue_lock); + kfree_skb(skb); + dev_watchdog_down(dev); /* Wait for outstanding dev_queue_xmit calls. */ @@ -561,11 +567,6 @@ void dev_deactivate(struct net_device *dev) /* Wait for outstanding qdisc_run calls. */ while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) yield(); - - if (dev->gso_skb) { - kfree_skb(dev->gso_skb); - dev->gso_skb = NULL; - } } void dev_init_scheduler(struct net_device *dev) diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index d24914db7861..f05ad9a30b4c 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -94,14 +94,13 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch) struct net_device *dev = sch->dev; struct teql_sched_data *q = qdisc_priv(sch); - __skb_queue_tail(&q->q, skb); - if (q->q.qlen <= dev->tx_queue_len) { + if (q->q.qlen < dev->tx_queue_len) { + __skb_queue_tail(&q->q, skb); sch->bstats.bytes += skb->len; sch->bstats.packets++; return 0; } - __skb_unlink(skb, &q->q); kfree_skb(skb); sch->qstats.drops++; return NET_XMIT_DROP; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 83a76ba9d7b3..4dcdabf56473 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4164,6 +4164,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, rwlock_t *addr_lock; int err = 0; void *addrs; + void *buf; int bytes_copied = 0; if (len != sizeof(struct sctp_getaddrs_old)) @@ -4217,13 +4218,14 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, } } + buf = addrs; list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); memcpy(&temp, &addr->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; - memcpy(addrs, &temp, addrlen); - to += addrlen; + memcpy(buf, &temp, addrlen); + buf += addrlen; bytes_copied += addrlen; cnt ++; if (cnt >= getaddrs.addr_num) break; @@ -4266,6 +4268,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, size_t space_left; int bytes_copied = 0; void *addrs; + void *buf; if (len <= sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -4316,6 +4319,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, } } + buf = addrs; list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); memcpy(&temp, &addr->a, sizeof(temp)); @@ -4325,8 +4329,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, err = -ENOMEM; /*fixme: right error?*/ goto error; } - memcpy(addrs, &temp, addrlen); - to += addrlen; + memcpy(buf, &temp, addrlen); + buf += addrlen; bytes_copied += addrlen; cnt ++; space_left -= addrlen; @@ -5227,7 +5231,12 @@ int sctp_inet_listen(struct socket *sock, int backlog) /* Allocate HMAC for generating cookie. */ if (sctp_hmac_alg) { tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); - if (!tfm) { + if (IS_ERR(tfm)) { + if (net_ratelimit()) { + printk(KERN_INFO + "SCTP: failed to load transform for %s: %ld\n", + sctp_hmac_alg, PTR_ERR(tfm)); + } err = -ENOSYS; goto out; } diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 661ea2dd78ba..bfecb353ab3d 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -141,11 +141,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( * an ABORT, so we need to include it in the sac_info. */ if (chunk) { - /* sctp_inqu_pop() has allready pulled off the chunk - * header. We need to put it back temporarily - */ - skb_push(chunk->skb, sizeof(sctp_chunkhdr_t)); - /* Copy the chunk data to a new skb and reserve enough * head room to use as notification. */ @@ -155,9 +150,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( if (!skb) goto fail; - /* put back the chunk header now that we have a copy */ - skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); - /* Embed the event fields inside the cloned skb. */ event = sctp_skb2event(skb); sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); @@ -168,7 +160,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( /* Trim the buffer to the right length. */ skb_trim(skb, sizeof(struct sctp_assoc_change) + - ntohs(chunk->chunk_hdr->length)); + ntohs(chunk->chunk_hdr->length) - + sizeof(sctp_chunkhdr_t)); } else { event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), MSG_NOTIFICATION, gfp); diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c index e91f9f66f395..ded516717940 100644 --- a/sound/aoa/codecs/snd-aoa-codec-onyx.c +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c @@ -1018,7 +1018,7 @@ static int onyx_create(struct i2c_adapter *adapter, onyx->i2c.driver = &onyx_driver; onyx->i2c.adapter = adapter; onyx->i2c.addr = addr & 0x7f; - strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE-1); + strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE); if (i2c_attach_client(&onyx->i2c)) { printk(KERN_ERR PFX "failed to attach to i2c\n"); @@ -1033,7 +1033,7 @@ static int onyx_create(struct i2c_adapter *adapter, goto fail; } - strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN-1); + strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN); onyx->codec.owner = THIS_MODULE; onyx->codec.init = onyx_init_codec; onyx->codec.exit = onyx_exit_codec; diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c index 041fe52cbf29..2f771f57c76f 100644 --- a/sound/aoa/codecs/snd-aoa-codec-tas.c +++ b/sound/aoa/codecs/snd-aoa-codec-tas.c @@ -899,14 +899,14 @@ static int tas_create(struct i2c_adapter *adapter, tas->i2c.addr = addr; /* seems that half is a saner default */ tas->drc_range = TAS3004_DRC_MAX / 2; - strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); + strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE); if (i2c_attach_client(&tas->i2c)) { printk(KERN_ERR PFX "failed to attach to i2c\n"); goto fail; } - strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1); + strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN); tas->codec.owner = THIS_MODULE; tas->codec.init = tas_init_codec; tas->codec.exit = tas_exit_codec; diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 8b2e9b905cda..64d163914335 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c @@ -163,8 +163,6 @@ static int soundbus_device_resume(struct device * dev) #endif /* CONFIG_PM */ -extern struct device_attribute soundbus_dev_attrs[]; - static struct bus_type soundbus_bus_type = { .name = "aoa-soundbus", .probe = soundbus_probe, diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c index 0fccdbf51663..efb9441b3acf 100644 --- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c +++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c @@ -23,9 +23,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); MODULE_DESCRIPTION("Apple Soundbus: I2S support"); -/* for auto-loading, declare that we handle this weird - * string that macio puts into the relevant device */ -MODULE_ALIAS("of:Ni2sTi2sC"); static int force; module_param(force, int, 0444); @@ -37,6 +34,8 @@ static struct of_device_id i2sbus_match[] = { { } }; +MODULE_DEVICE_TABLE(of, i2sbus_match); + static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, struct dbdma_command_mem *r, int numcmds) diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h index 5c27297835d7..622cd37a0118 100644 --- a/sound/aoa/soundbus/soundbus.h +++ b/sound/aoa/soundbus/soundbus.h @@ -199,4 +199,6 @@ struct soundbus_driver { extern int soundbus_register_driver(struct soundbus_driver *drv); extern void soundbus_unregister_driver(struct soundbus_driver *drv); +extern struct device_attribute soundbus_dev_attrs[]; + #endif /* __SOUNDBUS_H */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 905234817c89..a96733a5beb8 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -712,26 +712,23 @@ static int snd_pcm_action_group(struct action_ops *ops, struct snd_pcm_substream *substream, int state, int do_lock) { - struct list_head *pos; struct snd_pcm_substream *s = NULL; struct snd_pcm_substream *s1; int res = 0; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (do_lock && s != substream) - spin_lock(&s->self_group.lock); + spin_lock_nested(&s->self_group.lock, + SINGLE_DEPTH_NESTING); res = ops->pre_action(s, state); if (res < 0) goto _unlock; } - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { res = ops->do_action(s, state); if (res < 0) { if (ops->undo_action) { - snd_pcm_group_for_each(pos, substream) { - s1 = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s1, substream) { if (s1 == s) /* failed stream */ break; ops->undo_action(s1, state); @@ -741,15 +738,13 @@ static int snd_pcm_action_group(struct action_ops *ops, goto _unlock; } } - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { ops->post_action(s, state); } _unlock: if (do_lock) { /* unlock streams */ - snd_pcm_group_for_each(pos, substream) { - s1 = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s1, substream) { if (s1 != substream) spin_unlock(&s1->self_group.lock); if (s1 == s) /* end */ @@ -1438,7 +1433,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) { struct snd_card *card; struct snd_pcm_runtime *runtime; - struct list_head *pos; + struct snd_pcm_substream *s; int result = 0; int i, num_drecs; struct drain_rec *drec, drec_tmp, *d; @@ -1473,8 +1468,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) /* count only playback streams */ num_drecs = 0; - snd_pcm_group_for_each(pos, substream) { - struct snd_pcm_substream *s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { runtime = s->runtime; if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { d = &drec[num_drecs++]; @@ -1674,7 +1668,7 @@ static void relink_to_local(struct snd_pcm_substream *substream) static int snd_pcm_unlink(struct snd_pcm_substream *substream) { - struct list_head *pos; + struct snd_pcm_substream *s; int res = 0; down_write(&snd_pcm_link_rwsem); @@ -1686,8 +1680,8 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream) list_del(&substream->link_list); substream->group->count--; if (substream->group->count == 1) { /* detach the last stream, too */ - snd_pcm_group_for_each(pos, substream) { - relink_to_local(snd_pcm_group_substream_entry(pos)); + snd_pcm_group_for_each_entry(s, substream) { + relink_to_local(s); break; } kfree(substream->group); diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index 9f7b32e1ccde..7cd5e8f5d4ce 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -24,6 +24,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/moduleparam.h> +#include <linux/log2.h> #include <sound/core.h> #include <sound/timer.h> @@ -129,7 +130,7 @@ static int __init rtctimer_init(void) struct snd_timer *timer; if (rtctimer_freq < 2 || rtctimer_freq > 8192 || - (rtctimer_freq & (rtctimer_freq - 1)) != 0) { + !is_power_of_2(rtctimer_freq)) { snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", rtctimer_freq); return -EINVAL; diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 2de181ad0b05..1d563e515c17 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -42,6 +42,7 @@ static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; #endif static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */ static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */ +static int uart_enter[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for MPU-401 device."); @@ -57,6 +58,8 @@ module_param_array(port, long, NULL, 0444); MODULE_PARM_DESC(port, "Port # for MPU-401 device."); module_param_array(irq, int, NULL, 0444); MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device."); +module_param_array(uart_enter, bool, NULL, 0444); +MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open."); static struct platform_device *platform_devices[SNDRV_CARDS]; static int pnp_registered; @@ -80,10 +83,11 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) strcat(card->longname, "polled"); } - if ((err = snd_mpu401_uart_new(card, 0, - MPU401_HW_MPU401, - port[dev], 0, - irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL)) < 0) { + err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], + uart_enter[dev] ? 0 : MPU401_INFO_UART_ONLY, + irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0, + NULL); + if (err < 0) { printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]); goto _err; } diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 3daa9fa56c0b..85aedc348e2d 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -266,6 +266,16 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, return 0; } +static int snd_mpu401_do_reset(struct snd_mpu401 *mpu) +{ + if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) + return -EIO; + if (!(mpu->info_flags & MPU401_INFO_UART_ONLY) && + snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1)) + return -EIO; + return 0; +} + /* * input/output open/close - protected by open_mutex in rawmidi.c */ @@ -278,9 +288,7 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream) if (mpu->open_input && (err = mpu->open_input(mpu)) < 0) return err; if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { - if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) - goto error_out; - if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1)) + if (snd_mpu401_do_reset(mpu) < 0) goto error_out; } mpu->substream_input = substream; @@ -302,9 +310,7 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream) if (mpu->open_output && (err = mpu->open_output(mpu)) < 0) return err; if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { - if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) - goto error_out; - if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1)) + if (snd_mpu401_do_reset(mpu) < 0) goto error_out; } mpu->substream_output = substream; diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 6c9f4c9bfeb6..ebb1bdac7237 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -892,13 +892,13 @@ static void __devinit snd_mts64_attach(struct parport *p) struct platform_device *device; device = platform_device_alloc(PLATFORM_DRIVER, device_count); - if (!device) + if (!device) return; /* Temporary assignment to forward the parport */ platform_set_drvdata(device, p); - if (platform_device_register(device) < 0) { + if (platform_device_add(device) < 0) { platform_device_put(device); return; } diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index b2d0ba4bd184..497cafb57d9b 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -676,13 +676,13 @@ static void __devinit snd_portman_attach(struct parport *p) struct platform_device *device; device = platform_device_alloc(PLATFORM_DRIVER, device_count); - if (!device) + if (!device) return; /* Temporary assignment to forward the parport */ platform_set_drvdata(device, p); - if (platform_device_register(device) < 0) { + if (platform_device_add(device) < 0) { platform_device_put(device); return; } diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index e1920af4501d..9a8154c9416e 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c @@ -30,6 +30,20 @@ #ifdef SND_VX_FW_LOADER +MODULE_FIRMWARE("vx/bx_1_vxp.b56"); +MODULE_FIRMWARE("vx/bx_1_vp4.b56"); +MODULE_FIRMWARE("vx/x1_1_vx2.xlx"); +MODULE_FIRMWARE("vx/x1_2_v22.xlx"); +MODULE_FIRMWARE("vx/x1_1_vxp.xlx"); +MODULE_FIRMWARE("vx/x1_1_vp4.xlx"); +MODULE_FIRMWARE("vx/bd56002.boot"); +MODULE_FIRMWARE("vx/bd563v2.boot"); +MODULE_FIRMWARE("vx/bd563s3.boot"); +MODULE_FIRMWARE("vx/l_1_vx2.d56"); +MODULE_FIRMWARE("vx/l_1_v22.d56"); +MODULE_FIRMWARE("vx/l_1_vxp.d56"); +MODULE_FIRMWARE("vx/l_1_vp4.d56"); + int snd_vx_setup_firmware(struct vx_core *chip) { static char *fw_files[VX_TYPE_NUMS][4] = { diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index adbfd5884d06..1efb973137a6 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -36,6 +36,7 @@ MODULE_LICENSE("GPL"); #define AK4114_ADDR 0x00 /* fixed address */ static void ak4114_stats(struct work_struct *work); +static void ak4114_init_regs(struct ak4114 *chip); static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val) { @@ -105,7 +106,7 @@ int snd_ak4114_create(struct snd_card *card, for (reg = 0; reg < 5; reg++) chip->txcsb[reg] = txcsb[reg]; - snd_ak4114_reinit(chip); + ak4114_init_regs(chip); chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); chip->rcs1 = reg_read(chip, AK4114_REG_RCS1); @@ -131,13 +132,10 @@ void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); } -void snd_ak4114_reinit(struct ak4114 *chip) +static void ak4114_init_regs(struct ak4114 *chip) { unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg; - chip->init = 1; - mb(); - flush_scheduled_work(); /* bring the chip to reset state and powerdown state */ reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN)); udelay(200); @@ -150,9 +148,18 @@ void snd_ak4114_reinit(struct ak4114 *chip) reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]); /* release powerdown, everything is initialized now */ reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); +} + +void snd_ak4114_reinit(struct ak4114 *chip) +{ + chip->init = 1; + mb(); + flush_scheduled_work(); + ak4114_init_regs(chip); /* bring up statistics / event queing */ chip->init = 0; - schedule_delayed_work(&chip->work, HZ / 10); + if (chip->kctls[0]) + schedule_delayed_work(&chip->work, HZ / 10); } static unsigned int external_rate(unsigned char rcs1) @@ -428,7 +435,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4114_in_bit_info, .get = snd_ak4114_in_bit_get, - .private_value = (6<<8) | AK4114_REG_RCS1, + .private_value = (6<<8) | AK4114_REG_RCS0, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -436,7 +443,15 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4114_in_bit_info, .get = snd_ak4114_in_bit_get, - .private_value = (3<<8) | AK4114_REG_RCS1, + .private_value = (3<<8) | AK4114_REG_RCS0, +}, +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "IEC958 PPL Lock Status", + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_ak4114_in_bit_info, + .get = snd_ak4114_in_bit_get, + .private_value = (1<<31) | (4<<8) | AK4114_REG_RCS0, } }; @@ -455,7 +470,7 @@ int snd_ak4114_build(struct ak4114 *ak4114, kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114); if (kctl == NULL) return -ENOMEM; - if (!strstr(kctl->id.name, "Playback")) { + if (strstr(kctl->id.name, "Playback")) { if (ply_substream == NULL) { snd_ctl_free_one(kctl); ak4114->kctls[idx] = NULL; @@ -472,9 +487,58 @@ int snd_ak4114_build(struct ak4114 *ak4114, return err; ak4114->kctls[idx] = kctl; } + /* trigger workq */ + schedule_delayed_work(&ak4114->work, HZ / 10); return 0; } +/* notify kcontrols if any parameters are changed */ +static void ak4114_notify(struct ak4114 *ak4114, + unsigned char rcs0, unsigned char rcs1, + unsigned char c0, unsigned char c1) +{ + if (!ak4114->kctls[0]) + return; + + if (rcs0 & AK4114_PAR) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[0]->id); + if (rcs0 & AK4114_V) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[1]->id); + if (rcs1 & AK4114_CCRC) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[2]->id); + if (rcs1 & AK4114_QCRC) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[3]->id); + + /* rate change */ + if (c1 & 0xf0) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[4]->id); + + if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT)) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[9]->id); + if (c0 & AK4114_QINT) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[10]->id); + + if (c0 & AK4114_AUDION) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[11]->id); + if (c0 & AK4114_AUTO) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[12]->id); + if (c0 & AK4114_DTSCD) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[13]->id); + if (c0 & AK4114_UNLCK) + snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, + &ak4114->kctls[14]->id); +} + int snd_ak4114_external_rate(struct ak4114 *ak4114) { unsigned char rcs1; @@ -511,31 +575,7 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) ak4114->rcs1 = rcs1; spin_unlock_irqrestore(&ak4114->lock, _flags); - if (rcs0 & AK4114_PAR) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[0]->id); - if (rcs0 & AK4114_V) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[1]->id); - if (rcs1 & AK4114_CCRC) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[2]->id); - if (rcs1 & AK4114_QCRC) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[3]->id); - - /* rate change */ - if (c1 & 0xf0) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[4]->id); - - if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT)) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[9]->id); - if (c0 & AK4114_QINT) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[10]->id); - - if (c0 & AK4114_AUDION) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[11]->id); - if (c0 & AK4114_AUTO) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[12]->id); - if (c0 & AK4114_DTSCD) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[13]->id); - + ak4114_notify(ak4114, rcs0, rcs1, c0, c1); if (ak4114->change_callback && (c0 | c1) != 0) ak4114->change_callback(ak4114, c0, c1); @@ -558,9 +598,9 @@ static void ak4114_stats(struct work_struct *work) { struct ak4114 *chip = container_of(work, struct ak4114, work.work); - if (chip->init) - return; - snd_ak4114_check_rate_and_errors(chip, 0); + if (!chip->init) + snd_ak4114_check_rate_and_errors(chip, 0); + schedule_delayed_work(&chip->work, HZ / 10); } diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 4e3a9729f569..cf3803cd579c 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -358,12 +358,21 @@ config SND_SBAWE config SND_SB16_CSP bool "Sound Blaster 16/AWE CSP support" depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) - select FW_LOADER + select FW_LOADER if !SND_SB16_CSP_FIRMWARE_IN_KERNEL help Say Y here to include support for the CSP core. This special coprocessor can do variable tasks like various compression and decompression algorithms. +config SND_SB16_CSP_FIRMWARE_IN_KERNEL + bool "In-kernel firmware for SB16 CSP" + depends on SND_SB16_CSP + default y + help + Say Y here to include the static firmware built in the kernel + for the SB16 CSP controller. If you choose N here, you need + to install the firmware files from the alsa-firmware package. + config SND_SGALAXY tristate "Aztech Sound Galaxy" depends on SND @@ -391,7 +400,7 @@ config SND_SSCAPE config SND_WAVEFRONT tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)" depends on SND - select FW_LOADER + select FW_LOADER if !SND_WAVEFRONT_FIRMWARE_IN_KERNEL select SND_OPL3_LIB select SND_MPU401_UART select SND_CS4231_LIB @@ -402,4 +411,13 @@ config SND_WAVEFRONT To compile this driver as a module, choose M here: the module will be called snd-wavefront. +config SND_WAVEFRONT_FIRMWARE_IN_KERNEL + bool "In-kernel firmware for Wavefront" + depends on SND_WAVEFRONT + default y + help + Say Y here to include the static firmware built in the kernel + for the Wavefront driver. If you choose N here, you need to + install the firmware files from the alsa-firmware package. + endmenu diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 59034507175b..fc88a31da6f5 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -129,8 +129,8 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar } acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL); if (acard->devmpu == NULL) { - kfree(cfg); - return -EBUSY; + mpu_port[dev] = -1; + snd_printk(KERN_WARNING PFX "MPU401 device busy, skipping.\n"); } pdev = acard->dev; @@ -162,6 +162,10 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar dma2[dev] = pnp_dma(pdev, 1); irq[dev] = pnp_irq(pdev, 0); + if (acard->devmpu == NULL) { + kfree(cfg); + return 0; + } pdev = acard->devmpu; pnp_init_resource_table(cfg); diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 74e501dea8b1..d09a7fa86545 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -24,7 +24,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/time.h> #include <linux/wait.h> #include <linux/moduleparam.h> @@ -32,8 +32,11 @@ #include <sound/ad1848.h> #include <sound/initval.h> +#define CRD_NAME "Generic AD1848/AD1847/CS4248" +#define DEV_NAME "ad1848" + +MODULE_DESCRIPTION(CRD_NAME); MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>"); -MODULE_DESCRIPTION("AD1848/AD1847/CS4248"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848}," "{Analog Devices,AD1847}," @@ -48,95 +51,98 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ static int thinkpad[SNDRV_CARDS]; /* Thinkpad special case */ module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for AD1848 soundcard."); +MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for AD1848 soundcard."); +MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable AD1848 soundcard."); +MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for AD1848 driver."); +MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for AD1848 driver."); +MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for AD1848 driver."); +MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); module_param_array(thinkpad, bool, NULL, 0444); MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series."); -static struct platform_device *devices[SNDRV_CARDS]; +static int __devinit snd_ad1848_match(struct device *dev, unsigned int n) +{ + if (!enable[n]) + return 0; + if (port[n] == SNDRV_AUTO_PORT) { + snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id); + return 0; + } + if (irq[n] == SNDRV_AUTO_IRQ) { + snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id); + return 0; + } + if (dma1[n] == SNDRV_AUTO_DMA) { + snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id); + return 0; + } + return 1; +} -static int __devinit snd_ad1848_probe(struct platform_device *pdev) +static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) { - int dev = pdev->id; struct snd_card *card; struct snd_ad1848 *chip; struct snd_pcm *pcm; - int err; + int error; - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "ad1848: specify port\n"); + card = snd_card_new(index[n], id[n], THIS_MODULE, 0); + if (!card) return -EINVAL; - } - if (irq[dev] == SNDRV_AUTO_IRQ) { - snd_printk(KERN_ERR "ad1848: specify irq\n"); - return -EINVAL; - } - if (dma1[dev] == SNDRV_AUTO_DMA) { - snd_printk(KERN_ERR "ad1848: specify dma1\n"); - return -EINVAL; - } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + error = snd_ad1848_create(card, port[n], irq[n], dma1[n], + thinkpad[n] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT, &chip); + if (error < 0) + goto out; - if ((err = snd_ad1848_create(card, port[dev], - irq[dev], - dma1[dev], - thinkpad[dev] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT, - &chip)) < 0) - goto _err; card->private_data = chip; - if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0) - goto _err; + error = snd_ad1848_pcm(chip, 0, &pcm); + if (error < 0) + goto out; - if ((err = snd_ad1848_mixer(chip)) < 0) - goto _err; + error = snd_ad1848_mixer(chip); + if (error < 0) + goto out; strcpy(card->driver, "AD1848"); strcpy(card->shortname, pcm->name); sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - pcm->name, chip->port, irq[dev], dma1[dev]); - - if (thinkpad[dev]) + pcm->name, chip->port, irq[n], dma1[n]); + if (thinkpad[n]) strcat(card->longname, " [Thinkpad]"); - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, dev); - if ((err = snd_card_register(card)) < 0) - goto _err; + error = snd_card_register(card); + if (error < 0) + goto out; - platform_set_drvdata(pdev, card); + dev_set_drvdata(dev, card); return 0; - _err: - snd_card_free(card); - return err; +out: snd_card_free(card); + return error; } -static int __devexit snd_ad1848_remove(struct platform_device *devptr) +static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(dev)); + dev_set_drvdata(dev, NULL); return 0; } #ifdef CONFIG_PM -static int snd_ad1848_suspend(struct platform_device *pdev, pm_message_t state) +static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state) { - struct snd_card *card = platform_get_drvdata(pdev); + struct snd_card *card = dev_get_drvdata(dev); struct snd_ad1848 *chip = card->private_data; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); @@ -144,9 +150,9 @@ static int snd_ad1848_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int snd_ad1848_resume(struct platform_device *pdev) +static int snd_ad1848_resume(struct device *dev, unsigned int n) { - struct snd_card *card = platform_get_drvdata(pdev); + struct snd_card *card = dev_get_drvdata(dev); struct snd_ad1848 *chip = card->private_data; chip->resume(chip); @@ -155,9 +161,8 @@ static int snd_ad1848_resume(struct platform_device *pdev) } #endif -#define SND_AD1848_DRIVER "snd_ad1848" - -static struct platform_driver snd_ad1848_driver = { +static struct isa_driver snd_ad1848_driver = { + .match = snd_ad1848_match, .probe = snd_ad1848_probe, .remove = __devexit_p(snd_ad1848_remove), #ifdef CONFIG_PM @@ -165,57 +170,19 @@ static struct platform_driver snd_ad1848_driver = { .resume = snd_ad1848_resume, #endif .driver = { - .name = SND_AD1848_DRIVER - }, + .name = DEV_NAME + } }; -static void __init_or_module snd_ad1848_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_ad1848_driver); -} - static int __init alsa_card_ad1848_init(void) { - int i, cards, err; - - err = platform_driver_register(&snd_ad1848_driver); - if (err < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_AD1848_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "AD1848 soundcard not found or device busy\n"); -#endif - snd_ad1848_unregister_all(); - return -ENODEV; - } - return 0; + return isa_register_driver(&snd_ad1848_driver, SNDRV_CARDS); } static void __exit alsa_card_ad1848_exit(void) { - snd_ad1848_unregister_all(); + isa_unregister_driver(&snd_ad1848_driver); } -module_init(alsa_card_ad1848_init) -module_exit(alsa_card_ad1848_exit) +module_init(alsa_card_ad1848_init); +module_exit(alsa_card_ad1848_exit); diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c index 1124344ed948..d68720724c91 100644 --- a/sound/isa/adlib.c +++ b/sound/isa/adlib.c @@ -5,13 +5,13 @@ #include <sound/driver.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <sound/core.h> #include <sound/initval.h> #include <sound/opl3.h> #define CRD_NAME "AdLib FM" -#define DRV_NAME "snd_adlib" +#define DEV_NAME "adlib" MODULE_DESCRIPTION(CRD_NAME); MODULE_AUTHOR("Rene Herman"); @@ -31,133 +31,99 @@ MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); module_param_array(port, long, NULL, 0444); MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -static struct platform_device *devices[SNDRV_CARDS]; +static int __devinit snd_adlib_match(struct device *dev, unsigned int n) +{ + if (!enable[n]) + return 0; + + if (port[n] == SNDRV_AUTO_PORT) { + snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id); + return 0; + } + return 1; +} static void snd_adlib_free(struct snd_card *card) { release_and_free_resource(card->private_data); } -static int __devinit snd_adlib_probe(struct platform_device *device) +static int __devinit snd_adlib_probe(struct device *dev, unsigned int n) { struct snd_card *card; struct snd_opl3 *opl3; + int error; - int error, i = device->id; - - if (port[i] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR DRV_NAME ": please specify port\n"); - error = -EINVAL; - goto out0; - } - - card = snd_card_new(index[i], id[i], THIS_MODULE, 0); + card = snd_card_new(index[n], id[n], THIS_MODULE, 0); if (!card) { - snd_printk(KERN_ERR DRV_NAME ": could not create card\n"); - error = -EINVAL; - goto out0; + snd_printk(KERN_ERR "%s: could not create card\n", dev->bus_id); + return -EINVAL; } - card->private_data = request_region(port[i], 4, CRD_NAME); + card->private_data = request_region(port[n], 4, CRD_NAME); if (!card->private_data) { - snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n"); + snd_printk(KERN_ERR "%s: could not grab ports\n", dev->bus_id); error = -EBUSY; - goto out1; + goto out; } card->private_free = snd_adlib_free; - error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3); + strcpy(card->driver, DEV_NAME); + strcpy(card->shortname, CRD_NAME); + sprintf(card->longname, CRD_NAME " at %#lx", port[n]); + + error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3); if (error < 0) { - snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n"); - goto out1; + snd_printk(KERN_ERR "%s: could not create OPL\n", dev->bus_id); + goto out; } error = snd_opl3_hwdep_new(opl3, 0, 0, NULL); if (error < 0) { - snd_printk(KERN_ERR DRV_NAME ": could not create FM\n"); - goto out1; + snd_printk(KERN_ERR "%s: could not create FM\n", dev->bus_id); + goto out; } - strcpy(card->driver, DRV_NAME); - strcpy(card->shortname, CRD_NAME); - sprintf(card->longname, CRD_NAME " at %#lx", port[i]); - - snd_card_set_dev(card, &device->dev); + snd_card_set_dev(card, dev); error = snd_card_register(card); if (error < 0) { - snd_printk(KERN_ERR DRV_NAME ": could not register card\n"); - goto out1; + snd_printk(KERN_ERR "%s: could not register card\n", dev->bus_id); + goto out; } - platform_set_drvdata(device, card); + dev_set_drvdata(dev, card); return 0; -out1: snd_card_free(card); -out0: return error; +out: snd_card_free(card); + return error; } -static int __devexit snd_adlib_remove(struct platform_device *device) +static int __devexit snd_adlib_remove(struct device *dev, unsigned int n) { - snd_card_free(platform_get_drvdata(device)); - platform_set_drvdata(device, NULL); + snd_card_free(dev_get_drvdata(dev)); + dev_set_drvdata(dev, NULL); return 0; } -static struct platform_driver snd_adlib_driver = { +static struct isa_driver snd_adlib_driver = { + .match = snd_adlib_match, .probe = snd_adlib_probe, .remove = __devexit_p(snd_adlib_remove), .driver = { - .name = DRV_NAME + .name = DEV_NAME } }; static int __init alsa_card_adlib_init(void) { - int i, cards; - - if (platform_driver_register(&snd_adlib_driver) < 0) { - snd_printk(KERN_ERR DRV_NAME ": could not register driver\n"); - return -ENODEV; - } - - for (cards = 0, i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - - if (!enable[i]) - continue; - - device = platform_device_register_simple(DRV_NAME, i, NULL, 0); - if (IS_ERR(device)) - continue; - - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - - devices[i] = device; - cards++; - } - - if (!cards) { -#ifdef MODULE - printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n"); -#endif - platform_driver_unregister(&snd_adlib_driver); - return -ENODEV; - } - return 0; + return isa_register_driver(&snd_adlib_driver, SNDRV_CARDS); } static void __exit alsa_card_adlib_exit(void) { - int i; - - for (i = 0; i < SNDRV_CARDS; i++) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_adlib_driver); + isa_unregister_driver(&snd_adlib_driver); } module_init(alsa_card_adlib_init); diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index c09a8009d2fa..214d65d94c45 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -46,7 +46,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/slab.h> #include <linux/pnp.h> #include <linux/moduleparam.h> @@ -108,7 +108,6 @@ MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver."); module_param_array(wssdma, int, NULL, 0444); MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver."); -static struct platform_device *platform_devices[SNDRV_CARDS]; #ifdef CONFIG_PNP static int pnp_registered; #endif @@ -547,70 +546,78 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) return snd_card_register(card); } -static int __devinit snd_cmi8330_nonpnp_probe(struct platform_device *pdev) +static int __devinit snd_cmi8330_isa_match(struct device *pdev, + unsigned int dev) { - struct snd_card *card; - int err; - int dev = pdev->id; - + if (!enable[dev] || is_isapnp_selected(dev)) + return 0; if (wssport[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR PFX "specify wssport\n"); - return -EINVAL; + return 0; } if (sbport[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR PFX "specify sbport\n"); - return -EINVAL; + return 0; } + return 1; +} + +static int __devinit snd_cmi8330_isa_probe(struct device *pdev, + unsigned int dev) +{ + struct snd_card *card; + int err; card = snd_cmi8330_card_new(dev); if (! card) return -ENOMEM; - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, pdev); if ((err = snd_cmi8330_probe(card, dev)) < 0) { snd_card_free(card); return err; } - platform_set_drvdata(pdev, card); + dev_set_drvdata(pdev, card); return 0; } -static int __devexit snd_cmi8330_nonpnp_remove(struct platform_device *devptr) +static int __devexit snd_cmi8330_isa_remove(struct device *devptr, + unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } #ifdef CONFIG_PM -static int snd_cmi8330_nonpnp_suspend(struct platform_device *dev, pm_message_t state) +static int snd_cmi8330_isa_suspend(struct device *dev, unsigned int n, + pm_message_t state) { - return snd_cmi8330_suspend(platform_get_drvdata(dev)); + return snd_cmi8330_suspend(dev_get_drvdata(dev)); } -static int snd_cmi8330_nonpnp_resume(struct platform_device *dev) +static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n) { - return snd_cmi8330_resume(platform_get_drvdata(dev)); + return snd_cmi8330_resume(dev_get_drvdata(dev)); } #endif -#define CMI8330_DRIVER "snd_cmi8330" +#define DEV_NAME "cmi8330" -static struct platform_driver snd_cmi8330_driver = { - .probe = snd_cmi8330_nonpnp_probe, - .remove = __devexit_p(snd_cmi8330_nonpnp_remove), +static struct isa_driver snd_cmi8330_driver = { + .match = snd_cmi8330_isa_match, + .probe = snd_cmi8330_isa_probe, + .remove = __devexit_p(snd_cmi8330_isa_remove), #ifdef CONFIG_PM - .suspend = snd_cmi8330_nonpnp_suspend, - .resume = snd_cmi8330_nonpnp_resume, + .suspend = snd_cmi8330_isa_suspend, + .resume = snd_cmi8330_isa_resume, #endif .driver = { - .name = CMI8330_DRIVER + .name = DEV_NAME }, }; #ifdef CONFIG_PNP -static unsigned int __devinitdata cmi8330_pnp_devices; - static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, const struct pnp_card_device_id *pid) { @@ -640,7 +647,6 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, } pnp_set_card_drvdata(pcard, card); dev++; - cmi8330_pnp_devices++; return 0; } @@ -675,63 +681,28 @@ static struct pnp_card_driver cmi8330_pnpc_driver = { }; #endif /* CONFIG_PNP */ -static void __init_or_module snd_cmi8330_unregister_all(void) -{ - int i; - -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&cmi8330_pnpc_driver); -#endif - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&snd_cmi8330_driver); -} - static int __init alsa_card_cmi8330_init(void) { - int i, err, cards = 0; + int err; - if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0) + err = isa_register_driver(&snd_cmi8330_driver, SNDRV_CARDS); + if (err < 0) return err; - - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i] || is_isapnp_selected(i)) - continue; - device = platform_device_register_simple(CMI8330_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - cards++; - } - #ifdef CONFIG_PNP err = pnp_register_card_driver(&cmi8330_pnpc_driver); - if (!err) { + if (!err) pnp_registered = 1; - cards += cmi8330_pnp_devices; - } #endif - - if (!cards) { -#ifdef MODULE - snd_printk(KERN_ERR "CMI8330 not found or device busy\n"); -#endif - snd_cmi8330_unregister_all(); - return -ENODEV; - } return 0; } static void __exit alsa_card_cmi8330_exit(void) { - snd_cmi8330_unregister_all(); +#ifdef CONFIG_PNP + if (pnp_registered) + pnp_unregister_card_driver(&cmi8330_pnpc_driver); +#endif + isa_unregister_driver(&snd_cmi8330_driver); } module_init(alsa_card_cmi8330_init) diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index 696a5c86bcfa..ac4041134150 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c @@ -23,7 +23,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/time.h> #include <linux/wait.h> #include <linux/moduleparam.h> @@ -32,8 +32,11 @@ #include <sound/mpu401.h> #include <sound/initval.h> +#define CRD_NAME "Generic CS4231" +#define DEV_NAME "cs4231" + +MODULE_DESCRIPTION(CRD_NAME); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); -MODULE_DESCRIPTION("Generic CS4231"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); @@ -48,132 +51,136 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for CS4231 soundcard."); +MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for CS4231 soundcard."); +MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable CS4231 soundcard."); +MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for CS4231 driver."); +MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for CS4231 driver."); +MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for CS4231 driver."); +MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for CS4231 driver."); +MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for CS4231 driver."); +MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for CS4231 driver."); +MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver."); -static struct platform_device *devices[SNDRV_CARDS]; +static int __devinit snd_cs4231_match(struct device *dev, unsigned int n) +{ + if (!enable[n]) + return 0; + if (port[n] == SNDRV_AUTO_PORT) { + snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id); + return 0; + } + if (irq[n] == SNDRV_AUTO_IRQ) { + snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id); + return 0; + } + if (dma1[n] == SNDRV_AUTO_DMA) { + snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id); + return 0; + } + return 1; +} -static int __init snd_cs4231_probe(struct platform_device *pdev) +static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) { - int dev = pdev->id; struct snd_card *card; - struct snd_pcm *pcm; struct snd_cs4231 *chip; - int err; + struct snd_pcm *pcm; + int error; - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify port\n"); - return -EINVAL; - } - if (irq[dev] == SNDRV_AUTO_IRQ) { - snd_printk(KERN_ERR "specify irq\n"); - return -EINVAL; - } - if (dma1[dev] == SNDRV_AUTO_DMA) { - snd_printk(KERN_ERR "specify dma1\n"); + card = snd_card_new(index[n], id[n], THIS_MODULE, 0); + if (!card) return -EINVAL; - } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; - if ((err = snd_cs4231_create(card, port[dev], -1, - irq[dev], - dma1[dev], - dma2[dev], - CS4231_HW_DETECT, - 0, &chip)) < 0) - goto _err; + + error = snd_cs4231_create(card, port[n], -1, irq[n], dma1[n], dma2[n], + CS4231_HW_DETECT, 0, &chip); + if (error < 0) + goto out; + card->private_data = chip; - if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) - goto _err; + error = snd_cs4231_pcm(chip, 0, &pcm); + if (error < 0) + goto out; strcpy(card->driver, "CS4231"); strcpy(card->shortname, pcm->name); + sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - pcm->name, chip->port, irq[dev], dma1[dev]); - if (dma2[dev] >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); - - if ((err = snd_cs4231_mixer(chip)) < 0) - goto _err; - if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) - goto _err; - - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - if (mpu_irq[dev] == SNDRV_AUTO_IRQ) - mpu_irq[dev] = -1; + pcm->name, chip->port, irq[n], dma1[n]); + if (dma2[n] >= 0) + sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]); + + error = snd_cs4231_mixer(chip); + if (error < 0) + goto out; + + error = snd_cs4231_timer(chip, 0, NULL); + if (error < 0) + goto out; + + if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) { + if (mpu_irq[n] == SNDRV_AUTO_IRQ) + mpu_irq[n] = -1; if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, - mpu_port[dev], 0, - mpu_irq[dev], - mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, + mpu_port[n], 0, mpu_irq[n], + mpu_irq[n] >= 0 ? IRQF_DISABLED : 0, NULL) < 0) - printk(KERN_WARNING "cs4231: MPU401 not detected\n"); + printk(KERN_WARNING "%s: MPU401 not detected\n", dev->bus_id); } - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, dev); - if ((err = snd_card_register(card)) < 0) - goto _err; + error = snd_card_register(card); + if (error < 0) + goto out; - platform_set_drvdata(pdev, card); + dev_set_drvdata(dev, card); return 0; - _err: - snd_card_free(card); - return err; +out: snd_card_free(card); + return error; } -static int __devexit snd_cs4231_remove(struct platform_device *devptr) +static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(dev)); + dev_set_drvdata(dev, NULL); return 0; } #ifdef CONFIG_PM -static int snd_cs4231_suspend(struct platform_device *dev, pm_message_t state) +static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state) { - struct snd_card *card; - struct snd_cs4231 *chip; - card = platform_get_drvdata(dev); + struct snd_card *card = dev_get_drvdata(dev); + struct snd_cs4231 *chip = card->private_data; + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip = card->private_data; chip->suspend(chip); return 0; } -static int snd_cs4231_resume(struct platform_device *dev) +static int snd_cs4231_resume(struct device *dev, unsigned int n) { - struct snd_card *card; - struct snd_cs4231 *chip; - card = platform_get_drvdata(dev); - chip = card->private_data; + struct snd_card *card = dev_get_drvdata(dev); + struct snd_cs4231 *chip = card->private_data; + chip->resume(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif -#define SND_CS4231_DRIVER "snd_cs4231" - -static struct platform_driver snd_cs4231_driver = { +static struct isa_driver snd_cs4231_driver = { + .match = snd_cs4231_match, .probe = snd_cs4231_probe, .remove = __devexit_p(snd_cs4231_remove), #ifdef CONFIG_PM @@ -181,57 +188,19 @@ static struct platform_driver snd_cs4231_driver = { .resume = snd_cs4231_resume, #endif .driver = { - .name = SND_CS4231_DRIVER - }, + .name = DEV_NAME + } }; -static void __init_or_module snd_cs4231_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_cs4231_driver); -} - static int __init alsa_card_cs4231_init(void) { - int i, cards, err; - - err = platform_driver_register(&snd_cs4231_driver); - if (err < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_CS4231_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "CS4231 soundcard not found or device busy\n"); -#endif - snd_cs4231_unregister_all(); - return -ENODEV; - } - return 0; + return isa_register_driver(&snd_cs4231_driver, SNDRV_CARDS); } static void __exit alsa_card_cs4231_exit(void) { - snd_cs4231_unregister_all(); + isa_unregister_driver(&snd_cs4231_driver); } -module_init(alsa_card_cs4231_init) -module_exit(alsa_card_cs4231_exit) +module_init(alsa_card_cs4231_init); +module_exit(alsa_card_cs4231_exit); diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c index 75c7c5f01989..914d77b61b0c 100644 --- a/sound/isa/cs423x/cs4231_lib.c +++ b/sound/isa/cs423x/cs4231_lib.c @@ -405,7 +405,6 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); int result = 0; unsigned int what; - struct list_head *pos; struct snd_pcm_substream *s; int do_start; @@ -425,8 +424,7 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, } what = 0; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == chip->playback_substream) { what |= CS4231_PLAYBACK_ENABLE; snd_pcm_trigger_done(s, substream); diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 07ffd5c22e81..87f1392a2fa7 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -22,7 +22,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/slab.h> #include <linux/pnp.h> #include <linux/moduleparam.h> @@ -75,10 +75,10 @@ MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235}," #ifdef CS4232 #define IDENT "CS4232" -#define CS423X_DRIVER "snd_cs4232" +#define DEV_NAME "cs4232" #else #define IDENT "CS4236+" -#define CS423X_DRIVER "snd_cs4236" +#define DEV_NAME "cs4236" #endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ @@ -126,14 +126,12 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver."); module_param_array(dma2, int, NULL, 0444); MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver."); -static struct platform_device *platform_devices[SNDRV_CARDS]; #ifdef CONFIG_PNP static int pnpc_registered; #ifdef CS4232 static int pnp_registered; #endif #endif /* CONFIG_PNP */ -static unsigned int snd_cs423x_devices; struct snd_card_cs4236 { struct snd_cs4231 *chip; @@ -542,38 +540,55 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) return snd_card_register(card); } -static int __init snd_cs423x_nonpnp_probe(struct platform_device *pdev) +static int __devinit snd_cs423x_isa_match(struct device *pdev, + unsigned int dev) { - int dev = pdev->id; - struct snd_card *card; - int err; + if (!enable[dev] || is_isapnp_selected(dev)) + return 0; if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify port\n"); - return -EINVAL; + snd_printk(KERN_ERR "%s: please specify port\n", pdev->bus_id); + return 0; } if (cport[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify cport\n"); - return -EINVAL; + snd_printk(KERN_ERR "%s: please specify cport\n", pdev->bus_id); + return 0; + } + if (irq[dev] == SNDRV_AUTO_IRQ) { + snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id); + return 0; } + if (dma1[dev] == SNDRV_AUTO_DMA) { + snd_printk(KERN_ERR "%s: please specify dma1\n", pdev->bus_id); + return 0; + } + return 1; +} + +static int __devinit snd_cs423x_isa_probe(struct device *pdev, + unsigned int dev) +{ + struct snd_card *card; + int err; card = snd_cs423x_card_new(dev); if (! card) return -ENOMEM; - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, pdev); if ((err = snd_cs423x_probe(card, dev)) < 0) { snd_card_free(card); return err; } - platform_set_drvdata(pdev, card); + dev_set_drvdata(pdev, card); return 0; } -static int __devexit snd_cs423x_nonpnp_remove(struct platform_device *devptr) +static int __devexit snd_cs423x_isa_remove(struct device *pdev, + unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(pdev)); + dev_set_drvdata(pdev, NULL); return 0; } @@ -594,26 +609,28 @@ static int snd_cs423x_resume(struct snd_card *card) return 0; } -static int snd_cs423x_nonpnp_suspend(struct platform_device *dev, pm_message_t state) +static int snd_cs423x_isa_suspend(struct device *dev, unsigned int n, + pm_message_t state) { - return snd_cs423x_suspend(platform_get_drvdata(dev)); + return snd_cs423x_suspend(dev_get_drvdata(dev)); } -static int snd_cs423x_nonpnp_resume(struct platform_device *dev) +static int snd_cs423x_isa_resume(struct device *dev, unsigned int n) { - return snd_cs423x_resume(platform_get_drvdata(dev)); + return snd_cs423x_resume(dev_get_drvdata(dev)); } #endif -static struct platform_driver cs423x_nonpnp_driver = { - .probe = snd_cs423x_nonpnp_probe, - .remove = __devexit_p(snd_cs423x_nonpnp_remove), +static struct isa_driver cs423x_isa_driver = { + .match = snd_cs423x_isa_match, + .probe = snd_cs423x_isa_probe, + .remove = __devexit_p(snd_cs423x_isa_remove), #ifdef CONFIG_PM - .suspend = snd_cs423x_nonpnp_suspend, - .resume = snd_cs423x_nonpnp_resume, + .suspend = snd_cs423x_isa_suspend, + .resume = snd_cs423x_isa_resume, #endif .driver = { - .name = CS423X_DRIVER + .name = DEV_NAME }, }; @@ -651,7 +668,6 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev, } pnp_set_drvdata(pdev, card); dev++; - snd_cs423x_devices++; return 0; } @@ -715,7 +731,6 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, } pnp_set_card_drvdata(pcard, card); dev++; - snd_cs423x_devices++; return 0; } @@ -750,45 +765,13 @@ static struct pnp_card_driver cs423x_pnpc_driver = { }; #endif /* CONFIG_PNP */ -static void __init_or_module snd_cs423x_unregister_all(void) -{ - int i; - -#ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&cs423x_pnpc_driver); -#ifdef CS4232 - if (pnp_registered) - pnp_unregister_driver(&cs4232_pnp_driver); -#endif -#endif /* CONFIG_PNP */ - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&cs423x_nonpnp_driver); -} - static int __init alsa_card_cs423x_init(void) { - int i, err; + int err; - if ((err = platform_driver_register(&cs423x_nonpnp_driver)) < 0) + err = isa_register_driver(&cs423x_isa_driver, SNDRV_CARDS); + if (err < 0) return err; - - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i] || is_isapnp_selected(i)) - continue; - device = platform_device_register_simple(CS423X_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - snd_cs423x_devices++; - } #ifdef CONFIG_PNP #ifdef CS4232 err = pnp_register_driver(&cs4232_pnp_driver); @@ -799,20 +782,20 @@ static int __init alsa_card_cs423x_init(void) if (!err) pnpc_registered = 1; #endif /* CONFIG_PNP */ - - if (!snd_cs423x_devices) { -#ifdef MODULE - printk(KERN_ERR IDENT " soundcard not found or device busy\n"); -#endif - snd_cs423x_unregister_all(); - return -ENODEV; - } return 0; } static void __exit alsa_card_cs423x_exit(void) { - snd_cs423x_unregister_all(); +#ifdef CONFIG_PNP + if (pnpc_registered) + pnp_unregister_card_driver(&cs423x_pnpc_driver); +#ifdef CS4232 + if (pnp_registered) + pnp_unregister_driver(&cs4232_pnp_driver); +#endif +#endif /* CONFIG_PNP */ + isa_unregister_driver(&cs423x_isa_driver); } module_init(alsa_card_cs423x_init) diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index 65f97ff4eef1..edc398712e8b 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -22,7 +22,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/time.h> #include <linux/wait.h> #include <linux/moduleparam.h> @@ -35,8 +35,11 @@ #define SNDRV_LEGACY_FIND_FREE_DMA #include <sound/initval.h> +#define CRD_NAME "Generic ESS ES1688/ES688 AudioDrive" +#define DEV_NAME "es1688" + +MODULE_DESCRIPTION(CRD_NAME); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); -MODULE_DESCRIPTION("ESS ESx688 AudioDrive"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100}," "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102}," @@ -53,189 +56,157 @@ static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ESx688 soundcard."); +MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ESx688 soundcard."); +MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ESx688 soundcard."); +MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for ESx688 driver."); +MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ESx688 driver."); +MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for ESx688 driver."); +MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ESx688 driver."); +MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver."); - -static struct platform_device *devices[SNDRV_CARDS]; +MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver."); -#define PFX "es1688: " +static int __devinit snd_es1688_match(struct device *dev, unsigned int n) +{ + return enable[n]; +} -static int __devinit snd_es1688_probe(struct platform_device *pdev) +static int __devinit snd_es1688_legacy_create(struct snd_card *card, + struct device *dev, unsigned int n, struct snd_es1688 **rchip) { - int dev = pdev->id; + static long possible_ports[] = {0x220, 0x240, 0x260}; static int possible_irqs[] = {5, 9, 10, 7, -1}; static int possible_dmas[] = {1, 3, 0, -1}; - int xirq, xdma, xmpu_irq; - struct snd_card *card; - struct snd_es1688 *chip; - struct snd_opl3 *opl3; - struct snd_pcm *pcm; - int err; - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; - - xirq = irq[dev]; - if (xirq == SNDRV_AUTO_IRQ) { - if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - err = -EBUSY; - goto _err; + + int i, error; + + if (irq[n] == SNDRV_AUTO_IRQ) { + irq[n] = snd_legacy_find_free_irq(possible_irqs); + if (irq[n] < 0) { + snd_printk(KERN_ERR "%s: unable to find a free IRQ\n", + dev->bus_id); + return -EBUSY; } } - xmpu_irq = mpu_irq[dev]; - xdma = dma8[dev]; - if (xdma == SNDRV_AUTO_DMA) { - if ((xdma = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); - err = -EBUSY; - goto _err; + if (dma8[n] == SNDRV_AUTO_DMA) { + dma8[n] = snd_legacy_find_free_dma(possible_dmas); + if (dma8[n] < 0) { + snd_printk(KERN_ERR "%s: unable to find a free DMA\n", + dev->bus_id); + return -EBUSY; } } - if (port[dev] != SNDRV_AUTO_PORT) { - if ((err = snd_es1688_create(card, port[dev], mpu_port[dev], - xirq, xmpu_irq, xdma, - ES1688_HW_AUTO, &chip)) < 0) - goto _err; - } else { - /* auto-probe legacy ports */ - static unsigned long possible_ports[] = { - 0x220, 0x240, 0x260, - }; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - err = snd_es1688_create(card, possible_ports[i], - mpu_port[dev], - xirq, xmpu_irq, xdma, - ES1688_HW_AUTO, &chip); - if (err >= 0) { - port[dev] = possible_ports[i]; - break; - } - } - if (i >= ARRAY_SIZE(possible_ports)) - goto _err; - } + if (port[n] != SNDRV_AUTO_PORT) + return snd_es1688_create(card, port[n], mpu_port[n], irq[n], + mpu_irq[n], dma8[n], ES1688_HW_AUTO, rchip); + + i = 0; + do { + port[n] = possible_ports[i]; + error = snd_es1688_create(card, port[n], mpu_port[n], irq[n], + mpu_irq[n], dma8[n], ES1688_HW_AUTO, rchip); + } while (error < 0 && ++i < ARRAY_SIZE(possible_ports)); + + return error; +} + +static int __devinit snd_es1688_probe(struct device *dev, unsigned int n) +{ + struct snd_card *card; + struct snd_es1688 *chip; + struct snd_opl3 *opl3; + struct snd_pcm *pcm; + int error; + + card = snd_card_new(index[n], id[n], THIS_MODULE, 0); + if (!card) + return -EINVAL; + + error = snd_es1688_legacy_create(card, dev, n, &chip); + if (error < 0) + goto out; - if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0) - goto _err; + error = snd_es1688_pcm(chip, 0, &pcm); + if (error < 0) + goto out; - if ((err = snd_es1688_mixer(chip)) < 0) - goto _err; + error = snd_es1688_mixer(chip); + if (error < 0) + goto out; strcpy(card->driver, "ES1688"); strcpy(card->shortname, pcm->name); - sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, xirq, xdma); - - if ((snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_OPL3, 0, &opl3)) < 0) { - printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->port); - } else { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) - goto _err; + sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, + chip->port, chip->irq, chip->dma8); + + if (snd_opl3_create(card, chip->port, chip->port + 2, + OPL3_HW_OPL3, 0, &opl3) < 0) + printk(KERN_WARNING "%s: opl3 not detected at 0x%lx\n", + dev->bus_id, chip->port); + else { + error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (error < 0) + goto out; } - if (xmpu_irq >= 0 && xmpu_irq != SNDRV_AUTO_IRQ && chip->mpu_port > 0) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, - chip->mpu_port, 0, - xmpu_irq, - IRQF_DISABLED, - NULL)) < 0) - goto _err; + if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ && + chip->mpu_port > 0) { + error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, + chip->mpu_port, 0, + mpu_irq[n], IRQF_DISABLED, NULL); + if (error < 0) + goto out; } - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, dev); - if ((err = snd_card_register(card)) < 0) - goto _err; + error = snd_card_register(card); + if (error < 0) + goto out; - platform_set_drvdata(pdev, card); + dev_set_drvdata(dev, card); return 0; - _err: - snd_card_free(card); - return err; +out: snd_card_free(card); + return error; } -static int __devexit snd_es1688_remove(struct platform_device *devptr) +static int __devexit snd_es1688_remove(struct device *dev, unsigned int n) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(dev)); + dev_set_drvdata(dev, NULL); return 0; } -#define ES1688_DRIVER "snd_es1688" - -static struct platform_driver snd_es1688_driver = { +static struct isa_driver snd_es1688_driver = { + .match = snd_es1688_match, .probe = snd_es1688_probe, - .remove = __devexit_p(snd_es1688_remove), - /* FIXME: suspend/resume */ + .remove = snd_es1688_remove, +#if 0 /* FIXME */ + .suspend = snd_es1688_suspend, + .resume = snd_es1688_resume, +#endif .driver = { - .name = ES1688_DRIVER - }, + .name = DEV_NAME + } }; -static void __init_or_module snd_es1688_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_es1688_driver); -} - static int __init alsa_card_es1688_init(void) { - int i, cards, err; - - err = platform_driver_register(&snd_es1688_driver); - if (err < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(ES1688_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n"); -#endif - snd_es1688_unregister_all(); - return -ENODEV; - } - return 0; + return isa_register_driver(&snd_es1688_driver, SNDRV_CARDS); } static void __exit alsa_card_es1688_exit(void) { - snd_es1688_unregister_all(); + isa_unregister_driver(&snd_es1688_driver); } -module_init(alsa_card_es1688_init) -module_exit(alsa_card_es1688_exit) +module_init(alsa_card_es1688_init); +module_exit(alsa_card_es1688_exit); diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 725c115ff97d..d2a9c7df0ce5 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -80,7 +80,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/slab.h> #include <linux/pnp.h> #include <linux/isapnp.h> @@ -2035,8 +2035,6 @@ MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver."); module_param_array(dma2, int, NULL, 0444); MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver."); -static struct platform_device *platform_devices[SNDRV_CARDS]; - #ifdef CONFIG_PNP static int pnp_registered, pnpc_registered; @@ -2237,7 +2235,12 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) return snd_card_register(card); } -static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr) +static int __devinit snd_es18xx_isa_match(struct device *pdev, unsigned int dev) +{ + return enable[dev] && !is_isapnp_selected(dev); +} + +static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr) { struct snd_card *card; int err; @@ -2245,18 +2248,17 @@ static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *d card = snd_es18xx_card_new(dev); if (! card) return -ENOMEM; - snd_card_set_dev(card, &devptr->dev); + snd_card_set_dev(card, devptr); if ((err = snd_audiodrive_probe(card, dev)) < 0) { snd_card_free(card); return err; } - platform_set_drvdata(devptr, card); + dev_set_drvdata(devptr, card); return 0; } -static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev) +static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev) { - int dev = pdev->id; int err; static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1}; static int possible_dmas[] = {1, 0, 3, 5, -1}; @@ -2281,13 +2283,13 @@ static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev) } if (port[dev] != SNDRV_AUTO_PORT) { - return snd_es18xx_nonpnp_probe1(dev, pdev); + return snd_es18xx_isa_probe1(dev, pdev); } else { static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280}; int i; for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { port[dev] = possible_ports[i]; - err = snd_es18xx_nonpnp_probe1(dev, pdev); + err = snd_es18xx_isa_probe1(dev, pdev); if (! err) return 0; } @@ -2295,43 +2297,44 @@ static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev) } } -static int __devexit snd_es18xx_nonpnp_remove(struct platform_device *devptr) +static int __devexit snd_es18xx_isa_remove(struct device *devptr, + unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } #ifdef CONFIG_PM -static int snd_es18xx_nonpnp_suspend(struct platform_device *dev, pm_message_t state) +static int snd_es18xx_isa_suspend(struct device *dev, unsigned int n, + pm_message_t state) { - return snd_es18xx_suspend(platform_get_drvdata(dev), state); + return snd_es18xx_suspend(dev_get_drvdata(dev), state); } -static int snd_es18xx_nonpnp_resume(struct platform_device *dev) +static int snd_es18xx_isa_resume(struct device *dev, unsigned int n) { - return snd_es18xx_resume(platform_get_drvdata(dev)); + return snd_es18xx_resume(dev_get_drvdata(dev)); } #endif -#define ES18XX_DRIVER "snd_es18xx" +#define DEV_NAME "es18xx" -static struct platform_driver snd_es18xx_nonpnp_driver = { - .probe = snd_es18xx_nonpnp_probe, - .remove = __devexit_p(snd_es18xx_nonpnp_remove), +static struct isa_driver snd_es18xx_isa_driver = { + .match = snd_es18xx_isa_match, + .probe = snd_es18xx_isa_probe, + .remove = __devexit_p(snd_es18xx_isa_remove), #ifdef CONFIG_PM - .suspend = snd_es18xx_nonpnp_suspend, - .resume = snd_es18xx_nonpnp_resume, + .suspend = snd_es18xx_isa_suspend, + .resume = snd_es18xx_isa_resume, #endif .driver = { - .name = ES18XX_DRIVER + .name = DEV_NAME }, }; #ifdef CONFIG_PNP -static unsigned int __devinitdata es18xx_pnp_devices; - static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, const struct pnp_device_id *id) { @@ -2362,7 +2365,6 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, } pnp_set_drvdata(pdev, card); dev++; - es18xx_pnp_devices++; return 0; } @@ -2424,7 +2426,6 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, pnp_set_card_drvdata(pcard, card); dev++; - es18xx_pnp_devices++; return 0; } @@ -2460,44 +2461,14 @@ static struct pnp_card_driver es18xx_pnpc_driver = { }; #endif /* CONFIG_PNP */ -static void __init_or_module snd_es18xx_unregister_all(void) -{ - int i; - -#ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&es18xx_pnpc_driver); - if (pnp_registered) - pnp_unregister_driver(&es18xx_pnp_driver); -#endif - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&snd_es18xx_nonpnp_driver); -} - static int __init alsa_card_es18xx_init(void) { - int i, err, cards = 0; + int err; - if ((err = platform_driver_register(&snd_es18xx_nonpnp_driver)) < 0) + err = isa_register_driver(&snd_es18xx_isa_driver, SNDRV_CARDS); + if (err < 0) return err; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i] || is_isapnp_selected(i)) - continue; - device = platform_device_register_simple(ES18XX_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - cards++; - } - #ifdef CONFIG_PNP err = pnp_register_driver(&es18xx_pnp_driver); if (!err) @@ -2505,22 +2476,19 @@ static int __init alsa_card_es18xx_init(void) err = pnp_register_card_driver(&es18xx_pnpc_driver); if (!err) pnpc_registered = 1; - cards += es18xx_pnp_devices; -#endif - - if(!cards) { -#ifdef MODULE - snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n"); #endif - snd_es18xx_unregister_all(); - return -ENODEV; - } return 0; } static void __exit alsa_card_es18xx_exit(void) { - snd_es18xx_unregister_all(); +#ifdef CONFIG_PNP + if (pnpc_registered) + pnp_unregister_card_driver(&es18xx_pnpc_driver); + if (pnp_registered) + pnp_unregister_driver(&es18xx_pnp_driver); +#endif + isa_unregister_driver(&snd_es18xx_isa_driver); } module_init(alsa_card_es18xx_init) diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 0395e2e0dd03..8f23f433d491 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c @@ -22,7 +22,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/delay.h> #include <linux/time.h> #include <linux/moduleparam.h> @@ -33,8 +33,11 @@ #define SNDRV_LEGACY_FIND_FREE_DMA #include <sound/initval.h> +#define CRD_NAME "Gravis UltraSound Classic" +#define DEV_NAME "gusclassic" + +MODULE_DESCRIPTION(CRD_NAME); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); -MODULE_DESCRIPTION("Gravis UltraSound Classic"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}"); @@ -51,32 +54,80 @@ static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for GUS Classic soundcard."); +MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for GUS Classic soundcard."); +MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable GUS Classic soundcard."); +MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for GUS Classic driver."); +MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for GUS Classic driver."); +MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for GUS Classic driver."); +MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for GUS Classic driver."); +MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver."); module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Classic driver."); +MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver."); module_param_array(channels, int, NULL, 0444); -MODULE_PARM_DESC(channels, "GF1 channels for GUS Classic driver."); +MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver."); module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver."); +MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver."); + +static int __devinit snd_gusclassic_match(struct device *dev, unsigned int n) +{ + return enable[n]; +} + +static int __devinit snd_gusclassic_create(struct snd_card *card, + struct device *dev, unsigned int n, struct snd_gus_card **rgus) +{ + static long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260}; + static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1}; + static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; + + int i, error; + + if (irq[n] == SNDRV_AUTO_IRQ) { + irq[n] = snd_legacy_find_free_irq(possible_irqs); + if (irq[n] < 0) { + snd_printk(KERN_ERR "%s: unable to find a free IRQ\n", + dev->bus_id); + return -EBUSY; + } + } + if (dma1[n] == SNDRV_AUTO_DMA) { + dma1[n] = snd_legacy_find_free_dma(possible_dmas); + if (dma1[n] < 0) { + snd_printk(KERN_ERR "%s: unable to find a free DMA1\n", + dev->bus_id); + return -EBUSY; + } + } + if (dma2[n] == SNDRV_AUTO_DMA) { + dma2[n] = snd_legacy_find_free_dma(possible_dmas); + if (dma2[n] < 0) { + snd_printk(KERN_ERR "%s: unable to find a free DMA2\n", + dev->bus_id); + return -EBUSY; + } + } -static struct platform_device *devices[SNDRV_CARDS]; + if (port[n] != SNDRV_AUTO_PORT) + return snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n], + 0, channels[n], pcm_channels[n], 0, rgus); + i = 0; + do { + port[n] = possible_ports[i]; + error = snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n], + 0, channels[n], pcm_channels[n], 0, rgus); + } while (error < 0 && ++i < ARRAY_SIZE(possible_ports)); -#define PFX "gusclassic: " + return error; +} -static int __devinit snd_gusclassic_detect(struct snd_gus_card * gus) +static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus) { unsigned char d; @@ -95,187 +146,104 @@ static int __devinit snd_gusclassic_detect(struct snd_gus_card * gus) return 0; } -static void __devinit snd_gusclassic_init(int dev, struct snd_gus_card * gus) -{ - gus->equal_irq = 0; - gus->codec_flag = 0; - gus->max_flag = 0; - gus->joystick_dac = joystick_dac[dev]; -} - -static int __devinit snd_gusclassic_probe(struct platform_device *pdev) +static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n) { - int dev = pdev->id; - static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1}; - static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; - int xirq, xdma1, xdma2; struct snd_card *card; - struct snd_gus_card *gus = NULL; - int err; - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; - if (pcm_channels[dev] < 2) - pcm_channels[dev] = 2; - - xirq = irq[dev]; - if (xirq == SNDRV_AUTO_IRQ) { - if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - err = -EBUSY; - goto _err; - } - } - xdma1 = dma1[dev]; - if (xdma1 == SNDRV_AUTO_DMA) { - if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); - err = -EBUSY; - goto _err; - } - } - xdma2 = dma2[dev]; - if (xdma2 == SNDRV_AUTO_DMA) { - if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); - err = -EBUSY; - goto _err; - } - } + struct snd_gus_card *gus; + int error; - if (port[dev] != SNDRV_AUTO_PORT) { - err = snd_gus_create(card, - port[dev], - xirq, xdma1, xdma2, - 0, channels[dev], pcm_channels[dev], - 0, &gus); - } else { - /* auto-probe legacy ports */ - static unsigned long possible_ports[] = { - 0x220, 0x230, 0x240, 0x250, 0x260, - }; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - err = snd_gus_create(card, - possible_ports[i], - xirq, xdma1, xdma2, - 0, channels[dev], pcm_channels[dev], - 0, &gus); - if (err >= 0) { - port[dev] = possible_ports[i]; - break; - } - } - } - if (err < 0) - goto _err; + card = snd_card_new(index[n], id[n], THIS_MODULE, 0); + if (!card) + return -EINVAL; - if ((err = snd_gusclassic_detect(gus)) < 0) - goto _err; + if (pcm_channels[n] < 2) + pcm_channels[n] = 2; - snd_gusclassic_init(dev, gus); - if ((err = snd_gus_initialize(gus)) < 0) - goto _err; + error = snd_gusclassic_create(card, dev, n, &gus); + if (error < 0) + goto out; + error = snd_gusclassic_detect(gus); + if (error < 0) + goto out; + + gus->joystick_dac = joystick_dac[n]; + + error = snd_gus_initialize(gus); + if (error < 0) + goto out; + + error = -ENODEV; if (gus->max_flag || gus->ess_flag) { - snd_printk(KERN_ERR PFX "GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port); - err = -ENODEV; - goto _err; + snd_printk(KERN_ERR "%s: GUS Classic or ACE soundcard was " + "not detected at 0x%lx\n", dev->bus_id, gus->gf1.port); + goto out; } - if ((err = snd_gf1_new_mixer(gus)) < 0) - goto _err; + error = snd_gf1_new_mixer(gus); + if (error < 0) + goto out; - if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0) - goto _err; + error = snd_gf1_pcm_new(gus, 0, 0, NULL); + if (error < 0) + goto out; if (!gus->ace_flag) { - if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) - goto _err; + error = snd_gf1_rawmidi_new(gus, 0, NULL); + if (error < 0) + goto out; } - sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, xirq, xdma1); - if (xdma2 >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", xdma2); - snd_card_set_dev(card, &pdev->dev); + sprintf(card->longname + strlen(card->longname), + " at 0x%lx, irq %d, dma %d", + gus->gf1.port, gus->gf1.irq, gus->gf1.dma1); - if ((err = snd_card_register(card)) < 0) - goto _err; + if (gus->gf1.dma2 >= 0) + sprintf(card->longname + strlen(card->longname), + "&%d", gus->gf1.dma2); - platform_set_drvdata(pdev, card); + snd_card_set_dev(card, dev); + + error = snd_card_register(card); + if (error < 0) + goto out; + + dev_set_drvdata(dev, card); return 0; - _err: - snd_card_free(card); - return err; +out: snd_card_free(card); + return error; } -static int __devexit snd_gusclassic_remove(struct platform_device *devptr) +static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(dev)); + dev_set_drvdata(dev, NULL); return 0; } -#define GUSCLASSIC_DRIVER "snd_gusclassic" - -static struct platform_driver snd_gusclassic_driver = { +static struct isa_driver snd_gusclassic_driver = { + .match = snd_gusclassic_match, .probe = snd_gusclassic_probe, .remove = __devexit_p(snd_gusclassic_remove), - /* FIXME: suspend/resume */ +#if 0 /* FIXME */ + .suspend = snd_gusclassic_suspend, + .remove = snd_gusclassic_remove, +#endif .driver = { - .name = GUSCLASSIC_DRIVER - }, + .name = DEV_NAME + } }; -static void __init_or_module snd_gusclassic_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_gusclassic_driver); -} - static int __init alsa_card_gusclassic_init(void) { - int i, cards, err; - - err = platform_driver_register(&snd_gusclassic_driver); - if (err < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(GUSCLASSIC_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "GUS Classic soundcard not found or device busy\n"); -#endif - snd_gusclassic_unregister_all(); - return -ENODEV; - } - return 0; + return isa_register_driver(&snd_gusclassic_driver, SNDRV_CARDS); } static void __exit alsa_card_gusclassic_exit(void) { - snd_gusclassic_unregister_all(); + isa_unregister_driver(&snd_gusclassic_driver); } -module_init(alsa_card_gusclassic_init) -module_exit(alsa_card_gusclassic_exit) +module_init(alsa_card_gusclassic_init); +module_exit(alsa_card_gusclassic_exit); diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 4f55fc3e66c1..0aeaa6cf6cf0 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c @@ -22,7 +22,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/delay.h> #include <linux/time.h> #include <linux/moduleparam.h> @@ -37,8 +37,11 @@ #define SNDRV_LEGACY_FIND_FREE_DMA #include <sound/initval.h> +#define CRD_NAME "Gravis UltraSound Extreme" +#define DEV_NAME "gusextreme" + +MODULE_DESCRIPTION(CRD_NAME); MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); -MODULE_DESCRIPTION("Gravis UltraSound Extreme"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}"); @@ -59,43 +62,107 @@ static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for GUS Extreme soundcard."); +MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for GUS Extreme soundcard."); +MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable GUS Extreme soundcard."); +MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for GUS Extreme driver."); +MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); module_param_array(gf1_port, long, NULL, 0444); -MODULE_PARM_DESC(gf1_port, "GF1 port # for GUS Extreme driver (optional)."); +MODULE_PARM_DESC(gf1_port, "GF1 port # for " CRD_NAME " driver (optional)."); module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for GUS Extreme driver."); +MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for GUS Extreme driver."); +MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for GUS Extreme driver."); +MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); module_param_array(gf1_irq, int, NULL, 0444); -MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for GUS Extreme driver."); +MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for " CRD_NAME " driver."); module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for GUS Extreme driver."); +MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver."); module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "GF1 DMA # for GUS Extreme driver."); +MODULE_PARM_DESC(dma1, "GF1 DMA # for " CRD_NAME " driver."); module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Extreme driver."); +MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver."); module_param_array(channels, int, NULL, 0444); -MODULE_PARM_DESC(channels, "GF1 channels for GUS Extreme driver."); +MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver."); module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver."); +MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver."); + +static int __devinit snd_gusextreme_match(struct device *dev, unsigned int n) +{ + return enable[n]; +} + +static int __devinit snd_gusextreme_es1688_create(struct snd_card *card, + struct device *dev, unsigned int n, struct snd_es1688 **rchip) +{ + static long possible_ports[] = {0x220, 0x240, 0x260}; + static int possible_irqs[] = {5, 9, 10, 7, -1}; + static int possible_dmas[] = {1, 3, 0, -1}; + + int i, error; + + if (irq[n] == SNDRV_AUTO_IRQ) { + irq[n] = snd_legacy_find_free_irq(possible_irqs); + if (irq[n] < 0) { + snd_printk(KERN_ERR "%s: unable to find a free IRQ " + "for ES1688\n", dev->bus_id); + return -EBUSY; + } + } + if (dma8[n] == SNDRV_AUTO_DMA) { + dma8[n] = snd_legacy_find_free_dma(possible_dmas); + if (dma8[n] < 0) { + snd_printk(KERN_ERR "%s: unable to find a free DMA " + "for ES1688\n", dev->bus_id); + return -EBUSY; + } + } -static struct platform_device *devices[SNDRV_CARDS]; + if (port[n] != SNDRV_AUTO_PORT) + return snd_es1688_create(card, port[n], mpu_port[n], irq[n], + mpu_irq[n], dma8[n], ES1688_HW_1688, rchip); + i = 0; + do { + port[n] = possible_ports[i]; + error = snd_es1688_create(card, port[n], mpu_port[n], irq[n], + mpu_irq[n], dma8[n], ES1688_HW_1688, rchip); + } while (error < 0 && ++i < ARRAY_SIZE(possible_ports)); -#define PFX "gusextreme: " + return error; +} -static int __devinit snd_gusextreme_detect(int dev, - struct snd_card *card, - struct snd_gus_card * gus, - struct snd_es1688 *es1688) +static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card, + struct device *dev, unsigned int n, struct snd_gus_card **rgus) +{ + static int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1}; + static int possible_dmas[] = {5, 6, 7, 3, 1, -1}; + + if (gf1_irq[n] == SNDRV_AUTO_IRQ) { + gf1_irq[n] = snd_legacy_find_free_irq(possible_irqs); + if (gf1_irq[n] < 0) { + snd_printk(KERN_ERR "%s: unable to find a free IRQ " + "for GF1\n", dev->bus_id); + return -EBUSY; + } + } + if (dma1[n] == SNDRV_AUTO_DMA) { + dma1[n] = snd_legacy_find_free_dma(possible_dmas); + if (dma1[n] < 0) { + snd_printk(KERN_ERR "%s: unable to find a free DMA " + "for GF1\n", dev->bus_id); + return -EBUSY; + } + } + return snd_gus_create(card, gf1_port[n], gf1_irq[n], dma1[n], -1, + 0, channels[n], pcm_channels[n], 0, rgus); +} + +static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus, + struct snd_es1688 *es1688) { unsigned long flags; unsigned char d; @@ -117,12 +184,13 @@ static int __devinit snd_gusextreme_detect(int dev, spin_lock_irqsave(&es1688->mixer_lock, flags); snd_es1688_mixer_write(es1688, 0x40, 0x0b); /* don't change!!! */ spin_unlock_irqrestore(&es1688->mixer_lock, flags); + spin_lock_irqsave(&es1688->reg_lock, flags); - outb(gf1_port[dev] & 0x040 ? 2 : 0, ES1688P(es1688, INIT1)); + outb(gus->gf1.port & 0x040 ? 2 : 0, ES1688P(es1688, INIT1)); outb(0, 0x201); - outb(gf1_port[dev] & 0x020 ? 2 : 0, ES1688P(es1688, INIT1)); + outb(gus->gf1.port & 0x020 ? 2 : 0, ES1688P(es1688, INIT1)); outb(0, 0x201); - outb(gf1_port[dev] & 0x010 ? 3 : 1, ES1688P(es1688, INIT1)); + outb(gus->gf1.port & 0x010 ? 3 : 1, ES1688P(es1688, INIT1)); spin_unlock_irqrestore(&es1688->reg_lock, flags); udelay(100); @@ -139,253 +207,172 @@ static int __devinit snd_gusextreme_detect(int dev, snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -EIO; } - return 0; -} -static void __devinit snd_gusextreme_init(int dev, struct snd_gus_card * gus) -{ - gus->joystick_dac = joystick_dac[dev]; + return 0; } static int __devinit snd_gusextreme_mixer(struct snd_es1688 *chip) { struct snd_card *card = chip->card; struct snd_ctl_elem_id id1, id2; - int err; + int error; memset(&id1, 0, sizeof(id1)); memset(&id2, 0, sizeof(id2)); id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + /* reassign AUX to SYNTHESIZER */ strcpy(id1.name, "Aux Playback Volume"); strcpy(id2.name, "Synth Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; + error = snd_ctl_rename_id(card, &id1, &id2); + if (error < 0) + return error; + /* reassign Master Playback Switch to Synth Playback Switch */ strcpy(id1.name, "Master Playback Switch"); strcpy(id2.name, "Synth Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; + error = snd_ctl_rename_id(card, &id1, &id2); + if (error < 0) + return error; + return 0; } -static int __devinit snd_gusextreme_probe(struct platform_device *pdev) +static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n) { - int dev = pdev->id; - static int possible_ess_irqs[] = {5, 9, 10, 7, -1}; - static int possible_ess_dmas[] = {1, 3, 0, -1}; - static int possible_gf1_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; - static int possible_gf1_dmas[] = {5, 6, 7, 1, 3, -1}; - int xgf1_irq, xgf1_dma, xess_irq, xmpu_irq, xess_dma; struct snd_card *card; struct snd_gus_card *gus; struct snd_es1688 *es1688; struct snd_opl3 *opl3; - int err; + int error; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + card = snd_card_new(index[n], id[n], THIS_MODULE, 0); + if (!card) + return -EINVAL; - xgf1_irq = gf1_irq[dev]; - if (xgf1_irq == SNDRV_AUTO_IRQ) { - if ((xgf1_irq = snd_legacy_find_free_irq(possible_gf1_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ for GF1\n"); - err = -EBUSY; - goto out; - } - } - xess_irq = irq[dev]; - if (xess_irq == SNDRV_AUTO_IRQ) { - if ((xess_irq = snd_legacy_find_free_irq(possible_ess_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ for ES1688\n"); - err = -EBUSY; - goto out; - } - } - if (mpu_port[dev] == SNDRV_AUTO_PORT) - mpu_port[dev] = 0; - xmpu_irq = mpu_irq[dev]; - if (xmpu_irq > 15) - xmpu_irq = -1; - xgf1_dma = dma1[dev]; - if (xgf1_dma == SNDRV_AUTO_DMA) { - if ((xgf1_dma = snd_legacy_find_free_dma(possible_gf1_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA for GF1\n"); - err = -EBUSY; - goto out; - } - } - xess_dma = dma8[dev]; - if (xess_dma == SNDRV_AUTO_DMA) { - if ((xess_dma = snd_legacy_find_free_dma(possible_ess_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA for ES1688\n"); - err = -EBUSY; - goto out; - } - } + if (mpu_port[n] == SNDRV_AUTO_PORT) + mpu_port[n] = 0; - if (port[dev] != SNDRV_AUTO_PORT) { - err = snd_es1688_create(card, port[dev], mpu_port[dev], - xess_irq, xmpu_irq, xess_dma, - ES1688_HW_1688, &es1688); - } else { - /* auto-probe legacy ports */ - static unsigned long possible_ports[] = {0x220, 0x240, 0x260}; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - err = snd_es1688_create(card, - possible_ports[i], - mpu_port[dev], - xess_irq, xmpu_irq, xess_dma, - ES1688_HW_1688, &es1688); - if (err >= 0) { - port[dev] = possible_ports[i]; - break; - } - } - } - if (err < 0) + if (mpu_irq[n] > 15) + mpu_irq[n] = -1; + + error = snd_gusextreme_es1688_create(card, dev, n, &es1688); + if (error < 0) goto out; - if (gf1_port[dev] < 0) - gf1_port[dev] = port[dev] + 0x20; - if ((err = snd_gus_create(card, - gf1_port[dev], - xgf1_irq, - xgf1_dma, - -1, - 0, channels[dev], - pcm_channels[dev], 0, - &gus)) < 0) + if (gf1_port[n] < 0) + gf1_port[n] = es1688->port + 0x20; + + error = snd_gusextreme_gus_card_create(card, dev, n, &gus); + if (error < 0) goto out; - if ((err = snd_gusextreme_detect(dev, card, gus, es1688)) < 0) + error = snd_gusextreme_detect(gus, es1688); + if (error < 0) goto out; - snd_gusextreme_init(dev, gus); - if ((err = snd_gus_initialize(gus)) < 0) + gus->joystick_dac = joystick_dac[n]; + + error = snd_gus_initialize(gus); + if (error < 0) goto out; + error = -ENODEV; if (!gus->ess_flag) { - snd_printk(KERN_ERR PFX "GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port); - err = -ENODEV; + snd_printk(KERN_ERR "%s: GUS Extreme soundcard was not " + "detected at 0x%lx\n", dev->bus_id, gus->gf1.port); goto out; } - if ((err = snd_es1688_pcm(es1688, 0, NULL)) < 0) + gus->codec_flag = 1; + + error = snd_es1688_pcm(es1688, 0, NULL); + if (error < 0) goto out; - if ((err = snd_es1688_mixer(es1688)) < 0) + error = snd_es1688_mixer(es1688); + if (error < 0) goto out; snd_component_add(card, "ES1688"); - if (pcm_channels[dev] > 0) { - if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) + + if (pcm_channels[n] > 0) { + error = snd_gf1_pcm_new(gus, 1, 1, NULL); + if (error < 0) goto out; } - if ((err = snd_gf1_new_mixer(gus)) < 0) + + error = snd_gf1_new_mixer(gus); + if (error < 0) goto out; - if ((err = snd_gusextreme_mixer(es1688)) < 0) + error = snd_gusextreme_mixer(es1688); + if (error < 0) goto out; if (snd_opl3_create(card, es1688->port, es1688->port + 2, - OPL3_HW_OPL3, 0, &opl3) < 0) { - printk(KERN_ERR PFX "gusextreme: opl3 not detected at 0x%lx\n", es1688->port); - } else { - if ((err = snd_opl3_hwdep_new(opl3, 0, 2, NULL)) < 0) + OPL3_HW_OPL3, 0, &opl3) < 0) + printk(KERN_ERR "%s: opl3 not detected at 0x%lx\n", + dev->bus_id, es1688->port); + else { + error = snd_opl3_hwdep_new(opl3, 0, 2, NULL); + if (error < 0) goto out; } - if (es1688->mpu_port >= 0x300 && - (err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, - es1688->mpu_port, 0, - xmpu_irq, - IRQF_DISABLED, - NULL)) < 0) - goto out; + if (es1688->mpu_port >= 0x300) { + error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, + es1688->mpu_port, 0, + mpu_irq[n], IRQF_DISABLED, NULL); + if (error < 0) + goto out; + } - sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i", - es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma); + sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, " + "irq %i&%i, dma %i&%i", es1688->port, + gus->gf1.irq, es1688->irq, gus->gf1.dma1, es1688->dma8); - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, dev); - if ((err = snd_card_register(card)) < 0) + error = snd_card_register(card); + if (error < 0) goto out; - platform_set_drvdata(pdev, card); + dev_set_drvdata(dev, card); return 0; - out: - snd_card_free(card); - return err; +out: snd_card_free(card); + return error; } -static int __devexit snd_gusextreme_remove(struct platform_device *devptr) +static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(dev)); + dev_set_drvdata(dev, NULL); return 0; } -#define GUSEXTREME_DRIVER "snd_gusextreme" - -static struct platform_driver snd_gusextreme_driver = { +static struct isa_driver snd_gusextreme_driver = { + .match = snd_gusextreme_match, .probe = snd_gusextreme_probe, - .remove = __devexit_p(snd_gusextreme_remove), - /* FIXME: suspend/resume */ + .remove = snd_gusextreme_remove, +#if 0 /* FIXME */ + .suspend = snd_gusextreme_suspend, + .resume = snd_gusextreme_resume, +#endif .driver = { - .name = GUSEXTREME_DRIVER - }, + .name = DEV_NAME + } }; -static void __init_or_module snd_gusextreme_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_gusextreme_driver); -} - static int __init alsa_card_gusextreme_init(void) { - int i, cards, err; - - err = platform_driver_register(&snd_gusextreme_driver); - if (err < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(GUSEXTREME_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n"); -#endif - snd_gusextreme_unregister_all(); - return -ENODEV; - } - return 0; + return isa_register_driver(&snd_gusextreme_driver, SNDRV_CARDS); } static void __exit alsa_card_gusextreme_exit(void) { - snd_gusextreme_unregister_all(); + isa_unregister_driver(&snd_gusextreme_driver); } -module_init(alsa_card_gusextreme_init) -module_exit(alsa_card_gusextreme_exit) +module_init(alsa_card_gusextreme_init); +module_exit(alsa_card_gusextreme_exit); diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index d1ad90ca035d..708783d4351f 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c @@ -22,7 +22,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/delay.h> #include <linux/time.h> #include <linux/moduleparam.h> @@ -72,8 +72,6 @@ MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver."); module_param_array(pcm_channels, int, NULL, 0444); MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver."); -static struct platform_device *devices[SNDRV_CARDS]; - struct snd_gusmax { int irq; struct snd_card *card; @@ -205,9 +203,13 @@ static void snd_gusmax_free(struct snd_card *card) free_irq(maxcard->irq, (void *)maxcard); } -static int __devinit snd_gusmax_probe(struct platform_device *pdev) +static int __devinit snd_gusmax_match(struct device *pdev, unsigned int dev) +{ + return enable[dev]; +} + +static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) { - int dev = pdev->id; static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; int xirq, xdma1, xdma2, err; @@ -333,7 +335,7 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev) if (xdma2 >= 0) sprintf(card->longname + strlen(card->longname), "&%i", xdma2); - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, pdev); if ((err = snd_card_register(card)) < 0) goto _err; @@ -341,7 +343,7 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev) maxcard->gus = gus; maxcard->cs4231 = cs4231; - platform_set_drvdata(pdev, card); + dev_set_drvdata(pdev, card); return 0; _err: @@ -349,70 +351,33 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev) return err; } -static int __devexit snd_gusmax_remove(struct platform_device *devptr) +static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } -#define GUSMAX_DRIVER "snd_gusmax" +#define DEV_NAME "gusmax" -static struct platform_driver snd_gusmax_driver = { +static struct isa_driver snd_gusmax_driver = { + .match = snd_gusmax_match, .probe = snd_gusmax_probe, .remove = __devexit_p(snd_gusmax_remove), /* FIXME: suspend/resume */ .driver = { - .name = GUSMAX_DRIVER + .name = DEV_NAME }, }; -static void __init_or_module snd_gusmax_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_gusmax_driver); -} - static int __init alsa_card_gusmax_init(void) { - int i, cards, err; - - err = platform_driver_register(&snd_gusmax_driver); - if (err < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(GUSMAX_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "GUS MAX soundcard not found or device busy\n"); -#endif - snd_gusmax_unregister_all(); - return -ENODEV; - } - return 0; + return isa_register_driver(&snd_gusmax_driver, SNDRV_CARDS); } static void __exit alsa_card_gusmax_exit(void) { - snd_gusmax_unregister_all(); + isa_unregister_driver(&snd_gusmax_driver); } module_init(alsa_card_gusmax_init) diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 4ec2d79431fc..3e4657255536 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -25,7 +25,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/pnp.h> @@ -115,9 +115,6 @@ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver."); module_param_array(effect, int, NULL, 0444); MODULE_PARM_DESC(effect, "Effects enable for InterWave driver."); -static struct platform_device *platform_devices[SNDRV_CARDS]; -static int pnp_registered; - struct snd_interwave { int irq; struct snd_card *card; @@ -138,6 +135,7 @@ struct snd_interwave { #ifdef CONFIG_PNP +static int pnp_registered; static struct pnp_card_device_id snd_interwave_pnpids[] = { #ifndef SNDRV_STB @@ -793,7 +791,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev) return 0; } -static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr) +static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr) { struct snd_card *card; int err; @@ -802,18 +800,30 @@ static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device if (! card) return -ENOMEM; - snd_card_set_dev(card, &devptr->dev); + snd_card_set_dev(card, devptr); if ((err = snd_interwave_probe(card, dev)) < 0) { snd_card_free(card); return err; } - platform_set_drvdata(devptr, card); + dev_set_drvdata(devptr, card); return 0; } -static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev) +static int __devinit snd_interwave_isa_match(struct device *pdev, + unsigned int dev) +{ + if (!enable[dev]) + return 0; +#ifdef CONFIG_PNP + if (isapnp[dev]) + return 0; +#endif + return 1; +} + +static int __devinit snd_interwave_isa_probe(struct device *pdev, + unsigned int dev) { - int dev = pdev->id; int err; static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1}; @@ -838,13 +848,13 @@ static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev) } if (port[dev] != SNDRV_AUTO_PORT) - return snd_interwave_nonpnp_probe1(dev, pdev); + return snd_interwave_isa_probe1(dev, pdev); else { static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260}; int i; for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { port[dev] = possible_ports[i]; - err = snd_interwave_nonpnp_probe1(dev, pdev); + err = snd_interwave_isa_probe1(dev, pdev); if (! err) return 0; } @@ -852,16 +862,17 @@ static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev) } } -static int __devexit snd_interwave_nonpnp_remove(struct platform_device *devptr) +static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } -static struct platform_driver snd_interwave_driver = { - .probe = snd_interwave_nonpnp_probe, - .remove = __devexit_p(snd_interwave_nonpnp_remove), +static struct isa_driver snd_interwave_driver = { + .match = snd_interwave_isa_match, + .probe = snd_interwave_isa_probe, + .remove = __devexit_p(snd_interwave_isa_remove), /* FIXME: suspend,resume */ .driver = { .name = INTERWAVE_DRIVER @@ -869,8 +880,6 @@ static struct platform_driver snd_interwave_driver = { }; #ifdef CONFIG_PNP -static unsigned int __devinitdata interwave_pnp_devices; - static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, const struct pnp_card_device_id *pid) { @@ -900,7 +909,6 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, } pnp_set_card_drvdata(pcard, card); dev++; - interwave_pnp_devices++; return 0; } @@ -921,64 +929,29 @@ static struct pnp_card_driver interwave_pnpc_driver = { #endif /* CONFIG_PNP */ -static void __init_or_module snd_interwave_unregister_all(void) -{ - int i; - - if (pnp_registered) - pnp_unregister_card_driver(&interwave_pnpc_driver); - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&snd_interwave_driver); -} - static int __init alsa_card_interwave_init(void) { - int i, err, cards = 0; + int err; - if ((err = platform_driver_register(&snd_interwave_driver)) < 0) + err = isa_register_driver(&snd_interwave_driver, SNDRV_CARDS); + if (err < 0) return err; - - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; #ifdef CONFIG_PNP - if (isapnp[i]) - continue; -#endif - device = platform_device_register_simple(INTERWAVE_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - cards++; - } - /* ISA PnP cards */ err = pnp_register_card_driver(&interwave_pnpc_driver); - if (!err) { + if (!err) pnp_registered = 1; - cards += interwave_pnp_devices;; - } - - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "InterWave soundcard not found or device busy\n"); #endif - snd_interwave_unregister_all(); - return -ENODEV; - } return 0; } static void __exit alsa_card_interwave_exit(void) { - snd_interwave_unregister_all(); +#ifdef CONFIG_PNP + if (pnp_registered) + pnp_unregister_card_driver(&interwave_pnpc_driver); +#endif + isa_unregister_driver(&snd_interwave_driver); } module_init(alsa_card_interwave_init) diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index f3db686b1c0c..48743eb85fb6 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -22,7 +22,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/interrupt.h> #include <linux/pm.h> #include <linux/slab.h> @@ -91,12 +91,10 @@ MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver."); module_param_array(opl3sa3_ymode, int, NULL, 0444); MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi."); -static struct platform_device *platform_devices[SNDRV_CARDS]; #ifdef CONFIG_PNP static int pnp_registered; static int pnpc_registered; #endif -static unsigned int snd_opl3sa2_devices; /* control ports */ #define OPL3SA2_PM_CTRL 0x01 @@ -783,7 +781,6 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, } pnp_set_drvdata(pdev, card); dev++; - snd_opl3sa2_devices++; return 0; } @@ -850,7 +847,6 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, } pnp_set_card_drvdata(pcard, card); dev++; - snd_opl3sa2_devices++; return 0; } @@ -884,116 +880,95 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = { }; #endif /* CONFIG_PNP */ -static int __devinit snd_opl3sa2_nonpnp_probe(struct platform_device *pdev) +static int __devinit snd_opl3sa2_isa_match(struct device *pdev, + unsigned int dev) { - struct snd_card *card; - int err; - int dev = pdev->id; - + if (!enable[dev]) + return 0; +#ifdef CONFIG_PNP + if (isapnp[dev]) + return 0; +#endif if (port[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR PFX "specify port\n"); - return -EINVAL; + return 0; } if (wss_port[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR PFX "specify wss_port\n"); - return -EINVAL; + return 0; } if (fm_port[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR PFX "specify fm_port\n"); - return -EINVAL; + return 0; } if (midi_port[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR PFX "specify midi_port\n"); - return -EINVAL; + return 0; } + return 1; +} + +static int __devinit snd_opl3sa2_isa_probe(struct device *pdev, + unsigned int dev) +{ + struct snd_card *card; + int err; card = snd_opl3sa2_card_new(dev); if (! card) return -ENOMEM; - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, pdev); if ((err = snd_opl3sa2_probe(card, dev)) < 0) { snd_card_free(card); return err; } - platform_set_drvdata(pdev, card); + dev_set_drvdata(pdev, card); return 0; } -static int __devexit snd_opl3sa2_nonpnp_remove(struct platform_device *devptr) +static int __devexit snd_opl3sa2_isa_remove(struct device *devptr, + unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } #ifdef CONFIG_PM -static int snd_opl3sa2_nonpnp_suspend(struct platform_device *dev, pm_message_t state) +static int snd_opl3sa2_isa_suspend(struct device *dev, unsigned int n, + pm_message_t state) { - return snd_opl3sa2_suspend(platform_get_drvdata(dev), state); + return snd_opl3sa2_suspend(dev_get_drvdata(dev), state); } -static int snd_opl3sa2_nonpnp_resume(struct platform_device *dev) +static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n) { - return snd_opl3sa2_resume(platform_get_drvdata(dev)); + return snd_opl3sa2_resume(dev_get_drvdata(dev)); } #endif -#define OPL3SA2_DRIVER "snd_opl3sa2" +#define DEV_NAME "opl3sa2" -static struct platform_driver snd_opl3sa2_nonpnp_driver = { - .probe = snd_opl3sa2_nonpnp_probe, - .remove = __devexit( snd_opl3sa2_nonpnp_remove), +static struct isa_driver snd_opl3sa2_isa_driver = { + .match = snd_opl3sa2_isa_match, + .probe = snd_opl3sa2_isa_probe, + .remove = __devexit( snd_opl3sa2_isa_remove), #ifdef CONFIG_PM - .suspend = snd_opl3sa2_nonpnp_suspend, - .resume = snd_opl3sa2_nonpnp_resume, + .suspend = snd_opl3sa2_isa_suspend, + .resume = snd_opl3sa2_isa_resume, #endif .driver = { - .name = OPL3SA2_DRIVER + .name = DEV_NAME }, }; -static void __init_or_module snd_opl3sa2_unregister_all(void) -{ - int i; - -#ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&opl3sa2_pnpc_driver); - if (pnp_registered) - pnp_unregister_driver(&opl3sa2_pnp_driver); -#endif - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&snd_opl3sa2_nonpnp_driver); -} - static int __init alsa_card_opl3sa2_init(void) { - int i, err; + int err; - if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0) + err = isa_register_driver(&snd_opl3sa2_isa_driver, SNDRV_CARDS); + if (err < 0) return err; - - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; -#ifdef CONFIG_PNP - if (isapnp[i]) - continue; -#endif - device = platform_device_register_simple(OPL3SA2_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - snd_opl3sa2_devices++; - } - #ifdef CONFIG_PNP err = pnp_register_driver(&opl3sa2_pnp_driver); if (!err) @@ -1002,20 +977,18 @@ static int __init alsa_card_opl3sa2_init(void) if (!err) pnpc_registered = 1; #endif - - if (!snd_opl3sa2_devices) { -#ifdef MODULE - snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n"); -#endif - snd_opl3sa2_unregister_all(); - return -ENODEV; - } return 0; } static void __exit alsa_card_opl3sa2_exit(void) { - snd_opl3sa2_unregister_all(); +#ifdef CONFIG_PNP + if (pnpc_registered) + pnp_unregister_card_driver(&opl3sa2_pnpc_driver); + if (pnp_registered) + pnp_unregister_driver(&opl3sa2_pnp_driver); +#endif + isa_unregister_driver(&snd_opl3sa2_isa_driver); } module_init(alsa_card_opl3sa2_init) diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 1dd98375ac85..cd29b30b362e 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -25,7 +25,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/ioport.h> @@ -137,10 +137,6 @@ struct snd_miro { static void snd_miro_proc_init(struct snd_miro * miro); -#define DRIVER_NAME "snd-miro" - -static struct platform_device *device; - static char * snd_opti9xx_names[] = { "unkown", "82C928", "82C929", @@ -558,7 +554,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, return change; } -static struct snd_kcontrol_new snd_miro_controls[] = { +static struct snd_kcontrol_new snd_miro_controls[] __devinitdata = { MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER), MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC), MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE), @@ -570,7 +566,7 @@ MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2), /* Equalizer with seven bands (only PCM20) from -12dB up to +12dB on each band */ -static struct snd_kcontrol_new snd_miro_eq_controls[] = { +static struct snd_kcontrol_new snd_miro_eq_controls[] __devinitdata = { MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1), MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2), MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3), @@ -580,15 +576,15 @@ MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6), MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7), }; -static struct snd_kcontrol_new snd_miro_radio_control[] = { +static struct snd_kcontrol_new snd_miro_radio_control[] __devinitdata = { MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1), }; -static struct snd_kcontrol_new snd_miro_line_control[] = { +static struct snd_kcontrol_new snd_miro_line_control[] __devinitdata = { MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1), }; -static struct snd_kcontrol_new snd_miro_preamp_control[] = { +static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic Boost", @@ -598,7 +594,7 @@ static struct snd_kcontrol_new snd_miro_preamp_control[] = { .put = snd_miro_put_preamp, }}; -static struct snd_kcontrol_new snd_miro_amp_control[] = { +static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line Boost", @@ -608,7 +604,7 @@ static struct snd_kcontrol_new snd_miro_amp_control[] = { .put = snd_miro_put_amp, }}; -static struct snd_kcontrol_new snd_miro_capture_control[] = { +static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Capture Switch", @@ -618,7 +614,7 @@ static struct snd_kcontrol_new snd_miro_capture_control[] = { .put = snd_miro_put_capture, }}; -static unsigned char aci_init_values[][2] __initdata = { +static unsigned char aci_init_values[][2] __devinitdata = { { ACI_SET_MUTE, 0x00 }, { ACI_SET_POWERAMP, 0x00 }, { ACI_SET_PREAMP, 0x00 }, @@ -641,7 +637,7 @@ static unsigned char aci_init_values[][2] __initdata = { { ACI_SET_MASTER + 1, 0x20 }, }; -static int __init snd_set_aci_init_values(struct snd_miro *miro) +static int __devinit snd_set_aci_init_values(struct snd_miro *miro) { int idx, error; @@ -751,7 +747,8 @@ static long snd_legacy_find_free_ioport(long *port_table, long size) return -1; } -static int __init snd_miro_init(struct snd_miro *chip, unsigned short hardware) +static int __devinit snd_miro_init(struct snd_miro *chip, + unsigned short hardware) { static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; @@ -962,7 +959,7 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp); } -static void __init snd_miro_proc_init(struct snd_miro * miro) +static void __devinit snd_miro_proc_init(struct snd_miro * miro) { struct snd_info_entry *entry; @@ -974,7 +971,7 @@ static void __init snd_miro_proc_init(struct snd_miro * miro) * Init */ -static int __init snd_miro_configure(struct snd_miro *chip) +static int __devinit snd_miro_configure(struct snd_miro *chip) { unsigned char wss_base_bits; unsigned char irq_bits; @@ -1131,7 +1128,8 @@ __skip_mpu: return 0; } -static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *chip) +static int __devinit snd_card_miro_detect(struct snd_card *card, + struct snd_miro *chip) { int i, err; unsigned char value; @@ -1157,7 +1155,8 @@ static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *c return -ENODEV; } -static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro * miro) +static int __devinit snd_card_miro_aci_detect(struct snd_card *card, + struct snd_miro * miro) { unsigned char regval; int i; @@ -1213,7 +1212,12 @@ static void snd_card_miro_free(struct snd_card *card) release_and_free_resource(miro->res_mc_base); } -static int __init snd_miro_probe(struct platform_device *devptr) +static int __devinit snd_miro_match(struct device *devptr, unsigned int n) +{ + return 1; +} + +static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) { static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1}; @@ -1399,56 +1403,44 @@ static int __init snd_miro_probe(struct platform_device *devptr) return error; } - snd_card_set_dev(card, &devptr->dev); + snd_card_set_dev(card, devptr); if ((error = snd_card_register(card))) { snd_card_free(card); return error; } - platform_set_drvdata(devptr, card); + dev_set_drvdata(devptr, card); return 0; } -static int __devexit snd_miro_remove(struct platform_device *devptr) +static int __devexit snd_miro_remove(struct device *devptr, unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } -static struct platform_driver snd_miro_driver = { +#define DEV_NAME "miro" + +static struct isa_driver snd_miro_driver = { + .match = snd_miro_match, .probe = snd_miro_probe, .remove = __devexit_p(snd_miro_remove), /* FIXME: suspend/resume */ .driver = { - .name = DRIVER_NAME + .name = DEV_NAME }, }; static int __init alsa_card_miro_init(void) { - int error; - - if ((error = platform_driver_register(&snd_miro_driver)) < 0) - return error; - device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); - if (! IS_ERR(device)) { - if (platform_get_drvdata(device)) - return 0; - platform_device_unregister(device); - } -#ifdef MODULE - printk(KERN_ERR "no miro soundcard found\n"); -#endif - platform_driver_unregister(&snd_miro_driver); - return PTR_ERR(device); + return isa_register_driver(&snd_miro_driver, 1); } static void __exit alsa_card_miro_exit(void) { - platform_device_unregister(device); - platform_driver_unregister(&snd_miro_driver); + isa_unregister_driver(&snd_miro_driver); } module_init(alsa_card_miro_init) diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index df227377c333..60c120ffb9de 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -26,7 +26,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/pnp.h> @@ -259,7 +259,6 @@ struct snd_opti9xx { }; static int snd_opti9xx_pnp_is_probed; -static struct platform_device *snd_opti9xx_platform_device; #ifdef CONFIG_PNP @@ -281,10 +280,10 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids); #endif /* CONFIG_PNP */ #ifdef OPTi93X -#define DRIVER_NAME "snd-card-opti93x" +#define DEV_NAME "opti93x" #else -#define DRIVER_NAME "snd-card-opti92x" -#endif /* OPTi93X */ +#define DEV_NAME "opti92x" +#endif static char * snd_opti9xx_names[] = { "unkown", @@ -294,7 +293,7 @@ static char * snd_opti9xx_names[] = { }; -static long __init snd_legacy_find_free_ioport(long *port_table, long size) +static long __devinit snd_legacy_find_free_ioport(long *port_table, long size) { while (*port_table != -1) { if (request_region(*port_table, size, "ALSA test")) { @@ -306,7 +305,8 @@ static long __init snd_legacy_find_free_ioport(long *port_table, long size) return -1; } -static int __init snd_opti9xx_init(struct snd_opti9xx *chip, unsigned short hardware) +static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, + unsigned short hardware) { static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; @@ -451,7 +451,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) -static int __init snd_opti9xx_configure(struct snd_opti9xx *chip) +static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip) { unsigned char wss_base_bits; unsigned char irq_bits; @@ -934,10 +934,8 @@ static int snd_opti93x_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_STOP: { unsigned int what = 0; - struct list_head *pos; struct snd_pcm_substream *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == chip->playback_substream) { what |= OPTi93X_PLAYBACK_ENABLE; snd_pcm_trigger_done(s, substream); @@ -1291,7 +1289,7 @@ static int snd_opti93x_create(struct snd_card *card, struct snd_opti9xx *chip, } codec->dma2 = chip->dma2; - if (request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DRIVER_NAME" - WSS", codec)) { + if (request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DEV_NAME" - WSS", codec)) { snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq); snd_opti93x_free(codec); return -EBUSY; @@ -1561,7 +1559,7 @@ static int snd_opti93x_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ return change; } -static struct snd_kcontrol_new snd_opti93x_controls[] = { +static struct snd_kcontrol_new snd_opti93x_controls[] __devinitdata = { OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1), @@ -1622,7 +1620,8 @@ static int snd_opti93x_mixer(struct snd_opti93x *chip) #endif /* OPTi93X */ -static int __init snd_card_opti9xx_detect(struct snd_card *card, struct snd_opti9xx *chip) +static int __devinit snd_card_opti9xx_detect(struct snd_card *card, + struct snd_opti9xx *chip) { int i, err; @@ -1676,8 +1675,9 @@ static int __init snd_card_opti9xx_detect(struct snd_card *card, struct snd_opti } #ifdef CONFIG_PNP -static int __init snd_card_opti9xx_pnp(struct snd_opti9xx *chip, struct pnp_card_link *card, - const struct pnp_card_device_id *pid) +static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, + struct pnp_card_link *card, + const struct pnp_card_device_id *pid) { struct pnp_dev *pdev; struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); @@ -1778,7 +1778,7 @@ static void snd_card_opti9xx_free(struct snd_card *card) release_and_free_resource(chip->res_mc_base); } -static int __init snd_opti9xx_probe(struct snd_card *card) +static int __devinit snd_opti9xx_probe(struct snd_card *card) { static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; int error; @@ -1924,7 +1924,18 @@ static struct snd_card *snd_opti9xx_card_new(void) return card; } -static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr) +static int __devinit snd_opti9xx_isa_match(struct device *devptr, + unsigned int dev) +{ + if (snd_opti9xx_pnp_is_probed) + return 0; + if (isapnp) + return 0; + return 1; +} + +static int __devinit snd_opti9xx_isa_probe(struct device *devptr, + unsigned int dev) { struct snd_card *card; int error; @@ -1940,9 +1951,6 @@ static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr) static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}}; #endif /* CS4231 || OPTi93X */ - if (snd_opti9xx_pnp_is_probed) - return -EBUSY; - if (mpu_port == SNDRV_AUTO_PORT) { if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) { snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); @@ -1984,34 +1992,36 @@ static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr) snd_card_free(card); return error; } - snd_card_set_dev(card, &devptr->dev); + snd_card_set_dev(card, devptr); if ((error = snd_opti9xx_probe(card)) < 0) { snd_card_free(card); return error; } - platform_set_drvdata(devptr, card); + dev_set_drvdata(devptr, card); return 0; } -static int __devexit snd_opti9xx_nonpnp_remove(struct platform_device *devptr) +static int __devexit snd_opti9xx_isa_remove(struct device *devptr, + unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } -static struct platform_driver snd_opti9xx_driver = { - .probe = snd_opti9xx_nonpnp_probe, - .remove = __devexit_p(snd_opti9xx_nonpnp_remove), +static struct isa_driver snd_opti9xx_driver = { + .match = snd_opti9xx_isa_match, + .probe = snd_opti9xx_isa_probe, + .remove = __devexit_p(snd_opti9xx_isa_remove), /* FIXME: suspend/resume */ .driver = { - .name = DRIVER_NAME + .name = DEV_NAME }, }; #ifdef CONFIG_PNP -static int __init snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) +static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, + const struct pnp_card_device_id *pid) { struct snd_card *card; int error, hw; @@ -2074,11 +2084,6 @@ static struct pnp_card_driver opti9xx_pnpc_driver = { }; #endif -#ifdef CONFIG_PNP -#define is_isapnp_selected() isapnp -#else -#define is_isapnp_selected() 0 -#endif #ifdef OPTi93X #define CHIP_NAME "82C93x" #else @@ -2087,42 +2092,19 @@ static struct pnp_card_driver opti9xx_pnpc_driver = { static int __init alsa_card_opti9xx_init(void) { - int error; - struct platform_device *device; - #ifdef CONFIG_PNP pnp_register_card_driver(&opti9xx_pnpc_driver); if (snd_opti9xx_pnp_is_probed) return 0; #endif - if (! is_isapnp_selected()) { - error = platform_driver_register(&snd_opti9xx_driver); - if (error < 0) - return error; - device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); - if (!IS_ERR(device)) { - if (platform_get_drvdata(device)) { - snd_opti9xx_platform_device = device; - return 0; - } - platform_device_unregister(device); - } - platform_driver_unregister(&snd_opti9xx_driver); - } -#ifdef CONFIG_PNP - pnp_unregister_card_driver(&opti9xx_pnpc_driver); -#endif -#ifdef MODULE - printk(KERN_ERR "no OPTi " CHIP_NAME " soundcard found\n"); -#endif - return -ENODEV; + return isa_register_driver(&snd_opti9xx_driver, 1); } static void __exit alsa_card_opti9xx_exit(void) { if (!snd_opti9xx_pnp_is_probed) { - platform_device_unregister(snd_opti9xx_platform_device); - platform_driver_unregister(&snd_opti9xx_driver); + isa_unregister_driver(&snd_opti9xx_driver); + return; } #ifdef CONFIG_PNP pnp_unregister_card_driver(&opti9xx_pnpc_driver); diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index d64e67f2bafa..2a19b0a39eda 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -25,7 +25,7 @@ #include <linux/slab.h> #include <linux/pnp.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/moduleparam.h> #include <sound/core.h> #include <sound/sb.h> @@ -128,7 +128,6 @@ module_param_array(seq_ports, int, NULL, 0444); MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth."); #endif -static struct platform_device *platform_devices[SNDRV_CARDS]; #ifdef CONFIG_PNP static int pnp_registered; #endif @@ -519,7 +518,7 @@ static int snd_sb16_resume(struct snd_card *card) } #endif -static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr) +static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev) { struct snd_card_sb16 *acard; struct snd_card *card; @@ -539,19 +538,23 @@ static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *dev awe_port[dev] = port[dev] + 0x400; #endif - snd_card_set_dev(card, &devptr->dev); + snd_card_set_dev(card, pdev); if ((err = snd_sb16_probe(card, dev)) < 0) { snd_card_free(card); return err; } - platform_set_drvdata(devptr, card); + dev_set_drvdata(pdev, card); return 0; } -static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev) +static int __devinit snd_sb16_isa_match(struct device *pdev, unsigned int dev) +{ + return enable[dev] && !is_isapnp_selected(dev); +} + +static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev) { - int dev = pdev->id; int err; static int possible_irqs[] = {5, 9, 10, 7, -1}; static int possible_dmas8[] = {1, 3, 0, -1}; @@ -577,13 +580,13 @@ static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev) } if (port[dev] != SNDRV_AUTO_PORT) - return snd_sb16_nonpnp_probe1(dev, pdev); + return snd_sb16_isa_probe1(dev, pdev); else { static int possible_ports[] = {0x220, 0x240, 0x260, 0x280}; int i; for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { port[dev] = possible_ports[i]; - err = snd_sb16_nonpnp_probe1(dev, pdev); + err = snd_sb16_isa_probe1(dev, pdev); if (! err) return 0; } @@ -591,47 +594,47 @@ static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev) } } -static int __devexit snd_sb16_nonpnp_remove(struct platform_device *devptr) +static int __devexit snd_sb16_isa_remove(struct device *pdev, unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(pdev)); + dev_set_drvdata(pdev, NULL); return 0; } #ifdef CONFIG_PM -static int snd_sb16_nonpnp_suspend(struct platform_device *dev, pm_message_t state) +static int snd_sb16_isa_suspend(struct device *dev, unsigned int n, + pm_message_t state) { - return snd_sb16_suspend(platform_get_drvdata(dev), state); + return snd_sb16_suspend(dev_get_drvdata(dev), state); } -static int snd_sb16_nonpnp_resume(struct platform_device *dev) +static int snd_sb16_isa_resume(struct device *dev, unsigned int n) { - return snd_sb16_resume(platform_get_drvdata(dev)); + return snd_sb16_resume(dev_get_drvdata(dev)); } #endif #ifdef SNDRV_SBAWE -#define SND_SB16_DRIVER "snd_sbawe" +#define DEV_NAME "sbawe" #else -#define SND_SB16_DRIVER "snd_sb16" +#define DEV_NAME "sb16" #endif -static struct platform_driver snd_sb16_nonpnp_driver = { - .probe = snd_sb16_nonpnp_probe, - .remove = __devexit_p(snd_sb16_nonpnp_remove), +static struct isa_driver snd_sb16_isa_driver = { + .match = snd_sb16_isa_match, + .probe = snd_sb16_isa_probe, + .remove = __devexit_p(snd_sb16_isa_remove), #ifdef CONFIG_PM - .suspend = snd_sb16_nonpnp_suspend, - .resume = snd_sb16_nonpnp_resume, + .suspend = snd_sb16_isa_suspend, + .resume = snd_sb16_isa_resume, #endif .driver = { - .name = SND_SB16_DRIVER + .name = DEV_NAME }, }; #ifdef CONFIG_PNP -static unsigned int __devinitdata sb16_pnp_devices; - static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, const struct pnp_card_device_id *pid) { @@ -653,7 +656,6 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, } pnp_set_card_drvdata(pcard, card); dev++; - sb16_pnp_devices++; return 0; } @@ -695,68 +697,29 @@ static struct pnp_card_driver sb16_pnpc_driver = { #endif /* CONFIG_PNP */ -static void __init_or_module snd_sb16_unregister_all(void) -{ - int i; - -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&sb16_pnpc_driver); -#endif - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&snd_sb16_nonpnp_driver); -} - static int __init alsa_card_sb16_init(void) { - int i, err, cards = 0; + int err; - if ((err = platform_driver_register(&snd_sb16_nonpnp_driver)) < 0) + err = isa_register_driver(&snd_sb16_isa_driver, SNDRV_CARDS); + if (err < 0) return err; - - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i] || is_isapnp_selected(i)) - continue; - device = platform_device_register_simple(SND_SB16_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - cards++; - } #ifdef CONFIG_PNP /* PnP cards at last */ err = pnp_register_card_driver(&sb16_pnpc_driver); - if (!err) { + if (!err) pnp_registered = 1; - cards += sb16_pnp_devices; - } -#endif - - if (!cards) { -#ifdef MODULE - snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n"); -#ifdef SNDRV_SBAWE_EMU8000 - snd_printk(KERN_ERR "In case, if you have non-AWE card, try snd-sb16 module\n"); -#else - snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n"); #endif -#endif - snd_sb16_unregister_all(); - return -ENODEV; - } return 0; } static void __exit alsa_card_sb16_exit(void) { - snd_sb16_unregister_all(); +#ifdef CONFIG_PNP + if (pnp_registered) + pnp_unregister_card_driver(&sb16_pnpc_driver); +#endif + isa_unregister_driver(&snd_sb16_isa_driver); } module_init(alsa_card_sb16_init) diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 3d9d7e0107ca..b279f2308aef 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -36,6 +36,13 @@ MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>"); MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor"); MODULE_LICENSE("GPL"); +#ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL +MODULE_FIRMWARE("sb16/mulaw_main.csp"); +MODULE_FIRMWARE("sb16/alaw_main.csp"); +MODULE_FIRMWARE("sb16/ima_adpcm_init.csp"); +MODULE_FIRMWARE("sb16/ima_adpcm_playback.csp"); +MODULE_FIRMWARE("sb16/ima_adpcm_capture.csp"); +#endif #ifdef SNDRV_LITTLE_ENDIAN #define CSP_HDR_VALUE(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24)) @@ -161,13 +168,17 @@ int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep) */ static void snd_sb_csp_free(struct snd_hwdep *hwdep) { +#ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL int i; +#endif struct snd_sb_csp *p = hwdep->private_data; if (p) { if (p->running & SNDRV_SB_CSP_ST_RUNNING) snd_sb_csp_stop(p); +#ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i) release_firmware(p->csp_programs[i]); +#endif kfree(p); } } @@ -690,9 +701,7 @@ static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __use return err; } -#define FIRMWARE_IN_THE_KERNEL - -#ifdef FIRMWARE_IN_THE_KERNEL +#ifdef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL #include "sb16_csp_codecs.h" static const struct firmware snd_sb_csp_static_programs[] = { @@ -714,22 +723,19 @@ static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags) "sb16/ima_adpcm_capture.csp", }; const struct firmware *program; - int err; BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT); program = p->csp_programs[index]; if (!program) { - err = request_firmware(&program, names[index], - p->chip->card->dev); - if (err >= 0) - p->csp_programs[index] = program; - else { -#ifdef FIRMWARE_IN_THE_KERNEL - program = &snd_sb_csp_static_programs[index]; +#ifdef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL + program = &snd_sb_csp_static_programs[index]; #else + int err = request_firmware(&program, names[index], + p->chip->card->dev); + if (err < 0) return err; #endif - } + p->csp_programs[index] = program; } return snd_sb_csp_load(p, program->data, program->size, flags); } diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index be1e83e6dea3..a1b3786b391e 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -22,7 +22,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/slab.h> #include <linux/ioport.h> #include <linux/moduleparam.h> @@ -56,8 +56,6 @@ MODULE_PARM_DESC(irq, "IRQ # for SB8 driver."); module_param_array(dma8, int, NULL, 0444); MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver."); -static struct platform_device *devices[SNDRV_CARDS]; - struct snd_sb8 { struct resource *fm_res; /* used to block FM i/o region for legacy cards */ struct snd_sb *chip; @@ -83,9 +81,23 @@ static void snd_sb8_free(struct snd_card *card) release_and_free_resource(acard->fm_res); } -static int __devinit snd_sb8_probe(struct platform_device *pdev) +static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev) +{ + if (!enable[dev]) + return 0; + if (irq[dev] == SNDRV_AUTO_IRQ) { + snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id); + return 0; + } + if (dma8[dev] == SNDRV_AUTO_DMA) { + snd_printk(KERN_ERR "%s: please specify dma8\n", pdev->bus_id); + return 0; + } + return 1; +} + +static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev) { - int dev = pdev->id; struct snd_sb *chip; struct snd_card *card; struct snd_sb8 *acard; @@ -180,12 +192,12 @@ static int __devinit snd_sb8_probe(struct platform_device *pdev) chip->port, irq[dev], dma8[dev]); - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, pdev); if ((err = snd_card_register(card)) < 0) goto _err; - platform_set_drvdata(pdev, card); + dev_set_drvdata(pdev, card); return 0; _err: @@ -193,17 +205,18 @@ static int __devinit snd_sb8_probe(struct platform_device *pdev) return err; } -static int __devexit snd_sb8_remove(struct platform_device *pdev) +static int __devexit snd_sb8_remove(struct device *pdev, unsigned int dev) { - snd_card_free(platform_get_drvdata(pdev)); - platform_set_drvdata(pdev, NULL); + snd_card_free(dev_get_drvdata(pdev)); + dev_set_drvdata(pdev, NULL); return 0; } #ifdef CONFIG_PM -static int snd_sb8_suspend(struct platform_device *dev, pm_message_t state) +static int snd_sb8_suspend(struct device *dev, unsigned int n, + pm_message_t state) { - struct snd_card *card = platform_get_drvdata(dev); + struct snd_card *card = dev_get_drvdata(dev); struct snd_sb8 *acard = card->private_data; struct snd_sb *chip = acard->chip; @@ -213,9 +226,9 @@ static int snd_sb8_suspend(struct platform_device *dev, pm_message_t state) return 0; } -static int snd_sb8_resume(struct platform_device *dev) +static int snd_sb8_resume(struct device *dev, unsigned int n) { - struct snd_card *card = platform_get_drvdata(dev); + struct snd_card *card = dev_get_drvdata(dev); struct snd_sb8 *acard = card->private_data; struct snd_sb *chip = acard->chip; @@ -226,9 +239,10 @@ static int snd_sb8_resume(struct platform_device *dev) } #endif -#define SND_SB8_DRIVER "snd_sb8" +#define DEV_NAME "sb8" -static struct platform_driver snd_sb8_driver = { +static struct isa_driver snd_sb8_driver = { + .match = snd_sb8_match, .probe = snd_sb8_probe, .remove = __devexit_p(snd_sb8_remove), #ifdef CONFIG_PM @@ -236,56 +250,18 @@ static struct platform_driver snd_sb8_driver = { .resume = snd_sb8_resume, #endif .driver = { - .name = SND_SB8_DRIVER + .name = DEV_NAME }, }; -static void __init_or_module snd_sb8_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_sb8_driver); -} - static int __init alsa_card_sb8_init(void) { - int i, cards, err; - - err = platform_driver_register(&snd_sb8_driver); - if (err < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_SB8_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - snd_printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n"); -#endif - snd_sb8_unregister_all(); - return -ENODEV; - } - return 0; + return isa_register_driver(&snd_sb8_driver, SNDRV_CARDS); } static void __exit alsa_card_sb8_exit(void) { - snd_sb8_unregister_all(); + isa_unregister_driver(&snd_sb8_driver); } module_init(alsa_card_sb8_init) diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index 4fcd0f4e868c..922519def099 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c @@ -24,7 +24,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/delay.h> #include <linux/time.h> #include <linux/interrupt.h> @@ -64,8 +64,6 @@ MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver."); module_param_array(dma1, int, NULL, 0444); MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver."); -static struct platform_device *devices[SNDRV_CARDS]; - #define SGALAXY_AUXC_LEFT 18 #define SGALAXY_AUXC_RIGHT 19 @@ -96,7 +94,8 @@ static int snd_sgalaxy_sbdsp_reset(unsigned long port) return 0; } -static int __init snd_sgalaxy_sbdsp_command(unsigned long port, unsigned char val) +static int __devinit snd_sgalaxy_sbdsp_command(unsigned long port, + unsigned char val) { int i; @@ -114,7 +113,7 @@ static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id) return IRQ_NONE; } -static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma) +static int __devinit snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma) { static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20, -1, -1, -1, -1}; @@ -161,7 +160,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma) return 0; } -static int __init snd_sgalaxy_detect(int dev, int irq, int dma) +static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma) { #if 0 snd_printdd(PFX "switching to WSS mode\n"); @@ -182,7 +181,7 @@ AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7 AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0) }; -static int __init snd_sgalaxy_mixer(struct snd_ad1848 *chip) +static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip) { struct snd_card *card = chip->card; struct snd_ctl_elem_id id1, id2; @@ -218,23 +217,29 @@ static int __init snd_sgalaxy_mixer(struct snd_ad1848 *chip) return 0; } -static int __init snd_sgalaxy_probe(struct platform_device *devptr) +static int __devinit snd_sgalaxy_match(struct device *devptr, unsigned int dev) { - int dev = devptr->id; - static int possible_irqs[] = {7, 9, 10, 11, -1}; - static int possible_dmas[] = {1, 3, 0, -1}; - int err, xirq, xdma1; - struct snd_card *card; - struct snd_ad1848 *chip; - + if (!enable[dev]) + return 0; if (sbport[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR PFX "specify SB port\n"); - return -EINVAL; + return 0; } if (wssport[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR PFX "specify WSS port\n"); - return -EINVAL; + return 0; } + return 1; +} + +static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) +{ + static int possible_irqs[] = {7, 9, 10, 11, -1}; + static int possible_dmas[] = {1, 3, 0, -1}; + int err, xirq, xdma1; + struct snd_card *card; + struct snd_ad1848 *chip; + card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; @@ -283,12 +288,12 @@ static int __init snd_sgalaxy_probe(struct platform_device *devptr) sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d", wssport[dev], xirq, xdma1); - snd_card_set_dev(card, &devptr->dev); + snd_card_set_dev(card, devptr); if ((err = snd_card_register(card)) < 0) goto _err; - platform_set_drvdata(devptr, card); + dev_set_drvdata(devptr, card); return 0; _err: @@ -296,17 +301,18 @@ static int __init snd_sgalaxy_probe(struct platform_device *devptr) return err; } -static int __devexit snd_sgalaxy_remove(struct platform_device *devptr) +static int __devexit snd_sgalaxy_remove(struct device *devptr, unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } #ifdef CONFIG_PM -static int snd_sgalaxy_suspend(struct platform_device *pdev, pm_message_t state) +static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n, + pm_message_t state) { - struct snd_card *card = platform_get_drvdata(pdev); + struct snd_card *card = dev_get_drvdata(pdev); struct snd_ad1848 *chip = card->private_data; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); @@ -314,9 +320,9 @@ static int snd_sgalaxy_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int snd_sgalaxy_resume(struct platform_device *pdev) +static int snd_sgalaxy_resume(struct device *pdev, unsigned int n) { - struct snd_card *card = platform_get_drvdata(pdev); + struct snd_card *card = dev_get_drvdata(pdev); struct snd_ad1848 *chip = card->private_data; chip->resume(chip); @@ -328,9 +334,10 @@ static int snd_sgalaxy_resume(struct platform_device *pdev) } #endif -#define SND_SGALAXY_DRIVER "snd_sgalaxy" +#define DEV_NAME "sgalaxy" -static struct platform_driver snd_sgalaxy_driver = { +static struct isa_driver snd_sgalaxy_driver = { + .match = snd_sgalaxy_match, .probe = snd_sgalaxy_probe, .remove = __devexit_p(snd_sgalaxy_remove), #ifdef CONFIG_PM @@ -338,56 +345,18 @@ static struct platform_driver snd_sgalaxy_driver = { .resume = snd_sgalaxy_resume, #endif .driver = { - .name = SND_SGALAXY_DRIVER + .name = DEV_NAME }, }; -static void __init_or_module snd_sgalaxy_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_sgalaxy_driver); -} - static int __init alsa_card_sgalaxy_init(void) { - int i, cards, err; - - err = platform_driver_register(&snd_sgalaxy_driver); - if (err < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_SGALAXY_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n"); -#endif - snd_sgalaxy_unregister_all(); - return -ENODEV; - } - return 0; + return isa_register_driver(&snd_sgalaxy_driver, SNDRV_CARDS); } static void __exit alsa_card_sgalaxy_exit(void) { - snd_sgalaxy_unregister_all(); + isa_unregister_driver(&snd_sgalaxy_driver); } module_init(alsa_card_sgalaxy_init) diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index b1f25823c652..08c14978558c 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -24,7 +24,7 @@ #include <sound/driver.h> #include <linux/init.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/delay.h> #include <linux/pnp.h> #include <linux/spinlock.h> @@ -68,8 +68,6 @@ MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver."); module_param_array(dma, int, NULL, 0444); MODULE_PARM_DESC(dma, "DMA # for SoundScape driver."); -static struct platform_device *platform_devices[SNDRV_CARDS]; - #ifdef CONFIG_PNP static int pnp_registered; static struct pnp_card_device_id sscape_pnpids[] = { @@ -1254,9 +1252,27 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) } -static int __devinit snd_sscape_probe(struct platform_device *pdev) +static int __devinit snd_sscape_match(struct device *pdev, unsigned int i) +{ + /* + * Make sure we were given ALL of the other parameters. + */ + if (port[i] == SNDRV_AUTO_PORT) + return 0; + + if (irq[i] == SNDRV_AUTO_IRQ || + mpu_irq[i] == SNDRV_AUTO_IRQ || + dma[i] == SNDRV_AUTO_DMA) { + printk(KERN_INFO + "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n"); + return 0; + } + + return 1; +} + +static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) { - int dev = pdev->id; struct snd_card *card; int ret; @@ -1264,30 +1280,31 @@ static int __devinit snd_sscape_probe(struct platform_device *pdev) ret = create_sscape(dev, &card); if (ret < 0) return ret; - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, pdev); if ((ret = snd_card_register(card)) < 0) { printk(KERN_ERR "sscape: Failed to register sound card\n"); return ret; } - platform_set_drvdata(pdev, card); + dev_set_drvdata(pdev, card); return 0; } -static int __devexit snd_sscape_remove(struct platform_device *devptr) +static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } -#define SSCAPE_DRIVER "snd_sscape" +#define DEV_NAME "sscape" -static struct platform_driver snd_sscape_driver = { +static struct isa_driver snd_sscape_driver = { + .match = snd_sscape_match, .probe = snd_sscape_probe, .remove = __devexit_p(snd_sscape_remove), /* FIXME: suspend/resume */ .driver = { - .name = SSCAPE_DRIVER + .name = DEV_NAME }, }; @@ -1386,72 +1403,6 @@ static struct pnp_card_driver sscape_pnpc_driver = { #endif /* CONFIG_PNP */ -static void __init_or_module sscape_unregister_all(void) -{ - int i; - -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&sscape_pnpc_driver); -#endif - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&snd_sscape_driver); -} - -static int __init sscape_manual_probe(void) -{ - struct platform_device *device; - int i, ret; - - ret = platform_driver_register(&snd_sscape_driver); - if (ret < 0) - return ret; - - for (i = 0; i < SNDRV_CARDS; ++i) { - /* - * We do NOT probe for ports. - * If we're not given a port number for this - * card then we completely ignore this line - * of parameters. - */ - if (port[i] == SNDRV_AUTO_PORT) - continue; - - /* - * Make sure we were given ALL of the other parameters. - */ - if (irq[i] == SNDRV_AUTO_IRQ || - mpu_irq[i] == SNDRV_AUTO_IRQ || - dma[i] == SNDRV_AUTO_DMA) { - printk(KERN_INFO - "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n"); - sscape_unregister_all(); - return -ENXIO; - } - - /* - * This cards looks OK ... - */ - device = platform_device_register_simple(SSCAPE_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - } - return 0; -} - -static void sscape_exit(void) -{ - sscape_unregister_all(); -} - - static int __init sscape_init(void) { int ret; @@ -1462,7 +1413,7 @@ static int __init sscape_init(void) * of allocating cards, because the operator is * S-P-E-L-L-I-N-G it out for us... */ - ret = sscape_manual_probe(); + ret = isa_register_driver(&snd_sscape_driver, SNDRV_CARDS); if (ret < 0) return ret; #ifdef CONFIG_PNP @@ -1472,5 +1423,14 @@ static int __init sscape_init(void) return 0; } +static void __exit sscape_exit(void) +{ +#ifdef CONFIG_PNP + if (pnp_registered) + pnp_unregister_card_driver(&sscape_pnpc_driver); +#endif + isa_unregister_driver(&snd_sscape_driver); +} + module_init(sscape_init); module_exit(sscape_exit); diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index e2fdd5fd39d0..75673f723857 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -24,7 +24,7 @@ #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/err.h> -#include <linux/platform_device.h> +#include <linux/isa.h> #include <linux/pnp.h> #include <linux/moduleparam.h> #include <sound/core.h> @@ -40,7 +40,9 @@ MODULE_SUPPORTED_DEVICE("{{Turtle Beach,Maui/Tropez/Tropez+}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ +#ifdef CONFIG_PNP static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; +#endif static long cs4232_pcm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ static int cs4232_pcm_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ static long cs4232_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ @@ -83,8 +85,6 @@ MODULE_PARM_DESC(fm_port, "FM port #."); module_param_array(use_cs4232_midi, bool, NULL, 0444); MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)"); -static struct platform_device *platform_devices[SNDRV_CARDS]; - #ifdef CONFIG_PNP static int pnp_registered; @@ -588,56 +588,67 @@ snd_wavefront_probe (struct snd_card *card, int dev) return snd_card_register(card); } -static int __devinit snd_wavefront_nonpnp_probe(struct platform_device *pdev) +static int __devinit snd_wavefront_isa_match(struct device *pdev, + unsigned int dev) { - int dev = pdev->id; - struct snd_card *card; - int err; - + if (!enable[dev]) + return 0; +#ifdef CONFIG_PNP + if (isapnp[dev]) + return 0; +#endif if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { snd_printk("specify CS4232 port\n"); - return -EINVAL; + return 0; } if (ics2115_port[dev] == SNDRV_AUTO_PORT) { snd_printk("specify ICS2115 port\n"); - return -ENODEV; + return 0; } + return 1; +} + +static int __devinit snd_wavefront_isa_probe(struct device *pdev, + unsigned int dev) +{ + struct snd_card *card; + int err; card = snd_wavefront_card_new(dev); if (! card) return -ENOMEM; - snd_card_set_dev(card, &pdev->dev); + snd_card_set_dev(card, pdev); if ((err = snd_wavefront_probe(card, dev)) < 0) { snd_card_free(card); return err; } - platform_set_drvdata(pdev, card); + dev_set_drvdata(pdev, card); return 0; } -static int __devexit snd_wavefront_nonpnp_remove(struct platform_device *devptr) +static int __devexit snd_wavefront_isa_remove(struct device *devptr, + unsigned int dev) { - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); + snd_card_free(dev_get_drvdata(devptr)); + dev_set_drvdata(devptr, NULL); return 0; } -#define WAVEFRONT_DRIVER "snd_wavefront" +#define DEV_NAME "wavefront" -static struct platform_driver snd_wavefront_driver = { - .probe = snd_wavefront_nonpnp_probe, - .remove = __devexit_p(snd_wavefront_nonpnp_remove), +static struct isa_driver snd_wavefront_driver = { + .match = snd_wavefront_isa_match, + .probe = snd_wavefront_isa_probe, + .remove = __devexit_p(snd_wavefront_isa_remove), /* FIXME: suspend, resume */ .driver = { - .name = WAVEFRONT_DRIVER + .name = DEV_NAME }, }; #ifdef CONFIG_PNP -static unsigned int __devinitdata wavefront_pnp_devices; - static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, const struct pnp_card_device_id *pid) { @@ -670,7 +681,6 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, pnp_set_card_drvdata(pcard, card); dev++; - wavefront_pnp_devices++; return 0; } @@ -691,67 +701,28 @@ static struct pnp_card_driver wavefront_pnpc_driver = { #endif /* CONFIG_PNP */ -static void __init_or_module snd_wavefront_unregister_all(void) -{ - int i; - -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&wavefront_pnpc_driver); -#endif - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&snd_wavefront_driver); -} - static int __init alsa_card_wavefront_init(void) { - int i, err, cards = 0; + int err; - if ((err = platform_driver_register(&snd_wavefront_driver)) < 0) + err = isa_register_driver(&snd_wavefront_driver, SNDRV_CARDS); + if (err < 0) return err; - - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; -#ifdef CONFIG_PNP - if (isapnp[i]) - continue; -#endif - device = platform_device_register_simple(WAVEFRONT_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - cards++; - } - #ifdef CONFIG_PNP err = pnp_register_card_driver(&wavefront_pnpc_driver); - if (!err) { + if (!err) pnp_registered = 1; - cards += wavefront_pnp_devices; - } -#endif - - if (!cards) { -#ifdef MODULE - printk (KERN_ERR "No WaveFront cards found or devices busy\n"); #endif - snd_wavefront_unregister_all(); - return -ENODEV; - } return 0; } static void __exit alsa_card_wavefront_exit(void) { - snd_wavefront_unregister_all(); +#ifdef CONFIG_PNP + if (pnp_registered) + pnp_unregister_card_driver(&wavefront_pnpc_driver); +#endif + isa_unregister_driver(&snd_wavefront_driver); } module_init(alsa_card_wavefront_init) diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index 15331ed88194..fc95a870f690 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c @@ -35,9 +35,7 @@ #define WAIT_IDLE 0xff -#define FIRMWARE_IN_THE_KERNEL - -#ifdef FIRMWARE_IN_THE_KERNEL +#ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL #include "yss225.c" static const struct firmware yss225_registers_firmware = { .data = (u8 *)yss225_registers, @@ -258,21 +256,21 @@ snd_wavefront_fx_start (snd_wavefront_t *dev) { unsigned int i; int err; - const struct firmware *firmware; + const struct firmware *firmware = NULL; if (dev->fx_initialized) return 0; +#ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL + firmware = &yss225_registers_firmware; +#else err = request_firmware(&firmware, "yamaha/yss225_registers.bin", dev->card->dev); if (err < 0) { -#ifdef FIRMWARE_IN_THE_KERNEL - firmware = &yss225_registers_firmware; -#else err = -1; goto out; -#endif } +#endif for (i = 0; i + 1 < firmware->size; i += 2) { if (firmware->data[i] >= 8 && firmware->data[i] < 16) { @@ -295,9 +293,12 @@ snd_wavefront_fx_start (snd_wavefront_t *dev) err = 0; out: -#ifdef FIRMWARE_IN_THE_KERNEL - if (firmware != &yss225_registers_firmware) +#ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL + release_firmware(firmware); #endif - release_firmware(firmware); return err; } + +#ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL +MODULE_FIRMWARE("yamaha/yss225_registers.bin"); +#endif diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 1bcfb3aac18d..61e35ecc57b8 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -576,7 +576,7 @@ config SND_INTEL8X0M config SND_KORG1212 tristate "Korg 1212 IO" depends on SND - select FW_LOADER + select FW_LOADER if !SND_KORG1212_FIRMWARE_IN_KERNEL select SND_PCM help Say Y here to include support for Korg 1212IO soundcards. @@ -584,10 +584,19 @@ config SND_KORG1212 To compile this driver as a module, choose M here: the module will be called snd-korg1212. +config SND_KORG1212_FIRMWARE_IN_KERNEL + bool "In-kernel firmware for Korg1212 driver" + depends on SND_KORG1212 + default y + help + Say Y here to include the static firmware built in the kernel + for the Korg1212 driver. If you choose N here, you need to + install the firmware files from the alsa-firmware package. + config SND_MAESTRO3 tristate "ESS Allegro/Maestro3" depends on SND - select FW_LOADER + select FW_LOADER if !SND_MAESTRO3_FIRMWARE_IN_KERNEL select SND_AC97_CODEC help Say Y here to include support for soundcards based on ESS Maestro 3 @@ -596,6 +605,15 @@ config SND_MAESTRO3 To compile this driver as a module, choose M here: the module will be called snd-maestro3. +config SND_MAESTRO3_FIRMWARE_IN_KERNEL + bool "In-kernel firmware for Maestro3 driver" + depends on SND_MAESTRO3 + default y + help + Say Y here to include the static firmware built in the kernel + for the Maestro3 driver. If you choose N here, you need to + install the firmware files from the alsa-firmware package. + config SND_MIXART tristate "Digigram miXart" depends on SND @@ -737,7 +755,7 @@ config SND_VX222 config SND_YMFPCI tristate "Yamaha YMF724/740/744/754" depends on SND - select FW_LOADER + select FW_LOADER if !SND_YMFPCI_FIRMWARE_IN_KERNEL select SND_OPL3_LIB select SND_MPU401_UART select SND_AC97_CODEC @@ -748,6 +766,15 @@ config SND_YMFPCI To compile this driver as a module, choose M here: the module will be called snd-ymfpci. +config SND_YMFPCI_FIRMWARE_IN_KERNEL + bool "In-kernel firmware for YMFPCI driver" + depends on SND_YMFPCI + default y + help + Say Y here to include the static firmware built in the kernel + for the YMFPCI driver. If you choose N here, you need to + install the firmware files from the alsa-firmware package. + config SND_AC97_POWER_SAVE bool "AC97 Power-Saving Mode" depends on SND_AC97_CODEC && EXPERIMENTAL diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile index 3c3222122d8b..f5d471896b95 100644 --- a/sound/pci/ac97/Makefile +++ b/sound/pci/ac97/Makefile @@ -3,7 +3,7 @@ # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> # -snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o ac97_patch.o +snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o ifneq ($(CONFIG_PROC_FS),) snd-ac97-codec-objs += ac97_proc.o diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 3bfb2102fc5d..bbed644bf9c5 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -35,9 +35,9 @@ #include <sound/ac97_codec.h> #include <sound/asoundef.h> #include <sound/initval.h> -#include "ac97_local.h" #include "ac97_id.h" -#include "ac97_patch.h" + +#include "ac97_patch.c" MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_DESCRIPTION("Universal interface for Audio Codec '97"); @@ -432,7 +432,8 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns * Controls */ -int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +static int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; @@ -446,7 +447,8 @@ int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem return 0; } -int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; @@ -462,7 +464,8 @@ int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ return 0; } -int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; @@ -508,7 +511,8 @@ static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save) } /* volume and switch controls */ -int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +static int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { int mask = (kcontrol->private_value >> 16) & 0xff; int shift = (kcontrol->private_value >> 8) & 0x0f; @@ -521,7 +525,8 @@ int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info return 0; } -int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; @@ -544,7 +549,8 @@ int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value return 0; } -int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; @@ -646,7 +652,7 @@ AC97_ENUM("Mic Select", std_enum[3]), AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) }; -const struct snd_kcontrol_new snd_ac97_controls_3d[2] = { +static const struct snd_kcontrol_new snd_ac97_controls_3d[2] = { AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0), AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0) }; @@ -817,7 +823,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ return change; } -const struct snd_kcontrol_new snd_ac97_controls_spdif[5] = { +static const struct snd_kcontrol_new snd_ac97_controls_spdif[5] = { { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1097,7 +1103,7 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha } } -int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit) +static int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit) { unsigned short mask, val, orig, res; @@ -1137,7 +1143,8 @@ static inline int printable(unsigned int x) return x; } -struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, struct snd_ac97 * ac97) +static struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, + struct snd_ac97 * ac97) { struct snd_kcontrol_new template; memcpy(&template, _template, sizeof(template)); @@ -2544,7 +2551,8 @@ static void set_ctl_name(char *dst, const char *src, const char *suffix) } /* remove the control with the given name and optional suffix */ -int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, const char *suffix) +static int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, + const char *suffix) { struct snd_ctl_elem_id id; memset(&id, 0, sizeof(id)); @@ -2563,7 +2571,8 @@ static struct snd_kcontrol *ctl_find(struct snd_ac97 *ac97, const char *name, co } /* rename the control with the given name and optional suffix */ -int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst, const char *suffix) +static int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, + const char *dst, const char *suffix) { struct snd_kcontrol *kctl = ctl_find(ac97, src, suffix); if (kctl) { @@ -2574,14 +2583,16 @@ int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst, } /* rename both Volume and Switch controls - don't check the return value */ -void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, const char *dst) +static void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, + const char *dst) { snd_ac97_rename_ctl(ac97, src, dst, "Switch"); snd_ac97_rename_ctl(ac97, src, dst, "Volume"); } /* swap controls */ -int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, const char *s2, const char *suffix) +static int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, + const char *s2, const char *suffix) { struct snd_kcontrol *kctl1, *kctl2; kctl1 = ctl_find(ac97, s1, suffix); diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h index a6244c720a1d..78745c5c6df8 100644 --- a/sound/pci/ac97/ac97_local.h +++ b/sound/pci/ac97/ac97_local.h @@ -22,59 +22,8 @@ * */ -#define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | ((invert) << 24)) -#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | (1<<25) | ((page) << 26)) -#define AC97_SINGLE(xname, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \ - .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ - .private_value = AC97_SINGLE_VALUE(reg, shift, mask, invert) } -#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \ - .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ - .private_value = AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) } -#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_volsw, \ - .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ - .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) } - -/* enum control */ -struct ac97_enum { - unsigned char reg; - unsigned char shift_l; - unsigned char shift_r; - unsigned short mask; - const char **texts; -}; - -#define AC97_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \ -{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .mask = xmask, .texts = xtexts } -#define AC97_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \ - AC97_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts) -#define AC97_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \ - .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \ - .private_value = (unsigned long)&xenum } - -/* ac97_codec.c */ -extern const struct snd_kcontrol_new snd_ac97_controls_3d[]; -extern const struct snd_kcontrol_new snd_ac97_controls_spdif[]; -struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, struct snd_ac97 * ac97); -void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int modem); -int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); -int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit); -int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, const char *suffix); -int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst, const char *suffix); -int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, const char *s2, const char *suffix); -void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, const char *dst); -void snd_ac97_restore_status(struct snd_ac97 *ac97); -void snd_ac97_restore_iec958(struct snd_ac97 *ac97); -int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); -int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); - +void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, + int modem); int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value); diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index b188a4df58cb..3eac0f86266c 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -23,20 +23,8 @@ * */ -#include <sound/driver.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/mutex.h> - -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/control.h> -#include <sound/tlv.h> -#include <sound/ac97_codec.h> -#include "ac97_patch.h" -#include "ac97_id.h" #include "ac97_local.h" +#include "ac97_patch.h" /* * Chip specific initialization @@ -390,7 +378,7 @@ static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = { .build_post_spdif = patch_yamaha_ymf753_post_spdif }; -int patch_yamaha_ymf753(struct snd_ac97 * ac97) +static int patch_yamaha_ymf753(struct snd_ac97 * ac97) { /* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com. This chip has nonstandard and extended behaviour with regard to its S/PDIF output. @@ -436,7 +424,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9703_ops = { .build_specific = patch_wolfson_wm9703_specific, }; -int patch_wolfson03(struct snd_ac97 * ac97) +static int patch_wolfson03(struct snd_ac97 * ac97) { ac97->build_ops = &patch_wolfson_wm9703_ops; return 0; @@ -467,7 +455,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9704_ops = { .build_specific = patch_wolfson_wm9704_specific, }; -int patch_wolfson04(struct snd_ac97 * ac97) +static int patch_wolfson04(struct snd_ac97 * ac97) { /* WM9704M/9704Q */ ac97->build_ops = &patch_wolfson_wm9704_ops; @@ -489,7 +477,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9705_ops = { .build_specific = patch_wolfson_wm9705_specific, }; -int patch_wolfson05(struct snd_ac97 * ac97) +static int patch_wolfson05(struct snd_ac97 * ac97) { /* WM9705, WM9710 */ ac97->build_ops = &patch_wolfson_wm9705_ops; @@ -625,7 +613,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9711_ops = { .build_specific = patch_wolfson_wm9711_specific, }; -int patch_wolfson11(struct snd_ac97 * ac97) +static int patch_wolfson11(struct snd_ac97 * ac97) { /* WM9711, WM9712 */ ac97->build_ops = &patch_wolfson_wm9711_ops; @@ -824,7 +812,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = { #endif }; -int patch_wolfson13(struct snd_ac97 * ac97) +static int patch_wolfson13(struct snd_ac97 * ac97) { /* WM9713, WM9714 */ ac97->build_ops = &patch_wolfson_wm9713_ops; @@ -844,7 +832,7 @@ int patch_wolfson13(struct snd_ac97 * ac97) /* * Tritech codec */ -int patch_tritech_tr28028(struct snd_ac97 * ac97) +static int patch_tritech_tr28028(struct snd_ac97 * ac97) { snd_ac97_write_cache(ac97, 0x26, 0x0300); snd_ac97_write_cache(ac97, 0x26, 0x0000); @@ -922,7 +910,7 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = { .build_specific = patch_sigmatel_stac97xx_specific }; -int patch_sigmatel_stac9700(struct snd_ac97 * ac97) +static int patch_sigmatel_stac9700(struct snd_ac97 * ac97) { ac97->build_ops = &patch_sigmatel_stac9700_ops; return 0; @@ -969,7 +957,7 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = { .build_specific = patch_sigmatel_stac9708_specific }; -int patch_sigmatel_stac9708(struct snd_ac97 * ac97) +static int patch_sigmatel_stac9708(struct snd_ac97 * ac97) { unsigned int codec72, codec6c; @@ -995,7 +983,7 @@ int patch_sigmatel_stac9708(struct snd_ac97 * ac97) return 0; } -int patch_sigmatel_stac9721(struct snd_ac97 * ac97) +static int patch_sigmatel_stac9721(struct snd_ac97 * ac97) { ac97->build_ops = &patch_sigmatel_stac9700_ops; if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) { @@ -1009,7 +997,7 @@ int patch_sigmatel_stac9721(struct snd_ac97 * ac97) return 0; } -int patch_sigmatel_stac9744(struct snd_ac97 * ac97) +static int patch_sigmatel_stac9744(struct snd_ac97 * ac97) { // patch for SigmaTel ac97->build_ops = &patch_sigmatel_stac9700_ops; @@ -1021,7 +1009,7 @@ int patch_sigmatel_stac9744(struct snd_ac97 * ac97) return 0; } -int patch_sigmatel_stac9756(struct snd_ac97 * ac97) +static int patch_sigmatel_stac9756(struct snd_ac97 * ac97) { // patch for SigmaTel ac97->build_ops = &patch_sigmatel_stac9700_ops; @@ -1198,7 +1186,7 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = { .build_specific = patch_sigmatel_stac9758_specific }; -int patch_sigmatel_stac9758(struct snd_ac97 * ac97) +static int patch_sigmatel_stac9758(struct snd_ac97 * ac97) { static unsigned short regs[4] = { AC97_SIGMATEL_OUTSEL, @@ -1272,7 +1260,7 @@ static struct snd_ac97_build_ops patch_cirrus_ops = { .build_spdif = patch_cirrus_build_spdif }; -int patch_cirrus_spdif(struct snd_ac97 * ac97) +static int patch_cirrus_spdif(struct snd_ac97 * ac97) { /* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers. WHY CAN'T ANYONE FOLLOW THE BLOODY SPEC? *sigh* @@ -1293,7 +1281,7 @@ int patch_cirrus_spdif(struct snd_ac97 * ac97) return 0; } -int patch_cirrus_cs4299(struct snd_ac97 * ac97) +static int patch_cirrus_cs4299(struct snd_ac97 * ac97) { /* force the detection of PC Beep */ ac97->flags |= AC97_HAS_PC_BEEP; @@ -1329,7 +1317,7 @@ static struct snd_ac97_build_ops patch_conexant_ops = { .build_spdif = patch_conexant_build_spdif }; -int patch_conexant(struct snd_ac97 * ac97) +static int patch_conexant(struct snd_ac97 * ac97) { ac97->build_ops = &patch_conexant_ops; ac97->flags |= AC97_CX_SPDIF; @@ -1338,7 +1326,7 @@ int patch_conexant(struct snd_ac97 * ac97) return 0; } -int patch_cx20551(struct snd_ac97 *ac97) +static int patch_cx20551(struct snd_ac97 *ac97) { snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01); return 0; @@ -1430,7 +1418,7 @@ static const struct snd_ac97_res_table ad1819_restbl[] = { { } /* terminator */ }; -int patch_ad1819(struct snd_ac97 * ac97) +static int patch_ad1819(struct snd_ac97 * ac97) { unsigned short scfg; @@ -1507,7 +1495,7 @@ static struct snd_ac97_build_ops patch_ad1881_build_ops = { #endif }; -int patch_ad1881(struct snd_ac97 * ac97) +static int patch_ad1881(struct snd_ac97 * ac97) { static const char cfg_idxs[3][2] = { {2, 1}, @@ -1595,7 +1583,7 @@ static struct snd_ac97_build_ops patch_ad1885_build_ops = { #endif }; -int patch_ad1885(struct snd_ac97 * ac97) +static int patch_ad1885(struct snd_ac97 * ac97) { patch_ad1881(ac97); /* This is required to deal with the Intel D815EEAL2 */ @@ -1622,7 +1610,7 @@ static struct snd_ac97_build_ops patch_ad1886_build_ops = { #endif }; -int patch_ad1886(struct snd_ac97 * ac97) +static int patch_ad1886(struct snd_ac97 * ac97) { patch_ad1881(ac97); /* Presario700 workaround */ @@ -1844,7 +1832,7 @@ static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97) snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11); } -int patch_ad1981a(struct snd_ac97 *ac97) +static int patch_ad1981a(struct snd_ac97 *ac97) { patch_ad1881(ac97); ac97->build_ops = &patch_ad1981a_build_ops; @@ -1877,7 +1865,7 @@ static struct snd_ac97_build_ops patch_ad1981b_build_ops = { #endif }; -int patch_ad1981b(struct snd_ac97 *ac97) +static int patch_ad1981b(struct snd_ac97 *ac97) { patch_ad1881(ac97); ac97->build_ops = &patch_ad1981b_build_ops; @@ -2014,7 +2002,7 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = { .update_jacks = ad1888_update_jacks, }; -int patch_ad1888(struct snd_ac97 * ac97) +static int patch_ad1888(struct snd_ac97 * ac97) { unsigned short misc; @@ -2052,7 +2040,7 @@ static struct snd_ac97_build_ops patch_ad1980_build_ops = { .update_jacks = ad1888_update_jacks, }; -int patch_ad1980(struct snd_ac97 * ac97) +static int patch_ad1980(struct snd_ac97 * ac97) { patch_ad1888(ac97); ac97->build_ops = &patch_ad1980_build_ops; @@ -2168,7 +2156,7 @@ static struct snd_ac97_build_ops patch_ad1985_build_ops = { .update_jacks = ad1985_update_jacks, }; -int patch_ad1985(struct snd_ac97 * ac97) +static int patch_ad1985(struct snd_ac97 * ac97) { unsigned short misc; @@ -2468,7 +2456,7 @@ static struct snd_ac97_build_ops patch_ad1986_build_ops = { .update_jacks = ad1986_update_jacks, }; -int patch_ad1986(struct snd_ac97 * ac97) +static int patch_ad1986(struct snd_ac97 * ac97) { patch_ad1881(ac97); ac97->build_ops = &patch_ad1986_build_ops; @@ -2561,7 +2549,7 @@ static struct snd_ac97_build_ops patch_alc650_ops = { .update_jacks = alc650_update_jacks }; -int patch_alc650(struct snd_ac97 * ac97) +static int patch_alc650(struct snd_ac97 * ac97) { unsigned short val; @@ -2713,7 +2701,7 @@ static struct snd_ac97_build_ops patch_alc655_ops = { .update_jacks = alc655_update_jacks }; -int patch_alc655(struct snd_ac97 * ac97) +static int patch_alc655(struct snd_ac97 * ac97) { unsigned int val; @@ -2739,6 +2727,7 @@ int patch_alc655(struct snd_ac97 * ac97) (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */ ac97->subsystem_device == 0x0161 || /* LG K1 Express */ ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */ + ac97->subsystem_device == 0x0471 || /* MSI L720 laptop */ ac97->subsystem_device == 0x0061)) /* MSI S250 laptop */ val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ else @@ -2815,7 +2804,7 @@ static struct snd_ac97_build_ops patch_alc850_ops = { .update_jacks = alc850_update_jacks }; -int patch_alc850(struct snd_ac97 *ac97) +static int patch_alc850(struct snd_ac97 *ac97) { ac97->build_ops = &patch_alc850_ops; @@ -2875,7 +2864,7 @@ static struct snd_ac97_build_ops patch_cm9738_ops = { .update_jacks = cm9738_update_jacks }; -int patch_cm9738(struct snd_ac97 * ac97) +static int patch_cm9738(struct snd_ac97 * ac97) { ac97->build_ops = &patch_cm9738_ops; /* FIXME: can anyone confirm below? */ @@ -2967,7 +2956,7 @@ static struct snd_ac97_build_ops patch_cm9739_ops = { .update_jacks = cm9739_update_jacks }; -int patch_cm9739(struct snd_ac97 * ac97) +static int patch_cm9739(struct snd_ac97 * ac97) { unsigned short val; @@ -3141,7 +3130,7 @@ static struct snd_ac97_build_ops patch_cm9761_ops = { .update_jacks = cm9761_update_jacks }; -int patch_cm9761(struct snd_ac97 *ac97) +static int patch_cm9761(struct snd_ac97 *ac97) { unsigned short val; @@ -3236,7 +3225,7 @@ static struct snd_ac97_build_ops patch_cm9780_ops = { .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */ }; -int patch_cm9780(struct snd_ac97 *ac97) +static int patch_cm9780(struct snd_ac97 *ac97) { unsigned short val; @@ -3279,7 +3268,7 @@ static struct snd_ac97_build_ops patch_vt1616_ops = { .build_specific = patch_vt1616_specific }; -int patch_vt1616(struct snd_ac97 * ac97) +static int patch_vt1616(struct snd_ac97 * ac97) { ac97->build_ops = &patch_vt1616_ops; return 0; @@ -3288,16 +3277,111 @@ int patch_vt1616(struct snd_ac97 * ac97) /* * VT1617A codec */ + +/* + * unfortunately, the vt1617a stashes the twiddlers required for + * nooding the i/o jacks on 2 different regs. * thameans that we cant + * use the easy way provided by AC97_ENUM_DOUBLE() we have to write + * are own funcs. + * + * NB: this is absolutely and utterly different from the vt1618. dunno + * about the 1616. + */ + +/* copied from ac97_surround_jack_mode_info() */ +static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + /* ordering in this list reflects vt1617a docs for Reg 20 and + * 7a and Table 6 that lays out the matrix NB WRT Table6: SM51 + * is SM51EN *AND* it's Bit14, not Bit15 so the table is very + * counter-intuitive */ + + static const char* texts[] = { "LineIn Mic1", "LineIn Mic1 Mic3", + "Surr LFE/C Mic3", "LineIn LFE/C Mic3", + "LineIn Mic2", "LineIn Mic2 Mic1", + "Surr LFE Mic1", "Surr LFE Mic1 Mic2"}; + return ac97_enum_text_info(kcontrol, uinfo, texts, 8); +} + +static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ushort usSM51, usMS; + + struct snd_ac97 *pac97; + + pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ + + /* grab our desirec bits, then mash them together in a manner + * consistent with Table 6 on page 17 in the 1617a docs */ + + usSM51 = snd_ac97_read(pac97, 0x7a) >> 14; + usMS = snd_ac97_read(pac97, 0x20) >> 8; + + ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS; + + return 0; +} + +static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ushort usSM51, usMS, usReg; + + struct snd_ac97 *pac97; + + pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ + + usSM51 = ucontrol->value.enumerated.item[0] >> 1; + usMS = ucontrol->value.enumerated.item[0] & 1; + + /* push our values into the register - consider that things will be left + * in a funky state if the write fails */ + + usReg = snd_ac97_read(pac97, 0x7a); + snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14)); + usReg = snd_ac97_read(pac97, 0x20); + snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS << 8)); + + return 0; +} + +static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = { + + AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0), + /* + * These are used to enable/disable surround sound on motherboards + * that have 3 bidirectional analog jacks + */ + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Smart 5.1 Select", + .info = snd_ac97_vt1617a_smart51_info, + .get = snd_ac97_vt1617a_smart51_get, + .put = snd_ac97_vt1617a_smart51_put, + }, +}; + int patch_vt1617a(struct snd_ac97 * ac97) { - /* bring analog power consumption to normal, like WinXP driver - * for EPIA SP + int err = 0; + + /* we choose to not fail out at this point, but we tell the + caller when we return */ + + err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0], + ARRAY_SIZE(snd_ac97_controls_vt1617a)); + + /* bring analog power consumption to normal by turning off the + * headphone amplifier, like WinXP driver for EPIA SP */ snd_ac97_write_cache(ac97, 0x5c, 0x20); ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; ac97->build_ops = &patch_vt1616_ops; - return 0; + + return err; } /* @@ -3338,7 +3422,7 @@ static struct snd_ac97_build_ops patch_it2646_ops = { .update_jacks = it2646_update_jacks }; -int patch_it2646(struct snd_ac97 * ac97) +static int patch_it2646(struct snd_ac97 * ac97) { ac97->build_ops = &patch_it2646_ops; /* full DAC volume */ @@ -3371,7 +3455,7 @@ static struct snd_ac97_build_ops patch_si3036_ops = { .build_specific = patch_si3036_specific, }; -int mpatch_si3036(struct snd_ac97 * ac97) +static int mpatch_si3036(struct snd_ac97 * ac97) { ac97->build_ops = &patch_si3036_ops; snd_ac97_write_cache(ac97, 0x5c, 0xf210 ); @@ -3403,7 +3487,7 @@ static struct snd_ac97_res_table lm4550_restbl[] = { { } /* terminator */ }; -int patch_lm4550(struct snd_ac97 *ac97) +static int patch_lm4550(struct snd_ac97 *ac97) { ac97->res_table = lm4550_restbl; return 0; @@ -3438,7 +3522,7 @@ static struct snd_ac97_build_ops patch_ucb1400_ops = { .build_specific = patch_ucb1400_specific, }; -int patch_ucb1400(struct snd_ac97 * ac97) +static int patch_ucb1400(struct snd_ac97 * ac97) { ac97->build_ops = &patch_ucb1400_ops; /* enable headphone driver and smart low power mode by default */ diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h index 555d1c9a98fd..fd341ce63762 100644 --- a/sound/pci/ac97/ac97_patch.h +++ b/sound/pci/ac97/ac97_patch.h @@ -22,44 +22,72 @@ * */ -int patch_yamaha_ymf753(struct snd_ac97 * ac97); -int patch_wolfson00(struct snd_ac97 * ac97); -int patch_wolfson03(struct snd_ac97 * ac97); -int patch_wolfson04(struct snd_ac97 * ac97); -int patch_wolfson05(struct snd_ac97 * ac97); -int patch_wolfson11(struct snd_ac97 * ac97); -int patch_wolfson13(struct snd_ac97 * ac97); -int patch_tritech_tr28028(struct snd_ac97 * ac97); -int patch_sigmatel_stac9700(struct snd_ac97 * ac97); -int patch_sigmatel_stac9708(struct snd_ac97 * ac97); -int patch_sigmatel_stac9721(struct snd_ac97 * ac97); -int patch_sigmatel_stac9744(struct snd_ac97 * ac97); -int patch_sigmatel_stac9756(struct snd_ac97 * ac97); -int patch_sigmatel_stac9758(struct snd_ac97 * ac97); -int patch_cirrus_cs4299(struct snd_ac97 * ac97); -int patch_cirrus_spdif(struct snd_ac97 * ac97); -int patch_conexant(struct snd_ac97 * ac97); -int patch_cx20551(struct snd_ac97 * ac97); -int patch_ad1819(struct snd_ac97 * ac97); -int patch_ad1881(struct snd_ac97 * ac97); -int patch_ad1885(struct snd_ac97 * ac97); -int patch_ad1886(struct snd_ac97 * ac97); -int patch_ad1888(struct snd_ac97 * ac97); -int patch_ad1980(struct snd_ac97 * ac97); -int patch_ad1981a(struct snd_ac97 * ac97); -int patch_ad1981b(struct snd_ac97 * ac97); -int patch_ad1985(struct snd_ac97 * ac97); -int patch_ad1986(struct snd_ac97 * ac97); -int patch_alc650(struct snd_ac97 * ac97); -int patch_alc655(struct snd_ac97 * ac97); -int patch_alc850(struct snd_ac97 * ac97); -int patch_cm9738(struct snd_ac97 * ac97); -int patch_cm9739(struct snd_ac97 * ac97); -int patch_cm9761(struct snd_ac97 * ac97); -int patch_cm9780(struct snd_ac97 * ac97); -int patch_vt1616(struct snd_ac97 * ac97); -int patch_vt1617a(struct snd_ac97 * ac97); -int patch_it2646(struct snd_ac97 * ac97); -int patch_ucb1400(struct snd_ac97 * ac97); -int mpatch_si3036(struct snd_ac97 * ac97); -int patch_lm4550(struct snd_ac97 * ac97); +#define AC97_SINGLE_VALUE(reg,shift,mask,invert) \ + ((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | \ + ((invert) << 24)) +#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) \ + (AC97_SINGLE_VALUE(reg,shift,mask,invert) | (1<<25) | ((page) << 26)) +#define AC97_SINGLE(xname, reg, shift, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_ac97_info_volsw, \ + .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ + .private_value = AC97_SINGLE_VALUE(reg, shift, mask, invert) } +#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_ac97_info_volsw, \ + .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ + .private_value = AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) } +#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = snd_ac97_info_volsw, \ + .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ + .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) } + +/* enum control */ +struct ac97_enum { + unsigned char reg; + unsigned char shift_l; + unsigned char shift_r; + unsigned short mask; + const char **texts; +}; + +#define AC97_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \ +{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ + .mask = xmask, .texts = xtexts } +#define AC97_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \ + AC97_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts) +#define AC97_ENUM(xname, xenum) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_ac97_info_enum_double, \ + .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \ + .private_value = (unsigned long)&xenum } + +/* ac97_codec.c */ +static const struct snd_kcontrol_new snd_ac97_controls_3d[]; +static const struct snd_kcontrol_new snd_ac97_controls_spdif[]; +static struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, + struct snd_ac97 * ac97); +static int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +static int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit); +static int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, + const char *suffix); +static int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, + const char *dst, const char *suffix); +static int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, + const char *s2, const char *suffix); +static void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, + const char *dst); +static void snd_ac97_restore_status(struct snd_ac97 *ac97); +static void snd_ac97_restore_iec958(struct snd_ac97 *ac97); +static int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +static int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +static int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index 3758d07182f8..4281e6d0c5b6 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c @@ -34,7 +34,6 @@ #include <sound/control.h> #include <sound/ac97_codec.h> #include <sound/asoundef.h> -#include "ac97_patch.h" #include "ac97_id.h" #include "ac97_local.h" diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index ba7fa22b285d..e1ed59549c50 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -69,10 +69,10 @@ module_param(enable, bool, 0444); * Debug part definitions */ -//#define ALI_DEBUG +/* #define ALI_DEBUG */ #ifdef ALI_DEBUG -#define snd_ali_printk(format, args...) printk(format, ##args); +#define snd_ali_printk(format, args...) printk(KERN_DEBUG format, ##args); #else #define snd_ali_printk(format, args...) #endif @@ -105,10 +105,10 @@ module_param(enable, bool, 0444); * Direct Registers */ -#define ALI_LEGACY_DMAR0 0x00 // ADR0 -#define ALI_LEGACY_DMAR4 0x04 // CNT0 -#define ALI_LEGACY_DMAR11 0x0b // MOD -#define ALI_LEGACY_DMAR15 0x0f // MMR +#define ALI_LEGACY_DMAR0 0x00 /* ADR0 */ +#define ALI_LEGACY_DMAR4 0x04 /* CNT0 */ +#define ALI_LEGACY_DMAR11 0x0b /* MOD */ +#define ALI_LEGACY_DMAR15 0x0f /* MMR */ #define ALI_MPUR0 0x20 #define ALI_MPUR1 0x21 #define ALI_MPUR2 0x22 @@ -175,7 +175,7 @@ struct snd_ali; struct snd_ali_voice; struct snd_ali_channel_control { - // register data + /* register data */ struct REGDATA { unsigned int start; unsigned int stop; @@ -183,7 +183,7 @@ struct snd_ali_channel_control { unsigned int ainten; } data; - // register addresses + /* register addresses */ struct REGS { unsigned int start; unsigned int stop; @@ -197,19 +197,18 @@ struct snd_ali_channel_control { struct snd_ali_voice { unsigned int number; - unsigned int use: 1, - pcm: 1, - midi: 1, - mode: 1, - synth: 1; + unsigned int use :1, + pcm :1, + midi :1, + mode :1, + synth :1, + running :1; /* PCM data */ struct snd_ali *codec; struct snd_pcm_substream *substream; struct snd_ali_voice *extra; - unsigned int running: 1; - int eso; /* final ESO value for channel */ int count; /* runtime->period_size */ @@ -231,14 +230,12 @@ struct snd_alidev { }; -#ifdef CONFIG_PM #define ALI_GLOBAL_REGS 56 #define ALI_CHANNEL_REGS 8 struct snd_ali_image { - unsigned long regs[ALI_GLOBAL_REGS]; - unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS]; + u32 regs[ALI_GLOBAL_REGS]; + u32 channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS]; }; -#endif struct snd_ali { @@ -246,8 +243,8 @@ struct snd_ali { unsigned long port; unsigned char revision; - unsigned int hw_initialized: 1; - unsigned int spdif_support: 1; + unsigned int hw_initialized :1; + unsigned int spdif_support :1; struct pci_dev *pci; struct pci_dev *pci_m1533; @@ -287,108 +284,28 @@ MODULE_DEVICE_TABLE(pci, snd_ali_ids); static void snd_ali_clear_voices(struct snd_ali *, unsigned int, unsigned int); static unsigned short snd_ali_codec_peek(struct snd_ali *, int, unsigned short); -static void snd_ali_codec_poke(struct snd_ali *, int, unsigned short, unsigned short); - -/* - * Debug Part - */ - -#ifdef ALI_DEBUG - -static void ali_read_regs(struct snd_ali *codec, int channel) -{ - int i,j; - unsigned int dwVal; - - printk("channel %d registers map:\n", channel); - outb((unsigned char)(channel & 0x001f), ALI_REG(codec,ALI_GC_CIR)); - - printk(" "); - for(j=0;j<8;j++) - printk("%2.2x ", j*4); - printk("\n"); - - for (i=0; i<=0xf8/4;i++) { - if(i%8 == 0) - printk("%2.2x ", (i*4/0x10)*0x10); - dwVal = inl(ALI_REG(codec,i*4)); - printk("%8.8x ", dwVal); - if ((i+1)%8 == 0) - printk("\n"); - } - printk("\n"); -} -static void ali_read_cfg(unsigned int vendor, unsigned deviceid) -{ - unsigned int dwVal; - struct pci_dev *pci_dev; - int i,j; - - pci_dev = pci_get_device(vendor, deviceid, NULL); - if (pci_dev == NULL) - return ; - - printk("\nM%x PCI CFG\n", deviceid); - printk(" "); - for(j=0;j<8;j++) - printk("%d ",j); - printk("\n"); - - for(i=0;i<8;i++) { - printk("%d ",i); - for(j=0;j<8;j++) - { - pci_read_config_dword(pci_dev, i*0x20+j*4, &dwVal); - printk("%8.8x ", dwVal); - } - printk("\n"); - } - pci_dev_put(pci_dev); - } -static void ali_read_ac97regs(struct snd_ali *codec, int secondary) -{ - unsigned short i,j; - unsigned short wVal; - - printk("\ncodec %d registers map:\n", secondary); - - printk(" "); - for(j=0;j<8;j++) - printk("%2.2x ",j*2); - printk("\n"); - - for (i=0; i<64;i++) { - if(i%8 == 0) - printk("%2.2x ", (i/8)*0x10); - wVal = snd_ali_codec_peek(codec, secondary, i*2); - printk("%4.4x ", wVal); - if ((i+1)%8 == 0) - printk("\n"); - } - printk("\n"); -} - -#endif +static void snd_ali_codec_poke(struct snd_ali *, int, unsigned short, + unsigned short); /* * AC97 ACCESS */ static inline unsigned int snd_ali_5451_peek(struct snd_ali *codec, - unsigned int port ) + unsigned int port) { return (unsigned int)inl(ALI_REG(codec, port)); } -static inline void snd_ali_5451_poke( struct snd_ali *codec, - unsigned int port, - unsigned int val ) +static inline void snd_ali_5451_poke(struct snd_ali *codec, + unsigned int port, + unsigned int val) { outl((unsigned int)val, ALI_REG(codec, port)); } -static int snd_ali_codec_ready( struct snd_ali *codec, - unsigned int port ) +static int snd_ali_codec_ready(struct snd_ali *codec, + unsigned int port) { unsigned long end_time; unsigned int res; @@ -396,7 +313,7 @@ static int snd_ali_codec_ready( struct snd_ali *codec, end_time = jiffies + msecs_to_jiffies(250); do { res = snd_ali_5451_peek(codec,port); - if (! (res & 0x8000)) + if (!(res & 0x8000)) return 0; schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); @@ -425,11 +342,11 @@ static int snd_ali_stimer_ready(struct snd_ali *codec) } static void snd_ali_codec_poke(struct snd_ali *codec,int secondary, - unsigned short reg, - unsigned short val) + unsigned short reg, + unsigned short val) { - unsigned int dwVal = 0; - unsigned int port = 0; + unsigned int dwVal; + unsigned int port; if (reg >= 0x80) { snd_printk(KERN_ERR "ali_codec_poke: reg(%xh) invalid.\n", reg); @@ -445,20 +362,22 @@ static void snd_ali_codec_poke(struct snd_ali *codec,int secondary, dwVal = (unsigned int) (reg & 0xff); dwVal |= 0x8000 | (val << 16); - if (secondary) dwVal |= 0x0080; - if (codec->revision == ALI_5451_V02) dwVal |= 0x0100; + if (secondary) + dwVal |= 0x0080; + if (codec->revision == ALI_5451_V02) + dwVal |= 0x0100; - snd_ali_5451_poke(codec,port,dwVal); + snd_ali_5451_poke(codec, port, dwVal); return ; } -static unsigned short snd_ali_codec_peek( struct snd_ali *codec, - int secondary, - unsigned short reg) +static unsigned short snd_ali_codec_peek(struct snd_ali *codec, + int secondary, + unsigned short reg) { - unsigned int dwVal = 0; - unsigned int port = 0; + unsigned int dwVal; + unsigned int port; if (reg >= 0x80) { snd_printk(KERN_ERR "ali_codec_peek: reg(%xh) invalid.\n", reg); @@ -474,7 +393,8 @@ static unsigned short snd_ali_codec_peek( struct snd_ali *codec, dwVal = (unsigned int) (reg & 0xff); dwVal |= 0x8000; /* bit 15*/ - if (secondary) dwVal |= 0x0080; + if (secondary) + dwVal |= 0x0080; snd_ali_5451_poke(codec, port, dwVal); @@ -483,7 +403,7 @@ static unsigned short snd_ali_codec_peek( struct snd_ali *codec, if (snd_ali_codec_ready(codec, port) < 0) return ~0; - return (snd_ali_5451_peek(codec, port) & 0xffff0000)>>16; + return (snd_ali_5451_peek(codec, port) & 0xffff0000) >> 16; } static void snd_ali_codec_write(struct snd_ac97 *ac97, @@ -493,9 +413,9 @@ static void snd_ali_codec_write(struct snd_ac97 *ac97, struct snd_ali *codec = ac97->private_data; snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val); - if(reg == AC97_GPIO_STATUS) { - outl((val << ALI_AC97_GPIO_DATA_SHIFT)|ALI_AC97_GPIO_ENABLE, - ALI_REG(codec, ALI_AC97_GPIO)); + if (reg == AC97_GPIO_STATUS) { + outl((val << ALI_AC97_GPIO_DATA_SHIFT) | ALI_AC97_GPIO_ENABLE, + ALI_REG(codec, ALI_AC97_GPIO)); return; } snd_ali_codec_poke(codec, ac97->num, reg, val); @@ -503,12 +423,13 @@ static void snd_ali_codec_write(struct snd_ac97 *ac97, } -static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97, unsigned short reg) +static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97, + unsigned short reg) { struct snd_ali *codec = ac97->private_data; snd_ali_printk("codec_read reg=%xh.\n", reg); - return (snd_ali_codec_peek(codec, ac97->num, reg)); + return snd_ali_codec_peek(codec, ac97->num, reg); } /* @@ -517,11 +438,12 @@ static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97, unsigned short r static int snd_ali_reset_5451(struct snd_ali *codec) { - struct pci_dev *pci_dev = NULL; + struct pci_dev *pci_dev; unsigned short wCount, wReg; unsigned int dwVal; - if ((pci_dev = codec->pci_m1533) != NULL) { + pci_dev = codec->pci_m1533; + if (pci_dev) { pci_read_config_dword(pci_dev, 0x7c, &dwVal); pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000); udelay(5000); @@ -541,7 +463,7 @@ static int snd_ali_reset_5451(struct snd_ali *codec) wCount = 200; while(wCount--) { wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN); - if((wReg & 0x000f) == 0x000f) + if ((wReg & 0x000f) == 0x000f) return 0; udelay(5000); } @@ -555,8 +477,8 @@ static int snd_ali_reset_5451(struct snd_ali *codec) static int snd_ali_reset_codec(struct snd_ali *codec) { - struct pci_dev *pci_dev = NULL; - unsigned char bVal = 0; + struct pci_dev *pci_dev; + unsigned char bVal; unsigned int dwVal; unsigned short wCount, wReg; @@ -579,9 +501,9 @@ static int snd_ali_reset_codec(struct snd_ali *codec) udelay(15000); wCount = 200; - while(wCount--) { + while (wCount--) { wReg = snd_ali_codec_read(codec->ac97, AC97_POWERDOWN); - if((wReg & 0x000f) == 0x000f) + if ((wReg & 0x000f) == 0x000f) return 0; udelay(5000); } @@ -594,25 +516,27 @@ static int snd_ali_reset_codec(struct snd_ali *codec) * ALI 5451 Controller */ -static void snd_ali_enable_special_channel(struct snd_ali *codec, unsigned int channel) +static void snd_ali_enable_special_channel(struct snd_ali *codec, + unsigned int channel) { - unsigned long dwVal = 0; + unsigned long dwVal; - dwVal = inl(ALI_REG(codec,ALI_GLOBAL_CONTROL)); + dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)); dwVal |= 1 << (channel & 0x0000001f); - outl(dwVal, ALI_REG(codec,ALI_GLOBAL_CONTROL)); + outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); } -static void snd_ali_disable_special_channel(struct snd_ali *codec, unsigned int channel) +static void snd_ali_disable_special_channel(struct snd_ali *codec, + unsigned int channel) { - unsigned long dwVal = 0; + unsigned long dwVal; - dwVal = inl(ALI_REG(codec,ALI_GLOBAL_CONTROL)); + dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)); dwVal &= ~(1 << (channel & 0x0000001f)); - outl(dwVal, ALI_REG(codec,ALI_GLOBAL_CONTROL)); + outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); } -static void snd_ali_enable_address_interrupt(struct snd_ali * codec) +static void snd_ali_enable_address_interrupt(struct snd_ali *codec) { unsigned int gc; @@ -622,7 +546,7 @@ static void snd_ali_enable_address_interrupt(struct snd_ali * codec) outl( gc, ALI_REG(codec, ALI_GC_CIR)); } -static void snd_ali_disable_address_interrupt(struct snd_ali * codec) +static void snd_ali_disable_address_interrupt(struct snd_ali *codec) { unsigned int gc; @@ -632,8 +556,9 @@ static void snd_ali_disable_address_interrupt(struct snd_ali * codec) outl(gc, ALI_REG(codec, ALI_GC_CIR)); } -#if 0 // not used -static void snd_ali_enable_voice_irq(struct snd_ali *codec, unsigned int channel) +#if 0 /* not used */ +static void snd_ali_enable_voice_irq(struct snd_ali *codec, + unsigned int channel) { unsigned int mask; struct snd_ali_channel_control *pchregs = &(codec->chregs); @@ -641,13 +566,14 @@ static void snd_ali_enable_voice_irq(struct snd_ali *codec, unsigned int channel snd_ali_printk("enable_voice_irq channel=%d\n",channel); mask = 1 << (channel & 0x1f); - pchregs->data.ainten = inl(ALI_REG(codec,pchregs->regs.ainten)); + pchregs->data.ainten = inl(ALI_REG(codec, pchregs->regs.ainten)); pchregs->data.ainten |= mask; - outl(pchregs->data.ainten,ALI_REG(codec,pchregs->regs.ainten)); + outl(pchregs->data.ainten, ALI_REG(codec, pchregs->regs.ainten)); } #endif -static void snd_ali_disable_voice_irq(struct snd_ali *codec, unsigned int channel) +static void snd_ali_disable_voice_irq(struct snd_ali *codec, + unsigned int channel) { unsigned int mask; struct snd_ali_channel_control *pchregs = &(codec->chregs); @@ -655,9 +581,9 @@ static void snd_ali_disable_voice_irq(struct snd_ali *codec, unsigned int channe snd_ali_printk("disable_voice_irq channel=%d\n",channel); mask = 1 << (channel & 0x1f); - pchregs->data.ainten = inl(ALI_REG(codec,pchregs->regs.ainten)); + pchregs->data.ainten = inl(ALI_REG(codec, pchregs->regs.ainten)); pchregs->data.ainten &= ~mask; - outl(pchregs->data.ainten,ALI_REG(codec,pchregs->regs.ainten)); + outl(pchregs->data.ainten, ALI_REG(codec, pchregs->regs.ainten)); } static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel) @@ -665,7 +591,8 @@ static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel) unsigned int idx = channel & 0x1f; if (codec->synth.chcnt >= ALI_CHANNELS){ - snd_printk(KERN_ERR "ali_alloc_pcm_channel: no free channels.\n"); + snd_printk(KERN_ERR + "ali_alloc_pcm_channel: no free channels.\n"); return -1; } @@ -685,35 +612,41 @@ static int snd_ali_find_free_channel(struct snd_ali * codec, int rec) snd_ali_printk("find_free_channel: for %s\n",rec ? "rec" : "pcm"); - // recording + /* recording */ if (rec) { if (codec->spdif_support && - (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_IN_SUPPORT)) + (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & + ALI_SPDIF_IN_SUPPORT)) idx = ALI_SPDIF_IN_CHANNEL; else idx = ALI_PCM_IN_CHANNEL; - if ((result = snd_ali_alloc_pcm_channel(codec,idx)) >= 0) { + result = snd_ali_alloc_pcm_channel(codec, idx); + if (result >= 0) return result; - } else { - snd_printk(KERN_ERR "ali_find_free_channel: record channel is busy now.\n"); + else { + snd_printk(KERN_ERR "ali_find_free_channel: " + "record channel is busy now.\n"); return -1; } } - //playback... + /* playback... */ if (codec->spdif_support && - (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_OUT_CH_ENABLE)) { + (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & + ALI_SPDIF_OUT_CH_ENABLE)) { idx = ALI_SPDIF_OUT_CHANNEL; - if ((result = snd_ali_alloc_pcm_channel(codec,idx)) >= 0) { + result = snd_ali_alloc_pcm_channel(codec, idx); + if (result >= 0) return result; - } else { - snd_printk(KERN_ERR "ali_find_free_channel: S/PDIF out channel is in busy now.\n"); - } + else + snd_printk(KERN_ERR "ali_find_free_channel: " + "S/PDIF out channel is in busy now.\n"); } for (idx = 0; idx < ALI_CHANNELS; idx++) { - if ((result = snd_ali_alloc_pcm_channel(codec,idx)) >= 0) + result = snd_ali_alloc_pcm_channel(codec, idx); + if (result >= 0) return result; } snd_printk(KERN_ERR "ali_find_free_channel: no free channels.\n"); @@ -730,7 +663,8 @@ static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel) return; if (!(codec->synth.chmap & (1 << idx))) { - snd_printk(KERN_ERR "ali_free_channel_pcm: channel %d is not in use.\n",channel); + snd_printk(KERN_ERR "ali_free_channel_pcm: " + "channel %d is not in use.\n", channel); return; } else { codec->synth.chmap &= ~(1 << idx); @@ -738,8 +672,8 @@ static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel) } } -#if 0 // not used -static void snd_ali_start_voice(struct snd_ali * codec, unsigned int channel) +#if 0 /* not used */ +static void snd_ali_start_voice(struct snd_ali *codec, unsigned int channel) { unsigned int mask = 1 << (channel & 0x1f); @@ -748,7 +682,7 @@ static void snd_ali_start_voice(struct snd_ali * codec, unsigned int channel) } #endif -static void snd_ali_stop_voice(struct snd_ali * codec, unsigned int channel) +static void snd_ali_stop_voice(struct snd_ali *codec, unsigned int channel) { unsigned int mask = 1 << (channel & 0x1f); @@ -768,26 +702,27 @@ static void snd_ali_delay(struct snd_ali *codec,int interval) currenttimer = inl(ALI_REG(codec, ALI_STIMER)); while (currenttimer < begintimer + interval) { - if(snd_ali_stimer_ready(codec) < 0) + if (snd_ali_stimer_ready(codec) < 0) break; currenttimer = inl(ALI_REG(codec, ALI_STIMER)); + cpu_relax(); } } static void snd_ali_detect_spdif_rate(struct snd_ali *codec) { - u16 wval = 0; + u16 wval; u16 count = 0; - u8 bval = 0, R1 = 0, R2 = 0; + u8 bval, R1 = 0, R2; - bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1)); + bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1)); bval |= 0x1F; - outb(bval,ALI_REG(codec,ALI_SPDIF_CTRL + 1)); + outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL + 1)); - while (((R1 < 0x0B )||(R1 > 0x0E)) && (R1 != 0x12) && count <= 50000) { + while ((R1 < 0x0b || R1 > 0x0e) && R1 != 0x12 && count <= 50000) { count ++; snd_ali_delay(codec, 6); - bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1)); + bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1)); R1 = bval & 0x1F; } @@ -801,7 +736,10 @@ static void snd_ali_detect_spdif_rate(struct snd_ali *codec) snd_ali_delay(codec, 6); bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1)); R2 = bval & 0x1F; - if (R2 != R1) R1 = R2; else break; + if (R2 != R1) + R1 = R2; + else + break; } if (count > 50000) { @@ -810,42 +748,45 @@ static void snd_ali_detect_spdif_rate(struct snd_ali *codec) } if (R2 >= 0x0b && R2 <= 0x0e) { - wval = inw(ALI_REG(codec,ALI_SPDIF_CTRL + 2)); - wval &= 0xE0F0; - wval |= (u16)0x09 << 8 | (u16)0x05; - outw(wval,ALI_REG(codec,ALI_SPDIF_CTRL + 2)); + wval = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2)); + wval &= 0xe0f0; + wval |= (0x09 << 8) | 0x05; + outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2)); - bval = inb(ALI_REG(codec,ALI_SPDIF_CS +3)) & 0xF0; - outb(bval|0x02,ALI_REG(codec,ALI_SPDIF_CS + 3)); + bval = inb(ALI_REG(codec, ALI_SPDIF_CS + 3)) & 0xf0; + outb(bval | 0x02, ALI_REG(codec, ALI_SPDIF_CS + 3)); } else if (R2 == 0x12) { - wval = inw(ALI_REG(codec,ALI_SPDIF_CTRL + 2)); - wval &= 0xE0F0; - wval |= (u16)0x0E << 8 | (u16)0x08; - outw(wval,ALI_REG(codec,ALI_SPDIF_CTRL + 2)); + wval = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2)); + wval &= 0xe0f0; + wval |= (0x0e << 8) | 0x08; + outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2)); - bval = inb(ALI_REG(codec,ALI_SPDIF_CS +3)) & 0xF0; - outb(bval|0x03,ALI_REG(codec,ALI_SPDIF_CS + 3)); + bval = inb(ALI_REG(codec,ALI_SPDIF_CS + 3)) & 0xf0; + outb(bval | 0x03, ALI_REG(codec, ALI_SPDIF_CS + 3)); } } static unsigned int snd_ali_get_spdif_in_rate(struct snd_ali *codec) { - u32 dwRate = 0; - u8 bval = 0; + u32 dwRate; + u8 bval; - bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL)); - bval &= 0x7F; + bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL)); + bval &= 0x7f; bval |= 0x40; - outb(bval, ALI_REG(codec,ALI_SPDIF_CTRL)); + outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL)); snd_ali_detect_spdif_rate(codec); - bval = inb(ALI_REG(codec,ALI_SPDIF_CS + 3)); - bval &= 0x0F; + bval = inb(ALI_REG(codec, ALI_SPDIF_CS + 3)); + bval &= 0x0f; - if (bval == 0) dwRate = 44100; - if (bval == 1) dwRate = 48000; - if (bval == 2) dwRate = 32000; + switch (bval) { + case 0: dwRate = 44100; break; + case 1: dwRate = 48000; break; + case 2: dwRate = 32000; break; + default: dwRate = 0; break; + } return dwRate; } @@ -880,20 +821,22 @@ static void snd_ali_disable_spdif_in(struct snd_ali *codec) static void snd_ali_set_spdif_out_rate(struct snd_ali *codec, unsigned int rate) { unsigned char bVal; - unsigned int dwRate = 0; + unsigned int dwRate; - if (rate == 32000) dwRate = 0x300; - if (rate == 44100) dwRate = 0; - if (rate == 48000) dwRate = 0x200; + switch (rate) { + case 32000: dwRate = 0x300; break; + case 48000: dwRate = 0x200; break; + default: dwRate = 0; break; + } bVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL)); bVal &= (unsigned char)(~(1<<6)); - bVal |= 0x80; //select right + bVal |= 0x80; /* select right */ outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL)); outb(dwRate | 0x20, ALI_REG(codec, ALI_SPDIF_CS + 2)); - bVal &= (~0x80); //select left + bVal &= ~0x80; /* select left */ outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL)); outw(rate | 0x10, ALI_REG(codec, ALI_SPDIF_CS + 2)); } @@ -902,8 +845,7 @@ static void snd_ali_enable_spdif_out(struct snd_ali *codec) { unsigned short wVal; unsigned char bVal; - - struct pci_dev *pci_dev = NULL; + struct pci_dev *pci_dev; pci_dev = codec->pci_m1533; if (pci_dev == NULL) @@ -926,17 +868,15 @@ static void snd_ali_enable_spdif_out(struct snd_ali *codec) bVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL)); outb(bVal & ALI_SPDIF_OUT_CH_STATUS, ALI_REG(codec, ALI_SPDIF_CTRL)); - { - wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL)); - wVal |= ALI_SPDIF_OUT_SEL_PCM; - outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); - snd_ali_disable_special_channel(codec,ALI_SPDIF_OUT_CHANNEL); - } + wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL)); + wVal |= ALI_SPDIF_OUT_SEL_PCM; + outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); + snd_ali_disable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL); } static void snd_ali_enable_spdif_chnout(struct snd_ali *codec) { - unsigned short wVal = 0; + unsigned short wVal; wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL)); wVal &= ~ALI_SPDIF_OUT_SEL_PCM; @@ -949,12 +889,13 @@ static void snd_ali_enable_spdif_chnout(struct snd_ali *codec) wVal &= (~0x0002); outw(wVal, ALI_REG(codec, ALI_SPDIF_CS)); */ - snd_ali_enable_special_channel(codec,ALI_SPDIF_OUT_CHANNEL); + snd_ali_enable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL); } static void snd_ali_disable_spdif_chnout(struct snd_ali *codec) { - unsigned short wVal = 0; + unsigned short wVal; + wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL)); wVal |= ALI_SPDIF_OUT_SEL_PCM; outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); @@ -972,11 +913,11 @@ static void snd_ali_disable_spdif_out(struct snd_ali *codec) snd_ali_disable_spdif_chnout(codec); } -static void snd_ali_update_ptr(struct snd_ali *codec,int channel) +static void snd_ali_update_ptr(struct snd_ali *codec, int channel) { - struct snd_ali_voice *pvoice = NULL; + struct snd_ali_voice *pvoice; struct snd_pcm_runtime *runtime; - struct snd_ali_channel_control *pchregs = NULL; + struct snd_ali_channel_control *pchregs; unsigned int old, mask; #ifdef ALI_DEBUG unsigned int temp, cspf; @@ -984,9 +925,9 @@ static void snd_ali_update_ptr(struct snd_ali *codec,int channel) pchregs = &(codec->chregs); - // check if interrupt occurred for channel + /* check if interrupt occurred for channel */ old = pchregs->data.aint; - mask = ((unsigned int) 1L) << (channel & 0x1f); + mask = 1U << (channel & 0x1f); if (!(old & mask)) return; @@ -1005,7 +946,8 @@ static void snd_ali_update_ptr(struct snd_ali *codec,int channel) cspf = (inl(ALI_REG(codec, ALI_CSPF)) & mask) == mask; #endif if (pvoice->running) { - snd_ali_printk("update_ptr: cso=%4.4x cspf=%d.\n",(u16)temp,cspf); + snd_ali_printk("update_ptr: cso=%4.4x cspf=%d.\n", + (u16)temp, cspf); spin_unlock(&codec->reg_lock); snd_pcm_period_elapsed(pvoice->substream); spin_lock(&codec->reg_lock); @@ -1027,49 +969,47 @@ static void snd_ali_update_ptr(struct snd_ali *codec,int channel) pchregs->data.aint = old & (~mask); } -static void snd_ali_interrupt(struct snd_ali * codec) +static irqreturn_t snd_ali_card_interrupt(int irq, void *dev_id) { + struct snd_ali *codec = dev_id; int channel; unsigned int audio_int; - struct snd_ali_channel_control *pchregs = NULL; - pchregs = &(codec->chregs); + struct snd_ali_channel_control *pchregs; + + if (codec == NULL || !codec->hw_initialized) + return IRQ_NONE; audio_int = inl(ALI_REG(codec, ALI_MISCINT)); + if (!audio_int) + return IRQ_NONE; + + pchregs = &(codec->chregs); if (audio_int & ADDRESS_IRQ) { - // get interrupt status for all channels - pchregs->data.aint = inl(ALI_REG(codec,pchregs->regs.aint)); - for (channel = 0; channel < ALI_CHANNELS; channel++) { + /* get interrupt status for all channels */ + pchregs->data.aint = inl(ALI_REG(codec, pchregs->regs.aint)); + for (channel = 0; channel < ALI_CHANNELS; channel++) snd_ali_update_ptr(codec, channel); - } } outl((TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), - ALI_REG(codec,ALI_MISCINT)); -} - - -static irqreturn_t snd_ali_card_interrupt(int irq, void *dev_id) -{ - struct snd_ali *codec = dev_id; + ALI_REG(codec, ALI_MISCINT)); - if (codec == NULL) - return IRQ_NONE; - snd_ali_interrupt(codec); return IRQ_HANDLED; } -static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, int type, int rec, int channel) +static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, + int type, int rec, int channel) { - struct snd_ali_voice *pvoice = NULL; + struct snd_ali_voice *pvoice; int idx; - snd_ali_printk("alloc_voice: type=%d rec=%d\n",type,rec); + snd_ali_printk("alloc_voice: type=%d rec=%d\n", type, rec); spin_lock_irq(&codec->voice_alloc); if (type == SNDRV_ALI_VOICE_TYPE_PCM) { idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) : snd_ali_find_free_channel(codec,rec); - if(idx < 0) { + if (idx < 0) { snd_printk(KERN_ERR "ali_alloc_voice: err.\n"); spin_unlock_irq(&codec->voice_alloc); return NULL; @@ -1087,7 +1027,8 @@ static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, int typ } -static void snd_ali_free_voice(struct snd_ali * codec, struct snd_ali_voice *pvoice) +static void snd_ali_free_voice(struct snd_ali * codec, + struct snd_ali_voice *pvoice) { void (*private_free)(void *); void *private_data; @@ -1101,9 +1042,8 @@ static void snd_ali_free_voice(struct snd_ali * codec, struct snd_ali_voice *pvo private_data = pvoice->private_data; pvoice->private_free = NULL; pvoice->private_data = NULL; - if (pvoice->pcm) { + if (pvoice->pcm) snd_ali_free_channel_pcm(codec, pvoice->number); - } pvoice->use = pvoice->pcm = pvoice->synth = 0; pvoice->substream = NULL; spin_unlock_irq(&codec->voice_alloc); @@ -1112,9 +1052,9 @@ static void snd_ali_free_voice(struct snd_ali * codec, struct snd_ali_voice *pvo } -static void snd_ali_clear_voices(struct snd_ali * codec, - unsigned int v_min, - unsigned int v_max) +static void snd_ali_clear_voices(struct snd_ali *codec, + unsigned int v_min, + unsigned int v_max) { unsigned int i; @@ -1124,7 +1064,7 @@ static void snd_ali_clear_voices(struct snd_ali * codec, } } -static void snd_ali_write_voice_regs(struct snd_ali * codec, +static void snd_ali_write_voice_regs(struct snd_ali *codec, unsigned int Channel, unsigned int LBA, unsigned int CSO, @@ -1139,7 +1079,7 @@ static void snd_ali_write_voice_regs(struct snd_ali * codec, { unsigned int ctlcmds[4]; - outb((unsigned char)(Channel & 0x001f),ALI_REG(codec,ALI_GC_CIR)); + outb((unsigned char)(Channel & 0x001f), ALI_REG(codec, ALI_GC_CIR)); ctlcmds[0] = (CSO << 16) | (ALPHA_FMS & 0x0000ffff); ctlcmds[1] = LBA; @@ -1152,10 +1092,10 @@ static void snd_ali_write_voice_regs(struct snd_ali * codec, outb(Channel, ALI_REG(codec, ALI_GC_CIR)); - outl(ctlcmds[0], ALI_REG(codec,ALI_CSO_ALPHA_FMS)); - outl(ctlcmds[1], ALI_REG(codec,ALI_LBA)); - outl(ctlcmds[2], ALI_REG(codec,ALI_ESO_DELTA)); - outl(ctlcmds[3], ALI_REG(codec,ALI_GVSEL_PAN_VOC_CTRL_EC)); + outl(ctlcmds[0], ALI_REG(codec, ALI_CSO_ALPHA_FMS)); + outl(ctlcmds[1], ALI_REG(codec, ALI_LBA)); + outl(ctlcmds[2], ALI_REG(codec, ALI_ESO_DELTA)); + outl(ctlcmds[3], ALI_REG(codec, ALI_GVSEL_PAN_VOC_CTRL_EC)); outl(0x30000000, ALI_REG(codec, ALI_EBUF1)); /* Still Mode */ outl(0x30000000, ALI_REG(codec, ALI_EBUF2)); /* Still Mode */ @@ -1165,8 +1105,10 @@ static unsigned int snd_ali_convert_rate(unsigned int rate, int rec) { unsigned int delta; - if (rate < 4000) rate = 4000; - if (rate > 48000) rate = 48000; + if (rate < 4000) + rate = 4000; + if (rate > 48000) + rate = 48000; if (rec) { if (rate == 44100) @@ -1201,11 +1143,11 @@ static unsigned int snd_ali_control_mode(struct snd_pcm_substream *substream) */ CTRL = 0x00000001; if (snd_pcm_format_width(runtime->format) == 16) - CTRL |= 0x00000008; // 16-bit data + CTRL |= 0x00000008; /* 16-bit data */ if (!snd_pcm_format_unsigned(runtime->format)) - CTRL |= 0x00000002; // signed data + CTRL |= 0x00000002; /* signed data */ if (runtime->channels > 1) - CTRL |= 0x00000004; // stereo data + CTRL |= 0x00000004; /* stereo data */ return CTRL; } @@ -1213,45 +1155,39 @@ static unsigned int snd_ali_control_mode(struct snd_pcm_substream *substream) * PCM part */ -static int snd_ali_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - static int snd_ali_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct list_head *pos; struct snd_pcm_substream *s; unsigned int what, whati, capture_flag; - struct snd_ali_voice *pvoice = NULL, *evoice = NULL; + struct snd_ali_voice *pvoice, *evoice; unsigned int val; int do_start; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: - do_start = 1; break; + do_start = 1; + break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: - do_start = 0; break; + do_start = 0; + break; default: return -EINVAL; } what = whati = capture_flag = 0; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if ((struct snd_ali *) snd_pcm_substream_chip(s) == codec) { pvoice = s->runtime->private_data; evoice = pvoice->extra; what |= 1 << (pvoice->number & 0x1f); - if (evoice == NULL) { + if (evoice == NULL) whati |= 1 << (pvoice->number & 0x1f); - } else { + else { whati |= 1 << (evoice->number & 0x1f); what |= 1 << (evoice->number & 0x1f); } @@ -1270,48 +1206,51 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, } } spin_lock(&codec->reg_lock); - if (! do_start) { + if (!do_start) outl(what, ALI_REG(codec, ALI_STOP)); - } val = inl(ALI_REG(codec, ALI_AINTEN)); - if (do_start) { + if (do_start) val |= whati; - } else { + else val &= ~whati; - } outl(val, ALI_REG(codec, ALI_AINTEN)); - if (do_start) { + if (do_start) outl(what, ALI_REG(codec, ALI_START)); - } - snd_ali_printk("trigger: what=%xh whati=%xh\n",what,whati); + snd_ali_printk("trigger: what=%xh whati=%xh\n", what, whati); spin_unlock(&codec->reg_lock); return 0; } static int snd_ali_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) + struct snd_pcm_hw_params *hw_params) { struct snd_ali *codec = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_ali_voice *pvoice = runtime->private_data; struct snd_ali_voice *evoice = pvoice->extra; int err; - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) return err; + + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; /* voice management */ - if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) { - if (evoice == NULL) { - evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0, -1); - if (evoice == NULL) + if (params_buffer_size(hw_params) / 2 != + params_period_size(hw_params)) { + if (!evoice) { + evoice = snd_ali_alloc_voice(codec, + SNDRV_ALI_VOICE_TYPE_PCM, + 0, -1); + if (!evoice) return -ENOMEM; pvoice->extra = evoice; evoice->substream = substream; } } else { - if (evoice != NULL) { + if (!evoice) { snd_ali_free_voice(codec, evoice); pvoice->extra = evoice = NULL; } @@ -1328,7 +1267,7 @@ static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream) struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL; snd_pcm_lib_free_pages(substream); - if (evoice != NULL) { + if (!evoice) { snd_ali_free_voice(codec, evoice); pvoice->extra = NULL; } @@ -1336,9 +1275,10 @@ static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream) } static int snd_ali_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) + struct snd_pcm_hw_params *hw_params) { - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); } static int snd_ali_hw_free(struct snd_pcm_substream *substream) @@ -1369,12 +1309,13 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream) /* set Delta (rate) value */ Delta = snd_ali_convert_rate(runtime->rate, 0); - if ((pvoice->number == ALI_SPDIF_IN_CHANNEL) || - (pvoice->number == ALI_PCM_IN_CHANNEL)) + if (pvoice->number == ALI_SPDIF_IN_CHANNEL || + pvoice->number == ALI_PCM_IN_CHANNEL) snd_ali_disable_special_channel(codec, pvoice->number); else if (codec->spdif_support && - (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_OUT_CH_ENABLE) - && (pvoice->number == ALI_SPDIF_OUT_CHANNEL)) { + (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & + ALI_SPDIF_OUT_CH_ENABLE) + && pvoice->number == ALI_SPDIF_OUT_CHANNEL) { snd_ali_set_spdif_out_rate(codec, runtime->rate); Delta = 0x1000; } @@ -1388,7 +1329,8 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream) /* set target ESO for channel */ pvoice->eso = runtime->buffer_size; - snd_ali_printk("playback_prepare: eso=%xh count=%xh\n",pvoice->eso,pvoice->count); + snd_ali_printk("playback_prepare: eso=%xh count=%xh\n", + pvoice->eso, pvoice->count); /* set ESO to capture first MIDLP interrupt */ ESO = pvoice->eso -1; @@ -1399,35 +1341,37 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream) PAN = 0; VOL = 0; EC = 0; - snd_ali_printk("playback_prepare:\n ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n",pvoice->number,runtime->rate,Delta,GVSEL,PAN,CTRL); - snd_ali_write_voice_regs( codec, - pvoice->number, - LBA, - 0, /* cso */ - ESO, - Delta, - 0, /* alpha */ - GVSEL, - PAN, - VOL, - CTRL, - EC); - if (evoice != NULL) { + snd_ali_printk("playback_prepare:\n"); + snd_ali_printk("ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n", + pvoice->number,runtime->rate,Delta,GVSEL,PAN,CTRL); + snd_ali_write_voice_regs(codec, + pvoice->number, + LBA, + 0, /* cso */ + ESO, + Delta, + 0, /* alpha */ + GVSEL, + PAN, + VOL, + CTRL, + EC); + if (!evoice) { evoice->count = pvoice->count; evoice->eso = pvoice->count << 1; ESO = evoice->eso - 1; snd_ali_write_voice_regs(codec, - evoice->number, - LBA, - 0, /* cso */ - ESO, - Delta, - 0, /* alpha */ - GVSEL, - (unsigned int)0x7f, - (unsigned int)0x3ff, - CTRL, - EC); + evoice->number, + LBA, + 0, /* cso */ + ESO, + Delta, + 0, /* alpha */ + GVSEL, + 0x7f, + 0x3ff, + CTRL, + EC); } spin_unlock_irq(&codec->reg_lock); return 0; @@ -1459,7 +1403,7 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream) pvoice->number == ALI_MODEM_OUT_CHANNEL) ? 0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode); - // Prepare capture intr channel + /* Prepare capture intr channel */ if (pvoice->number == ALI_SPDIF_IN_CHANNEL) { unsigned int rate; @@ -1470,7 +1414,8 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream) rate = snd_ali_get_spdif_in_rate(codec); if (rate == 0) { - snd_printk(KERN_WARNING "ali_capture_preapre: spdif rate detect err!\n"); + snd_printk(KERN_WARNING "ali_capture_preapre: " + "spdif rate detect err!\n"); rate = 48000; } spin_lock_irq(&codec->reg_lock); @@ -1481,19 +1426,19 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream) } if (rate != 48000) - Delta = ((rate << 12)/runtime->rate)&0x00ffff; + Delta = ((rate << 12) / runtime->rate) & 0x00ffff; } - // set target ESO for channel + /* set target ESO for channel */ pvoice->eso = runtime->buffer_size; - // set interrupt count size + /* set interrupt count size */ pvoice->count = runtime->period_size; - // set Loop Back Address + /* set Loop Back Address */ LBA = runtime->dma_addr; - // set ESO to capture first MIDLP interrupt + /* set ESO to capture first MIDLP interrupt */ ESO = pvoice->eso - 1; CTRL = snd_ali_control_mode(substream); GVSEL = 0; @@ -1514,14 +1459,14 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream) CTRL, EC); - spin_unlock_irq(&codec->reg_lock); return 0; } -static snd_pcm_uframes_t snd_ali_playback_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t +snd_ali_playback_pointer(struct snd_pcm_substream *substream) { struct snd_ali *codec = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; @@ -1563,14 +1508,14 @@ static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream) static struct snd_pcm_hardware snd_ali_playback = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_SYNC_START), + .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), + .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 4000, .rate_max = 48000, .channels_min = 1, @@ -1589,14 +1534,14 @@ static struct snd_pcm_hardware snd_ali_playback = static struct snd_pcm_hardware snd_ali_capture = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_SYNC_START), + .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), + .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 4000, .rate_max = 48000, .channels_min = 1, @@ -1620,15 +1565,16 @@ static void snd_ali_pcm_free_substream(struct snd_pcm_runtime *runtime) } } -static int snd_ali_open(struct snd_pcm_substream *substream, int rec, int channel, - struct snd_pcm_hardware *phw) +static int snd_ali_open(struct snd_pcm_substream *substream, int rec, + int channel, struct snd_pcm_hardware *phw) { struct snd_ali *codec = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_ali_voice *pvoice; - pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel); - if (pvoice == NULL) + pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, + channel); + if (!pvoice) return -EAGAIN; pvoice->substream = substream; @@ -1637,7 +1583,8 @@ static int snd_ali_open(struct snd_pcm_substream *substream, int rec, int channe runtime->hw = *phw; snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); + snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + 0, 64*1024); return 0; } @@ -1669,7 +1616,7 @@ static int snd_ali_close(struct snd_pcm_substream *substream) static struct snd_pcm_ops snd_ali_playback_ops = { .open = snd_ali_playback_open, .close = snd_ali_playback_close, - .ioctl = snd_ali_ioctl, + .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_ali_playback_hw_params, .hw_free = snd_ali_playback_hw_free, .prepare = snd_ali_playback_prepare, @@ -1680,7 +1627,7 @@ static struct snd_pcm_ops snd_ali_playback_ops = { static struct snd_pcm_ops snd_ali_capture_ops = { .open = snd_ali_capture_open, .close = snd_ali_close, - .ioctl = snd_ali_ioctl, + .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_ali_hw_params, .hw_free = snd_ali_hw_free, .prepare = snd_ali_prepare, @@ -1697,20 +1644,22 @@ static int snd_ali_modem_hw_params(struct snd_pcm_substream *substream, { struct snd_ali *chip = snd_pcm_substream_chip(substream); unsigned int modem_num = chip->num_of_codecs - 1; - snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, params_rate(hw_params)); + snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, + params_rate(hw_params)); snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0); return snd_ali_hw_params(substream, hw_params); } static struct snd_pcm_hardware snd_ali_modem = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_KNOT|SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000, + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000), .rate_min = 8000, .rate_max = 16000, .channels_min = 1, @@ -1723,15 +1672,17 @@ static struct snd_pcm_hardware snd_ali_modem = .fifo_size = 0, }; -static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec, int channel) +static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec, + int channel) { - static unsigned int rates [] = {8000,9600,12000,16000}; + static unsigned int rates[] = {8000, 9600, 12000, 16000}; static struct snd_pcm_hw_constraint_list hw_constraint_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, }; int err = snd_ali_open(substream, rec, channel, &snd_ali_modem); + if (err) return err; return snd_pcm_hw_constraint_list(substream->runtime, 0, @@ -1788,7 +1739,8 @@ static void snd_ali_pcm_free(struct snd_pcm *pcm) } -static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, struct ali_pcm_description *desc) +static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, + struct ali_pcm_description *desc) { struct snd_pcm *pcm; int err; @@ -1802,12 +1754,15 @@ static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, struct ali_ pcm->private_data = codec; pcm->private_free = snd_ali_pcm_free; if (desc->playback_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, desc->playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + desc->playback_ops); if (desc->capture_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, desc->capture_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + desc->capture_ops); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(codec->pci), 64*1024, 128*1024); + snd_dma_pci_data(codec->pci), + 64*1024, 128*1024); pcm->info_flags = 0; pcm->dev_class = desc->class; @@ -1818,16 +1773,29 @@ static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, struct ali_ } static struct ali_pcm_description ali_pcms[] = { - { "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops }, - { "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops, SNDRV_PCM_CLASS_MODEM } + { .name = "ALI 5451", + .playback_num = ALI_CHANNELS, + .capture_num = 1, + .playback_ops = &snd_ali_playback_ops, + .capture_ops = &snd_ali_capture_ops + }, + { .name = "ALI 5451 modem", + .playback_num = 1, + .capture_num = 1, + .playback_ops = &snd_ali_modem_playback_ops, + .capture_ops = &snd_ali_modem_capture_ops, + .class = SNDRV_PCM_CLASS_MODEM + } }; static int __devinit snd_ali_build_pcms(struct snd_ali *codec) { int i, err; - for(i = 0 ; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms) ; i++) - if((err = snd_ali_pcm(codec, i, &ali_pcms[i])) < 0) + for (i = 0; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms); i++) { + err = snd_ali_pcm(codec, i, &ali_pcms[i]); + if (err < 0) return err; + } return 0; } @@ -1837,7 +1805,8 @@ static int __devinit snd_ali_build_pcms(struct snd_ali *codec) .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \ .put = snd_ali5451_spdif_put, .private_value = value} -static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; @@ -1846,7 +1815,8 @@ static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ return 0; } -static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ali *codec = kcontrol->private_data; unsigned int enable; @@ -1854,12 +1824,13 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e enable = ucontrol->value.integer.value[0] ? 1 : 0; spin_lock_irq(&codec->reg_lock); - switch(kcontrol->private_value) { + switch (kcontrol->private_value) { case 0: enable = (codec->spdif_mask & 0x02) ? 1 : 0; break; case 1: - enable = ((codec->spdif_mask & 0x02) && (codec->spdif_mask & 0x04)) ? 1 : 0; + enable = ((codec->spdif_mask & 0x02) && + (codec->spdif_mask & 0x04)) ? 1 : 0; break; case 2: enable = (codec->spdif_mask & 0x01) ? 1 : 0; @@ -1872,7 +1843,8 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e return 0; } -static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ali *codec = kcontrol->private_data; unsigned int change = 0, enable = 0; @@ -1939,18 +1911,6 @@ static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = { ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2) }; -static void snd_ali_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct snd_ali *codec = bus->private_data; - codec->ac97_bus = NULL; -} - -static void snd_ali_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct snd_ali *codec = ac97->private_data; - codec->ac97[ac97->num] = NULL; -} - static int __devinit snd_ali_mixer(struct snd_ali * codec) { struct snd_ac97_template ac97; @@ -1961,19 +1921,20 @@ static int __devinit snd_ali_mixer(struct snd_ali * codec) .read = snd_ali_codec_read, }; - if ((err = snd_ac97_bus(codec->card, 0, &ops, codec, &codec->ac97_bus)) < 0) + err = snd_ac97_bus(codec->card, 0, &ops, codec, &codec->ac97_bus); + if (err < 0) return err; - codec->ac97_bus->private_free = snd_ali_mixer_free_ac97_bus; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = codec; - ac97.private_free = snd_ali_mixer_free_ac97; - for ( i = 0 ; i < codec->num_of_codecs ; i++) { + for (i = 0; i < codec->num_of_codecs; i++) { ac97.num = i; - if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) { - snd_printk(KERN_ERR "ali mixer %d creating error.\n", i); - if(i == 0) + err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i]); + if (err < 0) { + snd_printk(KERN_ERR + "ali mixer %d creating error.\n", i); + if (i == 0) return err; codec->num_of_codecs = 1; break; @@ -1981,9 +1942,11 @@ static int __devinit snd_ali_mixer(struct snd_ali * codec) } if (codec->spdif_support) { - for(idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) { - err=snd_ctl_add(codec->card, snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec)); - if (err < 0) return err; + for (idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) { + err = snd_ctl_add(codec->card, + snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec)); + if (err < 0) + return err; } } return 0; @@ -1998,11 +1961,11 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state) int i, j; im = chip->image; - if (! im) + if (!im) return 0; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for(i = 0 ; i < chip->num_of_codecs ; i++) { + for (i = 0; i < chip->num_of_codecs; i++) { snd_pcm_suspend_all(chip->pcm[i]); snd_ac97_suspend(chip->ac97[i]); } @@ -2010,10 +1973,10 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state) spin_lock_irq(&chip->reg_lock); im->regs[ALI_MISCINT >> 2] = inl(ALI_REG(chip, ALI_MISCINT)); - // im->regs[ALI_START >> 2] = inl(ALI_REG(chip, ALI_START)); + /* im->regs[ALI_START >> 2] = inl(ALI_REG(chip, ALI_START)); */ im->regs[ALI_STOP >> 2] = inl(ALI_REG(chip, ALI_STOP)); - // disable all IRQ bits + /* disable all IRQ bits */ outl(0, ALI_REG(chip, ALI_MISCINT)); for (i = 0; i < ALI_GLOBAL_REGS; i++) { @@ -2028,7 +1991,7 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state) im->channel_regs[i][j] = inl(ALI_REG(chip, j*4 + 0xe0)); } - // stop all HW channel + /* stop all HW channel */ outl(0xffffffff, ALI_REG(chip, ALI_STOP)); spin_unlock_irq(&chip->reg_lock); @@ -2047,7 +2010,7 @@ static int ali_resume(struct pci_dev *pci) int i, j; im = chip->image; - if (! im) + if (!im) return 0; pci_set_power_state(pci, PCI_D0); @@ -2069,19 +2032,20 @@ static int ali_resume(struct pci_dev *pci) } for (i = 0; i < ALI_GLOBAL_REGS; i++) { - if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP) || (i*4 == ALI_START)) + if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP) || + (i*4 == ALI_START)) continue; outl(im->regs[i], ALI_REG(chip, i*4)); } - // start HW channel + /* start HW channel */ outl(im->regs[ALI_START >> 2], ALI_REG(chip, ALI_START)); - // restore IRQ enable bits + /* restore IRQ enable bits */ outl(im->regs[ALI_MISCINT >> 2], ALI_REG(chip, ALI_MISCINT)); spin_unlock_irq(&chip->reg_lock); - for(i = 0 ; i < chip->num_of_codecs ; i++) + for (i = 0 ; i < chip->num_of_codecs; i++) snd_ac97_resume(chip->ac97[i]); snd_power_change_state(card, SNDRV_CTL_POWER_D0); @@ -2113,7 +2077,7 @@ static int snd_ali_chip_init(struct snd_ali *codec) { unsigned int legacy; unsigned char temp; - struct pci_dev *pci_dev = NULL; + struct pci_dev *pci_dev; snd_ali_printk("chip initializing ... \n"); @@ -2146,7 +2110,8 @@ static int snd_ali_chip_init(struct snd_ali *codec) outb(0x10, ALI_REG(codec, ALI_MPUR2)); codec->ac97_ext_id = snd_ali_codec_peek(codec, 0, AC97_EXTENDED_ID); - codec->ac97_ext_status = snd_ali_codec_peek(codec, 0, AC97_EXTENDED_STATUS); + codec->ac97_ext_status = snd_ali_codec_peek(codec, 0, + AC97_EXTENDED_STATUS); if (codec->spdif_support) { snd_ali_enable_spdif_out(codec); codec->spdif_mask = 0x00000002; @@ -2158,8 +2123,9 @@ static int snd_ali_chip_init(struct snd_ali *codec) if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) { codec->num_of_codecs++; outl(inl(ALI_REG(codec, ALI_SCTRL)) | - (ALI_SCTRL_LINE_IN2|ALI_SCTRL_GPIO_IN2|ALI_SCTRL_LINE_OUT_EN), - ALI_REG(codec, ALI_SCTRL)); + (ALI_SCTRL_LINE_IN2 | ALI_SCTRL_GPIO_IN2 | + ALI_SCTRL_LINE_OUT_EN), + ALI_REG(codec, ALI_SCTRL)); } snd_ali_printk("chip initialize succeed.\n"); @@ -2168,18 +2134,19 @@ static int snd_ali_chip_init(struct snd_ali *codec) } /* proc for register dump */ -static void snd_ali_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buf) +static void snd_ali_proc_read(struct snd_info_entry *entry, + struct snd_info_buffer *buf) { struct snd_ali *codec = entry->private_data; int i; - for(i = 0 ; i < 256 ; i+= 4) + for (i = 0; i < 256 ; i+= 4) snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i))); } static void __devinit snd_ali_proc_init(struct snd_ali *codec) { struct snd_info_entry *entry; - if(!snd_card_proc_new(codec->card, "ali5451", &entry)) + if (!snd_card_proc_new(codec->card, "ali5451", &entry)) snd_info_set_text_ops(entry, codec, snd_ali_proc_read); } @@ -2188,7 +2155,8 @@ static int __devinit snd_ali_resources(struct snd_ali *codec) int err; snd_ali_printk("resouces allocation ...\n"); - if ((err = pci_request_regions(codec->pci, "ALI 5451")) < 0) + err = pci_request_regions(codec->pci, "ALI 5451"); + if (err < 0) return err; codec->port = pci_resource_start(codec->pci, 0); @@ -2201,9 +2169,9 @@ static int __devinit snd_ali_resources(struct snd_ali *codec) snd_ali_printk("resouces allocated.\n"); return 0; } -static int snd_ali_dev_free(struct snd_device *device) +static int snd_ali_dev_free(struct snd_device *device) { - struct snd_ali *codec=device->device_data; + struct snd_ali *codec = device->device_data; snd_ali_free(codec); return 0; } @@ -2226,17 +2194,20 @@ static int __devinit snd_ali_create(struct snd_card *card, snd_ali_printk("creating ...\n"); /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; /* check, if we can restrict PCI DMA transfers to 31 bits */ if (pci_set_dma_mask(pci, DMA_31BIT_MASK) < 0 || pci_set_consistent_dma_mask(pci, DMA_31BIT_MASK) < 0) { - snd_printk(KERN_ERR "architecture does not support 31bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support " + "31bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } - if ((codec = kzalloc(sizeof(*codec), GFP_KERNEL)) == NULL) { + codec = kzalloc(sizeof(*codec), GFP_KERNEL); + if (!codec) { pci_disable_device(pci); return -ENOMEM; } @@ -2293,21 +2264,22 @@ static int __devinit snd_ali_create(struct snd_card *card, /* M1533: southbridge */ codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL); - if (! codec->pci_m1533) { + if (!codec->pci_m1533) { snd_printk(KERN_ERR "ali5451: cannot find ALi 1533 chip.\n"); snd_ali_free(codec); return -ENODEV; } /* M7101: power management */ codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL); - if (! codec->pci_m7101 && codec->revision == ALI_5451_V02) { + if (!codec->pci_m7101 && codec->revision == ALI_5451_V02) { snd_printk(KERN_ERR "ali5451: cannot find ALi 7101 chip.\n"); snd_ali_free(codec); return -ENODEV; } snd_ali_printk("snd_device_new is called.\n"); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops); + if (err < 0) { snd_ali_free(codec); return err; } @@ -2315,18 +2287,18 @@ static int __devinit snd_ali_create(struct snd_card *card, snd_card_set_dev(card, &pci->dev); /* initialise synth voices*/ - for (i = 0; i < ALI_CHANNELS; i++ ) { + for (i = 0; i < ALI_CHANNELS; i++) codec->synth.voices[i].number = i; - } - if ((err = snd_ali_chip_init(codec)) < 0) { + err = snd_ali_chip_init(codec); + if (err < 0) { snd_printk(KERN_ERR "ali create: chip init error.\n"); return err; } #ifdef CONFIG_PM codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL); - if (! codec->image) + if (!codec->image) snd_printk(KERN_WARNING "can't allocate apm buffer\n"); #endif @@ -2348,26 +2320,23 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, snd_ali_printk("probe ...\n"); card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) + if (!card) return -ENOMEM; - if ((err = snd_ali_create(card, pci, pcm_channels, spdif, &codec)) < 0) { - snd_card_free(card); - return err; - } + err = snd_ali_create(card, pci, pcm_channels, spdif, &codec); + if (err < 0) + goto error; card->private_data = codec; snd_ali_printk("mixer building ...\n"); - if ((err = snd_ali_mixer(codec)) < 0) { - snd_card_free(card); - return err; - } + err = snd_ali_mixer(codec); + if (err < 0) + goto error; snd_ali_printk("pcm building ...\n"); - if ((err = snd_ali_build_pcms(codec)) < 0) { - snd_card_free(card); - return err; - } + err = snd_ali_build_pcms(codec); + if (err < 0) + goto error; snd_ali_proc_init(codec); @@ -2378,12 +2347,16 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, card->shortname, codec->port, codec->irq); snd_ali_printk("register card.\n"); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } + err = snd_card_register(card); + if (err < 0) + goto error; + pci_set_drvdata(pci, card); return 0; + + error: + snd_card_free(card); + return err; } static void __devexit snd_ali_remove(struct pci_dev *pci) diff --git a/sound/pci/au88x0/au88x0_sb.h b/sound/pci/au88x0/au88x0_sb.h deleted file mode 100644 index 5a4d8fc2bbfc..000000000000 --- a/sound/pci/au88x0/au88x0_sb.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * au88x0_sb.h - * - * Wed Oct 29 22:10:42 2003 - * - ****************************************************************************/ - -#ifdef CHIP_AU8820 -/* AU8820 starting @ 64KiB offset */ -#define SBEMU_BASE 0x10000 -#else -/* AU8810? and AU8830 starting @ 164KiB offset */ -#define SBEMU_BASE 0x29000 -#endif - -#define FM_A_STATUS (SBEMU_BASE + 0x00) /* read */ -#define FM_A_ADDRESS (SBEMU_BASE + 0x00) /* write */ -#define FM_A_DATA (SBEMU_BASE + 0x04) -#define FM_B_STATUS (SBEMU_BASE + 0x08) -#define FM_B_ADDRESS (SBEMU_BASE + 0x08) -#define FM_B_DATA (SBEMU_BASE + 0x0C) -#define SB_MIXER_ADDR (SBEMU_BASE + 0x10) -#define SB_MIXER_DATA (SBEMU_BASE + 0x14) -#define SB_RESET (SBEMU_BASE + 0x18) -#define SB_RESET_ALIAS (SBEMU_BASE + 0x1C) -#define FM_STATUS2 (SBEMU_BASE + 0x20) -#define FM_ADDR2 (SBEMU_BASE + 0x20) -#define FM_DATA2 (SBEMU_BASE + 0x24) -#define SB_DSP_READ (SBEMU_BASE + 0x28) -#define SB_DSP_WRITE (SBEMU_BASE + 0x30) -#define SB_DSP_WRITE_STATUS (SBEMU_BASE + 0x30) /* bit 7 */ -#define SB_DSP_READ_STATUS (SBEMU_BASE + 0x38) /* bit 7 */ -#define SB_LACR (SBEMU_BASE + 0x40) /* ? */ -#define SB_LADCR (SBEMU_BASE + 0x44) /* ? */ -#define SB_LAMR (SBEMU_BASE + 0x48) /* ? */ -#define SB_LARR (SBEMU_BASE + 0x4C) /* ? */ -#define SB_VERSION (SBEMU_BASE + 0x50) -#define SB_CTRLSTAT (SBEMU_BASE + 0x54) -#define SB_TIMERSTAT (SBEMU_BASE + 0x58) -#define FM_RAM (SBEMU_BASE + 0x100) /* 0x40 ULONG */ diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 43edd2839b5a..36d3666a5b77 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1,6 +1,6 @@ /* * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168). - * Copyright (C) 2002, 2005 by Andreas Mohr <andi AT lisas.de> + * Copyright (C) 2002, 2005, 2006, 2007 by Andreas Mohr <andi AT lisas.de> * * Framework borrowed from Bart Hartgers's als4000.c. * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), @@ -52,6 +52,9 @@ * - full duplex 16bit playback/record at independent sampling rate * - MPU401 (+ legacy address support) FIXME: how to enable legacy addr?? * - game port (legacy address support) + * - builtin 3D enhancement (said to be YAMAHA Ymersion) + * - builtin DirectInput support, helps reduce CPU overhead (interrupt-driven + * features supported) * - built-in General DirectX timer having a 20 bits counter * with 1us resolution (see below!) * - I2S serial port for external DAC @@ -94,6 +97,10 @@ * * BUGS * - full-duplex might *still* be problematic, not fully tested recently + * - (non-bug) "Bass/Treble or 3D settings don't work" - they do get evaluated + * if you set PCM output switch to "pre 3D" instead of "post 3D". + * If this can't be set, then get a mixer application that Isn't Stupid (tm) + * (e.g. kmix, gamix) - unfortunately several are!! * * TODO * - test MPU401 MIDI playback etc. @@ -622,7 +629,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol, return (nreg != oreg); } -static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = { +static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = { AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1), AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1), AZF3328_MIXER_SWITCH("Wave Playback Switch", IDX_MIXER_WAVEOUT, 15, 1), @@ -652,7 +659,7 @@ static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1), AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8), AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9), - AZF3328_MIXER_ENUM("PCM", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */ + AZF3328_MIXER_ENUM("PCM Output Route", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */ AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0), AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0), AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0), @@ -678,7 +685,7 @@ static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata #endif }; -static const u16 __devinitdata snd_azf3328_init_values[][2] = { +static u16 __devinitdata snd_azf3328_init_values[][2] = { { IDX_MIXER_PLAY_MASTER, MIXER_MUTE_MASK|0x1f1f }, { IDX_MIXER_MODEMOUT, MIXER_MUTE_MASK|0x1f1f }, { IDX_MIXER_BASSTREBLE, 0x0000 }, @@ -1369,7 +1376,6 @@ snd_azf3328_playback_close(struct snd_pcm_substream *substream) struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); snd_azf3328_dbgcallenter(); - chip->playback_substream = NULL; snd_azf3328_dbgcallleave(); return 0; @@ -1660,10 +1666,10 @@ snd_azf3328_test_bit(unsigned int reg, int bit) } #endif +#if DEBUG_MISC static void snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) { -#if DEBUG_MISC u16 tmp; snd_azf3328_dbgmisc("codec_port 0x%lx, io2_port 0x%lx, mpu_port 0x%lx, synth_port 0x%lx, mixer_port 0x%lx, irq %d\n", chip->codec_port, chip->io2_port, chip->mpu_port, chip->synth_port, chip->mixer_port, chip->irq); @@ -1673,10 +1679,16 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) for (tmp=0; tmp <= 0x01; tmp += 1) snd_azf3328_dbgmisc("0x%02x: opl 0x%04x, mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, mpu330 0x%04x\n", tmp, inb(0x388 + tmp), inb(0x300 + tmp), inb(0x310 + tmp), inb(0x320 + tmp), inb(0x330 + tmp)); - for (tmp = 0; tmp <= 0x6E; tmp += 2) - snd_azf3328_dbgmisc("0x%02x: 0x%04x\n", tmp, snd_azf3328_codec_inb(chip, tmp)); -#endif + for (tmp = 0; tmp < AZF_IO_SIZE_CODEC; tmp += 2) + snd_azf3328_dbgmisc("codec 0x%02x: 0x%04x\n", tmp, snd_azf3328_codec_inw(chip, tmp)); + + for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2) + snd_azf3328_dbgmisc("mixer 0x%02x: 0x%04x\n", tmp, snd_azf3328_mixer_inw(chip, tmp)); } +#else +static inline void +snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) {} +#endif static int __devinit snd_azf3328_create(struct snd_card *card, @@ -1842,8 +1854,8 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) #ifdef MODULE printk( -"azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168\n" -"azt3328: (hardware was completely undocumented - ZERO support from Aztech).\n" +"azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168.\n" +"azt3328: Hardware was completely undocumented, unfortunately.\n" "azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n" "azt3328: User-scalable sequencer timer set to %dHz (1024000Hz / %d).\n", 1024000 / seqtimer_scaling, seqtimer_scaling); diff --git a/sound/pci/azt3328.h b/sound/pci/azt3328.h index b4f3e3cd006b..679fa992e2bc 100644 --- a/sound/pci/azt3328.h +++ b/sound/pci/azt3328.h @@ -106,8 +106,8 @@ #define IRQ_RECORDING 0x0002 #define IRQ_MPU401 0x0010 #define IRQ_TIMER 0x0020 /* DirectX timer */ - #define IRQ_UNKNOWN1 0x0040 /* probably unused */ - #define IRQ_UNKNOWN2 0x0080 /* probably unused */ + #define IRQ_UNKNOWN1 0x0040 /* probably unused, or possibly I2S port? or gameport IRQ? */ + #define IRQ_UNKNOWN2 0x0080 /* probably unused, or possibly I2S port? or gameport IRQ? */ #define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ #define IDX_IO_SOME_VALUE 0x68 /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */ #define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated (FIXME: correct??); actually inhibits PCM playback!!! maybe power management?? */ diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index e9b029e1cd6d..6523ba07db96 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -781,6 +781,8 @@ static struct pci_device_id snd_bt87x_ids[] = { BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), /* Viewcast Osprey 200 */ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), + /* ATI TV-Wonder */ + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, 32000), /* Leadtek Winfast tv 2000xp delux */ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), /* Voodoo TV 200 */ @@ -833,7 +835,7 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) pci->device, pci->subsystem_vendor, pci->subsystem_device); snd_printk(KERN_DEBUG "please mail id, board name, and, " "if it works, the correct digital_rate option to " - "<alsa-devel@lists.sf.net>\n"); + "<alsa-devel@alsa-project.org>\n"); return 32000; /* default rate */ } diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index ea6712b63c9f..48f3f17c5170 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -775,7 +775,6 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, struct snd_ca0106_pcm *epcm; int channel; int result = 0; - struct list_head *pos; struct snd_pcm_substream *s; u32 basic = 0; u32 extended = 0; @@ -790,8 +789,7 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, running=0; break; } - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { runtime = s->runtime; epcm = runtime->private_data; channel = epcm->channel_id; diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 2ae539b195fd..bef1f6d1859c 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -3107,7 +3107,7 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) snd_printk(KERN_ERR "ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n"); snd_printk(KERN_ERR " Try reloading the ALSA driver, if you find something\n"); snd_printk(KERN_ERR " broken or not working on your soundcard upon\n"); - snd_printk(KERN_ERR " this message please report to alsa-devel@lists.sourceforge.net\n"); + snd_printk(KERN_ERR " this message please report to alsa-devel@alsa-project.org\n"); return -EIO; #endif diff --git a/sound/pci/cs46xx/imgs/cwcemb80.h b/sound/pci/cs46xx/imgs/cwcemb80.h deleted file mode 100644 index a64c6ff9983a..000000000000 --- a/sound/pci/cs46xx/imgs/cwcemb80.h +++ /dev/null @@ -1,1607 +0,0 @@ -/* generated from cwcemb80.osp DO NOT MODIFY */ - -#ifndef __HEADER_cwcemb80_H__ -#define __HEADER_cwcemb80_H__ - -static struct dsp_symbol_entry cwcemb80_symbols[] = { - { 0x0000, "BEGINADDRESS",0x00 }, - { 0x8000, "EXECCHILD",0x03 }, - { 0x8001, "EXECCHILD_98",0x03 }, - { 0x8003, "EXECCHILD_PUSH1IND",0x03 }, - { 0x8008, "EXECSIBLING",0x03 }, - { 0x800a, "EXECSIBLING_298",0x03 }, - { 0x800b, "EXECSIBLING_2IND1",0x03 }, - { 0x8010, "TIMINGMASTER",0x03 }, - { 0x804f, "S16_CODECINPUTTASK",0x03 }, - { 0x805e, "PCMSERIALINPUTTASK",0x03 }, - { 0x806d, "S16_MIX_TO_OSTREAM",0x03 }, - { 0x809a, "S16_MIX",0x03 }, - { 0x80bb, "S16_UPSRC",0x03 }, - { 0x813b, "MIX3_EXP",0x03 }, - { 0x8164, "DECIMATEBYPOW2",0x03 }, - { 0x8197, "VARIDECIMATE",0x03 }, - { 0x81f2, "_3DINPUTTASK",0x03 }, - { 0x820a, "_3DPRLGCINPTASK",0x03 }, - { 0x8227, "_3DSTEREOINPUTTASK",0x03 }, - { 0x8242, "_3DOUTPUTTASK",0x03 }, - { 0x82c4, "HRTF_MORPH_TASK",0x03 }, - { 0x82c6, "WAIT4DATA",0x03 }, - { 0x82fa, "PROLOGIC",0x03 }, - { 0x8496, "DECORRELATOR",0x03 }, - { 0x84a4, "STEREO2MONO",0x03 }, - { 0x0070, "SPOSCB",0x02 }, - { 0x0105, "TASKTREETHREAD",0x03 }, - { 0x0136, "TASKTREEHEADERCODE",0x03 }, - { 0x013f, "FGTASKTREEHEADERCODE",0x03 }, - { 0x0163, "NULLALGORITHM",0x03 }, - { 0x0167, "HFGEXECCHILD",0x03 }, - { 0x0168, "HFGEXECCHILD_98",0x03 }, - { 0x016a, "HFGEXECCHILD_PUSH1IND",0x03 }, - { 0x016d, "HFGEXECSIBLING",0x03 }, - { 0x016f, "HFGEXECSIBLING_298",0x03 }, - { 0x0170, "HFGEXECSIBLING_2IND1",0x03 }, - { 0x0173, "S16_CODECOUTPUTTASK",0x03 }, - { 0x018e, "#CODE_END",0x00 }, -}; /* cwcemb80 symbols */ - -static u32 cwcemb80_code[] = { -/* BEGINADDRESS */ -/* 0000 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 0002 */ 0x00001705,0x00001400,0x000a411e,0x00001003, -/* 0004 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 0006 */ 0x00009705,0x00001400,0x000a411e,0x00001003, -/* 0008 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 000A */ 0x00011705,0x00001400,0x000a411e,0x00001003, -/* 000C */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 000E */ 0x00019705,0x00001400,0x000a411e,0x00001003, -/* 0010 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 0012 */ 0x00021705,0x00001400,0x000a411e,0x00001003, -/* 0014 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 0016 */ 0x00029705,0x00001400,0x000a411e,0x00001003, -/* 0018 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 001A */ 0x00031705,0x00001400,0x000a411e,0x00001003, -/* 001C */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 001E */ 0x00039705,0x00001400,0x000a411e,0x00001003, -/* 0020 */ 0x000fe19e,0x00001003,0x0009c730,0x00001003, -/* 0022 */ 0x0008e19c,0x00001003,0x000083c1,0x00093040, -/* 0024 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 0026 */ 0x00009705,0x00001400,0x000a211e,0x00001003, -/* 0028 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 002A */ 0x00011705,0x00001400,0x000a211e,0x00001003, -/* 002C */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 002E */ 0x00019705,0x00001400,0x000a211e,0x00001003, -/* 0030 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 0032 */ 0x00021705,0x00001400,0x000a211e,0x00001003, -/* 0034 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 0036 */ 0x00029705,0x00001400,0x000a211e,0x00001003, -/* 0038 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 003A */ 0x00031705,0x00001400,0x000a211e,0x00001003, -/* 003C */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 003E */ 0x00039705,0x00001400,0x000a211e,0x00001003, -/* 0040 */ 0x0000a730,0x00001008,0x000e2730,0x00001002, -/* 0042 */ 0x0000a731,0x00001002,0x0000a731,0x00001002, -/* 0044 */ 0x0000a731,0x00001002,0x0000a731,0x00001002, -/* 0046 */ 0x0000a731,0x00001002,0x0000a731,0x00001002, -/* 0048 */ 0x00000000,0x00000000,0x000f619c,0x00001003, -/* 004A */ 0x0007f801,0x000c0000,0x00000037,0x00001000, -/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 004E */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0050 */ 0x00000000,0x000c0000,0x00000000,0x00000000, -/* 0052 */ 0x0000373c,0x00001000,0x00000000,0x00000000, -/* 0054 */ 0x000ee19c,0x00001003,0x0007f801,0x000c0000, -/* 0056 */ 0x00000037,0x00001000,0x00000000,0x00000000, -/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 005A */ 0x00000000,0x00000000,0x0000273c,0x00001000, -/* 005C */ 0x00000033,0x00001000,0x000e679e,0x00001003, -/* 005E */ 0x00007705,0x00001400,0x000ac71e,0x00001003, -/* 0060 */ 0x00087fc1,0x000c3be0,0x0007f801,0x000c0000, -/* 0062 */ 0x00000037,0x00001000,0x00000000,0x00000000, -/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0066 */ 0x00000000,0x00000000,0x0000a730,0x00001003, -/* 0068 */ 0x00000033,0x00001000,0x0007f801,0x000c0000, -/* 006A */ 0x00000037,0x00001000,0x00000000,0x00000000, -/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 006E */ 0x00000000,0x00000000,0x00000000,0x000c0000, -/* 0070 */ 0x00000032,0x00001000,0x0000273d,0x00001000, -/* 0072 */ 0x0004a730,0x00001003,0x00000f41,0x00097140, -/* 0074 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040, -/* 0076 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0, -/* 0078 */ 0x00000000,0x00000000,0x0001bf05,0x0003fc40, -/* 007A */ 0x00002725,0x000aa400,0x00013705,0x00093a00, -/* 007C */ 0x0000002e,0x0009d6c0,0x00038630,0x00001004, -/* 007E */ 0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000, -/* 0080 */ 0x00000000,0x000c70e0,0x0007d182,0x0002c640, -/* 0082 */ 0x00000630,0x00001004,0x000799b8,0x0002c6c0, -/* 0084 */ 0x00031705,0x00092240,0x00039f05,0x000932c0, -/* 0086 */ 0x0003520a,0x00000000,0x00040731,0x0000100b, -/* 0088 */ 0x00010705,0x000b20c0,0x00000000,0x000eba44, -/* 008A */ 0x00032108,0x000c60c4,0x00065208,0x000c2917, -/* 008C */ 0x000406b0,0x00001007,0x00012f05,0x00036880, -/* 008E */ 0x0002818e,0x000c0000,0x0004410a,0x00000000, -/* 0090 */ 0x00040630,0x00001007,0x00029705,0x000c0000, -/* 0092 */ 0x00000000,0x00000000,0x00003fc1,0x0003fc40, -/* 0094 */ 0x000037c1,0x00091b40,0x00003fc1,0x000911c0, -/* 0096 */ 0x000037c1,0x000957c0,0x00003fc1,0x000951c0, -/* 0098 */ 0x000037c1,0x00000000,0x00003fc1,0x000991c0, -/* 009A */ 0x000037c1,0x00000000,0x00003fc1,0x0009d1c0, -/* 009C */ 0x000037c1,0x00000000,0x0001ccc1,0x000915c0, -/* 009E */ 0x0001c441,0x0009d800,0x0009cdc1,0x00091240, -/* 00A0 */ 0x0001c541,0x00091d00,0x0009cfc1,0x00095240, -/* 00A2 */ 0x0001c741,0x00095c80,0x000e8ca9,0x00099240, -/* 00A4 */ 0x000e85ad,0x00095640,0x00069ca9,0x00099d80, -/* 00A6 */ 0x000e952d,0x00099640,0x000eaca9,0x0009d6c0, -/* 00A8 */ 0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80, -/* 00AA */ 0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0, -/* 00AC */ 0x000ec5ad,0x0009da40,0x000edca9,0x0009d300, -/* 00AE */ 0x000a6e0a,0x00001000,0x000ed52d,0x00091e40, -/* 00B0 */ 0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40, -/* 00B2 */ 0x0006fca9,0x00002500,0x000fb208,0x000c59a0, -/* 00B4 */ 0x000ef52d,0x0009de40,0x00068ca9,0x000912c1, -/* 00B6 */ 0x000683ad,0x00095241,0x00020f05,0x000991c1, -/* 00B8 */ 0x00000000,0x00000000,0x00086f88,0x00001000, -/* 00BA */ 0x0009cf81,0x000b5340,0x0009c701,0x000b92c0, -/* 00BC */ 0x0009de81,0x000bd300,0x0009d601,0x000b1700, -/* 00BE */ 0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0, -/* 00C0 */ 0x000a0f81,0x000bd740,0x00020701,0x000b5c80, -/* 00C2 */ 0x000a1681,0x000b97c0,0x00021601,0x00002500, -/* 00C4 */ 0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0, -/* 00C6 */ 0x00021681,0x00002d00,0x00020f81,0x000bd800, -/* 00C8 */ 0x000a0701,0x000b5bc0,0x00021601,0x00003500, -/* 00CA */ 0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0, -/* 00CC */ 0x00021681,0x00003d00,0x00020f81,0x000b1d00, -/* 00CE */ 0x000a0701,0x000b1fc0,0x00021601,0x00020500, -/* 00D0 */ 0x00020f81,0x000b1341,0x000a0701,0x000b9fc0, -/* 00D2 */ 0x00021681,0x00020d00,0x00020f81,0x000bde80, -/* 00D4 */ 0x000a0701,0x000bdfc0,0x00021601,0x00021500, -/* 00D6 */ 0x00020f81,0x000b9341,0x00020701,0x000b53c1, -/* 00D8 */ 0x00021681,0x00021d00,0x000a0f81,0x000d0380, -/* 00DA */ 0x0000b601,0x000b15c0,0x00007b01,0x00000000, -/* 00DC */ 0x00007b81,0x000bd1c0,0x00007b01,0x00000000, -/* 00DE */ 0x00007b81,0x000b91c0,0x00007b01,0x000b57c0, -/* 00E0 */ 0x00007b81,0x000b51c0,0x00007b01,0x000b1b40, -/* 00E2 */ 0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0, -/* 00E4 */ 0x0007e488,0x000d7e45,0x00000000,0x000d7a44, -/* 00E6 */ 0x0007e48a,0x00000000,0x00011f05,0x00084080, -/* 00E8 */ 0x00000000,0x00000000,0x00001705,0x000b3540, -/* 00EA */ 0x00008a01,0x000bf040,0x00007081,0x000bb5c0, -/* 00EC */ 0x00055488,0x00000000,0x0000d482,0x0003fc40, -/* 00EE */ 0x0003fc88,0x00000000,0x0001e401,0x000b3a00, -/* 00F0 */ 0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784, -/* 00F2 */ 0x000c86b0,0x00001007,0x00008281,0x000bb240, -/* 00F4 */ 0x0000b801,0x000b7140,0x00007888,0x00000000, -/* 00F6 */ 0x0000073c,0x00001000,0x0007f188,0x000c0000, -/* 00F8 */ 0x00000000,0x00000000,0x00055288,0x000c555c, -/* 00FA */ 0x0005528a,0x000c0000,0x0009fa88,0x000c5d00, -/* 00FC */ 0x0000fa88,0x00000000,0x00000032,0x00001000, -/* 00FE */ 0x0000073d,0x00001000,0x0007f188,0x000c0000, -/* 0100 */ 0x00000000,0x00000000,0x0008c01c,0x00001003, -/* 0102 */ 0x00002705,0x00001008,0x0008b201,0x000c1392, -/* 0104 */ 0x0000ba01,0x00000000, -/* TASKTREETHREAD */ -/* 0105 */ 0x00008731,0x00001400,0x0004c108,0x000fe0c4, -/* 0107 */ 0x00057488,0x00000000,0x000a6388,0x00001001, -/* 0109 */ 0x0008b334,0x000bc141,0x0003020e,0x00000000, -/* 010B */ 0x000886b0,0x00001008,0x00003625,0x000c5dfa, -/* 010D */ 0x000a638a,0x00001001,0x0008020e,0x00001002, -/* 010F */ 0x0008a6b0,0x00001008,0x0007f301,0x00000000, -/* 0111 */ 0x00000000,0x00000000,0x00002725,0x000a8c40, -/* 0113 */ 0x000000ae,0x00000000,0x000d8630,0x00001008, -/* 0115 */ 0x00000000,0x000c74e0,0x0007d182,0x0002d640, -/* 0117 */ 0x000a8630,0x00001008,0x000799b8,0x0002d6c0, -/* 0119 */ 0x0000748a,0x000c3ec5,0x0007420a,0x000c0000, -/* 011B */ 0x00062208,0x000c4117,0x00070630,0x00001009, -/* 011D */ 0x00000000,0x000c0000,0x0001022e,0x00000000, -/* 011F */ 0x0003a630,0x00001009,0x00000000,0x000c0000, -/* 0121 */ 0x00000036,0x00001000,0x00000000,0x00000000, -/* 0123 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0125 */ 0x00000000,0x00000000,0x0002a730,0x00001008, -/* 0127 */ 0x0007f801,0x000c0000,0x00000037,0x00001000, -/* 0129 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 012B */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 012D */ 0x0002a730,0x00001008,0x00000033,0x00001000, -/* 012F */ 0x0002a705,0x00001008,0x00007a01,0x000c0000, -/* 0131 */ 0x000e6288,0x000d550a,0x0006428a,0x00000000, -/* 0133 */ 0x00060730,0x0000100a,0x00000000,0x000c0000, -/* 0135 */ 0x00000000,0x00000000, -/* TASKTREEHEADERCODE */ -/* 0136 */ 0x0007aab0,0x00034880,0x00078fb0,0x0000100b, -/* 0138 */ 0x00057488,0x00000000,0x00033b94,0x00081140, -/* 013A */ 0x000183ae,0x00000000,0x000786b0,0x0000100b, -/* 013C */ 0x00022f05,0x000c3545,0x0000eb8a,0x00000000, -/* 013E */ 0x00042731,0x00001003, -/* FGTASKTREEHEADERCODE */ -/* 013F */ 0x0007aab0,0x00034880,0x00048fb0,0x0000100a, -/* 0141 */ 0x00057488,0x00000000,0x00033b94,0x00081140, -/* 0143 */ 0x000183ae,0x00000000,0x000806b0,0x0000100b, -/* 0145 */ 0x00022f05,0x00000000,0x00007401,0x00091140, -/* 0147 */ 0x00048f05,0x000951c0,0x00042731,0x00001003, -/* 0149 */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47, -/* 014B */ 0x00080000,0x000bffc7,0x000fe19e,0x00001003, -/* 014D */ 0x00000000,0x00000000,0x0008e19c,0x00001003, -/* 014F */ 0x000083c1,0x00093040,0x00000f41,0x00097140, -/* 0151 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040, -/* 0153 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0, -/* 0155 */ 0x00000000,0x000fdc44,0x00055208,0x00000000, -/* 0157 */ 0x00010705,0x000a2880,0x0000a23a,0x00093a00, -/* 0159 */ 0x0003fc8a,0x000df6c5,0x0004ef0a,0x000c0000, -/* 015B */ 0x00012f05,0x00036880,0x00065308,0x000c2997, -/* 015D */ 0x000d86b0,0x0000100a,0x0004410a,0x000d40c7, -/* 015F */ 0x00000000,0x00000000,0x00080730,0x00001004, -/* 0161 */ 0x00056f0a,0x000ea105,0x00000000,0x00000000, -/* NULLALGORITHM */ -/* 0163 */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47, -/* 0165 */ 0x00080000,0x000bffc7,0x0000273d,0x00001000, -/* HFGEXECCHILD */ -/* 0167 */ 0x00000000,0x000eba44, -/* HFGEXECCHILD_98 */ -/* 0168 */ 0x00048f05,0x0000f440,0x00007401,0x0000f7c0, -/* HFGEXECCHILD_PUSH1IND */ -/* 016A */ 0x00000734,0x00001000,0x00010705,0x000a6880, -/* 016C */ 0x00006a88,0x000c75c4, -/* HFGEXECSIBLING */ -/* 016D */ 0x00000000,0x000e5084,0x00000000,0x000eba44, -/* HFGEXECSIBLING_298 */ -/* 016F */ 0x00087401,0x000e4782, -/* HFGEXECSIBLING_2IND1 */ -/* 0170 */ 0x00000734,0x00001000,0x00010705,0x000a6880, -/* 0172 */ 0x00006a88,0x000c75c4, -/* S16_CODECOUTPUTTASK */ -/* 0173 */ 0x0007c108,0x000c0000,0x0007e721,0x000bed40, -/* 0175 */ 0x00005f25,0x000badc0,0x0003ba97,0x000beb80, -/* 0177 */ 0x00065590,0x000b2e00,0x00033217,0x00003ec0, -/* 0179 */ 0x00065590,0x000b8e40,0x0003ed80,0x000491c0, -/* 017B */ 0x00073fb0,0x00074c80,0x000283a0,0x0000100c, -/* 017D */ 0x000ee388,0x00042970,0x00008301,0x00021ef2, -/* 017F */ 0x000b8f14,0x0000000f,0x000c4d8d,0x0000001b, -/* 0181 */ 0x000d6dc2,0x000e06c6,0x000032ac,0x000c3916, -/* 0183 */ 0x0004edc2,0x00074c80,0x00078898,0x00001000, -/* 0185 */ 0x00038894,0x00000032,0x000c4d8d,0x00092e1b, -/* 0187 */ 0x000d6dc2,0x000e06c6,0x0004edc2,0x000c1956, -/* 0189 */ 0x0000722c,0x00034a00,0x00041705,0x0009ed40, -/* 018B */ 0x00058730,0x00001400,0x000d7488,0x000c3a00, -/* 018D */ 0x00048f05,0x00000000 -}; -/* #CODE_END */ - -static u32 cwcemb80_parameter[] = { -/* 0000 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0004 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0008 */ 0x00000000,0x00000000,0x00000163,0x00000000, -/* 000C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0010 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0014 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0018 */ 0x00000000,0x00200040,0x00008010,0x00000000, -/* 001C */ 0x00000000,0x80000001,0x00000001,0x00060000, -/* 0020 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0024 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0028 */ 0x00000000,0x00900080,0x00000173,0x00000000, -/* 002C */ 0x00000000,0x00000010,0x00800000,0x00900000, -/* 0030 */ 0xf2c0000f,0x00000200,0x00000000,0x00010600, -/* 0034 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0038 */ 0x00000000,0x00000000,0x00000163,0x330300c2, -/* 003C */ 0x06000000,0x00000000,0x80008000,0x80008000, -/* 0040 */ 0x3fc0000f,0x00000301,0x00010400,0x00000000, -/* 0044 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0048 */ 0x00000000,0x00b00000,0x00d0806d,0x330480c3, -/* 004C */ 0x04800000,0x00000001,0x00800001,0x0000ffff, -/* 0050 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0054 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 005C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0060 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0068 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0070 */ 0x066a0600,0x06350070,0x0000929d,0x929d929d, -/* 0074 */ 0x00000000,0x0000735a,0x00000600,0x00000000, -/* 0078 */ 0x929d735a,0x00000000,0x00010000,0x735a735a, -/* 007C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0080 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0084 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0088 */ 0x00000000,0x00000000,0x0000804f,0x000000c3, -/* 008C */ 0x05000000,0x00a00010,0x00000000,0x80008000, -/* 0090 */ 0x00000000,0x00000000,0x00000700,0x00000000, -/* 0094 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0098 */ 0x00000080,0x00a00000,0x0000809a,0x000000c2, -/* 009C */ 0x07400000,0x00000000,0x80008000,0xffffffff, -/* 00A0 */ 0x00c80028,0x00005555,0x00000000,0x000107a0, -/* 00A4 */ 0x00c80028,0x000000c2,0x06800000,0x00000000, -/* 00A8 */ 0x06e00080,0x00300000,0x000080bb,0x000000c9, -/* 00AC */ 0x07a00000,0x04000000,0x80008000,0xffffffff, -/* 00B0 */ 0x00c80028,0x00005555,0x00000000,0x00000780, -/* 00B4 */ 0x00c80028,0x000000c5,0xff800000,0x00000000, -/* 00B8 */ 0x00640080,0x00c00000,0x00008197,0x000000c9, -/* 00BC */ 0x07800000,0x04000000,0x80008000,0xffffffff, -/* 00C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00C8 */ 0x00000000,0x00000000,0x0000805e,0x000000c1, -/* 00CC */ 0x00000000,0x00800000,0x80008000,0x80008000, -/* 00D0 */ 0x00020000,0x0000ffff,0x00000000,0x00000000, -/* 00D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0100 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0104 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0108 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 010C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0110 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0114 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0118 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 011C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0120 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0124 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0128 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 012C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0130 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0134 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0138 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 013C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0140 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0144 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0148 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 014C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0150 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0154 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0158 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 015C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0160 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0164 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0168 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 016C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0170 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0174 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0178 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 017C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0180 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0184 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0188 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 018C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0190 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0194 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0198 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 019C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0200 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0204 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0208 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 020C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0210 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0214 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0218 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 021C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0220 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0224 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0228 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 022C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0230 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0234 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0238 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 023C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0240 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0244 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0248 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 024C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0250 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0254 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0258 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 025C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0260 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0264 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0268 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 026C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0270 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0274 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0278 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 027C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0280 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0284 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0288 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 028C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0290 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0294 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0298 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 029C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0300 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0304 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0308 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 030C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0310 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0314 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0318 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 031C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0320 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0324 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0328 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 032C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0330 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0334 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0338 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 033C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0340 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0344 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0348 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 034C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0350 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0354 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0358 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 035C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0360 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0364 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0368 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 036C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0370 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0374 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0378 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 037C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0380 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0384 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0388 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 038C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0390 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0394 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0398 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 039C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0400 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0404 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0408 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 040C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0410 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0414 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0418 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 041C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0420 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0424 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0428 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 042C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0430 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0434 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0438 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 043C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0440 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0444 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0448 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 044C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0450 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0454 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0458 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 045C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0460 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0464 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0468 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 046C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0470 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0474 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0478 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 047C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0480 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0484 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0488 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 048C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0490 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0494 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0498 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 049C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0500 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0504 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0508 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 050C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0510 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0514 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0518 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 051C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0520 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0524 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0528 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 052C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0530 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0534 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0538 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 053C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0540 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0544 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0548 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 054C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0550 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0554 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0558 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 055C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0560 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0564 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0568 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 056C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0570 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0574 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0578 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 057C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0580 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0584 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0588 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 058C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0590 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0594 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0598 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 059C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0600 */ 0x929d0600,0x929d929d,0x929d929d,0x929d0000, -/* 0604 */ 0x929d929d,0x929d929d,0x929d929d,0x929d929d, -/* 0608 */ 0x929d929d,0x00100635,0x060b013f,0x00000004, -/* 060C */ 0x00000001,0x007a0002,0x00000000,0x066e0610, -/* 0610 */ 0x0105929d,0x929d929d,0x929d929d,0x929d929d, -/* 0614 */ 0x929d929d,0xa431ac75,0x0001735a,0xa431ac75, -/* 0618 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 061C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0620 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0624 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0628 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 062C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0630 */ 0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051, -/* 0634 */ 0x00000000,0x929d929d,0x929d929d,0x929d929d, -/* 0638 */ 0x929d929d,0x929d929d,0x929d929d,0x929d929d, -/* 063C */ 0x929d929d,0x929d929d,0x00000000,0x06400136, -/* 0640 */ 0x0000270f,0x00010000,0x007a0000,0x00000000, -/* 0644 */ 0x068e0645,0x0105929d,0x929d929d,0x929d929d, -/* 0648 */ 0x929d929d,0x929d929d,0xa431ac75,0x0001735a, -/* 064C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0650 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0654 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0658 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 065C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0660 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0664 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -/* 0668 */ 0x735a0100,0x00000000,0x00000000,0x00000000, -/* 066C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0670 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0674 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0678 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 067C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0680 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0684 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0688 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 068C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0690 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0694 */ 0x00000000,0x00000000,0x00000000 -}; /* #PARAMETER_END */ - -static u32 cwcemb80_sample[] = { -/* 0000 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0004 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0008 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 000C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0010 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0014 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0018 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 001C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0020 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0024 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0028 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 002C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0030 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0034 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0038 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 003C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0040 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0044 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0048 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0050 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0054 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 005C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0060 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0068 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0070 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0074 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0078 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 007C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0080 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0084 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0088 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 008C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0090 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0094 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0098 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 009C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 00FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0100 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0104 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0108 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 010C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0110 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0114 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0118 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 011C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0120 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0124 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0128 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 012C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0130 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0134 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0138 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 013C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0140 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0144 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0148 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 014C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0150 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0154 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0158 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 015C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0160 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0164 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0168 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 016C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0170 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0174 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0178 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 017C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0180 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0184 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0188 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 018C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0190 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0194 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0198 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 019C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 01FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0200 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0204 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0208 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 020C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0210 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0214 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0218 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 021C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0220 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0224 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0228 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 022C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0230 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0234 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0238 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 023C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0240 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0244 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0248 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 024C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0250 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0254 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0258 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 025C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0260 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0264 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0268 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 026C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0270 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0274 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0278 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 027C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0280 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0284 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0288 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 028C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0290 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0294 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0298 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 029C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 02FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0300 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0304 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0308 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 030C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0310 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0314 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0318 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 031C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0320 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0324 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0328 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 032C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0330 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0334 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0338 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 033C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0340 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0344 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0348 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 034C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0350 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0354 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0358 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 035C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0360 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0364 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0368 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 036C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0370 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0374 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0378 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 037C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0380 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0384 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0388 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 038C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0390 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0394 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0398 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 039C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 03FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0400 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0404 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0408 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 040C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0410 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0414 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0418 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 041C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0420 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0424 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0428 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 042C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0430 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0434 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0438 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 043C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0440 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0444 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0448 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 044C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0450 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0454 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0458 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 045C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0460 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0464 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0468 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 046C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0470 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0474 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0478 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 047C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0480 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0484 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0488 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 048C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0490 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0494 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0498 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 049C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 04FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0500 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0504 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0508 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 050C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0510 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0514 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0518 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 051C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0520 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0524 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0528 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 052C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0530 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0534 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0538 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 053C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0540 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0544 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0548 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 054C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0550 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0554 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0558 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 055C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0560 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0564 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0568 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 056C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0570 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0574 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0578 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 057C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0580 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0584 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0588 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 058C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0590 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0594 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0598 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 059C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 05FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0600 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0604 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0608 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 060C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0610 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0614 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0618 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 061C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0620 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0624 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0628 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 062C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0630 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0634 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0638 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 063C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0640 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0644 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0648 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 064C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0650 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0654 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0658 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 065C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0660 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0664 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0668 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 066C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0670 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0674 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0678 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 067C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0680 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0684 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0688 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 068C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0690 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0694 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0698 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 069C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 06FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0700 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0704 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0708 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 070C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0710 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0714 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0718 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 071C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0720 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0724 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0728 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 072C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0730 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0734 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0738 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 073C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0740 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0744 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0748 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 074C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0750 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0754 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0758 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 075C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0760 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0764 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0768 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 076C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0770 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0774 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0778 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 077C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0780 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0784 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0788 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 078C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0790 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0794 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0798 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 079C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 07FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0800 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0804 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0808 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 080C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0810 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0814 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0818 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 081C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0820 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0824 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0828 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 082C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0830 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0834 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0838 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 083C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0840 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0844 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0848 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 084C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0850 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0854 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0858 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 085C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0860 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0864 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0868 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 086C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0870 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0874 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0878 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 087C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0880 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0884 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0888 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 088C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0890 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0894 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0898 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 089C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 08FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0900 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0904 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0908 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 090C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0910 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0914 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0918 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 091C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0920 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0924 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0928 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 092C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0930 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0934 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0938 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 093C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0940 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0944 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0948 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 094C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0950 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0954 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0958 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 095C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0960 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0964 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0968 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 096C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0970 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0974 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0978 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 097C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0980 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0984 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0988 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 098C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0990 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0994 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0998 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 099C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09A0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09A4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09A8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09AC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09B0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09B4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09B8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09BC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09C0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09C4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09C8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09CC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09D0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09D4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09D8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09DC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09E0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09E4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09E8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09EC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09F0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09F4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09F8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 09FC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A00 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A04 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A08 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A0C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A10 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A14 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A18 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A1C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A20 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A24 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A28 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A2C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A30 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A34 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A38 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A3C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A40 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A44 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A48 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A4C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A50 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A54 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A58 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A5C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A60 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A64 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A68 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A6C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A70 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A74 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A78 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A7C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A80 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A84 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A88 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A8C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A90 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A94 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A98 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0A9C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AA0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AA4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AA8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AAC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AB0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AB4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AB8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0ABC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AC0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AC4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AC8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0ACC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AD0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AD4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AD8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0ADC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AE0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AE4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AE8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AEC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AF0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AF4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AF8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0AFC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B00 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B04 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B08 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B0C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B10 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B14 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B18 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B1C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B20 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B24 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B28 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B2C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B30 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B34 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B38 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B3C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B40 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B44 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B48 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B4C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B50 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B54 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B58 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B5C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B60 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B64 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B68 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B6C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B70 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B74 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B78 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B7C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B80 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B84 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B88 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B8C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B90 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B94 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B98 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0B9C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BA0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BA4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BA8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BAC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BB0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BB4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BB8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BBC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BC0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BC4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BC8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BCC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BD0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BD4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BD8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BDC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BE0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BE4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BE8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BEC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BF0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BF4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BF8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0BFC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C00 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C04 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C08 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C0C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C10 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C14 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C18 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C1C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C20 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C24 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C28 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C2C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C30 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C34 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C38 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C3C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C40 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C44 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C48 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C4C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C50 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C54 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C58 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C5C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C60 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C64 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C68 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C6C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C70 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C74 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C78 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C7C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C80 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C84 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C88 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C8C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C90 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C94 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C98 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0C9C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CA0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CA4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CA8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CAC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CB0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CB4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CB8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CBC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CC0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CC4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CC8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CCC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CD0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CD4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CD8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CDC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CE0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CE4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CE8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CEC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CF0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CF4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CF8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0CFC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D00 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D04 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D08 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D0C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D10 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D14 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D18 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D1C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D20 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D24 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D28 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D2C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D30 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D34 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D38 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D3C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D40 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D44 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D48 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D4C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D50 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D54 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D58 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D5C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D60 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D64 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D68 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D6C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D70 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D74 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D78 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D7C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D80 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D84 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D88 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D8C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D90 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D94 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D98 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0D9C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DA0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DA4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DA8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DAC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DB0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DB4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DB8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DBC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DC0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DC4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DC8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DCC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DD0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DD4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DD8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DDC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DE0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DE4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DE8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DEC */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DF0 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DF4 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DF8 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0DFC */ 0x00000000,0x00000000,0x00000000,0x00010004 -}; /* #SAMPLE_END */ - - -static struct dsp_segment_desc cwcemb80_segments[] = { - { SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000031c, cwcemb80_code }, - { SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000697, cwcemb80_parameter }, - { SEGTYPE_SP_SAMPLE, 0x00000000, 0x00000e00, cwcemb80_sample }, -}; - -static struct dsp_module_desc cwcemb80_module = { - "cwcemb80", - { - 38, - cwcemb80_symbols - }, - 3, - cwcemb80_segments, -}; - -#endif /* __HEADER_cwcemb80_H__ */ diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c index 8e7fe033270f..87078d3a6854 100644 --- a/sound/pci/echoaudio/darla20.c +++ b/sound/pci/echoaudio/darla20.c @@ -56,6 +56,8 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/darla20_dsp.fw"); + #define FW_DARLA20_DSP 0 static const struct firmware card_fw[] = { diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c index a13c623eb999..42b48f9d2128 100644 --- a/sound/pci/echoaudio/darla24.c +++ b/sound/pci/echoaudio/darla24.c @@ -60,6 +60,8 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/darla24_dsp.fw"); + #define FW_DARLA24_DSP 0 static const struct firmware card_fw[] = { diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c index 8fb15823aca5..8dbb7ac865c1 100644 --- a/sound/pci/echoaudio/echo3g.c +++ b/sound/pci/echoaudio/echo3g.c @@ -68,6 +68,10 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/echo3g_dsp.fw"); +MODULE_FIRMWARE("ea/3g_asic.fw"); + #define FW_361_LOADER 0 #define FW_ECHO3G_DSP 1 #define FW_3G_ASIC 2 diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index e413da00759b..f27b6a733b96 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -705,11 +705,9 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct audiopipe *pipe = runtime->private_data; int i, err; u32 channelmask = 0; - struct list_head *pos; struct snd_pcm_substream *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { for (i = 0; i < DSP_MAXPIPES; i++) { if (s == chip->substream[i]) { channelmask |= 1 << i; diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c index 9f439ea459f4..52a933189576 100644 --- a/sound/pci/echoaudio/echoaudio_3g.c +++ b/sound/pci/echoaudio/echoaudio_3g.c @@ -233,8 +233,8 @@ static int load_asic(struct echoaudio *chip) chip->asic_code = &card_fw[FW_3G_ASIC]; - /* Now give the new ASIC a little time to set up */ - mdelay(2); + /* Now give the new ASIC some time to set up */ + msleep(1000); /* See if it worked */ box_type = check_asic_status(chip); diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c index af4d32026e4a..fee2d4831732 100644 --- a/sound/pci/echoaudio/gina20.c +++ b/sound/pci/echoaudio/gina20.c @@ -60,6 +60,8 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/gina20_dsp.fw"); + #define FW_GINA20_DSP 0 static const struct firmware card_fw[] = { diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c index 9ff454a947ed..d5eae470fe9a 100644 --- a/sound/pci/echoaudio/gina24.c +++ b/sound/pci/echoaudio/gina24.c @@ -66,6 +66,12 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/gina24_301_dsp.fw"); +MODULE_FIRMWARE("ea/gina24_361_dsp.fw"); +MODULE_FIRMWARE("ea/gina24_301_asic.fw"); +MODULE_FIRMWARE("ea/gina24_361_asic.fw"); + #define FW_361_LOADER 0 #define FW_GINA24_301_DSP 1 #define FW_GINA24_361_DSP 2 diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c index 37eb726fd03d..40f601cd016f 100644 --- a/sound/pci/echoaudio/indigo.c +++ b/sound/pci/echoaudio/indigo.c @@ -58,6 +58,9 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/indigo_dsp.fw"); + #define FW_361_LOADER 0 #define FW_INDIGO_DSP 1 diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c index dc8b91824181..771c5383210d 100644 --- a/sound/pci/echoaudio/indigodj.c +++ b/sound/pci/echoaudio/indigodj.c @@ -58,6 +58,9 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/indigo_dj_dsp.fw"); + #define FW_361_LOADER 0 #define FW_INDIGO_DJ_DSP 1 diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c index eadf3263453a..49c550defcf9 100644 --- a/sound/pci/echoaudio/indigoio.c +++ b/sound/pci/echoaudio/indigoio.c @@ -59,6 +59,9 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/indigo_io_dsp.fw"); + #define FW_361_LOADER 0 #define FW_INDIGO_IO_DSP 1 diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c index 6cede497579e..8f5483a405ae 100644 --- a/sound/pci/echoaudio/layla20.c +++ b/sound/pci/echoaudio/layla20.c @@ -66,6 +66,9 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/layla20_dsp.fw"); +MODULE_FIRMWARE("ea/layla20_asic.fw"); + #define FW_LAYLA20_DSP 0 #define FW_LAYLA20_ASIC 1 diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c index 44f735426aa0..0524667c02f7 100644 --- a/sound/pci/echoaudio/layla24.c +++ b/sound/pci/echoaudio/layla24.c @@ -68,6 +68,12 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/layla24_dsp.fw"); +MODULE_FIRMWARE("ea/layla24_1_asic.fw"); +MODULE_FIRMWARE("ea/layla24_2A_asic.fw"); +MODULE_FIRMWARE("ea/layla24_2S_asic.fw"); + #define FW_361_LOADER 0 #define FW_LAYLA24_DSP 1 #define FW_LAYLA24_1_ASIC 2 diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c index dc172d03ac3f..893c7c20dd70 100644 --- a/sound/pci/echoaudio/mia.c +++ b/sound/pci/echoaudio/mia.c @@ -66,6 +66,9 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/mia_dsp.fw"); + #define FW_361_LOADER 0 #define FW_MIA_DSP 1 diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c index c856ed50dd9a..3a5d5b0020df 100644 --- a/sound/pci/echoaudio/mona.c +++ b/sound/pci/echoaudio/mona.c @@ -64,6 +64,15 @@ #include <asm/atomic.h> #include "echoaudio.h" +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/mona_301_dsp.fw"); +MODULE_FIRMWARE("ea/mona_361_dsp.fw"); +MODULE_FIRMWARE("ea/mona_301_1_asic_48.fw"); +MODULE_FIRMWARE("ea/mona_301_1_asic_96.fw"); +MODULE_FIRMWARE("ea/mona_361_1_asic_48.fw"); +MODULE_FIRMWARE("ea/mona_361_1_asic_96.fw"); +MODULE_FIRMWARE("ea/mona_2_asic.fw"); + #define FW_361_LOADER 0 #define FW_MONA_301_DSP 1 #define FW_MONA_361_DSP 2 diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 80aa585eade4..dbc805c33fc4 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -49,6 +49,13 @@ #include "p17v.h" +#define HANA_FILENAME "emu/hana.fw" +#define DOCK_FILENAME "emu/audio_dock.fw" + +MODULE_FIRMWARE(HANA_FILENAME); +MODULE_FIRMWARE(DOCK_FILENAME); + + /************************************************************************* * EMU10K1 init / done *************************************************************************/ @@ -693,8 +700,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) int tmp,tmp2; int reg; int err; - const char *hana_filename = "emu/hana.fw"; - const char *dock_filename = "emu/audio_dock.fw"; snd_printk(KERN_INFO "emu1010: Special config.\n"); /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, @@ -735,8 +740,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) return -ENODEV; } snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg); - if ((err = snd_emu1010_load_firmware(emu, hana_filename)) != 0) { - snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", hana_filename); + if ((err = snd_emu1010_load_firmware(emu, HANA_FILENAME)) != 0) { + snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", HANA_FILENAME); return err; } @@ -938,7 +943,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) /* Return to Audio Dock programming mode */ snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); - if ((err = snd_emu1010_load_firmware(emu, dock_filename)) != 0) { + if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { return err; } snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); @@ -1216,6 +1221,15 @@ static struct snd_emu_chip_details emu_chip_details[] = { .spi_dac = 1, .i2c_adc = 1, .spk71 = 1} , + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, + .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", + .id = "EMU1010", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .ca_cardbus_chip = 1, + .spi_dac = 1, + .i2c_adc = 1, + .spk71 = 1} , {.vendor = 0x1102, .device = 0x0008, .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", .id = "Audigy2", diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 465f8d505329..7ee19c63c2c8 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -433,7 +433,6 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, struct snd_emu10k1_pcm *epcm; int channel; int result = 0; - struct list_head *pos; struct snd_pcm_substream *s; u32 basic = 0; u32 inte = 0; @@ -448,8 +447,7 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, running = 0; break; } - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { runtime = s->runtime; epcm = runtime->private_data; channel = substream->pcm->device-emu->p16v_device_offset; diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 425b167522d5..6a0ddcf00884 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -798,10 +798,8 @@ static int snd_ensoniq_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: { unsigned int what = 0; - struct list_head *pos; struct snd_pcm_substream *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == ensoniq->playback1_substream) { what |= ES_P1_PAUSE; snd_pcm_trigger_done(s, substream); @@ -824,10 +822,8 @@ static int snd_ensoniq_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_STOP: { unsigned int what = 0; - struct list_head *pos; struct snd_pcm_substream *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == ensoniq->playback1_substream) { what |= ES_DAC1_EN; snd_pcm_trigger_done(s, substream); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index dc84c189b05f..2faf009076bb 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -1554,10 +1554,7 @@ static int snd_es1968_playback_open(struct snd_pcm_substream *substream) runtime->hw = snd_es1968_playback; runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = calc_available_memory_size(chip); -#if 0 - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - 1024); -#endif + spin_lock_irq(&chip->substream_lock); list_add(&es->list, &chip->substream_list); spin_unlock_irq(&chip->substream_lock); @@ -1613,10 +1610,8 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream) runtime->hw = snd_es1968_capture; runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = calc_available_memory_size(chip) - 1024; /* keep MIXBUF size */ -#if 0 - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - 1024); -#endif + snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES); + spin_lock_irq(&chip->substream_lock); list_add(&es->list, &chip->substream_list); spin_unlock_irq(&chip->substream_lock); diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 60d7b05a204a..b2484bbdcc1d 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -1,5 +1,8 @@ snd-hda-intel-objs := hda_intel.o -snd-hda-codec-objs := hda_codec.o \ +# since snd-hda-intel is the only driver using hda-codec, +# merge it into a single module although it was originally +# designed to be individual modules +snd-hda-intel-objs += hda_codec.o \ hda_generic.o \ patch_realtek.o \ patch_cmedia.o \ @@ -10,7 +13,7 @@ snd-hda-codec-objs := hda_codec.o \ patch_conexant.o \ patch_via.o ifdef CONFIG_PROC_FS -snd-hda-codec-objs += hda_proc.o +snd-hda-intel-objs += hda_proc.o endif -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o snd-hda-codec.o +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 8f34fb447983..14649d54b493 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -24,7 +24,6 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/pci.h> -#include <linux/moduleparam.h> #include <linux/mutex.h> #include <sound/core.h> #include "hda_codec.h" @@ -34,11 +33,6 @@ #include "hda_local.h" -MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); -MODULE_DESCRIPTION("Universal interface for High Definition Audio Codec"); -MODULE_LICENSE("GPL"); - - /* * vendor / preset table */ @@ -77,12 +71,13 @@ static struct hda_vendor_id hda_vendor_ids[] = { * * Returns the obtained response value, or -1 for an error. */ -unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct, +unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, + int direct, unsigned int verb, unsigned int parm) { unsigned int res; mutex_lock(&codec->bus->cmd_mutex); - if (! codec->bus->ops.command(codec, nid, direct, verb, parm)) + if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) res = codec->bus->ops.get_response(codec); else res = (unsigned int)-1; @@ -90,8 +85,6 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int dire return res; } -EXPORT_SYMBOL(snd_hda_codec_read); - /** * snd_hda_codec_write - send a single command without waiting for response * @codec: the HDA codec @@ -114,8 +107,6 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, return err; } -EXPORT_SYMBOL(snd_hda_codec_write); - /** * snd_hda_sequence_write - sequence writes * @codec: the HDA codec @@ -130,8 +121,6 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq) snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); } -EXPORT_SYMBOL(snd_hda_sequence_write); - /** * snd_hda_get_sub_nodes - get the range of sub nodes * @codec: the HDA codec @@ -141,7 +130,8 @@ EXPORT_SYMBOL(snd_hda_sequence_write); * Parse the NID and store the start NID of its sub-nodes. * Returns the number of sub-nodes. */ -int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id) +int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, + hda_nid_t *start_id) { unsigned int parm; @@ -150,8 +140,6 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *sta return (int)(parm & 0x7fff); } -EXPORT_SYMBOL(snd_hda_get_sub_nodes); - /** * snd_hda_get_connections - get connection list * @codec: the HDA codec @@ -187,12 +175,13 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, conn_len = parm & AC_CLIST_LENGTH; mask = (1 << (shift-1)) - 1; - if (! conn_len) + if (!conn_len) return 0; /* no connection */ if (conn_len == 1) { /* single connection */ - parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, 0); + parm = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_CONNECT_LIST, 0); conn_list[0] = parm & mask; return 1; } @@ -207,18 +196,21 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, if (i % num_elems == 0) parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, i); - range_val = !! (parm & (1 << (shift-1))); /* ranges */ + range_val = !!(parm & (1 << (shift-1))); /* ranges */ val = parm & mask; parm >>= shift; if (range_val) { /* ranges between the previous and this one */ - if (! prev_nid || prev_nid >= val) { - snd_printk(KERN_WARNING "hda_codec: invalid dep_range_val %x:%x\n", prev_nid, val); + if (!prev_nid || prev_nid >= val) { + snd_printk(KERN_WARNING "hda_codec: " + "invalid dep_range_val %x:%x\n", + prev_nid, val); continue; } for (n = prev_nid + 1; n <= val; n++) { if (conns >= max_conns) { - snd_printk(KERN_ERR "Too many connections\n"); + snd_printk(KERN_ERR + "Too many connections\n"); return -EINVAL; } conn_list[conns++] = n; @@ -253,7 +245,8 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) struct hda_bus_unsolicited *unsol; unsigned int wp; - if ((unsol = bus->unsol) == NULL) + unsol = bus->unsol; + if (!unsol) return 0; wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE; @@ -268,8 +261,6 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) return 0; } -EXPORT_SYMBOL(snd_hda_queue_unsol_event); - /* * process queueud unsolicited events */ @@ -287,7 +278,7 @@ static void process_unsol_events(struct work_struct *work) rp <<= 1; res = unsol->queue[rp]; caddr = unsol->queue[rp + 1]; - if (! (caddr & (1 << 4))) /* no unsolicited event? */ + if (!(caddr & (1 << 4))) /* no unsolicited event? */ continue; codec = bus->caddr_tbl[caddr & 0x0f]; if (codec && codec->patch_ops.unsol_event) @@ -298,7 +289,7 @@ static void process_unsol_events(struct work_struct *work) /* * initialize unsolicited queue */ -static int init_unsol_queue(struct hda_bus *bus) +static int __devinit init_unsol_queue(struct hda_bus *bus) { struct hda_bus_unsolicited *unsol; @@ -306,8 +297,9 @@ static int init_unsol_queue(struct hda_bus *bus) return 0; unsol = kzalloc(sizeof(*unsol), GFP_KERNEL); - if (! unsol) { - snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n"); + if (!unsol) { + snd_printk(KERN_ERR "hda_codec: " + "can't allocate unsolicited queue\n"); return -ENOMEM; } INIT_WORK(&unsol->work, process_unsol_events); @@ -323,16 +315,15 @@ static void snd_hda_codec_free(struct hda_codec *codec); static int snd_hda_bus_free(struct hda_bus *bus) { - struct list_head *p, *n; + struct hda_codec *codec, *n; - if (! bus) + if (!bus) return 0; if (bus->unsol) { flush_scheduled_work(); kfree(bus->unsol); } - list_for_each_safe(p, n, &bus->codec_list) { - struct hda_codec *codec = list_entry(p, struct hda_codec, list); + list_for_each_entry_safe(codec, n, &bus->codec_list, list) { snd_hda_codec_free(codec); } if (bus->ops.private_free) @@ -355,8 +346,9 @@ static int snd_hda_bus_dev_free(struct snd_device *device) * * Returns 0 if successful, or a negative error code. */ -int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, - struct hda_bus **busp) +int __devinit snd_hda_bus_new(struct snd_card *card, + const struct hda_bus_template *temp, + struct hda_bus **busp) { struct hda_bus *bus; int err; @@ -385,7 +377,8 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, mutex_init(&bus->cmd_mutex); INIT_LIST_HEAD(&bus->codec_list); - if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); + if (err < 0) { snd_hda_bus_free(bus); return err; } @@ -394,22 +387,24 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, return 0; } -EXPORT_SYMBOL(snd_hda_bus_new); - /* * find a matching codec preset */ -static const struct hda_codec_preset *find_codec_preset(struct hda_codec *codec) +static const struct hda_codec_preset __devinit * +find_codec_preset(struct hda_codec *codec) { const struct hda_codec_preset **tbl, *preset; + if (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) + return NULL; /* use the generic parser */ + for (tbl = hda_preset_tables; *tbl; tbl++) { for (preset = *tbl; preset->id; preset++) { u32 mask = preset->mask; - if (! mask) + if (!mask) mask = ~0; if (preset->id == (codec->vendor_id & mask) && - (! preset->rev || + (!preset->rev || preset->rev == codec->revision_id)) return preset; } @@ -434,27 +429,30 @@ void snd_hda_get_codec_name(struct hda_codec *codec, break; } } - if (! vendor) { + if (!vendor) { sprintf(tmp, "Generic %04x", vendor_id); vendor = tmp; } if (codec->preset && codec->preset->name) snprintf(name, namelen, "%s %s", vendor, codec->preset->name); else - snprintf(name, namelen, "%s ID %x", vendor, codec->vendor_id & 0xffff); + snprintf(name, namelen, "%s ID %x", vendor, + codec->vendor_id & 0xffff); } /* * look for an AFG and MFG nodes */ -static void setup_fg_nodes(struct hda_codec *codec) +static void __devinit setup_fg_nodes(struct hda_codec *codec) { int i, total_nodes; hda_nid_t nid; total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); for (i = 0; i < total_nodes; i++, nid++) { - switch((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff)) { + unsigned int func; + func = snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE); + switch (func & 0xff) { case AC_GRP_AUDIO_FUNCTION: codec->afg = nid; break; @@ -478,7 +476,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node, &codec->start_nid); codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL); - if (! codec->wcaps) + if (!codec->wcaps) return -ENOMEM; nid = codec->start_nid; for (i = 0; i < codec->num_nodes; i++, nid++) @@ -493,7 +491,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) */ static void snd_hda_codec_free(struct hda_codec *codec) { - if (! codec) + if (!codec) return; list_del(&codec->list); codec->bus->caddr_tbl[codec->addr] = NULL; @@ -514,8 +512,8 @@ static void init_amp_hash(struct hda_codec *codec); * * Returns 0 if successful, or a negative error code. */ -int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, - struct hda_codec **codecp) +int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, + struct hda_codec **codecp) { struct hda_codec *codec; char component[13]; @@ -525,7 +523,8 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, snd_assert(codec_addr <= HDA_MAX_CODEC_ADDRESS, return -EINVAL); if (bus->caddr_tbl[codec_addr]) { - snd_printk(KERN_ERR "hda_codec: address 0x%x is already occupied\n", codec_addr); + snd_printk(KERN_ERR "hda_codec: " + "address 0x%x is already occupied\n", codec_addr); return -EBUSY; } @@ -543,18 +542,21 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, list_add_tail(&codec->list, &bus->codec_list); bus->caddr_tbl[codec_addr] = codec; - codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID); + codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, + AC_PAR_VENDOR_ID); if (codec->vendor_id == -1) /* read again, hopefully the access method was corrected * in the last read... */ codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID); - codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID); - codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID); + codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, + AC_PAR_SUBSYSTEM_ID); + codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, + AC_PAR_REV_ID); setup_fg_nodes(codec); - if (! codec->afg && ! codec->mfg) { + if (!codec->afg && !codec->mfg) { snd_printdd("hda_codec: no AFG or MFG node found\n"); snd_hda_codec_free(codec); return -ENODEV; @@ -566,15 +568,16 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, return -ENOMEM; } - if (! codec->subsystem_id) { + if (!codec->subsystem_id) { hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; - codec->subsystem_id = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_SUBSYSTEM_ID, - 0); + codec->subsystem_id = + snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_SUBSYSTEM_ID, 0); } codec->preset = find_codec_preset(codec); - if (! *bus->card->mixername) + /* audio codec should override the mixer name */ + if (codec->afg || !*bus->card->mixername) snd_hda_get_codec_name(codec, bus->card->mixername, sizeof(bus->card->mixername)); @@ -600,8 +603,6 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, return 0; } -EXPORT_SYMBOL(snd_hda_codec_new); - /** * snd_hda_codec_setup_stream - set up the codec for streaming * @codec: the CODEC to set up @@ -610,13 +611,15 @@ EXPORT_SYMBOL(snd_hda_codec_new); * @channel_id: channel id to pass, zero based. * @format: stream format. */ -void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, +void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, + u32 stream_tag, int channel_id, int format) { - if (! nid) + if (!nid) return; - snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", + snd_printdd("hda_codec_setup_stream: " + "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", nid, stream_tag, channel_id, format); snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | channel_id); @@ -624,8 +627,6 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); } -EXPORT_SYMBOL(snd_hda_codec_setup_stream); - /* * amp access functions */ @@ -636,7 +637,7 @@ EXPORT_SYMBOL(snd_hda_codec_setup_stream); #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) /* initialize the hash table */ -static void init_amp_hash(struct hda_codec *codec) +static void __devinit init_amp_hash(struct hda_codec *codec) { memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash)); codec->num_amp_entries = 0; @@ -662,15 +663,18 @@ static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key) if (codec->num_amp_entries >= codec->amp_info_size) { /* reallocate the array */ int new_size = codec->amp_info_size + 64; - struct hda_amp_info *new_info = kcalloc(new_size, sizeof(struct hda_amp_info), - GFP_KERNEL); - if (! new_info) { - snd_printk(KERN_ERR "hda_codec: can't malloc amp_info\n"); + struct hda_amp_info *new_info; + new_info = kcalloc(new_size, sizeof(struct hda_amp_info), + GFP_KERNEL); + if (!new_info) { + snd_printk(KERN_ERR "hda_codec: " + "can't malloc amp_info\n"); return NULL; } if (codec->amp_info) { memcpy(new_info, codec->amp_info, - codec->amp_info_size * sizeof(struct hda_amp_info)); + codec->amp_info_size * + sizeof(struct hda_amp_info)); kfree(codec->amp_info); } codec->amp_info_size = new_size; @@ -691,15 +695,18 @@ static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key) */ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) { - struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); + struct hda_amp_info *info; - if (! info) + info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); + if (!info) return 0; - if (! (info->status & INFO_AMP_CAPS)) { - if (! (get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) + if (!(info->status & INFO_AMP_CAPS)) { + if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) nid = codec->afg; - info->amp_caps = snd_hda_param_read(codec, nid, direction == HDA_OUTPUT ? - AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); + info->amp_caps = snd_hda_param_read(codec, nid, + direction == HDA_OUTPUT ? + AC_PAR_AMP_OUT_CAP : + AC_PAR_AMP_IN_CAP); info->status |= INFO_AMP_CAPS; } return info->amp_caps; @@ -709,8 +716,9 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) * read the current volume to info * if the cache exists, read the cache value. */ -static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, - hda_nid_t nid, int ch, int direction, int index) +static unsigned int get_vol_mute(struct hda_codec *codec, + struct hda_amp_info *info, hda_nid_t nid, + int ch, int direction, int index) { u32 val, parm; @@ -720,7 +728,8 @@ static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *i parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; parm |= index; - val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm); + val = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_AMP_GAIN_MUTE, parm); info->vol[ch] = val & 0xff; info->status |= INFO_AMP_VOL(ch); return info->vol[ch]; @@ -730,7 +739,8 @@ static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *i * write the current volume in info to the h/w and update the cache */ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, - hda_nid_t nid, int ch, int direction, int index, int val) + hda_nid_t nid, int ch, int direction, int index, + int val) { u32 parm; @@ -748,8 +758,9 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index) { - struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); - if (! info) + struct hda_amp_info *info; + info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); + if (!info) return 0; return get_vol_mute(codec, info, nid, ch, direction, index); } @@ -760,13 +771,14 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int mask, int val) { - struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); + struct hda_amp_info *info; - if (! info) + info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); + if (!info) return 0; val &= mask; val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; - if (info->vol[ch] == val && ! codec->in_resume) + if (info->vol[ch] == val && !codec->in_resume) return 0; put_vol_mute(codec, info, nid, ch, direction, idx, val); return 1; @@ -783,7 +795,8 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) /* volume */ -int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); u16 nid = get_amp_nid(kcontrol); @@ -792,9 +805,11 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ u32 caps; caps = query_amp_caps(codec, nid, dir); - caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; /* num steps */ - if (! caps) { - printk(KERN_WARNING "hda_codec: num_steps = 0 for NID=0x%x\n", nid); + /* num steps */ + caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; + if (!caps) { + printk(KERN_WARNING "hda_codec: " + "num_steps = 0 for NID=0x%x\n", nid); return -EINVAL; } uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; @@ -804,7 +819,8 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ return 0; } -int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = get_amp_nid(kcontrol); @@ -820,7 +836,8 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e return 0; } -int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = get_amp_nid(kcontrol); @@ -852,7 +869,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, if (size < 4 * sizeof(unsigned int)) return -ENOMEM; caps = query_amp_caps(codec, nid, dir); - val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25; + val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; + val2 = (val2 + 1) * 25; val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); val1 = ((int)val1) * ((int)val2); if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) @@ -867,7 +885,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, } /* switch */ -int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { int chs = get_amp_channels(kcontrol); @@ -878,7 +897,8 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ return 0; } -int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = get_amp_nid(kcontrol); @@ -888,13 +908,16 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e long *valp = ucontrol->value.integer.value; if (chs & 1) - *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80) ? 0 : 1; + *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & + 0x80) ? 0 : 1; if (chs & 2) - *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80) ? 0 : 1; + *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & + 0x80) ? 0 : 1; return 0; } -int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = get_amp_nid(kcontrol); @@ -925,7 +948,8 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e #define AMP_VAL_IDX_SHIFT 19 #define AMP_VAL_IDX_MASK (0x0f<<19) -int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); unsigned long pval; @@ -940,7 +964,8 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ return err; } -int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); unsigned long pval; @@ -950,7 +975,8 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ pval = kcontrol->private_value; indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; for (i = 0; i < indices; i++) { - kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT); + kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | + (i << AMP_VAL_IDX_SHIFT); err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); if (err < 0) break; @@ -965,14 +991,16 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ * SPDIF out controls */ -static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0; } -static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_NONAUDIO | @@ -983,7 +1011,8 @@ static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl return 0; } -static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_NONAUDIO | @@ -991,7 +1020,8 @@ static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl return 0; } -static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); @@ -1011,19 +1041,21 @@ static unsigned short convert_from_spdif_status(unsigned int sbits) unsigned short val = 0; if (sbits & IEC958_AES0_PROFESSIONAL) - val |= 1 << 6; + val |= AC_DIG1_PROFESSIONAL; if (sbits & IEC958_AES0_NONAUDIO) - val |= 1 << 5; + val |= AC_DIG1_NONAUDIO; if (sbits & IEC958_AES0_PROFESSIONAL) { - if ((sbits & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015) - val |= 1 << 3; + if ((sbits & IEC958_AES0_PRO_EMPHASIS) == + IEC958_AES0_PRO_EMPHASIS_5015) + val |= AC_DIG1_EMPHASIS; } else { - if ((sbits & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_5015) - val |= 1 << 3; - if (! (sbits & IEC958_AES0_CON_NOT_COPYRIGHT)) - val |= 1 << 4; + if ((sbits & IEC958_AES0_CON_EMPHASIS) == + IEC958_AES0_CON_EMPHASIS_5015) + val |= AC_DIG1_EMPHASIS; + if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT)) + val |= AC_DIG1_COPYRIGHT; if (sbits & (IEC958_AES1_CON_ORIGINAL << 8)) - val |= 1 << 7; + val |= AC_DIG1_LEVEL; val |= sbits & (IEC958_AES1_CON_CATEGORY << 8); } return val; @@ -1035,26 +1067,27 @@ static unsigned int convert_to_spdif_status(unsigned short val) { unsigned int sbits = 0; - if (val & (1 << 5)) + if (val & AC_DIG1_NONAUDIO) sbits |= IEC958_AES0_NONAUDIO; - if (val & (1 << 6)) + if (val & AC_DIG1_PROFESSIONAL) sbits |= IEC958_AES0_PROFESSIONAL; if (sbits & IEC958_AES0_PROFESSIONAL) { - if (sbits & (1 << 3)) + if (sbits & AC_DIG1_EMPHASIS) sbits |= IEC958_AES0_PRO_EMPHASIS_5015; } else { - if (val & (1 << 3)) + if (val & AC_DIG1_EMPHASIS) sbits |= IEC958_AES0_CON_EMPHASIS_5015; - if (! (val & (1 << 4))) + if (!(val & AC_DIG1_COPYRIGHT)) sbits |= IEC958_AES0_CON_NOT_COPYRIGHT; - if (val & (1 << 7)) + if (val & AC_DIG1_LEVEL) sbits |= (IEC958_AES1_CON_ORIGINAL << 8); sbits |= val & (0x7f << 8); } return sbits; } -static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value; @@ -1072,15 +1105,18 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_c codec->spdif_ctls = val; if (change || codec->in_resume) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, val >> 8); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, + val & 0xff); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, + val >> 8); } mutex_unlock(&codec->spdif_mutex); return change; } -static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; @@ -1089,15 +1125,17 @@ static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, struct s return 0; } -static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = codec->spdif_ctls & 1; + ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE; return 0; } -static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value; @@ -1105,16 +1143,21 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct sn int change; mutex_lock(&codec->spdif_mutex); - val = codec->spdif_ctls & ~1; + val = codec->spdif_ctls & ~AC_DIG1_ENABLE; if (ucontrol->value.integer.value[0]) - val |= 1; + val |= AC_DIG1_ENABLE; change = codec->spdif_ctls != val; if (change || codec->in_resume) { codec->spdif_ctls = val; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | - AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80)); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, + val & 0xff); + /* unmute amp switch (if any) */ + if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && + (val & AC_DIG1_ENABLE)) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | + AC_AMP_SET_OUTPUT); } mutex_unlock(&codec->spdif_mutex); return change; @@ -1162,7 +1205,8 @@ static struct snd_kcontrol_new dig_mixes[] = { * * Returns 0 if successful, or a negative error code. */ -int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) +int __devinit snd_hda_create_spdif_out_ctls(struct hda_codec *codec, + hda_nid_t nid) { int err; struct snd_kcontrol *kctl; @@ -1171,10 +1215,12 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { kctl = snd_ctl_new1(dig_mix, codec); kctl->private_value = nid; - if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0) + err = snd_ctl_add(codec->bus->card, kctl); + if (err < 0) return err; } - codec->spdif_ctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0); + codec->spdif_ctls = + snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0); codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls); return 0; } @@ -1185,7 +1231,8 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) #define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info -static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); @@ -1193,7 +1240,8 @@ static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, struct snd return 0; } -static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value; @@ -1204,13 +1252,15 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, struct snd change = codec->spdif_in_enable != val; if (change || codec->in_resume) { codec->spdif_in_enable = val; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, + val); } mutex_unlock(&codec->spdif_mutex); return change; } -static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value; @@ -1254,7 +1304,8 @@ static struct snd_kcontrol_new dig_in_ctls[] = { * * Returns 0 if successful, or a negative error code. */ -int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) +int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec, + hda_nid_t nid) { int err; struct snd_kcontrol *kctl; @@ -1263,10 +1314,13 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { kctl = snd_ctl_new1(dig_mix, codec); kctl->private_value = nid; - if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0) + err = snd_ctl_add(codec->bus->card, kctl); + if (err < 0) return err; } - codec->spdif_in_enable = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) & 1; + codec->spdif_in_enable = + snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) & + AC_DIG1_ENABLE; return 0; } @@ -1304,15 +1358,14 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, * * Returns 0 if successful, otherwise a negative error code. */ -int snd_hda_build_controls(struct hda_bus *bus) +int __devinit snd_hda_build_controls(struct hda_bus *bus) { - struct list_head *p; + struct hda_codec *codec; /* build controls */ - list_for_each(p, &bus->codec_list) { - struct hda_codec *codec = list_entry(p, struct hda_codec, list); + list_for_each_entry(codec, &bus->codec_list, list) { int err; - if (! codec->patch_ops.build_controls) + if (!codec->patch_ops.build_controls) continue; err = codec->patch_ops.build_controls(codec); if (err < 0) @@ -1320,13 +1373,12 @@ int snd_hda_build_controls(struct hda_bus *bus) } /* initialize */ - list_for_each(p, &bus->codec_list) { - struct hda_codec *codec = list_entry(p, struct hda_codec, list); + list_for_each_entry(codec, &bus->codec_list, list) { int err; hda_set_power_state(codec, codec->afg ? codec->afg : codec->mfg, AC_PWRST_D0); - if (! codec->patch_ops.init) + if (!codec->patch_ops.init) continue; err = codec->patch_ops.init(codec); if (err < 0) @@ -1335,8 +1387,6 @@ int snd_hda_build_controls(struct hda_bus *bus) return 0; } -EXPORT_SYMBOL(snd_hda_build_controls); - /* * stream formats */ @@ -1361,6 +1411,11 @@ static struct hda_rate_tbl rate_bits[] = { { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ +#define AC_PAR_PCM_RATE_BITS 11 + /* up to bits 10, 384kHZ isn't supported properly */ + + /* not autodetected value */ + { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */ { 0 } /* terminator */ }; @@ -1389,7 +1444,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, val = rate_bits[i].hda_fmt; break; } - if (! rate_bits[i].hz) { + if (!rate_bits[i].hz) { snd_printdd("invalid rate %d\n", rate); return 0; } @@ -1414,15 +1469,14 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, val |= 0x20; break; default: - snd_printdd("invalid format width %d\n", snd_pcm_format_width(format)); + snd_printdd("invalid format width %d\n", + snd_pcm_format_width(format)); return 0; } return val; } -EXPORT_SYMBOL(snd_hda_calc_stream_format); - /** * snd_hda_query_supported_pcm - query the supported PCM rates and formats * @codec: the HDA codec @@ -1449,12 +1503,12 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, if (val == -1) return -EIO; } - if (! val) + if (!val) val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); if (ratesp) { u32 rates = 0; - for (i = 0; rate_bits[i].hz; i++) { + for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) { if (val & (1 << i)) rates |= rate_bits[i].alsa_bits; } @@ -1470,8 +1524,9 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); if (streams == -1) return -EIO; - if (! streams) { - streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); + if (!streams) { + streams = snd_hda_param_read(codec, codec->afg, + AC_PAR_STREAM); if (streams == -1) return -EIO; } @@ -1495,7 +1550,8 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, bps = 24; else if (val & AC_SUPPCM_BITS_20) bps = 20; - } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|AC_SUPPCM_BITS_32)) { + } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24| + AC_SUPPCM_BITS_32)) { formats |= SNDRV_PCM_FMTBIT_S32_LE; if (val & AC_SUPPCM_BITS_32) bps = 32; @@ -1505,10 +1561,12 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, bps = 20; } } - else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ + else if (streams == AC_SUPFMT_FLOAT32) { + /* should be exclusive */ formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; bps = 32; - } else if (streams == AC_SUPFMT_AC3) { /* should be exclusive */ + } else if (streams == AC_SUPFMT_AC3) { + /* should be exclusive */ /* temporary hack: we have still no proper support * for the direct AC3 stream... */ @@ -1525,7 +1583,8 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, } /** - * snd_hda_is_supported_format - check whether the given node supports the format val + * snd_hda_is_supported_format - check whether the given node supports + * the format val * * Returns 1 if supported, 0 if not. */ @@ -1541,50 +1600,50 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, if (val == -1) return 0; } - if (! val) { + if (!val) { val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); if (val == -1) return 0; } rate = format & 0xff00; - for (i = 0; rate_bits[i].hz; i++) + for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) if (rate_bits[i].hda_fmt == rate) { if (val & (1 << i)) break; return 0; } - if (! rate_bits[i].hz) + if (i >= AC_PAR_PCM_RATE_BITS) return 0; stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); if (stream == -1) return 0; - if (! stream && nid != codec->afg) + if (!stream && nid != codec->afg) stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); - if (! stream || stream == -1) + if (!stream || stream == -1) return 0; if (stream & AC_SUPFMT_PCM) { switch (format & 0xf0) { case 0x00: - if (! (val & AC_SUPPCM_BITS_8)) + if (!(val & AC_SUPPCM_BITS_8)) return 0; break; case 0x10: - if (! (val & AC_SUPPCM_BITS_16)) + if (!(val & AC_SUPPCM_BITS_16)) return 0; break; case 0x20: - if (! (val & AC_SUPPCM_BITS_20)) + if (!(val & AC_SUPPCM_BITS_20)) return 0; break; case 0x30: - if (! (val & AC_SUPPCM_BITS_24)) + if (!(val & AC_SUPPCM_BITS_24)) return 0; break; case 0x40: - if (! (val & AC_SUPPCM_BITS_32)) + if (!(val & AC_SUPPCM_BITS_32)) return 0; break; default: @@ -1625,15 +1684,15 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, return 0; } -static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream *info) +static int __devinit set_pcm_default_values(struct hda_codec *codec, + struct hda_pcm_stream *info) { - if (info->nid) { - /* query support PCM information from the given NID */ - if (! info->rates || ! info->formats) - snd_hda_query_supported_pcm(codec, info->nid, - info->rates ? NULL : &info->rates, - info->formats ? NULL : &info->formats, - info->maxbps ? NULL : &info->maxbps); + /* query support PCM information from the given NID */ + if (info->nid && (!info->rates || !info->formats)) { + snd_hda_query_supported_pcm(codec, info->nid, + info->rates ? NULL : &info->rates, + info->formats ? NULL : &info->formats, + info->maxbps ? NULL : &info->maxbps); } if (info->ops.open == NULL) info->ops.open = hda_pcm_default_open_close; @@ -1676,15 +1735,14 @@ static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream * * This function returns 0 if successfull, or a negative error code. */ -int snd_hda_build_pcms(struct hda_bus *bus) +int __devinit snd_hda_build_pcms(struct hda_bus *bus) { - struct list_head *p; + struct hda_codec *codec; - list_for_each(p, &bus->codec_list) { - struct hda_codec *codec = list_entry(p, struct hda_codec, list); + list_for_each_entry(codec, &bus->codec_list, list) { unsigned int pcm, s; int err; - if (! codec->patch_ops.build_pcms) + if (!codec->patch_ops.build_pcms) continue; err = codec->patch_ops.build_pcms(codec); if (err < 0) @@ -1693,7 +1751,7 @@ int snd_hda_build_pcms(struct hda_bus *bus) for (s = 0; s < 2; s++) { struct hda_pcm_stream *info; info = &codec->pcm_info[pcm].stream[s]; - if (! info->substreams) + if (!info->substreams) continue; err = set_pcm_default_values(codec, info); if (err < 0) @@ -1704,8 +1762,6 @@ int snd_hda_build_pcms(struct hda_bus *bus) return 0; } -EXPORT_SYMBOL(snd_hda_build_pcms); - /** * snd_hda_check_board_config - compare the current codec with the config table * @codec: the HDA codec @@ -1719,9 +1775,9 @@ EXPORT_SYMBOL(snd_hda_build_pcms); * * If no entries are matching, the function returns a negative value. */ -int snd_hda_check_board_config(struct hda_codec *codec, - int num_configs, const char **models, - const struct snd_pci_quirk *tbl) +int __devinit snd_hda_check_board_config(struct hda_codec *codec, + int num_configs, const char **models, + const struct snd_pci_quirk *tbl) { if (codec->bus->modelname && models) { int i; @@ -1771,24 +1827,26 @@ int snd_hda_check_board_config(struct hda_codec *codec, * * Returns 0 if successful, or a negative error code. */ -int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) +int __devinit snd_hda_add_new_ctls(struct hda_codec *codec, + struct snd_kcontrol_new *knew) { int err; for (; knew->name; knew++) { struct snd_kcontrol *kctl; kctl = snd_ctl_new1(knew, codec); - if (! kctl) + if (!kctl) return -ENOMEM; err = snd_ctl_add(codec->bus->card, kctl); if (err < 0) { - if (! codec->addr) + if (!codec->addr) return err; kctl = snd_ctl_new1(knew, codec); - if (! kctl) + if (!kctl) return -ENOMEM; kctl->id.device = codec->addr; - if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0) + err = snd_ctl_add(codec->bus->card, kctl); + if (err < 0) return err; } } @@ -1799,8 +1857,10 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) /* * Channel mode helper */ -int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinfo, - const struct hda_channel_mode *chmode, int num_chmodes) +int snd_hda_ch_mode_info(struct hda_codec *codec, + struct snd_ctl_elem_info *uinfo, + const struct hda_channel_mode *chmode, + int num_chmodes) { uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; @@ -1812,8 +1872,10 @@ int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinf return 0; } -int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, - const struct hda_channel_mode *chmode, int num_chmodes, +int snd_hda_ch_mode_get(struct hda_codec *codec, + struct snd_ctl_elem_value *ucontrol, + const struct hda_channel_mode *chmode, + int num_chmodes, int max_channels) { int i; @@ -1827,15 +1889,17 @@ int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucon return 0; } -int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, - const struct hda_channel_mode *chmode, int num_chmodes, +int snd_hda_ch_mode_put(struct hda_codec *codec, + struct snd_ctl_elem_value *ucontrol, + const struct hda_channel_mode *chmode, + int num_chmodes, int *max_channelsp) { unsigned int mode; mode = ucontrol->value.enumerated.item[0]; snd_assert(mode < num_chmodes, return -EINVAL); - if (*max_channelsp == chmode[mode].channels && ! codec->in_resume) + if (*max_channelsp == chmode[mode].channels && !codec->in_resume) return 0; /* change the current channel setting */ *max_channelsp = chmode[mode].channels; @@ -1847,7 +1911,8 @@ int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucon /* * input MUX helper */ -int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem_info *uinfo) +int snd_hda_input_mux_info(const struct hda_input_mux *imux, + struct snd_ctl_elem_info *uinfo) { unsigned int index; @@ -1861,8 +1926,10 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem return 0; } -int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux, - struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, +int snd_hda_input_mux_put(struct hda_codec *codec, + const struct hda_input_mux *imux, + struct snd_ctl_elem_value *ucontrol, + hda_nid_t nid, unsigned int *cur_val) { unsigned int idx; @@ -1870,7 +1937,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i idx = ucontrol->value.enumerated.item[0]; if (idx >= imux->num_items) idx = imux->num_items - 1; - if (*cur_val == idx && ! codec->in_resume) + if (*cur_val == idx && !codec->in_resume) return 0; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, imux->items[idx].index); @@ -1883,25 +1950,53 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i * Multi-channel / digital-out PCM helper functions */ +/* setup SPDIF output stream */ +static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, + unsigned int stream_tag, unsigned int format) +{ + /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ + if (codec->spdif_ctls & AC_DIG1_ENABLE) + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, + codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); + snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); + /* turn on again (if needed) */ + if (codec->spdif_ctls & AC_DIG1_ENABLE) + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, + codec->spdif_ctls & 0xff); +} + /* * open the digital out in the exclusive mode */ -int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout) +int snd_hda_multi_out_dig_open(struct hda_codec *codec, + struct hda_multi_out *mout) { mutex_lock(&codec->spdif_mutex); - if (mout->dig_out_used) { - mutex_unlock(&codec->spdif_mutex); - return -EBUSY; /* already being used */ - } + if (mout->dig_out_used == HDA_DIG_ANALOG_DUP) + /* already opened as analog dup; reset it once */ + snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); mout->dig_out_used = HDA_DIG_EXCLUSIVE; mutex_unlock(&codec->spdif_mutex); return 0; } +int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, + struct hda_multi_out *mout, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + mutex_lock(&codec->spdif_mutex); + setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format); + mutex_unlock(&codec->spdif_mutex); + return 0; +} + /* * release the digital out */ -int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout) +int snd_hda_multi_out_dig_close(struct hda_codec *codec, + struct hda_multi_out *mout) { mutex_lock(&codec->spdif_mutex); mout->dig_out_used = 0; @@ -1912,7 +2007,8 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *m /* * set up more restrictions for analog out */ -int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, +int snd_hda_multi_out_analog_open(struct hda_codec *codec, + struct hda_multi_out *mout, struct snd_pcm_substream *substream) { substream->runtime->hw.channels_max = mout->max_channels; @@ -1924,7 +2020,8 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out * set up the i/o for analog out * when the digital out is available, copy the front out to digital out, too. */ -int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, +int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, + struct hda_multi_out *mout, unsigned int stream_tag, unsigned int format, struct snd_pcm_substream *substream) @@ -1936,24 +2033,27 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o mutex_lock(&codec->spdif_mutex); if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { if (chs == 2 && - snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && - ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) { + snd_hda_is_supported_format(codec, mout->dig_out_nid, + format) && + !(codec->spdif_status & IEC958_AES0_NONAUDIO)) { mout->dig_out_used = HDA_DIG_ANALOG_DUP; - /* setup digital receiver */ - snd_hda_codec_setup_stream(codec, mout->dig_out_nid, - stream_tag, 0, format); + setup_dig_out_stream(codec, mout->dig_out_nid, + stream_tag, format); } else { mout->dig_out_used = 0; - snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); + snd_hda_codec_setup_stream(codec, mout->dig_out_nid, + 0, 0, 0); } } mutex_unlock(&codec->spdif_mutex); /* front */ - snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); + snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, + 0, format); if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) /* headphone out will just decode front left/right (stereo) */ - snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); + snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, + 0, format); /* extra outputs copied from front */ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) if (mout->extra_out_nid[i]) @@ -1964,11 +2064,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o /* surrounds */ for (i = 1; i < mout->num_dacs; i++) { if (chs >= (i + 1) * 2) /* independent out */ - snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, - format); + snd_hda_codec_setup_stream(codec, nids[i], stream_tag, + i * 2, format); else /* copy front */ - snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, - format); + snd_hda_codec_setup_stream(codec, nids[i], stream_tag, + 0, format); } return 0; } @@ -1976,7 +2076,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o /* * clean up the setting for analog out */ -int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout) +int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, + struct hda_multi_out *mout) { hda_nid_t *nids = mout->dac_nids; int i; @@ -2003,7 +2104,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o * Helper for automatic ping configuration */ -static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) +static int __devinit is_in_nid_list(hda_nid_t nid, hda_nid_t *list) { for (; *list; list++) if (*list == nid) @@ -2011,6 +2112,32 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) return 0; } + +/* + * Sort an associated group of pins according to their sequence numbers. + */ +static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, + int num_pins) +{ + int i, j; + short seq; + hda_nid_t nid; + + for (i = 0; i < num_pins; i++) { + for (j = i + 1; j < num_pins; j++) { + if (sequences[i] > sequences[j]) { + seq = sequences[i]; + sequences[i] = sequences[j]; + sequences[j] = seq; + nid = pins[i]; + pins[i] = pins[j]; + pins[j] = nid; + } + } + } +} + + /* * Parse all pin widgets and store the useful pin nids to cfg * @@ -2028,22 +2155,27 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, * respectively. */ -int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, - hda_nid_t *ignore_nids) +int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec, + struct auto_pin_cfg *cfg, + hda_nid_t *ignore_nids) { hda_nid_t nid, nid_start; - int i, j, nodes; - short seq, assoc_line_out, sequences[ARRAY_SIZE(cfg->line_out_pins)]; + int nodes; + short seq, assoc_line_out, assoc_speaker; + short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; + short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; memset(cfg, 0, sizeof(*cfg)); - memset(sequences, 0, sizeof(sequences)); - assoc_line_out = 0; + memset(sequences_line_out, 0, sizeof(sequences_line_out)); + memset(sequences_speaker, 0, sizeof(sequences_speaker)); + assoc_line_out = assoc_speaker = 0; nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); for (nid = nid_start; nid < nodes + nid_start; nid++) { unsigned int wid_caps = get_wcaps(codec, nid); - unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + unsigned int wid_type = + (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; unsigned int def_conf; short assoc, loc; @@ -2054,7 +2186,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c if (ignore_nids && is_in_nid_list(nid, ignore_nids)) continue; - def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); + def_conf = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_CONFIG_DEFAULT, 0); if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) continue; loc = get_defcfg_location(def_conf); @@ -2062,22 +2195,31 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c case AC_JACK_LINE_OUT: seq = get_defcfg_sequence(def_conf); assoc = get_defcfg_association(def_conf); - if (! assoc) + if (!assoc) continue; - if (! assoc_line_out) + if (!assoc_line_out) assoc_line_out = assoc; else if (assoc_line_out != assoc) continue; if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) continue; cfg->line_out_pins[cfg->line_outs] = nid; - sequences[cfg->line_outs] = seq; + sequences_line_out[cfg->line_outs] = seq; cfg->line_outs++; break; case AC_JACK_SPEAKER: + seq = get_defcfg_sequence(def_conf); + assoc = get_defcfg_association(def_conf); + if (! assoc) + continue; + if (! assoc_speaker) + assoc_speaker = assoc; + else if (assoc_speaker != assoc) + continue; if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) continue; cfg->speaker_pins[cfg->speaker_outs] = nid; + sequences_speaker[cfg->speaker_outs] = seq; cfg->speaker_outs++; break; case AC_JACK_HP_OUT: @@ -2123,34 +2265,45 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c } /* sort by sequence */ - for (i = 0; i < cfg->line_outs; i++) - for (j = i + 1; j < cfg->line_outs; j++) - if (sequences[i] > sequences[j]) { - seq = sequences[i]; - sequences[i] = sequences[j]; - sequences[j] = seq; - nid = cfg->line_out_pins[i]; - cfg->line_out_pins[i] = cfg->line_out_pins[j]; - cfg->line_out_pins[j] = nid; - } + sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out, + cfg->line_outs); + sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker, + cfg->speaker_outs); + + /* + * FIX-UP: if no line-outs are detected, try to use speaker or HP pin + * as a primary output + */ + if (!cfg->line_outs) { + if (cfg->speaker_outs) { + cfg->line_outs = cfg->speaker_outs; + memcpy(cfg->line_out_pins, cfg->speaker_pins, + sizeof(cfg->speaker_pins)); + cfg->speaker_outs = 0; + memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); + cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; + } else if (cfg->hp_outs) { + cfg->line_outs = cfg->hp_outs; + memcpy(cfg->line_out_pins, cfg->hp_pins, + sizeof(cfg->hp_pins)); + cfg->hp_outs = 0; + memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); + cfg->line_out_type = AUTO_PIN_HP_OUT; + } + } /* Reorder the surround channels * ALSA sequence is front/surr/clfe/side * HDA sequence is: * 4-ch: front/surr => OK as it is * 6-ch: front/clfe/surr - * 8-ch: front/clfe/side/surr + * 8-ch: front/clfe/rear/side|fc */ switch (cfg->line_outs) { case 3: - nid = cfg->line_out_pins[1]; - cfg->line_out_pins[1] = cfg->line_out_pins[2]; - cfg->line_out_pins[2] = nid; - break; case 4: nid = cfg->line_out_pins[1]; - cfg->line_out_pins[1] = cfg->line_out_pins[3]; - cfg->line_out_pins[3] = cfg->line_out_pins[2]; + cfg->line_out_pins[1] = cfg->line_out_pins[2]; cfg->line_out_pins[2] = nid; break; } @@ -2179,26 +2332,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c cfg->input_pins[AUTO_PIN_CD], cfg->input_pins[AUTO_PIN_AUX]); - /* - * FIX-UP: if no line-outs are detected, try to use speaker or HP pin - * as a primary output - */ - if (! cfg->line_outs) { - if (cfg->speaker_outs) { - cfg->line_outs = cfg->speaker_outs; - memcpy(cfg->line_out_pins, cfg->speaker_pins, - sizeof(cfg->speaker_pins)); - cfg->speaker_outs = 0; - memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); - } else if (cfg->hp_outs) { - cfg->line_outs = cfg->hp_outs; - memcpy(cfg->line_out_pins, cfg->hp_pins, - sizeof(cfg->hp_pins)); - cfg->hp_outs = 0; - memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); - } - } - return 0; } @@ -2222,11 +2355,10 @@ const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = { */ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) { - struct list_head *p; + struct hda_codec *codec; /* FIXME: should handle power widget capabilities */ - list_for_each(p, &bus->codec_list) { - struct hda_codec *codec = list_entry(p, struct hda_codec, list); + list_for_each_entry(codec, &bus->codec_list, list) { if (codec->patch_ops.suspend) codec->patch_ops.suspend(codec, state); hda_set_power_state(codec, @@ -2236,8 +2368,6 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) return 0; } -EXPORT_SYMBOL(snd_hda_suspend); - /** * snd_hda_resume - resume the codecs * @bus: the HDA bus @@ -2247,10 +2377,9 @@ EXPORT_SYMBOL(snd_hda_suspend); */ int snd_hda_resume(struct hda_bus *bus) { - struct list_head *p; + struct hda_codec *codec; - list_for_each(p, &bus->codec_list) { - struct hda_codec *codec = list_entry(p, struct hda_codec, list); + list_for_each_entry(codec, &bus->codec_list, list) { hda_set_power_state(codec, codec->afg ? codec->afg : codec->mfg, AC_PWRST_D0); @@ -2260,8 +2389,6 @@ int snd_hda_resume(struct hda_bus *bus) return 0; } -EXPORT_SYMBOL(snd_hda_resume); - /** * snd_hda_resume_ctls - resume controls in the new control list * @codec: the HDA codec @@ -2276,7 +2403,7 @@ int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) struct snd_ctl_elem_value *val; val = kmalloc(sizeof(*val), GFP_KERNEL); - if (! val) + if (!val) return -ENOMEM; codec->in_resume = 1; for (; knew->name; knew++) { @@ -2320,19 +2447,3 @@ int snd_hda_resume_spdif_in(struct hda_codec *codec) return snd_hda_resume_ctls(codec, dig_in_ctls); } #endif - -/* - * INIT part - */ - -static int __init alsa_hda_init(void) -{ - return 0; -} - -static void __exit alsa_hda_exit(void) -{ -} - -module_init(alsa_hda_init) -module_exit(alsa_hda_exit) diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index c12bc4e8840f..56c26e7ccdf1 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -233,7 +233,7 @@ enum { */ /* Amp gain/mute */ -#define AC_AMP_MUTE (1<<8) +#define AC_AMP_MUTE (1<<7) #define AC_AMP_GAIN (0x7f) #define AC_AMP_GET_INDEX (0xf<<0) diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 1e5ff0cd3709..000287f7da43 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -133,7 +133,7 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid return -ENOMEM; } } - memcpy(node->conn_list, conn_list, nconns); + memcpy(node->conn_list, conn_list, nconns * sizeof(hda_nid_t)); node->nconns = nconns; node->wid_caps = get_wcaps(codec, nid); node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1672cace1ae7..2fa281cbef91 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -88,6 +88,8 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{ATI, SB600}," "{ATI, RS600}," "{ATI, RS690}," + "{ATI, RS780}," + "{ATI, R600}," "{VIA, VT8251}," "{VIA, VT8237A}," "{SiS, SIS966}," @@ -198,6 +200,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define RIRB_INT_MASK 0x05 /* STATESTS int mask: SD2,SD1,SD0 */ +#define AZX_MAX_CODECS 3 #define STATESTS_INT_MASK 0x07 /* SD_CTL bits */ @@ -978,7 +981,7 @@ static unsigned int azx_max_codecs[] __devinitdata = { static int __devinit azx_codec_create(struct azx *chip, const char *model) { struct hda_bus_template bus_temp; - int c, codecs, err; + int c, codecs, audio_codecs, err; memset(&bus_temp, 0, sizeof(bus_temp)); bus_temp.private_data = chip; @@ -990,16 +993,30 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0) return err; - codecs = 0; - for (c = 0; c < azx_max_codecs[chip->driver_type]; c++) { + codecs = audio_codecs = 0; + for (c = 0; c < AZX_MAX_CODECS; c++) { if ((chip->codec_mask & (1 << c)) & probe_mask) { - err = snd_hda_codec_new(chip->bus, c, NULL); + struct hda_codec *codec; + err = snd_hda_codec_new(chip->bus, c, &codec); if (err < 0) continue; codecs++; + if (codec->afg) + audio_codecs++; } } - if (! codecs) { + if (!audio_codecs) { + /* probe additional slots if no codec is found */ + for (; c < azx_max_codecs[chip->driver_type]; c++) { + if ((chip->codec_mask & (1 << c)) & probe_mask) { + err = snd_hda_codec_new(chip->bus, c, NULL); + if (err < 0) + continue; + codecs++; + } + } + } + if (!codecs) { snd_printk(KERN_ERR SFX "no codecs initialized\n"); return -ENXIO; } @@ -1518,7 +1535,7 @@ static int azx_dev_free(struct snd_device *device) /* * white/black-listing for position_fix */ -static const struct snd_pci_quirk position_fix_list[] __devinitdata = { +static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE), {} }; @@ -1758,6 +1775,8 @@ static struct pci_device_id azx_ids[] = { { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */ { 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */ + { 0x1002, 0x960c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS780 HDMI */ + { 0x1002, 0xaa00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI R600 HDMI */ { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 39718d6cdadd..be12b8814c39 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -148,6 +148,11 @@ struct hda_multi_out { int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout); int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout); +int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, + struct hda_multi_out *mout, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream); int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, struct snd_pcm_substream *substream); int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, @@ -217,6 +222,12 @@ enum { AUTO_PIN_LAST }; +enum { + AUTO_PIN_LINE_OUT, + AUTO_PIN_SPEAKER_OUT, + AUTO_PIN_HP_OUT +}; + extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; struct auto_pin_cfg { @@ -225,6 +236,7 @@ struct auto_pin_cfg { int speaker_outs; hda_nid_t speaker_pins[5]; int hp_outs; + int line_out_type; /* AUTO_PIN_XXX_OUT */ hda_nid_t hp_pins[5]; hda_nid_t input_pins[AUTO_PIN_LAST]; hda_nid_t dig_out_pin; diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index f94f1f22889e..0e1a879663fa 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -192,6 +192,17 @@ static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_close(codec, &spec->multiout); } +static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + struct ad198x_spec *spec = codec->spec; + return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, + format, substream); +} + /* * Analog capture */ @@ -250,7 +261,8 @@ static struct hda_pcm_stream ad198x_pcm_digital_playback = { .nid = 0, /* fill later */ .ops = { .open = ad198x_dig_playback_pcm_open, - .close = ad198x_dig_playback_pcm_close + .close = ad198x_dig_playback_pcm_close, + .prepare = ad198x_dig_playback_pcm_prepare }, }; @@ -739,41 +751,35 @@ static struct hda_verb ad1986a_init_verbs[] = { { } /* end */ }; -/* additional verbs for 3-stack model */ -static struct hda_verb ad1986a_3st_init_verbs[] = { - /* Mic and line-in selectors */ - {0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, - {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, - { } /* end */ -}; - static struct hda_verb ad1986a_ch2_init[] = { /* Surround out -> Line In */ - { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, + /* Line-in selectors */ + { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 }, /* CLFE -> Mic in */ - { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */ + { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, { } /* end */ }; static struct hda_verb ad1986a_ch4_init[] = { /* Surround out -> Surround */ - { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, /* CLFE -> Mic in */ - { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, { } /* end */ }; static struct hda_verb ad1986a_ch6_init[] = { /* Surround out -> Surround out */ - { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, /* CLFE -> CLFE */ - { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 }, { } /* end */ }; @@ -828,6 +834,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD), SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD), SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD), + SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK), SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK), SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK), @@ -882,9 +889,8 @@ static int patch_ad1986a(struct hda_codec *codec) case AD1986A_3STACK: spec->num_mixers = 2; spec->mixers[1] = ad1986a_3st_mixers; - spec->num_init_verbs = 3; - spec->init_verbs[1] = ad1986a_3st_init_verbs; - spec->init_verbs[2] = ad1986a_ch2_init; + spec->num_init_verbs = 2; + spec->init_verbs[1] = ad1986a_ch2_init; spec->channel_mode = ad1986a_modes; spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); spec->need_dac_fix = 1; @@ -1892,8 +1898,9 @@ static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); if (sel > 0) { - sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0); - if (sel <= 3) + sel = snd_hda_codec_read(codec, 0x0b, 0, + AC_VERB_GET_CONNECT_SEL, 0); + if (sel < 3) sel++; else sel = 0; @@ -1906,23 +1913,27 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int sel; + unsigned int val, sel; int change; + val = ucontrol->value.enumerated.item[0]; sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); - if (! ucontrol->value.enumerated.item[0]) { + if (!val) { change = sel != 0; - if (change) - snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 0); + if (change || codec->in_resume) + snd_hda_codec_write(codec, 0x02, 0, + AC_VERB_SET_CONNECT_SEL, 0); } else { change = sel == 0; - if (change) - snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 1); - sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1; - change |= sel == ucontrol->value.enumerated.item[0]; - if (change) - snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, - ucontrol->value.enumerated.item[0] - 1); + if (change || codec->in_resume) + snd_hda_codec_write(codec, 0x02, 0, + AC_VERB_SET_CONNECT_SEL, 1); + sel = snd_hda_codec_read(codec, 0x0b, 0, + AC_VERB_GET_CONNECT_SEL, 0) + 1; + change |= sel != val; + if (change || codec->in_resume) + snd_hda_codec_write(codec, 0x0b, 0, + AC_VERB_SET_CONNECT_SEL, val - 1); } return change; } diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index 831469d3a923..f8eb4c90f801 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c @@ -94,6 +94,17 @@ static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_close(codec, &spec->multiout); } +static int atihdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + struct atihdmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, + format, substream); +} + static struct hda_pcm_stream atihdmi_pcm_digital_playback = { .substreams = 1, .channels_min = 2, @@ -101,7 +112,8 @@ static struct hda_pcm_stream atihdmi_pcm_digital_playback = { .nid = 0x2, /* NID to query formats and rates and setup streams */ .ops = { .open = atihdmi_dig_playback_pcm_open, - .close = atihdmi_dig_playback_pcm_close + .close = atihdmi_dig_playback_pcm_close, + .prepare = atihdmi_dig_playback_pcm_prepare }, }; @@ -160,6 +172,7 @@ static int patch_atihdmi(struct hda_codec *codec) */ struct hda_codec_preset snd_hda_preset_atihdmi[] = { { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, - { .id = 0x1002791a, .name = "ATI RS690 HDMI", .patch = patch_atihdmi }, + { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi }, + { .id = 0x1002aa01, .name = "ATI R600 HDMI", .patch = patch_atihdmi }, {} /* terminator */ }; diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 5b9d3a31a1ae..3c722e667bc8 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c @@ -497,6 +497,17 @@ static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_close(codec, &spec->multiout); } +static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + struct cmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, + format, substream); +} + /* * Analog capture */ @@ -556,7 +567,8 @@ static struct hda_pcm_stream cmi9880_pcm_digital_playback = { /* NID is set in cmi9880_build_pcms */ .ops = { .open = cmi9880_dig_playback_pcm_open, - .close = cmi9880_dig_playback_pcm_close + .close = cmi9880_dig_playback_pcm_close, + .prepare = cmi9880_dig_playback_pcm_prepare }, }; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 46e93c6b9a42..a5a4b2bddf20 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -136,6 +136,18 @@ static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_close(codec, &spec->multiout); } +static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + struct conexant_spec *spec = codec->spec; + return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, + stream_tag, + format, substream); +} + /* * Analog capture */ @@ -194,7 +206,8 @@ static struct hda_pcm_stream conexant_pcm_digital_playback = { .nid = 0, /* fill later */ .ops = { .open = conexant_dig_playback_pcm_open, - .close = conexant_dig_playback_pcm_close + .close = conexant_dig_playback_pcm_close, + .prepare = conexant_dig_playback_pcm_prepare }, }; @@ -452,115 +465,6 @@ static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol, .put = conexant_ch_mode_put, \ .private_value = nid | (dir<<16) } -static int cxt_gpio_data_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int cxt_gpio_data_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long *valp = ucontrol->value.integer.value; - unsigned int val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_DATA, 0x00); - - *valp = (val & mask) != 0; - return 0; -} - -static int cxt_gpio_data_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long val = *ucontrol->value.integer.value; - unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_DATA, - 0x00); - unsigned int old_data = gpio_data; - - /* Set/unset the masked GPIO bit(s) as needed */ - if (val == 0) - gpio_data &= ~mask; - else - gpio_data |= mask; - if (gpio_data == old_data && !codec->in_resume) - return 0; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); - return 1; -} - -#define CXT_GPIO_DATA_SWITCH(xname, nid, mask) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = cxt_gpio_data_info, \ - .get = cxt_gpio_data_get, \ - .put = cxt_gpio_data_put, \ - .private_value = nid | (mask<<16) } -#if 0 -static int cxt_spdif_ctrl_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int cxt_spdif_ctrl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long *valp = ucontrol->value.integer.value; - unsigned int val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_DIGI_CONVERT, 0x00); - - *valp = (val & mask) != 0; - return 0; -} - -static int cxt_spdif_ctrl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value & 0xffff; - unsigned char mask = (kcontrol->private_value >> 16) & 0xff; - long val = *ucontrol->value.integer.value; - unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_DIGI_CONVERT, - 0x00); - unsigned int old_data = ctrl_data; - - /* Set/unset the masked control bit(s) as needed */ - if (val == 0) - ctrl_data &= ~mask; - else - ctrl_data |= mask; - if (ctrl_data == old_data && !codec->in_resume) - return 0; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, - ctrl_data); - return 1; -} - -#define CXT_SPDIF_CTRL_SWITCH(xname, nid, mask) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = cxt_spdif_ctrl_info, \ - .get = cxt_spdif_ctrl_get, \ - .put = cxt_spdif_ctrl_put, \ - .private_value = nid | (mask<<16) } -#endif #endif /* CONFIG_SND_DEBUG */ /* Conexant 5045 specific */ @@ -599,6 +503,7 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); + bits = spec->cur_eapd ? 0 : 0x80; snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits); snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits); @@ -624,6 +529,29 @@ static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol, return change; } +/* toggle input of built-in and mic jack appropriately */ +static void cxt5045_hp_automic(struct hda_codec *codec) +{ + static struct hda_verb mic_jack_on[] = { + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + {} + }; + static struct hda_verb mic_jack_off[] = { + {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + {} + }; + unsigned int present; + + present = snd_hda_codec_read(codec, 0x12, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + if (present) + snd_hda_sequence_write(codec, mic_jack_on); + else + snd_hda_sequence_write(codec, mic_jack_off); +} + /* mute internal speaker if HP is plugged */ static void cxt5045_hp_automute(struct hda_codec *codec) @@ -634,7 +562,7 @@ static void cxt5045_hp_automute(struct hda_codec *codec) spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; - bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; + bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); } @@ -648,6 +576,10 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, case CONEXANT_HP_EVENT: cxt5045_hp_automute(codec); break; + case CONEXANT_MIC_EVENT: + cxt5045_hp_automic(codec); + break; + } } @@ -659,12 +591,10 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { .get = conexant_mux_enum_get, .put = conexant_mux_enum_put }, - HDA_CODEC_VOLUME("Int Mic Volume", 0x17, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Int Mic Switch", 0x17, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Ext Mic Volume", 0x17, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Ext Mic Switch", 0x17, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Int Mic Volume", 0x1a, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT), + HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Volume", @@ -688,7 +618,7 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { static struct hda_verb cxt5045_init_verbs[] = { /* Line in, Mic */ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, /* HP, Amp */ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, {0x17, AC_VERB_SET_CONNECT_SEL,0x01}, @@ -701,18 +631,29 @@ static struct hda_verb cxt5045_init_verbs[] = { {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04}, /* Record selector: Int mic */ - {0x1a, AC_VERB_SET_CONNECT_SEL,0x0}, + {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, /* SPDIF route: PCM */ { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, - /* pin sensing on HP and Mic jacks */ - {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, /* EAPD */ {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ { } /* end */ }; + +static struct hda_verb cxt5045_hp_sense_init_verbs[] = { + /* pin sensing on HP jack */ + {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, + { } /* end */ +}; + +static struct hda_verb cxt5045_mic_sense_init_verbs[] = { + /* pin sensing on HP jack */ + {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, + { } /* end */ +}; + #ifdef CONFIG_SND_DEBUG /* Test configuration for debugging, modelled after the ALC260 test * configuration. @@ -733,6 +674,10 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { /* Output controls */ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Node 11 Playback Volume", 0x11, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Node 11 Playback Switch", 0x11, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Node 12 Playback Volume", 0x12, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Node 12 Playback Switch", 0x12, 0x0, HDA_OUTPUT), /* Modes for retasking pin widgets */ CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), @@ -742,25 +687,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), /* Loopback mixer controls */ - HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x17, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("MIC1 Playback Switch", 0x17, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("LINE loopback Playback Volume", 0x17, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("LINE loopback Playback Switch", 0x17, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x17, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x17, 0x03, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x04, HDA_INPUT), - - HDA_CODEC_VOLUME("Capture-1 Volume", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture-1 Switch", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture-2 Volume", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Capture-2 Switch", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Capture-3 Volume", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Capture-3 Switch", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("Capture-4 Volume", 0x17, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("Capture-4 Switch", 0x17, 0x3, HDA_INPUT), - HDA_CODEC_VOLUME("Capture-5 Volume", 0x17, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("Capture-5 Switch", 0x17, 0x4, HDA_INPUT), + + HDA_CODEC_VOLUME("Mixer-1 Volume", 0x17, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mixer-1 Switch", 0x17, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Mixer-2 Volume", 0x17, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Mixer-2 Switch", 0x17, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("Mixer-3 Volume", 0x17, 0x2, HDA_INPUT), + HDA_CODEC_MUTE("Mixer-3 Switch", 0x17, 0x2, HDA_INPUT), + HDA_CODEC_VOLUME("Mixer-4 Volume", 0x17, 0x3, HDA_INPUT), + HDA_CODEC_MUTE("Mixer-4 Switch", 0x17, 0x3, HDA_INPUT), + HDA_CODEC_VOLUME("Mixer-5 Volume", 0x17, 0x4, HDA_INPUT), + HDA_CODEC_MUTE("Mixer-5 Switch", 0x17, 0x4, HDA_INPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Source", @@ -768,14 +705,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { .get = conexant_mux_enum_get, .put = conexant_mux_enum_put, }, - { } /* end */ }; static struct hda_verb cxt5045_test_init_verbs[] = { + /* Set connections */ + { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, + { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, + { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 }, /* Enable retasking pins as output, initially without power amp */ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Disable digital (SPDIF) pins initially, but users can enable * them via a mixer switch. In the case of SPDIF-out, this initverb @@ -804,6 +744,7 @@ static struct hda_verb cxt5045_test_init_verbs[] = { * pin) */ {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x17, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Mute all inputs to mixer widget (even unconnected ones) */ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */ @@ -827,7 +768,8 @@ static int cxt5045_init(struct hda_codec *codec) enum { - CXT5045_LAPTOP, /* Laptops w/ EAPD support */ + CXT5045_LAPTOP, /* Laptops w/ EAPD support */ + CXT5045_FUJITSU, /* Laptops w/ EAPD support */ #ifdef CONFIG_SND_DEBUG CXT5045_TEST, #endif @@ -836,6 +778,7 @@ enum { static const char *cxt5045_models[CXT5045_MODELS] = { [CXT5045_LAPTOP] = "laptop", + [CXT5045_FUJITSU] = "fujitsu", #ifdef CONFIG_SND_DEBUG [CXT5045_TEST] = "test", #endif @@ -844,7 +787,11 @@ static const char *cxt5045_models[CXT5045_MODELS] = { static struct snd_pci_quirk cxt5045_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP), SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP), - SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP), + SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP), + SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP), + SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP), + SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU), + SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP), {} }; @@ -877,16 +824,23 @@ static int patch_cxt5045(struct hda_codec *codec) codec->patch_ops = conexant_patch_ops; - codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, cxt5045_models, cxt5045_cfg_tbl); switch (board_config) { case CXT5045_LAPTOP: + codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; + spec->input_mux = &cxt5045_capture_source; + spec->num_init_verbs = 2; + spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; + spec->mixers[0] = cxt5045_mixers; + codec->patch_ops.init = cxt5045_init; + break; + case CXT5045_FUJITSU: spec->input_mux = &cxt5045_capture_source; spec->num_init_verbs = 2; - spec->init_verbs[1] = cxt5045_init_verbs; + spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; spec->mixers[0] = cxt5045_mixers; codec->patch_ops.init = cxt5045_init; break; @@ -913,10 +867,9 @@ static struct hda_channel_mode cxt5047_modes[1] = { }; static struct hda_input_mux cxt5047_capture_source = { - .num_items = 2, + .num_items = 1, .items = { - { "ExtMic", 0x0 }, - { "IntMic", 0x1 }, + { "Mic", 0x2 }, } }; @@ -1009,7 +962,7 @@ static void cxt5047_hp_automic(struct hda_codec *codec) }; unsigned int present; - present = snd_hda_codec_read(codec, 0x08, 0, + present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; if (present) snd_hda_sequence_write(codec, mic_jack_on); @@ -1033,37 +986,20 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec, } static struct snd_kcontrol_new cxt5047_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = conexant_mux_enum_info, - .get = conexant_mux_enum_get, - .put = conexant_mux_enum_put - }, HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT), HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = snd_hda_mixer_amp_volume_info, - .get = snd_hda_mixer_amp_volume_get, - .put = cxt5047_hp_master_vol_put, - .private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = cxt_eapd_info, - .get = cxt_eapd_get, - .put = cxt5047_hp_master_sw_put, - .private_value = 0x13, - }, + HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), + HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x13, 0x00, HDA_OUTPUT), {} }; @@ -1133,18 +1069,19 @@ static struct hda_verb cxt5047_init_verbs[] = { {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, - /* HP, Amp, Speaker */ - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - {0x1A, AC_VERB_SET_CONNECT_SEL,0x00}, - {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, - {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, + /* HP, Speaker */ + {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, + {0x13, AC_VERB_SET_CONNECT_SEL,0x1}, {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, - /* Record selector: Front mic */ + /* Record selector: Mic */ {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, + {0x1A, AC_VERB_SET_CONNECT_SEL,0x02}, + {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, + AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, + {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, + AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, /* SPDIF route: PCM */ { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, /* Enable unsolicited events */ @@ -1161,8 +1098,6 @@ static struct hda_verb cxt5047_toshiba_init_verbs[] = { {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, /* Speaker routing */ {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, - /* Change default to ExtMic for recording */ - {0x1a, AC_VERB_SET_CONNECT_SEL,0x2}, {} }; @@ -1172,7 +1107,6 @@ static struct hda_verb cxt5047_hp_init_verbs[] = { {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, /* Record selector: Ext Mic */ {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, - {0x1a, AC_VERB_SET_CONNECT_SEL,0x02}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, /* Speaker routing */ @@ -1242,14 +1176,6 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = { .get = conexant_mux_enum_get, .put = conexant_mux_enum_put, }, - /* Controls for GPIO pins, assuming they exist and are configured - * as outputs - */ - CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), - CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), - CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), - CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), - { } /* end */ }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index fba3cb11bc2a..a4ede27af021 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -74,6 +74,8 @@ enum { ALC260_HP_3013, ALC260_FUJITSU_S702X, ALC260_ACER, + ALC260_WILL, + ALC260_REPLACER_672V, #ifdef CONFIG_SND_DEBUG ALC260_TEST, #endif @@ -115,15 +117,28 @@ enum { ALC861VD_3ST, ALC861VD_3ST_DIG, ALC861VD_6ST_DIG, + ALC861VD_LENOVO, ALC861VD_AUTO, ALC861VD_MODEL_LAST, }; +/* ALC662 models */ +enum { + ALC662_3ST_2ch_DIG, + ALC662_3ST_6ch_DIG, + ALC662_3ST_6ch, + ALC662_5ST_DIG, + ALC662_LENOVO_101E, + ALC662_AUTO, + ALC662_MODEL_LAST, +}; + /* ALC882 models */ enum { ALC882_3ST_DIG, ALC882_6ST_DIG, ALC882_ARIMA, + ALC882_W2JC, ALC882_AUTO, ALC885_MACPRO, ALC882_MODEL_LAST, @@ -141,6 +156,7 @@ enum { ALC883_ACER, ALC883_MEDION, ALC883_LAPTOP_EAPD, + ALC883_LENOVO_101E_2ch, ALC883_AUTO, ALC883_MODEL_LAST, }; @@ -163,7 +179,7 @@ struct alc_spec { struct hda_pcm_stream *stream_analog_playback; struct hda_pcm_stream *stream_analog_capture; - char *stream_name_digital; /* digital PCM stream */ + char *stream_name_digital; /* digital PCM stream */ struct hda_pcm_stream *stream_digital_playback; struct hda_pcm_stream *stream_digital_capture; @@ -401,7 +417,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); - if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) + if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) val = alc_pin_mode_min(dir); change = pinctl != alc_pin_mode_values[val]; @@ -460,7 +476,8 @@ static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0; -} +} + static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -520,7 +537,8 @@ static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0; -} +} + static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -592,7 +610,7 @@ static void setup_preset(struct alc_spec *spec, spec->multiout.hp_nid = preset->hp_nid; spec->num_mux_defs = preset->num_mux_defs; - if (! spec->num_mux_defs) + if (!spec->num_mux_defs) spec->num_mux_defs = 1; spec->input_mux = preset->input_mux; @@ -604,6 +622,90 @@ static void setup_preset(struct alc_spec *spec, spec->init_hook = preset->init_hook; } +/* Enable GPIO mask and set output */ +static struct hda_verb alc_gpio1_init_verbs[] = { + {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, + { } +}; + +static struct hda_verb alc_gpio2_init_verbs[] = { + {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, + { } +}; + +static struct hda_verb alc_gpio3_init_verbs[] = { + {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, + { } +}; + +/* 32-bit subsystem ID for BIOS loading in HD Audio codec. + * 31 ~ 16 : Manufacture ID + * 15 ~ 8 : SKU ID + * 7 ~ 0 : Assembly ID + * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36 + */ +static void alc_subsystem_id(struct hda_codec *codec, + unsigned int porta, unsigned int porte, + unsigned int portd) +{ + unsigned int ass, tmp; + + ass = codec->subsystem_id; + if (!(ass & 1)) + return; + + /* Override */ + tmp = (ass & 0x38) >> 3; /* external Amp control */ + switch (tmp) { + case 1: + snd_hda_sequence_write(codec, alc_gpio1_init_verbs); + break; + case 3: + snd_hda_sequence_write(codec, alc_gpio2_init_verbs); + break; + case 7: + snd_hda_sequence_write(codec, alc_gpio3_init_verbs); + break; + case 5: + switch (codec->vendor_id) { + case 0x10ec0862: + case 0x10ec0660: + case 0x10ec0662: + case 0x10ec0267: + case 0x10ec0268: + snd_hda_codec_write(codec, 0x14, 0, + AC_VERB_SET_EAPD_BTLENABLE, 2); + snd_hda_codec_write(codec, 0x15, 0, + AC_VERB_SET_EAPD_BTLENABLE, 2); + return; + } + case 6: + if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */ + hda_nid_t port = 0; + tmp = (ass & 0x1800) >> 11; + switch (tmp) { + case 0: port = porta; break; + case 1: port = porte; break; + case 2: port = portd; break; + } + if (port) + snd_hda_codec_write(codec, port, 0, + AC_VERB_SET_EAPD_BTLENABLE, + 2); + } + snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); + snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, + (tmp == 5 ? 0x3040 : 0x3050)); + break; + } +} + /* * ALC880 3-stack model * @@ -801,7 +903,7 @@ static struct hda_channel_mode alc880_fivestack_modes[2] = { static hda_nid_t alc880_6st_dac_nids[4] = { /* front, rear, clfe, rear_surr */ 0x02, 0x03, 0x04, 0x05 -}; +}; static struct hda_input_mux alc880_6stack_capture_source = { .num_items = 4, @@ -1409,25 +1511,43 @@ static struct hda_verb alc880_beep_init_verbs[] = { }; /* toggle speaker-output according to the hp-jack state */ -static void alc880_uniwill_automute(struct hda_codec *codec) +static void alc880_uniwill_hp_automute(struct hda_codec *codec) { unsigned int present; + unsigned char bits; present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); +} + +/* auto-toggle front mic */ +static void alc880_uniwill_mic_automute(struct hda_codec *codec) +{ + unsigned int present; + unsigned char bits; present = snd_hda_codec_read(codec, 0x18, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; - snd_hda_codec_write(codec, 0x0b, 0, AC_VERB_SET_AMP_GAIN_MUTE, - 0x7000 | (0x01 << 8) | (present ? 0x80 : 0)); + bits = present ? 0x80 : 0; + snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, + 0x80, bits); +} + +static void alc880_uniwill_automute(struct hda_codec *codec) +{ + alc880_uniwill_hp_automute(codec); + alc880_uniwill_mic_automute(codec); } static void alc880_uniwill_unsol_event(struct hda_codec *codec, @@ -1436,22 +1556,28 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec, /* Looks like the unsol event is incompatible with the standard * definition. 4bit tag is placed at 28 bit! */ - if ((res >> 28) == ALC880_HP_EVENT || - (res >> 28) == ALC880_MIC_EVENT) - alc880_uniwill_automute(codec); + switch (res >> 28) { + case ALC880_HP_EVENT: + alc880_uniwill_hp_automute(codec); + break; + case ALC880_MIC_EVENT: + alc880_uniwill_mic_automute(codec); + break; + } } static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec) { unsigned int present; + unsigned char bits; present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; - + bits = present ? 0x80 : 0; snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); } static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) @@ -1480,7 +1606,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, */ if ((res >> 28) == ALC880_HP_EVENT) alc880_uniwill_p53_hp_automute(codec); - if ((res >> 28) == ALC880_DCVOL_EVENT) + if ((res >> 28) == ALC880_DCVOL_EVENT) alc880_uniwill_p53_dcvol_automute(codec); } @@ -1547,22 +1673,8 @@ static struct hda_verb alc880_pin_asus_init_verbs[] = { }; /* Enable GPIO mask and set output */ -static struct hda_verb alc880_gpio1_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - - { } -}; - -/* Enable GPIO mask and set output */ -static struct hda_verb alc880_gpio2_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, - - { } -}; +#define alc880_gpio1_init_verbs alc_gpio1_init_verbs +#define alc880_gpio2_init_verbs alc_gpio2_init_verbs /* Clevo m520g init */ static struct hda_verb alc880_pin_clevo_init_verbs[] = { @@ -1734,13 +1846,15 @@ static struct hda_verb alc880_lg_init_verbs[] = { static void alc880_lg_automute(struct hda_codec *codec) { unsigned int present; + unsigned char bits; present = snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); } static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) @@ -1810,13 +1924,15 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = { static void alc880_lg_lw_automute(struct hda_codec *codec) { unsigned int present; + unsigned char bits; present = snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); } static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) @@ -1916,6 +2032,17 @@ static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_open(codec, &spec->multiout); } +static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + struct alc_spec *spec = codec->spec; + return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, + stream_tag, format, substream); +} + static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) @@ -1984,7 +2111,8 @@ static struct hda_pcm_stream alc880_pcm_digital_playback = { /* NID is set in alc_build_pcms */ .ops = { .open = alc880_dig_playback_pcm_open, - .close = alc880_dig_playback_pcm_close + .close = alc880_dig_playback_pcm_close, + .prepare = alc880_dig_playback_pcm_prepare }, }; @@ -2075,7 +2203,7 @@ static void alc_free(struct hda_codec *codec) struct alc_spec *spec = codec->spec; unsigned int i; - if (! spec) + if (!spec) return; if (spec->kctl_alloc) { @@ -2477,7 +2605,8 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { static struct alc_config_preset alc880_presets[] = { [ALC880_3ST] = { .mixers = { alc880_three_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_3stack_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_dac_nids), .dac_nids = alc880_dac_nids, .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), @@ -2487,7 +2616,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_3ST_DIG] = { .mixers = { alc880_three_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_3stack_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_dac_nids), .dac_nids = alc880_dac_nids, .dig_out_nid = ALC880_DIGOUT_NID, @@ -2509,8 +2639,10 @@ static struct alc_config_preset alc880_presets[] = { .input_mux = &alc880_capture_source, }, [ALC880_5ST] = { - .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer}, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, + .mixers = { alc880_three_stack_mixer, + alc880_five_stack_mixer}, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_5stack_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_dac_nids), .dac_nids = alc880_dac_nids, .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), @@ -2518,8 +2650,10 @@ static struct alc_config_preset alc880_presets[] = { .input_mux = &alc880_capture_source, }, [ALC880_5ST_DIG] = { - .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, + .mixers = { alc880_three_stack_mixer, + alc880_five_stack_mixer }, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_5stack_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_dac_nids), .dac_nids = alc880_dac_nids, .dig_out_nid = ALC880_DIGOUT_NID, @@ -2529,7 +2663,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_6ST] = { .mixers = { alc880_six_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_6stack_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), .dac_nids = alc880_6st_dac_nids, .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), @@ -2538,7 +2673,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_6ST_DIG] = { .mixers = { alc880_six_stack_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_6stack_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), .dac_nids = alc880_6st_dac_nids, .dig_out_nid = ALC880_DIGOUT_NID, @@ -2548,7 +2684,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_W810] = { .mixers = { alc880_w810_base_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_w810_init_verbs, alc880_gpio2_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), .dac_nids = alc880_w810_dac_nids, @@ -2559,7 +2696,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_Z71V] = { .mixers = { alc880_z71v_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs }, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_z71v_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), .dac_nids = alc880_z71v_dac_nids, .dig_out_nid = ALC880_DIGOUT_NID, @@ -2570,7 +2708,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_F1734] = { .mixers = { alc880_f1734_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs }, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_f1734_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), .dac_nids = alc880_f1734_dac_nids, .hp_nid = 0x02, @@ -2580,7 +2719,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_ASUS] = { .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_asus_init_verbs, alc880_gpio1_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), .dac_nids = alc880_asus_dac_nids, @@ -2591,7 +2731,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_ASUS_DIG] = { .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_asus_init_verbs, alc880_gpio1_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), .dac_nids = alc880_asus_dac_nids, @@ -2603,7 +2744,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_ASUS_DIG2] = { .mixers = { alc880_asus_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_asus_init_verbs, alc880_gpio2_init_verbs }, /* use GPIO2 */ .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), .dac_nids = alc880_asus_dac_nids, @@ -2615,7 +2757,8 @@ static struct alc_config_preset alc880_presets[] = { }, [ALC880_ASUS_W1V] = { .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, - .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, + .init_verbs = { alc880_volume_init_verbs, + alc880_pin_asus_init_verbs, alc880_gpio1_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), .dac_nids = alc880_asus_dac_nids, @@ -2664,7 +2807,7 @@ static struct alc_config_preset alc880_presets[] = { .init_hook = alc880_uniwill_p53_hp_automute, }, [ALC880_FUJITSU] = { - .mixers = { alc880_fujitsu_mixer, + .mixers = { alc880_fujitsu_mixer, alc880_pcbeep_mixer, }, .init_verbs = { alc880_volume_init_verbs, alc880_uniwill_p53_init_verbs, @@ -2707,7 +2850,7 @@ static struct alc_config_preset alc880_presets[] = { .mixers = { alc880_lg_lw_mixer }, .init_verbs = { alc880_volume_init_verbs, alc880_lg_lw_init_verbs }, - .num_dacs = 1, + .num_dacs = 1, .dac_nids = alc880_dac_nids, .dig_out_nid = ALC880_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), @@ -2749,18 +2892,21 @@ static struct snd_kcontrol_new alc880_control_templates[] = { }; /* add dynamic controls */ -static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val) +static int add_control(struct alc_spec *spec, int type, const char *name, + unsigned long val) { struct snd_kcontrol_new *knew; if (spec->num_kctl_used >= spec->num_kctl_alloc) { int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; - knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ - if (! knew) + /* array + terminator */ + knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); + if (!knew) return -ENOMEM; if (spec->kctl_alloc) { - memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); + memcpy(knew, spec->kctl_alloc, + sizeof(*knew) * spec->num_kctl_alloc); kfree(spec->kctl_alloc); } spec->kctl_alloc = knew; @@ -2770,7 +2916,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, unsign knew = &spec->kctl_alloc[spec->num_kctl_used]; *knew = alc880_control_templates[type]; knew->name = kstrdup(name, GFP_KERNEL); - if (! knew->name) + if (!knew->name) return -ENOMEM; knew->private_value = val; spec->num_kctl_used++; @@ -2790,7 +2936,8 @@ static int add_control(struct alc_spec *spec, int type, const char *name, unsign #define ALC880_PIN_CD_NID 0x1c /* fill in the dac_nids table from the parsed pin configuration */ -static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg) +static int alc880_auto_fill_dac_nids(struct alc_spec *spec, + const struct auto_pin_cfg *cfg) { hda_nid_t nid; int assigned[4]; @@ -2815,8 +2962,9 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pi continue; /* search for an empty channel */ for (j = 0; j < cfg->line_outs; j++) { - if (! assigned[j]) { - spec->multiout.dac_nids[i] = alc880_idx_to_dac(j); + if (!assigned[j]) { + spec->multiout.dac_nids[i] = + alc880_idx_to_dac(j); assigned[j] = 1; break; } @@ -2831,36 +2979,54 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) { char name[32]; - static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; + static const char *chname[4] = { + "Front", "Surround", NULL /*CLFE*/, "Side" + }; hda_nid_t nid; int i, err; for (i = 0; i < cfg->line_outs; i++) { - if (! spec->multiout.dac_nids[i]) + if (!spec->multiout.dac_nids[i]) continue; nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); if (i == 2) { /* Center/LFE */ - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume", - HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "Center Playback Volume", + HDA_COMPOSE_AMP_VAL(nid, 1, 0, + HDA_OUTPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume", - HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "LFE Playback Volume", + HDA_COMPOSE_AMP_VAL(nid, 2, 0, + HDA_OUTPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, + "Center Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 1, 2, + HDA_INPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, + "LFE Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 2, 2, + HDA_INPUT)); + if (err < 0) return err; } else { sprintf(name, "%s Playback Volume", chname[i]); - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, + HDA_OUTPUT)); + if (err < 0) return err; sprintf(name, "%s Playback Switch", chname[i]); - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 2, + HDA_INPUT)); + if (err < 0) return err; } } @@ -2875,51 +3041,57 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, int err; char name[32]; - if (! pin) + if (!pin) return 0; if (alc880_is_fixed_pin(pin)) { nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); /* specify the DAC as the extra output */ - if (! spec->multiout.hp_nid) + if (!spec->multiout.hp_nid) spec->multiout.hp_nid = nid; else spec->multiout.extra_out_nid[0] = nid; /* control HP volume/switch on the output mixer amp */ nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); sprintf(name, "%s Playback Volume", pfx); - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); + if (err < 0) return err; sprintf(name, "%s Playback Switch", pfx); - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); + if (err < 0) return err; } else if (alc880_is_multi_pin(pin)) { /* set manual connection */ /* we have only a switch on HP-out PIN */ sprintf(name, "%s Playback Switch", pfx); - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, + HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); + if (err < 0) return err; } return 0; } /* create input playback/capture controls for the given pin */ -static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname, +static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, + const char *ctlname, int idx, hda_nid_t mix_nid) { char name[32]; int err; sprintf(name, "%s Playback Volume", ctlname); - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); + if (err < 0) return err; sprintf(name, "%s Playback Switch", ctlname); - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, + HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); + if (err < 0) return err; return 0; } @@ -2939,8 +3111,10 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, idx, 0x0b); if (err < 0) return err; - imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; - imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]); + imux->items[imux->num_items].label = + auto_pin_cfg_labels[i]; + imux->items[imux->num_items].index = + alc880_input_pin_idx(cfg->input_pins[i]); imux->num_items++; } } @@ -2952,8 +3126,10 @@ static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, int dac_idx) { /* set as output */ - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, + pin_type); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_UNMUTE); /* need the manual connection? */ if (alc880_is_multi_pin(nid)) { struct alc_spec *spec = codec->spec; @@ -2964,14 +3140,24 @@ static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, } } +static int get_pin_type(int line_out_type) +{ + if (line_out_type == AUTO_PIN_HP_OUT) + return PIN_HP; + else + return PIN_OUT; +} + static void alc880_auto_init_multi_out(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; int i; - + + alc_subsystem_id(codec, 0x15, 0x1b, 0x14); for (i = 0; i < spec->autocfg.line_outs; i++) { hda_nid_t nid = spec->autocfg.line_out_pins[i]; - alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); + int pin_type = get_pin_type(spec->autocfg.line_out_type); + alc880_auto_set_output_and_unmute(codec, nid, pin_type, i); } } @@ -2996,37 +3182,52 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec) for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = spec->autocfg.input_pins[i]; if (alc880_is_input_pin(nid)) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + i <= AUTO_PIN_FRONT_MIC ? + PIN_VREF80 : PIN_IN); if (nid != ALC880_PIN_CD_NID) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); } } } /* parse the BIOS configuration and set up the alc_spec */ -/* return 1 if successful, 0 if the proper config is not found, or a negative error code */ +/* return 1 if successful, 0 if the proper config is not found, + * or a negative error code + */ static int alc880_parse_auto_config(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; int err; static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; - if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, - alc880_ignore)) < 0) + err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, + alc880_ignore); + if (err < 0) return err; - if (! spec->autocfg.line_outs) + if (!spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ - if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || - (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || - (err = alc880_auto_create_extra_out(spec, - spec->autocfg.speaker_pins[0], - "Speaker")) < 0 || - (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], - "Headphone")) < 0 || - (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) + err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); + if (err < 0) + return err; + err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); + if (err < 0) + return err; + err = alc880_auto_create_extra_out(spec, + spec->autocfg.speaker_pins[0], + "Speaker"); + if (err < 0) + return err; + err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], + "Headphone"); + if (err < 0) + return err; + err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); + if (err < 0) return err; spec->multiout.max_channels = spec->multiout.num_dacs * 2; @@ -3086,7 +3287,7 @@ static int patch_alc880(struct hda_codec *codec) if (err < 0) { alc_free(codec); return err; - } else if (! err) { + } else if (!err) { printk(KERN_INFO "hda_codec: Cannot set up configuration " "from BIOS. Using 3-stack mode...\n"); @@ -3105,14 +3306,16 @@ static int patch_alc880(struct hda_codec *codec) spec->stream_digital_playback = &alc880_pcm_digital_playback; spec->stream_digital_capture = &alc880_pcm_digital_capture; - if (! spec->adc_nids && spec->input_mux) { + if (!spec->adc_nids && spec->input_mux) { /* check whether NID 0x07 is valid */ unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]); - wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ + /* get type */ + wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; if (wcap != AC_WID_AUD_IN) { spec->adc_nids = alc880_adc_nids_alt; spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); - spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer; + spec->mixers[spec->num_mixers] = + alc880_capture_alt_mixer; spec->num_mixers++; } else { spec->adc_nids = alc880_adc_nids; @@ -3254,7 +3457,7 @@ static struct snd_kcontrol_new alc260_base_output_mixer[] = { HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), { } /* end */ -}; +}; static struct snd_kcontrol_new alc260_input_mixer[] = { HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), @@ -3349,6 +3552,42 @@ static struct snd_kcontrol_new alc260_acer_mixer[] = { { } /* end */ }; +/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12, + * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17. + */ +static struct snd_kcontrol_new alc260_will_mixer[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), + ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), + HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), + ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), + { } /* end */ +}; + +/* Replacer 672V ALC260 pin usage: Mic jack = 0x12, + * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f. + */ +static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), + ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), + HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), + ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), + { } /* end */ +}; + /* capture mixer elements */ static struct snd_kcontrol_new alc260_capture_mixer[] = { HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), @@ -3434,7 +3673,9 @@ static struct hda_verb alc260_init_verbs[] = { {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* unmute LINE-2 out pin */ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ + /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & + * Line In 2 = 0x03 + */ /* mute CD */ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* mute Line In */ @@ -3482,7 +3723,9 @@ static struct hda_verb alc260_hp_init_verbs[] = { {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, /* mute pin widget amp left and right (no gain on this amp) */ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, - /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ + /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & + * Line In 2 = 0x03 + */ /* unmute CD */ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /* unmute Line In */ @@ -3530,7 +3773,9 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = { {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, /* mute pin widget amp left and right (no gain on this amp) */ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, - /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ + /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & + * Line In 2 = 0x03 + */ /* unmute CD */ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /* unmute Line In */ @@ -3680,7 +3925,9 @@ static struct hda_verb alc260_acer_init_verbs[] = { {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */ + /* Unmute Line-out pin widget amp left and right + * (no equiv mixer ctrl) + */ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Unmute mono pin widget amp output (no equiv mixer ctrl) */ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, @@ -3719,6 +3966,55 @@ static struct hda_verb alc260_acer_init_verbs[] = { { } }; +static struct hda_verb alc260_will_verbs[] = { + {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, + {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, + {0x1a, AC_VERB_SET_PROC_COEF, 0x3040}, + {} +}; + +static struct hda_verb alc260_replacer_672v_verbs[] = { + {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, + {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, + {0x1a, AC_VERB_SET_PROC_COEF, 0x3050}, + + {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, + + {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {} +}; + +/* toggle speaker-output according to the hp-jack state */ +static void alc260_replacer_672v_automute(struct hda_codec *codec) +{ + unsigned int present; + + /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */ + present = snd_hda_codec_read(codec, 0x0f, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + if (present) { + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1); + snd_hda_codec_write(codec, 0x0f, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); + } else { + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0); + snd_hda_codec_write(codec, 0x0f, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + } +} + +static void alc260_replacer_672v_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) == ALC880_HP_EVENT) + alc260_replacer_672v_automute(codec); +} + /* Test configuration for debugging, modelled after the ALC880 test * configuration. */ @@ -3946,10 +4242,12 @@ static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid, return 0; /* N/A */ snprintf(name, sizeof(name), "%s Playback Volume", pfx); - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val); + if (err < 0) return err; snprintf(name, sizeof(name), "%s Playback Switch", pfx); - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val); + if (err < 0) return err; return 1; } @@ -3985,7 +4283,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, if (err < 0) return err; } - return 0; + return 0; } /* create playback/capture controls for input pins */ @@ -3999,20 +4297,24 @@ static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, if (cfg->input_pins[i] >= 0x12) { idx = cfg->input_pins[i] - 0x12; err = new_analog_input(spec, cfg->input_pins[i], - auto_pin_cfg_labels[i], idx, 0x07); + auto_pin_cfg_labels[i], idx, + 0x07); if (err < 0) return err; - imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; + imux->items[imux->num_items].label = + auto_pin_cfg_labels[i]; imux->items[imux->num_items].index = idx; imux->num_items++; } - if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){ + if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){ idx = cfg->input_pins[i] - 0x09; err = new_analog_input(spec, cfg->input_pins[i], - auto_pin_cfg_labels[i], idx, 0x07); + auto_pin_cfg_labels[i], idx, + 0x07); if (err < 0) return err; - imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; + imux->items[imux->num_items].label = + auto_pin_cfg_labels[i]; imux->items[imux->num_items].index = idx; imux->num_items++; } @@ -4025,14 +4327,15 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec, int sel_idx) { /* set as output */ - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, + pin_type); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_UNMUTE); /* need the manual connection? */ if (nid >= 0x12) { int idx = nid - 0x12; snd_hda_codec_write(codec, idx + 0x0b, 0, AC_VERB_SET_CONNECT_SEL, sel_idx); - } } @@ -4041,9 +4344,12 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) struct alc_spec *spec = codec->spec; hda_nid_t nid; - nid = spec->autocfg.line_out_pins[0]; - if (nid) - alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); + alc_subsystem_id(codec, 0x10, 0x15, 0x0f); + nid = spec->autocfg.line_out_pins[0]; + if (nid) { + int pin_type = get_pin_type(spec->autocfg.line_out_type); + alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0); + } nid = spec->autocfg.speaker_pins[0]; if (nid) @@ -4051,8 +4357,8 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) nid = spec->autocfg.hp_pins[0]; if (nid) - alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); -} + alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0); +} #define ALC260_PIN_CD_NID 0x16 static void alc260_auto_init_analog_input(struct hda_codec *codec) @@ -4063,10 +4369,13 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec) for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = spec->autocfg.input_pins[i]; if (nid >= 0x12) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + i <= AUTO_PIN_FRONT_MIC ? + PIN_VREF80 : PIN_IN); if (nid != ALC260_PIN_CD_NID) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); } } @@ -4086,8 +4395,8 @@ static struct hda_verb alc260_volume_init_verbs[] = { /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front panel - * mic (mic 2) + * Note: PASD motherboards uses the Line In 2 as the input for + * front panel mic (mic 2) */ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -4122,14 +4431,17 @@ static int alc260_parse_auto_config(struct hda_codec *codec) int err; static hda_nid_t alc260_ignore[] = { 0x17, 0 }; - if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, - alc260_ignore)) < 0) + err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, + alc260_ignore); + if (err < 0) return err; - if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0) + err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg); + if (err < 0) return err; - if (! spec->kctl_alloc) + if (!spec->kctl_alloc) return 0; /* can't find valid BIOS pin config */ - if ((err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) + err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg); + if (err < 0) return err; spec->multiout.max_channels = 2; @@ -4177,6 +4489,8 @@ static const char *alc260_models[ALC260_MODEL_LAST] = { [ALC260_HP_3013] = "hp-3013", [ALC260_FUJITSU_S702X] = "fujitsu", [ALC260_ACER] = "acer", + [ALC260_WILL] = "will", + [ALC260_REPLACER_672V] = "replacer", #ifdef CONFIG_SND_DEBUG [ALC260_TEST] = "test", #endif @@ -4200,6 +4514,8 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = { SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), + SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL), + SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V), {} }; @@ -4270,6 +4586,34 @@ static struct alc_config_preset alc260_presets[] = { .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), .input_mux = alc260_acer_capture_sources, }, + [ALC260_WILL] = { + .mixers = { alc260_will_mixer, + alc260_capture_mixer }, + .init_verbs = { alc260_init_verbs, alc260_will_verbs }, + .num_dacs = ARRAY_SIZE(alc260_dac_nids), + .dac_nids = alc260_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), + .adc_nids = alc260_adc_nids, + .dig_out_nid = ALC260_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc260_modes), + .channel_mode = alc260_modes, + .input_mux = &alc260_capture_source, + }, + [ALC260_REPLACER_672V] = { + .mixers = { alc260_replacer_672v_mixer, + alc260_capture_mixer }, + .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, + .num_dacs = ARRAY_SIZE(alc260_dac_nids), + .dac_nids = alc260_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), + .adc_nids = alc260_adc_nids, + .dig_out_nid = ALC260_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc260_modes), + .channel_mode = alc260_modes, + .input_mux = &alc260_capture_source, + .unsol_event = alc260_replacer_672v_unsol_event, + .init_hook = alc260_replacer_672v_automute, + }, #ifdef CONFIG_SND_DEBUG [ALC260_TEST] = { .mixers = { alc260_test_mixer, @@ -4313,7 +4657,7 @@ static int patch_alc260(struct hda_codec *codec) if (err < 0) { alc_free(codec); return err; - } else if (! err) { + } else if (!err) { printk(KERN_INFO "hda_codec: Cannot set up configuration " "from BIOS. Using base mode...\n"); @@ -4382,7 +4726,8 @@ static struct hda_input_mux alc882_capture_source = { #define alc882_mux_enum_info alc_mux_enum_info #define alc882_mux_enum_get alc_mux_enum_get -static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; @@ -4396,7 +4741,7 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele idx = ucontrol->value.enumerated.item[0]; if (idx >= imux->num_items) idx = imux->num_items - 1; - if (*cur_val == idx && ! codec->in_resume) + if (*cur_val == idx && !codec->in_resume) return 0; for (i = 0; i < imux->num_items; i++) { unsigned int v = (i == idx) ? 0x7000 : 0x7080; @@ -4464,6 +4809,21 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { { } /* end */ }; +static struct snd_kcontrol_new alc882_w2jc_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), + { } /* end */ +}; + static struct snd_kcontrol_new alc882_chmode_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -4559,7 +4919,7 @@ static struct hda_verb alc882_eapd_verbs[] = { /* change to EAPD mode */ {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, - { } + { } }; /* Mac Pro test */ @@ -4624,6 +4984,7 @@ static struct hda_verb alc882_macpro_init_verbs[] = { { } }; + static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) { unsigned int gpiostate, gpiomask, gpiodir; @@ -4672,8 +5033,8 @@ static struct hda_verb alc882_auto_init_verbs[] = { /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front panel - * mic (mic 2) + * Note: PASD motherboards uses the Line In 2 as the input for + * front panel mic (mic 2) */ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -4782,6 +5143,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { [ALC882_3ST_DIG] = "3stack-dig", [ALC882_6ST_DIG] = "6stack-dig", [ALC882_ARIMA] = "arima", + [ALC882_W2JC] = "w2jc", [ALC885_MACPRO] = "macpro", [ALC882_AUTO] = "auto", }; @@ -4792,6 +5154,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), + SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), {} }; @@ -4828,6 +5191,18 @@ static struct alc_config_preset alc882_presets[] = { .channel_mode = alc882_sixstack_modes, .input_mux = &alc882_capture_source, }, + [ALC882_W2JC] = { + .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer }, + .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, + alc880_gpio1_init_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), + .channel_mode = alc880_threestack_modes, + .need_dac_fix = 1, + .input_mux = &alc882_capture_source, + .dig_out_nid = ALC882_DIGOUT_NID, + }, [ALC885_MACPRO] = { .mixers = { alc882_macpro_mixer }, .init_verbs = { alc882_macpro_init_verbs }, @@ -4851,15 +5226,17 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, { /* set as output */ struct alc_spec *spec = codec->spec; - int idx; - + int idx; + if (spec->multiout.dac_nids[dac_idx] == 0x25) idx = 4; else idx = spec->multiout.dac_nids[dac_idx] - 2; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, + pin_type); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_UNMUTE); snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); } @@ -4869,10 +5246,13 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec) struct alc_spec *spec = codec->spec; int i; + alc_subsystem_id(codec, 0x15, 0x1b, 0x14); for (i = 0; i <= HDA_SIDE; i++) { - hda_nid_t nid = spec->autocfg.line_out_pins[i]; + hda_nid_t nid = spec->autocfg.line_out_pins[i]; + int pin_type = get_pin_type(spec->autocfg.line_out_type); if (nid) - alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); + alc882_auto_set_output_and_unmute(codec, nid, pin_type, + i); } } @@ -4883,7 +5263,8 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) pin = spec->autocfg.hp_pins[0]; if (pin) /* connect to front */ - alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ + /* use dac 0 */ + alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); } #define alc882_is_input_pin(nid) alc880_is_input_pin(nid) @@ -4897,10 +5278,13 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec) for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = spec->autocfg.input_pins[i]; if (alc882_is_input_pin(nid)) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + i <= AUTO_PIN_FRONT_MIC ? + PIN_VREF80 : PIN_IN); if (nid != ALC882_PIN_CD_NID) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); } } @@ -4962,7 +5346,7 @@ static int patch_alc882(struct hda_codec *codec) if (err < 0) { alc_free(codec); return err; - } else if (! err) { + } else if (!err) { printk(KERN_INFO "hda_codec: Cannot set up configuration " "from BIOS. Using base mode...\n"); @@ -4986,14 +5370,16 @@ static int patch_alc882(struct hda_codec *codec) spec->stream_digital_playback = &alc882_pcm_digital_playback; spec->stream_digital_capture = &alc882_pcm_digital_capture; - if (! spec->adc_nids && spec->input_mux) { + if (!spec->adc_nids && spec->input_mux) { /* check whether NID 0x07 is valid */ unsigned int wcap = get_wcaps(codec, 0x07); - wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ + /* get type */ + wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; if (wcap != AC_WID_AUD_IN) { spec->adc_nids = alc882_adc_nids_alt; spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); - spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer; + spec->mixers[spec->num_mixers] = + alc882_capture_alt_mixer; spec->num_mixers++; } else { spec->adc_nids = alc882_adc_nids; @@ -5033,6 +5419,7 @@ static hda_nid_t alc883_adc_nids[2] = { /* ADC1-2 */ 0x08, 0x09, }; + /* input MUX */ /* FIXME: should be a matrix-type input source selection */ @@ -5045,6 +5432,15 @@ static struct hda_input_mux alc883_capture_source = { { "CD", 0x4 }, }, }; + +static struct hda_input_mux alc883_lenovo_101e_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x1 }, + { "Line", 0x2 }, + }, +}; + #define alc883_mux_enum_info alc_mux_enum_info #define alc883_mux_enum_get alc_mux_enum_get @@ -5063,7 +5459,7 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, idx = ucontrol->value.enumerated.item[0]; if (idx >= imux->num_items) idx = imux->num_items - 1; - if (*cur_val == idx && ! codec->in_resume) + if (*cur_val == idx && !codec->in_resume) return 0; for (i = 0; i < imux->num_items; i++) { unsigned int v = (i == idx) ? 0x7000 : 0x7080; @@ -5073,6 +5469,7 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, *cur_val = idx; return 1; } + /* * 2ch mode */ @@ -5325,7 +5722,7 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = { .put = alc883_mux_enum_put, }, { } /* end */ -}; +}; static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), @@ -5350,7 +5747,30 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { .put = alc883_mux_enum_put, }, { } /* end */ -}; +}; + +static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 1, + .info = alc883_mux_enum_info, + .get = alc883_mux_enum_get, + .put = alc883_mux_enum_put, + }, + { } /* end */ +}; static struct snd_kcontrol_new alc883_chmode_mixer[] = { { @@ -5452,10 +5872,17 @@ static struct hda_verb alc883_tagra_verbs[] = { {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, - {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, + {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, + + { } /* end */ +}; +static struct hda_verb alc883_lenovo_101e_verbs[] = { + {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN}, + {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN}, { } /* end */ }; @@ -5463,14 +5890,17 @@ static struct hda_verb alc883_tagra_verbs[] = { static void alc883_tagra_automute(struct hda_codec *codec) { unsigned int present; + unsigned char bits; present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); + 0x80, bits); snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, - 0x80, present ? 0x80 : 0); - snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3); + 0x80, bits); + snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, + present ? 1 : 3); } static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) @@ -5479,6 +5909,47 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) alc883_tagra_automute(codec); } +static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) +{ + unsigned int present; + unsigned char bits; + + present = snd_hda_codec_read(codec, 0x14, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; + snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, + 0x80, bits); +} + +static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) +{ + unsigned int present; + unsigned char bits; + + present = snd_hda_codec_read(codec, 0x1b, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; + snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, + 0x80, bits); +} + +static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) == ALC880_HP_EVENT) + alc883_lenovo_101e_all_automute(codec); + if ((res >> 26) == ALC880_FRONT_EVENT) + alc883_lenovo_101e_ispeaker_automute(codec); +} + /* * generic initialization of ADC, input mixers and output mixers */ @@ -5493,8 +5964,8 @@ static struct hda_verb alc883_auto_init_verbs[] = { /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front panel - * mic (mic 2) + * Note: PASD motherboards uses the Line In 2 as the input for + * front panel mic (mic 2) */ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -5530,13 +6001,13 @@ static struct hda_verb alc883_auto_init_verbs[] = { {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - //{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, + /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* Input mixer2 */ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - //{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, + /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, { } @@ -5584,6 +6055,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { [ALC883_ACER] = "acer", [ALC883_MEDION] = "medion", [ALC883_LAPTOP_EAPD] = "laptop-eapd", + [ALC883_LENOVO_101E_2ch] = "lenovo-101e", [ALC883_AUTO] = "auto", }; @@ -5592,6 +6064,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), + SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), @@ -5609,6 +6082,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), + SND_PCI_QUIRK(0x17aa, 0x101e, "lenovo 101e", ALC883_LENOVO_101E_2ch), {} }; @@ -5639,7 +6113,7 @@ static struct alc_config_preset alc883_presets[] = { .channel_mode = alc883_3ST_6ch_modes, .need_dac_fix = 1, .input_mux = &alc883_capture_source, - }, + }, [ALC883_3ST_6ch] = { .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, .init_verbs = { alc883_init_verbs }, @@ -5651,7 +6125,7 @@ static struct alc_config_preset alc883_presets[] = { .channel_mode = alc883_3ST_6ch_modes, .need_dac_fix = 1, .input_mux = &alc883_capture_source, - }, + }, [ALC883_6ST_DIG] = { .mixers = { alc883_base_mixer, alc883_chmode_mixer }, .init_verbs = { alc883_init_verbs }, @@ -5749,6 +6223,19 @@ static struct alc_config_preset alc883_presets[] = { .channel_mode = alc883_3ST_2ch_modes, .input_mux = &alc883_capture_source, }, + [ALC883_LENOVO_101E_2ch] = { + .mixers = { alc883_lenovo_101e_2ch_mixer}, + .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs}, + .num_dacs = ARRAY_SIZE(alc883_dac_nids), + .dac_nids = alc883_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), + .adc_nids = alc883_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), + .channel_mode = alc883_3ST_2ch_modes, + .input_mux = &alc883_lenovo_101e_capture_source, + .unsol_event = alc883_lenovo_101e_unsol_event, + .init_hook = alc883_lenovo_101e_all_automute, + }, }; @@ -5761,8 +6248,8 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, { /* set as output */ struct alc_spec *spec = codec->spec; - int idx; - + int idx; + if (spec->multiout.dac_nids[dac_idx] == 0x25) idx = 4; else @@ -5781,10 +6268,13 @@ static void alc883_auto_init_multi_out(struct hda_codec *codec) struct alc_spec *spec = codec->spec; int i; + alc_subsystem_id(codec, 0x15, 0x1b, 0x14); for (i = 0; i <= HDA_SIDE; i++) { - hda_nid_t nid = spec->autocfg.line_out_pins[i]; + hda_nid_t nid = spec->autocfg.line_out_pins[i]; + int pin_type = get_pin_type(spec->autocfg.line_out_type); if (nid) - alc883_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); + alc883_auto_set_output_and_unmute(codec, nid, pin_type, + i); } } @@ -5833,8 +6323,8 @@ static int alc883_parse_auto_config(struct hda_codec *codec) else if (err > 0) /* hack - override the init verbs */ spec->init_verbs[0] = alc883_auto_init_verbs; - spec->mixers[spec->num_mixers] = alc883_capture_mixer; - spec->num_mixers++; + spec->mixers[spec->num_mixers] = alc883_capture_mixer; + spec->num_mixers++; return err; } @@ -5872,7 +6362,7 @@ static int patch_alc883(struct hda_codec *codec) if (err < 0) { alc_free(codec); return err; - } else if (! err) { + } else if (!err) { printk(KERN_INFO "hda_codec: Cannot set up configuration " "from BIOS. Using base mode...\n"); @@ -5891,7 +6381,7 @@ static int patch_alc883(struct hda_codec *codec) spec->stream_digital_playback = &alc883_pcm_digital_playback; spec->stream_digital_capture = &alc883_pcm_digital_capture; - if (! spec->adc_nids && spec->input_mux) { + if (!spec->adc_nids && spec->input_mux) { spec->adc_nids = alc883_adc_nids; spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); } @@ -6028,8 +6518,8 @@ static struct hda_verb alc262_init_verbs[] = { /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front panel - * mic (mic 2) + * Note: PASD motherboards uses the Line In 2 as the input for + * front panel mic (mic 2) */ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -6086,7 +6576,7 @@ static struct hda_verb alc262_init_verbs[] = { {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, { } }; @@ -6113,7 +6603,7 @@ static void alc262_hippo_automute(struct hda_codec *codec, int force) struct alc_spec *spec = codec->spec; unsigned int mute; - if (force || ! spec->sense_updated) { + if (force || !spec->sense_updated) { unsigned int present; /* need to execute and sync at first */ snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); @@ -6153,7 +6643,7 @@ static void alc262_hippo1_automute(struct hda_codec *codec, int force) struct alc_spec *spec = codec->spec; unsigned int mute; - if (force || ! spec->sense_updated) { + if (force || !spec->sense_updated) { unsigned int present; /* need to execute and sync at first */ snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); @@ -6226,7 +6716,7 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force) struct alc_spec *spec = codec->spec; unsigned int mute; - if (force || ! spec->sense_updated) { + if (force || !spec->sense_updated) { unsigned int present; /* need to execute and sync at first */ snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); @@ -6331,7 +6821,8 @@ static struct hda_verb alc262_EAPD_verbs[] = { }; /* add playback controls from the parsed DAC table */ -static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) +static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, + const struct auto_pin_cfg *cfg) { hda_nid_t nid; int err; @@ -6342,26 +6833,39 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct nid = cfg->line_out_pins[0]; if (nid) { - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume", - HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "Front Playback Volume", + HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, + "Front Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); + if (err < 0) return err; } nid = cfg->speaker_pins[0]; if (nid) { if (nid == 0x16) { - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", - HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "Speaker Playback Volume", + HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, + HDA_OUTPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, + "Speaker Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 2, 0, + HDA_OUTPUT)); + if (err < 0) return err; } else { - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, + "Speaker Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 3, 0, + HDA_OUTPUT)); + if (err < 0) return err; } } @@ -6369,23 +6873,33 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct if (nid) { /* spec->multiout.hp_nid = 2; */ if (nid == 0x16) { - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume", - HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "Headphone Playback Volume", + HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, + HDA_OUTPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, + "Headphone Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 2, 0, + HDA_OUTPUT)); + if (err < 0) return err; } else { - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, + "Headphone Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 3, 0, + HDA_OUTPUT)); + if (err < 0) return err; } } - return 0; + return 0; } /* identical with ALC880 */ -#define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls +#define alc262_auto_create_analog_input_ctls \ + alc880_auto_create_analog_input_ctls /* * generic initialization of ADC, input mixers and output mixers @@ -6403,8 +6917,8 @@ static struct hda_verb alc262_volume_init_verbs[] = { /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front panel - * mic (mic 2) + * Note: PASD motherboards uses the Line In 2 as the input for + * front panel mic (mic 2) */ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -6464,8 +6978,8 @@ static struct hda_verb alc262_HP_BPC_init_verbs[] = { /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front panel - * mic (mic 2) + * Note: PASD motherboards uses the Line In 2 as the input for + * front panel mic (mic 2) */ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -6647,13 +7161,17 @@ static int alc262_parse_auto_config(struct hda_codec *codec) int err; static hda_nid_t alc262_ignore[] = { 0x1d, 0 }; - if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, - alc262_ignore)) < 0) + err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, + alc262_ignore); + if (err < 0) return err; - if (! spec->autocfg.line_outs) + if (!spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ - if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || - (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) + err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); + if (err < 0) + return err; + err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg); + if (err < 0) return err; spec->multiout.max_channels = spec->multiout.num_dacs * 2; @@ -6777,7 +7295,7 @@ static struct alc_config_preset alc262_presets[] = { .num_channel_mode = ARRAY_SIZE(alc262_modes), .channel_mode = alc262_modes, .input_mux = &alc262_HP_capture_source, - }, + }, [ALC262_HP_BPC_D7000_WF] = { .mixers = { alc262_HP_BPC_WildWest_mixer }, .init_verbs = { alc262_HP_BPC_WildWest_init_verbs }, @@ -6787,7 +7305,7 @@ static struct alc_config_preset alc262_presets[] = { .num_channel_mode = ARRAY_SIZE(alc262_modes), .channel_mode = alc262_modes, .input_mux = &alc262_HP_capture_source, - }, + }, [ALC262_HP_BPC_D7000_WL] = { .mixers = { alc262_HP_BPC_WildWest_mixer, alc262_HP_BPC_WildWest_option_mixer }, @@ -6798,7 +7316,7 @@ static struct alc_config_preset alc262_presets[] = { .num_channel_mode = ARRAY_SIZE(alc262_modes), .channel_mode = alc262_modes, .input_mux = &alc262_HP_capture_source, - }, + }, [ALC262_BENQ_ED8] = { .mixers = { alc262_base_mixer }, .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, @@ -6808,7 +7326,7 @@ static struct alc_config_preset alc262_presets[] = { .num_channel_mode = ARRAY_SIZE(alc262_modes), .channel_mode = alc262_modes, .input_mux = &alc262_capture_source, - }, + }, }; static int patch_alc262(struct hda_codec *codec) @@ -6823,7 +7341,9 @@ static int patch_alc262(struct hda_codec *codec) codec->spec = spec; #if 0 - /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is under-run */ + /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is + * under-run + */ { int tmp; snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); @@ -6849,7 +7369,7 @@ static int patch_alc262(struct hda_codec *codec) if (err < 0) { alc_free(codec); return err; - } else if (! err) { + } else if (!err) { printk(KERN_INFO "hda_codec: Cannot set up configuration " "from BIOS. Using base mode...\n"); @@ -6868,15 +7388,17 @@ static int patch_alc262(struct hda_codec *codec) spec->stream_digital_playback = &alc262_pcm_digital_playback; spec->stream_digital_capture = &alc262_pcm_digital_capture; - if (! spec->adc_nids && spec->input_mux) { + if (!spec->adc_nids && spec->input_mux) { /* check whether NID 0x07 is valid */ unsigned int wcap = get_wcaps(codec, 0x07); - wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ + /* get type */ + wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; if (wcap != AC_WID_AUD_IN) { spec->adc_nids = alc262_adc_nids_alt; spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); - spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer; + spec->mixers[spec->num_mixers] = + alc262_capture_alt_mixer; spec->num_mixers++; } else { spec->adc_nids = alc262_adc_nids; @@ -6904,7 +7426,9 @@ static int patch_alc262(struct hda_codec *codec) static struct hda_verb alc861_threestack_ch2_init[] = { /* set pin widget 1Ah (line in) for input */ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */ + /* set pin widget 18h (mic1/2) for input, for mic also enable + * the vref + */ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, @@ -6961,7 +7485,9 @@ static struct hda_channel_mode alc861_uniwill_m31_modes[2] = { static struct hda_verb alc861_asus_ch2_init[] = { /* set pin widget 1Ah (line in) for input */ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */ + /* set pin widget 18h (mic1/2) for input, for mic also enable + * the vref + */ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, @@ -7016,7 +7542,7 @@ static struct snd_kcontrol_new alc861_base_mixer[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), - + /* Capture mixer control */ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), @@ -7050,7 +7576,7 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), - + /* Capture mixer control */ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), @@ -7092,7 +7618,7 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = { }, { } /* end */ -}; +}; static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { /* output mixer control */ @@ -7113,7 +7639,7 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), - + /* Capture mixer control */ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), @@ -7134,7 +7660,7 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes), }, { } /* end */ -}; +}; static struct snd_kcontrol_new alc861_asus_mixer[] = { /* output mixer control */ @@ -7154,8 +7680,8 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = { HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), /* was HDA_INPUT (why?) */ - + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), + /* Capture mixer control */ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), @@ -7239,7 +7765,7 @@ static struct hda_verb alc861_base_init_verbs[] = { {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, @@ -7249,7 +7775,8 @@ static struct hda_verb alc861_base_init_verbs[] = { {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front) + /* hp used DAC 3 (Front) */ + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, { } @@ -7300,7 +7827,7 @@ static struct hda_verb alc861_threestack_init_verbs[] = { {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, @@ -7310,7 +7837,8 @@ static struct hda_verb alc861_threestack_init_verbs[] = { {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front) + /* hp used DAC 3 (Front) */ + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, { } }; @@ -7329,7 +7857,8 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = { { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, /* port-E for HP out (front panel) */ - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80 + /* this has to be set to VREF80 */ + { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* route front PCM to HP */ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, /* port-F for mic-in (front panel) with vref */ @@ -7360,7 +7889,7 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = { {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, @@ -7370,7 +7899,8 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = { {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front) + /* hp used DAC 3 (Front) */ + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, { } }; @@ -7379,7 +7909,9 @@ static struct hda_verb alc861_asus_init_verbs[] = { /* * Unmute ADC0 and set the default input to mic-in */ - /* port-A for surround (rear panel) | according to codec#0 this is the HP jack*/ + /* port-A for surround (rear panel) + * according to codec#0 this is the HP jack + */ { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */ /* route front PCM to HP */ { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 }, @@ -7391,7 +7923,8 @@ static struct hda_verb alc861_asus_init_verbs[] = { { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, /* port-E for HP out (front panel) */ - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* this has to be set to VREF80 */ + /* this has to be set to VREF80 */ + { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* route front PCM to HP */ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, /* port-F for mic-in (front panel) with vref */ @@ -7421,7 +7954,7 @@ static struct hda_verb alc861_asus_init_verbs[] = { {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, /* Output 0~12 step */ + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, @@ -7431,7 +7964,8 @@ static struct hda_verb alc861_asus_init_verbs[] = { {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, /* hp used DAC 3 (Front) */ + /* hp used DAC 3 (Front) */ + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, { } }; @@ -7450,7 +7984,7 @@ static struct hda_verb alc861_auto_init_verbs[] = { /* * Unmute ADC0 and set the default input to mic-in */ -// {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, + /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* Unmute DAC0~3 & spdif out*/ @@ -7483,21 +8017,21 @@ static struct hda_verb alc861_auto_init_verbs[] = { {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, // set Mic 1 + {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */ { } }; static struct hda_verb alc861_toshiba_init_verbs[] = { {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, - + { } }; @@ -7521,9 +8055,6 @@ static void alc861_toshiba_automute(struct hda_codec *codec) static void alc861_toshiba_unsol_event(struct hda_codec *codec, unsigned int res) { - /* Looks like the unsol event is incompatible with the standard - * definition. 6bit tag is placed at 26 bit! - */ if ((res >> 26) == ALC880_HP_EVENT) alc861_toshiba_automute(codec); } @@ -7568,7 +8099,8 @@ static struct hda_input_mux alc861_capture_source = { }; /* fill in the dac_nids table from the parsed pin configuration */ -static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg) +static int alc861_auto_fill_dac_nids(struct alc_spec *spec, + const struct auto_pin_cfg *cfg) { int i; hda_nid_t nid; @@ -7591,29 +8123,40 @@ static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) { char name[32]; - static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; + static const char *chname[4] = { + "Front", "Surround", NULL /*CLFE*/, "Side" + }; hda_nid_t nid; int i, idx, err; for (i = 0; i < cfg->line_outs; i++) { nid = spec->multiout.dac_nids[i]; - if (! nid) + if (!nid) continue; if (nid == 0x05) { /* Center/LFE */ - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, + "Center Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 1, 0, + HDA_OUTPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, + "LFE Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 2, 0, + HDA_OUTPUT)); + if (err < 0) return err; } else { - for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++) + for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; + idx++) if (nid == alc861_dac_nids[idx]) break; sprintf(name, "%s Playback Switch", chname[idx]); - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, + HDA_OUTPUT)); + if (err < 0) return err; } } @@ -7625,13 +8168,15 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) int err; hda_nid_t nid; - if (! pin) + if (!pin) return 0; if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) { nid = 0x03; - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, + "Headphone Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); + if (err < 0) return err; spec->multiout.hp_nid = nid; } @@ -7639,32 +8184,33 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) } /* create playback/capture controls for input pins */ -static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) +static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, + const struct auto_pin_cfg *cfg) { struct hda_input_mux *imux = &spec->private_imux; int i, err, idx, idx1; for (i = 0; i < AUTO_PIN_LAST; i++) { - switch(cfg->input_pins[i]) { + switch (cfg->input_pins[i]) { case 0x0c: idx1 = 1; - idx = 2; // Line In + idx = 2; /* Line In */ break; case 0x0f: idx1 = 2; - idx = 2; // Line In + idx = 2; /* Line In */ break; case 0x0d: idx1 = 0; - idx = 1; // Mic In + idx = 1; /* Mic In */ break; - case 0x10: + case 0x10: idx1 = 3; - idx = 1; // Mic In + idx = 1; /* Mic In */ break; case 0x11: idx1 = 4; - idx = 0; // CD + idx = 0; /* CD */ break; default: continue; @@ -7677,7 +8223,7 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const str imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; imux->items[imux->num_items].index = idx1; - imux->num_items++; + imux->num_items++; } return 0; } @@ -7702,13 +8248,16 @@ static struct snd_kcontrol_new alc861_capture_mixer[] = { { } /* end */ }; -static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, +static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, + hda_nid_t nid, int pin_type, int dac_idx) { /* set as output */ - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); - snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, + pin_type); + snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_UNMUTE); } @@ -7717,10 +8266,13 @@ static void alc861_auto_init_multi_out(struct hda_codec *codec) struct alc_spec *spec = codec->spec; int i; + alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b); for (i = 0; i < spec->autocfg.line_outs; i++) { hda_nid_t nid = spec->autocfg.line_out_pins[i]; + int pin_type = get_pin_type(spec->autocfg.line_out_type); if (nid) - alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]); + alc861_auto_set_output_and_unmute(codec, nid, pin_type, + spec->multiout.dac_nids[i]); } } @@ -7731,7 +8283,8 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) pin = spec->autocfg.hp_pins[0]; if (pin) /* connect to front */ - alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); + alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, + spec->multiout.dac_nids[0]); } static void alc861_auto_init_analog_input(struct hda_codec *codec) @@ -7741,31 +8294,43 @@ static void alc861_auto_init_analog_input(struct hda_codec *codec) for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = spec->autocfg.input_pins[i]; - if ((nid>=0x0c) && (nid <=0x11)) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); + if (nid >= 0x0c && nid <= 0x11) { + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + i <= AUTO_PIN_FRONT_MIC ? + PIN_VREF80 : PIN_IN); } } } /* parse the BIOS configuration and set up the alc_spec */ -/* return 1 if successful, 0 if the proper config is not found, or a negative error code */ +/* return 1 if successful, 0 if the proper config is not found, + * or a negative error code + */ static int alc861_parse_auto_config(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; int err; static hda_nid_t alc861_ignore[] = { 0x1d, 0 }; - if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, - alc861_ignore)) < 0) + err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, + alc861_ignore); + if (err < 0) return err; - if (! spec->autocfg.line_outs) + if (!spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ - if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || - (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || - (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 || - (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) + err = alc861_auto_fill_dac_nids(spec, &spec->autocfg); + if (err < 0) + return err; + err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg); + if (err < 0) + return err; + err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); + if (err < 0) + return err; + err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg); + if (err < 0) return err; spec->multiout.max_channels = spec->multiout.num_dacs * 2; @@ -7817,12 +8382,14 @@ static struct snd_pci_quirk alc861_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST), SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP), SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP), + SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP), SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660_3ST), SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA), SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31), SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31), + SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST), SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST), {} }; @@ -7892,7 +8459,8 @@ static struct alc_config_preset alc861_presets[] = { }, [ALC861_TOSHIBA] = { .mixers = { alc861_toshiba_mixer }, - .init_verbs = { alc861_base_init_verbs, alc861_toshiba_init_verbs }, + .init_verbs = { alc861_base_init_verbs, + alc861_toshiba_init_verbs }, .num_dacs = ARRAY_SIZE(alc861_dac_nids), .dac_nids = alc861_dac_nids, .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), @@ -7944,7 +8512,7 @@ static int patch_alc861(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; - codec->spec = spec; + codec->spec = spec; board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST, alc861_models, @@ -7962,7 +8530,7 @@ static int patch_alc861(struct hda_codec *codec) if (err < 0) { alc_free(codec); return err; - } else if (! err) { + } else if (!err) { printk(KERN_INFO "hda_codec: Cannot set up configuration " "from BIOS. Using base mode...\n"); @@ -8049,7 +8617,7 @@ static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol, idx = ucontrol->value.enumerated.item[0]; if (idx >= imux->num_items) idx = imux->num_items - 1; - if (*cur_val == idx && ! codec->in_resume) + if (*cur_val == idx && !codec->in_resume) return 0; for (i = 0; i < imux->num_items; i++) { unsigned int v = (i == idx) ? 0x7000 : 0x7080; @@ -8193,6 +8761,27 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = { { } /* end */ }; +static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), + /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/ + HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), + + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + + HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + + HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + + { } /* end */ +}; + /* * generic initialization of ADC, input mixers and output mixers */ @@ -8214,10 +8803,10 @@ static struct hda_verb alc861vd_volume_init_verbs[] = { {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(8)}, /* * Set up output mixers (0x02 - 0x05) @@ -8318,6 +8907,68 @@ static struct hda_verb alc861vd_6stack_init_verbs[] = { { } }; +static struct hda_verb alc861vd_eapd_verbs[] = { + {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, + { } +}; + +static struct hda_verb alc861vd_lenovo_unsol_verbs[] = { + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, + {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, + {} +}; + +/* toggle speaker-output according to the hp-jack state */ +static void alc861vd_lenovo_hp_automute(struct hda_codec *codec) +{ + unsigned int present; + unsigned char bits; + + present = snd_hda_codec_read(codec, 0x1b, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; + snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, + 0x80, bits); +} + +static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) +{ + unsigned int present; + unsigned char bits; + + present = snd_hda_codec_read(codec, 0x18, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; + snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, + 0x80, bits); +} + +static void alc861vd_lenovo_automute(struct hda_codec *codec) +{ + alc861vd_lenovo_hp_automute(codec); + alc861vd_lenovo_mic_automute(codec); +} + +static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + switch (res >> 26) { + case ALC880_HP_EVENT: + alc861vd_lenovo_hp_automute(codec); + break; + case ALC880_MIC_EVENT: + alc861vd_lenovo_mic_automute(codec); + break; + } +} + /* pcm configuration: identiacal with ALC880 */ #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture @@ -8332,15 +8983,18 @@ static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { [ALC861VD_3ST] = "3stack", [ALC861VD_3ST_DIG] = "3stack-digout", [ALC861VD_6ST_DIG] = "6stack-digout", + [ALC861VD_LENOVO] = "lenovo", [ALC861VD_AUTO] = "auto", }; static struct snd_pci_quirk alc861vd_cfg_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), - SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_3ST), + SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), + SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), {} }; @@ -8389,6 +9043,22 @@ static struct alc_config_preset alc861vd_presets[] = { .channel_mode = alc861vd_6stack_modes, .input_mux = &alc861vd_capture_source, }, + [ALC861VD_LENOVO] = { + .mixers = { alc861vd_lenovo_mixer }, + .init_verbs = { alc861vd_volume_init_verbs, + alc861vd_3stack_init_verbs, + alc861vd_eapd_verbs, + alc861vd_lenovo_unsol_verbs }, + .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), + .dac_nids = alc660vd_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), + .adc_nids = alc861vd_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), + .channel_mode = alc861vd_3stack_2ch_modes, + .input_mux = &alc861vd_capture_source, + .unsol_event = alc861vd_lenovo_unsol_event, + .init_hook = alc861vd_lenovo_automute, + }, }; /* @@ -8409,11 +9079,13 @@ static void alc861vd_auto_init_multi_out(struct hda_codec *codec) struct alc_spec *spec = codec->spec; int i; + alc_subsystem_id(codec, 0x15, 0x1b, 0x14); for (i = 0; i <= HDA_SIDE; i++) { hda_nid_t nid = spec->autocfg.line_out_pins[i]; + int pin_type = get_pin_type(spec->autocfg.line_out_type); if (nid) alc861vd_auto_set_output_and_unmute(codec, nid, - PIN_OUT, i); + pin_type, i); } } @@ -8466,7 +9138,7 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, int i, err; for (i = 0; i < cfg->line_outs; i++) { - if (! spec->multiout.dac_nids[i]) + if (!spec->multiout.dac_nids[i]) continue; nid_v = alc861vd_idx_to_mixer_vol( alc880_dac_to_idx( @@ -8477,36 +9149,42 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, if (i == 2) { /* Center/LFE */ - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, - "Center Playback Volume", - HDA_COMPOSE_AMP_VAL(nid_v, 1, - 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "Center Playback Volume", + HDA_COMPOSE_AMP_VAL(nid_v, 1, 0, + HDA_OUTPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, - "LFE Playback Volume", - HDA_COMPOSE_AMP_VAL(nid_v, 2, - 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "LFE Playback Volume", + HDA_COMPOSE_AMP_VAL(nid_v, 2, 0, + HDA_OUTPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, - "Center Playback Switch", - HDA_COMPOSE_AMP_VAL(nid_s, 1, - 2, HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, + "Center Playback Switch", + HDA_COMPOSE_AMP_VAL(nid_s, 1, 2, + HDA_INPUT)); + if (err < 0) return err; - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, - "LFE Playback Switch", - HDA_COMPOSE_AMP_VAL(nid_s, 2, - 2, HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, + "LFE Playback Switch", + HDA_COMPOSE_AMP_VAL(nid_s, 2, 2, + HDA_INPUT)); + if (err < 0) return err; } else { sprintf(name, "%s Playback Volume", chname[i]); - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid_v, 3, - 0, HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, + HDA_OUTPUT)); + if (err < 0) return err; sprintf(name, "%s Playback Switch", chname[i]); - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid_v, 3, - 2, HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, name, + HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, + HDA_INPUT)); + if (err < 0) return err; } } @@ -8523,13 +9201,13 @@ static int alc861vd_auto_create_extra_out(struct alc_spec *spec, int err; char name[32]; - if (! pin) + if (!pin) return 0; if (alc880_is_fixed_pin(pin)) { nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); /* specify the DAC as the extra output */ - if (! spec->multiout.hp_nid) + if (!spec->multiout.hp_nid) spec->multiout.hp_nid = nid_v; else spec->multiout.extra_out_nid[0] = nid_v; @@ -8540,22 +9218,22 @@ static int alc861vd_auto_create_extra_out(struct alc_spec *spec, alc880_fixed_pin_idx(pin)); sprintf(name, "%s Playback Volume", pfx); - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, - HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT)); + if (err < 0) return err; sprintf(name, "%s Playback Switch", pfx); - if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, - HDA_INPUT))) < 0) + err = add_control(spec, ALC_CTL_BIND_MUTE, name, + HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT)); + if (err < 0) return err; } else if (alc880_is_multi_pin(pin)) { /* set manual connection */ /* we have only a switch on HP-out PIN */ sprintf(name, "%s Playback Switch", pfx); - if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(pin, 3, 0, - HDA_OUTPUT))) < 0) + err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, + HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); + if (err < 0) return err; } return 0; @@ -8572,21 +9250,31 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) int err; static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; - if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, - alc861vd_ignore)) < 0) + err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, + alc861vd_ignore); + if (err < 0) return err; - if (! spec->autocfg.line_outs) + if (!spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ - if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || - (err = alc861vd_auto_create_multi_out_ctls(spec, - &spec->autocfg)) < 0 || - (err = alc861vd_auto_create_extra_out(spec, - spec->autocfg.speaker_pins[0], "Speaker")) < 0 || - (err = alc861vd_auto_create_extra_out(spec, - spec->autocfg.hp_pins[0], "Headphone")) < 0 || - (err = alc880_auto_create_analog_input_ctls(spec, - &spec->autocfg)) < 0) + err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); + if (err < 0) + return err; + err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg); + if (err < 0) + return err; + err = alc861vd_auto_create_extra_out(spec, + spec->autocfg.speaker_pins[0], + "Speaker"); + if (err < 0) + return err; + err = alc861vd_auto_create_extra_out(spec, + spec->autocfg.hp_pins[0], + "Headphone"); + if (err < 0) + return err; + err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg); + if (err < 0) return err; spec->multiout.max_channels = spec->multiout.num_dacs * 2; @@ -8641,7 +9329,7 @@ static int patch_alc861vd(struct hda_codec *codec) if (err < 0) { alc_free(codec); return err; - } else if (! err) { + } else if (!err) { printk(KERN_INFO "hda_codec: Cannot set up configuration " "from BIOS. Using base mode...\n"); @@ -8675,16 +9363,875 @@ static int patch_alc861vd(struct hda_codec *codec) } /* + * ALC662 support + * + * ALC662 is almost identical with ALC880 but has cleaner and more flexible + * configuration. Each pin widget can choose any input DACs and a mixer. + * Each ADC is connected from a mixer of all inputs. This makes possible + * 6-channel independent captures. + * + * In addition, an independent DAC for the multi-playback (not used in this + * driver yet). + */ +#define ALC662_DIGOUT_NID 0x06 +#define ALC662_DIGIN_NID 0x0a + +static hda_nid_t alc662_dac_nids[4] = { + /* front, rear, clfe, rear_surr */ + 0x02, 0x03, 0x04 +}; + +static hda_nid_t alc662_adc_nids[1] = { + /* ADC1-2 */ + 0x09, +}; +/* input MUX */ +/* FIXME: should be a matrix-type input source selection */ + +static struct hda_input_mux alc662_capture_source = { + .num_items = 4, + .items = { + { "Mic", 0x0 }, + { "Front Mic", 0x1 }, + { "Line", 0x2 }, + { "CD", 0x4 }, + }, +}; + +static struct hda_input_mux alc662_lenovo_101e_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x1 }, + { "Line", 0x2 }, + }, +}; +#define alc662_mux_enum_info alc_mux_enum_info +#define alc662_mux_enum_get alc_mux_enum_get + +static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + const struct hda_input_mux *imux = spec->input_mux; + unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; + hda_nid_t nid = capture_mixers[adc_idx]; + unsigned int *cur_val = &spec->cur_mux[adc_idx]; + unsigned int i, idx; + + idx = ucontrol->value.enumerated.item[0]; + if (idx >= imux->num_items) + idx = imux->num_items - 1; + if (*cur_val == idx && !codec->in_resume) + return 0; + for (i = 0; i < imux->num_items; i++) { + unsigned int v = (i == idx) ? 0x7000 : 0x7080; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, + v | (imux->items[i].index << 8)); + } + *cur_val = idx; + return 1; +} +/* + * 2ch mode + */ +static struct hda_channel_mode alc662_3ST_2ch_modes[1] = { + { 2, NULL } +}; + +/* + * 2ch mode + */ +static struct hda_verb alc662_3ST_ch2_init[] = { + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { } /* end */ +}; + +/* + * 6ch mode + */ +static struct hda_verb alc662_3ST_ch6_init[] = { + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { } /* end */ +}; + +static struct hda_channel_mode alc662_3ST_6ch_modes[2] = { + { 2, alc662_3ST_ch2_init }, + { 6, alc662_3ST_ch6_init }, +}; + +/* + * 2ch mode + */ +static struct hda_verb alc662_sixstack_ch6_init[] = { + { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, + { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, + { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { } /* end */ +}; + +/* + * 6ch mode + */ +static struct hda_verb alc662_sixstack_ch8_init[] = { + { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { } /* end */ +}; + +static struct hda_channel_mode alc662_5stack_modes[2] = { + { 2, alc662_sixstack_ch6_init }, + { 6, alc662_sixstack_ch8_init }, +}; + +/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 + * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b + */ + +static struct snd_kcontrol_new alc662_base_mixer[] = { + /* output mixer control */ + HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + + /*Input mixer control */ + HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT), + + /* Capture mixer control */ + HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .count = 1, + .info = alc_mux_enum_info, + .get = alc_mux_enum_get, + .put = alc_mux_enum_put, + }, + { } /* end */ +}; + +static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 1, + .info = alc662_mux_enum_info, + .get = alc662_mux_enum_get, + .put = alc662_mux_enum_put, + }, + { } /* end */ +}; + +static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT), + HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 1, + .info = alc662_mux_enum_info, + .get = alc662_mux_enum_get, + .put = alc662_mux_enum_put, + }, + { } /* end */ +}; + +static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT), + HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x03, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("iSpeaker Playback Switch", 0x03, 2, HDA_INPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 1, + .info = alc662_mux_enum_info, + .get = alc662_mux_enum_get, + .put = alc662_mux_enum_put, + }, + { } /* end */ +}; + +static struct snd_kcontrol_new alc662_chmode_mixer[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Channel Mode", + .info = alc_ch_mode_info, + .get = alc_ch_mode_get, + .put = alc_ch_mode_put, + }, + { } /* end */ +}; + +static struct hda_verb alc662_init_verbs[] = { + /* ADC: mute amp left and right */ + {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, + /* Front mixer: unmute input/output amp left and right (volume = 0) */ + + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, + + {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + + /* Front Pin: output 0 (0x0c) */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + + /* Rear Pin: output 1 (0x0d) */ + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + + /* CLFE Pin: output 2 (0x0e) */ + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + + /* Mic (rear) pin: input vref at 80% */ + {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Front Mic pin: input vref at 80% */ + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Line In pin: input */ + {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Line-2 In: Headphone output (output 0 - 0x0c) */ + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, + /* CD pin widget for input */ + {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + + /* FIXME: use matrix-type input source selection */ + /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ + /* Input mixer */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, + { } +}; + +static struct hda_verb alc662_sue_init_verbs[] = { + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, + {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, + {} +}; + +/* + * generic initialization of ADC, input mixers and output mixers + */ +static struct hda_verb alc662_auto_init_verbs[] = { + /* + * Unmute ADC and set the default input to mic-in + */ + {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + + /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback + * mixer widget + * Note: PASD motherboards uses the Line In 2 as the input for front + * panel mic (mic 2) + */ + /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, + + /* + * Set up output mixers (0x0c - 0x0f) + */ + /* set vol=0 to output mixers */ + {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + + /* set up input amps for analog loopback */ + /* Amp Indices: DAC = 0, mixer = 1 */ + {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + + + /* FIXME: use matrix-type input source selection */ + /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ + /* Input mixer */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, + /*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/ + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, + + { } +}; + +/* capture mixer elements */ +static struct snd_kcontrol_new alc662_capture_mixer[] = { + HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* The multiple "Capture Source" controls confuse alsamixer + * So call somewhat different.. + * FIXME: the controls appear in the "playback" view! + */ + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 1, + .info = alc882_mux_enum_info, + .get = alc882_mux_enum_get, + .put = alc882_mux_enum_put, + }, + { } /* end */ +}; + +static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec) +{ + unsigned int present; + unsigned char bits; + + present = snd_hda_codec_read(codec, 0x14, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; + snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, + 0x80, bits); +} + +static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) +{ + unsigned int present; + unsigned char bits; + + present = snd_hda_codec_read(codec, 0x1b, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + bits = present ? 0x80 : 0; + snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, + 0x80, bits); + snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, + 0x80, bits); +} + +static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) == ALC880_HP_EVENT) + alc662_lenovo_101e_all_automute(codec); + if ((res >> 26) == ALC880_FRONT_EVENT) + alc662_lenovo_101e_ispeaker_automute(codec); +} + + +/* pcm configuration: identiacal with ALC880 */ +#define alc662_pcm_analog_playback alc880_pcm_analog_playback +#define alc662_pcm_analog_capture alc880_pcm_analog_capture +#define alc662_pcm_digital_playback alc880_pcm_digital_playback +#define alc662_pcm_digital_capture alc880_pcm_digital_capture + +/* + * configuration and preset + */ +static const char *alc662_models[ALC662_MODEL_LAST] = { + [ALC662_3ST_2ch_DIG] = "3stack-dig", + [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig", + [ALC662_3ST_6ch] = "3stack-6ch", + [ALC662_5ST_DIG] = "6stack-dig", + [ALC662_LENOVO_101E] = "lenovo-101e", + [ALC662_AUTO] = "auto", +}; + +static struct snd_pci_quirk alc662_cfg_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), + {} +}; + +static struct alc_config_preset alc662_presets[] = { + [ALC662_3ST_2ch_DIG] = { + .mixers = { alc662_3ST_2ch_mixer }, + .init_verbs = { alc662_init_verbs }, + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .dac_nids = alc662_dac_nids, + .dig_out_nid = ALC662_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), + .adc_nids = alc662_adc_nids, + .dig_in_nid = ALC662_DIGIN_NID, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), + .channel_mode = alc662_3ST_2ch_modes, + .input_mux = &alc662_capture_source, + }, + [ALC662_3ST_6ch_DIG] = { + .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, + .init_verbs = { alc662_init_verbs }, + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .dac_nids = alc662_dac_nids, + .dig_out_nid = ALC662_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), + .adc_nids = alc662_adc_nids, + .dig_in_nid = ALC662_DIGIN_NID, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), + .channel_mode = alc662_3ST_6ch_modes, + .need_dac_fix = 1, + .input_mux = &alc662_capture_source, + }, + [ALC662_3ST_6ch] = { + .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, + .init_verbs = { alc662_init_verbs }, + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .dac_nids = alc662_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), + .adc_nids = alc662_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), + .channel_mode = alc662_3ST_6ch_modes, + .need_dac_fix = 1, + .input_mux = &alc662_capture_source, + }, + [ALC662_5ST_DIG] = { + .mixers = { alc662_base_mixer, alc662_chmode_mixer }, + .init_verbs = { alc662_init_verbs }, + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .dac_nids = alc662_dac_nids, + .dig_out_nid = ALC662_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), + .adc_nids = alc662_adc_nids, + .dig_in_nid = ALC662_DIGIN_NID, + .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes), + .channel_mode = alc662_5stack_modes, + .input_mux = &alc662_capture_source, + }, + [ALC662_LENOVO_101E] = { + .mixers = { alc662_lenovo_101e_mixer }, + .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .dac_nids = alc662_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), + .adc_nids = alc662_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), + .channel_mode = alc662_3ST_2ch_modes, + .input_mux = &alc662_lenovo_101e_capture_source, + .unsol_event = alc662_lenovo_101e_unsol_event, + .init_hook = alc662_lenovo_101e_all_automute, + }, + +}; + + +/* + * BIOS auto configuration + */ + +/* add playback controls from the parsed DAC table */ +static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, + const struct auto_pin_cfg *cfg) +{ + char name[32]; + static const char *chname[4] = { + "Front", "Surround", NULL /*CLFE*/, "Side" + }; + hda_nid_t nid; + int i, err; + + for (i = 0; i < cfg->line_outs; i++) { + if (!spec->multiout.dac_nids[i]) + continue; + nid = alc880_idx_to_dac(i); + if (i == 2) { + /* Center/LFE */ + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "Center Playback Volume", + HDA_COMPOSE_AMP_VAL(nid, 1, 0, + HDA_OUTPUT)); + if (err < 0) + return err; + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "LFE Playback Volume", + HDA_COMPOSE_AMP_VAL(nid, 2, 0, + HDA_OUTPUT)); + if (err < 0) + return err; + err = add_control(spec, ALC_CTL_BIND_MUTE, + "Center Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 1, 2, + HDA_INPUT)); + if (err < 0) + return err; + err = add_control(spec, ALC_CTL_BIND_MUTE, + "LFE Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 2, 2, + HDA_INPUT)); + if (err < 0) + return err; + } else { + sprintf(name, "%s Playback Volume", chname[i]); + err = add_control(spec, ALC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, + HDA_OUTPUT)); + if (err < 0) + return err; + sprintf(name, "%s Playback Switch", chname[i]); + err = add_control(spec, ALC_CTL_BIND_MUTE, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 2, + HDA_INPUT)); + if (err < 0) + return err; + } + } + return 0; +} + +/* add playback controls for speaker and HP outputs */ +static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, + const char *pfx) +{ + hda_nid_t nid; + int err; + char name[32]; + + if (!pin) + return 0; + + if (alc880_is_fixed_pin(pin)) { + nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); + /* printk("DAC nid=%x\n",nid); */ + /* specify the DAC as the extra output */ + if (!spec->multiout.hp_nid) + spec->multiout.hp_nid = nid; + else + spec->multiout.extra_out_nid[0] = nid; + /* control HP volume/switch on the output mixer amp */ + nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); + sprintf(name, "%s Playback Volume", pfx); + err = add_control(spec, ALC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); + if (err < 0) + return err; + sprintf(name, "%s Playback Switch", pfx); + err = add_control(spec, ALC_CTL_BIND_MUTE, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); + if (err < 0) + return err; + } else if (alc880_is_multi_pin(pin)) { + /* set manual connection */ + /* we have only a switch on HP-out PIN */ + sprintf(name, "%s Playback Switch", pfx); + err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, + HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); + if (err < 0) + return err; + } + return 0; +} + +/* create playback/capture controls for input pins */ +static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec, + const struct auto_pin_cfg *cfg) +{ + struct hda_input_mux *imux = &spec->private_imux; + int i, err, idx; + + for (i = 0; i < AUTO_PIN_LAST; i++) { + if (alc880_is_input_pin(cfg->input_pins[i])) { + idx = alc880_input_pin_idx(cfg->input_pins[i]); + err = new_analog_input(spec, cfg->input_pins[i], + auto_pin_cfg_labels[i], + idx, 0x0b); + if (err < 0) + return err; + imux->items[imux->num_items].label = + auto_pin_cfg_labels[i]; + imux->items[imux->num_items].index = + alc880_input_pin_idx(cfg->input_pins[i]); + imux->num_items++; + } + } + return 0; +} + +static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, + hda_nid_t nid, int pin_type, + int dac_idx) +{ + /* set as output */ + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + /* need the manual connection? */ + if (alc880_is_multi_pin(nid)) { + struct alc_spec *spec = codec->spec; + int idx = alc880_multi_pin_idx(nid); + snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, + AC_VERB_SET_CONNECT_SEL, + alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); + } +} + +static void alc662_auto_init_multi_out(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int i; + + for (i = 0; i <= HDA_SIDE; i++) { + hda_nid_t nid = spec->autocfg.line_out_pins[i]; + int pin_type = get_pin_type(spec->autocfg.line_out_type); + if (nid) + alc662_auto_set_output_and_unmute(codec, nid, pin_type, + i); + } +} + +static void alc662_auto_init_hp_out(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t pin; + + pin = spec->autocfg.hp_pins[0]; + if (pin) /* connect to front */ + /* use dac 0 */ + alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); +} + +#define alc662_is_input_pin(nid) alc880_is_input_pin(nid) +#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID + +static void alc662_auto_init_analog_input(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int i; + + for (i = 0; i < AUTO_PIN_LAST; i++) { + hda_nid_t nid = spec->autocfg.input_pins[i]; + if (alc662_is_input_pin(nid)) { + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + (i <= AUTO_PIN_FRONT_MIC ? + PIN_VREF80 : PIN_IN)); + if (nid != ALC662_PIN_CD_NID) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_MUTE); + } + } +} + +static int alc662_parse_auto_config(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int err; + static hda_nid_t alc662_ignore[] = { 0x1d, 0 }; + + err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, + alc662_ignore); + if (err < 0) + return err; + if (!spec->autocfg.line_outs) + return 0; /* can't find valid BIOS pin config */ + + err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); + if (err < 0) + return err; + err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); + if (err < 0) + return err; + err = alc662_auto_create_extra_out(spec, + spec->autocfg.speaker_pins[0], + "Speaker"); + if (err < 0) + return err; + err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], + "Headphone"); + if (err < 0) + return err; + err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg); + if (err < 0) + return err; + + spec->multiout.max_channels = spec->multiout.num_dacs * 2; + + if (spec->autocfg.dig_out_pin) + spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; + + if (spec->kctl_alloc) + spec->mixers[spec->num_mixers++] = spec->kctl_alloc; + + spec->num_mux_defs = 1; + spec->input_mux = &spec->private_imux; + + if (err < 0) + return err; + else if (err > 0) + /* hack - override the init verbs */ + spec->init_verbs[0] = alc662_auto_init_verbs; + spec->mixers[spec->num_mixers] = alc662_capture_mixer; + spec->num_mixers++; + return err; +} + +/* additional initialization for auto-configuration model */ +static void alc662_auto_init(struct hda_codec *codec) +{ + alc662_auto_init_multi_out(codec); + alc662_auto_init_hp_out(codec); + alc662_auto_init_analog_input(codec); +} + +static int patch_alc662(struct hda_codec *codec) +{ + struct alc_spec *spec; + int err, board_config; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + codec->spec = spec; + + board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, + alc662_models, + alc662_cfg_tbl); + if (board_config < 0) { + printk(KERN_INFO "hda_codec: Unknown model for ALC662, " + "trying auto-probe from BIOS...\n"); + board_config = ALC662_AUTO; + } + + if (board_config == ALC662_AUTO) { + /* automatic parse from the BIOS config */ + err = alc662_parse_auto_config(codec); + if (err < 0) { + alc_free(codec); + return err; + } else if (err) { + printk(KERN_INFO + "hda_codec: Cannot set up configuration " + "from BIOS. Using base mode...\n"); + board_config = ALC662_3ST_2ch_DIG; + } + } + + if (board_config != ALC662_AUTO) + setup_preset(spec, &alc662_presets[board_config]); + + spec->stream_name_analog = "ALC662 Analog"; + spec->stream_analog_playback = &alc662_pcm_analog_playback; + spec->stream_analog_capture = &alc662_pcm_analog_capture; + + spec->stream_name_digital = "ALC662 Digital"; + spec->stream_digital_playback = &alc662_pcm_digital_playback; + spec->stream_digital_capture = &alc662_pcm_digital_capture; + + if (!spec->adc_nids && spec->input_mux) { + spec->adc_nids = alc662_adc_nids; + spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); + } + + codec->patch_ops = alc_patch_ops; + if (board_config == ALC662_AUTO) + spec->init_hook = alc662_auto_init; + + return 0; +} + +/* * patch entries */ struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", - .patch = patch_alc861 }, + .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd }, + { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2", + .patch = patch_alc883 }, + { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", + .patch = patch_alc662 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index c94291bc5367..93ae9c250767 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -62,6 +62,7 @@ enum { STAC_MACBOOK, STAC_MACBOOK_PRO_V1, STAC_MACBOOK_PRO_V2, + STAC_IMAC_INTEL, STAC_922X_MODELS }; @@ -175,8 +176,8 @@ static hda_nid_t stac9205_mux_nids[2] = { 0x19, 0x1a }; -static hda_nid_t stac9205_dmic_nids[3] = { - 0x17, 0x18, 0 +static hda_nid_t stac9205_dmic_nids[2] = { + 0x17, 0x18, }; static hda_nid_t stac9200_pin_nids[8] = { @@ -524,12 +525,6 @@ static unsigned int d945gtp5_pin_configs[10] = { 0x02a19320, 0x40000100, }; -static unsigned int macbook_pin_configs[10] = { - 0x0321e230, 0x03a1e020, 0x400000fd, 0x9017e110, - 0x400000fe, 0x0381e021, 0x1345e240, 0x13c5e22e, - 0x400000fc, 0x400000fb, -}; - static unsigned int macbook_pro_v1_pin_configs[10] = { 0x0321e230, 0x03a1e020, 0x9017e110, 0x01014010, 0x01a19021, 0x0381e021, 0x1345e240, 0x13c5e22e, @@ -542,14 +537,21 @@ static unsigned int macbook_pro_v2_pin_configs[10] = { 0x400000fc, 0x400000fb, }; +static unsigned int imac_intel_pin_configs[10] = { + 0x0121e230, 0x90a70120, 0x9017e110, 0x400000fe, + 0x400000fd, 0x0181e021, 0x1145e040, 0x400000fa, + 0x400000fc, 0x400000fb, +}; + static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { [STAC_D945_REF] = ref922x_pin_configs, [STAC_D945GTP3] = d945gtp3_pin_configs, [STAC_D945GTP5] = d945gtp5_pin_configs, - [STAC_MACMINI] = d945gtp5_pin_configs, - [STAC_MACBOOK] = macbook_pin_configs, + [STAC_MACMINI] = macbook_pro_v1_pin_configs, + [STAC_MACBOOK] = macbook_pro_v1_pin_configs, [STAC_MACBOOK_PRO_V1] = macbook_pro_v1_pin_configs, [STAC_MACBOOK_PRO_V2] = macbook_pro_v2_pin_configs, + [STAC_IMAC_INTEL] = imac_intel_pin_configs, }; static const char *stac922x_models[STAC_922X_MODELS] = { @@ -560,6 +562,7 @@ static const char *stac922x_models[STAC_922X_MODELS] = { [STAC_MACBOOK] = "macbook", [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", [STAC_MACBOOK_PRO_V2] = "macbook-pro", + [STAC_IMAC_INTEL] = "imac-intel", }; static struct snd_pci_quirk stac922x_cfg_tbl[] = { @@ -820,6 +823,17 @@ static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_close(codec, &spec->multiout); } +static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + struct sigmatel_spec *spec = codec->spec; + return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, + stream_tag, format, substream); +} + /* * Analog capture callbacks @@ -854,7 +868,8 @@ static struct hda_pcm_stream stac92xx_pcm_digital_playback = { /* NID is set in stac92xx_build_pcms */ .ops = { .open = stac92xx_dig_playback_pcm_open, - .close = stac92xx_dig_playback_pcm_close + .close = stac92xx_dig_playback_pcm_close, + .prepare = stac92xx_dig_playback_pcm_prepare }, }; @@ -1055,11 +1070,23 @@ static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg) { struct sigmatel_spec *spec = codec->spec; + unsigned int wcaps, wtype; + int i, num_dacs = 0; + + /* use the wcaps cache to count all DACs available for line-outs */ + for (i = 0; i < codec->num_nodes; i++) { + wcaps = codec->wcaps[i]; + wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) + num_dacs++; + } + snd_printdd("%s: total dac count=%d\n", __func__, num_dacs); + switch (cfg->line_outs) { case 3: /* add line-in as side */ - if (cfg->input_pins[AUTO_PIN_LINE]) { + if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) { cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE]; spec->line_switch = 1; cfg->line_outs++; @@ -1067,12 +1094,12 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf break; case 2: /* add line-in as clfe and mic as side */ - if (cfg->input_pins[AUTO_PIN_LINE]) { + if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) { cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE]; spec->line_switch = 1; cfg->line_outs++; } - if (cfg->input_pins[AUTO_PIN_MIC]) { + if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) { cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC]; spec->mic_switch = 1; cfg->line_outs++; @@ -1080,12 +1107,12 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf break; case 1: /* add line-in as surr and mic as clfe */ - if (cfg->input_pins[AUTO_PIN_LINE]) { + if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) { cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE]; spec->line_switch = 1; cfg->line_outs++; } - if (cfg->input_pins[AUTO_PIN_MIC]) { + if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) { cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC]; spec->mic_switch = 1; cfg->line_outs++; @@ -1096,33 +1123,76 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf return 0; } + +static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) +{ + int i; + + for (i = 0; i < spec->multiout.num_dacs; i++) { + if (spec->multiout.dac_nids[i] == nid) + return 1; + } + + return 0; +} + /* - * XXX The line_out pin widget connection list may not be set to the - * desired DAC nid. This is the case on 927x where ports A and B can - * be routed to several DACs. - * - * This requires an analysis of the line-out/hp pin configuration - * to provide a best fit for pin/DAC configurations that are routable. - * For now, 927x DAC4 is not supported and 927x DAC1 output to ports - * A and B is not supported. + * Fill in the dac_nids table from the parsed pin configuration + * This function only works when every pin in line_out_pins[] + * contains atleast one DAC in its connection list. Some 92xx + * codecs are not connected directly to a DAC, such as the 9200 + * and 9202/925x. For those, dac_nids[] must be hard-coded. */ -/* fill in the dac_nids table from the parsed pin configuration */ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid; - int i; - - /* check the pins hardwired to audio widget */ + int i, j, conn_len = 0; + hda_nid_t nid, conn[HDA_MAX_CONNECTIONS]; + unsigned int wcaps, wtype; + for (i = 0; i < cfg->line_outs; i++) { nid = cfg->line_out_pins[i]; - spec->multiout.dac_nids[i] = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CONNECT_LIST, 0) & 0xff; - } + conn_len = snd_hda_get_connections(codec, nid, conn, + HDA_MAX_CONNECTIONS); + for (j = 0; j < conn_len; j++) { + wcaps = snd_hda_param_read(codec, conn[j], + AC_PAR_AUDIO_WIDGET_CAP); + wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + + if (wtype != AC_WID_AUD_OUT || + (wcaps & AC_WCAP_DIGITAL)) + continue; + /* conn[j] is a DAC routed to this line-out */ + if (!is_in_dac_nids(spec, conn[j])) + break; + } + + if (j == conn_len) { + /* error out, no available DAC found */ + snd_printk(KERN_ERR + "%s: No available DAC for pin 0x%x\n", + __func__, nid); + return -ENODEV; + } - spec->multiout.num_dacs = cfg->line_outs; + spec->multiout.dac_nids[i] = conn[j]; + spec->multiout.num_dacs++; + if (conn_len > 1) { + /* select this DAC in the pin's input mux */ + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CONNECT_SEL, j); + + } + } + snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", + spec->multiout.num_dacs, + spec->multiout.dac_nids[0], + spec->multiout.dac_nids[1], + spec->multiout.dac_nids[2], + spec->multiout.dac_nids[3], + spec->multiout.dac_nids[4]); return 0; } @@ -1189,12 +1259,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) { - int i; - - for (i = 0; i < spec->multiout.num_dacs; i++) { - if (spec->multiout.dac_nids[i] == nid) - return 1; - } + if (is_in_dac_nids(spec, nid)) + return 1; if (spec->multiout.hp_nid == nid) return 1; return 0; @@ -1236,12 +1302,10 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, add_spec_dacs(spec, nid); } for (i = 0; i < cfg->speaker_outs; i++) { - nid = snd_hda_codec_read(codec, cfg->speaker_pins[0], 0, + nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; if (check_in_dac_nids(spec, nid)) nid = 0; - if (check_in_dac_nids(spec, nid)) - nid = 0; if (! nid) continue; add_spec_dacs(spec, nid); @@ -1355,7 +1419,7 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const imux->num_items++; } - if (imux->num_items == 1) { + if (imux->num_items) { /* * Set the current input for the muxes. * The STAC9221 has two input muxes with identical source @@ -1675,8 +1739,12 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, { unsigned int pin_ctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); - if (flag == AC_PINCTL_OUT_EN && (pin_ctl & AC_PINCTL_IN_EN)) - return; + + /* if setting pin direction bits, clear the current + direction bits first */ + if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) + pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_ctl | flag); @@ -1751,6 +1819,7 @@ static int stac92xx_resume(struct hda_codec *codec) stac92xx_init(codec); stac92xx_set_config_regs(codec); + snd_hda_resume_ctls(codec, spec->mixer); for (i = 0; i < spec->num_mixers; i++) snd_hda_resume_ctls(codec, spec->mixers[i]); if (spec->multiout.dig_out_nid) @@ -1905,12 +1974,18 @@ static int patch_stac922x(struct hda_codec *codec) */ printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id); switch (codec->subsystem_id) { + case 0x106b0a00: /* MacBook First generatoin */ + spec->board_config = STAC_MACBOOK; + break; case 0x106b0200: /* MacBook Pro first generation */ spec->board_config = STAC_MACBOOK_PRO_V1; break; case 0x106b1e00: /* MacBook Pro second generation */ spec->board_config = STAC_MACBOOK_PRO_V2; break; + case 0x106b0700: /* Intel-based iMac */ + spec->board_config = STAC_IMAC_INTEL; + break; } } @@ -1931,7 +2006,7 @@ static int patch_stac922x(struct hda_codec *codec) spec->adc_nids = stac922x_adc_nids; spec->mux_nids = stac922x_mux_nids; - spec->num_muxes = 2; + spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); spec->num_dmics = 0; spec->init = stac922x_core_init; @@ -1992,7 +2067,7 @@ static int patch_stac927x(struct hda_codec *codec) case STAC_D965_3ST: spec->adc_nids = stac927x_adc_nids; spec->mux_nids = stac927x_mux_nids; - spec->num_muxes = 3; + spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); spec->num_dmics = 0; spec->init = d965_core_init; spec->mixer = stac9227_mixer; @@ -2000,7 +2075,7 @@ static int patch_stac927x(struct hda_codec *codec) case STAC_D965_5ST: spec->adc_nids = stac927x_adc_nids; spec->mux_nids = stac927x_mux_nids; - spec->num_muxes = 3; + spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); spec->num_dmics = 0; spec->init = d965_core_init; spec->mixer = stac9227_mixer; @@ -2008,7 +2083,7 @@ static int patch_stac927x(struct hda_codec *codec) default: spec->adc_nids = stac927x_adc_nids; spec->mux_nids = stac927x_mux_nids; - spec->num_muxes = 3; + spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); spec->num_dmics = 0; spec->init = stac927x_core_init; spec->mixer = stac927x_mixer; @@ -2067,9 +2142,9 @@ static int patch_stac9205(struct hda_codec *codec) spec->adc_nids = stac9205_adc_nids; spec->mux_nids = stac9205_mux_nids; - spec->num_muxes = 2; + spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); spec->dmic_nids = stac9205_dmic_nids; - spec->num_dmics = 2; + spec->num_dmics = ARRAY_SIZE(stac9205_dmic_nids); spec->dmux_nid = 0x1d; spec->init = stac9205_core_init; @@ -2294,6 +2369,7 @@ static struct snd_pci_quirk stac9872_cfg_tbl[] = { SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO), SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO), SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO), + SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO), {} }; diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 2b11ac8689b9..ba32d1e52cb8 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -377,6 +377,17 @@ static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_close(codec, &spec->multiout); } +static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + struct via_spec *spec = codec->spec; + return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, + stream_tag, format, substream); +} + /* * Analog capture */ @@ -433,7 +444,8 @@ static struct hda_pcm_stream vt1708_pcm_digital_playback = { /* NID is set in via_build_pcms */ .ops = { .open = via_dig_playback_pcm_open, - .close = via_dig_playback_pcm_close + .close = via_dig_playback_pcm_close, + .prepare = via_dig_playback_pcm_prepare }, }; diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c index 6e22d326df32..44bbb630b949 100644 --- a/sound/pci/ice1712/amp.c +++ b/sound/pci/ice1712/amp.c @@ -75,7 +75,7 @@ static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice) /* entry point */ -const struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = { { .subvendor = VT1724_SUBDEVICE_AV710, .name = "Chaintech AV-710", diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h index 7b667bad0c6b..a0fc89b48122 100644 --- a/sound/pci/ice1712/amp.h +++ b/sound/pci/ice1712/amp.h @@ -42,7 +42,7 @@ #define WM_DAC_CTRL 0x02 #define WM_INT_CTRL 0x03 -extern const struct snd_ice1712_card_info snd_vt1724_amp_cards[]; +extern struct snd_ice1712_card_info snd_vt1724_amp_cards[]; #endif /* __SOUND_AMP_H */ diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 6941d85dfec9..66bacde1ead3 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -1411,7 +1411,7 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl * mixers */ -static const struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { +static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", @@ -1526,7 +1526,7 @@ static const struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { } }; -static const struct snd_kcontrol_new wm_controls[] __devinitdata = { +static struct snd_kcontrol_new wm_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Switch", @@ -1592,7 +1592,7 @@ static const struct snd_kcontrol_new wm_controls[] __devinitdata = { } }; -static const struct snd_kcontrol_new ac97_controls[] __devinitdata = { +static struct snd_kcontrol_new ac97_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "AC97 Playback Switch", @@ -1697,7 +1697,7 @@ static const struct snd_kcontrol_new ac97_controls[] __devinitdata = { } }; -static const struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { +static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "AC97 Playback Switch", @@ -1829,7 +1829,7 @@ static const struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { }; -static const struct snd_kcontrol_new cs8415_controls[] __devinitdata = { +static struct snd_kcontrol_new cs8415_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), @@ -2107,7 +2107,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) * hence the driver needs to sets up it properly. */ -static const unsigned char aureon51_eeprom[] __devinitdata = { +static unsigned char aureon51_eeprom[] __devinitdata = { [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */ [ICE_EEP2_ACLINK] = 0x80, /* I2S */ [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ @@ -2123,7 +2123,7 @@ static const unsigned char aureon51_eeprom[] __devinitdata = { [ICE_EEP2_GPIO_STATE2] = 0x00, }; -static const unsigned char aureon71_eeprom[] __devinitdata = { +static unsigned char aureon71_eeprom[] __devinitdata = { [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */ [ICE_EEP2_ACLINK] = 0x80, /* I2S */ [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ @@ -2140,7 +2140,7 @@ static const unsigned char aureon71_eeprom[] __devinitdata = { }; #define prodigy71_eeprom aureon71_eeprom -static const unsigned char prodigy71lt_eeprom[] __devinitdata = { +static unsigned char prodigy71lt_eeprom[] __devinitdata = { [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */ [ICE_EEP2_ACLINK] = 0x80, /* I2S */ [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ @@ -2158,7 +2158,7 @@ static const unsigned char prodigy71lt_eeprom[] __devinitdata = { #define prodigy71xt_eeprom prodigy71lt_eeprom /* entry point */ -const struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = { { .subvendor = VT1724_SUBDEVICE_AUREON51_SKY, .name = "Terratec Aureon 5.1-Sky", diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h index 79e58e88ed47..c253b8e2c789 100644 --- a/sound/pci/ice1712/aureon.h +++ b/sound/pci/ice1712/aureon.h @@ -38,7 +38,7 @@ #define VT1724_SUBDEVICE_PRODIGY71LT 0x32315441 /* PRODIGY 7.1 LT */ #define VT1724_SUBDEVICE_PRODIGY71XT 0x36315441 /* PRODIGY 7.1 XT*/ -extern const struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; +extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; /* GPIO bits */ #define AUREON_CS8415_CS (1 << 22) diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 3eeb36c6e985..af659800c9b0 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -416,7 +416,7 @@ static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kco return 0; } -static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata = +static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata = { .access = (SNDRV_CTL_ELEM_ACCESS_READ), .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -429,7 +429,7 @@ static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __ * initialize the chips on M-Audio cards */ -static const struct snd_akm4xxx akm_audiophile __devinitdata = { +static struct snd_akm4xxx akm_audiophile __devinitdata = { .type = SND_AK4528, .num_adcs = 2, .num_dacs = 2, @@ -438,7 +438,7 @@ static const struct snd_akm4xxx akm_audiophile __devinitdata = { } }; -static const struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = { +static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = { .caddr = 2, .cif = 0, .data_mask = ICE1712_DELTA_AP_DOUT, @@ -450,7 +450,7 @@ static const struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = { .mask_flags = 0, }; -static const struct snd_akm4xxx akm_delta410 __devinitdata = { +static struct snd_akm4xxx akm_delta410 __devinitdata = { .type = SND_AK4529, .num_adcs = 2, .num_dacs = 8, @@ -459,7 +459,7 @@ static const struct snd_akm4xxx akm_delta410 __devinitdata = { } }; -static const struct snd_ak4xxx_private akm_delta410_priv __devinitdata = { +static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = { .caddr = 0, .cif = 0, .data_mask = ICE1712_DELTA_AP_DOUT, @@ -471,7 +471,7 @@ static const struct snd_ak4xxx_private akm_delta410_priv __devinitdata = { .mask_flags = 0, }; -static const struct snd_akm4xxx akm_delta1010lt __devinitdata = { +static struct snd_akm4xxx akm_delta1010lt __devinitdata = { .type = SND_AK4524, .num_adcs = 8, .num_dacs = 8, @@ -481,7 +481,7 @@ static const struct snd_akm4xxx akm_delta1010lt __devinitdata = { } }; -static const struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = { +static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = { .caddr = 2, .cif = 0, /* the default level of the CIF pin from AK4524 */ .data_mask = ICE1712_DELTA_1010LT_DOUT, @@ -493,7 +493,7 @@ static const struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = { .mask_flags = 0, }; -static const struct snd_akm4xxx akm_delta44 __devinitdata = { +static struct snd_akm4xxx akm_delta44 __devinitdata = { .type = SND_AK4524, .num_adcs = 4, .num_dacs = 4, @@ -503,7 +503,7 @@ static const struct snd_akm4xxx akm_delta44 __devinitdata = { } }; -static const struct snd_ak4xxx_private akm_delta44_priv __devinitdata = { +static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = { .caddr = 2, .cif = 0, /* the default level of the CIF pin from AK4524 */ .data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA, @@ -515,7 +515,7 @@ static const struct snd_ak4xxx_private akm_delta44_priv __devinitdata = { .mask_flags = 0, }; -static const struct snd_akm4xxx akm_vx442 __devinitdata = { +static struct snd_akm4xxx akm_vx442 __devinitdata = { .type = SND_AK4524, .num_adcs = 4, .num_dacs = 4, @@ -525,7 +525,7 @@ static const struct snd_akm4xxx akm_vx442 __devinitdata = { } }; -static const struct snd_ak4xxx_private akm_vx442_priv __devinitdata = { +static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = { .caddr = 2, .cif = 0, .data_mask = ICE1712_VX442_DOUT, @@ -650,15 +650,15 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice) * additional controls for M-Audio cards */ -static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata = +static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata = ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0); -static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata = +static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata = ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0); -static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata = +static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata = ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE); -static const struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata = +static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata = ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0); -static const struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata = +static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata = ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE); @@ -735,7 +735,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice) /* entry point */ -const struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = { { .subvendor = ICE1712_SUBDEVICE_DELTA1010, .name = "M Audio Delta 1010", diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h index e47861ccd6e7..2697156607e4 100644 --- a/sound/pci/ice1712/delta.h +++ b/sound/pci/ice1712/delta.h @@ -46,7 +46,7 @@ #define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100 /* entry point */ -extern const struct snd_ice1712_card_info snd_ice1712_delta_cards[]; +extern struct snd_ice1712_card_info snd_ice1712_delta_cards[]; /* diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index 9b7ff302c072..b135389fec6c 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c @@ -332,7 +332,7 @@ static void ews88_setup_spdif(struct snd_ice1712 *ice, int rate) /* */ -static const struct snd_akm4xxx akm_ews88mt __devinitdata = { +static struct snd_akm4xxx akm_ews88mt __devinitdata = { .num_adcs = 8, .num_dacs = 8, .type = SND_AK4524, @@ -342,7 +342,7 @@ static const struct snd_akm4xxx akm_ews88mt __devinitdata = { } }; -static const struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = { +static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = { .caddr = 2, .cif = 1, /* CIF high */ .data_mask = ICE1712_EWS88_SERIAL_DATA, @@ -354,7 +354,7 @@ static const struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = { .mask_flags = 0, }; -static const struct snd_akm4xxx akm_ewx2496 __devinitdata = { +static struct snd_akm4xxx akm_ewx2496 __devinitdata = { .num_adcs = 2, .num_dacs = 2, .type = SND_AK4524, @@ -363,7 +363,7 @@ static const struct snd_akm4xxx akm_ewx2496 __devinitdata = { } }; -static const struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = { +static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = { .caddr = 2, .cif = 1, /* CIF high */ .data_mask = ICE1712_EWS88_SERIAL_DATA, @@ -375,7 +375,7 @@ static const struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = { .mask_flags = 0, }; -static const struct snd_akm4xxx akm_6fire __devinitdata = { +static struct snd_akm4xxx akm_6fire __devinitdata = { .num_adcs = 6, .num_dacs = 6, .type = SND_AK4524, @@ -384,7 +384,7 @@ static const struct snd_akm4xxx akm_6fire __devinitdata = { } }; -static const struct snd_ak4xxx_private akm_6fire_priv __devinitdata = { +static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = { .caddr = 2, .cif = 1, /* CIF high */ .data_mask = ICE1712_6FIRE_SERIAL_DATA, @@ -578,7 +578,7 @@ static int snd_ice1712_ewx_io_sense_put(struct snd_kcontrol *kcontrol, struct sn return val != nval; } -static const struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Sensitivity Switch", @@ -678,7 +678,7 @@ static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, st return ndata != data; } -static const struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Sensitivity Switch", .info = snd_ice1712_ewx_io_sense_info, @@ -687,7 +687,7 @@ static const struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitda .count = 8, }; -static const struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Output Sensitivity Switch", .info = snd_ice1712_ewx_io_sense_info, @@ -769,7 +769,7 @@ static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct .private_value = xshift | (xinvert << 8),\ } -static const struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = { EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */ EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0), EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0), @@ -909,7 +909,7 @@ static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, str .private_value = xshift | (xinvert << 8),\ } -static const struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Analog Input Select", @@ -989,7 +989,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice) /* entry point */ -const struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = { { .subvendor = ICE1712_SUBDEVICE_EWX2496, .name = "TerraTec EWX24/96", diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h index df449b4741f6..a12a0b053558 100644 --- a/sound/pci/ice1712/ews.h +++ b/sound/pci/ice1712/ews.h @@ -40,7 +40,7 @@ #define ICE1712_SUBDEVICE_PHASE88 0x3b155111 /* entry point */ -extern const struct snd_ice1712_card_info snd_ice1712_ews_cards[]; +extern struct snd_ice1712_card_info snd_ice1712_ews_cards[]; /* TerraTec EWX 24/96 configuration definitions */ diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c index df97313aaf83..8203562ef7e7 100644 --- a/sound/pci/ice1712/hoontech.c +++ b/sound/pci/ice1712/hoontech.c @@ -239,7 +239,7 @@ static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip) static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice) { /* Hoontech STDSP24 with modified hardware */ - static const struct snd_akm4xxx akm_stdsp24_mv __devinitdata = { + static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = { .num_adcs = 2, .num_dacs = 2, .type = SND_AK4524, @@ -248,7 +248,7 @@ static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice) } }; - static const struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = { + static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = { .caddr = 2, .cif = 1, /* CIF high */ .data_mask = ICE1712_STDSP24_SERIAL_DATA, @@ -298,7 +298,7 @@ static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice) /* entry point */ -const struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = { { .subvendor = ICE1712_SUBDEVICE_STDSP24, .name = "Hoontech SoundTrack Audio DSP24", diff --git a/sound/pci/ice1712/hoontech.h b/sound/pci/ice1712/hoontech.h index b62d6e4f6c71..1ee538b20fbf 100644 --- a/sound/pci/ice1712/hoontech.h +++ b/sound/pci/ice1712/hoontech.h @@ -35,7 +35,7 @@ #define ICE1712_SUBDEVICE_STDSP24_MEDIA7_1 0x16141217 /* Hoontech ST Audio DSP24 Media 7.1 */ #define ICE1712_SUBDEVICE_EVENT_EZ8 0x00010001 /* A dummy id for EZ8 */ -extern const struct snd_ice1712_card_info snd_ice1712_hoontech_cards[]; +extern struct snd_ice1712_card_info snd_ice1712_hoontech_cards[]; /* Hoontech SoundTrack Audio DSP 24 GPIO definitions */ diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 830a1bbd7110..6630a0ae9527 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -287,7 +287,7 @@ static int snd_ice1712_digmix_route_ac97_put(struct snd_kcontrol *kcontrol, stru return val != nval; } -static const struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Digital Mixer To AC97", .info = snd_ice1712_digmix_route_ac97_info, @@ -977,11 +977,9 @@ static int snd_ice1712_pro_trigger(struct snd_pcm_substream *substream, { unsigned int what = 0; unsigned int old; - struct list_head *pos; struct snd_pcm_substream *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == ice->playback_pro_substream) { what |= ICE1712_PLAYBACK_START; snd_pcm_trigger_done(s, substream); @@ -1380,7 +1378,7 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc static const DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0); -static const struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Playback Switch", @@ -1404,7 +1402,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devini }, }; -static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Multi Capture Switch", .info = snd_ice1712_pro_mixer_switch_info, @@ -1413,7 +1411,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __d .private_value = 10, }; -static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,SWITCH), .info = snd_ice1712_pro_mixer_switch_info, @@ -1423,7 +1421,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __de .count = 2, }; -static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ), @@ -1435,7 +1433,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __d .tlv = { .p = db_scale_playback } }; -static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,VOLUME), .info = snd_ice1712_pro_mixer_volume_info, @@ -1627,7 +1625,7 @@ static int snd_ice1712_eeprom_get(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = "ICE1712 EEPROM", .access = SNDRV_CTL_ELEM_ACCESS_READ, @@ -1663,7 +1661,7 @@ static int snd_ice1712_spdif_default_put(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata = +static struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), @@ -1714,7 +1712,7 @@ static int snd_ice1712_spdif_maskp_get(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata = +static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -1723,7 +1721,7 @@ static const struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata = .get = snd_ice1712_spdif_maskc_get, }; -static const struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata = +static struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -1750,7 +1748,7 @@ static int snd_ice1712_spdif_stream_put(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata = +static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata = { .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE), @@ -1891,7 +1889,7 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol, return change; } -static const struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Internal Clock", .info = snd_ice1712_pro_internal_clock_info, @@ -1962,7 +1960,7 @@ static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcont return change; } -static const struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Internal Clock Default", .info = snd_ice1712_pro_internal_clock_default_info, @@ -2001,7 +1999,7 @@ static int snd_ice1712_pro_rate_locking_put(struct snd_kcontrol *kcontrol, return change; } -static const struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Rate Locking", .info = snd_ice1712_pro_rate_locking_info, @@ -2040,7 +2038,7 @@ static int snd_ice1712_pro_rate_reset_put(struct snd_kcontrol *kcontrol, return change; } -static const struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Rate Reset", .info = snd_ice1712_pro_rate_reset_info, @@ -2207,7 +2205,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol, return change; } -static const struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Playback Route", .info = snd_ice1712_pro_route_info, @@ -2215,7 +2213,7 @@ static const struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devini .put = snd_ice1712_pro_route_analog_put, }; -static const struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", .info = snd_ice1712_pro_route_info, @@ -2257,7 +2255,7 @@ static int snd_ice1712_pro_volume_rate_put(struct snd_kcontrol *kcontrol, return change; } -static const struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Volume Rate", .info = snd_ice1712_pro_volume_rate_info, @@ -2290,7 +2288,7 @@ static int snd_ice1712_pro_peak_get(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = { +static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Peak", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, @@ -2305,7 +2303,7 @@ static const struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = /* * list of available boards */ -static const struct snd_ice1712_card_info *card_tables[] __devinitdata = { +static struct snd_ice1712_card_info *card_tables[] __devinitdata = { snd_ice1712_hoontech_cards, snd_ice1712_delta_cards, snd_ice1712_ews_cards, @@ -2329,7 +2327,7 @@ static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice, { int dev = 0xa0; /* EEPROM device address */ unsigned int i, size; - const struct snd_ice1712_card_info **tbl, *c; + struct snd_ice1712_card_info * const *tbl, *c; if (! modelname || ! *modelname) { ice->eeprom.subvendor = 0; @@ -2658,7 +2656,7 @@ static int __devinit snd_ice1712_create(struct snd_card *card, * */ -static const struct snd_ice1712_card_info no_matched __devinitdata; +static struct snd_ice1712_card_info no_matched __devinitdata; static int __devinit snd_ice1712_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) @@ -2667,7 +2665,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, struct snd_card *card; struct snd_ice1712 *ice; int pcm_dev = 0, err; - const struct snd_ice1712_card_info **tbl, *c; + struct snd_ice1712_card_info * const *tbl, *c; if (dev >= SNDRV_CARDS) return -ENODEV; diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index c3d9feaaf57d..6ac486d9c138 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h @@ -397,6 +397,9 @@ struct snd_ice1712 { struct ak4114 *ak4114; unsigned int analog: 1; } juli; + struct { + struct ak4114 *ak4114; + } prodigy192; } spec; }; diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 1127ebdf5fec..ee620dea7ef3 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -337,13 +337,11 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); unsigned char what; unsigned char old; - struct list_head *pos; struct snd_pcm_substream *s; what = 0; - snd_pcm_group_for_each(pos, substream) { + snd_pcm_group_for_each_entry(s, substream) { const struct vt1724_pcm_reg *reg; - s = snd_pcm_group_substream_entry(pos); reg = s->runtime->private_data; what |= reg->start; snd_pcm_trigger_done(s, substream); @@ -1318,7 +1316,7 @@ static int snd_vt1724_eeprom_get(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = { +static struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = "ICE1724 EEPROM", .access = SNDRV_CTL_ELEM_ACCESS_READ, @@ -1431,7 +1429,7 @@ static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol, return (val != old); } -static const struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata = +static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), @@ -1463,7 +1461,7 @@ static int snd_vt1724_spdif_maskp_get(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata = +static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -1472,7 +1470,7 @@ static const struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata = .get = snd_vt1724_spdif_maskc_get, }; -static const struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata = +static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -1517,7 +1515,7 @@ static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol, return old != val; } -static const struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata = +static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, /* FIXME: the following conflict with IEC958 Playback Route */ @@ -1668,7 +1666,12 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, spin_lock_irq(&ice->reg_lock); oval = inb(ICEMT1724(ice, RATE)); if (ucontrol->value.enumerated.item[0] == spdif) { + unsigned char i2s_oval; outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); + /* setting 256fs */ + i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); + outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, + ICEMT1724(ice, I2S_FORMAT)); } else { rate = rates[ucontrol->value.integer.value[0] % 15]; if (rate <= get_max_rate(ice)) { @@ -1695,7 +1698,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, return change; } -static const struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = { +static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Internal Clock", .info = snd_vt1724_pro_internal_clock_info, @@ -1734,7 +1737,7 @@ static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol, return change; } -static const struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = { +static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Rate Locking", .info = snd_vt1724_pro_rate_locking_info, @@ -1773,7 +1776,7 @@ static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol, return change; } -static const struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = { +static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Rate Reset", .info = snd_vt1724_pro_rate_reset_info, @@ -1892,7 +1895,7 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol, digital_route_shift(idx)); } -static const struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = { +static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Playback Route", .info = snd_vt1724_pro_route_info, @@ -1900,7 +1903,7 @@ static const struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinit .put = snd_vt1724_pro_route_analog_put, }; -static const struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = { +static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", .info = snd_vt1724_pro_route_info, @@ -1936,7 +1939,7 @@ static int snd_vt1724_pro_peak_get(struct snd_kcontrol *kcontrol, return 0; } -static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = { +static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Multi Track Peak", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, @@ -1948,9 +1951,9 @@ static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = { * */ -static const struct snd_ice1712_card_info no_matched __devinitdata; +static struct snd_ice1712_card_info no_matched __devinitdata; -static const struct snd_ice1712_card_info *card_tables[] __devinitdata = { +static struct snd_ice1712_card_info *card_tables[] __devinitdata = { snd_vt1724_revo_cards, snd_vt1724_amp_cards, snd_vt1724_aureon_cards, @@ -2009,7 +2012,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice, { const int dev = 0xa0; /* EEPROM device address */ unsigned int i, size; - const struct snd_ice1712_card_info **tbl, *c; + struct snd_ice1712_card_info * const *tbl, *c; if (! modelname || ! *modelname) { ice->eeprom.subvendor = 0; @@ -2308,7 +2311,7 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, struct snd_card *card; struct snd_ice1712 *ice; int pcm_dev = 0, err; - const struct snd_ice1712_card_info **tbl, *c; + struct snd_ice1712_card_info * const *tbl, *c; if (dev >= SNDRV_CARDS) return -ENODEV; @@ -2347,6 +2350,14 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, } c = &no_matched; __found: + /* + * VT1724 has separate DMAs for the analog and the SPDIF streams while + * ICE1712 has only one for both (mixed up). + * + * Confusingly the analog PCM is named "professional" here because it + * was called so in ice1712 driver, and vt1724 driver is derived from + * ice1712 driver. + */ if ((err = snd_vt1724_pcm_profi(ice, pcm_dev++)) < 0) { snd_card_free(card); diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index d88172fa95da..3d8e74e493d7 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c @@ -125,7 +125,7 @@ static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) snd_akm4xxx_reset(ak, 0); } -static const struct snd_akm4xxx akm_juli_dac __devinitdata = { +static struct snd_akm4xxx akm_juli_dac __devinitdata = { .type = SND_AK4358, .num_dacs = 2, .ops = { @@ -138,7 +138,16 @@ static const struct snd_akm4xxx akm_juli_dac __devinitdata = { static int __devinit juli_add_controls(struct snd_ice1712 *ice) { - return snd_ice1712_akm4xxx_build_controls(ice); + int err; + err = snd_ice1712_akm4xxx_build_controls(ice); + if (err < 0) + return err; + /* only capture SPDIF over AK4114 */ + err = snd_ak4114_build(ice->spec.juli.ak4114, NULL, + ice->pcm_pro->streams[SNDRV_PCM_STREAM_CAPTURE].substream); + if (err < 0) + return err; + return 0; } /* @@ -160,13 +169,6 @@ static int __devinit juli_init(struct snd_ice1712 *ice) int err; struct snd_akm4xxx *ak; -#if 0 - for (err = 0; err < 0x20; err++) - juli_ak4114_read(ice, err); - juli_ak4114_write(ice, 0, 0x0f); - juli_ak4114_read(ice, 0); - juli_ak4114_read(ice, 1); -#endif err = snd_ak4114_create(ice->card, juli_ak4114_read, juli_ak4114_write, @@ -206,7 +208,7 @@ static int __devinit juli_init(struct snd_ice1712 *ice) * hence the driver needs to sets up it properly. */ -static const unsigned char juli_eeprom[] __devinitdata = { +static unsigned char juli_eeprom[] __devinitdata = { [ICE_EEP2_SYSCONF] = 0x20, /* clock 512, mpu401, 1xADC, 1xDACs */ [ICE_EEP2_ACLINK] = 0x80, /* I2S */ [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */ @@ -223,7 +225,7 @@ static const unsigned char juli_eeprom[] __devinitdata = { }; /* entry point */ -const struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = { { .subvendor = VT1724_SUBDEVICE_JULI, .name = "ESI Juli@", diff --git a/sound/pci/ice1712/juli.h b/sound/pci/ice1712/juli.h index 1b9294f8bce3..d9f8534fd92e 100644 --- a/sound/pci/ice1712/juli.h +++ b/sound/pci/ice1712/juli.h @@ -5,6 +5,6 @@ #define VT1724_SUBDEVICE_JULI 0x31305345 /* Juli@ */ -extern const struct snd_ice1712_card_info snd_vt1724_juli_cards[]; +extern struct snd_ice1712_card_info snd_vt1724_juli_cards[]; #endif /* __SOUND_JULI_H */ diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index 0751718f4d7b..40a9098af777 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c @@ -89,13 +89,13 @@ static const unsigned char wm_vol[256] = { #define WM_VOL_MAX (sizeof(wm_vol) - 1) #define WM_VOL_MUTE 0x8000 -static const struct snd_akm4xxx akm_phase22 __devinitdata = { +static struct snd_akm4xxx akm_phase22 __devinitdata = { .type = SND_AK4524, .num_dacs = 2, .num_adcs = 2, }; -static const struct snd_ak4xxx_private akm_phase22_priv __devinitdata = { +static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = { .caddr = 2, .cif = 1, .data_mask = 1 << 4, @@ -152,7 +152,7 @@ static int __devinit phase22_add_controls(struct snd_ice1712 *ice) return 0; } -static const unsigned char phase22_eeprom[] __devinitdata = { +static unsigned char phase22_eeprom[] __devinitdata = { [ICE_EEP2_SYSCONF] = 0x00, /* 1xADC, 1xDACs */ [ICE_EEP2_ACLINK] = 0x80, /* I2S */ [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit */ @@ -168,7 +168,7 @@ static const unsigned char phase22_eeprom[] __devinitdata = { [ICE_EEP2_GPIO_STATE2] = 0x00, }; -static const unsigned char phase28_eeprom[] __devinitdata = { +static unsigned char phase28_eeprom[] __devinitdata = { [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */ [ICE_EEP2_ACLINK] = 0x80, /* I2S */ [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ @@ -700,7 +700,7 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ct static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); -static const struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { +static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", @@ -815,7 +815,7 @@ static const struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { } }; -static const struct snd_kcontrol_new wm_controls[] __devinitdata = { +static struct snd_kcontrol_new wm_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Switch", @@ -870,7 +870,7 @@ static int __devinit phase28_add_controls(struct snd_ice1712 *ice) return 0; } -const struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { { .subvendor = VT1724_SUBDEVICE_PHASE22, .name = "Terratec PHASE 22", diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h index ad379a99bf92..13e841b55488 100644 --- a/sound/pci/ice1712/phase.h +++ b/sound/pci/ice1712/phase.h @@ -31,7 +31,7 @@ #define VT1724_SUBDEVICE_PHASE28 0x3b154911 /* entry point */ -extern const struct snd_ice1712_card_info snd_vt1724_phase_cards[]; +extern struct snd_ice1712_card_info snd_vt1724_phase_cards[]; /* PHASE28 GPIO bits */ #define PHASE28_SPI_MISO (1 << 21) diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index 9552497f0765..01c69453ddeb 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c @@ -571,7 +571,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1); * mixers */ -static const struct snd_kcontrol_new pontis_controls[] __devinitdata = { +static struct snd_kcontrol_new pontis_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | @@ -826,7 +826,7 @@ static int __devinit pontis_init(struct snd_ice1712 *ice) * hence the driver needs to sets up it properly. */ -static const unsigned char pontis_eeprom[] __devinitdata = { +static unsigned char pontis_eeprom[] __devinitdata = { [ICE_EEP2_SYSCONF] = 0x08, /* clock 256, mpu401, spdif-in/ADC, 1DAC */ [ICE_EEP2_ACLINK] = 0x80, /* I2S */ [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */ @@ -843,7 +843,7 @@ static const unsigned char pontis_eeprom[] __devinitdata = { }; /* entry point */ -const struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = { { .subvendor = VT1720_SUBDEVICE_PONTIS_MS300, .name = "Pontis MS300", diff --git a/sound/pci/ice1712/pontis.h b/sound/pci/ice1712/pontis.h index 1a418255c19e..d0d1378b935c 100644 --- a/sound/pci/ice1712/pontis.h +++ b/sound/pci/ice1712/pontis.h @@ -28,6 +28,6 @@ #define VT1720_SUBDEVICE_PONTIS_MS300 0x00020002 /* a dummy id for MS300 */ -extern const struct snd_ice1712_card_info snd_vt1720_pontis_cards[]; +extern struct snd_ice1712_card_info snd_vt1720_pontis_cards[]; #endif /* __SOUND_PONTIS_H */ diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index 31cc66eb9f8f..f03c02c07743 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c @@ -2,6 +2,37 @@ * ALSA driver for ICEnsemble VT1724 (Envy24HT) * * Lowlevel functions for AudioTrak Prodigy 192 cards + * Supported IEC958 input from optional MI/ODI/O add-on card. + * + * Specifics (SW, HW): + * ------------------- + * * 49.5MHz crystal + * * SPDIF-OUT on the card: + * - coax (through isolation transformer)/toslink supplied by + * 74HC04 gates - 3 in parallel + * - output switched between on-board CD drive dig-out connector + * and ice1724 SPDTX pin, using 74HC02 NOR gates, controlled + * by GPIO20 (0 = CD dig-out, 1 = SPDTX) + * * SPDTX goes straight to MI/ODI/O card's SPDIF-OUT coax + * + * * MI/ODI/O card: AK4114 based, used for iec958 input only + * - toslink input -> RX0 + * - coax input -> RX1 + * - 4wire protocol: + * AK4114 ICE1724 + * ------------------------------ + * CDTO (pin 32) -- GPIO11 pin 86 + * CDTI (pin 33) -- GPIO10 pin 77 + * CCLK (pin 34) -- GPIO9 pin 76 + * CSN (pin 35) -- GPIO8 pin 75 + * - output data Mode 7 (24bit, I2S, slave) + * - both MCKO1 and MCKO2 of ak4114 are fed to FPGA, which + * outputs master clock to SPMCLKIN of ice1724. + * Experimentally I found out that only a combination of + * OCKS0=1, OCKS1=1 (128fs, 64fs output) and ice1724 - + * VT1724_MT_I2S_MCLK_128X=0 (256fs input) yields correct + * sampling rate. That means the the FPGA doubles the + * MCK01 rate. * * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de> * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca> @@ -356,6 +387,47 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl return 0; } #endif +static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[2] = { "Line In", "Mic" }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) + uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + + return 0; +} + + +static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + unsigned char val; + + val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); + ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1; + return 0; +} + +static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + unsigned char new, old; + int change; + old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); + new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80); + change = (new != old); + if (change) + stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); + return change; +} static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); @@ -364,7 +436,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); * mixers */ -static const struct snd_kcontrol_new stac_controls[] __devinitdata = { +static struct snd_kcontrol_new stac_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", @@ -406,7 +478,7 @@ static const struct snd_kcontrol_new stac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Switch", + .name = "ADC Capture Switch", .count = 1, .info = stac9460_adc_mute_info, .get = stac9460_adc_mute_get, @@ -417,13 +489,21 @@ static const struct snd_kcontrol_new stac_controls[] __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "ADC Volume", + .name = "ADC Capture Volume", .count = 1, .info = stac9460_adc_vol_info, .get = stac9460_adc_vol_get, .put = stac9460_adc_vol_put, .tlv = { .p = db_scale_adc } }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Capture Input", + .info = stac9460_mic_sw_info, + .get = stac9460_mic_sw_get, + .put = stac9460_mic_sw_put, + + }, #if 0 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -456,19 +536,261 @@ static const struct snd_kcontrol_new stac_controls[] __devinitdata = { #endif }; + +/* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */ +/* CDTO (pin 32) -- GPIO11 pin 86 + * CDTI (pin 33) -- GPIO10 pin 77 + * CCLK (pin 34) -- GPIO9 pin 76 + * CSN (pin 35) -- GPIO8 pin 75 + */ +#define AK4114_ADDR 0x00 /* C1-C0: Chip Address + * (According to datasheet fixed to “00â€) + */ + +/* + * 4wire ak4114 protocol - writing data + */ +static void write_data(struct snd_ice1712 *ice, unsigned int gpio, + unsigned int data, int idx) +{ + for (; idx >= 0; idx--) { + /* drop clock */ + gpio &= ~VT1724_PRODIGY192_CCLK; + snd_ice1712_gpio_write(ice, gpio); + udelay(1); + /* set data */ + if (data & (1 << idx)) + gpio |= VT1724_PRODIGY192_CDOUT; + else + gpio &= ~VT1724_PRODIGY192_CDOUT; + snd_ice1712_gpio_write(ice, gpio); + udelay(1); + /* raise clock */ + gpio |= VT1724_PRODIGY192_CCLK; + snd_ice1712_gpio_write(ice, gpio); + udelay(1); + } +} + +/* + * 4wire ak4114 protocol - reading data + */ +static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio, + int idx) +{ + unsigned char data = 0; + + for (; idx >= 0; idx--) { + /* drop clock */ + gpio &= ~VT1724_PRODIGY192_CCLK; + snd_ice1712_gpio_write(ice, gpio); + udelay(1); + /* read data */ + if (snd_ice1712_gpio_read(ice) & VT1724_PRODIGY192_CDIN) + data |= (1 << idx); + udelay(1); + /* raise clock */ + gpio |= VT1724_PRODIGY192_CCLK; + snd_ice1712_gpio_write(ice, gpio); + udelay(1); + } + return data; +} +/* + * 4wire ak4114 protocol - starting sequence + */ +static unsigned int prodigy192_4wire_start(struct snd_ice1712 *ice) +{ + unsigned int tmp; + + snd_ice1712_save_gpio_status(ice); + tmp = snd_ice1712_gpio_read(ice); + + tmp |= VT1724_PRODIGY192_CCLK; /* high at init */ + tmp &= ~VT1724_PRODIGY192_CS; /* drop chip select */ + snd_ice1712_gpio_write(ice, tmp); + udelay(1); + return tmp; +} + +/* + * 4wire ak4114 protocol - final sequence + */ +static void prodigy192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp) +{ + tmp |= VT1724_PRODIGY192_CS; /* raise chip select */ + snd_ice1712_gpio_write(ice, tmp); + udelay(1); + snd_ice1712_restore_gpio_status(ice); +} + +/* + * Write data to addr register of ak4114 + */ +static void prodigy192_ak4114_write(void *private_data, unsigned char addr, + unsigned char data) +{ + struct snd_ice1712 *ice = private_data; + unsigned int tmp, addrdata; + tmp = prodigy192_4wire_start(ice); + addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f); + addrdata = (addrdata << 8) | data; + write_data(ice, tmp, addrdata, 15); + prodigy192_4wire_finish(ice, tmp); +} + +/* + * Read data from addr register of ak4114 + */ +static unsigned char prodigy192_ak4114_read(void *private_data, + unsigned char addr) +{ + struct snd_ice1712 *ice = private_data; + unsigned int tmp; + unsigned char data; + + tmp = prodigy192_4wire_start(ice); + write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7); + data = read_data(ice, tmp, 7); + prodigy192_4wire_finish(ice, tmp); + return data; +} + + +static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[2] = { "Toslink", "Coax" }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) + uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + + +static int ak4114_input_sw_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + unsigned char val; + + val = prodigy192_ak4114_read(ice, AK4114_REG_IO1); + /* AK4114_IPS0 bit = 0 -> RX0 = Toslink + * AK4114_IPS0 bit = 1 -> RX1 = Coax + */ + ucontrol->value.enumerated.item[0] = (val & AK4114_IPS0) ? 1 : 0; + return 0; +} + +static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + unsigned char new, old, itemvalue; + int change; + + old = prodigy192_ak4114_read(ice, AK4114_REG_IO1); + /* AK4114_IPS0 could be any bit */ + itemvalue = (ucontrol->value.enumerated.item[0]) ? 0xff : 0x00; + + new = (itemvalue & AK4114_IPS0) | (old & ~AK4114_IPS0); + change = (new != old); + if (change) + prodigy192_ak4114_write(ice, AK4114_REG_IO1, new); + return change; +} + + +static const struct snd_kcontrol_new ak4114_controls[] __devinitdata = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "MIODIO IEC958 Capture Input", + .info = ak4114_input_sw_info, + .get = ak4114_input_sw_get, + .put = ak4114_input_sw_put, + + } +}; + + +static int prodigy192_ak4114_init(struct snd_ice1712 *ice) +{ + static const unsigned char ak4114_init_vals[] = { + AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1, + /* ice1724 expects I2S and provides clock, + * DEM0 disables the deemphasis filter + */ + AK4114_DIF_I24I2S | AK4114_DEM0 , + AK4114_TX1E, + AK4114_EFH_1024 | AK4114_DIT, /* default input RX0 */ + 0, + 0 + }; + static const unsigned char ak4114_init_txcsb[] = { + 0x41, 0x02, 0x2c, 0x00, 0x00 + }; + + return snd_ak4114_create(ice->card, + prodigy192_ak4114_read, + prodigy192_ak4114_write, + ak4114_init_vals, ak4114_init_txcsb, + ice, &ice->spec.prodigy192.ak4114); +} + static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice) { unsigned int i; int err; for (i = 0; i < ARRAY_SIZE(stac_controls); i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&stac_controls[i], ice)); + err = snd_ctl_add(ice->card, + snd_ctl_new1(&stac_controls[i], ice)); + if (err < 0) + return err; + } + if (ice->spec.prodigy192.ak4114) { + /* ak4114 is connected */ + for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) { + err = snd_ctl_add(ice->card, + snd_ctl_new1(&ak4114_controls[i], + ice)); + if (err < 0) + return err; + } + err = snd_ak4114_build(ice->spec.prodigy192.ak4114, + NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */ + ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); if (err < 0) return err; } return 0; } +/* + * check for presence of MI/ODI/O add-on card with digital inputs + */ +static int prodigy192_miodio_exists(struct snd_ice1712 *ice) +{ + + unsigned char orig_value; + const unsigned char test_data = 0xd1; /* random value */ + unsigned char addr = AK4114_REG_INT0_MASK; /* random SAFE address */ + int exists = 0; + + orig_value = prodigy192_ak4114_read(ice, addr); + prodigy192_ak4114_write(ice, addr, test_data); + if (prodigy192_ak4114_read(ice, addr) == test_data) { + /* ak4114 seems to communicate, apparently exists */ + /* writing back original value */ + prodigy192_ak4114_write(ice, addr, orig_value); + exists = 1; + } + return exists; +} /* * initialize the chip @@ -487,16 +809,30 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice) (unsigned short)-1 }; const unsigned short *p; + int err = 0; /* prodigy 192 */ ice->num_total_dacs = 6; ice->num_total_adcs = 2; + ice->vt1720 = 0; /* ice1724, e.g. 23 GPIOs */ /* initialize codec */ p = stac_inits_prodigy; for (; *p != (unsigned short)-1; p += 2) stac9460_put(ice, p[0], p[1]); + /* MI/ODI/O add on card with AK4114 */ + if (prodigy192_miodio_exists(ice)) { + err = prodigy192_ak4114_init(ice); + /* from this moment if err = 0 then + * ice->spec.prodigy192.ak4114 should not be null + */ + snd_printdd("AK4114 initialized with status %d\n", err); + } else + snd_printdd("AK4114 not found\n"); + if (err < 0) + return err; + return 0; } @@ -506,25 +842,31 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice) * hence the driver needs to sets up it properly. */ -static const unsigned char prodigy71_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC, 4DACs */ +static unsigned char prodigy71_eeprom[] __devinitdata = { + [ICE_EEP2_SYSCONF] = 0x6a, /* 49MHz crystal, mpu401, + * spdif-in+ 1 stereo ADC, + * 3 stereo DACs + */ [ICE_EEP2_ACLINK] = 0x80, /* I2S */ [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */ [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, + [ICE_EEP2_GPIO_DIR1] = ~(VT1724_PRODIGY192_CDIN >> 8) , [ICE_EEP2_GPIO_DIR2] = 0xbf, [ICE_EEP2_GPIO_MASK] = 0x00, [ICE_EEP2_GPIO_MASK1] = 0x00, [ICE_EEP2_GPIO_MASK2] = 0x00, [ICE_EEP2_GPIO_STATE] = 0x00, [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, + [ICE_EEP2_GPIO_STATE2] = 0x10, /* GPIO20: 0 = CD drive dig. input + * passthrough, + * 1 = SPDIF-OUT from ice1724 + */ }; /* entry point */ -const struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = { { .subvendor = VT1724_SUBDEVICE_PRODIGY192VE, .name = "Audiotrak Prodigy 192", diff --git a/sound/pci/ice1712/prodigy192.h b/sound/pci/ice1712/prodigy192.h index 2fa2e62b9e04..16a53b459c72 100644 --- a/sound/pci/ice1712/prodigy192.h +++ b/sound/pci/ice1712/prodigy192.h @@ -5,7 +5,15 @@ #define PRODIGY192_STAC9460_ADDR 0x54 #define VT1724_SUBDEVICE_PRODIGY192VE 0x34495345 /* PRODIGY 192 VE */ +/* + * AudioTrak Prodigy192 GPIO definitions for MI/ODI/O card with + * AK4114 (SPDIF-IN) + */ +#define VT1724_PRODIGY192_CS (1 << 8) /* GPIO8, pin 75 */ +#define VT1724_PRODIGY192_CCLK (1 << 9) /* GPIO9, pin 76 */ +#define VT1724_PRODIGY192_CDOUT (1 << 10) /* GPIO10, pin 77 */ +#define VT1724_PRODIGY192_CDIN (1 << 11) /* GPIO11, pin 86 */ -extern const struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[]; +extern struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[]; #endif /* __SOUND_PRODIGY192_H */ diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c index 025a7e8497c3..690ceb340644 100644 --- a/sound/pci/ice1712/revo.c +++ b/sound/pci/ice1712/revo.c @@ -219,7 +219,7 @@ static const struct snd_akm4xxx_adc_channel revo51_adc[] = { }, }; -static const struct snd_akm4xxx akm_revo_front __devinitdata = { +static struct snd_akm4xxx akm_revo_front __devinitdata = { .type = SND_AK4381, .num_dacs = 2, .ops = { @@ -228,7 +228,7 @@ static const struct snd_akm4xxx akm_revo_front __devinitdata = { .dac_info = revo71_front, }; -static const struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { +static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { .caddr = 1, .cif = 0, .data_mask = VT1724_REVO_CDOUT, @@ -240,7 +240,7 @@ static const struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { .mask_flags = 0, }; -static const struct snd_akm4xxx akm_revo_surround __devinitdata = { +static struct snd_akm4xxx akm_revo_surround __devinitdata = { .type = SND_AK4355, .idx_offset = 1, .num_dacs = 6, @@ -250,7 +250,7 @@ static const struct snd_akm4xxx akm_revo_surround __devinitdata = { .dac_info = revo71_surround, }; -static const struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { +static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { .caddr = 3, .cif = 0, .data_mask = VT1724_REVO_CDOUT, @@ -262,7 +262,7 @@ static const struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { .mask_flags = 0, }; -static const struct snd_akm4xxx akm_revo51 __devinitdata = { +static struct snd_akm4xxx akm_revo51 __devinitdata = { .type = SND_AK4358, .num_dacs = 6, .ops = { @@ -271,7 +271,7 @@ static const struct snd_akm4xxx akm_revo51 __devinitdata = { .dac_info = revo51_dac, }; -static const struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { +static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { .caddr = 2, .cif = 0, .data_mask = VT1724_REVO_CDOUT, @@ -283,13 +283,13 @@ static const struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { .mask_flags = 0, }; -static const struct snd_akm4xxx akm_revo51_adc __devinitdata = { +static struct snd_akm4xxx akm_revo51_adc __devinitdata = { .type = SND_AK5365, .num_adcs = 2, .adc_info = revo51_adc, }; -static const struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = { +static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = { .caddr = 2, .cif = 0, .data_mask = VT1724_REVO_CDOUT, @@ -324,7 +324,7 @@ static const struct snd_akm4xxx_dac_channel ap192_dac[] = { AK_DAC("PCM Playback Volume", 2) }; -static const struct snd_akm4xxx akm_ap192 __devinitdata = { +static struct snd_akm4xxx akm_ap192 __devinitdata = { .type = SND_AK4358, .num_dacs = 2, .ops = { @@ -333,7 +333,7 @@ static const struct snd_akm4xxx akm_ap192 __devinitdata = { .dac_info = ap192_dac, }; -static const struct snd_ak4xxx_private akm_ap192_priv __devinitdata = { +static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = { .caddr = 2, .cif = 0, .data_mask = VT1724_REVO_CDOUT, @@ -405,7 +405,7 @@ static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio, return data; } -static unsigned char ap192_4wire_start(struct snd_ice1712 *ice) +static unsigned int ap192_4wire_start(struct snd_ice1712 *ice) { unsigned int tmp; @@ -454,7 +454,7 @@ static unsigned char ap192_ak4114_read(void *private_data, unsigned char addr) return data; } -static int ap192_ak4114_init(struct snd_ice1712 *ice) +static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice) { static const unsigned char ak4114_init_vals[] = { AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1, @@ -582,7 +582,7 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice) } /* entry point */ -const struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = { { .subvendor = VT1724_SUBDEVICE_REVOLUTION71, .name = "M Audio Revolution-7.1", diff --git a/sound/pci/ice1712/revo.h b/sound/pci/ice1712/revo.h index 2a24488fad80..a3ba425911cc 100644 --- a/sound/pci/ice1712/revo.h +++ b/sound/pci/ice1712/revo.h @@ -34,7 +34,7 @@ #define VT1724_SUBDEVICE_AUDIOPHILE192 0x12143236 /* entry point */ -extern const struct snd_ice1712_card_info snd_vt1724_revo_cards[]; +extern struct snd_ice1712_card_info snd_vt1724_revo_cards[]; /* diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c index 72b060d63c29..239524158fe7 100644 --- a/sound/pci/ice1712/vt1720_mobo.c +++ b/sound/pci/ice1712/vt1720_mobo.c @@ -56,7 +56,7 @@ static int __devinit k8x800_add_controls(struct snd_ice1712 *ice) /* EEPROM image */ -static const unsigned char k8x800_eeprom[] __devinitdata = { +static unsigned char k8x800_eeprom[] __devinitdata = { [ICE_EEP2_SYSCONF] = 0x01, /* clock 256, 1ADC, 2DACs */ [ICE_EEP2_ACLINK] = 0x02, /* ACLINK, packed */ [ICE_EEP2_I2S] = 0x00, /* - */ @@ -72,7 +72,7 @@ static const unsigned char k8x800_eeprom[] __devinitdata = { [ICE_EEP2_GPIO_STATE2] = 0x00, /* - */ }; -static const unsigned char sn25p_eeprom[] __devinitdata = { +static unsigned char sn25p_eeprom[] __devinitdata = { [ICE_EEP2_SYSCONF] = 0x01, /* clock 256, 1ADC, 2DACs */ [ICE_EEP2_ACLINK] = 0x02, /* ACLINK, packed */ [ICE_EEP2_I2S] = 0x00, /* - */ @@ -90,7 +90,7 @@ static const unsigned char sn25p_eeprom[] __devinitdata = { /* entry point */ -const struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = { { .subvendor = VT1720_SUBDEVICE_K8X800, .name = "Albatron K8X800 Pro II", diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h index 70af3ad64a5d..0b1b0ee1bea7 100644 --- a/sound/pci/ice1712/vt1720_mobo.h +++ b/sound/pci/ice1712/vt1720_mobo.h @@ -36,6 +36,6 @@ #define VT1720_SUBDEVICE_9CJS 0x0f272327 #define VT1720_SUBDEVICE_SN25P 0x97123650 -extern const struct snd_ice1712_card_info snd_vt1720_mobo_cards[]; +extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[]; #endif /* __SOUND_VT1720_MOBO_H */ diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c index 4a706b16a0b9..04e535c8542b 100644 --- a/sound/pci/ice1712/wtm.c +++ b/sound/pci/ice1712/wtm.c @@ -409,7 +409,7 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, /* * Control tabs */ -static const struct snd_kcontrol_new stac9640_controls[] __devinitdata = { +static struct snd_kcontrol_new stac9640_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 7cf2dcb9d8d4..202f720b34b9 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2493,6 +2493,7 @@ static int intel8x0_resume(struct pci_dev *pci) return -EIO; } pci_set_master(pci); + snd_intel8x0_chip_init(chip, 0); if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED, card->shortname, chip)) { printk(KERN_ERR "intel8x0: unable to grab IRQ %d, " @@ -2502,7 +2503,6 @@ static int intel8x0_resume(struct pci_dev *pci) } chip->irq = pci->irq; synchronize_irq(chip->irq); - snd_intel8x0_chip_init(chip, 0); /* re-initialize mixer stuff */ if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) { @@ -2862,16 +2862,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, ICH_REG_ALI_INTERRUPTSR : ICH_REG_GLOB_STA; chip->int_sta_mask = int_sta_masks; - /* request irq after initializaing int_sta_mask, etc */ - if (request_irq(pci->irq, snd_intel8x0_interrupt, - IRQF_SHARED, card->shortname, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_intel8x0_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; pci_set_master(pci); - synchronize_irq(chip->irq); switch(chip->device_type) { case DEVICE_INTEL_ICH4: @@ -2901,6 +2892,15 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, return err; } + /* request irq after initializaing int_sta_mask, etc */ + if (request_irq(pci->irq, snd_intel8x0_interrupt, + IRQF_SHARED, card->shortname, chip)) { + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + snd_intel8x0_free(chip); + return -EBUSY; + } + chip->irq = pci->irq; + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_intel8x0_free(chip); return err; diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 21d0899ac382..5338243fb035 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -264,9 +264,7 @@ enum MonitorModeSelector { #define COMMAND_ACK_DELAY 13 // number of RTC ticks to wait for an acknowledgement // from the card after sending a command. -#define FIRMWARE_IN_THE_KERNEL - -#ifdef FIRMWARE_IN_THE_KERNEL +#ifdef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL #include "korg1212-firmware.h" static const struct firmware static_dsp_code = { .data = (u8 *)dspCode, @@ -418,6 +416,9 @@ struct snd_korg1212 { MODULE_DESCRIPTION("korg1212"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{KORG,korg1212}}"); +#ifndef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL +MODULE_FIRMWARE("korg/k1212.dsp"); +#endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -2342,26 +2343,25 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev * korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy + offsetof(struct KorgSharedBuffer, AdatTimeCode); +#ifdef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL + dsp_code = &static_dsp_code; +#else err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev); if (err < 0) { release_firmware(dsp_code); -#ifdef FIRMWARE_IN_THE_KERNEL - dsp_code = &static_dsp_code; -#else snd_printk(KERN_ERR "firmware not available\n"); snd_korg1212_free(korg1212); return err; -#endif } +#endif if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), dsp_code->size, &korg1212->dma_dsp) < 0) { snd_printk(KERN_ERR "korg1212: cannot allocate dsp code memory (%zd bytes)\n", dsp_code->size); snd_korg1212_free(korg1212); -#ifdef FIRMWARE_IN_THE_KERNEL - if (dsp_code != &static_dsp_code) +#ifndef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL + release_firmware(dsp_code); #endif - release_firmware(dsp_code); return -ENOMEM; } @@ -2371,10 +2371,9 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev * memcpy(korg1212->dma_dsp.area, dsp_code->data, dsp_code->size); -#ifdef FIRMWARE_IN_THE_KERNEL - if (dsp_code != &static_dsp_code) +#ifndef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL + release_firmware(dsp_code); #endif - release_firmware(dsp_code); rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 4526904e3f86..8a5ff1cb5362 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -59,6 +59,10 @@ MODULE_SUPPORTED_DEVICE("{{ESS,Maestro3 PCI}," "{ESS,Allegro PCI}," "{ESS,Allegro-1 PCI}," "{ESS,Canyon3D-2/LE PCI}}"); +#ifndef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL +MODULE_FIRMWARE("ess/maestro3_assp_kernel.fw"); +MODULE_FIRMWARE("ess/maestro3_assp_minisrc.fw"); +#endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -2101,9 +2105,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip) } -#define FIRMWARE_IN_THE_KERNEL - -#ifdef FIRMWARE_IN_THE_KERNEL +#ifdef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL /* * DSP Code images @@ -2242,7 +2244,7 @@ static const struct firmware assp_minisrc = { .size = sizeof assp_minisrc_image }; -#endif /* FIRMWARE_IN_THE_KERNEL */ +#else /* CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL */ #ifdef __LITTLE_ENDIAN static inline void snd_m3_convert_from_le(const struct firmware *fw) { } @@ -2257,6 +2259,8 @@ static void snd_m3_convert_from_le(const struct firmware *fw) } #endif +#endif /* CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL */ + /* * initialize ASSP @@ -2550,14 +2554,10 @@ static int snd_m3_free(struct snd_m3 *chip) if (chip->iobase) pci_release_regions(chip->pci); -#ifdef FIRMWARE_IN_THE_KERNEL - if (chip->assp_kernel_image != &assp_kernel) +#ifndef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL + release_firmware(chip->assp_kernel_image); + release_firmware(chip->assp_minisrc_image); #endif - release_firmware(chip->assp_kernel_image); -#ifdef FIRMWARE_IN_THE_KERNEL - if (chip->assp_minisrc_image != &assp_minisrc) -#endif - release_firmware(chip->assp_minisrc_image); pci_disable_device(chip->pci); kfree(chip); @@ -2747,29 +2747,29 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, return -ENOMEM; } +#ifdef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL + chip->assp_kernel_image = &assp_kernel; +#else err = request_firmware(&chip->assp_kernel_image, "ess/maestro3_assp_kernel.fw", &pci->dev); if (err < 0) { -#ifdef FIRMWARE_IN_THE_KERNEL - chip->assp_kernel_image = &assp_kernel; -#else snd_m3_free(chip); return err; -#endif } else snd_m3_convert_from_le(chip->assp_kernel_image); +#endif +#ifdef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL + chip->assp_minisrc_image = &assp_minisrc; +#else err = request_firmware(&chip->assp_minisrc_image, "ess/maestro3_assp_minisrc.fw", &pci->dev); if (err < 0) { -#ifdef FIRMWARE_IN_THE_KERNEL - chip->assp_minisrc_image = &assp_minisrc; -#else snd_m3_free(chip); return err; -#endif } else snd_m3_convert_from_le(chip->assp_minisrc_image); +#endif if ((err = pci_request_regions(pci, card->driver)) < 0) { snd_m3_free(chip); diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index ca05075c67c6..1d9232d2db34 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c @@ -565,6 +565,9 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr) return 0; } +MODULE_FIRMWARE("mixart/miXart8.xlx"); +MODULE_FIRMWARE("mixart/miXart8.elf"); +MODULE_FIRMWARE("mixart/miXart8AES.xlx"); #else /* old style firmware loading */ diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index d97413484ae9..f7f6a687f033 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -638,22 +638,22 @@ static void pcxhr_trigger_tasklet(unsigned long arg) static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd) { struct pcxhr_stream *stream; - struct list_head *pos; struct snd_pcm_substream *s; - int i; switch (cmd) { case SNDRV_PCM_TRIGGER_START: snd_printdd("SNDRV_PCM_TRIGGER_START\n"); - i = 0; - snd_pcm_group_for_each(pos, subs) { - s = snd_pcm_group_substream_entry(pos); - stream = s->runtime->private_data; - stream->status = PCXHR_STREAM_STATUS_SCHEDULE_RUN; - snd_pcm_trigger_done(s, subs); - i++; - } - if (i==1) { + if (snd_pcm_stream_linked(subs)) { + struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); + snd_pcm_group_for_each_entry(s, subs) { + stream = s->runtime->private_data; + stream->status = + PCXHR_STREAM_STATUS_SCHEDULE_RUN; + snd_pcm_trigger_done(s, subs); + } + tasklet_hi_schedule(&chip->mgr->trigger_taskq); + } else { + stream = subs->runtime->private_data; snd_printdd("Only one Substream %c %d\n", stream->pipe->is_capture ? 'C' : 'P', stream->pipe->first_audio); @@ -665,15 +665,11 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd) if (pcxhr_set_stream_state(stream)) return -EINVAL; stream->status = PCXHR_STREAM_STATUS_RUNNING; - } else { - struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); - tasklet_hi_schedule(&chip->mgr->trigger_taskq); } break; case SNDRV_PCM_TRIGGER_STOP: snd_printdd("SNDRV_PCM_TRIGGER_STOP\n"); - snd_pcm_group_for_each(pos, subs) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, subs) { stream = s->runtime->private_data; stream->status = PCXHR_STREAM_STATUS_SCHEDULE_STOP; if (pcxhr_set_stream_state(stream)) diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c index 369c19fea985..d55d8bc90eee 100644 --- a/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/sound/pci/pcxhr/pcxhr_hwdep.c @@ -356,6 +356,12 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) return 0; } +MODULE_FIRMWARE("pcxhr/xi_1_882.dat"); +MODULE_FIRMWARE("pcxhr/xc_1_882.dat"); +MODULE_FIRMWARE("pcxhr/e321_512.e56"); +MODULE_FIRMWARE("pcxhr/b321_512.b56"); +MODULE_FIRMWARE("pcxhr/d321_512.d56"); + #else /* old style firmware loading */ /* pcxhr hwdep interface id string */ diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 952625dead58..8e5410483e67 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -117,6 +117,7 @@ MODULE_AUTHOR("Peter Gruber <nokos@gmx.net>"); MODULE_DESCRIPTION("riptide"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Conexant,Riptide}}"); +MODULE_FIRMWARE("riptide.hex"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 6bb7ac650ec4..618653e22561 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1078,12 +1078,10 @@ static int snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); - struct list_head *pos; struct snd_pcm_substream *s; spin_lock(&rme32->lock); - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s != rme32->playback_substream && s != rme32->capture_substream) continue; @@ -1110,8 +1108,7 @@ snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) /* prefill playback buffer */ if (cmd == SNDRV_PCM_TRIGGER_START && rme32->fullduplex_mode) { - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == rme32->playback_substream) { s->ops->ack(s); break; diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 89b3c7ff5037..3b3ef657f73e 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -60,6 +60,12 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," "{RME HDSP-9652}," "{RME HDSP-9632}}"); +#ifdef HDSP_FW_LOADER +MODULE_FIRMWARE("multiface_firmware.bin"); +MODULE_FIRMWARE("multiface_firmware_rev11.bin"); +MODULE_FIRMWARE("digiface_firmware.bin"); +MODULE_FIRMWARE("digiface_firmware_rev11.bin"); +#endif #define HDSP_MAX_CHANNELS 26 #define HDSP_MAX_DS_CHANNELS 14 @@ -275,6 +281,11 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0) #define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1) #define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0) +/* RME says n = 104857600000000, but in the windows MADI driver, I see: + return 104857600000000 / rate; // 100 MHz + return 110100480000000 / rate; // 105 MHz +*/ +#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */ #define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask) #define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1) @@ -1001,11 +1012,7 @@ static void hdsp_set_dds_value(struct hdsp *hdsp, int rate) else if (rate >= 56000) rate /= 2; - /* RME says n = 104857600000000, but in the windows MADI driver, I see: -// return 104857600000000 / rate; // 100 MHz - return 110100480000000 / rate; // 105 MHz - */ - n = 104857600000000ULL; /* = 2^20 * 10^8 */ + n = DDS_NUMERATOR; div64_32(&n, rate, &r); /* n should be less than 2^32 for being written to FREQ register */ snd_assert((n >> 32) == 0); @@ -3085,11 +3092,83 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn return 0; } +#define HDSP_DDS_OFFSET(xname, xindex) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdsp_info_dds_offset, \ + .get = snd_hdsp_get_dds_offset, \ + .put = snd_hdsp_put_dds_offset \ +} + +static int hdsp_dds_offset(struct hdsp *hdsp) +{ + u64 n; + u32 r; + unsigned int dds_value = hdsp->dds_value; + int system_sample_rate = hdsp->system_sample_rate; + + n = DDS_NUMERATOR; + /* + * dds_value = n / rate + * rate = n / dds_value + */ + div64_32(&n, dds_value, &r); + if (system_sample_rate >= 112000) + n *= 4; + else if (system_sample_rate >= 56000) + n *= 2; + return ((int)n) - system_sample_rate; +} + +static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz) +{ + int rate = hdsp->system_sample_rate + offset_hz; + hdsp_set_dds_value(hdsp, rate); + return 0; +} + +static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = -5000; + uinfo->value.integer.max = 5000; + return 0; +} + +static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp); + return 0; +} + +static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + int change; + int val; + + if (!snd_hdsp_use_is_exclusive(hdsp)) + return -EBUSY; + val = ucontrol->value.enumerated.item[0]; + spin_lock_irq(&hdsp->lock); + if (val != hdsp_dds_offset(hdsp)) + change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0; + else + change = 0; + spin_unlock_irq(&hdsp->lock); + return change; +} + static struct snd_kcontrol_new snd_hdsp_9632_controls[] = { HDSP_DA_GAIN("DA Gain", 0), HDSP_AD_GAIN("AD Gain", 0), HDSP_PHONE_GAIN("Phones Gain", 0), -HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0) +HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0), +HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0) }; static struct snd_kcontrol_new snd_hdsp_controls[] = { @@ -3780,11 +3859,9 @@ static int snd_hdsp_reset(struct snd_pcm_substream *substream) else runtime->status->hw_ptr = 0; if (other) { - struct list_head *pos; struct snd_pcm_substream *s; struct snd_pcm_runtime *oruntime = other->runtime; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == other) { oruntime->status->hw_ptr = runtime->status->hw_ptr; break; @@ -3933,10 +4010,8 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) other = hdsp->playback_substream; if (other) { - struct list_head *pos; struct snd_pcm_substream *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == other) { snd_pcm_trigger_done(s, substream); if (cmd == SNDRV_PCM_TRIGGER_START) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 6e95857e4e67..143185e7e4dc 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -91,8 +91,10 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); #define HDSPM_controlRegister 64 #define HDSPM_interruptConfirmation 96 #define HDSPM_control2Reg 256 /* not in specs ???????? */ +#define HDSPM_freqReg 256 /* for AES32 */ #define HDSPM_midiDataOut0 352 /* just believe in old code */ #define HDSPM_midiDataOut1 356 +#define HDSPM_eeprom_wr 384 /* for AES32 */ /* DMA enable for 64 channels, only Bit 0 is relevant */ #define HDSPM_outputEnableBase 512 /* 512-767 input DMA */ @@ -389,9 +391,8 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); size is the same regardless of the number of channels, and also the latency to use. for one direction !!! - => need to mupltiply by 2!! */ -#define HDSPM_DMA_AREA_BYTES (2 * HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) +#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) /* revisions >= 230 indicate AES32 card */ @@ -484,28 +485,6 @@ static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = { 56, 57, 58, 59, 60, 61, 62, 63 }; -static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = { - 0, 2, 4, 6, 8, 10, 12, 14, - 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, - 48, 50, 52, 54, 56, 58, 60, 62, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = { - 0, 4, 8, 12, 16, 20, 24, 28, - 32, 36, 40, 44, 48, 52, 56, 60 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - static struct pci_device_id snd_hdspm_ids[] __devinitdata = { { @@ -818,6 +797,27 @@ static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames) return 0; } +static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) +{ + u64 n; + u32 r; + + if (rate >= 112000) + rate /= 4; + else if (rate >= 56000) + rate /= 2; + + /* RME says n = 104857600000000, but in the windows MADI driver, I see: +// return 104857600000000 / rate; // 100 MHz + return 110100480000000 / rate; // 105 MHz + */ + //n = 104857600000000ULL; /* = 2^20 * 10^8 */ + n = 110100480000000ULL; /* Value checked for AES32 and MADI */ + div64_32(&n, rate, &r); + /* n should be less than 2^32 for being written to FREQ register */ + snd_assert((n >> 32) == 0); + hdspm_write(hdspm, HDSPM_freqReg, (u32)n); +} /* dummy set rate lets see what happens */ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) @@ -943,12 +943,16 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) hdspm->control_register |= rate_bits; hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - if (rate > 96000 /* 64000*/) - hdspm->channel_map = channel_map_madi_qs; - else if (rate > 48000) - hdspm->channel_map = channel_map_madi_ds; - else - hdspm->channel_map = channel_map_madi_ss; + /* For AES32, need to set DDS value in FREQ register + For MADI, also apparently */ + hdspm_set_dds_value(hdspm, rate); + + if (hdspm->is_aes32 && rate != current_rate) + hdspm_write(hdspm, HDSPM_eeprom_wr, 0); + + /* For AES32 and for MADI (at least rev 204), channel_map needs to + * always be channel_map_madi_ss, whatever the sample rate */ + hdspm->channel_map = channel_map_madi_ss; hdspm->system_sample_rate = rate; @@ -3184,8 +3188,8 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); snd_iprintf(buffer, - "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n", - hdspm->control_register, hdspm->control2_register, + "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n", + hdspm->control_register, status, status2, timecode); snd_iprintf(buffer, "--- Settings ---\n"); @@ -3377,13 +3381,16 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm) hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); + if (!hdspm->is_aes32) { + /* No control2 register for AES32 */ #ifdef SNDRV_BIG_ENDIAN - hdspm->control2_register = HDSPM_BIGENDIAN_MODE; + hdspm->control2_register = HDSPM_BIGENDIAN_MODE; #else - hdspm->control2_register = 0; + hdspm->control2_register = 0; #endif - hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register); + hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register); + } hdspm_compute_period_size(hdspm); /* silence everything */ @@ -3575,11 +3582,9 @@ static int snd_hdspm_reset(struct snd_pcm_substream *substream) else runtime->status->hw_ptr = 0; if (other) { - struct list_head *pos; struct snd_pcm_substream *s; struct snd_pcm_runtime *oruntime = other->runtime; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == other) { oruntime->status->hw_ptr = runtime->status->hw_ptr; @@ -3658,11 +3663,10 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, /* Memory allocation, takashi's method, dont know if we should spinlock */ /* malloc all buffer even if not enabled to get sure */ - /* malloc only needed bytes */ + /* Update for MADI rev 204: we need to allocate for all channels, + * otherwise it doesn't work at 96kHz */ err = - snd_pcm_lib_malloc_pages(substream, - HDSPM_CHANNEL_BUFFER_BYTES * - params_channels(params)); + snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES); if (err < 0) return err; @@ -3698,6 +3702,13 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, "playback" : "capture", snd_pcm_sgbuf_get_addr(sgbuf, 0)); */ + /* + snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n", + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + "playback" : "capture", + params_rate(params), params_channels(params), + params_buffer_size(params)); + */ return 0; } @@ -3791,10 +3802,8 @@ static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd) other = hdspm->playback_substream; if (other) { - struct list_head *pos; struct snd_pcm_substream *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == other) { snd_pcm_trigger_done(s, substream); if (cmd == SNDRV_PCM_TRIGGER_START) @@ -3904,16 +3913,16 @@ static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params, struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (r->min > 48000) { + if (r->min > 48000 && r->max <= 96000) { struct snd_interval t = { - .min = 1, + .min = hdspm->ds_channels, .max = hdspm->ds_channels, .integer = 1, }; return snd_interval_refine(c, &t); } else if (r->max < 64000) { struct snd_interval t = { - .min = 1, + .min = hdspm->ss_channels, .max = hdspm->ss_channels, .integer = 1, }; @@ -3931,14 +3940,14 @@ static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params, struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (c->min <= hdspm->ss_channels) { + if (c->min >= hdspm->ss_channels) { struct snd_interval t = { .min = 32000, .max = 48000, .integer = 1, }; return snd_interval_refine(r, &t); - } else if (c->max > hdspm->ss_channels) { + } else if (c->max <= hdspm->ds_channels) { struct snd_interval t = { .min = 64000, .max = 96000, @@ -3950,13 +3959,39 @@ static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params, return 0; } +static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + unsigned int list[3]; + struct hdspm *hdspm = rule->private; + struct snd_interval *c = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + if (hdspm->is_aes32) { + list[0] = hdspm->qs_channels; + list[1] = hdspm->ds_channels; + list[2] = hdspm->ss_channels; + return snd_interval_list(c, 3, list, 0); + } else { + list[0] = hdspm->ds_channels; + list[1] = hdspm->ss_channels; + return snd_interval_list(c, 2, list, 0); + } +} + + +static unsigned int hdspm_aes32_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; + +static struct snd_pcm_hw_constraint_list hdspm_hw_constraints_aes32_sample_rates = { + .count = ARRAY_SIZE(hdspm_aes32_sample_rates), + .list = hdspm_aes32_sample_rates, + .mask = 0 +}; + static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) { struct hdspm *hdspm = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - snd_printdd("Open device substream %d\n", substream->stream); - spin_lock_irq(&hdspm->lock); snd_pcm_set_sync(substream); @@ -3977,14 +4012,21 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdspm_hw_rule_channels_rate, hdspm, - SNDRV_PCM_HW_PARAM_RATE, -1); - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_hdspm_hw_rule_rate_channels, hdspm, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - + if (hdspm->is_aes32) { + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &hdspm_hw_constraints_aes32_sample_rates); + } else { + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + snd_hdspm_hw_rule_channels, hdspm, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + snd_hdspm_hw_rule_channels_rate, hdspm, + SNDRV_PCM_HW_PARAM_RATE, -1); + + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + snd_hdspm_hw_rule_rate_channels, hdspm, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + } return 0; } @@ -4024,14 +4066,21 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes); - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdspm_hw_rule_channels_rate, hdspm, - SNDRV_PCM_HW_PARAM_RATE, -1); - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_hdspm_hw_rule_rate_channels, hdspm, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (hdspm->is_aes32) { + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &hdspm_hw_constraints_aes32_sample_rates); + } else { + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + snd_hdspm_hw_rule_channels, hdspm, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + snd_hdspm_hw_rule_channels_rate, hdspm, + SNDRV_PCM_HW_PARAM_RATE, -1); + + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + snd_hdspm_hw_rule_rate_channels, hdspm, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + } return 0; } diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index cc3bdececce7..bd7dbd267ed1 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -1992,11 +1992,9 @@ static int snd_rme9652_reset(struct snd_pcm_substream *substream) else runtime->status->hw_ptr = 0; if (other) { - struct list_head *pos; struct snd_pcm_substream *s; struct snd_pcm_runtime *oruntime = other->runtime; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == other) { oruntime->status->hw_ptr = runtime->status->hw_ptr; break; @@ -2140,10 +2138,8 @@ static int snd_rme9652_trigger(struct snd_pcm_substream *substream, other = rme9652->playback_substream; if (other) { - struct list_head *pos; struct snd_pcm_substream *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == other) { snd_pcm_trigger_done(s, substream); if (cmd == SNDRV_PCM_TRIGGER_START) diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 3bff32167f66..7ca606272460 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -1540,7 +1540,6 @@ static int snd_trident_trigger(struct snd_pcm_substream *substream, { struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct list_head *pos; struct snd_pcm_substream *s; unsigned int what, whati, capture_flag, spdif_flag; struct snd_trident_voice *voice, *evoice; @@ -1563,8 +1562,7 @@ static int snd_trident_trigger(struct snd_pcm_substream *substream, what = whati = capture_flag = spdif_flag = 0; spin_lock(&trident->reg_lock); val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if ((struct snd_trident *) snd_pcm_substream_chip(s) == trident) { voice = s->runtime->private_data; evoice = voice->extra; diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index fd12674d0394..ea861bceaddf 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -1998,9 +1998,7 @@ static void snd_ymfpci_disable_dsp(struct snd_ymfpci *chip) } } -#define FIRMWARE_IN_THE_KERNEL - -#ifdef FIRMWARE_IN_THE_KERNEL +#ifdef CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL #include "ymfpci_image.h" @@ -2018,6 +2016,24 @@ static struct firmware snd_ymfpci_controller_1e_microcode = { }; #endif +#ifdef CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL +static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip) +{ + chip->dsp_microcode = &snd_ymfpci_dsp_microcode; + if (chip->device_id == PCI_DEVICE_ID_YAMAHA_724F || + chip->device_id == PCI_DEVICE_ID_YAMAHA_740C || + chip->device_id == PCI_DEVICE_ID_YAMAHA_744 || + chip->device_id == PCI_DEVICE_ID_YAMAHA_754) + chip->controller_microcode = + &snd_ymfpci_controller_1e_microcode; + else + chip->controller_microcode = + &snd_ymfpci_controller_microcode; + return 0; +} + +#else /* use fw_loader */ + #ifdef __LITTLE_ENDIAN static inline void snd_ymfpci_convert_from_le(const struct firmware *fw) { } #else @@ -2046,13 +2062,8 @@ static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip) err = -EINVAL; } } - if (err < 0) { -#ifdef FIRMWARE_IN_THE_KERNEL - chip->dsp_microcode = &snd_ymfpci_dsp_microcode; -#else + if (err < 0) return err; -#endif - } is_1e = chip->device_id == PCI_DEVICE_ID_YAMAHA_724F || chip->device_id == PCI_DEVICE_ID_YAMAHA_740C || chip->device_id == PCI_DEVICE_ID_YAMAHA_744 || @@ -2069,18 +2080,17 @@ static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip) err = -EINVAL; } } - if (err < 0) { -#ifdef FIRMWARE_IN_THE_KERNEL - chip->controller_microcode = - is_1e ? &snd_ymfpci_controller_1e_microcode - : &snd_ymfpci_controller_microcode; -#else + if (err < 0) return err; -#endif - } return 0; } +MODULE_FIRMWARE("yamaha/ds1_dsp.fw"); +MODULE_FIRMWARE("yamaha/ds1_ctrl.fw"); +MODULE_FIRMWARE("yamaha/ds1e_ctrl.fw"); + +#endif + static void snd_ymfpci_download_image(struct snd_ymfpci *chip) { int i; @@ -2259,15 +2269,10 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip) pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); pci_disable_device(chip->pci); -#ifdef FIRMWARE_IN_THE_KERNEL - if (chip->dsp_microcode != &snd_ymfpci_dsp_microcode) -#endif - release_firmware(chip->dsp_microcode); -#ifdef FIRMWARE_IN_THE_KERNEL - if (chip->controller_microcode != &snd_ymfpci_controller_microcode && - chip->controller_microcode != &snd_ymfpci_controller_1e_microcode) +#ifndef CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL + release_firmware(chip->dsp_microcode); + release_firmware(chip->controller_microcode); #endif - release_firmware(chip->controller_microcode); kfree(chip); return 0; } diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 363bcb5f08e6..c57e127d9ccb 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -297,7 +297,7 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) /* find an empty slot from the card list */ for (i = 0; i < SNDRV_CARDS; i++) { - if (! card_alloc & (1 << i)) + if (!(card_alloc & (1 << i))) break; } if (i >= SNDRV_CARDS) { diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index dccaa4be679e..10cffc087181 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -2,31 +2,31 @@ # SoC audio configuration # -menu "SoC audio support" +menu "System on Chip audio support" depends on SND!=n config SND_SOC_AC97_BUS bool config SND_SOC - tristate "SoC audio support" + tristate "ALSA for SoC audio support" depends on SND select SND_PCM ---help--- - If you want SoC support, you should say Y here and also to the - specific driver for your SoC below. You will also need to select the - specific codec(s) attached to the SoC + If you want ASoC support, you should say Y here and also to the + specific driver for your SoC platform below. + + ASoC provides power efficient ALSA support for embedded battery powered + SoC based systems like PDA's, Phones and Personal Media Players. - This SoC audio support can also be built as a module. If so, the module + This ASoC audio support can also be built as a module. If so, the module will be called snd-soc-core. # All the supported Soc's -menu "SoC Platforms" -depends on SND_SOC source "sound/soc/at91/Kconfig" source "sound/soc/pxa/Kconfig" -endmenu +source "sound/soc/s3c24xx/Kconfig" # Supported codecs source "sound/soc/codecs/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 98e6f49dafc2..0ae2e49036f9 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,4 +1,4 @@ snd-soc-core-objs := soc-core.o soc-dapm.o obj-$(CONFIG_SND_SOC) += snd-soc-core.o -obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ +obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig index a5b2558916c1..5cb93fd3a407 100644 --- a/sound/soc/at91/Kconfig +++ b/sound/soc/at91/Kconfig @@ -1,5 +1,3 @@ -menu "SoC Audio for the Atmel AT91" - config SND_AT91_SOC tristate "SoC Audio for the Atmel AT91 System-on-Chip" depends on ARCH_AT91 && SND_SOC @@ -8,13 +6,13 @@ config SND_AT91_SOC the AT91 SSC interface. You will also need to select the audio interfaces to support below. -config SND_AT91_SOC_I2S +config SND_AT91_SOC_SSC tristate config SND_AT91_SOC_ETI_B1_WM8731 - tristate "SoC I2S Audio support for WM8731-based Endrelia ETI-B1 boards" + tristate "SoC Audio support for WM8731-based Endrelia ETI-B1 boards" depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1) - select SND_AT91_SOC_I2S + select SND_AT91_SOC_SSC select SND_SOC_WM8731 help Say Y if you want to add support for SoC audio on WM8731-based @@ -27,5 +25,3 @@ config SND_AT91_SOC_ETI_SLAVE help Say Y if you want to run with the AT91 SSC generating the BCLK and LRC signals on Endrelia boards. - -endmenu diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile index b77b01ab2028..f23da17cc328 100644 --- a/sound/soc/at91/Makefile +++ b/sound/soc/at91/Makefile @@ -1,9 +1,9 @@ # AT91 Platform Support snd-soc-at91-objs := at91-pcm.o -snd-soc-at91-i2s-objs := at91-i2s.o +snd-soc-at91-ssc-objs := at91-ssc.o obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o -obj-$(CONFIG_SND_AT91_SOC_I2S) += snd-soc-at91-i2s.o +obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o # AT91 Machine Support snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o diff --git a/sound/soc/at91/at91-i2s.c b/sound/soc/at91/at91-ssc.c index 9fc0c0388881..3d4e32cff75e 100644 --- a/sound/soc/at91/at91-i2s.c +++ b/sound/soc/at91/at91-ssc.c @@ -1,5 +1,5 @@ /* - * at91-i2s.c -- ALSA SoC I2S Audio Layer Platform driver + * at91-ssc.c -- ALSA SoC AT91 SSC Audio Layer Platform driver * * Author: Frank Mandarino <fmandarino@endrelia.com> * Endrelia Technologies Inc. @@ -25,6 +25,7 @@ #include <sound/driver.h> #include <sound/core.h> #include <sound/pcm.h> +#include <sound/pcm_params.h> #include <sound/initval.h> #include <sound/soc.h> @@ -33,10 +34,10 @@ #include <asm/arch/at91_ssc.h> #include "at91-pcm.h" -#include "at91-i2s.h" +#include "at91-ssc.h" #if 0 -#define DBG(x...) printk(KERN_DEBUG "at91-i2s:" x) +#define DBG(x...) printk(KERN_DEBUG "at91-ssc:" x) #else #define DBG(x...) #endif @@ -92,33 +93,33 @@ static struct at91_ssc_mask ssc_rx_mask = { */ static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = { {{ - .name = "SSC0/I2S PCM Stereo out", + .name = "SSC0 PCM out", .pdc = &pdc_tx_reg, .mask = &ssc_tx_mask, }, { - .name = "SSC0/I2S PCM Stereo in", + .name = "SSC0 PCM in", .pdc = &pdc_rx_reg, .mask = &ssc_rx_mask, }}, #if NUM_SSC_DEVICES == 3 {{ - .name = "SSC1/I2S PCM Stereo out", + .name = "SSC1 PCM out", .pdc = &pdc_tx_reg, .mask = &ssc_tx_mask, }, { - .name = "SSC1/I2S PCM Stereo in", + .name = "SSC1 PCM in", .pdc = &pdc_rx_reg, .mask = &ssc_rx_mask, }}, {{ - .name = "SSC2/I2S PCM Stereo out", + .name = "SSC2 PCM out", .pdc = &pdc_tx_reg, .mask = &ssc_tx_mask, }, { - .name = "SSC1/I2S PCM Stereo in", + .name = "SSC2 PCM in", .pdc = &pdc_rx_reg, .mask = &ssc_rx_mask, }}, @@ -151,33 +152,33 @@ static struct at91_ssc_info { } ssc_info[NUM_SSC_DEVICES] = { { .name = "ssc0", - .lock = SPIN_LOCK_UNLOCKED, + .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock), .dir_mask = 0, .initialized = 0, }, #if NUM_SSC_DEVICES == 3 { .name = "ssc1", - .lock = SPIN_LOCK_UNLOCKED, + .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock), .dir_mask = 0, .initialized = 0, }, { .name = "ssc2", - .lock = SPIN_LOCK_UNLOCKED, + .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock), .dir_mask = 0, .initialized = 0, }, #endif }; -static unsigned int at91_i2s_sysclk; +static unsigned int at91_ssc_sysclk; /* * SSC interrupt handler. Passes PDC interrupts to the DMA * interrupt handler in the PCM driver. */ -static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id) +static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id) { struct at91_ssc_info *ssc_p = dev_id; struct at91_pcm_dma_params *dma_params; @@ -209,13 +210,13 @@ static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id) /* * Startup. Only that one substream allowed in each direction. */ -static int at91_i2s_startup(struct snd_pcm_substream *substream) +static int at91_ssc_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; int dir_mask; - DBG("i2s_startup: SSC_SR=0x%08lx\n", + DBG("ssc_startup: SSC_SR=0x%08lx\n", at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)); dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2; @@ -234,7 +235,7 @@ static int at91_i2s_startup(struct snd_pcm_substream *substream) * Shutdown. Clear DMA parameters and shutdown the SSC if there * are no other substreams open. */ -static void at91_i2s_shutdown(struct snd_pcm_substream *substream) +static void at91_ssc_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; @@ -281,7 +282,7 @@ static void at91_i2s_shutdown(struct snd_pcm_substream *substream) /* * Record the SSC system clock rate. */ -static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, +static int at91_ssc_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { /* @@ -291,7 +292,7 @@ static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, */ switch (clk_id) { case AT91_SYSCLK_MCK: - at91_i2s_sysclk = freq; + at91_ssc_sysclk = freq; break; default: return -EINVAL; @@ -303,14 +304,11 @@ static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, /* * Record the DAI format for use in hw_params(). */ -static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, +static int at91_ssc_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, unsigned int fmt) { struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; - if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) - return -EINVAL; - ssc_p->daifmt = fmt; return 0; } @@ -318,7 +316,7 @@ static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, /* * Record SSC clock dividers for use in hw_params(). */ -static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai, +static int at91_ssc_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai, int div_id, int div) { struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; @@ -355,7 +353,7 @@ static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai, /* * Configure the SSC. */ -static int at91_i2s_hw_params(struct snd_pcm_substream *substream, +static int at91_ssc_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -391,20 +389,50 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, channels = params_channels(params); /* + * Determine sample size in bits and the PDC increment. + */ + switch(params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + bits = 8; + dma_params->pdc_xfer_size = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + bits = 16; + dma_params->pdc_xfer_size = 2; + break; + case SNDRV_PCM_FORMAT_S24_LE: + bits = 24; + dma_params->pdc_xfer_size = 4; + break; + case SNDRV_PCM_FORMAT_S32_LE: + bits = 32; + dma_params->pdc_xfer_size = 4; + break; + default: + printk(KERN_WARNING "at91-ssc: unsupported PCM format"); + return -EINVAL; + } + + /* * The SSC only supports up to 16-bit samples in I2S format, due - * to the size of the Frame Mode Register FSLEN field. Also, I2S - * implies signed data. + * to the size of the Frame Mode Register FSLEN field. */ - bits = 16; - dma_params->pdc_xfer_size = 2; + if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S + && bits > 16) { + printk(KERN_WARNING + "at91-ssc: sample size %d is too large for I2S\n", bits); + return -EINVAL; + } /* * Compute SSC register settings. */ - switch (ssc_p->daifmt) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (ssc_p->daifmt + & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { + + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: /* - * SSC provides BCLK and LRC clocks. + * I2S format, SSC provides BCLK and LRC clocks. * * The SSC transmit and receive clocks are generated from the * MCK divider, and the BCLK signal is output on the SSC TK line. @@ -441,10 +469,9 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, | (((bits - 1) << 0) & AT91_SSC_DATALEN); break; - case SND_SOC_DAIFMT_CBM_CFM: - + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: /* - * CODEC supplies BCLK and LRC clocks. + * I2S format, CODEC supplies BCLK and LRC clocks. * * The SSC transmit clock is obtained from the BCLK signal on * on the TK line, and the SSC receive clock is generated from the @@ -490,10 +517,51 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, | (((bits - 1) << 0) & AT91_SSC_DATALEN); break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: + /* + * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. + * + * The SSC transmit and receive clocks are generated from the + * MCK divider, and the BCLK signal is output on the SSC TK line. + */ + rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD) + | (( 1 << 16) & AT91_SSC_STTDLY) + | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) + | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) + | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO) + | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); + + rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) + | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) + | (( 0 << 16) & AT91_SSC_FSLEN) + | (((channels - 1) << 8) & AT91_SSC_DATNB) + | (( 1 << 7) & AT91_SSC_MSBF) + | (( 0 << 5) & AT91_SSC_LOOP) + | (((bits - 1) << 0) & AT91_SSC_DATALEN); + + tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD) + | (( 1 << 16) & AT91_SSC_STTDLY) + | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) + | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) + | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO) + | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); + + tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) + | (( 0 << 23) & AT91_SSC_FSDEN) + | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) + | (( 0 << 16) & AT91_SSC_FSLEN) + | (((channels - 1) << 8) & AT91_SSC_DATNB) + | (( 1 << 7) & AT91_SSC_MSBF) + | (( 0 << 5) & AT91_SSC_DATDEF) + | (((bits - 1) << 0) & AT91_SSC_DATALEN); + + + + break; + + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: default: - printk(KERN_WARNING "at91-i2s: unsupported DAI format 0x%x.\n", + printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n", ssc_p->daifmt); return -EINVAL; break; @@ -518,9 +586,9 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0); at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0); - if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt, + if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt, 0, ssc_p->name, ssc_p)) < 0) { - printk(KERN_WARNING "at91-i2s: request_irq failure\n"); + printk(KERN_WARNING "at91-ssc: request_irq failure\n"); DBG("Stopping pid %d clock\n", ssc_p->ssc.pid); at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid); @@ -546,7 +614,7 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, } -static int at91_i2s_prepare(struct snd_pcm_substream *substream) +static int at91_ssc_prepare(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; @@ -566,7 +634,7 @@ static int at91_i2s_prepare(struct snd_pcm_substream *substream) #ifdef CONFIG_PM -static int at91_i2s_suspend(struct platform_device *pdev, +static int at91_ssc_suspend(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai) { struct at91_ssc_info *ssc_p; @@ -594,7 +662,7 @@ static int at91_i2s_suspend(struct platform_device *pdev, return 0; } -static int at91_i2s_resume(struct platform_device *pdev, +static int at91_ssc_resume(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai) { struct at91_ssc_info *ssc_p; @@ -620,102 +688,105 @@ static int at91_i2s_resume(struct platform_device *pdev, } #else -#define at91_i2s_suspend NULL -#define at91_i2s_resume NULL +#define at91_ssc_suspend NULL +#define at91_ssc_resume NULL #endif -#define AT91_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ +#define AT91_SSC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ SNDRV_PCM_RATE_96000) -struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = { - { .name = "at91_ssc0/i2s", +#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +struct snd_soc_cpu_dai at91_ssc_dai[NUM_SSC_DEVICES] = { + { .name = "at91-ssc0", .id = 0, - .type = SND_SOC_DAI_I2S, - .suspend = at91_i2s_suspend, - .resume = at91_i2s_resume, + .type = SND_SOC_DAI_PCM, + .suspend = at91_ssc_suspend, + .resume = at91_ssc_resume, .playback = { .channels_min = 1, .channels_max = 2, - .rates = AT91_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .rates = AT91_SSC_RATES, + .formats = AT91_SSC_FORMATS,}, .capture = { .channels_min = 1, .channels_max = 2, - .rates = AT91_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .rates = AT91_SSC_RATES, + .formats = AT91_SSC_FORMATS,}, .ops = { - .startup = at91_i2s_startup, - .shutdown = at91_i2s_shutdown, - .prepare = at91_i2s_prepare, - .hw_params = at91_i2s_hw_params,}, + .startup = at91_ssc_startup, + .shutdown = at91_ssc_shutdown, + .prepare = at91_ssc_prepare, + .hw_params = at91_ssc_hw_params,}, .dai_ops = { - .set_sysclk = at91_i2s_set_dai_sysclk, - .set_fmt = at91_i2s_set_dai_fmt, - .set_clkdiv = at91_i2s_set_dai_clkdiv,}, + .set_sysclk = at91_ssc_set_dai_sysclk, + .set_fmt = at91_ssc_set_dai_fmt, + .set_clkdiv = at91_ssc_set_dai_clkdiv,}, .private_data = &ssc_info[0].ssc, }, #if NUM_SSC_DEVICES == 3 - { .name = "at91_ssc1/i2s", + { .name = "at91-ssc1", .id = 1, - .type = SND_SOC_DAI_I2S, - .suspend = at91_i2s_suspend, - .resume = at91_i2s_resume, + .type = SND_SOC_DAI_PCM, + .suspend = at91_ssc_suspend, + .resume = at91_ssc_resume, .playback = { .channels_min = 1, .channels_max = 2, - .rates = AT91_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .rates = AT91_SSC_RATES, + .formats = AT91_SSC_FORMATS,}, .capture = { .channels_min = 1, .channels_max = 2, - .rates = AT91_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .rates = AT91_SSC_RATES, + .formats = AT91_SSC_FORMATS,}, .ops = { - .startup = at91_i2s_startup, - .shutdown = at91_i2s_shutdown, - .prepare = at91_i2s_prepare, - .hw_params = at91_i2s_hw_params,}, + .startup = at91_ssc_startup, + .shutdown = at91_ssc_shutdown, + .prepare = at91_ssc_prepare, + .hw_params = at91_ssc_hw_params,}, .dai_ops = { - .set_sysclk = at91_i2s_set_dai_sysclk, - .set_fmt = at91_i2s_set_dai_fmt, - .set_clkdiv = at91_i2s_set_dai_clkdiv,}, + .set_sysclk = at91_ssc_set_dai_sysclk, + .set_fmt = at91_ssc_set_dai_fmt, + .set_clkdiv = at91_ssc_set_dai_clkdiv,}, .private_data = &ssc_info[1].ssc, }, - { .name = "at91_ssc2/i2s", + { .name = "at91-ssc2", .id = 2, - .type = SND_SOC_DAI_I2S, - .suspend = at91_i2s_suspend, - .resume = at91_i2s_resume, + .type = SND_SOC_DAI_PCM, + .suspend = at91_ssc_suspend, + .resume = at91_ssc_resume, .playback = { .channels_min = 1, .channels_max = 2, - .rates = AT91_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .rates = AT91_SSC_RATES, + .formats = AT91_SSC_FORMATS,}, .capture = { .channels_min = 1, .channels_max = 2, - .rates = AT91_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .rates = AT91_SSC_RATES, + .formats = AT91_SSC_FORMATS,}, .ops = { - .startup = at91_i2s_startup, - .shutdown = at91_i2s_shutdown, - .prepare = at91_i2s_prepare, - .hw_params = at91_i2s_hw_params,}, + .startup = at91_ssc_startup, + .shutdown = at91_ssc_shutdown, + .prepare = at91_ssc_prepare, + .hw_params = at91_ssc_hw_params,}, .dai_ops = { - .set_sysclk = at91_i2s_set_dai_sysclk, - .set_fmt = at91_i2s_set_dai_fmt, - .set_clkdiv = at91_i2s_set_dai_clkdiv,}, + .set_sysclk = at91_ssc_set_dai_sysclk, + .set_fmt = at91_ssc_set_dai_fmt, + .set_clkdiv = at91_ssc_set_dai_clkdiv,}, .private_data = &ssc_info[2].ssc, }, #endif }; -EXPORT_SYMBOL_GPL(at91_i2s_dai); +EXPORT_SYMBOL_GPL(at91_ssc_dai); /* Module information */ MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com"); -MODULE_DESCRIPTION("AT91 I2S ASoC Interface"); +MODULE_DESCRIPTION("AT91 SSC ASoC Interface"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/at91/at91-i2s.h b/sound/soc/at91/at91-ssc.h index f8a875ba0ccc..b188f973df9f 100644 --- a/sound/soc/at91/at91-i2s.h +++ b/sound/soc/at91/at91-ssc.h @@ -1,5 +1,5 @@ /* - * at91-i2s.h - ALSA I2S interface for the Atmel AT91 SoC + * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC * * Author: Frank Mandarino <fmandarino@endrelia.com> * Endrelia Technologies Inc. @@ -10,18 +10,18 @@ * published by the Free Software Foundation. */ -#ifndef _AT91_I2S_H -#define _AT91_I2S_H +#ifndef _AT91_SSC_H +#define _AT91_SSC_H -/* I2S system clock ids */ +/* SSC system clock ids */ #define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */ -/* I2S divider ids */ +/* SSC divider ids */ #define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */ #define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */ #define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */ -extern struct snd_soc_cpu_dai at91_i2s_dai[]; +extern struct snd_soc_cpu_dai at91_ssc_dai[]; -#endif /* _AT91_I2S_H */ +#endif /* _AT91_SSC_H */ diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c index 8179df3bb2f3..820a676c56bf 100644 --- a/sound/soc/at91/eti_b1_wm8731.c +++ b/sound/soc/at91/eti_b1_wm8731.c @@ -40,7 +40,7 @@ #include "../codecs/wm8731.h" #include "at91-pcm.h" -#include "at91-i2s.h" +#include "at91-ssc.h" #if 0 #define DBG(x...) printk(KERN_INFO "eti_b1_wm8731: " x) @@ -248,15 +248,15 @@ static int eti_b1_wm8731_init(struct snd_soc_codec *codec) static struct snd_soc_dai_link eti_b1_dai = { .name = "WM8731", - .stream_name = "WM8731", - .cpu_dai = &at91_i2s_dai[1], + .stream_name = "WM8731 PCM", + .cpu_dai = &at91_ssc_dai[1], .codec_dai = &wm8731_dai, .init = eti_b1_wm8731_init, .ops = &eti_b1_ops, }; static struct snd_soc_machine snd_soc_machine_eti_b1 = { - .name = "ETI_B1", + .name = "ETI_B1_WM8731", .dai_link = &eti_b1_dai, .num_links = 1, }; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index ec2a2787957a..e5fb437b86e8 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -10,6 +10,10 @@ config SND_SOC_WM8750 tristate depends on SND_SOC +config SND_SOC_WM8753 + tristate + depends on SND_SOC + config SND_SOC_WM9712 tristate depends on SND_SOC diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 3249a6e4f1d0..e39a747a17cf 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -1,9 +1,11 @@ snd-soc-ac97-objs := ac97.o snd-soc-wm8731-objs := wm8731.o snd-soc-wm8750-objs := wm8750.o +snd-soc-wm8753-objs := wm8753.o snd-soc-wm9712-objs := wm9712.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o +obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 55bc55eb6e24..0cdef971cbd3 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -60,6 +60,7 @@ static struct snd_soc_codec_dai ac97_dai = { .ops = { .prepare = ac97_prepare,}, }; +EXPORT_SYMBOL_GPL(ac97_dai); static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h index 930ddfc2321a..2bf6d69fd069 100644 --- a/sound/soc/codecs/ac97.h +++ b/sound/soc/codecs/ac97.h @@ -14,5 +14,6 @@ #define __LINUX_SND_SOC_AC97_H extern struct snd_soc_codec_device soc_codec_dev_ac97; +extern struct snd_soc_codec_dai ac97_dai; #endif diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 7073e8e294fc..28684eeda738 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -808,7 +808,7 @@ static int wm8750_init(struct snd_soc_device *socdev) codec->dai = &wm8750_dai; codec->num_dai = 1; codec->reg_cache_size = sizeof(wm8750_reg); - codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KRENEL); + codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KERNEL); if (codec->reg_cache == NULL) return -ENOMEM; diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c new file mode 100644 index 000000000000..efced934566d --- /dev/null +++ b/sound/soc/codecs/wm8753.c @@ -0,0 +1,1811 @@ +/* + * wm8753.c -- WM8753 ALSA Soc Audio driver + * + * Copyright 2003 Wolfson Microelectronics PLC. + * Author: Liam Girdwood + * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Notes: + * The WM8753 is a low power, high quality stereo codec with integrated PCM + * codec designed for portable digital telephony applications. + * + * Dual DAI:- + * + * This driver support 2 DAI PCM's. This makes the default PCM available for + * HiFi audio (e.g. MP3, ogg) playback/capture and the other PCM available for + * voice. + * + * Please note that the voice PCM can be connected directly to a Bluetooth + * codec or GSM modem and thus cannot be read or written to, although it is + * available to be configured with snd_hw_params(), etc and kcontrols in the + * normal alsa manner. + * + * Fast DAI switching:- + * + * The driver can now fast switch between the DAI configurations via a + * an alsa kcontrol. This allows the PCM to remain open. + * + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/version.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/i2c.h> +#include <linux/platform_device.h> +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/initval.h> +#include <asm/div64.h> + +#include "wm8753.h" + +#define AUDIO_NAME "wm8753" +#define WM8753_VERSION "0.16" + +/* + * Debug + */ + +#define WM8753_DEBUG 0 + +#ifdef WM8753_DEBUG +#define dbg(format, arg...) \ + printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg) +#else +#define dbg(format, arg...) do {} while (0) +#endif +#define err(format, arg...) \ + printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) +#define info(format, arg...) \ + printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) +#define warn(format, arg...) \ + printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) + +static int caps_charge = 2000; +module_param(caps_charge, int, 0); +MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); + +static void wm8753_set_dai_mode(struct snd_soc_codec *codec, + unsigned int mode); + +/* codec private data */ +struct wm8753_priv { + unsigned int sysclk; + unsigned int pcmclk; +}; + +/* + * wm8753 register cache + * We can't read the WM8753 register space when we + * are using 2 wire for device control, so we cache them instead. + */ +static const u16 wm8753_reg[] = { + 0x0008, 0x0000, 0x000a, 0x000a, + 0x0033, 0x0000, 0x0007, 0x00ff, + 0x00ff, 0x000f, 0x000f, 0x007b, + 0x0000, 0x0032, 0x0000, 0x00c3, + 0x00c3, 0x00c0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0055, + 0x0005, 0x0050, 0x0055, 0x0050, + 0x0055, 0x0050, 0x0055, 0x0079, + 0x0079, 0x0079, 0x0079, 0x0079, + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0097, 0x0097, 0x0000, 0x0004, + 0x0000, 0x0083, 0x0024, 0x01ba, + 0x0000, 0x0083, 0x0024, 0x01ba, + 0x0000, 0x0000 +}; + +/* + * read wm8753 register cache + */ +static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1)) + return -1; + return cache[reg - 1]; +} + +/* + * write wm8753 register cache + */ +static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + if (reg < 1 || reg > 0x3f) + return; + cache[reg - 1] = value; +} + +/* + * write to the WM8753 register space + */ +static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + /* data is + * D15..D9 WM8753 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8753_write_reg_cache (codec, reg, value); + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + +#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0) + +/* + * WM8753 Controls + */ +static const char *wm8753_base[] = {"Linear Control", "Adaptive Boost"}; +static const char *wm8753_base_filter[] = + {"130Hz @ 48kHz", "200Hz @ 48kHz", "100Hz @ 16kHz", "400Hz @ 48kHz", + "100Hz @ 8kHz", "200Hz @ 8kHz"}; +static const char *wm8753_treble[] = {"8kHz", "4kHz"}; +static const char *wm8753_alc_func[] = {"Off", "Right", "Left", "Stereo"}; +static const char *wm8753_ng_type[] = {"Constant PGA Gain", "Mute ADC Output"}; +static const char *wm8753_3d_func[] = {"Capture", "Playback"}; +static const char *wm8753_3d_uc[] = {"2.2kHz", "1.5kHz"}; +static const char *wm8753_3d_lc[] = {"200Hz", "500Hz"}; +static const char *wm8753_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz"}; +static const char *wm8753_mono_mix[] = {"Stereo", "Left", "Right", "Mono"}; +static const char *wm8753_dac_phase[] = {"Non Inverted", "Inverted"}; +static const char *wm8753_line_mix[] = {"Line 1 + 2", "Line 1 - 2", + "Line 1", "Line 2"}; +static const char *wm8753_mono_mux[] = {"Line Mix", "Rx Mix"}; +static const char *wm8753_right_mux[] = {"Line 2", "Rx Mix"}; +static const char *wm8753_left_mux[] = {"Line 1", "Rx Mix"}; +static const char *wm8753_rxmsel[] = {"RXP - RXN", "RXP + RXN", "RXP", "RXN"}; +static const char *wm8753_sidetone_mux[] = {"Left PGA", "Mic 1", "Mic 2", + "Right PGA"}; +static const char *wm8753_mono2_src[] = {"Inverted Mono 1", "Left", "Right", + "Left + Right"}; +static const char *wm8753_out3[] = {"VREF", "ROUT2", "Left + Right"}; +static const char *wm8753_out4[] = {"VREF", "Capture ST", "LOUT2"}; +static const char *wm8753_radcsel[] = {"PGA", "Line or RXP-RXN", "Sidetone"}; +static const char *wm8753_ladcsel[] = {"PGA", "Line or RXP-RXN", "Line"}; +static const char *wm8753_mono_adc[] = {"Stereo", "Analogue Mix Left", + "Analogue Mix Right", "Digital Mono Mix"}; +static const char *wm8753_adc_hp[] = {"3.4Hz @ 48kHz", "82Hz @ 16k", + "82Hz @ 8kHz", "170Hz @ 8kHz"}; +static const char *wm8753_adc_filter[] = {"HiFi", "Voice"}; +static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"}; +static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"}; +static const char *wm8753_dat_sel[] = {"Stereo", "Left ADC", "Right ADC", + "Channel Swap"}; + +static const struct soc_enum wm8753_enum[] = { +SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base), +SOC_ENUM_SINGLE(WM8753_BASS, 4, 6, wm8753_base_filter), +SOC_ENUM_SINGLE(WM8753_TREBLE, 6, 2, wm8753_treble), +SOC_ENUM_SINGLE(WM8753_ALC1, 7, 4, wm8753_alc_func), +SOC_ENUM_SINGLE(WM8753_NGATE, 1, 2, wm8753_ng_type), +SOC_ENUM_SINGLE(WM8753_3D, 7, 2, wm8753_3d_func), +SOC_ENUM_SINGLE(WM8753_3D, 6, 2, wm8753_3d_uc), +SOC_ENUM_SINGLE(WM8753_3D, 5, 2, wm8753_3d_lc), +SOC_ENUM_SINGLE(WM8753_DAC, 1, 4, wm8753_deemp), +SOC_ENUM_SINGLE(WM8753_DAC, 4, 4, wm8753_mono_mix), +SOC_ENUM_SINGLE(WM8753_DAC, 6, 2, wm8753_dac_phase), +SOC_ENUM_SINGLE(WM8753_INCTL1, 3, 4, wm8753_line_mix), +SOC_ENUM_SINGLE(WM8753_INCTL1, 2, 2, wm8753_mono_mux), +SOC_ENUM_SINGLE(WM8753_INCTL1, 1, 2, wm8753_right_mux), +SOC_ENUM_SINGLE(WM8753_INCTL1, 0, 2, wm8753_left_mux), +SOC_ENUM_SINGLE(WM8753_INCTL2, 6, 4, wm8753_rxmsel), +SOC_ENUM_SINGLE(WM8753_INCTL2, 4, 4, wm8753_sidetone_mux), +SOC_ENUM_SINGLE(WM8753_OUTCTL, 7, 4, wm8753_mono2_src), +SOC_ENUM_SINGLE(WM8753_OUTCTL, 0, 3, wm8753_out3), +SOC_ENUM_SINGLE(WM8753_ADCTL2, 7, 3, wm8753_out4), +SOC_ENUM_SINGLE(WM8753_ADCIN, 2, 3, wm8753_radcsel), +SOC_ENUM_SINGLE(WM8753_ADCIN, 0, 3, wm8753_ladcsel), +SOC_ENUM_SINGLE(WM8753_ADCIN, 4, 4, wm8753_mono_adc), +SOC_ENUM_SINGLE(WM8753_ADC, 2, 4, wm8753_adc_hp), +SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter), +SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel), +SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode), +SOC_ENUM_SINGLE(WM8753_ADC, 7, 4, wm8753_dat_sel), +}; + + +static int wm8753_get_dai(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); + + ucontrol->value.integer.value[0] = (mode & 0xc) >> 2; + return 0; +} + +static int wm8753_set_dai(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); + + if (((mode &0xc) >> 2) == ucontrol->value.integer.value[0]) + return 0; + + mode &= 0xfff3; + mode |= (ucontrol->value.integer.value[0] << 2); + + wm8753_write(codec, WM8753_IOCTL, mode); + wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]); + return 1; +} + +static const struct snd_kcontrol_new wm8753_snd_controls[] = { +SOC_DOUBLE_R("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0), + +SOC_DOUBLE_R("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0), + +SOC_DOUBLE_R("Headphone Playback Volume", WM8753_LOUT1V, WM8753_ROUT1V, 0, 127, 0), +SOC_DOUBLE_R("Speaker Playback Volume", WM8753_LOUT2V, WM8753_ROUT2V, 0, 127, 0), + +SOC_SINGLE("Mono Playback Volume", WM8753_MOUTV, 0, 127, 0), + +SOC_DOUBLE_R("Bypass Playback Volume", WM8753_LOUTM1, WM8753_ROUTM1, 4, 7, 1), +SOC_DOUBLE_R("Sidetone Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 4, 7, 1), +SOC_DOUBLE_R("Voice Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 0, 7, 1), + +SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8753_LOUT1V, WM8753_ROUT1V, 7, 1, 0), +SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0), + +SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1), +SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1), +SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 4, 7, 1), +SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0), + +SOC_ENUM("Bass Boost", wm8753_enum[0]), +SOC_ENUM("Bass Filter", wm8753_enum[1]), +SOC_SINGLE("Bass Volume", WM8753_BASS, 0, 15, 1), + +SOC_SINGLE("Treble Volume", WM8753_TREBLE, 0, 15, 1), +SOC_ENUM("Treble Cut-off", wm8753_enum[2]), + +SOC_DOUBLE("Sidetone Capture Volume", WM8753_RECMIX1, 0, 4, 7, 1), +SOC_SINGLE("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1), + +SOC_DOUBLE_R("Capture Volume", WM8753_LINVOL, WM8753_RINVOL, 0, 63, 0), +SOC_DOUBLE_R("Capture ZC Switch", WM8753_LINVOL, WM8753_RINVOL, 6, 1, 0), +SOC_DOUBLE_R("Capture Switch", WM8753_LINVOL, WM8753_RINVOL, 7, 1, 1), + +SOC_ENUM("Capture Filter Select", wm8753_enum[23]), +SOC_ENUM("Capture Filter Cut-off", wm8753_enum[24]), +SOC_SINGLE("Capture Filter Switch", WM8753_ADC, 0, 1, 1), + +SOC_SINGLE("ALC Capture Target Volume", WM8753_ALC1, 0, 7, 0), +SOC_SINGLE("ALC Capture Max Volume", WM8753_ALC1, 4, 7, 0), +SOC_ENUM("ALC Capture Function", wm8753_enum[3]), +SOC_SINGLE("ALC Capture ZC Switch", WM8753_ALC2, 8, 1, 0), +SOC_SINGLE("ALC Capture Hold Time", WM8753_ALC2, 0, 15, 1), +SOC_SINGLE("ALC Capture Decay Time", WM8753_ALC3, 4, 15, 1), +SOC_SINGLE("ALC Capture Attack Time", WM8753_ALC3, 0, 15, 0), +SOC_SINGLE("ALC Capture NG Threshold", WM8753_NGATE, 3, 31, 0), +SOC_ENUM("ALC Capture NG Type", wm8753_enum[4]), +SOC_SINGLE("ALC Capture NG Switch", WM8753_NGATE, 0, 1, 0), + +SOC_ENUM("3D Function", wm8753_enum[5]), +SOC_ENUM("3D Upper Cut-off", wm8753_enum[6]), +SOC_ENUM("3D Lower Cut-off", wm8753_enum[7]), +SOC_SINGLE("3D Volume", WM8753_3D, 1, 15, 0), +SOC_SINGLE("3D Switch", WM8753_3D, 0, 1, 0), + +SOC_SINGLE("Capture 6dB Attenuate", WM8753_ADCTL1, 2, 1, 0), +SOC_SINGLE("Playback 6dB Attenuate", WM8753_ADCTL1, 1, 1, 0), + +SOC_ENUM("De-emphasis", wm8753_enum[8]), +SOC_ENUM("Playback Mono Mix", wm8753_enum[9]), +SOC_ENUM("Playback Phase", wm8753_enum[10]), + +SOC_SINGLE("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0), +SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0), + +SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai), + +SOC_ENUM("ADC Data Select", wm8753_enum[27]), +}; + +/* add non dapm controls */ +static int wm8753_add_controls(struct snd_soc_codec *codec) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) { + err = snd_ctl_add(codec->card, + snd_soc_cnew(&wm8753_snd_controls[i],codec, NULL)); + if (err < 0) + return err; + } + return 0; +} + +/* + * _DAPM_ Controls + */ + +/* Left Mixer */ +static const struct snd_kcontrol_new wm8753_left_mixer_controls[] = { +SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_LOUTM2, 8, 1, 0), +SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_LOUTM2, 7, 1, 0), +SOC_DAPM_SINGLE("Left Playback Switch", WM8753_LOUTM1, 8, 1, 0), +SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_LOUTM1, 7, 1, 0), +}; + +/* Right mixer */ +static const struct snd_kcontrol_new wm8753_right_mixer_controls[] = { +SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_ROUTM2, 8, 1, 0), +SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_ROUTM2, 7, 1, 0), +SOC_DAPM_SINGLE("Right Playback Switch", WM8753_ROUTM1, 8, 1, 0), +SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_ROUTM1, 7, 1, 0), +}; + +/* Mono mixer */ +static const struct snd_kcontrol_new wm8753_mono_mixer_controls[] = { +SOC_DAPM_SINGLE("Left Playback Switch", WM8753_MOUTM1, 8, 1, 0), +SOC_DAPM_SINGLE("Right Playback Switch", WM8753_MOUTM2, 8, 1, 0), +SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_MOUTM2, 3, 1, 0), +SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_MOUTM2, 7, 1, 0), +SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_MOUTM1, 7, 1, 0), +}; + +/* Mono 2 Mux */ +static const struct snd_kcontrol_new wm8753_mono2_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[17]); + +/* Out 3 Mux */ +static const struct snd_kcontrol_new wm8753_out3_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[18]); + +/* Out 4 Mux */ +static const struct snd_kcontrol_new wm8753_out4_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[19]); + +/* ADC Mono Mix */ +static const struct snd_kcontrol_new wm8753_adc_mono_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[22]); + +/* Record mixer */ +static const struct snd_kcontrol_new wm8753_record_mixer_controls[] = { +SOC_DAPM_SINGLE("Voice Capture Switch", WM8753_RECMIX2, 3, 1, 0), +SOC_DAPM_SINGLE("Left Capture Switch", WM8753_RECMIX1, 3, 1, 0), +SOC_DAPM_SINGLE("Right Capture Switch", WM8753_RECMIX1, 7, 1, 0), +}; + +/* Left ADC mux */ +static const struct snd_kcontrol_new wm8753_adc_left_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[21]); + +/* Right ADC mux */ +static const struct snd_kcontrol_new wm8753_adc_right_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[20]); + +/* MIC mux */ +static const struct snd_kcontrol_new wm8753_mic_mux_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[16]); + +/* ALC mixer */ +static const struct snd_kcontrol_new wm8753_alc_mixer_controls[] = { +SOC_DAPM_SINGLE("Line Capture Switch", WM8753_INCTL2, 3, 1, 0), +SOC_DAPM_SINGLE("Mic2 Capture Switch", WM8753_INCTL2, 2, 1, 0), +SOC_DAPM_SINGLE("Mic1 Capture Switch", WM8753_INCTL2, 1, 1, 0), +SOC_DAPM_SINGLE("Rx Capture Switch", WM8753_INCTL2, 0, 1, 0), +}; + +/* Left Line mux */ +static const struct snd_kcontrol_new wm8753_line_left_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[14]); + +/* Right Line mux */ +static const struct snd_kcontrol_new wm8753_line_right_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[13]); + +/* Mono Line mux */ +static const struct snd_kcontrol_new wm8753_line_mono_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[12]); + +/* Line mux and mixer */ +static const struct snd_kcontrol_new wm8753_line_mux_mix_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[11]); + +/* Rx mux and mixer */ +static const struct snd_kcontrol_new wm8753_rx_mux_mix_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[15]); + +/* Mic Selector Mux */ +static const struct snd_kcontrol_new wm8753_mic_sel_mux_controls = +SOC_DAPM_ENUM("Route", wm8753_enum[25]); + +static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { +SND_SOC_DAPM_MICBIAS("Mic Bias", WM8753_PWR1, 5, 0), +SND_SOC_DAPM_MIXER("Left Mixer", WM8753_PWR4, 0, 0, + &wm8753_left_mixer_controls[0], ARRAY_SIZE(wm8753_left_mixer_controls)), +SND_SOC_DAPM_PGA("Left Out 1", WM8753_PWR3, 8, 0, NULL, 0), +SND_SOC_DAPM_PGA("Left Out 2", WM8753_PWR3, 6, 0, NULL, 0), +SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", WM8753_PWR1, 3, 0), +SND_SOC_DAPM_OUTPUT("LOUT1"), +SND_SOC_DAPM_OUTPUT("LOUT2"), +SND_SOC_DAPM_MIXER("Right Mixer", WM8753_PWR4, 1, 0, + &wm8753_right_mixer_controls[0], ARRAY_SIZE(wm8753_right_mixer_controls)), +SND_SOC_DAPM_PGA("Right Out 1", WM8753_PWR3, 7, 0, NULL, 0), +SND_SOC_DAPM_PGA("Right Out 2", WM8753_PWR3, 5, 0, NULL, 0), +SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", WM8753_PWR1, 2, 0), +SND_SOC_DAPM_OUTPUT("ROUT1"), +SND_SOC_DAPM_OUTPUT("ROUT2"), +SND_SOC_DAPM_MIXER("Mono Mixer", WM8753_PWR4, 2, 0, + &wm8753_mono_mixer_controls[0], ARRAY_SIZE(wm8753_mono_mixer_controls)), +SND_SOC_DAPM_PGA("Mono Out 1", WM8753_PWR3, 2, 0, NULL, 0), +SND_SOC_DAPM_PGA("Mono Out 2", WM8753_PWR3, 1, 0, NULL, 0), +SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", WM8753_PWR1, 4, 0), +SND_SOC_DAPM_OUTPUT("MONO1"), +SND_SOC_DAPM_MUX("Mono 2 Mux", SND_SOC_NOPM, 0, 0, &wm8753_mono2_controls), +SND_SOC_DAPM_OUTPUT("MONO2"), +SND_SOC_DAPM_MIXER("Out3 Left + Right", -1, 0, 0, NULL, 0), +SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out3_controls), +SND_SOC_DAPM_PGA("Out 3", WM8753_PWR3, 4, 0, NULL, 0), +SND_SOC_DAPM_OUTPUT("OUT3"), +SND_SOC_DAPM_MUX("Out4 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out4_controls), +SND_SOC_DAPM_PGA("Out 4", WM8753_PWR3, 3, 0, NULL, 0), +SND_SOC_DAPM_OUTPUT("OUT4"), +SND_SOC_DAPM_MIXER("Playback Mixer", WM8753_PWR4, 3, 0, + &wm8753_record_mixer_controls[0], + ARRAY_SIZE(wm8753_record_mixer_controls)), +SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8753_PWR2, 3, 0), +SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8753_PWR2, 2, 0), +SND_SOC_DAPM_MUX("Capture Left Mixer", SND_SOC_NOPM, 0, 0, + &wm8753_adc_mono_controls), +SND_SOC_DAPM_MUX("Capture Right Mixer", SND_SOC_NOPM, 0, 0, + &wm8753_adc_mono_controls), +SND_SOC_DAPM_MUX("Capture Left Mux", SND_SOC_NOPM, 0, 0, + &wm8753_adc_left_controls), +SND_SOC_DAPM_MUX("Capture Right Mux", SND_SOC_NOPM, 0, 0, + &wm8753_adc_right_controls), +SND_SOC_DAPM_MUX("Mic Sidetone Mux", SND_SOC_NOPM, 0, 0, + &wm8753_mic_mux_controls), +SND_SOC_DAPM_PGA("Left Capture Volume", WM8753_PWR2, 5, 0, NULL, 0), +SND_SOC_DAPM_PGA("Right Capture Volume", WM8753_PWR2, 4, 0, NULL, 0), +SND_SOC_DAPM_MIXER("ALC Mixer", WM8753_PWR2, 6, 0, + &wm8753_alc_mixer_controls[0], ARRAY_SIZE(wm8753_alc_mixer_controls)), +SND_SOC_DAPM_MUX("Line Left Mux", SND_SOC_NOPM, 0, 0, + &wm8753_line_left_controls), +SND_SOC_DAPM_MUX("Line Right Mux", SND_SOC_NOPM, 0, 0, + &wm8753_line_right_controls), +SND_SOC_DAPM_MUX("Line Mono Mux", SND_SOC_NOPM, 0, 0, + &wm8753_line_mono_controls), +SND_SOC_DAPM_MUX("Line Mixer", WM8753_PWR2, 0, 0, + &wm8753_line_mux_mix_controls), +SND_SOC_DAPM_MUX("Rx Mixer", WM8753_PWR2, 1, 0, + &wm8753_rx_mux_mix_controls), +SND_SOC_DAPM_PGA("Mic 1 Volume", WM8753_PWR2, 8, 0, NULL, 0), +SND_SOC_DAPM_PGA("Mic 2 Volume", WM8753_PWR2, 7, 0, NULL, 0), +SND_SOC_DAPM_MUX("Mic Selection Mux", SND_SOC_NOPM, 0, 0, + &wm8753_mic_sel_mux_controls), +SND_SOC_DAPM_INPUT("LINE1"), +SND_SOC_DAPM_INPUT("LINE2"), +SND_SOC_DAPM_INPUT("RXP"), +SND_SOC_DAPM_INPUT("RXN"), +SND_SOC_DAPM_INPUT("ACIN"), +SND_SOC_DAPM_OUTPUT("ACOP"), +SND_SOC_DAPM_INPUT("MIC1N"), +SND_SOC_DAPM_INPUT("MIC1"), +SND_SOC_DAPM_INPUT("MIC2N"), +SND_SOC_DAPM_INPUT("MIC2"), +SND_SOC_DAPM_VMID("VREF"), +}; + +static const char *audio_map[][3] = { + /* left mixer */ + {"Left Mixer", "Left Playback Switch", "Left DAC"}, + {"Left Mixer", "Voice Playback Switch", "Voice DAC"}, + {"Left Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"}, + {"Left Mixer", "Bypass Playback Switch", "Line Left Mux"}, + + /* right mixer */ + {"Right Mixer", "Right Playback Switch", "Right DAC"}, + {"Right Mixer", "Voice Playback Switch", "Voice DAC"}, + {"Right Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"}, + {"Right Mixer", "Bypass Playback Switch", "Line Right Mux"}, + + /* mono mixer */ + {"Mono Mixer", "Voice Playback Switch", "Voice DAC"}, + {"Mono Mixer", "Left Playback Switch", "Left DAC"}, + {"Mono Mixer", "Right Playback Switch", "Right DAC"}, + {"Mono Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"}, + {"Mono Mixer", "Bypass Playback Switch", "Line Mono Mux"}, + + /* left out */ + {"Left Out 1", NULL, "Left Mixer"}, + {"Left Out 2", NULL, "Left Mixer"}, + {"LOUT1", NULL, "Left Out 1"}, + {"LOUT2", NULL, "Left Out 2"}, + + /* right out */ + {"Right Out 1", NULL, "Right Mixer"}, + {"Right Out 2", NULL, "Right Mixer"}, + {"ROUT1", NULL, "Right Out 1"}, + {"ROUT2", NULL, "Right Out 2"}, + + /* mono 1 out */ + {"Mono Out 1", NULL, "Mono Mixer"}, + {"MONO1", NULL, "Mono Out 1"}, + + /* mono 2 out */ + {"Mono 2 Mux", "Left + Right", "Out3 Left + Right"}, + {"Mono 2 Mux", "Inverted Mono 1", "MONO1"}, + {"Mono 2 Mux", "Left", "Left Mixer"}, + {"Mono 2 Mux", "Right", "Right Mixer"}, + {"Mono Out 2", NULL, "Mono 2 Mux"}, + {"MONO2", NULL, "Mono Out 2"}, + + /* out 3 */ + {"Out3 Left + Right", NULL, "Left Mixer"}, + {"Out3 Left + Right", NULL, "Right Mixer"}, + {"Out3 Mux", "VREF", "VREF"}, + {"Out3 Mux", "Left + Right", "Out3 Left + Right"}, + {"Out3 Mux", "ROUT2", "ROUT2"}, + {"Out 3", NULL, "Out3 Mux"}, + {"OUT3", NULL, "Out 3"}, + + /* out 4 */ + {"Out4 Mux", "VREF", "VREF"}, + {"Out4 Mux", "Capture ST", "Capture ST Mixer"}, + {"Out4 Mux", "LOUT2", "LOUT2"}, + {"Out 4", NULL, "Out4 Mux"}, + {"OUT4", NULL, "Out 4"}, + + /* record mixer */ + {"Playback Mixer", "Left Capture Switch", "Left Mixer"}, + {"Playback Mixer", "Voice Capture Switch", "Mono Mixer"}, + {"Playback Mixer", "Right Capture Switch", "Right Mixer"}, + + /* Mic/SideTone Mux */ + {"Mic Sidetone Mux", "Left PGA", "Left Capture Volume"}, + {"Mic Sidetone Mux", "Right PGA", "Right Capture Volume"}, + {"Mic Sidetone Mux", "Mic 1", "Mic 1 Volume"}, + {"Mic Sidetone Mux", "Mic 2", "Mic 2 Volume"}, + + /* Capture Left Mux */ + {"Capture Left Mux", "PGA", "Left Capture Volume"}, + {"Capture Left Mux", "Line or RXP-RXN", "Line Left Mux"}, + {"Capture Left Mux", "Line", "LINE1"}, + + /* Capture Right Mux */ + {"Capture Right Mux", "PGA", "Right Capture Volume"}, + {"Capture Right Mux", "Line or RXP-RXN", "Line Right Mux"}, + {"Capture Right Mux", "Sidetone", "Capture ST Mixer"}, + + /* Mono Capture mixer-mux */ + {"Capture Right Mixer", "Stereo", "Capture Right Mux"}, + {"Capture Left Mixer", "Analogue Mix Left", "Capture Left Mux"}, + {"Capture Left Mixer", "Analogue Mix Left", "Capture Right Mux"}, + {"Capture Right Mixer", "Analogue Mix Right", "Capture Left Mux"}, + {"Capture Right Mixer", "Analogue Mix Right", "Capture Right Mux"}, + {"Capture Left Mixer", "Digital Mono Mix", "Capture Left Mux"}, + {"Capture Left Mixer", "Digital Mono Mix", "Capture Right Mux"}, + {"Capture Right Mixer", "Digital Mono Mix", "Capture Left Mux"}, + {"Capture Right Mixer", "Digital Mono Mix", "Capture Right Mux"}, + + /* ADC */ + {"Left ADC", NULL, "Capture Left Mixer"}, + {"Right ADC", NULL, "Capture Right Mixer"}, + + /* Left Capture Volume */ + {"Left Capture Volume", NULL, "ACIN"}, + + /* Right Capture Volume */ + {"Right Capture Volume", NULL, "Mic 2 Volume"}, + + /* ALC Mixer */ + {"ALC Mixer", "Line Capture Switch", "Line Mixer"}, + {"ALC Mixer", "Mic2 Capture Switch", "Mic 2 Volume"}, + {"ALC Mixer", "Mic1 Capture Switch", "Mic 1 Volume"}, + {"ALC Mixer", "Rx Capture Switch", "Rx Mixer"}, + + /* Line Left Mux */ + {"Line Left Mux", "Line 1", "LINE1"}, + {"Line Left Mux", "Rx Mix", "Rx Mixer"}, + + /* Line Right Mux */ + {"Line Right Mux", "Line 2", "LINE2"}, + {"Line Right Mux", "Rx Mix", "Rx Mixer"}, + + /* Line Mono Mux */ + {"Line Mono Mux", "Line Mix", "Line Mixer"}, + {"Line Mono Mux", "Rx Mix", "Rx Mixer"}, + + /* Line Mixer/Mux */ + {"Line Mixer", "Line 1 + 2", "LINE1"}, + {"Line Mixer", "Line 1 - 2", "LINE1"}, + {"Line Mixer", "Line 1 + 2", "LINE2"}, + {"Line Mixer", "Line 1 - 2", "LINE2"}, + {"Line Mixer", "Line 1", "LINE1"}, + {"Line Mixer", "Line 2", "LINE2"}, + + /* Rx Mixer/Mux */ + {"Rx Mixer", "RXP - RXN", "RXP"}, + {"Rx Mixer", "RXP + RXN", "RXP"}, + {"Rx Mixer", "RXP - RXN", "RXN"}, + {"Rx Mixer", "RXP + RXN", "RXN"}, + {"Rx Mixer", "RXP", "RXP"}, + {"Rx Mixer", "RXN", "RXN"}, + + /* Mic 1 Volume */ + {"Mic 1 Volume", NULL, "MIC1N"}, + {"Mic 1 Volume", NULL, "Mic Selection Mux"}, + + /* Mic 2 Volume */ + {"Mic 2 Volume", NULL, "MIC2N"}, + {"Mic 2 Volume", NULL, "MIC2"}, + + /* Mic Selector Mux */ + {"Mic Selection Mux", "Mic 1", "MIC1"}, + {"Mic Selection Mux", "Mic 2", "MIC2N"}, + {"Mic Selection Mux", "Mic 3", "MIC2"}, + + /* ACOP */ + {"ACOP", NULL, "ALC Mixer"}, + + /* terminator */ + {NULL, NULL, NULL}, +}; + +static int wm8753_add_widgets(struct snd_soc_codec *codec) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++) + snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]); + + /* set up the WM8753 audio map */ + for (i = 0; audio_map[i][0] != NULL; i++) { + snd_soc_dapm_connect_input(codec, audio_map[i][0], + audio_map[i][1], audio_map[i][2]); + } + + snd_soc_dapm_new_widgets(codec); + return 0; +} + +/* PLL divisors */ +struct _pll_div { + u32 div2:1; + u32 n:4; + u32 k:24; +}; + +/* The size in bits of the pll divide multiplied by 10 + * to allow rounding later */ +#define FIXED_PLL_SIZE ((1 << 22) * 10) + +static void pll_factors(struct _pll_div *pll_div, unsigned int target, + unsigned int source) +{ + u64 Kpart; + unsigned int K, Ndiv, Nmod; + + Ndiv = target / source; + if (Ndiv < 6) { + source >>= 1; + pll_div->div2 = 1; + Ndiv = target / source; + } else + pll_div->div2 = 0; + + if ((Ndiv < 6) || (Ndiv > 12)) + printk(KERN_WARNING + "WM8753 N value outwith recommended range! N = %d\n",Ndiv); + + pll_div->n = Ndiv; + Nmod = target % source; + Kpart = FIXED_PLL_SIZE * (long long)Nmod; + + do_div(Kpart, source); + + K = Kpart & 0xFFFFFFFF; + + /* Check if we need to round */ + if ((K % 10) >= 5) + K += 5; + + /* Move down to proper range now rounding is done */ + K /= 10; + + pll_div->k = K; +} + +static int wm8753_set_dai_pll(struct snd_soc_codec_dai *codec_dai, + int pll_id, unsigned int freq_in, unsigned int freq_out) +{ + u16 reg, enable; + int offset; + struct snd_soc_codec *codec = codec_dai->codec; + + if (pll_id < WM8753_PLL1 || pll_id > WM8753_PLL2) + return -ENODEV; + + if (pll_id == WM8753_PLL1) { + offset = 0; + enable = 0x10; + reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef; + } else { + offset = 4; + enable = 0x8; + reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7; + } + + if (!freq_in || !freq_out) { + /* disable PLL */ + wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); + wm8753_write(codec, WM8753_CLOCK, reg); + return 0; + } else { + u16 value = 0; + struct _pll_div pll_div; + + pll_factors(&pll_div, freq_out * 8, freq_in); + + /* set up N and K PLL divisor ratios */ + /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */ + value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18); + wm8753_write(codec, WM8753_PLL1CTL2 + offset, value); + + /* bits 8:0 = PLL_K[17:9] */ + value = (pll_div.k & 0x03fe00) >> 9; + wm8753_write(codec, WM8753_PLL1CTL3 + offset, value); + + /* bits 8:0 = PLL_K[8:0] */ + value = pll_div.k & 0x0001ff; + wm8753_write(codec, WM8753_PLL1CTL4 + offset, value); + + /* set PLL as input and enable */ + wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | + (pll_div.div2 << 3)); + wm8753_write(codec, WM8753_CLOCK, reg | enable); + } + return 0; +} + +struct _coeff_div { + u32 mclk; + u32 rate; + u8 sr:5; + u8 usb:1; +}; + +/* codec hifi mclk (after PLL) clock divider coefficients */ +static const struct _coeff_div coeff_div[] = { + /* 8k */ + {12288000, 8000, 0x6, 0x0}, + {11289600, 8000, 0x16, 0x0}, + {18432000, 8000, 0x7, 0x0}, + {16934400, 8000, 0x17, 0x0}, + {12000000, 8000, 0x6, 0x1}, + + /* 11.025k */ + {11289600, 11025, 0x18, 0x0}, + {16934400, 11025, 0x19, 0x0}, + {12000000, 11025, 0x19, 0x1}, + + /* 16k */ + {12288000, 16000, 0xa, 0x0}, + {18432000, 16000, 0xb, 0x0}, + {12000000, 16000, 0xa, 0x1}, + + /* 22.05k */ + {11289600, 22050, 0x1a, 0x0}, + {16934400, 22050, 0x1b, 0x0}, + {12000000, 22050, 0x1b, 0x1}, + + /* 32k */ + {12288000, 32000, 0xc, 0x0}, + {18432000, 32000, 0xd, 0x0}, + {12000000, 32000, 0xa, 0x1}, + + /* 44.1k */ + {11289600, 44100, 0x10, 0x0}, + {16934400, 44100, 0x11, 0x0}, + {12000000, 44100, 0x11, 0x1}, + + /* 48k */ + {12288000, 48000, 0x0, 0x0}, + {18432000, 48000, 0x1, 0x0}, + {12000000, 48000, 0x0, 0x1}, + + /* 88.2k */ + {11289600, 88200, 0x1e, 0x0}, + {16934400, 88200, 0x1f, 0x0}, + {12000000, 88200, 0x1f, 0x1}, + + /* 96k */ + {12288000, 96000, 0xe, 0x0}, + {18432000, 96000, 0xf, 0x0}, + {12000000, 96000, 0xe, 0x1}, +}; + +static int get_coeff(int mclk, int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { + if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) + return i; + } + return -EINVAL; +} + +/* + * Clock after PLL and dividers + */ +static int wm8753_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct wm8753_priv *wm8753 = codec->private_data; + + switch (freq) { + case 11289600: + case 12000000: + case 12288000: + case 16934400: + case 18432000: + if (clk_id == WM8753_MCLK) { + wm8753->sysclk = freq; + return 0; + } else if (clk_id == WM8753_PCMCLK) { + wm8753->pcmclk = freq; + return 0; + } + break; + } + return -EINVAL; +} + +/* + * Set's ADC and Voice DAC format. + */ +static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec; + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + voice |= 0x0002; + break; + case SND_SOC_DAIFMT_RIGHT_J: + break; + case SND_SOC_DAIFMT_LEFT_J: + voice |= 0x0001; + break; + case SND_SOC_DAIFMT_DSP_A: + voice |= 0x0003; + break; + case SND_SOC_DAIFMT_DSP_B: + voice |= 0x0013; + break; + default: + return -EINVAL; + } + + wm8753_write(codec, WM8753_PCM, voice); + return 0; +} + +/* + * Set PCM DAI bit size and sample rate. + */ +static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + struct wm8753_priv *wm8753 = codec->private_data; + u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; + u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; + + /* bit size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + voice |= 0x0004; + break; + case SNDRV_PCM_FORMAT_S24_LE: + voice |= 0x0008; + break; + case SNDRV_PCM_FORMAT_S32_LE: + voice |= 0x000c; + break; + } + + /* sample rate */ + if (params_rate(params) * 384 == wm8753->pcmclk) + srate |= 0x80; + wm8753_write(codec, WM8753_SRATE1, srate); + + wm8753_write(codec, WM8753_PCM, voice); + return 0; +} + +/* + * Set's PCM dai fmt and BCLK. + */ +static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 voice, ioctl; + + voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f; + ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d; + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + case SND_SOC_DAIFMT_CBM_CFM: + ioctl |= 0x2; + case SND_SOC_DAIFMT_CBM_CFS: + voice |= 0x0040; + break; + default: + return -EINVAL; + } + + /* clock inversion */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + /* frame inversion not valid for DSP modes */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + voice |= 0x0080; + break; + default: + return -EINVAL; + } + break; + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + voice &= ~0x0010; + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + voice |= 0x0090; + break; + case SND_SOC_DAIFMT_IB_NF: + voice |= 0x0080; + break; + case SND_SOC_DAIFMT_NB_IF: + voice |= 0x0010; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + wm8753_write(codec, WM8753_PCM, voice); + wm8753_write(codec, WM8753_IOCTL, ioctl); + return 0; +} + +static int wm8753_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai, + int div_id, int div) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 reg; + + switch (div_id) { + case WM8753_PCMDIV: + reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f; + wm8753_write(codec, WM8753_CLOCK, reg | div); + break; + case WM8753_BCLKDIV: + reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7; + wm8753_write(codec, WM8753_SRATE2, reg | div); + break; + case WM8753_VXCLKDIV: + reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f; + wm8753_write(codec, WM8753_SRATE2, reg | div); + break; + default: + return -EINVAL; + } + return 0; +} + +/* + * Set's HiFi DAC format. + */ +static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0; + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + hifi |= 0x0002; + break; + case SND_SOC_DAIFMT_RIGHT_J: + break; + case SND_SOC_DAIFMT_LEFT_J: + hifi |= 0x0001; + break; + case SND_SOC_DAIFMT_DSP_A: + hifi |= 0x0003; + break; + case SND_SOC_DAIFMT_DSP_B: + hifi |= 0x0013; + break; + default: + return -EINVAL; + } + + wm8753_write(codec, WM8753_HIFI, hifi); + return 0; +} + +/* + * Set's I2S DAI format. + */ +static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 ioctl, hifi; + + hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f; + ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae; + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + case SND_SOC_DAIFMT_CBM_CFM: + ioctl |= 0x1; + case SND_SOC_DAIFMT_CBM_CFS: + hifi |= 0x0040; + break; + default: + return -EINVAL; + } + + /* clock inversion */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + /* frame inversion not valid for DSP modes */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + hifi |= 0x0080; + break; + default: + return -EINVAL; + } + break; + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + hifi &= ~0x0010; + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + hifi |= 0x0090; + break; + case SND_SOC_DAIFMT_IB_NF: + hifi |= 0x0080; + break; + case SND_SOC_DAIFMT_NB_IF: + hifi |= 0x0010; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + wm8753_write(codec, WM8753_HIFI, hifi); + wm8753_write(codec, WM8753_IOCTL, ioctl); + return 0; +} + +/* + * Set PCM DAI bit size and sample rate. + */ +static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + struct wm8753_priv *wm8753 = codec->private_data; + u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; + u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; + int coeff; + + /* is digital filter coefficient valid ? */ + coeff = get_coeff(wm8753->sysclk, params_rate(params)); + if (coeff < 0) { + printk(KERN_ERR "wm8753 invalid MCLK or rate\n"); + return coeff; + } + wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | + coeff_div[coeff].usb); + + /* bit size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + hifi |= 0x0004; + break; + case SNDRV_PCM_FORMAT_S24_LE: + hifi |= 0x0008; + break; + case SNDRV_PCM_FORMAT_S32_LE: + hifi |= 0x000c; + break; + } + + wm8753_write(codec, WM8753_HIFI, hifi); + return 0; +} + +static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 clock; + + /* set clk source as pcmclk */ + clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; + wm8753_write(codec, WM8753_CLOCK, clock); + + if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) + return -EINVAL; + return wm8753_pcm_set_dai_fmt(codec_dai, fmt); +} + +static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, + unsigned int fmt) +{ + if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) + return -EINVAL; + return wm8753_i2s_set_dai_fmt(codec_dai, fmt); +} + +static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 clock; + + /* set clk source as pcmclk */ + clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; + wm8753_write(codec, WM8753_CLOCK, clock); + + if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) + return -EINVAL; + return wm8753_i2s_set_dai_fmt(codec_dai, fmt); +} + +static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 clock; + + /* set clk source as mclk */ + clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; + wm8753_write(codec, WM8753_CLOCK, clock | 0x4); + + if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) + return -EINVAL; + if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) + return -EINVAL; + return wm8753_i2s_set_dai_fmt(codec_dai, fmt); +} + +static int wm8753_mute(struct snd_soc_codec_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; + + /* the digital mute covers the HiFi and Voice DAC's on the WM8753. + * make sure we check if they are not both active when we mute */ + if (mute && dai->id == 1) { + if (!wm8753_dai[WM8753_DAI_VOICE].playback.active || + !wm8753_dai[WM8753_DAI_HIFI].playback.active) + wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); + } else { + if (mute) + wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); + else + wm8753_write(codec, WM8753_DAC, mute_reg); + } + + return 0; +} + +static int wm8753_dapm_event(struct snd_soc_codec *codec, int event) +{ + u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e; + + switch (event) { + case SNDRV_CTL_POWER_D0: /* full On */ + /* set vmid to 50k and unmute dac */ + wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); + break; + case SNDRV_CTL_POWER_D1: /* partial On */ + case SNDRV_CTL_POWER_D2: /* partial On */ + /* set vmid to 5k for quick power up */ + wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); + break; + case SNDRV_CTL_POWER_D3hot: /* Off, with power */ + /* mute dac and set vmid to 500k, enable VREF */ + wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141); + break; + case SNDRV_CTL_POWER_D3cold: /* Off, without power */ + wm8753_write(codec, WM8753_PWR1, 0x0001); + break; + } + codec->dapm_state = event; + return 0; +} + +#define WM8753_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) + +#define WM8753_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE) + +/* + * The WM8753 supports upto 4 different and mutually exclusive DAI + * configurations. This gives 2 PCM's available for use, hifi and voice. + * NOTE: The Voice PCM cannot play or capture audio to the CPU as it's DAI + * is connected between the wm8753 and a BT codec or GSM modem. + * + * 1. Voice over PCM DAI - HIFI DAC over HIFI DAI + * 2. Voice over HIFI DAI - HIFI disabled + * 3. Voice disabled - HIFI over HIFI + * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture + */ +static const struct snd_soc_codec_dai wm8753_all_dai[] = { +/* DAI HiFi mode 1 */ +{ .name = "WM8753 HiFi", + .id = 1, + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .capture = { /* dummy for fast DAI switching */ + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .ops = { + .hw_params = wm8753_i2s_hw_params,}, + .dai_ops = { + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode1h_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, + }, +}, +/* DAI Voice mode 1 */ +{ .name = "WM8753 Voice", + .id = 1, + .playback = { + .stream_name = "Voice Playback", + .channels_min = 1, + .channels_max = 1, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .ops = { + .hw_params = wm8753_pcm_hw_params,}, + .dai_ops = { + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode1v_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, + }, +}, +/* DAI HiFi mode 2 - dummy */ +{ .name = "WM8753 HiFi", + .id = 2, +}, +/* DAI Voice mode 2 */ +{ .name = "WM8753 Voice", + .id = 2, + .playback = { + .stream_name = "Voice Playback", + .channels_min = 1, + .channels_max = 1, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .ops = { + .hw_params = wm8753_pcm_hw_params,}, + .dai_ops = { + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode2_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, + }, +}, +/* DAI HiFi mode 3 */ +{ .name = "WM8753 HiFi", + .id = 3, + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .ops = { + .hw_params = wm8753_i2s_hw_params,}, + .dai_ops = { + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode3_4_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, + }, +}, +/* DAI Voice mode 3 - dummy */ +{ .name = "WM8753 Voice", + .id = 3, +}, +/* DAI HiFi mode 4 */ +{ .name = "WM8753 HiFi", + .id = 4, + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8753_RATES, + .formats = WM8753_FORMATS,}, + .ops = { + .hw_params = wm8753_i2s_hw_params,}, + .dai_ops = { + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode3_4_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, + }, +}, +/* DAI Voice mode 4 - dummy */ +{ .name = "WM8753 Voice", + .id = 4, +}, +}; + +struct snd_soc_codec_dai wm8753_dai[2]; +EXPORT_SYMBOL_GPL(wm8753_dai); + +static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode) +{ + if (mode < 4) { + int playback_active, capture_active, codec_active, pop_wait; + void *private_data; + + playback_active = wm8753_dai[0].playback.active; + capture_active = wm8753_dai[0].capture.active; + codec_active = wm8753_dai[0].active; + private_data = wm8753_dai[0].private_data; + pop_wait = wm8753_dai[0].pop_wait; + wm8753_dai[0] = wm8753_all_dai[mode << 1]; + wm8753_dai[0].playback.active = playback_active; + wm8753_dai[0].capture.active = capture_active; + wm8753_dai[0].active = codec_active; + wm8753_dai[0].private_data = private_data; + wm8753_dai[0].pop_wait = pop_wait; + + playback_active = wm8753_dai[1].playback.active; + capture_active = wm8753_dai[1].capture.active; + codec_active = wm8753_dai[1].active; + private_data = wm8753_dai[1].private_data; + pop_wait = wm8753_dai[1].pop_wait; + wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1]; + wm8753_dai[1].playback.active = playback_active; + wm8753_dai[1].capture.active = capture_active; + wm8753_dai[1].active = codec_active; + wm8753_dai[1].private_data = private_data; + wm8753_dai[1].pop_wait = pop_wait; + } + wm8753_dai[0].codec = codec; + wm8753_dai[1].codec = codec; +} + +static void wm8753_work(struct work_struct *work) +{ + struct snd_soc_codec *codec = + container_of(work, struct snd_soc_codec, delayed_work.work); + wm8753_dapm_event(codec, codec->dapm_state); +} + +static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + /* we only need to suspend if we are a valid card */ + if(!codec->card) + return 0; + + wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold); + return 0; +} + +static int wm8753_resume(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + int i; + u8 data[2]; + u16 *cache = codec->reg_cache; + + /* we only need to resume if we are a valid card */ + if(!codec->card) + return 0; + + /* Sync reg_cache with the hardware */ + for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { + if (i + 1 == WM8753_RESET) + continue; + data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); + data[1] = cache[i] & 0x00ff; + codec->hw_write(codec->control_data, data, 2); + } + + wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3hot); + + /* charge wm8753 caps */ + if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) { + wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2); + codec->dapm_state = SNDRV_CTL_POWER_D0; + schedule_delayed_work(&codec->delayed_work, + msecs_to_jiffies(caps_charge)); + } + + return 0; +} + +/* + * initialise the WM8753 driver + * register the mixer and dsp interfaces with the kernel + */ +static int wm8753_init(struct snd_soc_device *socdev) +{ + struct snd_soc_codec *codec = socdev->codec; + int reg, ret = 0; + + codec->name = "WM8753"; + codec->owner = THIS_MODULE; + codec->read = wm8753_read_reg_cache; + codec->write = wm8753_write; + codec->dapm_event = wm8753_dapm_event; + codec->dai = wm8753_dai; + codec->num_dai = 2; + codec->reg_cache_size = sizeof(wm8753_reg); + codec->reg_cache = kmemdup(wm8753_reg, sizeof(wm8753_reg), GFP_KERNEL); + + if (codec->reg_cache == NULL) + return -ENOMEM; + + wm8753_set_dai_mode(codec, 0); + + wm8753_reset(codec); + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + printk(KERN_ERR "wm8753: failed to create pcms\n"); + goto pcm_err; + } + + /* charge output caps */ + wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2); + codec->dapm_state = SNDRV_CTL_POWER_D3hot; + schedule_delayed_work(&codec->delayed_work, + msecs_to_jiffies(caps_charge)); + + /* set the update bits */ + reg = wm8753_read_reg_cache(codec, WM8753_LDAC); + wm8753_write(codec, WM8753_LDAC, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_RDAC); + wm8753_write(codec, WM8753_RDAC, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_LADC); + wm8753_write(codec, WM8753_LADC, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_RADC); + wm8753_write(codec, WM8753_RADC, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V); + wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V); + wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V); + wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V); + wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_LINVOL); + wm8753_write(codec, WM8753_LINVOL, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); + wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); + + wm8753_add_controls(codec); + wm8753_add_widgets(codec); + ret = snd_soc_register_card(socdev); + if (ret < 0) { + printk(KERN_ERR "wm8753: failed to register card\n"); + goto card_err; + } + return ret; + +card_err: + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +pcm_err: + kfree(codec->reg_cache); + return ret; +} + +/* If the i2c layer weren't so broken, we could pass this kind of data + around */ +static struct snd_soc_device *wm8753_socdev; + +#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) + +/* + * WM8753 2 wire address is determined by GPIO5 + * state during powerup. + * low = 0x1a + * high = 0x1b + */ +static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; + +/* Magic definition of all other variables and things */ +I2C_CLIENT_INSMOD; + +static struct i2c_driver wm8753_i2c_driver; +static struct i2c_client client_template; + +static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind) +{ + struct snd_soc_device *socdev = wm8753_socdev; + struct wm8753_setup_data *setup = socdev->codec_data; + struct snd_soc_codec *codec = socdev->codec; + struct i2c_client *i2c; + int ret; + + if (addr != setup->i2c_address) + return -ENODEV; + + client_template.adapter = adap; + client_template.addr = addr; + + i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); + if (i2c == NULL){ + kfree(codec); + return -ENOMEM; + } + i2c_set_clientdata(i2c, codec); + codec->control_data = i2c; + + ret = i2c_attach_client(i2c); + if (ret < 0) { + err("failed to attach codec at addr %x\n", addr); + goto err; + } + + ret = wm8753_init(socdev); + if (ret < 0) { + err("failed to initialise WM8753\n"); + goto err; + } + + return ret; + +err: + kfree(codec); + kfree(i2c); + return ret; +} + +static int wm8753_i2c_detach(struct i2c_client *client) +{ + struct snd_soc_codec *codec = i2c_get_clientdata(client); + i2c_detach_client(client); + kfree(codec->reg_cache); + kfree(client); + return 0; +} + +static int wm8753_i2c_attach(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, wm8753_codec_probe); +} + +/* corgi i2c codec control layer */ +static struct i2c_driver wm8753_i2c_driver = { + .driver = { + .name = "WM8753 I2C Codec", + .owner = THIS_MODULE, + }, + .id = I2C_DRIVERID_WM8753, + .attach_adapter = wm8753_i2c_attach, + .detach_client = wm8753_i2c_detach, + .command = NULL, +}; + +static struct i2c_client client_template = { + .name = "WM8753", + .driver = &wm8753_i2c_driver, +}; +#endif + +static int wm8753_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct wm8753_setup_data *setup; + struct snd_soc_codec *codec; + struct wm8753_priv *wm8753; + int ret = 0; + + info("WM8753 Audio Codec %s", WM8753_VERSION); + + setup = socdev->codec_data; + codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (codec == NULL) + return -ENOMEM; + + wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); + if (wm8753 == NULL) { + kfree(codec); + return -ENOMEM; + } + + codec->private_data = wm8753; + socdev->codec = codec; + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + wm8753_socdev = socdev; + INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); + +#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) + if (setup->i2c_address) { + normal_i2c[0] = setup->i2c_address; + codec->hw_write = (hw_write_t)i2c_master_send; + ret = i2c_add_driver(&wm8753_i2c_driver); + if (ret != 0) + printk(KERN_ERR "can't add i2c driver"); + } +#else + /* Add other interfaces here */ +#endif + return ret; +} + +/* + * This function forces any delayed work to be queued and run. + */ +static int run_delayed_work(struct delayed_work *dwork) +{ + int ret; + + /* cancel any work waiting to be queued. */ + ret = cancel_delayed_work(dwork); + + /* if there was any work waiting then we run it now and + * wait for it's completion */ + if (ret) { + schedule_delayed_work(dwork, 0); + flush_scheduled_work(); + } + return ret; +} + +/* power down chip */ +static int wm8753_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + if (codec->control_data) + wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold); + run_delayed_work(&codec->delayed_work); + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) + i2c_del_driver(&wm8753_i2c_driver); +#endif + kfree(codec->private_data); + kfree(codec); + + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_wm8753 = { + .probe = wm8753_probe, + .remove = wm8753_remove, + .suspend = wm8753_suspend, + .resume = wm8753_resume, +}; + +EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); + +MODULE_DESCRIPTION("ASoC WM8753 driver"); +MODULE_AUTHOR("Liam Girdwood"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h new file mode 100644 index 000000000000..95e2a1f53169 --- /dev/null +++ b/sound/soc/codecs/wm8753.h @@ -0,0 +1,126 @@ +/* + * wm8753.h -- audio driver for WM8753 + * + * Copyright 2003 Wolfson Microelectronics PLC. + * Author: Liam Girdwood + * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef _WM8753_H +#define _WM8753_H + +/* WM8753 register space */ + +#define WM8753_DAC 0x01 +#define WM8753_ADC 0x02 +#define WM8753_PCM 0x03 +#define WM8753_HIFI 0x04 +#define WM8753_IOCTL 0x05 +#define WM8753_SRATE1 0x06 +#define WM8753_SRATE2 0x07 +#define WM8753_LDAC 0x08 +#define WM8753_RDAC 0x09 +#define WM8753_BASS 0x0a +#define WM8753_TREBLE 0x0b +#define WM8753_ALC1 0x0c +#define WM8753_ALC2 0x0d +#define WM8753_ALC3 0x0e +#define WM8753_NGATE 0x0f +#define WM8753_LADC 0x10 +#define WM8753_RADC 0x11 +#define WM8753_ADCTL1 0x12 +#define WM8753_3D 0x13 +#define WM8753_PWR1 0x14 +#define WM8753_PWR2 0x15 +#define WM8753_PWR3 0x16 +#define WM8753_PWR4 0x17 +#define WM8753_ID 0x18 +#define WM8753_INTPOL 0x19 +#define WM8753_INTEN 0x1a +#define WM8753_GPIO1 0x1b +#define WM8753_GPIO2 0x1c +#define WM8753_RESET 0x1f +#define WM8753_RECMIX1 0x20 +#define WM8753_RECMIX2 0x21 +#define WM8753_LOUTM1 0x22 +#define WM8753_LOUTM2 0x23 +#define WM8753_ROUTM1 0x24 +#define WM8753_ROUTM2 0x25 +#define WM8753_MOUTM1 0x26 +#define WM8753_MOUTM2 0x27 +#define WM8753_LOUT1V 0x28 +#define WM8753_ROUT1V 0x29 +#define WM8753_LOUT2V 0x2a +#define WM8753_ROUT2V 0x2b +#define WM8753_MOUTV 0x2c +#define WM8753_OUTCTL 0x2d +#define WM8753_ADCIN 0x2e +#define WM8753_INCTL1 0x2f +#define WM8753_INCTL2 0x30 +#define WM8753_LINVOL 0x31 +#define WM8753_RINVOL 0x32 +#define WM8753_MICBIAS 0x33 +#define WM8753_CLOCK 0x34 +#define WM8753_PLL1CTL1 0x35 +#define WM8753_PLL1CTL2 0x36 +#define WM8753_PLL1CTL3 0x37 +#define WM8753_PLL1CTL4 0x38 +#define WM8753_PLL2CTL1 0x39 +#define WM8753_PLL2CTL2 0x3a +#define WM8753_PLL2CTL3 0x3b +#define WM8753_PLL2CTL4 0x3c +#define WM8753_BIASCTL 0x3d +#define WM8753_ADCTL2 0x3f + +struct wm8753_setup_data { + unsigned short i2c_address; +}; + +#define WM8753_PLL1 0 +#define WM8753_PLL2 1 + +/* clock inputs */ +#define WM8753_MCLK 0 +#define WM8753_PCMCLK 1 + +/* clock divider id's */ +#define WM8753_PCMDIV 0 +#define WM8753_BCLKDIV 1 +#define WM8753_VXCLKDIV 2 + +/* PCM clock dividers */ +#define WM8753_PCM_DIV_1 (0 << 6) +#define WM8753_PCM_DIV_3 (2 << 6) +#define WM8753_PCM_DIV_5_5 (3 << 6) +#define WM8753_PCM_DIV_2 (4 << 6) +#define WM8753_PCM_DIV_4 (5 << 6) +#define WM8753_PCM_DIV_6 (6 << 6) +#define WM8753_PCM_DIV_8 (7 << 6) + +/* BCLK clock dividers */ +#define WM8753_BCLK_DIV_1 (0 << 3) +#define WM8753_BCLK_DIV_2 (1 << 3) +#define WM8753_BCLK_DIV_4 (2 << 3) +#define WM8753_BCLK_DIV_8 (3 << 3) +#define WM8753_BCLK_DIV_16 (4 << 3) + +/* VXCLK clock dividers */ +#define WM8753_VXCLK_DIV_1 (0 << 6) +#define WM8753_VXCLK_DIV_2 (1 << 6) +#define WM8753_VXCLK_DIV_4 (2 << 6) +#define WM8753_VXCLK_DIV_8 (3 << 6) +#define WM8753_VXCLK_DIV_16 (4 << 6) + +#define WM8753_DAI_HIFI 0 +#define WM8753_DAI_VOICE 1 + +extern struct snd_soc_codec_dai wm8753_dai[2]; +extern struct snd_soc_codec_device soc_codec_dev_wm8753; + +#endif diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index ee7a691a9ba1..264413a00cac 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -676,14 +676,13 @@ static int wm9712_soc_probe(struct platform_device *pdev) codec = socdev->codec; mutex_init(&codec->mutex); - codec->reg_cache = - kzalloc(sizeof(u16) * ARRAY_SIZE(wm9712_reg), GFP_KERNEL); + codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL); + if (codec->reg_cache == NULL) { ret = -ENOMEM; goto cache_err; } - memcpy(codec->reg_cache, wm9712_reg, sizeof(u16) * ARRAY_SIZE(wm9712_reg)); - codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm9712_reg); + codec->reg_cache_size = sizeof(wm9712_reg); codec->reg_cache_step = 2; codec->name = "WM9712"; diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index b9ab3b8e1d3e..a83e22937c27 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -1,5 +1,3 @@ -menu "SoC Audio for the Intel PXA2xx" - config SND_PXA2XX_SOC tristate "SoC Audio for the Intel PXA2xx chip" depends on ARCH_PXA && SND_SOC @@ -55,5 +53,3 @@ config SND_PXA2XX_SOC_TOSA help Say Y if you want to add support for SoC audio on Sharp Zaurus SL-C6000x models (Tosa). - -endmenu diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig new file mode 100644 index 000000000000..044a3712077a --- /dev/null +++ b/sound/soc/s3c24xx/Kconfig @@ -0,0 +1,10 @@ +config SND_S3C24XX_SOC + tristate "SoC Audio for the Samsung S3C24XX chips" + depends on ARCH_S3C2410 && SND_SOC + help + Say Y or M if you want to add support for codecs attached to + the S3C24XX AC97, I2S or SSP interface. You will also need + to select the audio interfaces to support below. + +config SND_S3C24XX_SOC_I2S + tristate diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile new file mode 100644 index 000000000000..6f0fffcb30f5 --- /dev/null +++ b/sound/soc/s3c24xx/Makefile @@ -0,0 +1,6 @@ +# S3c24XX Platform Support +snd-soc-s3c24xx-objs := s3c24xx-pcm.o +snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o + +obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o +obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c new file mode 100644 index 000000000000..8ca314dc8891 --- /dev/null +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c @@ -0,0 +1,441 @@ +/* + * s3c24xx-i2s.c -- ALSA Soc Audio Layer + * + * (c) 2006 Wolfson Microelectronics PLC. + * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com + * + * (c) 2004-2005 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * + * Revision history + * 11th Dec 2006 Merged with Simtec driver + * 10th Nov 2006 Initial version. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/initval.h> +#include <sound/soc.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/arch/regs-iis.h> +#include <asm/arch/regs-gpio.h> +#include <asm/arch/regs-clock.h> +#include <asm/arch/audio.h> +#include <asm/dma.h> +#include <asm/arch/dma.h> + +#include "s3c24xx-pcm.h" +#include "s3c24xx-i2s.h" + +#define S3C24XX_I2S_DEBUG 0 +#if S3C24XX_I2S_DEBUG +#define DBG(x...) printk(KERN_DEBUG x) +#else +#define DBG(x...) +#endif + +static struct s3c2410_dma_client s3c24xx_dma_client_out = { + .name = "I2S PCM Stereo out" +}; + +static struct s3c2410_dma_client s3c24xx_dma_client_in = { + .name = "I2S PCM Stereo in" +}; + +static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_out = { + .client = &s3c24xx_dma_client_out, + .channel = DMACH_I2S_OUT, + .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, + .dma_size = 2, +}; + +static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_in = { + .client = &s3c24xx_dma_client_in, + .channel = DMACH_I2S_IN, + .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, + .dma_size = 2, +}; + +struct s3c24xx_i2s_info { + void __iomem *regs; + struct clk *iis_clk; +}; +static struct s3c24xx_i2s_info s3c24xx_i2s; + +static void s3c24xx_snd_txctrl(int on) +{ + u32 iisfcon; + u32 iiscon; + u32 iismod; + + DBG("Entered %s\n", __FUNCTION__); + + iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); + iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); + iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); + + DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); + + if (on) { + iisfcon |= S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE; + iiscon |= S3C2410_IISCON_TXDMAEN | S3C2410_IISCON_IISEN; + iiscon &= ~S3C2410_IISCON_TXIDLE; + iismod |= S3C2410_IISMOD_TXMODE; + + writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); + writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON); + writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); + } else { + /* note, we have to disable the FIFOs otherwise bad things + * seem to happen when the DMA stops. According to the + * Samsung supplied kernel, this should allow the DMA + * engine and FIFOs to reset. If this isn't allowed, the + * DMA engine will simply freeze randomly. + */ + + iisfcon &= ~S3C2410_IISFCON_TXENABLE; + iisfcon &= ~S3C2410_IISFCON_TXDMA; + iiscon |= S3C2410_IISCON_TXIDLE; + iiscon &= ~S3C2410_IISCON_TXDMAEN; + iismod &= ~S3C2410_IISMOD_TXMODE; + + writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); + writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON); + writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); + } + + DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); +} + +static void s3c24xx_snd_rxctrl(int on) +{ + u32 iisfcon; + u32 iiscon; + u32 iismod; + + DBG("Entered %s\n", __FUNCTION__); + + iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); + iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); + iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); + + DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); + + if (on) { + iisfcon |= S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE; + iiscon |= S3C2410_IISCON_RXDMAEN | S3C2410_IISCON_IISEN; + iiscon &= ~S3C2410_IISCON_RXIDLE; + iismod |= S3C2410_IISMOD_RXMODE; + + writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); + writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON); + writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); + } else { + /* note, we have to disable the FIFOs otherwise bad things + * seem to happen when the DMA stops. According to the + * Samsung supplied kernel, this should allow the DMA + * engine and FIFOs to reset. If this isn't allowed, the + * DMA engine will simply freeze randomly. + */ + + iisfcon &= ~S3C2410_IISFCON_RXENABLE; + iisfcon &= ~S3C2410_IISFCON_RXDMA; + iiscon |= S3C2410_IISCON_RXIDLE; + iiscon &= ~S3C2410_IISCON_RXDMAEN; + iismod &= ~S3C2410_IISMOD_RXMODE; + + writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON); + writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); + writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); + } + + DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); +} + +/* + * Wait for the LR signal to allow synchronisation to the L/R clock + * from the codec. May only be needed for slave mode. + */ +static int s3c24xx_snd_lrsync(void) +{ + u32 iiscon; + unsigned long timeout = jiffies + msecs_to_jiffies(5); + + DBG("Entered %s\n", __FUNCTION__); + + while (1) { + iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); + if (iiscon & S3C2410_IISCON_LRINDEX) + break; + + if (timeout < jiffies) + return -ETIMEDOUT; + } + + return 0; +} + +/* + * Check whether CPU is the master or slave + */ +static inline int s3c24xx_snd_is_clkmaster(void) +{ + DBG("Entered %s\n", __FUNCTION__); + + return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1; +} + +/* + * Set S3C24xx I2S DAI format + */ +static int s3c24xx_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai, + unsigned int fmt) +{ + u32 iismod; + + DBG("Entered %s\n", __FUNCTION__); + + iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); + DBG("hw_params r: IISMOD: %lx \n", iismod); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + iismod |= S3C2410_IISMOD_SLAVE; + break; + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_LEFT_J: + iismod |= S3C2410_IISMOD_MSB; + break; + case SND_SOC_DAIFMT_I2S: + break; + default: + return -EINVAL; + } + + writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); + DBG("hw_params w: IISMOD: %lx \n", iismod); + return 0; +} + +static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + u32 iismod; + + DBG("Entered %s\n", __FUNCTION__); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out; + else + rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_in; + + /* Working copies of register */ + iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); + DBG("hw_params r: IISMOD: %lx\n", iismod); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + break; + case SNDRV_PCM_FORMAT_S16_LE: + iismod |= S3C2410_IISMOD_16BIT; + break; + } + + writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); + DBG("hw_params w: IISMOD: %lx\n", iismod); + return 0; +} + +static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd) +{ + int ret = 0; + + DBG("Entered %s\n", __FUNCTION__); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (!s3c24xx_snd_is_clkmaster()) { + ret = s3c24xx_snd_lrsync(); + if (ret) + goto exit_err; + } + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + s3c24xx_snd_rxctrl(1); + else + s3c24xx_snd_txctrl(1); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + s3c24xx_snd_rxctrl(0); + else + s3c24xx_snd_txctrl(0); + break; + default: + ret = -EINVAL; + break; + } + +exit_err: + return ret; +} + +/* + * Set S3C24xx Clock source + */ +static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); + + DBG("Entered %s\n", __FUNCTION__); + + iismod &= ~S3C2440_IISMOD_MPLL; + + switch (clk_id) { + case S3C24XX_CLKSRC_PCLK: + break; + case S3C24XX_CLKSRC_MPLL: + iismod |= S3C2440_IISMOD_MPLL; + break; + default: + return -EINVAL; + } + + writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); + return 0; +} + +/* + * Set S3C24xx Clock dividers + */ +static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai, + int div_id, int div) +{ + u32 reg; + + DBG("Entered %s\n", __FUNCTION__); + + switch (div_id) { + case S3C24XX_DIV_MCLK: + reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK; + writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD); + break; + case S3C24XX_DIV_BCLK: + reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~(S3C2410_IISMOD_384FS); + writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD); + break; + case S3C24XX_DIV_PRESCALER: + writel(div, s3c24xx_i2s.regs + S3C2410_IISPSR); + reg = readl(s3c24xx_i2s.regs + S3C2410_IISCON); + writel(reg | S3C2410_IISCON_PSCEN, s3c24xx_i2s.regs + S3C2410_IISCON); + break; + default: + return -EINVAL; + } + + return 0; +} + +/* + * To avoid duplicating clock code, allow machine driver to + * get the clockrate from here. + */ +u32 s3c24xx_i2s_get_clockrate(void) +{ + return clk_get_rate(s3c24xx_i2s.iis_clk); +} +EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); + +static int s3c24xx_i2s_probe(struct platform_device *pdev) +{ + DBG("Entered %s\n", __FUNCTION__); + + s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); + if (s3c24xx_i2s.regs == NULL) + return -ENXIO; + + s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis"); + if (s3c24xx_i2s.iis_clk == NULL) { + DBG("failed to get iis_clock\n"); + return -ENODEV; + } + clk_enable(s3c24xx_i2s.iis_clk); + + /* Configure the I2S pins in correct mode */ + s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK); + s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2410_GPE1_I2SSCLK); + s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2410_GPE2_CDCLK); + s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI); + s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO); + + writel(S3C2410_IISCON_IISEN, s3c24xx_i2s.regs + S3C2410_IISCON); + + s3c24xx_snd_txctrl(0); + s3c24xx_snd_rxctrl(0); + + return 0; +} + +#define S3C24XX_I2S_RATES \ + (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) + +struct snd_soc_cpu_dai s3c24xx_i2s_dai = { + .name = "s3c24xx-i2s", + .id = 0, + .type = SND_SOC_DAI_I2S, + .probe = s3c24xx_i2s_probe, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C24XX_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C24XX_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .trigger = s3c24xx_i2s_trigger, + .hw_params = s3c24xx_i2s_hw_params,}, + .dai_ops = { + .set_fmt = s3c24xx_i2s_set_fmt, + .set_clkdiv = s3c24xx_i2s_set_clkdiv, + .set_sysclk = s3c24xx_i2s_set_sysclk, + }, +}; +EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); + +/* Module information */ +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); +MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.h b/sound/soc/s3c24xx/s3c24xx-i2s.h new file mode 100644 index 000000000000..537b4ecce8a3 --- /dev/null +++ b/sound/soc/s3c24xx/s3c24xx-i2s.h @@ -0,0 +1,37 @@ +/* + * s3c24xx-i2s.c -- ALSA Soc Audio Layer + * + * Copyright 2005 Wolfson Microelectronics PLC. + * Author: Graeme Gregory + * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Revision history + * 10th Nov 2006 Initial version. + */ + +#ifndef S3C24XXI2S_H_ +#define S3C24XXI2S_H_ + +/* clock sources */ +#define S3C24XX_CLKSRC_PCLK 0 +#define S3C24XX_CLKSRC_MPLL 1 + +/* Clock dividers */ +#define S3C24XX_DIV_MCLK 0 +#define S3C24XX_DIV_BCLK 1 +#define S3C24XX_DIV_PRESCALER 2 + +/* prescaler */ +#define S3C24XX_PRESCALE(a,b) \ + (((a - 1) << S3C2410_IISPSR_INTSHIFT) | ((b - 1) << S3C2410_IISPSR_EXTSHFIT)) + +u32 s3c24xx_i2s_get_clockrate(void); + +extern struct snd_soc_cpu_dai s3c24xx_i2s_dai; + +#endif /*S3C24XXI2S_H_*/ diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c new file mode 100644 index 000000000000..21dc6974d6a3 --- /dev/null +++ b/sound/soc/s3c24xx/s3c24xx-pcm.c @@ -0,0 +1,468 @@ +/* + * s3c24xx-pcm.c -- ALSA Soc Audio Layer + * + * (c) 2006 Wolfson Microelectronics PLC. + * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com + * + * (c) 2004-2005 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Revision history + * 11th Dec 2006 Merged with Simtec driver + * 10th Nov 2006 Initial version. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> + +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <asm/dma.h> +#include <asm/io.h> +#include <asm/hardware.h> +#include <asm/arch/dma.h> +#include <asm/arch/audio.h> + +#include "s3c24xx-pcm.h" + +#define S3C24XX_PCM_DEBUG 0 +#if S3C24XX_PCM_DEBUG +#define DBG(x...) printk(KERN_DEBUG x) +#else +#define DBG(x...) +#endif + +static const struct snd_pcm_hardware s3c24xx_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S8, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 128*1024, + .period_bytes_min = PAGE_SIZE, + .period_bytes_max = PAGE_SIZE*2, + .periods_min = 2, + .periods_max = 128, + .fifo_size = 32, +}; + +struct s3c24xx_runtime_data { + spinlock_t lock; + int state; + unsigned int dma_loaded; + unsigned int dma_limit; + unsigned int dma_period; + dma_addr_t dma_start; + dma_addr_t dma_pos; + dma_addr_t dma_end; + struct s3c24xx_pcm_dma_params *params; +}; + +/* s3c24xx_pcm_enqueue + * + * place a dma buffer onto the queue for the dma system + * to handle. +*/ +static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream) +{ + struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; + dma_addr_t pos = prtd->dma_pos; + int ret; + + DBG("Entered %s\n", __FUNCTION__); + + while (prtd->dma_loaded < prtd->dma_limit) { + unsigned long len = prtd->dma_period; + + DBG("dma_loaded: %d\n",prtd->dma_loaded); + + if ((pos + len) > prtd->dma_end) { + len = prtd->dma_end - pos; + DBG(KERN_DEBUG "%s: corrected dma len %ld\n", + __FUNCTION__, len); + } + + ret = s3c2410_dma_enqueue(prtd->params->channel, + substream, pos, len); + + if (ret == 0) { + prtd->dma_loaded++; + pos += prtd->dma_period; + if (pos >= prtd->dma_end) + pos = prtd->dma_start; + } else + break; + } + + prtd->dma_pos = pos; +} + +static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel, + void *dev_id, int size, + enum s3c2410_dma_buffresult result) +{ + struct snd_pcm_substream *substream = dev_id; + struct s3c24xx_runtime_data *prtd; + + DBG("Entered %s\n", __FUNCTION__); + + if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR) + return; + + prtd = substream->runtime->private_data; + + if (substream) + snd_pcm_period_elapsed(substream); + + spin_lock(&prtd->lock); + if (prtd->state & ST_RUNNING) { + prtd->dma_loaded--; + s3c24xx_pcm_enqueue(substream); + } + + spin_unlock(&prtd->lock); +} + +static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct s3c24xx_runtime_data *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct s3c24xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; + unsigned long totbytes = params_buffer_bytes(params); + int ret=0; + + DBG("Entered %s\n", __FUNCTION__); + + /* return if this is a bufferless transfer e.g. + * codec <--> BT codec or GSM modem -- lg FIXME */ + if (!dma) + return 0; + + /* prepare DMA */ + prtd->params = dma; + + DBG("params %p, client %p, channel %d\n", prtd->params, + prtd->params->client, prtd->params->channel); + + ret = s3c2410_dma_request(prtd->params->channel, + prtd->params->client, NULL); + + if (ret) { + DBG(KERN_ERR "failed to get dma channel\n"); + return ret; + } + + /* channel needs configuring for mem=>device, increment memory addr, + * sync to pclk, half-word transfers to the IIS-FIFO. */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + s3c2410_dma_devconfig(prtd->params->channel, + S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC | + S3C2410_DISRCC_APB, prtd->params->dma_addr); + + s3c2410_dma_config(prtd->params->channel, + prtd->params->dma_size, + S3C2410_DCON_SYNC_PCLK | + S3C2410_DCON_HANDSHAKE); + } else { + s3c2410_dma_config(prtd->params->channel, + prtd->params->dma_size, + S3C2410_DCON_HANDSHAKE | + S3C2410_DCON_SYNC_PCLK); + + s3c2410_dma_devconfig(prtd->params->channel, + S3C2410_DMASRC_HW, 0x3, + prtd->params->dma_addr); + } + + s3c2410_dma_set_buffdone_fn(prtd->params->channel, + s3c24xx_audio_buffdone); + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + + runtime->dma_bytes = totbytes; + + spin_lock_irq(&prtd->lock); + prtd->dma_loaded = 0; + prtd->dma_limit = runtime->hw.periods_min; + prtd->dma_period = params_period_bytes(params); + prtd->dma_start = runtime->dma_addr; + prtd->dma_pos = prtd->dma_start; + prtd->dma_end = prtd->dma_start + totbytes; + spin_unlock_irq(&prtd->lock); + + return 0; +} + +static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; + + DBG("Entered %s\n", __FUNCTION__); + + /* TODO - do we need to ensure DMA flushed */ + snd_pcm_set_runtime_buffer(substream, NULL); + + if (prtd->params) { + s3c2410_dma_free(prtd->params->channel, prtd->params->client); + prtd->params = NULL; + } + + return 0; +} + +static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; + int ret = 0; + + DBG("Entered %s\n", __FUNCTION__); + + /* return if this is a bufferless transfer e.g. + * codec <--> BT codec or GSM modem -- lg FIXME */ + if (!prtd->params) + return 0; + + /* flush the DMA channel */ + s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH); + prtd->dma_loaded = 0; + prtd->dma_pos = prtd->dma_start; + + /* enqueue dma buffers */ + s3c24xx_pcm_enqueue(substream); + + return ret; +} + +static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; + int ret = 0; + + DBG("Entered %s\n", __FUNCTION__); + + spin_lock(&prtd->lock); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + prtd->state |= ST_RUNNING; + s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START); + s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STARTED); + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + prtd->state &= ~ST_RUNNING; + s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP); + break; + + default: + ret = -EINVAL; + break; + } + + spin_unlock(&prtd->lock); + + return ret; +} + +static snd_pcm_uframes_t + s3c24xx_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct s3c24xx_runtime_data *prtd = runtime->private_data; + unsigned long res; + dma_addr_t src, dst; + + DBG("Entered %s\n", __FUNCTION__); + + spin_lock(&prtd->lock); + s3c2410_dma_getposition(prtd->params->channel, &src, &dst); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + res = dst - prtd->dma_start; + else + res = src - prtd->dma_start; + + spin_unlock(&prtd->lock); + + DBG("Pointer %x %x\n",src,dst); + + /* we seem to be getting the odd error from the pcm library due + * to out-of-bounds pointers. this is maybe due to the dma engine + * not having loaded the new values for the channel before being + * callled... (todo - fix ) + */ + + if (res >= snd_pcm_lib_buffer_bytes(substream)) { + if (res == snd_pcm_lib_buffer_bytes(substream)) + res = 0; + } + + return bytes_to_frames(substream->runtime, res); +} + +static int s3c24xx_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct s3c24xx_runtime_data *prtd; + + DBG("Entered %s\n", __FUNCTION__); + + snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware); + + prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL); + if (prtd == NULL) + return -ENOMEM; + + runtime->private_data = prtd; + return 0; +} + +static int s3c24xx_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct s3c24xx_runtime_data *prtd = runtime->private_data; + + DBG("Entered %s\n", __FUNCTION__); + + if (prtd) + kfree(prtd); + else + DBG("s3c24xx_pcm_close called with prtd == NULL\n"); + + return 0; +} + +static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + DBG("Entered %s\n", __FUNCTION__); + + return dma_mmap_writecombine(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); +} + +static struct snd_pcm_ops s3c24xx_pcm_ops = { + .open = s3c24xx_pcm_open, + .close = s3c24xx_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = s3c24xx_pcm_hw_params, + .hw_free = s3c24xx_pcm_hw_free, + .prepare = s3c24xx_pcm_prepare, + .trigger = s3c24xx_pcm_trigger, + .pointer = s3c24xx_pcm_pointer, + .mmap = s3c24xx_pcm_mmap, +}; + +static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = s3c24xx_pcm_hardware.buffer_bytes_max; + + DBG("Entered %s\n", __FUNCTION__); + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + buf->bytes = size; + return 0; +} + +static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + DBG("Entered %s\n", __FUNCTION__); + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + + dma_free_writecombine(pcm->card->dev, buf->bytes, + buf->area, buf->addr); + buf->area = NULL; + } +} + +static u64 s3c24xx_pcm_dmamask = DMA_32BIT_MASK; + +static int s3c24xx_pcm_new(struct snd_card *card, + struct snd_soc_codec_dai *dai, struct snd_pcm *pcm) +{ + int ret = 0; + + DBG("Entered %s\n", __FUNCTION__); + + if (!card->dev->dma_mask) + card->dev->dma_mask = &s3c24xx_pcm_dmamask; + if (!card->dev->coherent_dma_mask) + card->dev->coherent_dma_mask = 0xffffffff; + + if (dai->playback.channels_min) { + ret = s3c24xx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK); + if (ret) + goto out; + } + + if (dai->capture.channels_min) { + ret = s3c24xx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE); + if (ret) + goto out; + } + out: + return ret; +} + +struct snd_soc_platform s3c24xx_soc_platform = { + .name = "s3c24xx-audio", + .pcm_ops = &s3c24xx_pcm_ops, + .pcm_new = s3c24xx_pcm_new, + .pcm_free = s3c24xx_pcm_free_dma_buffers, +}; + +EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); + +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); +MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.h b/sound/soc/s3c24xx/s3c24xx-pcm.h new file mode 100644 index 000000000000..0088c79822ea --- /dev/null +++ b/sound/soc/s3c24xx/s3c24xx-pcm.h @@ -0,0 +1,31 @@ +/* + * s3c24xx-pcm.h -- + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * ALSA PCM interface for the Samsung S3C24xx CPU + */ + +#ifndef _S3C24XX_PCM_H +#define _S3C24XX_PCM_H + +#define ST_RUNNING (1<<0) +#define ST_OPENED (1<<1) + +struct s3c24xx_pcm_dma_params { + struct s3c2410_dma_client *client; /* stream identifier */ + int channel; /* Channel ID */ + dma_addr_t dma_addr; + int dma_size; /* Size of the DMA transfer */ +}; + +#define S3C24XX_DAI_I2S 0 + +/* platform data */ +extern struct snd_soc_platform s3c24xx_soc_platform; +extern struct snd_ac97_bus_ops s3c24xx_ac97_ops; + +#endif diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7caf8c7b0ac5..96bce55572a0 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -882,13 +882,15 @@ int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink, if (wsink->id == snd_soc_dapm_input) { if (wsource->id == snd_soc_dapm_micbias || wsource->id == snd_soc_dapm_mic || - wsink->id == snd_soc_dapm_line) + wsink->id == snd_soc_dapm_line || + wsink->id == snd_soc_dapm_output) wsink->ext = 1; } if (wsource->id == snd_soc_dapm_output) { if (wsink->id == snd_soc_dapm_spk || wsink->id == snd_soc_dapm_hp || - wsink->id == snd_soc_dapm_line) + wsink->id == snd_soc_dapm_line || + wsink->id == snd_soc_dapm_input) wsource->ext = 1; } diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 900a00de35fd..dca0344cc1bc 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -661,11 +661,9 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, int cmd) { unsigned int what = 0; struct snd_pcm_substream *s; - struct list_head *pos; unsigned long flags; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == chip->playback_substream) { what |= CS4231_PLAYBACK_ENABLE; snd_pcm_trigger_done(s, substream); diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index f05d02f5b69f..315360f31278 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -29,5 +29,33 @@ config SND_USB_USX2Y To compile this driver as a module, choose M here: the module will be called snd-usb-usx2y. +config SND_USB_CAIAQ + tristate "Native Instruments USB audio devices" + depends on SND && USB + select SND_HWDEP + select SND_RAWMIDI + select SND_PCM + help + Say Y here to include support for caiaq USB audio interfaces, + namely: + + * Native Instruments RigKontrol2 + * Native Instruments Kore Controller + * Native Instruments Audio Kontrol 1 + * Native Instruments Audio 8 DJ + + To compile this driver as a module, choose M here: the module + will be called snd-usb-caiaq. + +config SND_USB_CAIAQ_INPUT + bool "enable input device for controllers" + depends on SND_USB_CAIAQ + help + Say Y here to support input controllers like buttons, knobs, + alpha dials and analog pedals on the following products: + + * Native Instruments RigKontrol2 + * Native Instruments Audio Kontrol 1 + endmenu diff --git a/sound/usb/Makefile b/sound/usb/Makefile index 2c1dc11a72e2..aa252ef2ebfb 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -9,4 +9,4 @@ snd-usb-lib-objs := usbmidi.o obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o -obj-$(CONFIG_SND) += usx2y/ +obj-$(CONFIG_SND) += usx2y/ caiaq/ diff --git a/sound/usb/caiaq/Makefile b/sound/usb/caiaq/Makefile new file mode 100644 index 000000000000..455c8c58a1bd --- /dev/null +++ b/sound/usb/caiaq/Makefile @@ -0,0 +1,3 @@ +snd-usb-caiaq-objs := caiaq-device.o caiaq-audio.o caiaq-midi.o caiaq-input.o + +obj-$(CONFIG_SND_USB_CAIAQ) += snd-usb-caiaq.o diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c new file mode 100644 index 000000000000..0414d766ba07 --- /dev/null +++ b/sound/usb/caiaq/caiaq-audio.c @@ -0,0 +1,707 @@ +/* + * Copyright (c) 2006,2007 Daniel Mack, Karsten Wiese + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <sound/driver.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/interrupt.h> +#include <linux/usb.h> +#include <linux/spinlock.h> +#include <sound/core.h> +#include <sound/initval.h> +#include <sound/pcm.h> +#include <sound/rawmidi.h> +#ifdef CONFIG_SND_USB_CAIAQ_INPUT +#include <linux/input.h> +#endif + +#include "caiaq-device.h" +#include "caiaq-audio.h" + +#define N_URBS 32 +#define CLOCK_DRIFT_TOLERANCE 5 +#define FRAMES_PER_URB 8 +#define BYTES_PER_FRAME 512 +#define CHANNELS_PER_STREAM 2 +#define BYTES_PER_SAMPLE 3 +#define BYTES_PER_SAMPLE_USB 4 +#define MAX_BUFFER_SIZE (128*1024) + +#define ENDPOINT_CAPTURE 2 +#define ENDPOINT_PLAYBACK 6 + +#define MAKE_CHECKBYTE(dev,stream,i) \ + (stream << 1) | (~(i / (dev->n_streams * BYTES_PER_SAMPLE_USB)) & 1) + +static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER), + .formats = SNDRV_PCM_FMTBIT_S24_3BE, + .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000), + .rate_min = 44100, + .rate_max = 0, /* will overwrite later */ + .channels_min = CHANNELS_PER_STREAM, + .channels_max = CHANNELS_PER_STREAM, + .buffer_bytes_max = MAX_BUFFER_SIZE, + .period_bytes_min = 4096, + .period_bytes_max = MAX_BUFFER_SIZE, + .periods_min = 1, + .periods_max = 1024, +}; + +static void +activate_substream(struct snd_usb_caiaqdev *dev, + struct snd_pcm_substream *sub) +{ + if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) + dev->sub_playback[sub->number] = sub; + else + dev->sub_capture[sub->number] = sub; +} + +static void +deactivate_substream(struct snd_usb_caiaqdev *dev, + struct snd_pcm_substream *sub) +{ + if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) + dev->sub_playback[sub->number] = NULL; + else + dev->sub_capture[sub->number] = NULL; +} + +static int +all_substreams_zero(struct snd_pcm_substream **subs) +{ + int i; + for (i = 0; i < MAX_STREAMS; i++) + if (subs[i] != NULL) + return 0; + return 1; +} + +static int stream_start(struct snd_usb_caiaqdev *dev) +{ + int i, ret; + + debug("stream_start(%p)\n", dev); + spin_lock_irq(&dev->spinlock); + if (dev->streaming) { + spin_unlock_irq(&dev->spinlock); + return -EINVAL; + } + + dev->input_panic = 0; + dev->output_panic = 0; + dev->first_packet = 1; + dev->streaming = 1; + + for (i = 0; i < N_URBS; i++) { + ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC); + if (ret) { + log("unable to trigger initial read #%d! (ret = %d)\n", + i, ret); + dev->streaming = 0; + spin_unlock_irq(&dev->spinlock); + return -EPIPE; + } + } + + spin_unlock_irq(&dev->spinlock); + return 0; +} + +static void stream_stop(struct snd_usb_caiaqdev *dev) +{ + int i; + + debug("stream_stop(%p)\n", dev); + if (!dev->streaming) + return; + + dev->streaming = 0; + for (i = 0; i < N_URBS; i++) { + usb_unlink_urb(dev->data_urbs_in[i]); + usb_unlink_urb(dev->data_urbs_out[i]); + } +} + +static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) +{ + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); + debug("snd_usb_caiaq_substream_open(%p)\n", substream); + substream->runtime->hw = dev->pcm_info; + snd_pcm_limit_hw_rates(substream->runtime); + return 0; +} + +static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream) +{ + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); + + debug("snd_usb_caiaq_substream_close(%p)\n", substream); + if (all_substreams_zero(dev->sub_playback) && + all_substreams_zero(dev->sub_capture)) { + /* when the last client has stopped streaming, + * all sample rates are allowed again */ + stream_stop(dev); + dev->pcm_info.rates = dev->samplerates; + } + + return 0; +} + +static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub, + struct snd_pcm_hw_params *hw_params) +{ + debug("snd_usb_caiaq_pcm_hw_params(%p)\n", sub); + return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params)); +} + +static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) +{ + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); + debug("snd_usb_caiaq_pcm_hw_free(%p)\n", sub); + spin_lock_irq(&dev->spinlock); + deactivate_substream(dev, sub); + spin_unlock_irq(&dev->spinlock); + return snd_pcm_lib_free_pages(sub); +} + +/* this should probably go upstream */ +#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 +#error "Change this table" +#endif + +static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, + 48000, 64000, 88200, 96000, 176400, 192000 }; + +static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) +{ + int bytes_per_sample, bpp, ret, i; + int index = substream->number; + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + + debug("snd_usb_caiaq_pcm_prepare(%p)\n", substream); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1; + else + dev->audio_in_buf_pos[index] = 0; + + if (dev->streaming) + return 0; + + /* the first client that opens a stream defines the sample rate + * setting for all subsequent calls, until the last client closed. */ + for (i=0; i < ARRAY_SIZE(rates); i++) + if (runtime->rate == rates[i]) + dev->pcm_info.rates = 1 << i; + + snd_pcm_limit_hw_rates(runtime); + + bytes_per_sample = BYTES_PER_SAMPLE; + if (dev->spec.data_alignment == 2) + bytes_per_sample++; + + bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE) + * bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams; + + ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate, + runtime->sample_bits, bpp); + if (ret) + return ret; + + ret = stream_start(dev); + if (ret) + return ret; + + dev->output_running = 0; + wait_event_timeout(dev->prepare_wait_queue, dev->output_running, HZ); + if (!dev->output_running) { + stream_stop(dev); + return -EPIPE; + } + + return 0; +} + +static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd) +{ + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + spin_lock(&dev->spinlock); + activate_substream(dev, sub); + spin_unlock(&dev->spinlock); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + spin_lock(&dev->spinlock); + deactivate_substream(dev, sub); + spin_unlock(&dev->spinlock); + break; + default: + return -EINVAL; + } + + return 0; +} + +static snd_pcm_uframes_t +snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) +{ + int index = sub->number; + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); + + if (dev->input_panic || dev->output_panic) + return SNDRV_PCM_POS_XRUN; + + if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) + return bytes_to_frames(sub->runtime, + dev->audio_out_buf_pos[index]); + else + return bytes_to_frames(sub->runtime, + dev->audio_in_buf_pos[index]); +} + +/* operators for both playback and capture */ +static struct snd_pcm_ops snd_usb_caiaq_ops = { + .open = snd_usb_caiaq_substream_open, + .close = snd_usb_caiaq_substream_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_usb_caiaq_pcm_hw_params, + .hw_free = snd_usb_caiaq_pcm_hw_free, + .prepare = snd_usb_caiaq_pcm_prepare, + .trigger = snd_usb_caiaq_pcm_trigger, + .pointer = snd_usb_caiaq_pcm_pointer +}; + +static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev, + struct snd_pcm_substream **subs) +{ + int stream, pb, *cnt; + struct snd_pcm_substream *sub; + + for (stream = 0; stream < dev->n_streams; stream++) { + sub = subs[stream]; + if (!sub) + continue; + + pb = frames_to_bytes(sub->runtime, + sub->runtime->period_size); + cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + &dev->period_out_count[stream] : + &dev->period_in_count[stream]; + + if (*cnt >= pb) { + snd_pcm_period_elapsed(sub); + *cnt %= pb; + } + } +} + +static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev, + const struct urb *urb, + const struct usb_iso_packet_descriptor *iso) +{ + unsigned char *usb_buf = urb->transfer_buffer + iso->offset; + struct snd_pcm_substream *sub; + int stream, i; + + if (all_substreams_zero(dev->sub_capture)) + return; + + spin_lock(&dev->spinlock); + + for (i = 0; i < iso->actual_length;) { + for (stream = 0; stream < dev->n_streams; stream++, i++) { + sub = dev->sub_capture[stream]; + if (sub) { + struct snd_pcm_runtime *rt = sub->runtime; + char *audio_buf = rt->dma_area; + int sz = frames_to_bytes(rt, rt->buffer_size); + audio_buf[dev->audio_in_buf_pos[stream]++] + = usb_buf[i]; + dev->period_in_count[stream]++; + if (dev->audio_in_buf_pos[stream] == sz) + dev->audio_in_buf_pos[stream] = 0; + } + } + } + + spin_unlock(&dev->spinlock); +} + +static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev, + const struct urb *urb, + const struct usb_iso_packet_descriptor *iso) +{ + unsigned char *usb_buf = urb->transfer_buffer + iso->offset; + unsigned char check_byte; + struct snd_pcm_substream *sub; + int stream, i; + + spin_lock(&dev->spinlock); + + for (i = 0; i < iso->actual_length;) { + if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) { + for (stream = 0; + stream < dev->n_streams; + stream++, i++) { + if (dev->first_packet) + continue; + + check_byte = MAKE_CHECKBYTE(dev, stream, i); + + if ((usb_buf[i] & 0x3f) != check_byte) + dev->input_panic = 1; + + if (usb_buf[i] & 0x80) + dev->output_panic = 1; + } + } + dev->first_packet = 0; + + for (stream = 0; stream < dev->n_streams; stream++, i++) { + sub = dev->sub_capture[stream]; + if (sub) { + struct snd_pcm_runtime *rt = sub->runtime; + char *audio_buf = rt->dma_area; + int sz = frames_to_bytes(rt, rt->buffer_size); + audio_buf[dev->audio_in_buf_pos[stream]++] = + usb_buf[i]; + dev->period_in_count[stream]++; + if (dev->audio_in_buf_pos[stream] == sz) + dev->audio_in_buf_pos[stream] = 0; + } + } + } + + spin_unlock(&dev->spinlock); +} + +static void read_in_urb(struct snd_usb_caiaqdev *dev, + const struct urb *urb, + const struct usb_iso_packet_descriptor *iso) +{ + if (!dev->streaming) + return; + + switch (dev->spec.data_alignment) { + case 0: + read_in_urb_mode0(dev, urb, iso); + break; + case 2: + read_in_urb_mode2(dev, urb, iso); + break; + } + + if (dev->input_panic || dev->output_panic) { + debug("streaming error detected %s %s\n", + dev->input_panic ? "(input)" : "", + dev->output_panic ? "(output)" : ""); + } + + check_for_elapsed_periods(dev, dev->sub_capture); +} + +static void fill_out_urb(struct snd_usb_caiaqdev *dev, + struct urb *urb, + const struct usb_iso_packet_descriptor *iso) +{ + unsigned char *usb_buf = urb->transfer_buffer + iso->offset; + struct snd_pcm_substream *sub; + int stream, i; + + spin_lock(&dev->spinlock); + + for (i = 0; i < iso->length;) { + for (stream = 0; stream < dev->n_streams; stream++, i++) { + sub = dev->sub_playback[stream]; + if (sub) { + struct snd_pcm_runtime *rt = sub->runtime; + char *audio_buf = rt->dma_area; + int sz = frames_to_bytes(rt, rt->buffer_size); + usb_buf[i] = + audio_buf[dev->audio_out_buf_pos[stream]]; + dev->period_out_count[stream]++; + dev->audio_out_buf_pos[stream]++; + if (dev->audio_out_buf_pos[stream] == sz) + dev->audio_out_buf_pos[stream] = 0; + } else + usb_buf[i] = 0; + } + + /* fill in the check bytes */ + if (dev->spec.data_alignment == 2 && + i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == + (dev->n_streams * CHANNELS_PER_STREAM)) + for (stream = 0; stream < dev->n_streams; stream++, i++) + usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i); + } + + spin_unlock(&dev->spinlock); + check_for_elapsed_periods(dev, dev->sub_playback); +} + +static void read_completed(struct urb *urb) +{ + struct snd_usb_caiaq_cb_info *info = urb->context; + struct snd_usb_caiaqdev *dev; + struct urb *out; + int frame, len, send_it = 0, outframe = 0; + + if (urb->status || !info) + return; + + dev = info->dev; + if (!dev->streaming) + return; + + out = dev->data_urbs_out[info->index]; + + /* read the recently received packet and send back one which has + * the same layout */ + for (frame = 0; frame < FRAMES_PER_URB; frame++) { + if (urb->iso_frame_desc[frame].status) + continue; + + len = urb->iso_frame_desc[outframe].actual_length; + out->iso_frame_desc[outframe].length = len; + out->iso_frame_desc[outframe].actual_length = 0; + out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame; + + if (len > 0) { + fill_out_urb(dev, out, &out->iso_frame_desc[outframe]); + read_in_urb(dev, urb, &urb->iso_frame_desc[frame]); + send_it = 1; + } + + outframe++; + } + + if (send_it) { + out->number_of_packets = FRAMES_PER_URB; + out->transfer_flags = URB_ISO_ASAP; + usb_submit_urb(out, GFP_ATOMIC); + } + + /* re-submit inbound urb */ + for (frame = 0; frame < FRAMES_PER_URB; frame++) { + urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; + urb->iso_frame_desc[frame].length = BYTES_PER_FRAME; + urb->iso_frame_desc[frame].actual_length = 0; + } + + urb->number_of_packets = FRAMES_PER_URB; + urb->transfer_flags = URB_ISO_ASAP; + usb_submit_urb(urb, GFP_ATOMIC); +} + +static void write_completed(struct urb *urb) +{ + struct snd_usb_caiaq_cb_info *info = urb->context; + struct snd_usb_caiaqdev *dev = info->dev; + + if (!dev->output_running) { + dev->output_running = 1; + wake_up(&dev->prepare_wait_queue); + } +} + +static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret) +{ + int i, frame; + struct urb **urbs; + struct usb_device *usb_dev = dev->chip.dev; + unsigned int pipe; + + pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ? + usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) : + usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE); + + urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL); + if (!urbs) { + log("unable to kmalloc() urbs, OOM!?\n"); + *ret = -ENOMEM; + return NULL; + } + + for (i = 0; i < N_URBS; i++) { + urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL); + if (!urbs[i]) { + log("unable to usb_alloc_urb(), OOM!?\n"); + *ret = -ENOMEM; + return urbs; + } + + urbs[i]->transfer_buffer = + kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL); + if (!urbs[i]->transfer_buffer) { + log("unable to kmalloc() transfer buffer, OOM!?\n"); + *ret = -ENOMEM; + return urbs; + } + + for (frame = 0; frame < FRAMES_PER_URB; frame++) { + struct usb_iso_packet_descriptor *iso = + &urbs[i]->iso_frame_desc[frame]; + + iso->offset = BYTES_PER_FRAME * frame; + iso->length = BYTES_PER_FRAME; + } + + urbs[i]->dev = usb_dev; + urbs[i]->pipe = pipe; + urbs[i]->transfer_buffer_length = FRAMES_PER_URB + * BYTES_PER_FRAME; + urbs[i]->context = &dev->data_cb_info[i]; + urbs[i]->interval = 1; + urbs[i]->transfer_flags = URB_ISO_ASAP; + urbs[i]->number_of_packets = FRAMES_PER_URB; + urbs[i]->complete = (dir == SNDRV_PCM_STREAM_CAPTURE) ? + read_completed : write_completed; + } + + *ret = 0; + return urbs; +} + +static void free_urbs(struct urb **urbs) +{ + int i; + + if (!urbs) + return; + + for (i = 0; i < N_URBS; i++) { + if (!urbs[i]) + continue; + + usb_kill_urb(urbs[i]); + kfree(urbs[i]->transfer_buffer); + usb_free_urb(urbs[i]); + } + + kfree(urbs); +} + +int __devinit snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) +{ + int i, ret; + + dev->n_audio_in = max(dev->spec.num_analog_audio_in, + dev->spec.num_digital_audio_in) / + CHANNELS_PER_STREAM; + dev->n_audio_out = max(dev->spec.num_analog_audio_out, + dev->spec.num_digital_audio_out) / + CHANNELS_PER_STREAM; + dev->n_streams = max(dev->n_audio_in, dev->n_audio_out); + + debug("dev->n_audio_in = %d\n", dev->n_audio_in); + debug("dev->n_audio_out = %d\n", dev->n_audio_out); + debug("dev->n_streams = %d\n", dev->n_streams); + + if (dev->n_streams > MAX_STREAMS) { + log("unable to initialize device, too many streams.\n"); + return -EINVAL; + } + + ret = snd_pcm_new(dev->chip.card, dev->product_name, 0, + dev->n_audio_out, dev->n_audio_in, &dev->pcm); + + if (ret < 0) { + log("snd_pcm_new() returned %d\n", ret); + return ret; + } + + dev->pcm->private_data = dev; + strcpy(dev->pcm->name, dev->product_name); + + memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); + memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); + + memcpy(&dev->pcm_info, &snd_usb_caiaq_pcm_hardware, + sizeof(snd_usb_caiaq_pcm_hardware)); + + /* setup samplerates */ + dev->samplerates = dev->pcm_info.rates; + switch (dev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): + dev->samplerates |= SNDRV_PCM_RATE_88200; + dev->samplerates |= SNDRV_PCM_RATE_192000; + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): + dev->samplerates |= SNDRV_PCM_RATE_88200; + break; + } + + snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_usb_caiaq_ops); + snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_usb_caiaq_ops); + + snd_pcm_lib_preallocate_pages_for_all(dev->pcm, + SNDRV_DMA_TYPE_CONTINUOUS, + snd_dma_continuous_data(GFP_KERNEL), + MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); + + dev->data_cb_info = + kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, + GFP_KERNEL); + + if (!dev->data_cb_info) + return -ENOMEM; + + for (i = 0; i < N_URBS; i++) { + dev->data_cb_info[i].dev = dev; + dev->data_cb_info[i].index = i; + } + + dev->data_urbs_in = alloc_urbs(dev, SNDRV_PCM_STREAM_CAPTURE, &ret); + if (ret < 0) { + kfree(dev->data_cb_info); + free_urbs(dev->data_urbs_in); + return ret; + } + + dev->data_urbs_out = alloc_urbs(dev, SNDRV_PCM_STREAM_PLAYBACK, &ret); + if (ret < 0) { + kfree(dev->data_cb_info); + free_urbs(dev->data_urbs_in); + free_urbs(dev->data_urbs_out); + return ret; + } + + return 0; +} + +void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev) +{ + debug("snd_usb_caiaq_audio_free (%p)\n", dev); + stream_stop(dev); + free_urbs(dev->data_urbs_in); + free_urbs(dev->data_urbs_out); + kfree(dev->data_cb_info); +} + diff --git a/sound/usb/caiaq/caiaq-audio.h b/sound/usb/caiaq/caiaq-audio.h new file mode 100644 index 000000000000..8ab1f8d9529e --- /dev/null +++ b/sound/usb/caiaq/caiaq-audio.h @@ -0,0 +1,7 @@ +#ifndef CAIAQ_AUDIO_H +#define CAIAQ_AUDIO_H + +int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev); +void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev); + +#endif /* CAIAQ_AUDIO_H */ diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c new file mode 100644 index 000000000000..4709347326f9 --- /dev/null +++ b/sound/usb/caiaq/caiaq-device.c @@ -0,0 +1,436 @@ +/* + * caiaq.c: ALSA driver for caiaq/NativeInstruments devices + * + * Copyright (c) 2007 Daniel Mack <daniel@caiaq.de> + * Karsten Wiese <fzu@wemgehoertderstaat.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/interrupt.h> +#include <linux/usb.h> +#include <linux/input.h> +#include <linux/spinlock.h> +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/initval.h> +#include <sound/pcm.h> +#include <sound/rawmidi.h> + +#include "caiaq-device.h" +#include "caiaq-audio.h" +#include "caiaq-midi.h" + +#ifdef CONFIG_SND_USB_CAIAQ_INPUT +#include "caiaq-input.h" +#endif + +MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); +MODULE_DESCRIPTION("caiaq USB audio, version 1.1.0"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," + "{Native Instruments, Kore Controller}," + "{Native Instruments, Audio Kontrol 1}" + "{Native Instruments, Audio 8 DJ}}"); + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ +static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ +static int snd_card_used[SNDRV_CARDS]; + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for the caiaq sound device"); +module_param_array(id, charp, NULL, 0444); +MODULE_PARM_DESC(id, "ID string for the caiaq soundcard."); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable the caiaq soundcard."); + +enum { + SAMPLERATE_44100 = 0, + SAMPLERATE_48000 = 1, + SAMPLERATE_96000 = 2, + SAMPLERATE_192000 = 3, + SAMPLERATE_88200 = 4, + SAMPLERATE_INVALID = 0xff +}; + +enum { + DEPTH_NONE = 0, + DEPTH_16 = 1, + DEPTH_24 = 2, + DEPTH_32 = 3 +}; + +static struct usb_device_id snd_usb_id_table[] = { + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_RIGKONTROL2 + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_KORECONTROLLER + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_AK1 + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_AUDIO8DJ + }, + { /* terminator */ } +}; + +static void usb_ep1_command_reply_dispatch (struct urb* urb) +{ + int ret; + struct snd_usb_caiaqdev *dev = urb->context; + unsigned char *buf = urb->transfer_buffer; + + if (urb->status || !dev) { + log("received EP1 urb->status = %i\n", urb->status); + return; + } + + switch(buf[0]) { + case EP1_CMD_GET_DEVICE_INFO: + memcpy(&dev->spec, buf+1, sizeof(struct caiaq_device_spec)); + dev->spec.fw_version = le16_to_cpu(dev->spec.fw_version); + debug("device spec (firmware %d): audio: %d in, %d out, " + "MIDI: %d in, %d out, data alignment %d\n", + dev->spec.fw_version, + dev->spec.num_analog_audio_in, + dev->spec.num_analog_audio_out, + dev->spec.num_midi_in, + dev->spec.num_midi_out, + dev->spec.data_alignment); + + dev->spec_received++; + wake_up(&dev->ep1_wait_queue); + break; + case EP1_CMD_AUDIO_PARAMS: + dev->audio_parm_answer = buf[1]; + wake_up(&dev->ep1_wait_queue); + break; + case EP1_CMD_MIDI_READ: + snd_usb_caiaq_midi_handle_input(dev, buf[1], buf + 3, buf[2]); + break; + +#ifdef CONFIG_SND_USB_CAIAQ_INPUT + case EP1_CMD_READ_ERP: + case EP1_CMD_READ_ANALOG: + case EP1_CMD_READ_IO: + snd_usb_caiaq_input_dispatch(dev, buf, urb->actual_length); + break; +#endif + } + + dev->ep1_in_urb.actual_length = 0; + ret = usb_submit_urb(&dev->ep1_in_urb, GFP_ATOMIC); + if (ret < 0) + log("unable to submit urb. OOM!?\n"); +} + +static int send_command (struct snd_usb_caiaqdev *dev, + unsigned char command, + const unsigned char *buffer, + int len) +{ + int actual_len; + struct usb_device *usb_dev = dev->chip.dev; + + if (!usb_dev) + return -EIO; + + if (len > EP1_BUFSIZE - 1) + len = EP1_BUFSIZE - 1; + + if (buffer && len > 0) + memcpy(dev->ep1_out_buf+1, buffer, len); + + dev->ep1_out_buf[0] = command; + return usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, 1), + dev->ep1_out_buf, len+1, &actual_len, 200); +} + +int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, + int rate, int depth, int bpp) +{ + int ret; + char tmp[5]; + + switch (rate) { + case 44100: tmp[0] = SAMPLERATE_44100; break; + case 48000: tmp[0] = SAMPLERATE_48000; break; + case 88200: tmp[0] = SAMPLERATE_88200; break; + case 96000: tmp[0] = SAMPLERATE_96000; break; + case 192000: tmp[0] = SAMPLERATE_192000; break; + default: return -EINVAL; + } + + switch (depth) { + case 16: tmp[1] = DEPTH_16; break; + case 24: tmp[1] = DEPTH_24; break; + default: return -EINVAL; + } + + tmp[2] = bpp & 0xff; + tmp[3] = bpp >> 8; + tmp[4] = 1; /* packets per microframe */ + + debug("setting audio params: %d Hz, %d bits, %d bpp\n", + rate, depth, bpp); + + dev->audio_parm_answer = -1; + ret = send_command(dev, EP1_CMD_AUDIO_PARAMS, tmp, sizeof(tmp)); + + if (ret) + return ret; + + if (!wait_event_timeout(dev->ep1_wait_queue, + dev->audio_parm_answer >= 0, HZ)) + return -EPIPE; + + if (dev->audio_parm_answer != 1) + debug("unable to set the device's audio params\n"); + + return dev->audio_parm_answer == 1 ? 0 : -EINVAL; +} + +int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, + int digital, int analog, int erp) +{ + char tmp[3] = { digital, analog, erp }; + return send_command(dev, EP1_CMD_AUTO_MSG, tmp, sizeof(tmp)); +} + +static void setup_card(struct snd_usb_caiaqdev *dev) +{ + int ret; + char val[3]; + + /* device-specific startup specials */ + switch (dev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): + /* RigKontrol2 - display centered dash ('-') */ + val[0] = 0x00; + val[1] = 0x00; + val[2] = 0x01; + send_command(dev, EP1_CMD_WRITE_IO, val, 3); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): + /* Audio Kontrol 1 - make USB-LED stop blinking */ + val[0] = 0x00; + send_command(dev, EP1_CMD_WRITE_IO, val, 1); + break; + } + + ret = snd_usb_caiaq_audio_init(dev); + if (ret < 0) + log("Unable to set up audio system (ret=%d)\n", ret); + + ret = snd_usb_caiaq_midi_init(dev); + if (ret < 0) + log("Unable to set up MIDI system (ret=%d)\n", ret); + +#ifdef CONFIG_SND_USB_CAIAQ_INPUT + ret = snd_usb_caiaq_input_init(dev); + if (ret < 0) + log("Unable to set up input system (ret=%d)\n", ret); +#endif + + /* finally, register the card and all its sub-instances */ + ret = snd_card_register(dev->chip.card); + if (ret < 0) { + log("snd_card_register() returned %d\n", ret); + snd_card_free(dev->chip.card); + } +} + +static struct snd_card* create_card(struct usb_device* usb_dev) +{ + int devnum; + struct snd_card *card; + struct snd_usb_caiaqdev *dev; + + for (devnum = 0; devnum < SNDRV_CARDS; devnum++) + if (enable[devnum] && !snd_card_used[devnum]) + break; + + if (devnum >= SNDRV_CARDS) + return NULL; + + card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, + sizeof(struct snd_usb_caiaqdev)); + if (!card) + return NULL; + + dev = caiaqdev(card); + dev->chip.dev = usb_dev; + dev->chip.card = card; + dev->chip.usb_id = USB_ID(usb_dev->descriptor.idVendor, + usb_dev->descriptor.idProduct); + spin_lock_init(&dev->spinlock); + snd_card_set_dev(card, &usb_dev->dev); + + return card; +} + +static int init_card(struct snd_usb_caiaqdev *dev) +{ + char *c; + struct usb_device *usb_dev = dev->chip.dev; + struct snd_card *card = dev->chip.card; + int err, len; + + if (usb_set_interface(usb_dev, 0, 1) != 0) { + log("can't set alt interface.\n"); + return -EIO; + } + + usb_init_urb(&dev->ep1_in_urb); + usb_init_urb(&dev->midi_out_urb); + + usb_fill_bulk_urb(&dev->ep1_in_urb, usb_dev, + usb_rcvbulkpipe(usb_dev, 0x1), + dev->ep1_in_buf, EP1_BUFSIZE, + usb_ep1_command_reply_dispatch, dev); + + usb_fill_bulk_urb(&dev->midi_out_urb, usb_dev, + usb_sndbulkpipe(usb_dev, 0x1), + dev->midi_out_buf, EP1_BUFSIZE, + snd_usb_caiaq_midi_output_done, dev); + + init_waitqueue_head(&dev->ep1_wait_queue); + init_waitqueue_head(&dev->prepare_wait_queue); + + if (usb_submit_urb(&dev->ep1_in_urb, GFP_KERNEL) != 0) + return -EIO; + + err = send_command(dev, EP1_CMD_GET_DEVICE_INFO, NULL, 0); + if (err) + return err; + + if (!wait_event_timeout(dev->ep1_wait_queue, dev->spec_received, HZ)) + return -ENODEV; + + usb_string(usb_dev, usb_dev->descriptor.iManufacturer, + dev->vendor_name, CAIAQ_USB_STR_LEN); + + usb_string(usb_dev, usb_dev->descriptor.iProduct, + dev->product_name, CAIAQ_USB_STR_LEN); + + usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, + dev->serial, CAIAQ_USB_STR_LEN); + + /* terminate serial string at first white space occurence */ + c = strchr(dev->serial, ' '); + if (c) + *c = '\0'; + + strcpy(card->driver, MODNAME); + strcpy(card->shortname, dev->product_name); + + len = snprintf(card->longname, sizeof(card->longname), + "%s %s (serial %s, ", + dev->vendor_name, dev->product_name, dev->serial); + + if (len < sizeof(card->longname) - 2) + len += usb_make_path(usb_dev, card->longname + len, + sizeof(card->longname) - len); + + card->longname[len++] = ')'; + card->longname[len] = '\0'; + setup_card(dev); + return 0; +} + +static int snd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret; + struct snd_card *card; + struct usb_device *device = interface_to_usbdev(intf); + + card = create_card(device); + + if (!card) + return -ENOMEM; + + dev_set_drvdata(&intf->dev, card); + ret = init_card(caiaqdev(card)); + if (ret < 0) { + log("unable to init card! (ret=%d)\n", ret); + snd_card_free(card); + return ret; + } + + return 0; +} + +static void snd_disconnect(struct usb_interface *intf) +{ + struct snd_usb_caiaqdev *dev; + struct snd_card *card = dev_get_drvdata(&intf->dev); + + debug("snd_disconnect(%p)\n", intf); + + if (!card) + return; + + dev = caiaqdev(card); + snd_card_disconnect(card); + +#ifdef CONFIG_SND_USB_CAIAQ_INPUT + snd_usb_caiaq_input_free(dev); +#endif + snd_usb_caiaq_audio_free(dev); + + usb_kill_urb(&dev->ep1_in_urb); + usb_kill_urb(&dev->midi_out_urb); + + snd_card_free(card); + usb_reset_device(interface_to_usbdev(intf)); +} + + +MODULE_DEVICE_TABLE(usb, snd_usb_id_table); +static struct usb_driver snd_usb_driver = { + .name = MODNAME, + .probe = snd_probe, + .disconnect = snd_disconnect, + .id_table = snd_usb_id_table, +}; + +static int __init snd_module_init(void) +{ + return usb_register(&snd_usb_driver); +} + +static void __exit snd_module_exit(void) +{ + usb_deregister(&snd_usb_driver); +} + +module_init(snd_module_init) +module_exit(snd_module_exit) + diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h new file mode 100644 index 000000000000..088d5ec241f3 --- /dev/null +++ b/sound/usb/caiaq/caiaq-device.h @@ -0,0 +1,116 @@ +#ifndef CAIAQ_DEVICE_H +#define CAIAQ_DEVICE_H + +#include "../usbaudio.h" + +#define USB_VID_NATIVEINSTRUMENTS 0x17cc + +#define USB_PID_RIGKONTROL2 0x1969 +#define USB_PID_KORECONTROLLER 0x4711 +#define USB_PID_AK1 0x0815 +#define USB_PID_AUDIO8DJ 0x1978 + +#define EP1_BUFSIZE 64 +#define CAIAQ_USB_STR_LEN 0xff +#define MAX_STREAMS 32 + +//#define SND_USB_CAIAQ_DEBUG + +#define MODNAME "snd-usb-caiaq" +#define log(x...) snd_printk(KERN_WARNING MODNAME" log: " x) + +#ifdef SND_USB_CAIAQ_DEBUG +#define debug(x...) snd_printk(KERN_WARNING MODNAME " debug: " x) +#else +#define debug(x...) do { } while(0) +#endif + +#define EP1_CMD_GET_DEVICE_INFO 0x1 +#define EP1_CMD_READ_ERP 0x2 +#define EP1_CMD_READ_ANALOG 0x3 +#define EP1_CMD_READ_IO 0x4 +#define EP1_CMD_WRITE_IO 0x5 +#define EP1_CMD_MIDI_READ 0x6 +#define EP1_CMD_MIDI_WRITE 0x7 +#define EP1_CMD_AUDIO_PARAMS 0x9 +#define EP1_CMD_AUTO_MSG 0xb + +struct caiaq_device_spec { + unsigned short fw_version; + unsigned char hw_subtype; + unsigned char num_erp; + unsigned char num_analog_in; + unsigned char num_digital_in; + unsigned char num_digital_out; + unsigned char num_analog_audio_out; + unsigned char num_analog_audio_in; + unsigned char num_digital_audio_out; + unsigned char num_digital_audio_in; + unsigned char num_midi_out; + unsigned char num_midi_in; + unsigned char data_alignment; +} __attribute__ ((packed)); + +struct snd_usb_caiaq_cb_info; + +struct snd_usb_caiaqdev { + struct snd_usb_audio chip; + + struct urb ep1_in_urb; + struct urb midi_out_urb; + struct urb **data_urbs_in; + struct urb **data_urbs_out; + struct snd_usb_caiaq_cb_info *data_cb_info; + + unsigned char ep1_in_buf[EP1_BUFSIZE]; + unsigned char ep1_out_buf[EP1_BUFSIZE]; + unsigned char midi_out_buf[EP1_BUFSIZE]; + + struct caiaq_device_spec spec; + spinlock_t spinlock; + wait_queue_head_t ep1_wait_queue; + wait_queue_head_t prepare_wait_queue; + int spec_received, audio_parm_answer; + + char vendor_name[CAIAQ_USB_STR_LEN]; + char product_name[CAIAQ_USB_STR_LEN]; + char serial[CAIAQ_USB_STR_LEN]; + + int n_streams, n_audio_in, n_audio_out; + int streaming, first_packet, output_running; + int audio_in_buf_pos[MAX_STREAMS]; + int audio_out_buf_pos[MAX_STREAMS]; + int period_in_count[MAX_STREAMS]; + int period_out_count[MAX_STREAMS]; + int input_panic, output_panic; + char *audio_in_buf, *audio_out_buf; + unsigned int samplerates; + + struct snd_pcm_substream *sub_playback[MAX_STREAMS]; + struct snd_pcm_substream *sub_capture[MAX_STREAMS]; + + /* Linux input */ +#ifdef CONFIG_SND_USB_CAIAQ_INPUT + struct input_dev *input_dev; +#endif + + /* ALSA */ + struct snd_pcm *pcm; + struct snd_pcm_hardware pcm_info; + struct snd_rawmidi *rmidi; + struct snd_rawmidi_substream *midi_receive_substream; + struct snd_rawmidi_substream *midi_out_substream; +}; + +struct snd_usb_caiaq_cb_info { + struct snd_usb_caiaqdev *dev; + int index; +}; + +#define caiaqdev(c) ((struct snd_usb_caiaqdev*)(c)->private_data) + +int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, int rate, int depth, int bbp); +int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, int digital, int analog, int erp); + + +#endif /* CAIAQ_DEVICE_H */ diff --git a/sound/usb/caiaq/caiaq-input.c b/sound/usb/caiaq/caiaq-input.c new file mode 100644 index 000000000000..3acd12db6952 --- /dev/null +++ b/sound/usb/caiaq/caiaq-input.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2006,2007 Daniel Mack, Tim Ruetz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/input.h> +#include <linux/usb.h> +#include <linux/spinlock.h> +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/rawmidi.h> +#include <sound/pcm.h> +#include "caiaq-device.h" +#include "caiaq-input.h" + +#ifdef CONFIG_SND_USB_CAIAQ_INPUT + +static unsigned char keycode_ak1[] = { KEY_C, KEY_B, KEY_A }; +static unsigned char keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4, + KEY_5, KEY_6, KEY_7 }; + +#define DEG90 (range/2) +#define DEG180 (range) +#define DEG270 (DEG90 + DEG180) +#define DEG360 (DEG180 * 2) +#define HIGH_PEAK (268) +#define LOW_PEAK (-7) + +/* some of these devices have endless rotation potentiometers + * built in which use two tapers, 90 degrees phase shifted. + * this algorithm decodes them to one single value, ranging + * from 0 to 999 */ +static unsigned int decode_erp(unsigned char a, unsigned char b) +{ + int weight_a, weight_b; + int pos_a, pos_b; + int ret; + int range = HIGH_PEAK - LOW_PEAK; + int mid_value = (HIGH_PEAK + LOW_PEAK) / 2; + + weight_b = abs(mid_value-a) - (range/2 - 100)/2; + + if (weight_b < 0) + weight_b = 0; + + if (weight_b > 100) + weight_b = 100; + + weight_a = 100 - weight_b; + + if (a < mid_value) { + /* 0..90 and 270..360 degrees */ + pos_b = b - LOW_PEAK + DEG270; + if (pos_b >= DEG360) + pos_b -= DEG360; + } else + /* 90..270 degrees */ + pos_b = HIGH_PEAK - b + DEG90; + + + if (b > mid_value) + /* 0..180 degrees */ + pos_a = a - LOW_PEAK; + else + /* 180..360 degrees */ + pos_a = HIGH_PEAK - a + DEG180; + + /* interpolate both slider values, depending on weight factors */ + /* 0..99 x DEG360 */ + ret = pos_a * weight_a + pos_b * weight_b; + + /* normalize to 0..999 */ + ret *= 10; + ret /= DEG360; + + if (ret < 0) + ret += 1000; + + if (ret >= 1000) + ret -= 1000; + + return ret; +} + +#undef DEG90 +#undef DEG180 +#undef DEG270 +#undef DEG360 +#undef HIGH_PEAK +#undef LOW_PEAK + + +static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev, + const char *buf, unsigned int len) +{ + switch(dev->input_dev->id.product) { + case USB_PID_RIGKONTROL2: + input_report_abs(dev->input_dev, ABS_X, (buf[4] << 8) |buf[5]); + input_report_abs(dev->input_dev, ABS_Y, (buf[0] << 8) |buf[1]); + input_report_abs(dev->input_dev, ABS_Z, (buf[2] << 8) |buf[3]); + input_sync(dev->input_dev); + break; + } +} + +static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev, + const char *buf, unsigned int len) +{ + int i; + + switch(dev->input_dev->id.product) { + case USB_PID_AK1: + i = decode_erp(buf[0], buf[1]); + input_report_abs(dev->input_dev, ABS_X, i); + input_sync(dev->input_dev); + break; + } +} + +static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev, + char *buf, unsigned int len) +{ + int i; + unsigned char *keycode = dev->input_dev->keycode; + + if (!keycode) + return; + + if (dev->input_dev->id.product == USB_PID_RIGKONTROL2) + for (i=0; i<len; i++) + buf[i] = ~buf[i]; + + for (i=0; (i<dev->input_dev->keycodemax) && (i < len); i++) + input_report_key(dev->input_dev, keycode[i], + buf[i/8] & (1 << (i%8))); + + input_sync(dev->input_dev); +} + +void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, + char *buf, + unsigned int len) +{ + if (!dev->input_dev || (len < 1)) + return; + + switch (buf[0]) { + case EP1_CMD_READ_ANALOG: + snd_caiaq_input_read_analog(dev, buf+1, len-1); + break; + case EP1_CMD_READ_ERP: + snd_caiaq_input_read_erp(dev, buf+1, len-1); + break; + case EP1_CMD_READ_IO: + snd_caiaq_input_read_io(dev, buf+1, len-1); + break; + } +} + +int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev) +{ + struct usb_device *usb_dev = dev->chip.dev; + struct input_dev *input; + int i, ret; + + input = input_allocate_device(); + if (!input) + return -ENOMEM; + + input->name = dev->product_name; + input->id.bustype = BUS_USB; + input->id.vendor = usb_dev->descriptor.idVendor; + input->id.product = usb_dev->descriptor.idProduct; + input->id.version = usb_dev->descriptor.bcdDevice; + + switch (dev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): + input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_Z); + input->keycode = keycode_rk2; + input->keycodesize = sizeof(char); + input->keycodemax = ARRAY_SIZE(keycode_rk2); + for (i=0; i<ARRAY_SIZE(keycode_rk2); i++) + set_bit(keycode_rk2[i], input->keybit); + + input_set_abs_params(input, ABS_X, 0, 4096, 0, 10); + input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10); + input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10); + snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): + input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input->absbit[0] = BIT(ABS_X); + input->keycode = keycode_ak1; + input->keycodesize = sizeof(char); + input->keycodemax = ARRAY_SIZE(keycode_ak1); + for (i=0; i<ARRAY_SIZE(keycode_ak1); i++) + set_bit(keycode_ak1[i], input->keybit); + + input_set_abs_params(input, ABS_X, 0, 999, 0, 10); + snd_usb_caiaq_set_auto_msg(dev, 1, 0, 5); + break; + default: + /* no input methods supported on this device */ + input_free_device(input); + return 0; + } + + ret = input_register_device(input); + if (ret < 0) { + input_free_device(input); + return ret; + } + + dev->input_dev = input; + return 0; +} + +void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev) +{ + if (!dev || !dev->input_dev) + return; + + input_unregister_device(dev->input_dev); + input_free_device(dev->input_dev); + dev->input_dev = NULL; +} + +#endif /* CONFIG_SND_USB_CAIAQ_INPUT */ + diff --git a/sound/usb/caiaq/caiaq-input.h b/sound/usb/caiaq/caiaq-input.h new file mode 100644 index 000000000000..ced535577864 --- /dev/null +++ b/sound/usb/caiaq/caiaq-input.h @@ -0,0 +1,8 @@ +#ifndef CAIAQ_INPUT_H +#define CAIAQ_INPUT_H + +void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, char *buf, unsigned int len); +int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev); +void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev); + +#endif diff --git a/sound/usb/caiaq/caiaq-midi.c b/sound/usb/caiaq/caiaq-midi.c new file mode 100644 index 000000000000..793ca20ce349 --- /dev/null +++ b/sound/usb/caiaq/caiaq-midi.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2006,2007 Daniel Mack + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/interrupt.h> +#include <linux/usb.h> +#include <linux/input.h> +#include <linux/spinlock.h> +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/rawmidi.h> +#include <sound/pcm.h> + +#include "caiaq-device.h" +#include "caiaq-midi.h" + + +static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) +{ + struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; + + if (!dev) + return; + + dev->midi_receive_substream = up ? substream : NULL; +} + + +static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, + struct snd_rawmidi_substream *substream) +{ + int len, ret; + + dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; + dev->midi_out_buf[1] = 0; /* port */ + len = snd_rawmidi_transmit_peek(substream, dev->midi_out_buf+3, EP1_BUFSIZE-3); + + if (len <= 0) + return; + + dev->midi_out_buf[2] = len; + dev->midi_out_urb.transfer_buffer_length = len+3; + + ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); + if (ret < 0) + log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed, %d\n", + substream, ret); +} + +static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) +{ + struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; + + if (dev->midi_out_substream != NULL) + return; + + if (!up) { + dev->midi_out_substream = NULL; + return; + } + + dev->midi_out_substream = substream; + snd_usb_caiaq_midi_send(dev, substream); +} + + +static struct snd_rawmidi_ops snd_usb_caiaq_midi_output = +{ + .open = snd_usb_caiaq_midi_output_open, + .close = snd_usb_caiaq_midi_output_close, + .trigger = snd_usb_caiaq_midi_output_trigger, +}; + +static struct snd_rawmidi_ops snd_usb_caiaq_midi_input = +{ + .open = snd_usb_caiaq_midi_input_open, + .close = snd_usb_caiaq_midi_input_close, + .trigger = snd_usb_caiaq_midi_input_trigger, +}; + +void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, + int port, const char *buf, int len) +{ + if (!dev->midi_receive_substream) + return; + + snd_rawmidi_receive(dev->midi_receive_substream, buf, len); +} + +int __devinit snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device) +{ + int ret; + struct snd_rawmidi *rmidi; + + ret = snd_rawmidi_new(device->chip.card, device->product_name, 0, + device->spec.num_midi_out, + device->spec.num_midi_in, + &rmidi); + + if (ret < 0) + return ret; + + strcpy(rmidi->name, device->product_name); + + rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX; + rmidi->private_data = device; + + if (device->spec.num_midi_out > 0) { + rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, + &snd_usb_caiaq_midi_output); + } + + if (device->spec.num_midi_in > 0) { + rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, + &snd_usb_caiaq_midi_input); + } + + device->rmidi = rmidi; + + return 0; +} + +void snd_usb_caiaq_midi_output_done(struct urb* urb) +{ + struct snd_usb_caiaqdev *dev = urb->context; + char *buf = urb->transfer_buffer; + + if (urb->status != 0) + return; + + if (!dev->midi_out_substream) + return; + + snd_rawmidi_transmit_ack(dev->midi_out_substream, buf[2]); + dev->midi_out_substream = NULL; + snd_usb_caiaq_midi_send(dev, dev->midi_out_substream); +} + diff --git a/sound/usb/caiaq/caiaq-midi.h b/sound/usb/caiaq/caiaq-midi.h new file mode 100644 index 000000000000..9d16db027fc3 --- /dev/null +++ b/sound/usb/caiaq/caiaq-midi.h @@ -0,0 +1,8 @@ +#ifndef CAIAQ_MIDI_H +#define CAIAQ_MIDI_H + +int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev); +void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len); +void snd_usb_caiaq_midi_output_done(struct urb* urb); + +#endif /* CAIAQ_MIDI_H */ diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index b6d886373bb0..8ebc1adb5ed9 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1878,6 +1878,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre } /* set the period time minimum 1ms */ + /* FIXME: high-speed mode allows 125us minimum period, but many parts + * in the current code assume the 1ms period. + */ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000 * MIN_PACKS_URB, /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX); diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 24f5a26c5f0c..99295f9b7691 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -1,7 +1,7 @@ /* * usbmidi.c - ALSA USB MIDI driver * - * Copyright (c) 2002-2005 Clemens Ladisch + * Copyright (c) 2002-2007 Clemens Ladisch * All rights reserved. * * Based on the OSS usb-midi driver by NAGANO Daisuke, @@ -145,6 +145,7 @@ struct snd_usb_midi_in_endpoint { struct urb* urb; struct usbmidi_in_port { struct snd_rawmidi_substream *substream; + u8 running_status_length; } ports[0x10]; u8 seen_f5; u8 error_resubmit; @@ -366,6 +367,46 @@ static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint* ep, } /* + * Buggy M-Audio device: running status on input results in a packet that has + * the data bytes but not the status byte and that is marked with CIN 4. + */ +static void snd_usbmidi_maudio_broken_running_status_input( + struct snd_usb_midi_in_endpoint* ep, + uint8_t* buffer, int buffer_length) +{ + int i; + + for (i = 0; i + 3 < buffer_length; i += 4) + if (buffer[i] != 0) { + int cable = buffer[i] >> 4; + u8 cin = buffer[i] & 0x0f; + struct usbmidi_in_port *port = &ep->ports[cable]; + int length; + + length = snd_usbmidi_cin_length[cin]; + if (cin == 0xf && buffer[i + 1] >= 0xf8) + ; /* realtime msg: no running status change */ + else if (cin >= 0x8 && cin <= 0xe) + /* channel msg */ + port->running_status_length = length - 1; + else if (cin == 0x4 && + port->running_status_length != 0 && + buffer[i + 1] < 0x80) + /* CIN 4 that is not a SysEx */ + length = port->running_status_length; + else + /* + * All other msgs cannot begin running status. + * (A channel msg sent as two or three CIN 0xF + * packets could in theory, but this device + * doesn't use this format.) + */ + port->running_status_length = 0; + snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length); + } +} + +/* * Adds one USB MIDI packet to the output buffer. */ static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0, @@ -525,6 +566,12 @@ static struct usb_protocol_ops snd_usbmidi_midiman_ops = { .output_packet = snd_usbmidi_output_midiman_packet, }; +static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = { + .input = snd_usbmidi_maudio_broken_running_status_input, + .output = snd_usbmidi_standard_output, + .output_packet = snd_usbmidi_output_standard_packet, +}; + /* * Novation USB MIDI protocol: number of data bytes is in the first byte * (when receiving) (+1!) or in the second byte (when sending); data begins @@ -918,7 +965,11 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, } /* we never use interrupt output pipes */ pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep); - ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1); + if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */ + /* FIXME: we need more URBs to get reasonable bandwidth here: */ + ep->max_transfer = 4; + else + ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1); buffer = usb_buffer_alloc(umidi->chip->dev, ep->max_transfer, GFP_KERNEL, &ep->urb->transfer_dma); if (!buffer) { @@ -1606,6 +1657,9 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip, switch (quirk ? quirk->type : QUIRK_MIDI_STANDARD_INTERFACE) { case QUIRK_MIDI_STANDARD_INTERFACE: err = snd_usbmidi_get_ms_info(umidi, endpoints); + if (chip->usb_id == USB_ID(0x0763, 0x0150)) /* M-Audio Uno */ + umidi->usb_protocol_ops = + &snd_usbmidi_maudio_broken_running_status_ops; break; case QUIRK_MIDI_FIXED_ENDPOINT: memcpy(&endpoints[0], quirk->data, diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 858262068f4f..8fcbe93b2589 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -40,6 +40,29 @@ .bInterfaceClass = USB_CLASS_VENDOR_SPEC /* + * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface + * class matches do not take effect without an explicit ID match. + */ +{ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | + USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_SUBCLASS, + .idVendor = 0x046d, + .idProduct = 0x08f0, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL +}, +{ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | + USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_SUBCLASS, + .idVendor = 0x046d, + .idProduct = 0x08f6, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL +}, + +/* * Yamaha devices */ |