diff --git a/[refs] b/[refs] index a3ec190accd4..fe67ae3d5b87 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: dda415d41882449f841f88d829dd65b6ee1c374c +refs/heads/master: 20dd9e5ed6d65269ebd038fa900b46171a02d956 diff --git a/trunk/CREDITS b/trunk/CREDITS index d8fe12a9421f..2346b09ca8bb 100644 --- a/trunk/CREDITS +++ b/trunk/CREDITS @@ -1823,6 +1823,11 @@ S: Kattreinstr 38 S: D-64295 S: Germany +N: Avi Kivity +E: avi.kivity@gmail.com +D: Kernel-based Virtual Machine (KVM) +S: Ra'annana, Israel + N: Andi Kleen E: andi@firstfloor.org U: http://www.halobates.de diff --git a/trunk/Documentation/devicetree/bindings/net/mdio-gpio.txt b/trunk/Documentation/devicetree/bindings/net/mdio-gpio.txt index bc9549529014..c79bab025369 100644 --- a/trunk/Documentation/devicetree/bindings/net/mdio-gpio.txt +++ b/trunk/Documentation/devicetree/bindings/net/mdio-gpio.txt @@ -8,9 +8,16 @@ gpios property as described in section VIII.1 in the following order: MDC, MDIO. +Note: Each gpio-mdio bus should have an alias correctly numbered in "aliases" +node. + Example: -mdio { +aliases { + mdio-gpio0 = <&mdio0>; +}; + +mdio0: mdio { compatible = "virtual,mdio-gpio"; #address-cells = <1>; #size-cells = <0>; diff --git a/trunk/Documentation/networking/vxlan.txt b/trunk/Documentation/networking/vxlan.txt index 5b34b762d7d5..6d993510f091 100644 --- a/trunk/Documentation/networking/vxlan.txt +++ b/trunk/Documentation/networking/vxlan.txt @@ -32,7 +32,7 @@ no entry is in the forwarding table. # ip link delete vxlan0 3. Show vxlan info - # ip -d show vxlan0 + # ip -d link show vxlan0 It is possible to create, destroy and display the vxlan forwarding table using the new bridge command. @@ -41,7 +41,7 @@ forwarding table using the new bridge command. # bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0 2. Delete forwarding table entry - # bridge fdb delete 00:17:42:8a:b4:05 + # bridge fdb delete 00:17:42:8a:b4:05 dev vxlan0 3. Show forwarding table # bridge fdb show dev vxlan0 diff --git a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt index b9cfd339a6fa..d90d8ec2853d 100644 --- a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1905,6 +1905,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. vid - Vendor ID for the device (optional) pid - Product ID for the device (optional) nrpacks - Max. number of packets per URB (default: 8) + async_unlink - Use async unlink mode (default: yes) device_setup - Device specific magic number (optional) - Influence depends on the device - Default: 0x0000 @@ -1916,6 +1917,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. NB: nrpacks parameter can be modified dynamically via sysfs. Don't put the value over 20. Changing via sysfs has no sanity check. + NB: async_unlink=0 would cause Oops. It remains just for + debugging purpose (if any). NB: ignore_ctl_error=1 may help when you get an error at accessing the mixer element such as URB error -22. This happens on some buggy USB device or the controller. diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index bb0b27db673f..9386a63ea8f6 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -526,17 +526,17 @@ F: drivers/video/geode/ F: arch/x86/include/asm/geode.h AMD IOMMU (AMD-VI) -M: Joerg Roedel +M: Joerg Roedel L: iommu@lists.linux-foundation.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git -S: Supported +S: Maintained F: drivers/iommu/amd_iommu*.[ch] F: include/linux/amd-iommu.h AMD MICROCODE UPDATE SUPPORT -M: Andreas Herrmann +M: Andreas Herrmann L: amd64-microcode@amd64.org -S: Supported +S: Maintained F: arch/x86/kernel/microcode_amd.c AMS (Apple Motion Sensor) DRIVER @@ -841,6 +841,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git F: arch/arm/mach-sa1100/jornada720.c F: arch/arm/mach-sa1100/include/mach/jornada720.h +ARM/IGEP MACHINE SUPPORT +M: Enric Balletbo i Serra +M: Javier Martinez Canillas +L: linux-omap@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-omap2/board-igep0020.c + ARM/INCOME PXA270 SUPPORT M: Marek Vasut L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -2708,10 +2716,10 @@ F: include/linux/edac.h EDAC-AMD64 M: Doug Thompson -M: Borislav Petkov +M: Borislav Petkov L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net -S: Supported +S: Maintained F: drivers/edac/amd64_edac* EDAC-E752X @@ -3753,7 +3761,7 @@ S: Maintained F: drivers/platform/x86/ideapad-laptop.c IDE/ATAPI DRIVERS -M: Borislav Petkov +M: Borislav Petkov L: linux-ide@vger.kernel.org S: Maintained F: Documentation/cdrom/ide-cd @@ -4280,8 +4288,8 @@ F: include/linux/lockd/ F: include/linux/sunrpc/ KERNEL VIRTUAL MACHINE (KVM) -M: Avi Kivity M: Marcelo Tosatti +M: Gleb Natapov L: kvm@vger.kernel.org W: http://kvm.qumranet.com S: Supported @@ -5413,7 +5421,7 @@ S: Maintained F: sound/drivers/opl4/ OPROFILE -M: Robert Richter +M: Robert Richter L: oprofile-list@lists.sf.net S: Maintained F: arch/*/include/asm/oprofile*.h @@ -8198,7 +8206,7 @@ F: drivers/platform/x86 X86 MCE INFRASTRUCTURE M: Tony Luck -M: Borislav Petkov +M: Borislav Petkov L: linux-edac@vger.kernel.org S: Maintained F: arch/x86/kernel/cpu/mcheck/* diff --git a/trunk/Makefile b/trunk/Makefile index 9f6ca124e890..3d2fc460b22f 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 7 SUBLEVEL = 0 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Terrified Chipmunk # *DOCUMENTATION* diff --git a/trunk/arch/alpha/kernel/osf_sys.c b/trunk/arch/alpha/kernel/osf_sys.c index 1e6956a90608..14db93e4c8a8 100644 --- a/trunk/arch/alpha/kernel/osf_sys.c +++ b/trunk/arch/alpha/kernel/osf_sys.c @@ -445,7 +445,7 @@ struct procfs_args { * unhappy with OSF UFS. [CHECKME] */ static int -osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags) +osf_ufs_mount(const char *dirname, struct ufs_args __user *args, int flags) { int retval; struct cdfs_args tmp; @@ -465,7 +465,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags) } static int -osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags) +osf_cdfs_mount(const char *dirname, struct cdfs_args __user *args, int flags) { int retval; struct cdfs_args tmp; @@ -485,7 +485,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags) } static int -osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags) +osf_procfs_mount(const char *dirname, struct procfs_args __user *args, int flags) { struct procfs_args tmp; diff --git a/trunk/arch/arm/mach-davinci/dm644x.c b/trunk/arch/arm/mach-davinci/dm644x.c index cd0c8b1e1ecf..14e9947bad6e 100644 --- a/trunk/arch/arm/mach-davinci/dm644x.c +++ b/trunk/arch/arm/mach-davinci/dm644x.c @@ -713,8 +713,7 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type, break; case VPBE_ENC_CUSTOM_TIMINGS: if (pclock <= 27000000) { - v |= DM644X_VPSS_MUXSEL_PLL2_MODE | - DM644X_VPSS_DACCLKEN; + v |= DM644X_VPSS_DACCLKEN; writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL)); } else { /* diff --git a/trunk/arch/arm/mach-exynos/dma.c b/trunk/arch/arm/mach-exynos/dma.c index 21d568b3b149..87e07d6fc615 100644 --- a/trunk/arch/arm/mach-exynos/dma.c +++ b/trunk/arch/arm/mach-exynos/dma.c @@ -275,6 +275,9 @@ static int __init exynos_dma_init(void) exynos_pdma1_pdata.nr_valid_peri = ARRAY_SIZE(exynos4210_pdma1_peri); exynos_pdma1_pdata.peri_id = exynos4210_pdma1_peri; + + if (samsung_rev() == EXYNOS4210_REV_0) + exynos_mdma1_device.res.start = EXYNOS4_PA_S_MDMA1; } else if (soc_is_exynos4212() || soc_is_exynos4412()) { exynos_pdma0_pdata.nr_valid_peri = ARRAY_SIZE(exynos4212_pdma0_peri); diff --git a/trunk/arch/arm/mach-exynos/include/mach/map.h b/trunk/arch/arm/mach-exynos/include/mach/map.h index 8480849affb9..ed4da4544cd2 100644 --- a/trunk/arch/arm/mach-exynos/include/mach/map.h +++ b/trunk/arch/arm/mach-exynos/include/mach/map.h @@ -90,6 +90,7 @@ #define EXYNOS4_PA_MDMA0 0x10810000 #define EXYNOS4_PA_MDMA1 0x12850000 +#define EXYNOS4_PA_S_MDMA1 0x12840000 #define EXYNOS4_PA_PDMA0 0x12680000 #define EXYNOS4_PA_PDMA1 0x12690000 #define EXYNOS5_PA_MDMA0 0x10800000 diff --git a/trunk/arch/arm/mach-omap2/board-igep0020.c b/trunk/arch/arm/mach-omap2/board-igep0020.c index 48d5e41dfbfa..378590694447 100644 --- a/trunk/arch/arm/mach-omap2/board-igep0020.c +++ b/trunk/arch/arm/mach-omap2/board-igep0020.c @@ -580,6 +580,11 @@ static void __init igep_wlan_bt_init(void) } else return; + /* Make sure that the GPIO pins are muxed correctly */ + omap_mux_init_gpio(igep_wlan_bt_gpios[0].gpio, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(igep_wlan_bt_gpios[1].gpio, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(igep_wlan_bt_gpios[2].gpio, OMAP_PIN_OUTPUT); + err = gpio_request_array(igep_wlan_bt_gpios, ARRAY_SIZE(igep_wlan_bt_gpios)); if (err) { diff --git a/trunk/arch/arm/mach-omap2/common-board-devices.c b/trunk/arch/arm/mach-omap2/common-board-devices.c index 48daac2581b4..84551f205e46 100644 --- a/trunk/arch/arm/mach-omap2/common-board-devices.c +++ b/trunk/arch/arm/mach-omap2/common-board-devices.c @@ -64,30 +64,36 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, struct spi_board_info *spi_bi = &ads7846_spi_board_info; int err; - err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown"); - if (err) { - pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err); - return; - } + /* + * If a board defines get_pendown_state() function, request the pendown + * GPIO and set the GPIO debounce time. + * If a board does not define the get_pendown_state() function, then + * the ads7846 driver will setup the pendown GPIO itself. + */ + if (board_pdata && board_pdata->get_pendown_state) { + err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown"); + if (err) { + pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err); + return; + } - if (gpio_debounce) - gpio_set_debounce(gpio_pendown, gpio_debounce); + if (gpio_debounce) + gpio_set_debounce(gpio_pendown, gpio_debounce); + + gpio_export(gpio_pendown, 0); + } spi_bi->bus_num = bus_num; spi_bi->irq = gpio_to_irq(gpio_pendown); + ads7846_config.gpio_pendown = gpio_pendown; + if (board_pdata) { board_pdata->gpio_pendown = gpio_pendown; + board_pdata->gpio_pendown_debounce = gpio_debounce; spi_bi->platform_data = board_pdata; - if (board_pdata->get_pendown_state) - gpio_export(gpio_pendown, 0); - } else { - ads7846_config.gpio_pendown = gpio_pendown; } - if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state)) - gpio_free(gpio_pendown); - spi_register_board_info(&ads7846_spi_board_info, 1); } #else diff --git a/trunk/arch/arm/mach-omap2/twl-common.c b/trunk/arch/arm/mach-omap2/twl-common.c index 44c42057b61c..a256135d8e48 100644 --- a/trunk/arch/arm/mach-omap2/twl-common.c +++ b/trunk/arch/arm/mach-omap2/twl-common.c @@ -73,6 +73,7 @@ void __init omap4_pmic_init(const char *pmic_type, { /* PMIC part*/ omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE); + omap_mux_init_signal("fref_clk0_out.sys_drm_msecure", OMAP_PIN_OUTPUT); omap_pmic_init(1, 400, pmic_type, 7 + OMAP44XX_IRQ_GIC_START, pmic_data); /* Register additional devices on i2c1 bus if needed */ diff --git a/trunk/arch/arm/plat-omap/i2c.c b/trunk/arch/arm/plat-omap/i2c.c index a5683a84c6ee..6013831a043e 100644 --- a/trunk/arch/arm/plat-omap/i2c.c +++ b/trunk/arch/arm/plat-omap/i2c.c @@ -26,12 +26,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include #define OMAP_I2C_SIZE 0x3f @@ -127,6 +129,16 @@ static inline int omap1_i2c_add_bus(int bus_id) #ifdef CONFIG_ARCH_OMAP2PLUS +/* + * XXX This function is a temporary compatibility wrapper - only + * needed until the I2C driver can be converted to call + * omap_pm_set_max_dev_wakeup_lat() and handle a return code. + */ +static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, t); +} + static inline int omap2_i2c_add_bus(int bus_id) { int l; @@ -158,6 +170,15 @@ static inline int omap2_i2c_add_bus(int bus_id) dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr; pdata->flags = dev_attr->flags; + /* + * When waiting for completion of a i2c transfer, we need to + * set a wake up latency constraint for the MPU. This is to + * ensure quick enough wakeup from idle, when transfer + * completes. + * Only omap3 has support for constraints + */ + if (cpu_is_omap34xx()) + pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(struct omap_i2c_bus_platform_data), NULL, 0, 0); diff --git a/trunk/arch/m68k/include/asm/signal.h b/trunk/arch/m68k/include/asm/signal.h index 67e489d8d1bd..2df26b57c26a 100644 --- a/trunk/arch/m68k/include/asm/signal.h +++ b/trunk/arch/m68k/include/asm/signal.h @@ -41,7 +41,7 @@ struct k_sigaction { static inline void sigaddset(sigset_t *set, int _sig) { asm ("bfset %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -49,7 +49,7 @@ static inline void sigaddset(sigset_t *set, int _sig) static inline void sigdelset(sigset_t *set, int _sig) { asm ("bfclr %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -65,7 +65,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig) int ret; asm ("bfextu %1{%2,#1},%0" : "=d" (ret) - : "od" (*set), "id" ((_sig-1) ^ 31) + : "o" (*set), "id" ((_sig-1) ^ 31) : "cc"); return ret; } diff --git a/trunk/arch/mips/kernel/setup.c b/trunk/arch/mips/kernel/setup.c index a53f8ec37aac..290dc6a1d7a3 100644 --- a/trunk/arch/mips/kernel/setup.c +++ b/trunk/arch/mips/kernel/setup.c @@ -79,7 +79,7 @@ static struct resource data_resource = { .name = "Kernel data", }; void __init add_memory_region(phys_t start, phys_t size, long type) { int x = boot_mem_map.nr_map; - struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1; + int i; /* Sanity check */ if (start + size < start) { @@ -88,15 +88,29 @@ void __init add_memory_region(phys_t start, phys_t size, long type) } /* - * Try to merge with previous entry if any. This is far less than - * perfect but is sufficient for most real world cases. + * Try to merge with existing entry, if any. */ - if (x && prev->addr + prev->size == start && prev->type == type) { - prev->size += size; + for (i = 0; i < boot_mem_map.nr_map; i++) { + struct boot_mem_map_entry *entry = boot_mem_map.map + i; + unsigned long top; + + if (entry->type != type) + continue; + + if (start + size < entry->addr) + continue; /* no overlap */ + + if (entry->addr + entry->size < start) + continue; /* no overlap */ + + top = max(entry->addr + entry->size, start + size); + entry->addr = min(entry->addr, start); + entry->size = top - entry->addr; + return; } - if (x == BOOT_MEM_MAP_MAX) { + if (boot_mem_map.nr_map == BOOT_MEM_MAP_MAX) { pr_err("Ooops! Too many entries in the memory map!\n"); return; } diff --git a/trunk/arch/mips/lib/mips-atomic.c b/trunk/arch/mips/lib/mips-atomic.c index e091430dbeb1..cd160be3ce4d 100644 --- a/trunk/arch/mips/lib/mips-atomic.c +++ b/trunk/arch/mips/lib/mips-atomic.c @@ -56,7 +56,7 @@ __asm__( " .set pop \n" " .endm \n"); -void arch_local_irq_disable(void) +notrace void arch_local_irq_disable(void) { preempt_disable(); __asm__ __volatile__( @@ -93,7 +93,7 @@ __asm__( " .set pop \n" " .endm \n"); -unsigned long arch_local_irq_save(void) +notrace unsigned long arch_local_irq_save(void) { unsigned long flags; preempt_disable(); @@ -135,7 +135,7 @@ __asm__( " .set pop \n" " .endm \n"); -void arch_local_irq_restore(unsigned long flags) +notrace void arch_local_irq_restore(unsigned long flags) { unsigned long __tmp1; @@ -159,7 +159,7 @@ void arch_local_irq_restore(unsigned long flags) EXPORT_SYMBOL(arch_local_irq_restore); -void __arch_local_irq_restore(unsigned long flags) +notrace void __arch_local_irq_restore(unsigned long flags) { unsigned long __tmp1; diff --git a/trunk/arch/parisc/kernel/signal32.c b/trunk/arch/parisc/kernel/signal32.c index fd49aeda9eb8..5dede04f2f3e 100644 --- a/trunk/arch/parisc/kernel/signal32.c +++ b/trunk/arch/parisc/kernel/signal32.c @@ -65,7 +65,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) { compat_sigset_t s; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; sigset_64to32(&s, set); return copy_to_user(up, &s, sizeof s); @@ -77,7 +78,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) compat_sigset_t s; int r; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; if ((r = copy_from_user(&s, up, sz)) == 0) { sigset_32to64(set, &s); diff --git a/trunk/arch/parisc/kernel/sys_parisc.c b/trunk/arch/parisc/kernel/sys_parisc.c index 7426e40699bd..f76c10863c62 100644 --- a/trunk/arch/parisc/kernel/sys_parisc.c +++ b/trunk/arch/parisc/kernel/sys_parisc.c @@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping, struct vm_area_struct *vma; int offset = mapping ? get_offset(mapping) : 0; + offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000; + addr = DCACHE_ALIGN(addr - offset) + offset; for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { diff --git a/trunk/arch/powerpc/boot/dts/mpc5200b.dtsi b/trunk/arch/powerpc/boot/dts/mpc5200b.dtsi index 7ab286ab5300..39ed65a44c5f 100644 --- a/trunk/arch/powerpc/boot/dts/mpc5200b.dtsi +++ b/trunk/arch/powerpc/boot/dts/mpc5200b.dtsi @@ -231,6 +231,12 @@ interrupts = <2 7 0>; }; + sclpc@3c00 { + compatible = "fsl,mpc5200-lpbfifo"; + reg = <0x3c00 0x60>; + interrupts = <2 23 0>; + }; + i2c@3d00 { #address-cells = <1>; #size-cells = <0>; diff --git a/trunk/arch/powerpc/boot/dts/o2d.dtsi b/trunk/arch/powerpc/boot/dts/o2d.dtsi index 3444eb8f0ade..24f668039295 100644 --- a/trunk/arch/powerpc/boot/dts/o2d.dtsi +++ b/trunk/arch/powerpc/boot/dts/o2d.dtsi @@ -86,12 +86,6 @@ reg = <0>; }; }; - - sclpc@3c00 { - compatible = "fsl,mpc5200-lpbfifo"; - reg = <0x3c00 0x60>; - interrupts = <3 23 0>; - }; }; localbus { diff --git a/trunk/arch/powerpc/boot/dts/pcm030.dts b/trunk/arch/powerpc/boot/dts/pcm030.dts index 9e354997eb7e..96512c058033 100644 --- a/trunk/arch/powerpc/boot/dts/pcm030.dts +++ b/trunk/arch/powerpc/boot/dts/pcm030.dts @@ -59,7 +59,7 @@ #gpio-cells = <2>; }; - psc@2000 { /* PSC1 in ac97 mode */ + audioplatform: psc@2000 { /* PSC1 in ac97 mode */ compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97"; cell-index = <0>; }; @@ -134,4 +134,9 @@ localbus { status = "disabled"; }; + + sound { + compatible = "phytec,pcm030-audio-fabric"; + asoc-platform = <&audioplatform>; + }; }; diff --git a/trunk/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/trunk/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 8520b58a5e9a..b89ef65392dc 100644 --- a/trunk/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/trunk/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -372,10 +372,11 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq, case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break; case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break; case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break; - default: - pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n", - __func__, virq, l1irq, l2irq); - return -EINVAL; + case MPC52xx_IRQ_L1_CRIT: + pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n", + __func__, l2irq); + irq_set_chip(virq, &no_irq_chip); + return 0; } irq_set_chip_and_handler(virq, irqchip, handle_level_irq); diff --git a/trunk/arch/powerpc/platforms/pseries/eeh_pe.c b/trunk/arch/powerpc/platforms/pseries/eeh_pe.c index 797cd181dc3f..d16c8ded1084 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh_pe.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh_pe.c @@ -449,7 +449,7 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe) if (list_empty(&pe->edevs)) { cnt = 0; list_for_each_entry(child, &pe->child_list, child) { - if (!(pe->type & EEH_PE_INVALID)) { + if (!(child->type & EEH_PE_INVALID)) { cnt++; break; } diff --git a/trunk/arch/powerpc/platforms/pseries/msi.c b/trunk/arch/powerpc/platforms/pseries/msi.c index d19f4977c834..e5b084723131 100644 --- a/trunk/arch/powerpc/platforms/pseries/msi.c +++ b/trunk/arch/powerpc/platforms/pseries/msi.c @@ -220,7 +220,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total) /* Get the top level device in the PE */ edev = of_node_to_eeh_dev(dn); - edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list); + if (edev->pe) + edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list); dn = eeh_dev_to_of_node(edev); if (!dn) return NULL; diff --git a/trunk/arch/sparc/include/asm/prom.h b/trunk/arch/sparc/include/asm/prom.h index f93003123bce..67c62578d170 100644 --- a/trunk/arch/sparc/include/asm/prom.h +++ b/trunk/arch/sparc/include/asm/prom.h @@ -63,10 +63,13 @@ extern char *of_console_options; extern void irq_trans_init(struct device_node *dp); extern char *build_path_component(struct device_node *dp); -/* SPARC has a local implementation */ +/* SPARC has local implementations */ extern int of_address_to_resource(struct device_node *dev, int index, struct resource *r); #define of_address_to_resource of_address_to_resource +void __iomem *of_iomap(struct device_node *node, int index); +#define of_iomap of_iomap + #endif /* __KERNEL__ */ #endif /* _SPARC_PROM_H */ diff --git a/trunk/arch/sparc/kernel/signal_64.c b/trunk/arch/sparc/kernel/signal_64.c index 867de2f8189c..689e1ba62809 100644 --- a/trunk/arch/sparc/kernel/signal_64.c +++ b/trunk/arch/sparc/kernel/signal_64.c @@ -295,9 +295,7 @@ void do_rt_sigreturn(struct pt_regs *regs) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); - err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); - - if (err) + if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT) goto segv; err |= __get_user(rwin_save, &sf->rwin_save); diff --git a/trunk/arch/x86/boot/compressed/eboot.c b/trunk/arch/x86/boot/compressed/eboot.c index c760e073963e..e87b0cac14b5 100644 --- a/trunk/arch/x86/boot/compressed/eboot.c +++ b/trunk/arch/x86/boot/compressed/eboot.c @@ -12,6 +12,8 @@ #include #include +#undef memcpy /* Use memcpy from misc.c */ + #include "eboot.h" static efi_system_table_t *sys_table; diff --git a/trunk/arch/x86/boot/header.S b/trunk/arch/x86/boot/header.S index 2a017441b8b2..8c132a625b94 100644 --- a/trunk/arch/x86/boot/header.S +++ b/trunk/arch/x86/boot/header.S @@ -476,6 +476,3 @@ die: setup_corrupt: .byte 7 .string "No setup signature found...\n" - - .data -dummy: .long 0 diff --git a/trunk/arch/x86/include/asm/ptrace.h b/trunk/arch/x86/include/asm/ptrace.h index dcfde52979c3..19f16ebaf4fa 100644 --- a/trunk/arch/x86/include/asm/ptrace.h +++ b/trunk/arch/x86/include/asm/ptrace.h @@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs) } #endif -/* - * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode - * when it traps. The previous stack will be directly underneath the saved - * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. - * - * This is valid only for kernel mode traps. - */ -static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) -{ #ifdef CONFIG_X86_32 - return (unsigned long)(®s->sp); +extern unsigned long kernel_stack_pointer(struct pt_regs *regs); #else +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ return regs->sp; -#endif } +#endif #define GET_IP(regs) ((regs)->ip) #define GET_FP(regs) ((regs)->bp) diff --git a/trunk/arch/x86/kernel/cpu/amd.c b/trunk/arch/x86/kernel/cpu/amd.c index f7e98a2c0d12..1b7d1656a042 100644 --- a/trunk/arch/x86/kernel/cpu/amd.c +++ b/trunk/arch/x86/kernel/cpu/amd.c @@ -631,6 +631,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } } + /* + * The way access filter has a performance penalty on some workloads. + * Disable it on the affected CPUs. + */ + if ((c->x86 == 0x15) && + (c->x86_model >= 0x02) && (c->x86_model < 0x20)) { + u64 val; + + if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) { + val |= 0x1E; + wrmsrl_safe(0xc0011021, val); + } + } + cpu_detect_cache_sizes(c); /* Multi core CPU? */ diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce_amd.c b/trunk/arch/x86/kernel/cpu/mcheck/mce_amd.c index 698b6ec12e0f..1ac581f38dfa 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -6,7 +6,7 @@ * * Written by Jacob Shin - AMD, Inc. * - * Support: borislav.petkov@amd.com + * Maintained by: Borislav Petkov * * April 2006 * - added support for AMD Family 0x10 processors diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce_intel.c b/trunk/arch/x86/kernel/cpu/mcheck/mce_intel.c index 5f88abf07e9c..4f9a3cbfc4a3 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce_intel.c @@ -285,34 +285,39 @@ void cmci_clear(void) raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); } +static long cmci_rediscover_work_func(void *arg) +{ + int banks; + + /* Recheck banks in case CPUs don't all have the same */ + if (cmci_supported(&banks)) + cmci_discover(banks); + + return 0; +} + /* * After a CPU went down cycle through all the others and rediscover * Must run in process context. */ void cmci_rediscover(int dying) { - int banks; - int cpu; - cpumask_var_t old; + int cpu, banks; if (!cmci_supported(&banks)) return; - if (!alloc_cpumask_var(&old, GFP_KERNEL)) - return; - cpumask_copy(old, ¤t->cpus_allowed); for_each_online_cpu(cpu) { if (cpu == dying) continue; - if (set_cpus_allowed_ptr(current, cpumask_of(cpu))) + + if (cpu == smp_processor_id()) { + cmci_rediscover_work_func(NULL); continue; - /* Recheck banks in case CPUs don't all have the same */ - if (cmci_supported(&banks)) - cmci_discover(banks); - } + } - set_cpus_allowed_ptr(current, old); - free_cpumask_var(old); + work_on_cpu(cpu, cmci_rediscover_work_func, NULL); + } } /* diff --git a/trunk/arch/x86/kernel/entry_64.S b/trunk/arch/x86/kernel/entry_64.S index b51b2c7ee51f..1328fe49a3f1 100644 --- a/trunk/arch/x86/kernel/entry_64.S +++ b/trunk/arch/x86/kernel/entry_64.S @@ -995,8 +995,8 @@ END(interrupt) */ .p2align CONFIG_X86_L1_CACHE_SHIFT common_interrupt: - ASM_CLAC XCPT_FRAME + ASM_CLAC addq $-0x80,(%rsp) /* Adjust vector to [-256,-1] range */ interrupt do_IRQ /* 0(%rsp): old_rsp-ARGOFFSET */ @@ -1135,8 +1135,8 @@ END(common_interrupt) */ .macro apicinterrupt num sym do_sym ENTRY(\sym) - ASM_CLAC INTR_FRAME + ASM_CLAC pushq_cfi $~(\num) .Lcommon_\sym: interrupt \do_sym @@ -1190,8 +1190,8 @@ apicinterrupt IRQ_WORK_VECTOR \ */ .macro zeroentry sym do_sym ENTRY(\sym) - ASM_CLAC INTR_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */ subq $ORIG_RAX-R15, %rsp @@ -1208,8 +1208,8 @@ END(\sym) .macro paranoidzeroentry sym do_sym ENTRY(\sym) - ASM_CLAC INTR_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */ subq $ORIG_RAX-R15, %rsp @@ -1227,8 +1227,8 @@ END(\sym) #define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8) .macro paranoidzeroentry_ist sym do_sym ist ENTRY(\sym) - ASM_CLAC INTR_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */ subq $ORIG_RAX-R15, %rsp @@ -1247,8 +1247,8 @@ END(\sym) .macro errorentry sym do_sym ENTRY(\sym) - ASM_CLAC XCPT_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME subq $ORIG_RAX-R15, %rsp CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 @@ -1266,8 +1266,8 @@ END(\sym) /* error code is on the stack already */ .macro paranoiderrorentry sym do_sym ENTRY(\sym) - ASM_CLAC XCPT_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME subq $ORIG_RAX-R15, %rsp CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 diff --git a/trunk/arch/x86/kernel/microcode_amd.c b/trunk/arch/x86/kernel/microcode_amd.c index 7720ff5a9ee2..efdec7cd8e01 100644 --- a/trunk/arch/x86/kernel/microcode_amd.c +++ b/trunk/arch/x86/kernel/microcode_amd.c @@ -8,8 +8,8 @@ * Tigran Aivazian * * Maintainers: - * Andreas Herrmann - * Borislav Petkov + * Andreas Herrmann + * Borislav Petkov * * This driver allows to upgrade microcode on F10h AMD * CPUs and later. @@ -190,6 +190,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size, #define F1XH_MPB_MAX_SIZE 2048 #define F14H_MPB_MAX_SIZE 1824 #define F15H_MPB_MAX_SIZE 4096 +#define F16H_MPB_MAX_SIZE 3458 switch (c->x86) { case 0x14: @@ -198,6 +199,9 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size, case 0x15: max_size = F15H_MPB_MAX_SIZE; break; + case 0x16: + max_size = F16H_MPB_MAX_SIZE; + break; default: max_size = F1XH_MPB_MAX_SIZE; break; diff --git a/trunk/arch/x86/kernel/ptrace.c b/trunk/arch/x86/kernel/ptrace.c index b00b33a18390..5e0596b0632e 100644 --- a/trunk/arch/x86/kernel/ptrace.c +++ b/trunk/arch/x86/kernel/ptrace.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -166,6 +167,35 @@ static inline bool invalid_selector(u16 value) #define FLAG_MASK FLAG_MASK_32 +/* + * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode + * when it traps. The previous stack will be directly underneath the saved + * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. + * + * Now, if the stack is empty, '®s->sp' is out of range. In this + * case we try to take the previous stack. To always return a non-null + * stack pointer we fall back to regs as stack if no previous stack + * exists. + * + * This is valid only for kernel mode traps. + */ +unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1); + unsigned long sp = (unsigned long)®s->sp; + struct thread_info *tinfo; + + if (context == (sp & ~(THREAD_SIZE - 1))) + return sp; + + tinfo = (struct thread_info *)context; + if (tinfo->previous_esp) + return tinfo->previous_esp; + + return (unsigned long)regs; +} +EXPORT_SYMBOL_GPL(kernel_stack_pointer); + static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); diff --git a/trunk/arch/x86/mm/tlb.c b/trunk/arch/x86/mm/tlb.c index 0777f042e400..60f926cd8b0e 100644 --- a/trunk/arch/x86/mm/tlb.c +++ b/trunk/arch/x86/mm/tlb.c @@ -197,7 +197,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, } if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1 - || vmflag == VM_HUGETLB) { + || vmflag & VM_HUGETLB) { local_flush_tlb(); goto flush_all; } diff --git a/trunk/arch/x86/pci/ce4100.c b/trunk/arch/x86/pci/ce4100.c index 41bd2a2d2c50..b914e20b5a00 100644 --- a/trunk/arch/x86/pci/ce4100.c +++ b/trunk/arch/x86/pci/ce4100.c @@ -115,6 +115,16 @@ static void sata_revid_read(struct sim_dev_reg *reg, u32 *value) reg_read(reg, value); } +static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&pci_config_lock, flags); + /* force interrupt pin value to 0 */ + *value = reg->sim_reg.value & 0xfff00ff; + raw_spin_unlock_irqrestore(&pci_config_lock, flags); +} + static struct sim_dev_reg bus1_fixups[] = { DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write) DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write) @@ -144,6 +154,7 @@ static struct sim_dev_reg bus1_fixups[] = { DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write) DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write) DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write) + DEFINE_REG(11, 7, 0x3c, 256, reg_init, reg_noirq_read, reg_write) DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write) DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write) @@ -161,8 +172,10 @@ static struct sim_dev_reg bus1_fixups[] = { DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write) DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write) + DEFINE_REG(16, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write) DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write) + DEFINE_REG(18, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write) }; static void __init init_sim_regs(void) diff --git a/trunk/arch/x86/platform/ce4100/ce4100.c b/trunk/arch/x86/platform/ce4100/ce4100.c index 4c61b52191eb..92525cb8e54c 100644 --- a/trunk/arch/x86/platform/ce4100/ce4100.c +++ b/trunk/arch/x86/platform/ce4100/ce4100.c @@ -21,12 +21,25 @@ #include #include #include +#include static int ce4100_i8042_detect(void) { return 0; } +/* + * The CE4100 platform has an internal 8051 Microcontroller which is + * responsible for signaling to the external Power Management Unit the + * intention to reset, reboot or power off the system. This 8051 device has + * its command register mapped at I/O port 0xcf9 and the value 0x4 is used + * to power off the system. + */ +static void ce4100_power_off(void) +{ + outb(0x4, 0xcf9); +} + #ifdef CONFIG_SERIAL_8250 static unsigned int mem_serial_in(struct uart_port *p, int offset) @@ -139,8 +152,19 @@ void __init x86_ce4100_early_setup(void) x86_init.mpparse.find_smp_config = x86_init_noop; x86_init.pci.init = ce4100_pci_init; + /* + * By default, the reboot method is ACPI which is supported by the + * CE4100 bootloader CEFDK using FADT.ResetReg Address and ResetValue + * the bootloader will however issue a system power off instead of + * reboot. By using BOOT_KBD we ensure proper system reboot as + * expected. + */ + reboot_type = BOOT_KBD; + #ifdef CONFIG_X86_IO_APIC x86_init.pci.init_irq = sdv_pci_init; x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck; #endif + + pm_power_off = ce4100_power_off; } diff --git a/trunk/block/blk-exec.c b/trunk/block/blk-exec.c index 8b6dc5bd4dd0..f71eac35c1b9 100644 --- a/trunk/block/blk-exec.c +++ b/trunk/block/blk-exec.c @@ -52,11 +52,17 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, rq_end_io_fn *done) { int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + bool is_pm_resume; WARN_ON(irqs_disabled()); rq->rq_disk = bd_disk; rq->end_io = done; + /* + * need to check this before __blk_run_queue(), because rq can + * be freed before that returns. + */ + is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME; spin_lock_irq(q->queue_lock); @@ -71,7 +77,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, __elv_add_request(q, rq, where); __blk_run_queue(q); /* the queue is stopped so it won't be run */ - if (rq->cmd_type == REQ_TYPE_PM_RESUME) + if (is_pm_resume) q->request_fn(q); spin_unlock_irq(q->queue_lock); } diff --git a/trunk/drivers/ata/ahci_platform.c b/trunk/drivers/ata/ahci_platform.c index b1ae48054dc5..b7078afddb74 100644 --- a/trunk/drivers/ata/ahci_platform.c +++ b/trunk/drivers/ata/ahci_platform.c @@ -238,7 +238,7 @@ static int __devexit ahci_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int ahci_suspend(struct device *dev) { struct ahci_platform_data *pdata = dev_get_platdata(dev); diff --git a/trunk/drivers/ata/libata-acpi.c b/trunk/drivers/ata/libata-acpi.c index fd9ecf74e631..5b0ba3f20edc 100644 --- a/trunk/drivers/ata/libata-acpi.c +++ b/trunk/drivers/ata/libata-acpi.c @@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev, struct acpi_device *acpi_dev; struct acpi_device_power_state *states; - if (ap->flags & ATA_FLAG_ACPI_SATA) - ata_dev = &ap->link.device[sdev->channel]; - else + if (ap->flags & ATA_FLAG_ACPI_SATA) { + if (!sata_pmp_attached(ap)) + ata_dev = &ap->link.device[sdev->id]; + else + ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id]; + } + else { ata_dev = &ap->link.device[sdev->id]; + } *handle = ata_dev_acpi_handle(ata_dev); diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 3cc7096cfda7..f46fbd3bd3fb 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -2942,6 +2942,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode) if (xfer_mode == t->mode) return t; + + WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n", + __func__, xfer_mode); + return NULL; } diff --git a/trunk/drivers/ata/libata-scsi.c b/trunk/drivers/ata/libata-scsi.c index e3bda074fa12..a6df6a351d6e 100644 --- a/trunk/drivers/ata/libata-scsi.c +++ b/trunk/drivers/ata/libata-scsi.c @@ -1052,6 +1052,8 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) { sdev->use_10_for_rw = 1; sdev->use_10_for_ms = 1; + sdev->no_report_opcodes = 1; + sdev->no_write_same = 1; /* Schedule policy is determined by ->qc_defer() callback and * it needs to see every deferred qc. Set dev_blocked to 1 to diff --git a/trunk/drivers/ata/pata_arasan_cf.c b/trunk/drivers/ata/pata_arasan_cf.c index 26201ebef3ca..371fd2c698b7 100644 --- a/trunk/drivers/ata/pata_arasan_cf.c +++ b/trunk/drivers/ata/pata_arasan_cf.c @@ -317,6 +317,12 @@ static int cf_init(struct arasan_cf_dev *acdev) return ret; } + ret = clk_set_rate(acdev->clk, 166000000); + if (ret) { + dev_warn(acdev->host->dev, "clock set rate failed"); + return ret; + } + spin_lock_irqsave(&acdev->host->lock, flags); /* configure CF interface clock */ writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk : @@ -908,7 +914,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int arasan_cf_suspend(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); diff --git a/trunk/drivers/ata/sata_highbank.c b/trunk/drivers/ata/sata_highbank.c index 0d7c4c2cd26f..400bf1c3e982 100644 --- a/trunk/drivers/ata/sata_highbank.c +++ b/trunk/drivers/ata/sata_highbank.c @@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = { }; MODULE_DEVICE_TABLE(of, ahci_of_match); -static int __init ahci_highbank_probe(struct platform_device *pdev) +static int __devinit ahci_highbank_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ahci_host_priv *hpriv; @@ -378,7 +378,7 @@ static int __devexit ahci_highbank_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int ahci_highbank_suspend(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); diff --git a/trunk/drivers/ata/sata_svw.c b/trunk/drivers/ata/sata_svw.c index 44a4256533e1..08608de87e4e 100644 --- a/trunk/drivers/ata/sata_svw.c +++ b/trunk/drivers/ata/sata_svw.c @@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link, return 0; } +static int k2_sata_softreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return ata_sff_softreset(link, class, deadline); +} + +static int k2_sata_hardreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return sata_sff_hardreset(link, class, deadline); +} static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) { @@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = { static struct ata_port_operations k2_sata_ops = { .inherits = &ata_bmdma_port_ops, + .softreset = k2_sata_softreset, + .hardreset = k2_sata_hardreset, .sff_tf_load = k2_sata_tf_load, .sff_tf_read = k2_sata_tf_read, .sff_check_status = k2_stat_check_status, diff --git a/trunk/drivers/base/power/qos.c b/trunk/drivers/base/power/qos.c index 74a67e0019a2..fbbd4ed2edf2 100644 --- a/trunk/drivers/base/power/qos.c +++ b/trunk/drivers/base/power/qos.c @@ -451,7 +451,7 @@ int dev_pm_qos_add_ancestor_request(struct device *dev, if (ancestor) error = dev_pm_qos_add_request(ancestor, req, value); - if (error) + if (error < 0) req->dev = NULL; return error; diff --git a/trunk/drivers/block/aoe/aoecmd.c b/trunk/drivers/block/aoe/aoecmd.c index 3804a0af3ef1..9fe4f1865558 100644 --- a/trunk/drivers/block/aoe/aoecmd.c +++ b/trunk/drivers/block/aoe/aoecmd.c @@ -935,7 +935,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) /* cf. http://lkml.org/lkml/2006/10/31/28 */ if (!fastfail) - q->request_fn(q); + __blk_run_queue(q); } static void diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index 1c49d7173966..2ddd64a9ffde 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -4330,6 +4330,7 @@ static int __init do_floppy_init(void) out_unreg_blkdev: unregister_blkdev(FLOPPY_MAJOR, "fd"); out_put_disk: + destroy_workqueue(floppy_wq); for (drive = 0; drive < N_DRIVE; drive++) { if (!disks[drive]) break; @@ -4340,7 +4341,6 @@ static int __init do_floppy_init(void) } put_disk(disks[drive]); } - destroy_workqueue(floppy_wq); return err; } @@ -4555,6 +4555,8 @@ static void __exit floppy_module_exit(void) unregister_blkdev(FLOPPY_MAJOR, "fd"); platform_driver_unregister(&floppy_driver); + destroy_workqueue(floppy_wq); + for (drive = 0; drive < N_DRIVE; drive++) { del_timer_sync(&motor_off_timer[drive]); @@ -4578,7 +4580,6 @@ static void __exit floppy_module_exit(void) cancel_delayed_work_sync(&fd_timeout); cancel_delayed_work_sync(&fd_timer); - destroy_workqueue(floppy_wq); if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.c b/trunk/drivers/block/mtip32xx/mtip32xx.c index adc6f36564cf..9694dd99bbbc 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.c +++ b/trunk/drivers/block/mtip32xx/mtip32xx.c @@ -559,7 +559,7 @@ static void mtip_timeout_function(unsigned long int data) struct mtip_cmd *command; int tag, cmdto_cnt = 0; unsigned int bit, group; - unsigned int num_command_slots = port->dd->slot_groups * 32; + unsigned int num_command_slots; unsigned long to, tagaccum[SLOTBITS_IN_LONGS]; if (unlikely(!port)) @@ -572,6 +572,7 @@ static void mtip_timeout_function(unsigned long int data) } /* clear the tag accumulator */ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); + num_command_slots = port->dd->slot_groups * 32; for (tag = 0; tag < num_command_slots; tag++) { /* @@ -2218,8 +2219,8 @@ static int exec_drive_taskfile(struct driver_data *dd, fis.device); /* check for erase mode support during secure erase.*/ - if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) - && (outbuf[0] & MTIP_SEC_ERASE_MODE)) { + if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) && outbuf && + (outbuf[0] & MTIP_SEC_ERASE_MODE)) { erasemode = 1; } @@ -2439,7 +2440,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, * return value * None */ -static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, +static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector, int nsect, int nents, int tag, void *callback, void *data, int dir) { @@ -2447,6 +2448,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, struct mtip_port *port = dd->port; struct mtip_cmd *command = &port->commands[tag]; int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + u64 start = sector; /* Map the scatter list for DMA access */ nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir); @@ -2465,8 +2467,12 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, fis->opts = 1 << 7; fis->command = (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE); - *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF); - *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF); + fis->lba_low = start & 0xFF; + fis->lba_mid = (start >> 8) & 0xFF; + fis->lba_hi = (start >> 16) & 0xFF; + fis->lba_low_ex = (start >> 24) & 0xFF; + fis->lba_mid_ex = (start >> 32) & 0xFF; + fis->lba_hi_ex = (start >> 40) & 0xFF; fis->device = 1 << 6; fis->features = nsect & 0xFF; fis->features_ex = (nsect >> 8) & 0xFF; diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.h b/trunk/drivers/block/mtip32xx/mtip32xx.h index 5f4a917bd8bb..b1742640556a 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.h +++ b/trunk/drivers/block/mtip32xx/mtip32xx.h @@ -34,7 +34,7 @@ #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48 /* check for erase mode support during secure erase */ -#define MTIP_SEC_ERASE_MODE 0x3 +#define MTIP_SEC_ERASE_MODE 0x2 /* # of times to retry timed out/failed IOs */ #define MTIP_MAX_RETRIES 2 @@ -155,14 +155,14 @@ enum { MTIP_DDF_REBUILD_FAILED_BIT = 8, }; -__packed struct smart_attr{ +struct smart_attr { u8 attr_id; u16 flags; u8 cur; u8 worst; u32 data; u8 res[3]; -}; +} __packed; /* Register Frame Information Structure (FIS), host to device. */ struct host_to_dev_fis { diff --git a/trunk/drivers/edac/amd64_edac.h b/trunk/drivers/edac/amd64_edac.h index 8d4804732bac..8c4139647efc 100644 --- a/trunk/drivers/edac/amd64_edac.h +++ b/trunk/drivers/edac/amd64_edac.h @@ -33,7 +33,7 @@ * detection. The mods to Rev F required more family * information detection. * - * Changes/Fixes by Borislav Petkov : + * Changes/Fixes by Borislav Petkov : * - misc fixes and code cleanups * * This module is based on the following documents diff --git a/trunk/drivers/edac/edac_stub.c b/trunk/drivers/edac/edac_stub.c index 6c86f6e54558..351945fa2ecd 100644 --- a/trunk/drivers/edac/edac_stub.c +++ b/trunk/drivers/edac/edac_stub.c @@ -5,7 +5,7 @@ * * 2007 (c) MontaVista Software, Inc. * 2010 (c) Advanced Micro Devices Inc. - * Borislav Petkov + * Borislav Petkov * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/trunk/drivers/edac/mce_amd_inj.c b/trunk/drivers/edac/mce_amd_inj.c index 66b5151c1080..2ae78f20cc28 100644 --- a/trunk/drivers/edac/mce_amd_inj.c +++ b/trunk/drivers/edac/mce_amd_inj.c @@ -6,7 +6,7 @@ * This file may be distributed under the terms of the GNU General Public * License version 2. * - * Copyright (c) 2010: Borislav Petkov + * Copyright (c) 2010: Borislav Petkov * Advanced Micro Devices Inc. */ @@ -168,6 +168,6 @@ module_init(edac_init_mce_inject); module_exit(edac_exit_mce_inject); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Borislav Petkov "); +MODULE_AUTHOR("Borislav Petkov "); MODULE_AUTHOR("AMD Inc."); MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding"); diff --git a/trunk/drivers/firewire/sbp2.c b/trunk/drivers/firewire/sbp2.c index 1162d6b3bf85..bb1b392f5cda 100644 --- a/trunk/drivers/firewire/sbp2.c +++ b/trunk/drivers/firewire/sbp2.c @@ -1546,6 +1546,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) struct sbp2_logical_unit *lu = sdev->hostdata; sdev->use_10_for_rw = 1; + sdev->no_report_opcodes = 1; + sdev->no_write_same = 1; if (sbp2_param_exclusive_login) sdev->manage_start_stop = 1; diff --git a/trunk/drivers/gpio/Kconfig b/trunk/drivers/gpio/Kconfig index f11d8e3b4041..47150f5ded04 100644 --- a/trunk/drivers/gpio/Kconfig +++ b/trunk/drivers/gpio/Kconfig @@ -466,7 +466,7 @@ config GPIO_ADP5588_IRQ config GPIO_ADNP tristate "Avionic Design N-bit GPIO expander" - depends on I2C && OF + depends on I2C && OF_GPIO help This option enables support for N GPIOs found on Avionic Design I2C GPIO expanders. The register space will be extended by powers diff --git a/trunk/drivers/gpio/gpio-mcp23s08.c b/trunk/drivers/gpio/gpio-mcp23s08.c index 0f425189de11..ce1c84760076 100644 --- a/trunk/drivers/gpio/gpio-mcp23s08.c +++ b/trunk/drivers/gpio/gpio-mcp23s08.c @@ -77,7 +77,7 @@ struct mcp23s08_driver_data { /*----------------------------------------------------------------------*/ -#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg) { @@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, break; #endif /* CONFIG_SPI_MASTER */ -#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) case MCP_TYPE_008: mcp->ops = &mcp23008_ops; mcp->chip.ngpio = 8; @@ -473,7 +473,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, /*----------------------------------------------------------------------*/ -#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) static int __devinit mcp230xx_probe(struct i2c_client *client, const struct i2c_device_id *id) diff --git a/trunk/drivers/gpio/gpio-mvebu.c b/trunk/drivers/gpio/gpio-mvebu.c index cf7afb9eb61a..be65c0451ad5 100644 --- a/trunk/drivers/gpio/gpio-mvebu.c +++ b/trunk/drivers/gpio/gpio-mvebu.c @@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip) return mvchip->membase + GPIO_OUT_OFF; } +static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) +{ + return mvchip->membase + GPIO_BLINK_EN_OFF; +} + static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) { return mvchip->membase + GPIO_IO_CONF_OFF; @@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin) return (u >> pin) & 1; } +static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value) +{ + struct mvebu_gpio_chip *mvchip = + container_of(chip, struct mvebu_gpio_chip, chip); + unsigned long flags; + u32 u; + + spin_lock_irqsave(&mvchip->lock, flags); + u = readl_relaxed(mvebu_gpioreg_blink(mvchip)); + if (value) + u |= 1 << pin; + else + u &= ~(1 << pin); + writel_relaxed(u, mvebu_gpioreg_blink(mvchip)); + spin_unlock_irqrestore(&mvchip->lock, flags); +} + static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin) { struct mvebu_gpio_chip *mvchip = @@ -244,6 +266,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, if (ret) return ret; + mvebu_gpio_blink(chip, pin, 0); mvebu_gpio_set(chip, pin, value); spin_lock_irqsave(&mvchip->lock, flags); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 05a909a17cee..15b182c84ce8 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -49,13 +49,7 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) if (chan->vblank.crtc != crtc) continue; - if (nv_device(priv)->chipset == 0x50) { - nv_wr32(priv, 0x001704, chan->vblank.channel); - nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); - bar->flush(bar); - nv_wr32(priv, 0x001570, chan->vblank.offset); - nv_wr32(priv, 0x001574, chan->vblank.value); - } else { + if (nv_device(priv)->chipset >= 0xc0) { nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); bar->flush(bar); nv_wr32(priv, 0x06000c, @@ -63,6 +57,17 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset)); nv_wr32(priv, 0x060014, chan->vblank.value); + } else { + nv_wr32(priv, 0x001704, chan->vblank.channel); + nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); + bar->flush(bar); + if (nv_device(priv)->chipset == 0x50) { + nv_wr32(priv, 0x001570, chan->vblank.offset); + nv_wr32(priv, 0x001574, chan->vblank.value); + } else { + nv_wr32(priv, 0x060010, chan->vblank.offset); + nv_wr32(priv, 0x060014, chan->vblank.value); + } } list_del(&chan->vblank.head); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c index e45035efb8ca..7bbb1e1b7a8d 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c @@ -669,21 +669,27 @@ nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem) }); } -void +int nv40_grctx_init(struct nouveau_device *device, u32 *size) { - u32 ctxprog[256], i; + u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i; struct nouveau_grctx ctx = { .device = device, .mode = NOUVEAU_GRCTX_PROG, .data = ctxprog, - .ctxprog_max = ARRAY_SIZE(ctxprog) + .ctxprog_max = 256, }; + if (!ctxprog) + return -ENOMEM; + nv40_grctx_generate(&ctx); nv_wr32(device, 0x400324, 0); for (i = 0; i < ctx.ctxprog_len; i++) nv_wr32(device, 0x400328, ctxprog[i]); *size = ctx.ctxvals_pos * 4; + + kfree(ctxprog); + return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 425001204a89..cc6574eeb80e 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -346,7 +346,9 @@ nv40_graph_init(struct nouveau_object *object) return ret; /* generate and upload context program */ - nv40_grctx_init(nv_device(priv), &priv->size); + ret = nv40_grctx_init(nv_device(priv), &priv->size); + if (ret) + return ret; /* No context present currently */ nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h index d2ac975afc2e..7da35a4e7970 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h @@ -15,7 +15,7 @@ nv44_graph_class(void *priv) return !(0x0baf & (1 << (device->chipset & 0x0f))); } -void nv40_grctx_init(struct nouveau_device *, u32 *size); +int nv40_grctx_init(struct nouveau_device *, u32 *size); void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *); #endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/core/object.h b/trunk/drivers/gpu/drm/nouveau/core/include/core/object.h index 818feabbf4a0..486f1a9217fd 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/core/object.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/core/object.h @@ -175,14 +175,18 @@ nv_mo32(void *obj, u32 addr, u32 mask, u32 data) return temp; } -static inline bool -nv_strncmp(void *obj, u32 addr, u32 len, const char *str) +static inline int +nv_memcmp(void *obj, u32 addr, const char *str, u32 len) { + unsigned char c1, c2; + while (len--) { - if (nv_ro08(obj, addr++) != *(str++)) - return false; + c1 = nv_ro08(obj, addr++); + c2 = *(str++); + if (c1 != c2) + return c1 - c2; } - return true; + return 0; } #endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/clock.h index 39e73b91d360..41b7a6a76f19 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/clock.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/clock.h @@ -54,6 +54,7 @@ int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, int clk, struct nouveau_pll_vals *); int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1, struct nouveau_pll_vals *); - +int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, + int clk, struct nouveau_pll_vals *); #endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c index 7d750382a833..c51197157749 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c @@ -64,7 +64,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) } } else if (*ver >= 0x15) { - if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) { + if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) { u16 i2c = nv_ro16(bios, dcb + 2); *hdr = 4; *cnt = (i2c - dcb) / 10; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c index cc8d7d162d7c..9068c98b96f6 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c @@ -66,6 +66,24 @@ nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) return ret; } +int +nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, + int clk, struct nouveau_pll_vals *pv) +{ + int ret, N, M, P; + + ret = nva3_pll_calc(clock, info, clk, &N, NULL, &M, &P); + + if (ret > 0) { + pv->refclk = info->refclk; + pv->N1 = N; + pv->M1 = M; + pv->log2P = P; + } + return ret; +} + + static int nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -80,6 +98,7 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nva3_clock_pll_set; + priv->base.pll_calc = nva3_clock_pll_calc; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index 5ccce0b17bf3..f6962c9b6c36 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c @@ -79,6 +79,7 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nvc0_clock_pll_set; + priv->base.pll_calc = nva3_clock_pll_calc; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c b/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c index cc79c796afee..cbf1fc60a386 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -241,6 +241,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) if (unlikely(!abi16)) return -ENOMEM; + + if (!drm->channel) + return nouveau_abi16_put(abi16, -ENODEV); + client = nv_client(abi16->client); if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c index 0910125cbbc3..8503b2ea570a 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -129,7 +129,8 @@ nouveau_accel_init(struct nouveau_drm *drm) /* initialise synchronisation routines */ if (device->card_type < NV_10) ret = nv04_fence_create(drm); - else if (device->chipset < 0x84) ret = nv10_fence_create(drm); + else if (device->card_type < NV_50) ret = nv10_fence_create(drm); + else if (device->chipset < 0x84) ret = nv50_fence_create(drm); else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); else ret = nvc0_fence_create(drm); if (ret) { diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index af31f829f4a8..219942c660d7 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -1330,6 +1330,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav break; udelay(1); } + } else { + save->crtc_enabled[i] = false; } } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_agp.c b/trunk/drivers/gpu/drm/radeon/radeon_agp.c index 10ea17a6b2a6..42433344cb1b 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_agp.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_agp.c @@ -69,9 +69,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, PCI_VENDOR_ID_DELL, 0x00e3, 2}, - /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */ + /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, PCI_VENDOR_ID_DELL, 0x0149, 1}, + /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, + PCI_VENDOR_ID_IBM, 0x0531, 1}, /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 0x1025, 0x0061, 1}, diff --git a/trunk/drivers/i2c/busses/i2c-at91.c b/trunk/drivers/i2c/busses/i2c-at91.c index aa59a254be2c..c02bf208084f 100644 --- a/trunk/drivers/i2c/busses/i2c-at91.c +++ b/trunk/drivers/i2c/busses/i2c-at91.c @@ -39,6 +39,7 @@ #define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */ #define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */ #define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */ +#define AT91_TWI_QUICK 0x0040 /* SMBus quick command */ #define AT91_TWI_SWRST 0x0080 /* Software Reset */ #define AT91_TWI_MMR 0x0004 /* Master Mode Register */ @@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) INIT_COMPLETION(dev->cmd_complete); dev->transfer_status = 0; - if (dev->msg->flags & I2C_M_RD) { + + if (!dev->buf_len) { + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK); + at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + } else if (dev->msg->flags & I2C_M_RD) { unsigned start_flags = AT91_TWI_START; if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) { diff --git a/trunk/drivers/i2c/busses/i2c-mxs.c b/trunk/drivers/i2c/busses/i2c-mxs.c index 286ca1917820..0670da79ee5e 100644 --- a/trunk/drivers/i2c/busses/i2c-mxs.c +++ b/trunk/drivers/i2c/busses/i2c-mxs.c @@ -287,12 +287,14 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap, select_init_dma_fail: dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE); select_init_pio_fail: + dmaengine_terminate_all(i2c->dmach); return -EINVAL; /* Write failpath. */ write_init_dma_fail: dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE); write_init_pio_fail: + dmaengine_terminate_all(i2c->dmach); return -EINVAL; } diff --git a/trunk/drivers/i2c/busses/i2c-omap.c b/trunk/drivers/i2c/busses/i2c-omap.c index db31eaed6ea5..3525c9e62cb0 100644 --- a/trunk/drivers/i2c/busses/i2c-omap.c +++ b/trunk/drivers/i2c/busses/i2c-omap.c @@ -43,7 +43,6 @@ #include #include #include -#include /* I2C controller revisions */ #define OMAP_I2C_OMAP1_REV_2 0x20 @@ -187,8 +186,9 @@ struct omap_i2c_dev { int reg_shift; /* bit shift for I2C register addresses */ struct completion cmd_complete; struct resource *ioarea; - u32 latency; /* maximum MPU wkup latency */ - struct pm_qos_request pm_qos_request; + u32 latency; /* maximum mpu wkup latency */ + void (*set_mpu_wkup_lat)(struct device *dev, + long latency); u32 speed; /* Speed of bus in kHz */ u32 dtrev; /* extra revision from DT */ u32 flags; @@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx) dev->b_hw = 1; /* Enable hardware fixes */ /* calculate wakeup latency constraint for MPU */ - dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8); + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->threshold) / + (1000 * dev->speed / 8); } /* @@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf = msg->buf; dev->buf_len = msg->len; + /* make sure writes to dev->buf_len are ordered */ + barrier(); + omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); /* Clear the FIFO Buffers */ @@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, */ timeout = wait_for_completion_timeout(&dev->cmd_complete, OMAP_I2C_TIMEOUT); - dev->buf_len = 0; if (timeout == 0) { dev_err(dev->dev, "controller timed out\n"); omap_i2c_init(dev); @@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (r < 0) goto out; - /* - * When waiting for completion of a i2c transfer, we need to - * set a wake up latency constraint for the MPU. This is to - * ensure quick enough wakeup from idle, when transfer - * completes. - */ - if (dev->latency) - pm_qos_add_request(&dev->pm_qos_request, - PM_QOS_CPU_DMA_LATENCY, - dev->latency); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, dev->latency); for (i = 0; i < num; i++) { r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1))); @@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) break; } - if (dev->latency) - pm_qos_remove_request(&dev->pm_qos_request); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, -1); if (r == 0) r = num; @@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev) } else if (pdata != NULL) { dev->speed = pdata->clkrate; dev->flags = pdata->flags; + dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; dev->dtrev = pdata->rev; } @@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev) dev->b_hw = 1; /* Enable hardware fixes */ /* calculate wakeup latency constraint for MPU */ - dev->latency = (1000000 * dev->fifo_size) / - (1000 * dev->speed / 8); + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->fifo_size) / + (1000 * dev->speed / 8); } /* reset ASAP, clearing any IRQs */ diff --git a/trunk/drivers/i2c/busses/i2c-s3c2410.c b/trunk/drivers/i2c/busses/i2c-s3c2410.c index 3e0335f1fc60..9d902725bac9 100644 --- a/trunk/drivers/i2c/busses/i2c-s3c2410.c +++ b/trunk/drivers/i2c/busses/i2c-s3c2410.c @@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio); goto free_gpio; } + i2c->gpios[idx] = gpio; ret = gpio_request(gpio, "i2c-bus"); if (ret) { diff --git a/trunk/drivers/input/input-mt.c b/trunk/drivers/input/input-mt.c index c0ec7d42c3be..1abbc170d8b7 100644 --- a/trunk/drivers/input/input-mt.c +++ b/trunk/drivers/input/input-mt.c @@ -26,10 +26,14 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) * input_mt_init_slots() - initialize MT input slots * @dev: input device supporting MT events and finger tracking * @num_slots: number of slots used by the device + * @flags: mt tasks to handle in core * * This function allocates all necessary memory for MT slot handling * in the input device, prepares the ABS_MT_SLOT and * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers. + * Depending on the flags set, it also performs pointer emulation and + * frame synchronization. + * * May be called repeatedly. Returns -EINVAL if attempting to * reinitialize with a different number of slots. */ diff --git a/trunk/drivers/input/mousedev.c b/trunk/drivers/input/mousedev.c index 8f02e3d0e712..4c842c320c2e 100644 --- a/trunk/drivers/input/mousedev.c +++ b/trunk/drivers/input/mousedev.c @@ -12,8 +12,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define MOUSEDEV_MINOR_BASE 32 -#define MOUSEDEV_MINORS 32 -#define MOUSEDEV_MIX 31 +#define MOUSEDEV_MINORS 31 +#define MOUSEDEV_MIX 63 #include #include diff --git a/trunk/drivers/input/touchscreen/ads7846.c b/trunk/drivers/input/touchscreen/ads7846.c index f02028ec3db6..78e5d9ab0ba7 100644 --- a/trunk/drivers/input/touchscreen/ads7846.c +++ b/trunk/drivers/input/touchscreen/ads7846.c @@ -955,7 +955,8 @@ static int ads7846_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); -static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts) +static int __devinit ads7846_setup_pendown(struct spi_device *spi, + struct ads7846 *ts) { struct ads7846_platform_data *pdata = spi->dev.platform_data; int err; @@ -981,6 +982,9 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784 ts->gpio_pendown = pdata->gpio_pendown; + if (pdata->gpio_pendown_debounce) + gpio_set_debounce(pdata->gpio_pendown, + pdata->gpio_pendown_debounce); } else { dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); return -EINVAL; diff --git a/trunk/drivers/iommu/intel-iommu.c b/trunk/drivers/iommu/intel-iommu.c index d4a4cd445cab..0badfa48b32b 100644 --- a/trunk/drivers/iommu/intel-iommu.c +++ b/trunk/drivers/iommu/intel-iommu.c @@ -4108,7 +4108,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to) static int intel_iommu_add_device(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct pci_dev *bridge, *dma_pdev; + struct pci_dev *bridge, *dma_pdev = NULL; struct iommu_group *group; int ret; @@ -4122,7 +4122,7 @@ static int intel_iommu_add_device(struct device *dev) dma_pdev = pci_get_domain_bus_and_slot( pci_domain_nr(pdev->bus), bridge->subordinate->number, 0); - else + if (!dma_pdev) dma_pdev = pci_dev_get(bridge); } else dma_pdev = pci_dev_get(pdev); diff --git a/trunk/drivers/iommu/tegra-smmu.c b/trunk/drivers/iommu/tegra-smmu.c index a649f146d17b..c0f7a4266263 100644 --- a/trunk/drivers/iommu/tegra-smmu.c +++ b/trunk/drivers/iommu/tegra-smmu.c @@ -1054,6 +1054,7 @@ static int smmu_debugfs_stats_show(struct seq_file *s, void *v) stats[i], val, offs); } seq_printf(s, "\n"); + dput(dent); return 0; } diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index 02db9183ca01..77e6eff41cae 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -740,8 +740,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue) if (!md_in_flight(md)) wake_up(&md->wait); + /* + * Run this off this callpath, as drivers could invoke end_io while + * inside their request_fn (and holding the queue lock). Calling + * back into ->request_fn() could deadlock attempting to grab the + * queue lock again. + */ if (run_queue) - blk_run_queue(md->queue); + blk_run_queue_async(md->queue); /* * dm_put() must be at the end of this function. See the comment above diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 9ab768acfb62..61200717687b 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -1817,10 +1817,10 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev) memset(bbp, 0xff, PAGE_SIZE); for (i = 0 ; i < bb->count ; i++) { - u64 internal_bb = *p++; + u64 internal_bb = p[i]; u64 store_bb = ((BB_OFFSET(internal_bb) << 10) | BB_LEN(internal_bb)); - *bbp++ = cpu_to_le64(store_bb); + bbp[i] = cpu_to_le64(store_bb); } bb->changed = 0; if (read_seqretry(&bb->lock, seq)) @@ -5294,7 +5294,7 @@ void md_stop_writes(struct mddev *mddev) } EXPORT_SYMBOL_GPL(md_stop_writes); -void md_stop(struct mddev *mddev) +static void __md_stop(struct mddev *mddev) { mddev->ready = 0; mddev->pers->stop(mddev); @@ -5304,6 +5304,18 @@ void md_stop(struct mddev *mddev) mddev->pers = NULL; clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); } + +void md_stop(struct mddev *mddev) +{ + /* stop the array and free an attached data structures. + * This is called from dm-raid + */ + __md_stop(mddev); + bitmap_destroy(mddev); + if (mddev->bio_set) + bioset_free(mddev->bio_set); +} + EXPORT_SYMBOL_GPL(md_stop); static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) @@ -5364,7 +5376,7 @@ static int do_md_stop(struct mddev * mddev, int mode, set_disk_ro(disk, 0); __md_stop_writes(mddev); - md_stop(mddev); + __md_stop(mddev); mddev->queue->merge_bvec_fn = NULL; mddev->queue->backing_dev_info.congested_fn = NULL; @@ -7936,9 +7948,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, sector_t *first_bad, int *bad_sectors) { int hi; - int lo = 0; + int lo; u64 *p = bb->page; - int rv = 0; + int rv; sector_t target = s + sectors; unsigned seq; @@ -7953,7 +7965,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, retry: seq = read_seqbegin(&bb->lock); - + lo = 0; + rv = 0; hi = bb->count; /* Binary search between lo and hi for 'target' diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index d1295aff4173..0d5d0ff2c0f7 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -499,7 +499,7 @@ static void raid10_end_write_request(struct bio *bio, int error) */ one_write_done(r10_bio); if (dec_rdev) - rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); + rdev_dec_pending(rdev, conf->mddev); } /* @@ -1334,18 +1334,21 @@ static void make_request(struct mddev *mddev, struct bio * bio) blocked_rdev = rrdev; break; } + if (rdev && (test_bit(Faulty, &rdev->flags) + || test_bit(Unmerged, &rdev->flags))) + rdev = NULL; if (rrdev && (test_bit(Faulty, &rrdev->flags) || test_bit(Unmerged, &rrdev->flags))) rrdev = NULL; r10_bio->devs[i].bio = NULL; r10_bio->devs[i].repl_bio = NULL; - if (!rdev || test_bit(Faulty, &rdev->flags) || - test_bit(Unmerged, &rdev->flags)) { + + if (!rdev && !rrdev) { set_bit(R10BIO_Degraded, &r10_bio->state); continue; } - if (test_bit(WriteErrorSeen, &rdev->flags)) { + if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) { sector_t first_bad; sector_t dev_sector = r10_bio->devs[i].addr; int bad_sectors; @@ -1387,8 +1390,10 @@ static void make_request(struct mddev *mddev, struct bio * bio) max_sectors = good_sectors; } } - r10_bio->devs[i].bio = bio; - atomic_inc(&rdev->nr_pending); + if (rdev) { + r10_bio->devs[i].bio = bio; + atomic_inc(&rdev->nr_pending); + } if (rrdev) { r10_bio->devs[i].repl_bio = bio; atomic_inc(&rrdev->nr_pending); @@ -1444,69 +1449,71 @@ static void make_request(struct mddev *mddev, struct bio * bio) for (i = 0; i < conf->copies; i++) { struct bio *mbio; int d = r10_bio->devs[i].devnum; - if (!r10_bio->devs[i].bio) - continue; + if (r10_bio->devs[i].bio) { + struct md_rdev *rdev = conf->mirrors[d].rdev; + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr+ + choose_data_offset(r10_bio, + rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; + mbio->bi_private = r10_bio; - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].bio = mbio; + atomic_inc(&r10_bio->remaining); - mbio->bi_sector = (r10_bio->devs[i].addr+ - choose_data_offset(r10_bio, - conf->mirrors[d].rdev)); - mbio->bi_bdev = conf->mirrors[d].rdev->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; - mbio->bi_private = r10_bio; + cb = blk_check_plugged(raid10_unplug, mddev, + sizeof(*plug)); + if (cb) + plug = container_of(cb, struct raid10_plug_cb, + cb); + else + plug = NULL; + spin_lock_irqsave(&conf->device_lock, flags); + if (plug) { + bio_list_add(&plug->pending, mbio); + plug->pending_cnt++; + } else { + bio_list_add(&conf->pending_bio_list, mbio); + conf->pending_count++; + } + spin_unlock_irqrestore(&conf->device_lock, flags); + if (!plug) + md_wakeup_thread(mddev->thread); + } - atomic_inc(&r10_bio->remaining); + if (r10_bio->devs[i].repl_bio) { + struct md_rdev *rdev = conf->mirrors[d].replacement; + if (rdev == NULL) { + /* Replacement just got moved to main 'rdev' */ + smp_mb(); + rdev = conf->mirrors[d].rdev; + } + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].repl_bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr + + choose_data_offset( + r10_bio, rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; + mbio->bi_private = r10_bio; - cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug)); - if (cb) - plug = container_of(cb, struct raid10_plug_cb, cb); - else - plug = NULL; - spin_lock_irqsave(&conf->device_lock, flags); - if (plug) { - bio_list_add(&plug->pending, mbio); - plug->pending_cnt++; - } else { + atomic_inc(&r10_bio->remaining); + spin_lock_irqsave(&conf->device_lock, flags); bio_list_add(&conf->pending_bio_list, mbio); conf->pending_count++; + spin_unlock_irqrestore(&conf->device_lock, flags); + if (!mddev_check_plugged(mddev)) + md_wakeup_thread(mddev->thread); } - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!plug) - md_wakeup_thread(mddev->thread); - - if (!r10_bio->devs[i].repl_bio) - continue; - - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].repl_bio = mbio; - - /* We are actively writing to the original device - * so it cannot disappear, so the replacement cannot - * become NULL here - */ - mbio->bi_sector = (r10_bio->devs[i].addr + - choose_data_offset( - r10_bio, - conf->mirrors[d].replacement)); - mbio->bi_bdev = conf->mirrors[d].replacement->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; - mbio->bi_private = r10_bio; - - atomic_inc(&r10_bio->remaining); - spin_lock_irqsave(&conf->device_lock, flags); - bio_list_add(&conf->pending_bio_list, mbio); - conf->pending_count++; - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!mddev_check_plugged(mddev)) - md_wakeup_thread(mddev->thread); } /* Don't remove the bias on 'remaining' (one_write_done) until diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index c5439dce0295..a4502686e7a8 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -2774,10 +2774,12 @@ static void handle_stripe_clean_event(struct r5conf *conf, dev = &sh->dev[i]; if (!test_bit(R5_LOCKED, &dev->flags) && (test_bit(R5_UPTODATE, &dev->flags) || - test_and_clear_bit(R5_Discard, &dev->flags))) { + test_bit(R5_Discard, &dev->flags))) { /* We can return any write requests */ struct bio *wbi, *wbi2; pr_debug("Return write for disc %d\n", i); + if (test_and_clear_bit(R5_Discard, &dev->flags)) + clear_bit(R5_UPTODATE, &dev->flags); wbi = dev->written; dev->written = NULL; while (wbi && wbi->bi_sector < @@ -2795,7 +2797,8 @@ static void handle_stripe_clean_event(struct r5conf *conf, !test_bit(STRIPE_DEGRADED, &sh->state), 0); } - } + } else if (test_bit(R5_Discard, &sh->dev[i].flags)) + clear_bit(R5_Discard, &sh->dev[i].flags); if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state)) if (atomic_dec_and_test(&conf->pending_full_writes)) @@ -3490,40 +3493,6 @@ static void handle_stripe(struct stripe_head *sh) handle_failed_sync(conf, sh, &s); } - /* - * might be able to return some write requests if the parity blocks - * are safe, or on a failed drive - */ - pdev = &sh->dev[sh->pd_idx]; - s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx) - || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx); - qdev = &sh->dev[sh->qd_idx]; - s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx) - || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx) - || conf->level < 6; - - if (s.written && - (s.p_failed || ((test_bit(R5_Insync, &pdev->flags) - && !test_bit(R5_LOCKED, &pdev->flags) - && (test_bit(R5_UPTODATE, &pdev->flags) || - test_bit(R5_Discard, &pdev->flags))))) && - (s.q_failed || ((test_bit(R5_Insync, &qdev->flags) - && !test_bit(R5_LOCKED, &qdev->flags) - && (test_bit(R5_UPTODATE, &qdev->flags) || - test_bit(R5_Discard, &qdev->flags)))))) - handle_stripe_clean_event(conf, sh, disks, &s.return_bi); - - /* Now we might consider reading some blocks, either to check/generate - * parity, or to satisfy requests - * or to load a block that is being partially written. - */ - if (s.to_read || s.non_overwrite - || (conf->level == 6 && s.to_write && s.failed) - || (s.syncing && (s.uptodate + s.compute < disks)) - || s.replacing - || s.expanding) - handle_stripe_fill(sh, &s, disks); - /* Now we check to see if any write operations have recently * completed */ @@ -3561,6 +3530,40 @@ static void handle_stripe(struct stripe_head *sh) s.dec_preread_active = 1; } + /* + * might be able to return some write requests if the parity blocks + * are safe, or on a failed drive + */ + pdev = &sh->dev[sh->pd_idx]; + s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx) + || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx); + qdev = &sh->dev[sh->qd_idx]; + s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx) + || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx) + || conf->level < 6; + + if (s.written && + (s.p_failed || ((test_bit(R5_Insync, &pdev->flags) + && !test_bit(R5_LOCKED, &pdev->flags) + && (test_bit(R5_UPTODATE, &pdev->flags) || + test_bit(R5_Discard, &pdev->flags))))) && + (s.q_failed || ((test_bit(R5_Insync, &qdev->flags) + && !test_bit(R5_LOCKED, &qdev->flags) + && (test_bit(R5_UPTODATE, &qdev->flags) || + test_bit(R5_Discard, &qdev->flags)))))) + handle_stripe_clean_event(conf, sh, disks, &s.return_bi); + + /* Now we might consider reading some blocks, either to check/generate + * parity, or to satisfy requests + * or to load a block that is being partially written. + */ + if (s.to_read || s.non_overwrite + || (conf->level == 6 && s.to_write && s.failed) + || (s.syncing && (s.uptodate + s.compute < disks)) + || s.replacing + || s.expanding) + handle_stripe_fill(sh, &s, disks); + /* Now to consider new write requests and what else, if anything * should be read. We do not handle new writes when: * 1/ A 'write' operation (copy+xor) is already in flight. @@ -5529,6 +5532,10 @@ static int run(struct mddev *mddev) * discard data disk but write parity disk */ stripe = stripe * PAGE_SIZE; + /* Round up to power of 2, as discard handling + * currently assumes that */ + while ((stripe-1) & stripe) + stripe = (stripe | (stripe-1)) + 1; mddev->queue->limits.discard_alignment = stripe; mddev->queue->limits.discard_granularity = stripe; /* diff --git a/trunk/drivers/mtd/devices/slram.c b/trunk/drivers/mtd/devices/slram.c index 8f52fc858e48..5a5cd2ace4a6 100644 --- a/trunk/drivers/mtd/devices/slram.c +++ b/trunk/drivers/mtd/devices/slram.c @@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) if (*(szlength) != '+') { devlength = simple_strtoul(szlength, &buffer, 0); - devlength = handle_unit(devlength, buffer) - devstart; + devlength = handle_unit(devlength, buffer); if (devlength < devstart) goto err_out; diff --git a/trunk/drivers/mtd/nand/nand_base.c b/trunk/drivers/mtd/nand/nand_base.c index ec6841d8e956..1a03b7f673ce 100644 --- a/trunk/drivers/mtd/nand/nand_base.c +++ b/trunk/drivers/mtd/nand/nand_base.c @@ -2983,13 +2983,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, /* * Field definitions are in the following datasheets: * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) - * New style (6 byte ID): Samsung K9GAG08U0F (p.44) + * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) * Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) * - * Check for ID length, cell type, and Hynix/Samsung ID to decide what - * to do. + * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung + * ID to decide what to do. */ - if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) { + if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && + (chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + id_data[5] != 0x00) { /* Calc pagesize */ mtd->writesize = 2048 << (extid & 0x03); extid >>= 2; diff --git a/trunk/drivers/mtd/ofpart.c b/trunk/drivers/mtd/ofpart.c index 64be8f0848b0..d9127e2ed808 100644 --- a/trunk/drivers/mtd/ofpart.c +++ b/trunk/drivers/mtd/ofpart.c @@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, nr_parts = plen / sizeof(part[0]); *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); - if (!pparts) + if (!*pparts) return -ENOMEM; names = of_get_property(dp, "partition-names", &plen); diff --git a/trunk/drivers/mtd/onenand/onenand_base.c b/trunk/drivers/mtd/onenand/onenand_base.c index 7153e0d27101..b3f41f200622 100644 --- a/trunk/drivers/mtd/onenand/onenand_base.c +++ b/trunk/drivers/mtd/onenand/onenand_base.c @@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int * flexonenand_set_boundary - Writes the SLC boundary * @param mtd - mtd info structure */ -int flexonenand_set_boundary(struct mtd_info *mtd, int die, +static int flexonenand_set_boundary(struct mtd_info *mtd, int die, int boundary, int lock) { struct onenand_chip *this = mtd->priv; diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index b2530b002125..5f5b69f37d2e 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -1379,6 +1379,8 @@ static void bond_compute_features(struct bonding *bond) struct net_device *bond_dev = bond->dev; netdev_features_t vlan_features = BOND_VLAN_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; + unsigned int gso_max_size = GSO_MAX_SIZE; + u16 gso_max_segs = GSO_MAX_SEGS; int i; unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE; @@ -1394,11 +1396,16 @@ static void bond_compute_features(struct bonding *bond) dst_release_flag &= slave->dev->priv_flags; if (slave->dev->hard_header_len > max_hard_header_len) max_hard_header_len = slave->dev->hard_header_len; + + gso_max_size = min(gso_max_size, slave->dev->gso_max_size); + gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs); } done: bond_dev->vlan_features = vlan_features; bond_dev->hard_header_len = max_hard_header_len; + bond_dev->gso_max_segs = gso_max_segs; + netif_set_gso_max_size(bond_dev, gso_max_size); flags = bond_dev->priv_flags & ~IFF_XMIT_DST_RELEASE; bond_dev->priv_flags = flags | dst_release_flag; diff --git a/trunk/drivers/net/ethernet/8390/ne.c b/trunk/drivers/net/ethernet/8390/ne.c index d04911d33b64..47618e505355 100644 --- a/trunk/drivers/net/ethernet/8390/ne.c +++ b/trunk/drivers/net/ethernet/8390/ne.c @@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev) dev->irq = irq[this_dev]; dev->mem_end = bad[this_dev]; } + SET_NETDEV_DEV(dev, &pdev->dev); err = do_ne_probe(dev); if (err) { free_netdev(dev); diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index bd1fd3d87c24..01611b33a93d 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -9545,10 +9545,13 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) */ static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp) { - u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); - if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { - BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); - REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp)); + if (!CHIP_IS_E1x(bp)) { + u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); + if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { + BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); + REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, + 1 << BP_FUNC(bp)); + } } } diff --git a/trunk/drivers/net/ethernet/realtek/8139cp.c b/trunk/drivers/net/ethernet/realtek/8139cp.c index 1c818254b7be..b01f83a044c4 100644 --- a/trunk/drivers/net/ethernet/realtek/8139cp.c +++ b/trunk/drivers/net/ethernet/realtek/8139cp.c @@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp) cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); - cpw32_f(HiTxRingAddr, 0); - cpw32_f(HiTxRingAddr + 4, 0); - - ring_dma = cp->ring_dma; - cpw32_f(RxRingAddr, ring_dma & 0xffffffff); - cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); - - ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; - cpw32_f(TxRingAddr, ring_dma & 0xffffffff); - cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); - cp_start_hw(cp); cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ @@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp) cpw8(Config5, cpr8(Config5) & PMEStatus); + cpw32_f(HiTxRingAddr, 0); + cpw32_f(HiTxRingAddr + 4, 0); + + ring_dma = cp->ring_dma; + cpw32_f(RxRingAddr, ring_dma & 0xffffffff); + cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); + + ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; + cpw32_f(TxRingAddr, ring_dma & 0xffffffff); + cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); + cpw16(MultiIntr, 0); cpw8_f(Cfg9346, Cfg9346_Lock); diff --git a/trunk/drivers/net/ethernet/sis/sis900.c b/trunk/drivers/net/ethernet/sis/sis900.c index fb9f6b38511f..edf5edb13140 100644 --- a/trunk/drivers/net/ethernet/sis/sis900.c +++ b/trunk/drivers/net/ethernet/sis/sis900.c @@ -2479,7 +2479,7 @@ static int sis900_resume(struct pci_dev *pci_dev) netif_start_queue(net_dev); /* Workaround for EDB */ - sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); + sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); /* Enable all known interrupts by setting the interrupt mask. */ sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); diff --git a/trunk/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/trunk/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 77e6db9dcfed..a788501e978e 100644 --- a/trunk/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/trunk/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -894,6 +894,8 @@ static irqreturn_t axienet_rx_irq(int irq, void *_ndev) return IRQ_HANDLED; } +static void axienet_dma_err_handler(unsigned long data); + /** * axienet_open - Driver open routine. * @ndev: Pointer to net_device structure diff --git a/trunk/drivers/net/ethernet/xscale/ixp4xx_eth.c b/trunk/drivers/net/ethernet/xscale/ixp4xx_eth.c index 98934bdf6acf..477d6729b17f 100644 --- a/trunk/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/trunk/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1102,10 +1102,12 @@ static int init_queues(struct port *port) { int i; - if (!ports_open) - if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, - POOL_ALLOC_SIZE, 32, 0))) + if (!ports_open) { + dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev, + POOL_ALLOC_SIZE, 32, 0); + if (!dma_pool) return -ENOMEM; + } if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, &port->desc_tab_phys))) diff --git a/trunk/drivers/net/irda/sir_dev.c b/trunk/drivers/net/irda/sir_dev.c index 5039f08f5a5b..43e9ab4f4d7e 100644 --- a/trunk/drivers/net/irda/sir_dev.c +++ b/trunk/drivers/net/irda/sir_dev.c @@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work) break; case SIRDEV_STATE_DONGLE_SPEED: - if (dev->dongle_drv->reset) { + if (dev->dongle_drv->set_speed) { ret = dev->dongle_drv->set_speed(dev, fsm->param); if (ret < 0) { fsm->result = ret; diff --git a/trunk/drivers/net/phy/mdio-gpio.c b/trunk/drivers/net/phy/mdio-gpio.c index 899274f2f9b1..2ed1140df3e9 100644 --- a/trunk/drivers/net/phy/mdio-gpio.c +++ b/trunk/drivers/net/phy/mdio-gpio.c @@ -185,17 +185,20 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev) { struct mdio_gpio_platform_data *pdata; struct mii_bus *new_bus; - int ret; + int ret, bus_id; - if (pdev->dev.of_node) + if (pdev->dev.of_node) { pdata = mdio_gpio_of_get_data(pdev); - else + bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio"); + } else { pdata = pdev->dev.platform_data; + bus_id = pdev->id; + } if (!pdata) return -ENODEV; - new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id); + new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, bus_id); if (!new_bus) return -ENODEV; diff --git a/trunk/drivers/net/team/team_mode_broadcast.c b/trunk/drivers/net/team/team_mode_broadcast.c index 9db0171e9366..c5db428e73fa 100644 --- a/trunk/drivers/net/team/team_mode_broadcast.c +++ b/trunk/drivers/net/team/team_mode_broadcast.c @@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) if (last) { skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2) { - ret = team_dev_queue_xmit(team, last, - skb2); + ret = !team_dev_queue_xmit(team, last, + skb2); if (!sum_ret) sum_ret = ret; } @@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) } } if (last) { - ret = team_dev_queue_xmit(team, last, skb); + ret = !team_dev_queue_xmit(team, last, skb); if (!sum_ret) sum_ret = ret; } diff --git a/trunk/drivers/net/wan/ixp4xx_hss.c b/trunk/drivers/net/wan/ixp4xx_hss.c index 3f575afd8cfc..e9a3da588e95 100644 --- a/trunk/drivers/net/wan/ixp4xx_hss.c +++ b/trunk/drivers/net/wan/ixp4xx_hss.c @@ -969,10 +969,12 @@ static int init_hdlc_queues(struct port *port) { int i; - if (!ports_open) - if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, - POOL_ALLOC_SIZE, 32, 0))) + if (!ports_open) { + dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev, + POOL_ALLOC_SIZE, 32, 0); + if (!dma_pool) return -ENOMEM; + } if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, &port->desc_tab_phys))) diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 8e1559aba495..1829b445d0b0 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -1456,7 +1456,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) switch (type) { case ATH9K_RESET_POWER_ON: ret = ath9k_hw_set_reset_power_on(ah); - if (!ret) + if (ret) ah->reset_power_on = true; break; case ATH9K_RESET_WARM: diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c index fa4d1b8cd9f6..2d9eee93c743 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -1354,6 +1354,20 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, vif_priv->ctx = ctx; ctx->vif = vif; + /* + * In SNIFFER device type, the firmware reports the FCS to + * the host, rather than snipping it off. Unfortunately, + * mac80211 doesn't (yet) provide a per-packet flag for + * this, so that we have to set the hardware flag based + * on the interfaces added. As the monitor interface can + * only be present by itself, and will be removed before + * other interfaces are added, this is safe. + */ + if (vif->type == NL80211_IFTYPE_MONITOR) + priv->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS; + else + priv->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; + err = iwl_setup_interface(priv, ctx); if (!err || reset) goto out; diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c b/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c index 105e3af3c621..79a4ddc002d3 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u16 rd_ptr, wr_ptr; - int n_bd = trans_pcie->txq[txq_id].q.n_bd; if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { WARN_ONCE(1, "queue %d not used", txq_id); return; } - rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); - wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); - - WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", - txq_id, rd_ptr, wr_ptr); - iwl_txq_set_inactive(trans, txq_id); IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); } diff --git a/trunk/drivers/net/wireless/mwifiex/cmdevt.c b/trunk/drivers/net/wireless/mwifiex/cmdevt.c index 8d465107f52b..ae9010ed58de 100644 --- a/trunk/drivers/net/wireless/mwifiex/cmdevt.c +++ b/trunk/drivers/net/wireless/mwifiex/cmdevt.c @@ -890,9 +890,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) return; } cmd_node = adapter->curr_cmd; - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -ETIMEDOUT; - if (cmd_node) { adapter->dbg.timeout_cmd_id = adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; @@ -938,6 +935,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context) dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", adapter->ps_mode, adapter->ps_state); + + if (cmd_node->wait_q_enabled) { + adapter->cmd_wait_q.status = -ETIMEDOUT; + wake_up_interruptible(&adapter->cmd_wait_q.wait); + mwifiex_cancel_pending_ioctl(adapter); + /* reset cmd_sent flag to unblock new commands */ + adapter->cmd_sent = false; + } } if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) mwifiex_init_fw_complete(adapter); diff --git a/trunk/drivers/net/wireless/mwifiex/sdio.c b/trunk/drivers/net/wireless/mwifiex/sdio.c index fc8a9bfa1248..82cf0fa2d9f6 100644 --- a/trunk/drivers/net/wireless/mwifiex/sdio.c +++ b/trunk/drivers/net/wireless/mwifiex/sdio.c @@ -161,7 +161,6 @@ static int mwifiex_sdio_suspend(struct device *dev) struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; - int hs_actived = 0; int i; int ret = 0; @@ -188,12 +187,14 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; /* Enable the Host Sleep */ - hs_actived = mwifiex_enable_hs(adapter); - if (hs_actived) { - pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (!mwifiex_enable_hs(adapter)) { + dev_err(adapter->dev, "cmd: failed to suspend\n"); + return -EFAULT; } + dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + /* Indicate device suspended */ adapter->is_suspended = true; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 9970c2b1b199..b7e6607e6b6d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { /*=== Customer ID ===*/ /****** 8188CU ********/ {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ + {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ diff --git a/trunk/drivers/net/xen-netfront.c b/trunk/drivers/net/xen-netfront.c index caa011008cd0..fc24eb9b3948 100644 --- a/trunk/drivers/net/xen-netfront.c +++ b/trunk/drivers/net/xen-netfront.c @@ -452,29 +452,85 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, /* Grant backend access to each skb fragment page. */ for (i = 0; i < frags; i++) { skb_frag_t *frag = skb_shinfo(skb)->frags + i; + struct page *page = skb_frag_page(frag); - tx->flags |= XEN_NETTXF_more_data; + len = skb_frag_size(frag); + offset = frag->page_offset; - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); - np->tx_skbs[id].skb = skb_get(skb); - tx = RING_GET_REQUEST(&np->tx, prod++); - tx->id = id; - ref = gnttab_claim_grant_reference(&np->gref_tx_head); - BUG_ON((signed short)ref < 0); + /* Data must not cross a page boundary. */ + BUG_ON(len + offset > PAGE_SIZE<xbdev->otherend_id, - mfn, GNTMAP_readonly); + /* Skip unused frames from start of page */ + page += offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; - tx->gref = np->grant_tx_ref[id] = ref; - tx->offset = frag->page_offset; - tx->size = skb_frag_size(frag); - tx->flags = 0; + while (len > 0) { + unsigned long bytes; + + BUG_ON(offset >= PAGE_SIZE); + + bytes = PAGE_SIZE - offset; + if (bytes > len) + bytes = len; + + tx->flags |= XEN_NETTXF_more_data; + + id = get_id_from_freelist(&np->tx_skb_freelist, + np->tx_skbs); + np->tx_skbs[id].skb = skb_get(skb); + tx = RING_GET_REQUEST(&np->tx, prod++); + tx->id = id; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + + mfn = pfn_to_mfn(page_to_pfn(page)); + gnttab_grant_foreign_access_ref(ref, + np->xbdev->otherend_id, + mfn, GNTMAP_readonly); + + tx->gref = np->grant_tx_ref[id] = ref; + tx->offset = offset; + tx->size = bytes; + tx->flags = 0; + + offset += bytes; + len -= bytes; + + /* Next frame */ + if (offset == PAGE_SIZE && len) { + BUG_ON(!PageCompound(page)); + page++; + offset = 0; + } + } } np->tx.req_prod_pvt = prod; } +/* + * Count how many ring slots are required to send the frags of this + * skb. Each frag might be a compound page. + */ +static int xennet_count_skb_frag_slots(struct sk_buff *skb) +{ + int i, frags = skb_shinfo(skb)->nr_frags; + int pages = 0; + + for (i = 0; i < frags; i++) { + skb_frag_t *frag = skb_shinfo(skb)->frags + i; + unsigned long size = skb_frag_size(frag); + unsigned long offset = frag->page_offset; + + /* Skip unused frames from start of page */ + offset &= ~PAGE_MASK; + + pages += PFN_UP(offset + size); + } + + return pages; +} + static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned short id; @@ -487,23 +543,23 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) grant_ref_t ref; unsigned long mfn; int notify; - int frags = skb_shinfo(skb)->nr_frags; + int slots; unsigned int offset = offset_in_page(data); unsigned int len = skb_headlen(skb); unsigned long flags; - frags += DIV_ROUND_UP(offset + len, PAGE_SIZE); - if (unlikely(frags > MAX_SKB_FRAGS + 1)) { - printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n", - frags); - dump_stack(); + slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) + + xennet_count_skb_frag_slots(skb); + if (unlikely(slots > MAX_SKB_FRAGS + 1)) { + net_alert_ratelimited( + "xennet: skb rides the rocket: %d slots\n", slots); goto drop; } spin_lock_irqsave(&np->tx_lock, flags); if (unlikely(!netif_carrier_ok(dev) || - (frags > 1 && !xennet_can_sg(dev)) || + (slots > 1 && !xennet_can_sg(dev)) || netif_needs_gso(skb, netif_skb_features(skb)))) { spin_unlock_irqrestore(&np->tx_lock, flags); goto drop; diff --git a/trunk/drivers/nfc/pn533.c b/trunk/drivers/nfc/pn533.c index 97c440a8cd61..30ae18a03a9c 100644 --- a/trunk/drivers/nfc/pn533.c +++ b/trunk/drivers/nfc/pn533.c @@ -698,13 +698,14 @@ static void pn533_wq_cmd(struct work_struct *work) cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue); + list_del(&cmd->queue); + mutex_unlock(&dev->cmd_lock); __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, cmd->in_frame_len, cmd->cmd_complete, cmd->arg, cmd->flags); - list_del(&cmd->queue); kfree(cmd); } @@ -1678,11 +1679,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { - struct pn533_cmd_jump_dep *cmd; struct pn533_cmd_jump_dep_response *resp; struct nfc_target nfc_target; u8 target_gt_len; int rc; + struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg; + u8 active = cmd->active; + + kfree(arg); if (params_len == -ENOENT) { nfc_dev_dbg(&dev->interface->dev, ""); @@ -1704,7 +1708,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, } resp = (struct pn533_cmd_jump_dep_response *) params; - cmd = (struct pn533_cmd_jump_dep *) arg; rc = resp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { nfc_dev_err(&dev->interface->dev, @@ -1734,7 +1737,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (rc == 0) rc = nfc_dep_link_is_up(dev->nfc_dev, dev->nfc_dev->targets[0].idx, - !cmd->active, NFC_RF_INITIATOR); + !active, NFC_RF_INITIATOR); return 0; } @@ -1819,12 +1822,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, dev->in_maxlen, pn533_in_dep_link_up_complete, cmd, GFP_KERNEL); - if (rc) - goto out; - - -out: - kfree(cmd); + if (rc < 0) + kfree(cmd); return rc; } @@ -2078,8 +2077,12 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, static int pn533_tm_send_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { + struct sk_buff *skb_out = arg; + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_kfree_skb(skb_out); + if (params_len < 0) { nfc_dev_err(&dev->interface->dev, "Error %d when sending data", @@ -2117,7 +2120,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, dev->in_maxlen, pn533_tm_send_complete, - NULL, GFP_KERNEL); + skb, GFP_KERNEL); if (rc) { nfc_dev_err(&dev->interface->dev, "Error %d when trying to send data", rc); diff --git a/trunk/drivers/pinctrl/Kconfig b/trunk/drivers/pinctrl/Kconfig index d96caefd914a..aeecf0f72cad 100644 --- a/trunk/drivers/pinctrl/Kconfig +++ b/trunk/drivers/pinctrl/Kconfig @@ -178,7 +178,7 @@ config PINCTRL_COH901 ports of 8 GPIO pins each. config PINCTRL_SAMSUNG - bool "Samsung pinctrl driver" + bool depends on OF && GPIOLIB select PINMUX select PINCONF diff --git a/trunk/drivers/scsi/isci/request.c b/trunk/drivers/scsi/isci/request.c index c1bafc3f3fb1..9594ab62702b 100644 --- a/trunk/drivers/scsi/isci/request.c +++ b/trunk/drivers/scsi/isci/request.c @@ -1972,7 +1972,7 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_index, (void **)&frame_buffer); - sci_controller_copy_sata_response(&ireq->stp.req, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); diff --git a/trunk/drivers/scsi/scsi.c b/trunk/drivers/scsi/scsi.c index 2936b447cae9..2c0d0ec8150b 100644 --- a/trunk/drivers/scsi/scsi.c +++ b/trunk/drivers/scsi/scsi.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -1061,6 +1062,50 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, } EXPORT_SYMBOL_GPL(scsi_get_vpd_page); +/** + * scsi_report_opcode - Find out if a given command opcode is supported + * @sdev: scsi device to query + * @buffer: scratch buffer (must be at least 20 bytes long) + * @len: length of buffer + * @opcode: opcode for command to look up + * + * Uses the REPORT SUPPORTED OPERATION CODES to look up the given + * opcode. Returns 0 if RSOC fails or if the command opcode is + * unsupported. Returns 1 if the device claims to support the command. + */ +int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, + unsigned int len, unsigned char opcode) +{ + unsigned char cmd[16]; + struct scsi_sense_hdr sshdr; + int result; + + if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3) + return 0; + + memset(cmd, 0, 16); + cmd[0] = MAINTENANCE_IN; + cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES; + cmd[2] = 1; /* One command format */ + cmd[3] = opcode; + put_unaligned_be32(len, &cmd[6]); + memset(buffer, 0, len); + + result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, + &sshdr, 30 * HZ, 3, NULL); + + if (result && scsi_sense_valid(&sshdr) && + sshdr.sense_key == ILLEGAL_REQUEST && + (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00) + return 0; + + if ((buffer[1] & 3) == 3) /* Command supported */ + return 1; + + return 0; +} +EXPORT_SYMBOL(scsi_report_opcode); + /** * scsi_device_get - get an additional reference to a scsi_device * @sdev: device to get a reference to diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index da36a3a81a9e..9032e910bca3 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -900,11 +900,23 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) action = ACTION_FAIL; error = -EILSEQ; /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */ - } else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) && - (cmd->cmnd[0] == UNMAP || - cmd->cmnd[0] == WRITE_SAME_16 || - cmd->cmnd[0] == WRITE_SAME)) { - description = "Discard failure"; + } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) { + switch (cmd->cmnd[0]) { + case UNMAP: + description = "Discard failure"; + break; + case WRITE_SAME: + case WRITE_SAME_16: + if (cmd->cmnd[1] & 0x8) + description = "Discard failure"; + else + description = + "Write same failure"; + break; + default: + description = "Invalid command failure"; + break; + } action = ACTION_FAIL; error = -EREMOTEIO; } else diff --git a/trunk/drivers/scsi/sd.c b/trunk/drivers/scsi/sd.c index 12f6fdfc1147..352bc77b7c88 100644 --- a/trunk/drivers/scsi/sd.c +++ b/trunk/drivers/scsi/sd.c @@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); #endif static void sd_config_discard(struct scsi_disk *, unsigned int); +static void sd_config_write_same(struct scsi_disk *); static int sd_revalidate_disk(struct gendisk *); static void sd_unlock_native_capacity(struct gendisk *disk); static int sd_probe(struct device *); @@ -395,6 +396,45 @@ sd_store_max_medium_access_timeouts(struct device *dev, return err ? err : count; } +static ssize_t +sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + + return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks); +} + +static ssize_t +sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + struct scsi_device *sdp = sdkp->device; + unsigned long max; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (sdp->type != TYPE_DISK) + return -EINVAL; + + err = kstrtoul(buf, 10, &max); + + if (err) + return err; + + if (max == 0) + sdp->no_write_same = 1; + else if (max <= SD_MAX_WS16_BLOCKS) + sdkp->max_ws_blocks = max; + + sd_config_write_same(sdkp); + + return count; +} + static struct device_attribute sd_disk_attrs[] = { __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, sd_store_cache_type), @@ -410,6 +450,8 @@ static struct device_attribute sd_disk_attrs[] = { __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL), __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode, sd_store_provisioning_mode), + __ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR, + sd_show_write_same_blocks, sd_store_write_same_blocks), __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR, sd_show_max_medium_access_timeouts, sd_store_max_medium_access_timeouts), @@ -561,19 +603,23 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) return; case SD_LBP_UNMAP: - max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff); + max_blocks = min_not_zero(sdkp->max_unmap_blocks, + (u32)SD_MAX_WS16_BLOCKS); break; case SD_LBP_WS16: - max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff); + max_blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS16_BLOCKS); break; case SD_LBP_WS10: - max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff); + max_blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS10_BLOCKS); break; case SD_LBP_ZERO: - max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff); + max_blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS10_BLOCKS); q->limits.discard_zeroes_data = 1; break; } @@ -583,29 +629,26 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) } /** - * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device + * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device * @sdp: scsi device to operate one * @rq: Request to prepare * * Will issue either UNMAP or WRITE SAME(16) depending on preference * indicated by target device. **/ -static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) +static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) { struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); - struct bio *bio = rq->bio; - sector_t sector = bio->bi_sector; - unsigned int nr_sectors = bio_sectors(bio); + sector_t sector = blk_rq_pos(rq); + unsigned int nr_sectors = blk_rq_sectors(rq); + unsigned int nr_bytes = blk_rq_bytes(rq); unsigned int len; int ret; char *buf; struct page *page; - if (sdkp->device->sector_size == 4096) { - sector >>= 3; - nr_sectors >>= 3; - } - + sector >>= ilog2(sdp->sector_size) - 9; + nr_sectors >>= ilog2(sdp->sector_size) - 9; rq->timeout = SD_TIMEOUT; memset(rq->cmd, 0, rq->cmd_len); @@ -660,6 +703,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) blk_add_request_payload(rq, page, len); ret = scsi_setup_blk_pc_cmnd(sdp, rq); rq->buffer = page_address(page); + rq->__data_len = nr_bytes; out: if (ret != BLKPREP_OK) { @@ -669,6 +713,83 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) return ret; } +static void sd_config_write_same(struct scsi_disk *sdkp) +{ + struct request_queue *q = sdkp->disk->queue; + unsigned int logical_block_size = sdkp->device->sector_size; + unsigned int blocks = 0; + + if (sdkp->device->no_write_same) { + sdkp->max_ws_blocks = 0; + goto out; + } + + /* Some devices can not handle block counts above 0xffff despite + * supporting WRITE SAME(16). Consequently we default to 64k + * blocks per I/O unless the device explicitly advertises a + * bigger limit. + */ + if (sdkp->max_ws_blocks == 0) + sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS; + + if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS) + blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS16_BLOCKS); + else + blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS10_BLOCKS); + +out: + blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9)); +} + +/** + * sd_setup_write_same_cmnd - write the same data to multiple blocks + * @sdp: scsi device to operate one + * @rq: Request to prepare + * + * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on + * preference indicated by target device. + **/ +static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) +{ + struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); + struct bio *bio = rq->bio; + sector_t sector = blk_rq_pos(rq); + unsigned int nr_sectors = blk_rq_sectors(rq); + unsigned int nr_bytes = blk_rq_bytes(rq); + int ret; + + if (sdkp->device->no_write_same) + return BLKPREP_KILL; + + BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size); + + sector >>= ilog2(sdp->sector_size) - 9; + nr_sectors >>= ilog2(sdp->sector_size) - 9; + + rq->__data_len = sdp->sector_size; + rq->timeout = SD_WRITE_SAME_TIMEOUT; + memset(rq->cmd, 0, rq->cmd_len); + + if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) { + rq->cmd_len = 16; + rq->cmd[0] = WRITE_SAME_16; + put_unaligned_be64(sector, &rq->cmd[2]); + put_unaligned_be32(nr_sectors, &rq->cmd[10]); + } else { + rq->cmd_len = 10; + rq->cmd[0] = WRITE_SAME; + put_unaligned_be32(sector, &rq->cmd[2]); + put_unaligned_be16(nr_sectors, &rq->cmd[7]); + } + + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + rq->__data_len = nr_bytes; + + return ret; +} + static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) { rq->timeout = SD_FLUSH_TIMEOUT; @@ -712,7 +833,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * block PC requests to make life easier. */ if (rq->cmd_flags & REQ_DISCARD) { - ret = scsi_setup_discard_cmnd(sdp, rq); + ret = sd_setup_discard_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_flags & REQ_WRITE_SAME) { + ret = sd_setup_write_same_cmnd(sdp, rq); goto out; } else if (rq->cmd_flags & REQ_FLUSH) { ret = scsi_setup_flush_cmnd(sdp, rq); @@ -1482,12 +1606,21 @@ static int sd_done(struct scsi_cmnd *SCpnt) unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt); struct scsi_sense_hdr sshdr; struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk); + struct request *req = SCpnt->request; int sense_valid = 0; int sense_deferred = 0; unsigned char op = SCpnt->cmnd[0]; + unsigned char unmap = SCpnt->cmnd[1] & 8; - if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result) - scsi_set_resid(SCpnt, 0); + if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) { + if (!result) { + good_bytes = blk_rq_bytes(req); + scsi_set_resid(SCpnt, 0); + } else { + good_bytes = 0; + scsi_set_resid(SCpnt, blk_rq_bytes(req)); + } + } if (result) { sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); @@ -1536,9 +1669,25 @@ static int sd_done(struct scsi_cmnd *SCpnt) if (sshdr.asc == 0x10) /* DIX: Host detected corruption */ good_bytes = sd_completed_bytes(SCpnt); /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */ - if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) && - (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME)) - sd_config_discard(sdkp, SD_LBP_DISABLE); + if (sshdr.asc == 0x20 || sshdr.asc == 0x24) { + switch (op) { + case UNMAP: + sd_config_discard(sdkp, SD_LBP_DISABLE); + break; + case WRITE_SAME_16: + case WRITE_SAME: + if (unmap) + sd_config_discard(sdkp, SD_LBP_DISABLE); + else { + sdkp->device->no_write_same = 1; + sd_config_write_same(sdkp); + + good_bytes = 0; + req->__data_len = blk_rq_bytes(req); + req->cmd_flags |= REQ_QUIET; + } + } + } break; default: break; @@ -2374,9 +2523,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) if (buffer[3] == 0x3c) { unsigned int lba_count, desc_count; - sdkp->max_ws_blocks = - (u32) min_not_zero(get_unaligned_be64(&buffer[36]), - (u64)0xffffffff); + sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]); if (!sdkp->lbpme) goto out; @@ -2469,6 +2616,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp) kfree(buffer); } +static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) +{ + if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE, + WRITE_SAME_16)) + sdkp->ws16 = 1; +} + static int sd_try_extended_inquiry(struct scsi_device *sdp) { /* @@ -2528,6 +2682,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_write_protect_flag(sdkp, buffer); sd_read_cache_type(sdkp, buffer); sd_read_app_tag_own(sdkp, buffer); + sd_read_write_same(sdkp, buffer); } sdkp->first_scan = 0; @@ -2545,6 +2700,7 @@ static int sd_revalidate_disk(struct gendisk *disk) blk_queue_flush(sdkp->disk->queue, flush); set_capacity(disk, sdkp->capacity); + sd_config_write_same(sdkp); kfree(buffer); out: diff --git a/trunk/drivers/scsi/sd.h b/trunk/drivers/scsi/sd.h index 47c52a6d733c..74a1e4ca5401 100644 --- a/trunk/drivers/scsi/sd.h +++ b/trunk/drivers/scsi/sd.h @@ -14,6 +14,7 @@ #define SD_TIMEOUT (30 * HZ) #define SD_MOD_TIMEOUT (75 * HZ) #define SD_FLUSH_TIMEOUT (60 * HZ) +#define SD_WRITE_SAME_TIMEOUT (120 * HZ) /* * Number of allowed retries @@ -38,6 +39,11 @@ enum { SD_MEMPOOL_SIZE = 2, /* CDB pool size */ }; +enum { + SD_MAX_WS10_BLOCKS = 0xffff, + SD_MAX_WS16_BLOCKS = 0x7fffff, +}; + enum { SD_LBP_FULL = 0, /* Full logical block provisioning */ SD_LBP_UNMAP, /* Use UNMAP command */ @@ -77,6 +83,7 @@ struct scsi_disk { unsigned lbpws : 1; unsigned lbpws10 : 1; unsigned lbpvpd : 1; + unsigned ws16 : 1; }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev) diff --git a/trunk/drivers/usb/storage/scsiglue.c b/trunk/drivers/usb/storage/scsiglue.c index a3d54366afcc..92f35abee92d 100644 --- a/trunk/drivers/usb/storage/scsiglue.c +++ b/trunk/drivers/usb/storage/scsiglue.c @@ -186,6 +186,12 @@ static int slave_configure(struct scsi_device *sdev) /* Some devices don't handle VPD pages correctly */ sdev->skip_vpd_pages = 1; + /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */ + sdev->no_report_opcodes = 1; + + /* Do not attempt to use WRITE SAME */ + sdev->no_write_same = 1; + /* Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. * If this device makes that mistake, tell the sd driver. */ diff --git a/trunk/drivers/video/omap2/dss/dsi.c b/trunk/drivers/video/omap2/dss/dsi.c index d64ac3842884..bee92846cfab 100644 --- a/trunk/drivers/video/omap2/dss/dsi.c +++ b/trunk/drivers/video/omap2/dss/dsi.c @@ -365,11 +365,20 @@ struct platform_device *dsi_get_dsidev_from_id(int module) struct omap_dss_output *out; enum omap_dss_output_id id; - id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + switch (module) { + case 0: + id = OMAP_DSS_OUTPUT_DSI1; + break; + case 1: + id = OMAP_DSS_OUTPUT_DSI2; + break; + default: + return NULL; + } out = omap_dss_get_output(id); - return out->pdev; + return out ? out->pdev : NULL; } static inline void dsi_write_reg(struct platform_device *dsidev, diff --git a/trunk/drivers/video/omap2/dss/dss.c b/trunk/drivers/video/omap2/dss/dss.c index 2ab1c3e96553..5f6eea801b06 100644 --- a/trunk/drivers/video/omap2/dss/dss.c +++ b/trunk/drivers/video/omap2/dss/dss.c @@ -697,11 +697,15 @@ static int dss_get_clocks(void) dss.dss_clk = clk; - clk = clk_get(NULL, dss.feat->clk_name); - if (IS_ERR(clk)) { - DSSERR("Failed to get %s\n", dss.feat->clk_name); - r = PTR_ERR(clk); - goto err; + if (dss.feat->clk_name) { + clk = clk_get(NULL, dss.feat->clk_name); + if (IS_ERR(clk)) { + DSSERR("Failed to get %s\n", dss.feat->clk_name); + r = PTR_ERR(clk); + goto err; + } + } else { + clk = NULL; } dss.dpll4_m4_ck = clk; @@ -805,10 +809,10 @@ static int __init dss_init_features(struct device *dev) if (cpu_is_omap24xx()) src = &omap24xx_dss_feats; - else if (cpu_is_omap34xx()) - src = &omap34xx_dss_feats; else if (cpu_is_omap3630()) src = &omap3630_dss_feats; + else if (cpu_is_omap34xx()) + src = &omap34xx_dss_feats; else if (cpu_is_omap44xx()) src = &omap44xx_dss_feats; else if (soc_is_omap54xx()) diff --git a/trunk/drivers/video/omap2/dss/hdmi.c b/trunk/drivers/video/omap2/dss/hdmi.c index a48a7dd75b33..8c9b8b3b7f77 100644 --- a/trunk/drivers/video/omap2/dss/hdmi.c +++ b/trunk/drivers/video/omap2/dss/hdmi.c @@ -644,8 +644,10 @@ static void hdmi_dump_regs(struct seq_file *s) { mutex_lock(&hdmi.lock); - if (hdmi_runtime_get()) + if (hdmi_runtime_get()) { + mutex_unlock(&hdmi.lock); return; + } hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s); hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); diff --git a/trunk/drivers/video/omap2/omapfb/omapfb-ioctl.c b/trunk/drivers/video/omap2/omapfb/omapfb-ioctl.c index 606b89f12351..d630b26a005c 100644 --- a/trunk/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/trunk/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -787,7 +787,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) case OMAPFB_WAITFORVSYNC: DBG("ioctl WAITFORVSYNC\n"); - if (!display && !display->output && !display->output->manager) { + if (!display || !display->output || !display->output->manager) { r = -EINVAL; break; } diff --git a/trunk/drivers/xen/privcmd.c b/trunk/drivers/xen/privcmd.c index 8adb9cc267f9..71f5c459b088 100644 --- a/trunk/drivers/xen/privcmd.c +++ b/trunk/drivers/xen/privcmd.c @@ -361,13 +361,13 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) down_write(&mm->mmap_sem); vma = find_vma(mm, m.addr); - ret = -EINVAL; if (!vma || vma->vm_ops != &privcmd_vm_ops || (m.addr != vma->vm_start) || ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) || !privcmd_enforce_singleshot_mapping(vma)) { up_write(&mm->mmap_sem); + ret = -EINVAL; goto out; } @@ -383,12 +383,16 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) up_write(&mm->mmap_sem); - if (state.global_error && (version == 1)) { - /* Write back errors in second pass. */ - state.user_mfn = (xen_pfn_t *)m.arr; - state.err = err_array; - ret = traverse_pages(m.num, sizeof(xen_pfn_t), - &pagelist, mmap_return_errors_v1, &state); + if (version == 1) { + if (state.global_error) { + /* Write back errors in second pass. */ + state.user_mfn = (xen_pfn_t *)m.arr; + state.err = err_array; + ret = traverse_pages(m.num, sizeof(xen_pfn_t), + &pagelist, mmap_return_errors_v1, &state); + } else + ret = 0; + } else if (version == 2) { ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); if (ret) diff --git a/trunk/fs/ext3/balloc.c b/trunk/fs/ext3/balloc.c index 7320a66e958f..22548f56197b 100644 --- a/trunk/fs/ext3/balloc.c +++ b/trunk/fs/ext3/balloc.c @@ -2101,8 +2101,9 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range) end = start + (range->len >> sb->s_blocksize_bits) - 1; minlen = range->minlen >> sb->s_blocksize_bits; - if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) || - unlikely(start >= max_blks)) + if (minlen > EXT3_BLOCKS_PER_GROUP(sb) || + start >= max_blks || + range->len < sb->s_blocksize) return -EINVAL; if (end >= max_blks) end = max_blks - 1; diff --git a/trunk/fs/file.c b/trunk/fs/file.c index 708d997a7748..7cb71b992603 100644 --- a/trunk/fs/file.c +++ b/trunk/fs/file.c @@ -685,7 +685,6 @@ void do_close_on_exec(struct files_struct *files) struct fdtable *fdt; /* exec unshares first */ - BUG_ON(atomic_read(&files->count) != 1); spin_lock(&files->file_lock); for (i = 0; ; i++) { unsigned long set; diff --git a/trunk/fs/jffs2/file.c b/trunk/fs/jffs2/file.c index 60ef3fb707ff..1506673c087e 100644 --- a/trunk/fs/jffs2/file.c +++ b/trunk/fs/jffs2/file.c @@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, struct page *pg; struct inode *inode = mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_raw_inode ri; + uint32_t alloc_len = 0; pgoff_t index = pos >> PAGE_CACHE_SHIFT; uint32_t pageofs = index << PAGE_CACHE_SHIFT; int ret = 0; + jffs2_dbg(1, "%s()\n", __func__); + + if (pageofs > inode->i_size) { + ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + if (ret) + return ret; + } + + mutex_lock(&f->sem); pg = grab_cache_page_write_begin(mapping, index, flags); - if (!pg) + if (!pg) { + if (alloc_len) + jffs2_complete_reservation(c); + mutex_unlock(&f->sem); return -ENOMEM; + } *pagep = pg; - jffs2_dbg(1, "%s()\n", __func__); - - if (pageofs > inode->i_size) { + if (alloc_len) { /* Make new hole frag from old EOF to new page */ - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; - uint32_t alloc_len; jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs); - ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, - ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); - if (ret) - goto out_page; - - mutex_lock(&f->sem); memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, if (IS_ERR(fn)) { ret = PTR_ERR(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } ret = jffs2_add_full_dnode_to_inode(c, f, fn); @@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } jffs2_complete_reservation(c); inode->i_size = pageofs; - mutex_unlock(&f->sem); } /* @@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, * case of a short-copy. */ if (!PageUptodate(pg)) { - mutex_lock(&f->sem); ret = jffs2_do_readpage_nolock(inode, pg); - mutex_unlock(&f->sem); if (ret) goto out_page; } + mutex_unlock(&f->sem); jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); return ret; out_page: unlock_page(pg); page_cache_release(pg); + mutex_unlock(&f->sem); return ret; } diff --git a/trunk/fs/notify/fanotify/fanotify_user.c b/trunk/fs/notify/fanotify/fanotify_user.c index 721d692fa8d4..6fcaeb8c902e 100644 --- a/trunk/fs/notify/fanotify/fanotify_user.c +++ b/trunk/fs/notify/fanotify/fanotify_user.c @@ -258,7 +258,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, if (ret) goto out_close_fd; - fd_install(fd, f); + if (fd != FAN_NOFD) + fd_install(fd, f); return fanotify_event_metadata.event_len; out_close_fd: diff --git a/trunk/fs/reiserfs/inode.c b/trunk/fs/reiserfs/inode.c index f27f01a98aa2..d83736fbc26c 100644 --- a/trunk/fs/reiserfs/inode.c +++ b/trunk/fs/reiserfs/inode.c @@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, BUG_ON(!th->t_trans_id); - dquot_initialize(inode); + reiserfs_write_unlock(inode->i_sb); err = dquot_alloc_inode(inode); + reiserfs_write_lock(inode->i_sb); if (err) goto out_end_trans; if (!dir->i_nlink) { @@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, out_end_trans: journal_end(th, th->t_super, th->t_blocks_allocated); + reiserfs_write_unlock(inode->i_sb); /* Drop can be outside and it needs more credits so it's better to have it outside */ dquot_drop(inode); + reiserfs_write_lock(inode->i_sb); inode->i_flags |= S_NOQUOTA; make_bad_inode(inode); @@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) /* must be turned off for recursive notify_change calls */ ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); - depth = reiserfs_write_lock_once(inode->i_sb); if (is_quota_modification(inode, attr)) dquot_initialize(inode); - + depth = reiserfs_write_lock_once(inode->i_sb); if (attr->ia_valid & ATTR_SIZE) { /* version 2 items will be caught by the s_maxbytes check ** done for us in vmtruncate @@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) error = journal_begin(&th, inode->i_sb, jbegin_count); if (error) goto out; + reiserfs_write_unlock_once(inode->i_sb, depth); error = dquot_transfer(inode, attr); + depth = reiserfs_write_lock_once(inode->i_sb); if (error) { journal_end(&th, inode->i_sb, jbegin_count); goto out; diff --git a/trunk/fs/reiserfs/stree.c b/trunk/fs/reiserfs/stree.c index f8afa4b162b8..2f40a4c70a4d 100644 --- a/trunk/fs/reiserfs/stree.c +++ b/trunk/fs/reiserfs/stree.c @@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree key2type(&(key->on_disk_key))); #endif + reiserfs_write_unlock(inode->i_sb); retval = dquot_alloc_space_nodirty(inode, pasted_size); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(search_path); return retval; @@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, "reiserquota insert_item(): allocating %u id=%u type=%c", quota_bytes, inode->i_uid, head2type(ih)); #endif + reiserfs_write_unlock(inode->i_sb); /* We can't dirty inode here. It would be immediately written but * appropriate stat item isn't inserted yet... */ retval = dquot_alloc_space_nodirty(inode, quota_bytes); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(path); return retval; diff --git a/trunk/fs/reiserfs/super.c b/trunk/fs/reiserfs/super.c index 1078ae179993..418bdc3a57da 100644 --- a/trunk/fs/reiserfs/super.c +++ b/trunk/fs/reiserfs/super.c @@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s) retval = remove_save_link_only(s, &save_link_key, 0); continue; } + reiserfs_write_unlock(s); dquot_initialize(inode); + reiserfs_write_lock(s); if (truncate && S_ISDIR(inode->i_mode)) { /* We got a truncate request for a dir which is impossible. @@ -1335,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) kfree(qf_names[i]); #endif err = -EINVAL; - goto out_err; + goto out_unlock; } #ifdef CONFIG_QUOTA handle_quota_files(s, qf_names, &qfmt); @@ -1379,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (blocks) { err = reiserfs_resize(s, blocks); if (err != 0) - goto out_err; + goto out_unlock; } if (*mount_flags & MS_RDONLY) { @@ -1389,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) /* it is read-only already */ goto out_ok; + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_suspend() without it. + */ + reiserfs_write_unlock(s); err = dquot_suspend(s, -1); if (err < 0) goto out_err; + reiserfs_write_lock(s); /* try to remount file system with read-only permissions */ if (sb_umount_state(rs) == REISERFS_VALID_FS @@ -1401,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mounting a rw partition read-only. */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1416,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (reiserfs_is_journal_aborted(journal)) { err = journal->j_errno; - goto out_err; + goto out_unlock; } handle_data_mode(s, mount_options); @@ -1425,7 +1433,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mount a partition which is read-only, read-write */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1442,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) SB_JOURNAL(s)->j_must_wait = 1; err = journal_end(&th, s, 10); if (err) - goto out_err; + goto out_unlock; if (!(*mount_flags & MS_RDONLY)) { + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_resume() without it. + */ + reiserfs_write_unlock(s); dquot_resume(s, -1); + reiserfs_write_lock(s); finish_unfinished(s); reiserfs_xattr_init(s, *mount_flags); } @@ -1455,9 +1469,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) reiserfs_write_unlock(s); return 0; +out_unlock: + reiserfs_write_unlock(s); out_err: kfree(new_opts); - reiserfs_write_unlock(s); return err; } @@ -2095,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot) REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_commit(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2117,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_acquire(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2137,19 +2156,21 @@ static int reiserfs_release_dquot(struct dquot *dquot) ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); + reiserfs_write_unlock(dquot->dq_sb); if (ret) { /* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release(dquot); goto out; } ret = dquot_release(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: reiserfs_write_unlock(dquot->dq_sb); +out: return ret; } @@ -2174,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type) ret = journal_begin(&th, sb, 2); if (ret) goto out; + reiserfs_write_unlock(sb); ret = dquot_commit_info(sb, type); + reiserfs_write_lock(sb); err = journal_end(&th, sb, 2); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(sb); return ret; } @@ -2203,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, struct reiserfs_transaction_handle th; int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA; - if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) - return -EINVAL; + reiserfs_write_lock(sb); + if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) { + err = -EINVAL; + goto out; + } /* Quotafile not on the same filesystem? */ if (path->dentry->d_sb != sb) { @@ -2246,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, if (err) goto out; } - err = dquot_quota_on(sb, type, format_id, path); + reiserfs_write_unlock(sb); + return dquot_quota_on(sb, type, format_id, path); out: + reiserfs_write_unlock(sb); return err; } @@ -2320,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; tmp_bh.b_state = 0; + reiserfs_write_lock(sb); err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE); + reiserfs_write_unlock(sb); if (err) goto out; if (offset || tocopy != sb->s_blocksize) @@ -2336,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, flush_dcache_page(bh->b_page); set_buffer_uptodate(bh); unlock_buffer(bh); + reiserfs_write_lock(sb); reiserfs_prepare_for_journal(sb, bh, 1); journal_mark_dirty(current->journal_info, sb, bh); if (!journal_quota) reiserfs_add_ordered_list(inode, bh); + reiserfs_write_unlock(sb); brelse(bh); offset = 0; towrite -= tocopy; diff --git a/trunk/fs/xfs/xfs_aops.c b/trunk/fs/xfs/xfs_aops.c index e562dd43f41f..e57e2daa357c 100644 --- a/trunk/fs/xfs/xfs_aops.c +++ b/trunk/fs/xfs/xfs_aops.c @@ -481,11 +481,17 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) * * The fix is two passes across the ioend list - one to start writeback on the * buffer_heads, and then submit them for I/O on the second pass. + * + * If @fail is non-zero, it means that we have a situation where some part of + * the submission process has failed after we have marked paged for writeback + * and unlocked them. In this situation, we need to fail the ioend chain rather + * than submit it to IO. This typically only happens on a filesystem shutdown. */ STATIC void xfs_submit_ioend( struct writeback_control *wbc, - xfs_ioend_t *ioend) + xfs_ioend_t *ioend, + int fail) { xfs_ioend_t *head = ioend; xfs_ioend_t *next; @@ -506,6 +512,18 @@ xfs_submit_ioend( next = ioend->io_list; bio = NULL; + /* + * If we are failing the IO now, just mark the ioend with an + * error and finish it. This will run IO completion immediately + * as there is only one reference to the ioend at this point in + * time. + */ + if (fail) { + ioend->io_error = -fail; + xfs_finish_ioend(ioend); + continue; + } + for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { if (!bio) { @@ -1060,7 +1078,18 @@ xfs_vm_writepage( xfs_start_page_writeback(page, 1, count); - if (ioend && imap_valid) { + /* if there is no IO to be submitted for this page, we are done */ + if (!ioend) + return 0; + + ASSERT(iohead); + + /* + * Any errors from this point onwards need tobe reported through the IO + * completion path as we have marked the initial page as under writeback + * and unlocked it. + */ + if (imap_valid) { xfs_off_t end_index; end_index = imap.br_startoff + imap.br_blockcount; @@ -1079,20 +1108,15 @@ xfs_vm_writepage( wbc, end_index); } - if (iohead) { - /* - * Reserve log space if we might write beyond the on-disk - * inode size. - */ - if (ioend->io_type != XFS_IO_UNWRITTEN && - xfs_ioend_is_append(ioend)) { - err = xfs_setfilesize_trans_alloc(ioend); - if (err) - goto error; - } - xfs_submit_ioend(wbc, iohead); - } + /* + * Reserve log space if we might write beyond the on-disk inode size. + */ + err = 0; + if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend)) + err = xfs_setfilesize_trans_alloc(ioend); + + xfs_submit_ioend(wbc, iohead, err); return 0; diff --git a/trunk/fs/xfs/xfs_attr_leaf.c b/trunk/fs/xfs/xfs_attr_leaf.c index d330111ca738..70eec1829776 100644 --- a/trunk/fs/xfs/xfs_attr_leaf.c +++ b/trunk/fs/xfs/xfs_attr_leaf.c @@ -1291,6 +1291,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, leaf2 = blk2->bp->b_addr; ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); + ASSERT(leaf2->hdr.count == 0); args = state->args; trace_xfs_attr_leaf_rebalance(args); @@ -1361,6 +1362,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, * I assert that since all callers pass in an empty * second buffer, this code should never execute. */ + ASSERT(0); /* * Figure the total bytes to be added to the destination leaf. @@ -1422,10 +1424,24 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, args->index2 = 0; args->blkno2 = blk2->blkno; } else { + /* + * On a double leaf split, the original attr location + * is already stored in blkno2/index2, so don't + * overwrite it overwise we corrupt the tree. + */ blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); - args->index = args->index2 = blk2->index; - args->blkno = args->blkno2 = blk2->blkno; + args->index = blk2->index; + args->blkno = blk2->blkno; + if (!state->extravalid) { + /* + * set the new attr location to match the old + * one and let the higher level split code + * decide where in the leaf to place it. + */ + args->index2 = blk2->index; + args->blkno2 = blk2->blkno; + } } } else { ASSERT(state->inleaf == 1); diff --git a/trunk/fs/xfs/xfs_buf.c b/trunk/fs/xfs/xfs_buf.c index 933b7930b863..4b0b8dd1b7b0 100644 --- a/trunk/fs/xfs/xfs_buf.c +++ b/trunk/fs/xfs/xfs_buf.c @@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io( { xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; - xfs_buf_ioerror(bp, -error); + /* + * don't overwrite existing errors - otherwise we can lose errors on + * buffers that require multiple bios to complete. + */ + if (!bp->b_error) + xfs_buf_ioerror(bp, -error); - if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) + if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); _xfs_buf_ioend(bp, 1); @@ -1279,6 +1284,11 @@ xfs_buf_ioapply_map( if (size) goto next_chunk; } else { + /* + * This is guaranteed not to be the last io reference count + * because the caller (xfs_buf_iorequest) holds a count itself. + */ + atomic_dec(&bp->b_io_remaining); xfs_buf_ioerror(bp, EIO); bio_put(bio); } diff --git a/trunk/include/drm/drm_pciids.h b/trunk/include/drm/drm_pciids.h index af1cbaf535ed..c5c35e629426 100644 --- a/trunk/include/drm/drm_pciids.h +++ b/trunk/include/drm/drm_pciids.h @@ -210,6 +210,7 @@ {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ diff --git a/trunk/include/linux/i2c-omap.h b/trunk/include/linux/i2c-omap.h index df804ba73e0b..92a0dc75bc74 100644 --- a/trunk/include/linux/i2c-omap.h +++ b/trunk/include/linux/i2c-omap.h @@ -34,6 +34,7 @@ struct omap_i2c_bus_platform_data { u32 clkrate; u32 rev; u32 flags; + void (*set_mpu_wkup_lat)(struct device *dev, long set); }; #endif diff --git a/trunk/include/linux/of_address.h b/trunk/include/linux/of_address.h index e20e3af68fb6..0506eb53519b 100644 --- a/trunk/include/linux/of_address.h +++ b/trunk/include/linux/of_address.h @@ -42,10 +42,12 @@ static inline struct device_node *of_find_matching_node_by_address( { return NULL; } +#ifndef of_iomap static inline void __iomem *of_iomap(struct device_node *device, int index) { return NULL; } +#endif static inline const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags) { diff --git a/trunk/include/linux/spi/ads7846.h b/trunk/include/linux/spi/ads7846.h index c64de9dd7631..2f694f3846a9 100644 --- a/trunk/include/linux/spi/ads7846.h +++ b/trunk/include/linux/spi/ads7846.h @@ -46,8 +46,9 @@ struct ads7846_platform_data { u16 debounce_rep; /* additional consecutive good readings * required after the first two */ int gpio_pendown; /* the GPIO used to decide the pendown - * state if get_pendown_state == NULL - */ + * state if get_pendown_state == NULL */ + int gpio_pendown_debounce; /* platform specific debounce time for + * the gpio_pendown */ int (*get_pendown_state)(void); int (*filter_init) (const struct ads7846_platform_data *pdata, void **filter_data); diff --git a/trunk/include/net/xfrm.h b/trunk/include/net/xfrm.h index 6f0ba01afe73..63445ede48bb 100644 --- a/trunk/include/net/xfrm.h +++ b/trunk/include/net/xfrm.h @@ -1351,7 +1351,7 @@ struct xfrm6_tunnel { }; extern void xfrm_init(void); -extern void xfrm4_init(int rt_hash_size); +extern void xfrm4_init(void); extern int xfrm_state_init(struct net *net); extern void xfrm_state_fini(struct net *net); extern void xfrm4_state_init(void); diff --git a/trunk/include/scsi/scsi_device.h b/trunk/include/scsi/scsi_device.h index 88fae8d20154..55367b04dc94 100644 --- a/trunk/include/scsi/scsi_device.h +++ b/trunk/include/scsi/scsi_device.h @@ -135,6 +135,8 @@ struct scsi_device { * because we did a bus reset. */ unsigned use_10_for_rw:1; /* first try 10-byte read / write */ unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */ + unsigned no_report_opcodes:1; /* no REPORT SUPPORTED OPERATION CODES */ + unsigned no_write_same:1; /* no WRITE SAME command */ unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */ unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */ unsigned skip_vpd_pages:1; /* do not read VPD pages */ @@ -362,6 +364,8 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries, struct scsi_sense_hdr *sshdr); extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf, int buf_len); +extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, + unsigned int len, unsigned char opcode); extern int scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state); extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type, diff --git a/trunk/include/sound/Kbuild b/trunk/include/sound/Kbuild index e69de29bb2d1..6df30ed1581c 100644 --- a/trunk/include/sound/Kbuild +++ b/trunk/include/sound/Kbuild @@ -0,0 +1,10 @@ +header-y += asequencer.h +header-y += asound.h +header-y += asound_fm.h +header-y += emu10k1.h +header-y += hdsp.h +header-y += hdspm.h +header-y += sb16_csp.h +header-y += sfnt_info.h +header-y += compress_params.h +header-y += compress_offload.h diff --git a/trunk/include/sound/asequencer.h b/trunk/include/sound/asequencer.h index 75935ce739c5..1505e6d5ef82 100644 --- a/trunk/include/sound/asequencer.h +++ b/trunk/include/sound/asequencer.h @@ -22,9 +22,294 @@ #ifndef __SOUND_ASEQUENCER_H #define __SOUND_ASEQUENCER_H +#ifdef __KERNEL__ #include #include -#include +#endif + +/** version of the sequencer */ +#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1) + +/** + * definition of sequencer event types + */ + +/** system messages + * event data type = #snd_seq_result + */ +#define SNDRV_SEQ_EVENT_SYSTEM 0 +#define SNDRV_SEQ_EVENT_RESULT 1 + +/** note messages (channel specific) + * event data type = #snd_seq_ev_note + */ +#define SNDRV_SEQ_EVENT_NOTE 5 +#define SNDRV_SEQ_EVENT_NOTEON 6 +#define SNDRV_SEQ_EVENT_NOTEOFF 7 +#define SNDRV_SEQ_EVENT_KEYPRESS 8 + +/** control messages (channel specific) + * event data type = #snd_seq_ev_ctrl + */ +#define SNDRV_SEQ_EVENT_CONTROLLER 10 +#define SNDRV_SEQ_EVENT_PGMCHANGE 11 +#define SNDRV_SEQ_EVENT_CHANPRESS 12 +#define SNDRV_SEQ_EVENT_PITCHBEND 13 /**< from -8192 to 8191 */ +#define SNDRV_SEQ_EVENT_CONTROL14 14 /**< 14 bit controller value */ +#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN address + 14 bit unsigned value */ +#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */ + +/** synchronisation messages + * event data type = #snd_seq_ev_ctrl + */ +#define SNDRV_SEQ_EVENT_SONGPOS 20 /* Song Position Pointer with LSB and MSB values */ +#define SNDRV_SEQ_EVENT_SONGSEL 21 /* Song Select with song ID number */ +#define SNDRV_SEQ_EVENT_QFRAME 22 /* midi time code quarter frame */ +#define SNDRV_SEQ_EVENT_TIMESIGN 23 /* SMF Time Signature event */ +#define SNDRV_SEQ_EVENT_KEYSIGN 24 /* SMF Key Signature event */ + +/** timer messages + * event data type = snd_seq_ev_queue_control + */ +#define SNDRV_SEQ_EVENT_START 30 /* midi Real Time Start message */ +#define SNDRV_SEQ_EVENT_CONTINUE 31 /* midi Real Time Continue message */ +#define SNDRV_SEQ_EVENT_STOP 32 /* midi Real Time Stop message */ +#define SNDRV_SEQ_EVENT_SETPOS_TICK 33 /* set tick queue position */ +#define SNDRV_SEQ_EVENT_SETPOS_TIME 34 /* set realtime queue position */ +#define SNDRV_SEQ_EVENT_TEMPO 35 /* (SMF) Tempo event */ +#define SNDRV_SEQ_EVENT_CLOCK 36 /* midi Real Time Clock message */ +#define SNDRV_SEQ_EVENT_TICK 37 /* midi Real Time Tick message */ +#define SNDRV_SEQ_EVENT_QUEUE_SKEW 38 /* skew queue tempo */ + +/** others + * event data type = none + */ +#define SNDRV_SEQ_EVENT_TUNE_REQUEST 40 /* tune request */ +#define SNDRV_SEQ_EVENT_RESET 41 /* reset to power-on state */ +#define SNDRV_SEQ_EVENT_SENSING 42 /* "active sensing" event */ + +/** echo back, kernel private messages + * event data type = any type + */ +#define SNDRV_SEQ_EVENT_ECHO 50 /* echo event */ +#define SNDRV_SEQ_EVENT_OSS 51 /* OSS raw event */ + +/** system status messages (broadcast for subscribers) + * event data type = snd_seq_addr + */ +#define SNDRV_SEQ_EVENT_CLIENT_START 60 /* new client has connected */ +#define SNDRV_SEQ_EVENT_CLIENT_EXIT 61 /* client has left the system */ +#define SNDRV_SEQ_EVENT_CLIENT_CHANGE 62 /* client status/info has changed */ +#define SNDRV_SEQ_EVENT_PORT_START 63 /* new port was created */ +#define SNDRV_SEQ_EVENT_PORT_EXIT 64 /* port was deleted from system */ +#define SNDRV_SEQ_EVENT_PORT_CHANGE 65 /* port status/info has changed */ + +/** port connection changes + * event data type = snd_seq_connect + */ +#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */ +#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */ + +/* 70-89: synthesizer events - obsoleted */ + +/** user-defined events with fixed length + * event data type = any + */ +#define SNDRV_SEQ_EVENT_USR0 90 +#define SNDRV_SEQ_EVENT_USR1 91 +#define SNDRV_SEQ_EVENT_USR2 92 +#define SNDRV_SEQ_EVENT_USR3 93 +#define SNDRV_SEQ_EVENT_USR4 94 +#define SNDRV_SEQ_EVENT_USR5 95 +#define SNDRV_SEQ_EVENT_USR6 96 +#define SNDRV_SEQ_EVENT_USR7 97 +#define SNDRV_SEQ_EVENT_USR8 98 +#define SNDRV_SEQ_EVENT_USR9 99 + +/* 100-118: instrument layer - obsoleted */ +/* 119-129: reserved */ + +/* 130-139: variable length events + * event data type = snd_seq_ev_ext + * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set) + */ +#define SNDRV_SEQ_EVENT_SYSEX 130 /* system exclusive data (variable length) */ +#define SNDRV_SEQ_EVENT_BOUNCE 131 /* error event */ +/* 132-134: reserved */ +#define SNDRV_SEQ_EVENT_USR_VAR0 135 +#define SNDRV_SEQ_EVENT_USR_VAR1 136 +#define SNDRV_SEQ_EVENT_USR_VAR2 137 +#define SNDRV_SEQ_EVENT_USR_VAR3 138 +#define SNDRV_SEQ_EVENT_USR_VAR4 139 + +/* 150-151: kernel events with quote - DO NOT use in user clients */ +#define SNDRV_SEQ_EVENT_KERNEL_ERROR 150 +#define SNDRV_SEQ_EVENT_KERNEL_QUOTE 151 /* obsolete */ + +/* 152-191: reserved */ + +/* 192-254: hardware specific events */ + +/* 255: special event */ +#define SNDRV_SEQ_EVENT_NONE 255 + + +typedef unsigned char snd_seq_event_type_t; + +/** event address */ +struct snd_seq_addr { + unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */ + unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */ +}; + +/** port connection */ +struct snd_seq_connect { + struct snd_seq_addr sender; + struct snd_seq_addr dest; +}; + + +#define SNDRV_SEQ_ADDRESS_UNKNOWN 253 /* unknown source */ +#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS 254 /* send event to all subscribed ports */ +#define SNDRV_SEQ_ADDRESS_BROADCAST 255 /* send event to all queues/clients/ports/channels */ +#define SNDRV_SEQ_QUEUE_DIRECT 253 /* direct dispatch */ + + /* event mode flag - NOTE: only 8 bits available! */ +#define SNDRV_SEQ_TIME_STAMP_TICK (0<<0) /* timestamp in clock ticks */ +#define SNDRV_SEQ_TIME_STAMP_REAL (1<<0) /* timestamp in real time */ +#define SNDRV_SEQ_TIME_STAMP_MASK (1<<0) + +#define SNDRV_SEQ_TIME_MODE_ABS (0<<1) /* absolute timestamp */ +#define SNDRV_SEQ_TIME_MODE_REL (1<<1) /* relative to current time */ +#define SNDRV_SEQ_TIME_MODE_MASK (1<<1) + +#define SNDRV_SEQ_EVENT_LENGTH_FIXED (0<<2) /* fixed event size */ +#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /* variable event size */ +#define SNDRV_SEQ_EVENT_LENGTH_VARUSR (2<<2) /* variable event size - user memory space */ +#define SNDRV_SEQ_EVENT_LENGTH_MASK (3<<2) + +#define SNDRV_SEQ_PRIORITY_NORMAL (0<<4) /* normal priority */ +#define SNDRV_SEQ_PRIORITY_HIGH (1<<4) /* event should be processed before others */ +#define SNDRV_SEQ_PRIORITY_MASK (1<<4) + + + /* note event */ +struct snd_seq_ev_note { + unsigned char channel; + unsigned char note; + unsigned char velocity; + unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */ + unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */ +}; + + /* controller event */ +struct snd_seq_ev_ctrl { + unsigned char channel; + unsigned char unused1, unused2, unused3; /* pad */ + unsigned int param; + signed int value; +}; + + /* generic set of bytes (12x8 bit) */ +struct snd_seq_ev_raw8 { + unsigned char d[12]; /* 8 bit value */ +}; + + /* generic set of integers (3x32 bit) */ +struct snd_seq_ev_raw32 { + unsigned int d[3]; /* 32 bit value */ +}; + + /* external stored data */ +struct snd_seq_ev_ext { + unsigned int len; /* length of data */ + void *ptr; /* pointer to data (note: maybe 64-bit) */ +} __attribute__((packed)); + +struct snd_seq_result { + int event; /* processed event type */ + int result; +}; + + +struct snd_seq_real_time { + unsigned int tv_sec; /* seconds */ + unsigned int tv_nsec; /* nanoseconds */ +}; + +typedef unsigned int snd_seq_tick_time_t; /* midi ticks */ + +union snd_seq_timestamp { + snd_seq_tick_time_t tick; + struct snd_seq_real_time time; +}; + +struct snd_seq_queue_skew { + unsigned int value; + unsigned int base; +}; + + /* queue timer control */ +struct snd_seq_ev_queue_control { + unsigned char queue; /* affected queue */ + unsigned char pad[3]; /* reserved */ + union { + signed int value; /* affected value (e.g. tempo) */ + union snd_seq_timestamp time; /* time */ + unsigned int position; /* sync position */ + struct snd_seq_queue_skew skew; + unsigned int d32[2]; + unsigned char d8[8]; + } param; +}; + + /* quoted event - inside the kernel only */ +struct snd_seq_ev_quote { + struct snd_seq_addr origin; /* original sender */ + unsigned short value; /* optional data */ + struct snd_seq_event *event; /* quoted event */ +} __attribute__((packed)); + + + /* sequencer event */ +struct snd_seq_event { + snd_seq_event_type_t type; /* event type */ + unsigned char flags; /* event flags */ + char tag; + + unsigned char queue; /* schedule queue */ + union snd_seq_timestamp time; /* schedule time */ + + + struct snd_seq_addr source; /* source address */ + struct snd_seq_addr dest; /* destination address */ + + union { /* event data... */ + struct snd_seq_ev_note note; + struct snd_seq_ev_ctrl control; + struct snd_seq_ev_raw8 raw8; + struct snd_seq_ev_raw32 raw32; + struct snd_seq_ev_ext ext; + struct snd_seq_ev_queue_control queue; + union snd_seq_timestamp time; + struct snd_seq_addr addr; + struct snd_seq_connect connect; + struct snd_seq_result result; + struct snd_seq_ev_quote quote; + } data; +}; + + +/* + * bounce event - stored as variable size data + */ +struct snd_seq_event_bounce { + int err; + struct snd_seq_event event; + /* external data follows here. */ +}; + +#ifdef __KERNEL__ /* helper macro */ #define snd_seq_event_bounce_ext_data(ev) ((void*)((char *)(ev)->data.ext.ptr + sizeof(struct snd_seq_event_bounce))) @@ -83,4 +368,311 @@ /* queue sync port */ #define snd_seq_queue_sync_port(q) ((q) + 16) +#endif /* __KERNEL__ */ + + /* system information */ +struct snd_seq_system_info { + int queues; /* maximum queues count */ + int clients; /* maximum clients count */ + int ports; /* maximum ports per client */ + int channels; /* maximum channels per port */ + int cur_clients; /* current clients */ + int cur_queues; /* current queues */ + char reserved[24]; +}; + + + /* system running information */ +struct snd_seq_running_info { + unsigned char client; /* client id */ + unsigned char big_endian; /* 1 = big-endian */ + unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */ + unsigned char pad; /* reserved */ + unsigned char reserved[12]; +}; + + + /* known client numbers */ +#define SNDRV_SEQ_CLIENT_SYSTEM 0 + /* internal client numbers */ +#define SNDRV_SEQ_CLIENT_DUMMY 14 /* midi through */ +#define SNDRV_SEQ_CLIENT_OSS 15 /* oss sequencer emulator */ + + + /* client types */ +typedef int __bitwise snd_seq_client_type_t; +#define NO_CLIENT ((__force snd_seq_client_type_t) 0) +#define USER_CLIENT ((__force snd_seq_client_type_t) 1) +#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2) + + /* event filter flags */ +#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */ +#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */ +#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */ +#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */ + +struct snd_seq_client_info { + int client; /* client number to inquire */ + snd_seq_client_type_t type; /* client type */ + char name[64]; /* client name */ + unsigned int filter; /* filter flags */ + unsigned char multicast_filter[8]; /* multicast filter bitmap */ + unsigned char event_filter[32]; /* event filter bitmap */ + int num_ports; /* RO: number of ports */ + int event_lost; /* number of lost events */ + char reserved[64]; /* for future use */ +}; + + +/* client pool size */ +struct snd_seq_client_pool { + int client; /* client number to inquire */ + int output_pool; /* outgoing (write) pool size */ + int input_pool; /* incoming (read) pool size */ + int output_room; /* minimum free pool size for select/blocking mode */ + int output_free; /* unused size */ + int input_free; /* unused size */ + char reserved[64]; +}; + + +/* Remove events by specified criteria */ + +#define SNDRV_SEQ_REMOVE_INPUT (1<<0) /* Flush input queues */ +#define SNDRV_SEQ_REMOVE_OUTPUT (1<<1) /* Flush output queues */ +#define SNDRV_SEQ_REMOVE_DEST (1<<2) /* Restrict by destination q:client:port */ +#define SNDRV_SEQ_REMOVE_DEST_CHANNEL (1<<3) /* Restrict by channel */ +#define SNDRV_SEQ_REMOVE_TIME_BEFORE (1<<4) /* Restrict to before time */ +#define SNDRV_SEQ_REMOVE_TIME_AFTER (1<<5) /* Restrict to time or after */ +#define SNDRV_SEQ_REMOVE_TIME_TICK (1<<6) /* Time is in ticks */ +#define SNDRV_SEQ_REMOVE_EVENT_TYPE (1<<7) /* Restrict to event type */ +#define SNDRV_SEQ_REMOVE_IGNORE_OFF (1<<8) /* Do not flush off events */ +#define SNDRV_SEQ_REMOVE_TAG_MATCH (1<<9) /* Restrict to events with given tag */ + +struct snd_seq_remove_events { + unsigned int remove_mode; /* Flags that determine what gets removed */ + + union snd_seq_timestamp time; + + unsigned char queue; /* Queue for REMOVE_DEST */ + struct snd_seq_addr dest; /* Address for REMOVE_DEST */ + unsigned char channel; /* Channel for REMOVE_DEST */ + + int type; /* For REMOVE_EVENT_TYPE */ + char tag; /* Tag for REMOVE_TAG */ + + int reserved[10]; /* To allow for future binary compatibility */ + +}; + + + /* known port numbers */ +#define SNDRV_SEQ_PORT_SYSTEM_TIMER 0 +#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1 + + /* port capabilities (32 bits) */ +#define SNDRV_SEQ_PORT_CAP_READ (1<<0) /* readable from this port */ +#define SNDRV_SEQ_PORT_CAP_WRITE (1<<1) /* writable to this port */ + +#define SNDRV_SEQ_PORT_CAP_SYNC_READ (1<<2) +#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE (1<<3) + +#define SNDRV_SEQ_PORT_CAP_DUPLEX (1<<4) + +#define SNDRV_SEQ_PORT_CAP_SUBS_READ (1<<5) /* allow read subscription */ +#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /* allow write subscription */ +#define SNDRV_SEQ_PORT_CAP_NO_EXPORT (1<<7) /* routing not allowed */ + + /* port type */ +#define SNDRV_SEQ_PORT_TYPE_SPECIFIC (1<<0) /* hardware specific */ +#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1) /* generic MIDI device */ +#define SNDRV_SEQ_PORT_TYPE_MIDI_GM (1<<2) /* General MIDI compatible device */ +#define SNDRV_SEQ_PORT_TYPE_MIDI_GS (1<<3) /* GS compatible device */ +#define SNDRV_SEQ_PORT_TYPE_MIDI_XG (1<<4) /* XG compatible device */ +#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /* MT-32 compatible device */ +#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2 (1<<6) /* General MIDI 2 compatible device */ + +/* other standards...*/ +#define SNDRV_SEQ_PORT_TYPE_SYNTH (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */ +#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */ +#define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */ +/*...*/ +#define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */ +#define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */ +#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */ +#define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */ +#define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */ + +/* misc. conditioning flags */ +#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT (1<<0) +#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1) +#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2) + +struct snd_seq_port_info { + struct snd_seq_addr addr; /* client/port numbers */ + char name[64]; /* port name */ + + unsigned int capability; /* port capability bits */ + unsigned int type; /* port type bits */ + int midi_channels; /* channels per MIDI port */ + int midi_voices; /* voices per MIDI port */ + int synth_voices; /* voices per SYNTH port */ + + int read_use; /* R/O: subscribers for output (from this port) */ + int write_use; /* R/O: subscribers for input (to this port) */ + + void *kernel; /* reserved for kernel use (must be NULL) */ + unsigned int flags; /* misc. conditioning */ + unsigned char time_queue; /* queue # for timestamping */ + char reserved[59]; /* for future use */ +}; + + +/* queue flags */ +#define SNDRV_SEQ_QUEUE_FLG_SYNC (1<<0) /* sync enabled */ + +/* queue information */ +struct snd_seq_queue_info { + int queue; /* queue id */ + + /* + * security settings, only owner of this queue can start/stop timer + * etc. if the queue is locked for other clients + */ + int owner; /* client id for owner of the queue */ + unsigned locked:1; /* timing queue locked for other queues */ + char name[64]; /* name of this queue */ + unsigned int flags; /* flags */ + char reserved[60]; /* for future use */ + +}; + +/* queue info/status */ +struct snd_seq_queue_status { + int queue; /* queue id */ + int events; /* read-only - queue size */ + snd_seq_tick_time_t tick; /* current tick */ + struct snd_seq_real_time time; /* current time */ + int running; /* running state of queue */ + int flags; /* various flags */ + char reserved[64]; /* for the future */ +}; + + +/* queue tempo */ +struct snd_seq_queue_tempo { + int queue; /* sequencer queue */ + unsigned int tempo; /* current tempo, us/tick */ + int ppq; /* time resolution, ticks/quarter */ + unsigned int skew_value; /* queue skew */ + unsigned int skew_base; /* queue skew base */ + char reserved[24]; /* for the future */ +}; + + +/* sequencer timer sources */ +#define SNDRV_SEQ_TIMER_ALSA 0 /* ALSA timer */ +#define SNDRV_SEQ_TIMER_MIDI_CLOCK 1 /* Midi Clock (CLOCK event) */ +#define SNDRV_SEQ_TIMER_MIDI_TICK 2 /* Midi Timer Tick (TICK event) */ + +/* queue timer info */ +struct snd_seq_queue_timer { + int queue; /* sequencer queue */ + int type; /* source timer type */ + union { + struct { + struct snd_timer_id id; /* ALSA's timer ID */ + unsigned int resolution; /* resolution in Hz */ + } alsa; + } u; + char reserved[64]; /* for the future use */ +}; + + +struct snd_seq_queue_client { + int queue; /* sequencer queue */ + int client; /* sequencer client */ + int used; /* queue is used with this client + (must be set for accepting events) */ + /* per client watermarks */ + char reserved[64]; /* for future use */ +}; + + +#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE (1<<0) /* exclusive connection */ +#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP (1<<1) +#define SNDRV_SEQ_PORT_SUBS_TIME_REAL (1<<2) + +struct snd_seq_port_subscribe { + struct snd_seq_addr sender; /* sender address */ + struct snd_seq_addr dest; /* destination address */ + unsigned int voices; /* number of voices to be allocated (0 = don't care) */ + unsigned int flags; /* modes */ + unsigned char queue; /* input time-stamp queue (optional) */ + unsigned char pad[3]; /* reserved */ + char reserved[64]; +}; + +/* type of query subscription */ +#define SNDRV_SEQ_QUERY_SUBS_READ 0 +#define SNDRV_SEQ_QUERY_SUBS_WRITE 1 + +struct snd_seq_query_subs { + struct snd_seq_addr root; /* client/port id to be searched */ + int type; /* READ or WRITE */ + int index; /* 0..N-1 */ + int num_subs; /* R/O: number of subscriptions on this port */ + struct snd_seq_addr addr; /* R/O: result */ + unsigned char queue; /* R/O: result */ + unsigned int flags; /* R/O: result */ + char reserved[64]; /* for future use */ +}; + + +/* + * IOCTL commands + */ + +#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int) +#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int) +#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info) +#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info) + +#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info) +#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info) + +#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct snd_seq_port_info) +#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct snd_seq_port_info) +#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct snd_seq_port_info) +#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct snd_seq_port_info) + +#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe) +#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe) + +#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct snd_seq_queue_info) +#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct snd_seq_queue_info) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info) +#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct snd_seq_queue_info) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct snd_seq_queue_tempo) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct snd_seq_queue_tempo) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER _IOWR('S', 0x43, struct snd_seq_queue_owner) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER _IOW ('S', 0x44, struct snd_seq_queue_owner) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct snd_seq_queue_timer) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct snd_seq_queue_timer) +/* XXX +#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct snd_seq_queue_sync) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct snd_seq_queue_sync) +*/ +#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct snd_seq_queue_client) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct snd_seq_queue_client) +#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct snd_seq_client_pool) +#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct snd_seq_client_pool) +#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct snd_seq_remove_events) +#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct snd_seq_query_subs) +#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct snd_seq_port_subscribe) +#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct snd_seq_client_info) +#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct snd_seq_port_info) + #endif /* __SOUND_ASEQUENCER_H */ diff --git a/trunk/include/sound/asound.h b/trunk/include/sound/asound.h index c2dff5369d33..dfe7d441748c 100644 --- a/trunk/include/sound/asound.h +++ b/trunk/include/sound/asound.h @@ -19,9 +19,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ + #ifndef __SOUND_ASOUND_H #define __SOUND_ASOUND_H +#include + +#ifdef __KERNEL__ #include #include #include @@ -36,5 +40,934 @@ #endif #endif -#include +#endif /* __KERNEL__ **/ + +/* + * protocol version + */ + +#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor)) +#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff) +#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff) +#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff) +#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \ + (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \ + (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \ + SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion))) + +/**************************************************************************** + * * + * Digital audio interface * + * * + ****************************************************************************/ + +struct snd_aes_iec958 { + unsigned char status[24]; /* AES/IEC958 channel status bits */ + unsigned char subcode[147]; /* AES/IEC958 subcode bits */ + unsigned char pad; /* nothing */ + unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ +}; + +/**************************************************************************** + * * + * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort * + * * + ****************************************************************************/ + +struct snd_cea_861_aud_if { + unsigned char db1_ct_cc; /* coding type and channel count */ + unsigned char db2_sf_ss; /* sample frequency and size */ + unsigned char db3; /* not used, all zeros */ + unsigned char db4_ca; /* channel allocation code */ + unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */ +}; + +/**************************************************************************** + * * + * Section for driver hardware dependent interface - /dev/snd/hw? * + * * + ****************************************************************************/ + +#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1) + +enum { + SNDRV_HWDEP_IFACE_OPL2 = 0, + SNDRV_HWDEP_IFACE_OPL3, + SNDRV_HWDEP_IFACE_OPL4, + SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */ + SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */ + SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */ + SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */ + SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */ + SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */ + SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */ + SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */ + SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */ + SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */ + SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */ + SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ + SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ + SNDRV_HWDEP_IFACE_HDA, /* HD-audio */ + SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */ + + /* Don't forget to change the following: */ + SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM +}; + +struct snd_hwdep_info { + unsigned int device; /* WR: device number */ + int card; /* R: card number */ + unsigned char id[64]; /* ID (user selectable) */ + unsigned char name[80]; /* hwdep name */ + int iface; /* hwdep interface */ + unsigned char reserved[64]; /* reserved for future */ +}; + +/* generic DSP loader */ +struct snd_hwdep_dsp_status { + unsigned int version; /* R: driver-specific version */ + unsigned char id[32]; /* R: driver-specific ID string */ + unsigned int num_dsps; /* R: number of DSP images to transfer */ + unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */ + unsigned int chip_ready; /* R: 1 = initialization finished */ + unsigned char reserved[16]; /* reserved for future use */ +}; + +struct snd_hwdep_dsp_image { + unsigned int index; /* W: DSP index */ + unsigned char name[64]; /* W: ID (e.g. file name) */ + unsigned char __user *image; /* W: binary image */ + size_t length; /* W: size of image in bytes */ + unsigned long driver_data; /* W: driver-specific data */ +}; + +#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int) +#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info) +#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status) +#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image) + +/***************************************************************************** + * * + * Digital Audio (PCM) interface - /dev/snd/pcm?? * + * * + *****************************************************************************/ + +#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10) + +typedef unsigned long snd_pcm_uframes_t; +typedef signed long snd_pcm_sframes_t; + +enum { + SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */ + SNDRV_PCM_CLASS_MULTI, /* multichannel device */ + SNDRV_PCM_CLASS_MODEM, /* software modem class */ + SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */ + /* Don't forget to change the following: */ + SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER, +}; + +enum { + SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */ + SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */ + /* Don't forget to change the following: */ + SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX, +}; + +enum { + SNDRV_PCM_STREAM_PLAYBACK = 0, + SNDRV_PCM_STREAM_CAPTURE, + SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE, +}; + +typedef int __bitwise snd_pcm_access_t; +#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */ +#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */ +#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */ +#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */ +#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */ +#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED + +typedef int __bitwise snd_pcm_format_t; +#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0) +#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1) +#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2) +#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3) +#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4) +#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5) +#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */ +#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */ +#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */ +#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */ +#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10) +#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11) +#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12) +#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13) +#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ +#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ +#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ +#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ +#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */ +#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */ +#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20) +#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21) +#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22) +#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23) +#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24) +#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31) +#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */ +#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */ +#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */ +#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */ +#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */ +#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */ +#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */ +#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */ +#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */ +#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */ +#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */ +#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */ +#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */ +#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */ +#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */ +#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ +#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B + +#ifdef SNDRV_LITTLE_ENDIAN +#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE +#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE +#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE +#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE +#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE +#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE +#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE +#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE +#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE +#endif +#ifdef SNDRV_BIG_ENDIAN +#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE +#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE +#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE +#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE +#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE +#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE +#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE +#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE +#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE +#endif + +typedef int __bitwise snd_pcm_subformat_t; +#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0) +#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD + +#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */ +#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */ +#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */ +#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */ +#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */ +#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */ +#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */ +#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */ +#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */ +#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */ +#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */ +#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */ +#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */ +#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */ +#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */ +#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ + +typedef int __bitwise snd_pcm_state_t; +#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */ +#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */ +#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */ +#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */ +#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */ +#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */ +#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */ +#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */ +#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */ +#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED + +enum { + SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000, + SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000, + SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000, +}; + +union snd_pcm_sync_id { + unsigned char id[16]; + unsigned short id16[8]; + unsigned int id32[4]; +}; + +struct snd_pcm_info { + unsigned int device; /* RO/WR (control): device number */ + unsigned int subdevice; /* RO/WR (control): subdevice number */ + int stream; /* RO/WR (control): stream direction */ + int card; /* R: card number */ + unsigned char id[64]; /* ID (user selectable) */ + unsigned char name[80]; /* name of this device */ + unsigned char subname[32]; /* subdevice name */ + int dev_class; /* SNDRV_PCM_CLASS_* */ + int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */ + unsigned int subdevices_count; + unsigned int subdevices_avail; + union snd_pcm_sync_id sync; /* hardware synchronization ID */ + unsigned char reserved[64]; /* reserved for future... */ +}; + +typedef int snd_pcm_hw_param_t; +#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */ +#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */ +#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */ +#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS +#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT + +#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */ +#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */ +#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */ +#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */ +#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between + * interrupts in us + */ +#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between + * interrupts + */ +#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between + * interrupts + */ +#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per + * buffer + */ +#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer + * in us + */ +#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */ +#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */ +#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */ +#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS +#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME + +#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */ +#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */ +#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */ + +struct snd_interval { + unsigned int min, max; + unsigned int openmin:1, + openmax:1, + integer:1, + empty:1; +}; + +#define SNDRV_MASK_MAX 256 + +struct snd_mask { + __u32 bits[(SNDRV_MASK_MAX+31)/32]; +}; + +struct snd_pcm_hw_params { + unsigned int flags; + struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - + SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; + struct snd_mask mres[5]; /* reserved masks */ + struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - + SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; + struct snd_interval ires[9]; /* reserved intervals */ + unsigned int rmask; /* W: requested masks */ + unsigned int cmask; /* R: changed masks */ + unsigned int info; /* R: Info flags for returned setup */ + unsigned int msbits; /* R: used most significant bits */ + unsigned int rate_num; /* R: rate numerator */ + unsigned int rate_den; /* R: rate denominator */ + snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ + unsigned char reserved[64]; /* reserved for future */ +}; + +enum { + SNDRV_PCM_TSTAMP_NONE = 0, + SNDRV_PCM_TSTAMP_ENABLE, + SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE, +}; + +struct snd_pcm_sw_params { + int tstamp_mode; /* timestamp mode */ + unsigned int period_step; + unsigned int sleep_min; /* min ticks to sleep */ + snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */ + snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */ + snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */ + snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */ + snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */ + snd_pcm_uframes_t silence_size; /* silence block size */ + snd_pcm_uframes_t boundary; /* pointers wrap point */ + unsigned char reserved[64]; /* reserved for future */ +}; + +struct snd_pcm_channel_info { + unsigned int channel; + __kernel_off_t offset; /* mmap offset */ + unsigned int first; /* offset to first sample in bits */ + unsigned int step; /* samples distance in bits */ +}; + +struct snd_pcm_status { + snd_pcm_state_t state; /* stream state */ + struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */ + struct timespec tstamp; /* reference timestamp */ + snd_pcm_uframes_t appl_ptr; /* appl ptr */ + snd_pcm_uframes_t hw_ptr; /* hw ptr */ + snd_pcm_sframes_t delay; /* current delay in frames */ + snd_pcm_uframes_t avail; /* number of frames available */ + snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */ + snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */ + snd_pcm_state_t suspended_state; /* suspended stream state */ + unsigned char reserved[60]; /* must be filled with zero */ +}; + +struct snd_pcm_mmap_status { + snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */ + int pad1; /* Needed for 64 bit alignment */ + snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */ + struct timespec tstamp; /* Timestamp */ + snd_pcm_state_t suspended_state; /* RO: suspended stream state */ +}; + +struct snd_pcm_mmap_control { + snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */ + snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */ +}; + +#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */ +#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */ +#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */ + +struct snd_pcm_sync_ptr { + unsigned int flags; + union { + struct snd_pcm_mmap_status status; + unsigned char reserved[64]; + } s; + union { + struct snd_pcm_mmap_control control; + unsigned char reserved[64]; + } c; +}; + +struct snd_xferi { + snd_pcm_sframes_t result; + void __user *buf; + snd_pcm_uframes_t frames; +}; + +struct snd_xfern { + snd_pcm_sframes_t result; + void __user * __user *bufs; + snd_pcm_uframes_t frames; +}; + +enum { + SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */ + SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */ + SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, +}; + +/* channel positions */ +enum { + SNDRV_CHMAP_UNKNOWN = 0, + SNDRV_CHMAP_NA, /* N/A, silent */ + SNDRV_CHMAP_MONO, /* mono stream */ + /* this follows the alsa-lib mixer channel value + 3 */ + SNDRV_CHMAP_FL, /* front left */ + SNDRV_CHMAP_FR, /* front right */ + SNDRV_CHMAP_RL, /* rear left */ + SNDRV_CHMAP_RR, /* rear right */ + SNDRV_CHMAP_FC, /* front center */ + SNDRV_CHMAP_LFE, /* LFE */ + SNDRV_CHMAP_SL, /* side left */ + SNDRV_CHMAP_SR, /* side right */ + SNDRV_CHMAP_RC, /* rear center */ + /* new definitions */ + SNDRV_CHMAP_FLC, /* front left center */ + SNDRV_CHMAP_FRC, /* front right center */ + SNDRV_CHMAP_RLC, /* rear left center */ + SNDRV_CHMAP_RRC, /* rear right center */ + SNDRV_CHMAP_FLW, /* front left wide */ + SNDRV_CHMAP_FRW, /* front right wide */ + SNDRV_CHMAP_FLH, /* front left high */ + SNDRV_CHMAP_FCH, /* front center high */ + SNDRV_CHMAP_FRH, /* front right high */ + SNDRV_CHMAP_TC, /* top center */ + SNDRV_CHMAP_TFL, /* top front left */ + SNDRV_CHMAP_TFR, /* top front right */ + SNDRV_CHMAP_TFC, /* top front center */ + SNDRV_CHMAP_TRL, /* top rear left */ + SNDRV_CHMAP_TRR, /* top rear right */ + SNDRV_CHMAP_TRC, /* top rear center */ + SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC, +}; + +#define SNDRV_CHMAP_POSITION_MASK 0xffff +#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16) +#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16) + +#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) +#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) +#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) +#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int) +#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params) +#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params) +#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) +#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params) +#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status) +#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t) +#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22) +#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr) +#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info) +#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40) +#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41) +#define SNDRV_PCM_IOCTL_START _IO('A', 0x42) +#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43) +#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44) +#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int) +#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t) +#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47) +#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48) +#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t) +#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi) +#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi) +#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern) +#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern) +#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int) +#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61) + +/***************************************************************************** + * * + * MIDI v1.0 interface * + * * + *****************************************************************************/ + +/* + * Raw MIDI section - /dev/snd/midi?? + */ + +#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0) + +enum { + SNDRV_RAWMIDI_STREAM_OUTPUT = 0, + SNDRV_RAWMIDI_STREAM_INPUT, + SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT, +}; + +#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001 +#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002 +#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004 + +struct snd_rawmidi_info { + unsigned int device; /* RO/WR (control): device number */ + unsigned int subdevice; /* RO/WR (control): subdevice number */ + int stream; /* WR: stream */ + int card; /* R: card number */ + unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */ + unsigned char id[64]; /* ID (user selectable) */ + unsigned char name[80]; /* name of device */ + unsigned char subname[32]; /* name of active or selected subdevice */ + unsigned int subdevices_count; + unsigned int subdevices_avail; + unsigned char reserved[64]; /* reserved for future use */ +}; + +struct snd_rawmidi_params { + int stream; + size_t buffer_size; /* queue size in bytes */ + size_t avail_min; /* minimum avail bytes for wakeup */ + unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */ + unsigned char reserved[16]; /* reserved for future use */ +}; + +struct snd_rawmidi_status { + int stream; + struct timespec tstamp; /* Timestamp */ + size_t avail; /* available bytes */ + size_t xruns; /* count of overruns since last status (in bytes) */ + unsigned char reserved[16]; /* reserved for future use */ +}; + +#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) +#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info) +#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params) +#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status) +#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int) +#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int) + +/* + * Timer section - /dev/snd/timer + */ + +#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6) + +enum { + SNDRV_TIMER_CLASS_NONE = -1, + SNDRV_TIMER_CLASS_SLAVE = 0, + SNDRV_TIMER_CLASS_GLOBAL, + SNDRV_TIMER_CLASS_CARD, + SNDRV_TIMER_CLASS_PCM, + SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM, +}; + +/* slave timer classes */ +enum { + SNDRV_TIMER_SCLASS_NONE = 0, + SNDRV_TIMER_SCLASS_APPLICATION, + SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */ + SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */ + SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER, +}; + +/* global timers (device member) */ +#define SNDRV_TIMER_GLOBAL_SYSTEM 0 +#define SNDRV_TIMER_GLOBAL_RTC 1 +#define SNDRV_TIMER_GLOBAL_HPET 2 +#define SNDRV_TIMER_GLOBAL_HRTIMER 3 + +/* info flags */ +#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */ + +struct snd_timer_id { + int dev_class; + int dev_sclass; + int card; + int device; + int subdevice; +}; + +struct snd_timer_ginfo { + struct snd_timer_id tid; /* requested timer ID */ + unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ + int card; /* card number */ + unsigned char id[64]; /* timer identification */ + unsigned char name[80]; /* timer name */ + unsigned long reserved0; /* reserved for future use */ + unsigned long resolution; /* average period resolution in ns */ + unsigned long resolution_min; /* minimal period resolution in ns */ + unsigned long resolution_max; /* maximal period resolution in ns */ + unsigned int clients; /* active timer clients */ + unsigned char reserved[32]; +}; + +struct snd_timer_gparams { + struct snd_timer_id tid; /* requested timer ID */ + unsigned long period_num; /* requested precise period duration (in seconds) - numerator */ + unsigned long period_den; /* requested precise period duration (in seconds) - denominator */ + unsigned char reserved[32]; +}; + +struct snd_timer_gstatus { + struct snd_timer_id tid; /* requested timer ID */ + unsigned long resolution; /* current period resolution in ns */ + unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */ + unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */ + unsigned char reserved[32]; +}; + +struct snd_timer_select { + struct snd_timer_id id; /* bind to timer ID */ + unsigned char reserved[32]; /* reserved */ +}; + +struct snd_timer_info { + unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ + int card; /* card number */ + unsigned char id[64]; /* timer identificator */ + unsigned char name[80]; /* timer name */ + unsigned long reserved0; /* reserved for future use */ + unsigned long resolution; /* average period resolution in ns */ + unsigned char reserved[64]; /* reserved */ +}; + +#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */ +#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */ +#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */ + +struct snd_timer_params { + unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */ + unsigned int ticks; /* requested resolution in ticks */ + unsigned int queue_size; /* total size of queue (32-1024) */ + unsigned int reserved0; /* reserved, was: failure locations */ + unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */ + unsigned char reserved[60]; /* reserved */ +}; + +struct snd_timer_status { + struct timespec tstamp; /* Timestamp - last update */ + unsigned int resolution; /* current period resolution in ns */ + unsigned int lost; /* counter of master tick lost */ + unsigned int overrun; /* count of read queue overruns */ + unsigned int queue; /* used queue size */ + unsigned char reserved[64]; /* reserved */ +}; + +#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) +#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id) +#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int) +#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo) +#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams) +#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus) +#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select) +#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info) +#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params) +#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status) +/* The following four ioctls are changed since 1.0.9 due to confliction */ +#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0) +#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1) +#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2) +#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3) + +struct snd_timer_read { + unsigned int resolution; + unsigned int ticks; +}; + +enum { + SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */ + SNDRV_TIMER_EVENT_TICK, /* val = ticks */ + SNDRV_TIMER_EVENT_START, /* val = resolution in ns */ + SNDRV_TIMER_EVENT_STOP, /* val = 0 */ + SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */ + SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */ + SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */ + SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */ + SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */ + /* master timer events for slave timer instances */ + SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10, + SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10, + SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10, + SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10, + SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10, + SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10, +}; + +struct snd_timer_tread { + int event; + struct timespec tstamp; + unsigned int val; +}; + +/**************************************************************************** + * * + * Section for driver control interface - /dev/snd/control? * + * * + ****************************************************************************/ + +#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7) + +struct snd_ctl_card_info { + int card; /* card number */ + int pad; /* reserved for future (was type) */ + unsigned char id[16]; /* ID of card (user selectable) */ + unsigned char driver[16]; /* Driver name */ + unsigned char name[32]; /* Short name of soundcard */ + unsigned char longname[80]; /* name + info text about soundcard */ + unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */ + unsigned char mixername[80]; /* visual mixer identification */ + unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */ +}; + +typedef int __bitwise snd_ctl_elem_type_t; +#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */ +#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */ +#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */ +#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */ +#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */ +#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */ +#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */ +#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64 + +typedef int __bitwise snd_ctl_elem_iface_t; +#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */ +#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */ +#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */ +#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */ +#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */ +#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */ +#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */ +#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER + +#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0) +#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1) +#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE) +#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */ +#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */ +#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */ +#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */ +#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) +#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */ +#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */ +#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */ +#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */ +#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */ +#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */ +/* bits 30 and 31 are obsoleted (for indirect access) */ + +/* for further details see the ACPI and PCI power management specification */ +#define SNDRV_CTL_POWER_D0 0x0000 /* full On */ +#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */ +#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */ +#define SNDRV_CTL_POWER_D3 0x0300 /* Off */ +#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */ +#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */ + +struct snd_ctl_elem_id { + unsigned int numid; /* numeric identifier, zero = invalid */ + snd_ctl_elem_iface_t iface; /* interface identifier */ + unsigned int device; /* device/client number */ + unsigned int subdevice; /* subdevice (substream) number */ + unsigned char name[44]; /* ASCII name of item */ + unsigned int index; /* index of item */ +}; + +struct snd_ctl_elem_list { + unsigned int offset; /* W: first element ID to get */ + unsigned int space; /* W: count of element IDs to get */ + unsigned int used; /* R: count of element IDs set */ + unsigned int count; /* R: count of all elements */ + struct snd_ctl_elem_id __user *pids; /* R: IDs */ + unsigned char reserved[50]; +}; + +struct snd_ctl_elem_info { + struct snd_ctl_elem_id id; /* W: element ID */ + snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */ + unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */ + unsigned int count; /* count of values */ + __kernel_pid_t owner; /* owner's PID of this control */ + union { + struct { + long min; /* R: minimum value */ + long max; /* R: maximum value */ + long step; /* R: step (0 variable) */ + } integer; + struct { + long long min; /* R: minimum value */ + long long max; /* R: maximum value */ + long long step; /* R: step (0 variable) */ + } integer64; + struct { + unsigned int items; /* R: number of items */ + unsigned int item; /* W: item number */ + char name[64]; /* R: value name */ + __u64 names_ptr; /* W: names list (ELEM_ADD only) */ + unsigned int names_length; + } enumerated; + unsigned char reserved[128]; + } value; + union { + unsigned short d[4]; /* dimensions */ + unsigned short *d_ptr; /* indirect - obsoleted */ + } dimen; + unsigned char reserved[64-4*sizeof(unsigned short)]; +}; + +struct snd_ctl_elem_value { + struct snd_ctl_elem_id id; /* W: element ID */ + unsigned int indirect: 1; /* W: indirect access - obsoleted */ + union { + union { + long value[128]; + long *value_ptr; /* obsoleted */ + } integer; + union { + long long value[64]; + long long *value_ptr; /* obsoleted */ + } integer64; + union { + unsigned int item[128]; + unsigned int *item_ptr; /* obsoleted */ + } enumerated; + union { + unsigned char data[512]; + unsigned char *data_ptr; /* obsoleted */ + } bytes; + struct snd_aes_iec958 iec958; + } value; /* RO */ + struct timespec tstamp; + unsigned char reserved[128-sizeof(struct timespec)]; +}; + +struct snd_ctl_tlv { + unsigned int numid; /* control element numeric identification */ + unsigned int length; /* in bytes aligned to 4 */ + unsigned int tlv[0]; /* first TLV */ +}; + +#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int) +#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info) +#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list) +#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info) +#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value) +#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value) +#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id) +#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id) +#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int) +#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info) +#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info) +#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id) +#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv) +#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv) +#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv) +#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int) +#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info) +#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int) +#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info) +#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int) +#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int) +#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info) +#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int) +#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int) +#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int) + +/* + * Read interface. + */ + +enum sndrv_ctl_event_type { + SNDRV_CTL_EVENT_ELEM = 0, + SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM, +}; + +#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */ +#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */ +#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */ +#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */ +#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */ + +struct snd_ctl_event { + int type; /* event type - SNDRV_CTL_EVENT_* */ + union { + struct { + unsigned int mask; + struct snd_ctl_elem_id id; + } elem; + unsigned char data8[60]; + } data; +}; + +/* + * Control names + */ + +#define SNDRV_CTL_NAME_NONE "" +#define SNDRV_CTL_NAME_PLAYBACK "Playback " +#define SNDRV_CTL_NAME_CAPTURE "Capture " + +#define SNDRV_CTL_NAME_IEC958_NONE "" +#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch" +#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume" +#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default" +#define SNDRV_CTL_NAME_IEC958_MASK "Mask" +#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask" +#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask" +#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream" +#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what + #endif /* __SOUND_ASOUND_H */ diff --git a/trunk/include/uapi/sound/asound_fm.h b/trunk/include/sound/asound_fm.h similarity index 100% rename from trunk/include/uapi/sound/asound_fm.h rename to trunk/include/sound/asound_fm.h diff --git a/trunk/include/uapi/sound/compress_offload.h b/trunk/include/sound/compress_offload.h similarity index 100% rename from trunk/include/uapi/sound/compress_offload.h rename to trunk/include/sound/compress_offload.h diff --git a/trunk/include/uapi/sound/compress_params.h b/trunk/include/sound/compress_params.h similarity index 100% rename from trunk/include/uapi/sound/compress_params.h rename to trunk/include/sound/compress_params.h diff --git a/trunk/include/sound/emu10k1.h b/trunk/include/sound/emu10k1.h index f841ba4bacb8..1a33f48ebe78 100644 --- a/trunk/include/sound/emu10k1.h +++ b/trunk/include/sound/emu10k1.h @@ -1,3 +1,8 @@ +#ifndef __SOUND_EMU10K1_H +#define __SOUND_EMU10K1_H + +#include + /* * Copyright (c) by Jaroslav Kysela , * Creative Labs, Inc. @@ -19,9 +24,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#ifndef __SOUND_EMU10K1_H -#define __SOUND_EMU10K1_H +#ifdef __KERNEL__ #include #include @@ -32,10 +36,8 @@ #include #include #include -#include #include -#include /* ------------------- DEFINES -------------------- */ @@ -1786,8 +1788,6 @@ struct snd_emu10k1 { unsigned int efx_voices_mask[2]; unsigned int next_free_voice; - const struct firmware *firmware; - #ifdef CONFIG_PM_SLEEP unsigned int *saved_ptr; unsigned int *saved_gpr; @@ -1796,7 +1796,6 @@ struct snd_emu10k1 { unsigned int *saved_icode; unsigned int *p16v_saved; unsigned int saved_a_iocfg, saved_hcfg; - bool suspend; #endif }; @@ -1900,4 +1899,350 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu, int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu, struct snd_emu10k1_fx8010_irq *irq); +#endif /* __KERNEL__ */ + +/* + * ---- FX8010 ---- + */ + +#define EMU10K1_CARD_CREATIVE 0x00000000 +#define EMU10K1_CARD_EMUAPS 0x00000001 + +#define EMU10K1_FX8010_PCM_COUNT 8 + +/* instruction set */ +#define iMAC0 0x00 /* R = A + (X * Y >> 31) ; saturation */ +#define iMAC1 0x01 /* R = A + (-X * Y >> 31) ; saturation */ +#define iMAC2 0x02 /* R = A + (X * Y >> 31) ; wraparound */ +#define iMAC3 0x03 /* R = A + (-X * Y >> 31) ; wraparound */ +#define iMACINT0 0x04 /* R = A + X * Y ; saturation */ +#define iMACINT1 0x05 /* R = A + X * Y ; wraparound (31-bit) */ +#define iACC3 0x06 /* R = A + X + Y ; saturation */ +#define iMACMV 0x07 /* R = A, acc += X * Y >> 31 */ +#define iANDXOR 0x08 /* R = (A & X) ^ Y */ +#define iTSTNEG 0x09 /* R = (A >= Y) ? X : ~X */ +#define iLIMITGE 0x0a /* R = (A >= Y) ? X : Y */ +#define iLIMITLT 0x0b /* R = (A < Y) ? X : Y */ +#define iLOG 0x0c /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */ +#define iEXP 0x0d /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */ +#define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */ +#define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */ + +/* GPRs */ +#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */ +#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */ +#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */ +#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */ + /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */ + +#define C_00000000 0x40 +#define C_00000001 0x41 +#define C_00000002 0x42 +#define C_00000003 0x43 +#define C_00000004 0x44 +#define C_00000008 0x45 +#define C_00000010 0x46 +#define C_00000020 0x47 +#define C_00000100 0x48 +#define C_00010000 0x49 +#define C_00080000 0x4a +#define C_10000000 0x4b +#define C_20000000 0x4c +#define C_40000000 0x4d +#define C_80000000 0x4e +#define C_7fffffff 0x4f +#define C_ffffffff 0x50 +#define C_fffffffe 0x51 +#define C_c0000000 0x52 +#define C_4f1bbcdc 0x53 +#define C_5a7ef9db 0x54 +#define C_00100000 0x55 /* ?? */ +#define GPR_ACCU 0x56 /* ACCUM, accumulator */ +#define GPR_COND 0x57 /* CCR, condition register */ +#define GPR_NOISE0 0x58 /* noise source */ +#define GPR_NOISE1 0x59 /* noise source */ +#define GPR_IRQ 0x5a /* IRQ register */ +#define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */ +#define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */ +#define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ +#define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ +#define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ +#define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ + +#define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ +#define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ +#define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ +#define A_ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ +#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ +#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ + +#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */ +#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */ +#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */ +#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */ +#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */ +#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */ +#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */ +#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */ +#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */ +#define A_GPR(x) (A_FXGPREGBASE + (x)) + +/* cc_reg constants */ +#define CC_REG_NORMALIZED C_00000001 +#define CC_REG_BORROW C_00000002 +#define CC_REG_MINUS C_00000004 +#define CC_REG_ZERO C_00000008 +#define CC_REG_SATURATE C_00000010 +#define CC_REG_NONZERO C_00000100 + +/* FX buses */ +#define FXBUS_PCM_LEFT 0x00 +#define FXBUS_PCM_RIGHT 0x01 +#define FXBUS_PCM_LEFT_REAR 0x02 +#define FXBUS_PCM_RIGHT_REAR 0x03 +#define FXBUS_MIDI_LEFT 0x04 +#define FXBUS_MIDI_RIGHT 0x05 +#define FXBUS_PCM_CENTER 0x06 +#define FXBUS_PCM_LFE 0x07 +#define FXBUS_PCM_LEFT_FRONT 0x08 +#define FXBUS_PCM_RIGHT_FRONT 0x09 +#define FXBUS_MIDI_REVERB 0x0c +#define FXBUS_MIDI_CHORUS 0x0d +#define FXBUS_PCM_LEFT_SIDE 0x0e +#define FXBUS_PCM_RIGHT_SIDE 0x0f +#define FXBUS_PT_LEFT 0x14 +#define FXBUS_PT_RIGHT 0x15 + +/* Inputs */ +#define EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */ +#define EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */ +#define EXTIN_SPDIF_CD_L 0x02 /* internal S/PDIF CD - onboard - left */ +#define EXTIN_SPDIF_CD_R 0x03 /* internal S/PDIF CD - onboard - right */ +#define EXTIN_ZOOM_L 0x04 /* Zoom Video I2S - left */ +#define EXTIN_ZOOM_R 0x05 /* Zoom Video I2S - right */ +#define EXTIN_TOSLINK_L 0x06 /* LiveDrive - TOSLink Optical - left */ +#define EXTIN_TOSLINK_R 0x07 /* LiveDrive - TOSLink Optical - right */ +#define EXTIN_LINE1_L 0x08 /* LiveDrive - Line/Mic 1 - left */ +#define EXTIN_LINE1_R 0x09 /* LiveDrive - Line/Mic 1 - right */ +#define EXTIN_COAX_SPDIF_L 0x0a /* LiveDrive - Coaxial S/PDIF - left */ +#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */ +#define EXTIN_LINE2_L 0x0c /* LiveDrive - Line/Mic 2 - left */ +#define EXTIN_LINE2_R 0x0d /* LiveDrive - Line/Mic 2 - right */ + +/* Outputs */ +#define EXTOUT_AC97_L 0x00 /* AC'97 playback channel - left */ +#define EXTOUT_AC97_R 0x01 /* AC'97 playback channel - right */ +#define EXTOUT_TOSLINK_L 0x02 /* LiveDrive - TOSLink Optical - left */ +#define EXTOUT_TOSLINK_R 0x03 /* LiveDrive - TOSLink Optical - right */ +#define EXTOUT_AC97_CENTER 0x04 /* SB Live 5.1 - center */ +#define EXTOUT_AC97_LFE 0x05 /* SB Live 5.1 - LFE */ +#define EXTOUT_HEADPHONE_L 0x06 /* LiveDrive - Headphone - left */ +#define EXTOUT_HEADPHONE_R 0x07 /* LiveDrive - Headphone - right */ +#define EXTOUT_REAR_L 0x08 /* Rear channel - left */ +#define EXTOUT_REAR_R 0x09 /* Rear channel - right */ +#define EXTOUT_ADC_CAP_L 0x0a /* ADC Capture buffer - left */ +#define EXTOUT_ADC_CAP_R 0x0b /* ADC Capture buffer - right */ +#define EXTOUT_MIC_CAP 0x0c /* MIC Capture buffer */ +#define EXTOUT_AC97_REAR_L 0x0d /* SB Live 5.1 (c) 2003 - Rear Left */ +#define EXTOUT_AC97_REAR_R 0x0e /* SB Live 5.1 (c) 2003 - Rear Right */ +#define EXTOUT_ACENTER 0x11 /* Analog Center */ +#define EXTOUT_ALFE 0x12 /* Analog LFE */ + +/* Audigy Inputs */ +#define A_EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */ +#define A_EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */ +#define A_EXTIN_SPDIF_CD_L 0x02 /* digital CD left */ +#define A_EXTIN_SPDIF_CD_R 0x03 /* digital CD left */ +#define A_EXTIN_OPT_SPDIF_L 0x04 /* audigy drive Optical SPDIF - left */ +#define A_EXTIN_OPT_SPDIF_R 0x05 /* right */ +#define A_EXTIN_LINE2_L 0x08 /* audigy drive line2/mic2 - left */ +#define A_EXTIN_LINE2_R 0x09 /* right */ +#define A_EXTIN_ADC_L 0x0a /* Philips ADC - left */ +#define A_EXTIN_ADC_R 0x0b /* right */ +#define A_EXTIN_AUX2_L 0x0c /* audigy drive aux2 - left */ +#define A_EXTIN_AUX2_R 0x0d /* - right */ + +/* Audigiy Outputs */ +#define A_EXTOUT_FRONT_L 0x00 /* digital front left */ +#define A_EXTOUT_FRONT_R 0x01 /* right */ +#define A_EXTOUT_CENTER 0x02 /* digital front center */ +#define A_EXTOUT_LFE 0x03 /* digital front lfe */ +#define A_EXTOUT_HEADPHONE_L 0x04 /* headphone audigy drive left */ +#define A_EXTOUT_HEADPHONE_R 0x05 /* right */ +#define A_EXTOUT_REAR_L 0x06 /* digital rear left */ +#define A_EXTOUT_REAR_R 0x07 /* right */ +#define A_EXTOUT_AFRONT_L 0x08 /* analog front left */ +#define A_EXTOUT_AFRONT_R 0x09 /* right */ +#define A_EXTOUT_ACENTER 0x0a /* analog center */ +#define A_EXTOUT_ALFE 0x0b /* analog LFE */ +#define A_EXTOUT_ASIDE_L 0x0c /* analog side left - Audigy 2 ZS */ +#define A_EXTOUT_ASIDE_R 0x0d /* right - Audigy 2 ZS */ +#define A_EXTOUT_AREAR_L 0x0e /* analog rear left */ +#define A_EXTOUT_AREAR_R 0x0f /* right */ +#define A_EXTOUT_AC97_L 0x10 /* AC97 left (front) */ +#define A_EXTOUT_AC97_R 0x11 /* right */ +#define A_EXTOUT_ADC_CAP_L 0x16 /* ADC capture buffer left */ +#define A_EXTOUT_ADC_CAP_R 0x17 /* right */ +#define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */ + +/* Audigy constants */ +#define A_C_00000000 0xc0 +#define A_C_00000001 0xc1 +#define A_C_00000002 0xc2 +#define A_C_00000003 0xc3 +#define A_C_00000004 0xc4 +#define A_C_00000008 0xc5 +#define A_C_00000010 0xc6 +#define A_C_00000020 0xc7 +#define A_C_00000100 0xc8 +#define A_C_00010000 0xc9 +#define A_C_00000800 0xca +#define A_C_10000000 0xcb +#define A_C_20000000 0xcc +#define A_C_40000000 0xcd +#define A_C_80000000 0xce +#define A_C_7fffffff 0xcf +#define A_C_ffffffff 0xd0 +#define A_C_fffffffe 0xd1 +#define A_C_c0000000 0xd2 +#define A_C_4f1bbcdc 0xd3 +#define A_C_5a7ef9db 0xd4 +#define A_C_00100000 0xd5 +#define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */ +#define A_GPR_COND 0xd7 /* CCR, condition register */ +#define A_GPR_NOISE0 0xd8 /* noise source */ +#define A_GPR_NOISE1 0xd9 /* noise source */ +#define A_GPR_IRQ 0xda /* IRQ register */ +#define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */ +#define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */ + +/* definitions for debug register */ +#define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */ +#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */ +#define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */ +#define EMU10K1_DBG_SINGLE_STEP 0x00008000 /* single step mode */ +#define EMU10K1_DBG_STEP 0x00004000 /* start single step */ +#define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */ +#define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */ + +/* tank memory address line */ +#ifndef __KERNEL__ +#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */ +#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */ +#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */ +#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */ +#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */ +#endif + +struct snd_emu10k1_fx8010_info { + unsigned int internal_tram_size; /* in samples */ + unsigned int external_tram_size; /* in samples */ + char fxbus_names[16][32]; /* names of FXBUSes */ + char extin_names[16][32]; /* names of external inputs */ + char extout_names[32][32]; /* names of external outputs */ + unsigned int gpr_controls; /* count of GPR controls */ +}; + +#define EMU10K1_GPR_TRANSLATION_NONE 0 +#define EMU10K1_GPR_TRANSLATION_TABLE100 1 +#define EMU10K1_GPR_TRANSLATION_BASS 2 +#define EMU10K1_GPR_TRANSLATION_TREBLE 3 +#define EMU10K1_GPR_TRANSLATION_ONOFF 4 + +struct snd_emu10k1_fx8010_control_gpr { + struct snd_ctl_elem_id id; /* full control ID definition */ + unsigned int vcount; /* visible count */ + unsigned int count; /* count of GPR (1..16) */ + unsigned short gpr[32]; /* GPR number(s) */ + unsigned int value[32]; /* initial values */ + unsigned int min; /* minimum range */ + unsigned int max; /* maximum range */ + unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ + const unsigned int *tlv; +}; + +/* old ABI without TLV support */ +struct snd_emu10k1_fx8010_control_old_gpr { + struct snd_ctl_elem_id id; + unsigned int vcount; + unsigned int count; + unsigned short gpr[32]; + unsigned int value[32]; + unsigned int min; + unsigned int max; + unsigned int translation; +}; + +struct snd_emu10k1_fx8010_code { + char name[128]; + + DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */ + __u32 __user *gpr_map; /* initializers */ + + unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */ + struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */ + + unsigned int gpr_del_control_count; /* count of GPR controls to remove */ + struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */ + + unsigned int gpr_list_control_count; /* count of GPR controls to list */ + unsigned int gpr_list_control_total; /* total count of GPR controls */ + struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */ + + DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */ + __u32 __user *tram_data_map; /* data initializers */ + __u32 __user *tram_addr_map; /* map initializers */ + + DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */ + __u32 __user *code; /* one instruction - 64 bits */ +}; + +struct snd_emu10k1_fx8010_tram { + unsigned int address; /* 31.bit == 1 -> external TRAM */ + unsigned int size; /* size in samples (4 bytes) */ + unsigned int *samples; /* pointer to samples (20-bit) */ + /* NULL->clear memory */ +}; + +struct snd_emu10k1_fx8010_pcm_rec { + unsigned int substream; /* substream number */ + unsigned int res1; /* reserved */ + unsigned int channels; /* 16-bit channels count, zero = remove this substream */ + unsigned int tram_start; /* ring buffer position in TRAM (in samples) */ + unsigned int buffer_size; /* count of buffered samples */ + unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */ + unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */ + unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */ + unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */ + unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */ + unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */ + unsigned char pad; /* reserved */ + unsigned char etram[32]; /* external TRAM address & data (one per channel) */ + unsigned int res2; /* reserved */ +}; + +#define SNDRV_EMU10K1_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1) + +#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info) +#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code) +#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code) +#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int) +#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram) +#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram) +#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec) +#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec) +#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int) +#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80) +#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81) +#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82) +#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int) +#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int) + +/* typedefs for compatibility to user-space */ +typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t; +typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t; +typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t; +typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t; +typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t; + #endif /* __SOUND_EMU10K1_H */ diff --git a/trunk/include/uapi/sound/hdsp.h b/trunk/include/sound/hdsp.h similarity index 100% rename from trunk/include/uapi/sound/hdsp.h rename to trunk/include/sound/hdsp.h diff --git a/trunk/include/uapi/sound/hdspm.h b/trunk/include/sound/hdspm.h similarity index 100% rename from trunk/include/uapi/sound/hdspm.h rename to trunk/include/sound/hdspm.h diff --git a/trunk/include/sound/pcm.h b/trunk/include/sound/pcm.h index 45c1981c9ca2..6268a4192d5c 100644 --- a/trunk/include/sound/pcm.h +++ b/trunk/include/sound/pcm.h @@ -71,8 +71,6 @@ struct snd_pcm_ops { int (*prepare)(struct snd_pcm_substream *substream); int (*trigger)(struct snd_pcm_substream *substream, int cmd); snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream); - int (*wall_clock)(struct snd_pcm_substream *substream, - struct timespec *audio_ts); int (*copy)(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *buf, snd_pcm_uframes_t count); @@ -283,7 +281,6 @@ struct snd_pcm_runtime { unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */ unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */ snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */ - u64 hw_ptr_wrap; /* offset for hw_ptr due to boundary wrap-around */ /* -- HW params -- */ snd_pcm_access_t access; /* access mode */ diff --git a/trunk/include/sound/sb16_csp.h b/trunk/include/sound/sb16_csp.h index c7c7788005e4..7e950560e591 100644 --- a/trunk/include/sound/sb16_csp.h +++ b/trunk/include/sound/sb16_csp.h @@ -1,3 +1,6 @@ +#ifndef __SOUND_SB16_CSP_H +#define __SOUND_SB16_CSP_H + /* * Copyright (c) 1999 by Uros Bizjak * Takashi Iwai @@ -19,13 +22,106 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#ifndef __SOUND_SB16_CSP_H -#define __SOUND_SB16_CSP_H +/* CSP modes */ +#define SNDRV_SB_CSP_MODE_NONE 0x00 +#define SNDRV_SB_CSP_MODE_DSP_READ 0x01 /* Record from DSP */ +#define SNDRV_SB_CSP_MODE_DSP_WRITE 0x02 /* Play to DSP */ +#define SNDRV_SB_CSP_MODE_QSOUND 0x04 /* QSound */ + +/* CSP load flags */ +#define SNDRV_SB_CSP_LOAD_FROMUSER 0x01 +#define SNDRV_SB_CSP_LOAD_INITBLOCK 0x02 + +/* CSP sample width */ +#define SNDRV_SB_CSP_SAMPLE_8BIT 0x01 +#define SNDRV_SB_CSP_SAMPLE_16BIT 0x02 + +/* CSP channels */ +#define SNDRV_SB_CSP_MONO 0x01 +#define SNDRV_SB_CSP_STEREO 0x02 + +/* CSP rates */ +#define SNDRV_SB_CSP_RATE_8000 0x01 +#define SNDRV_SB_CSP_RATE_11025 0x02 +#define SNDRV_SB_CSP_RATE_22050 0x04 +#define SNDRV_SB_CSP_RATE_44100 0x08 +#define SNDRV_SB_CSP_RATE_ALL 0x0f + +/* CSP running state */ +#define SNDRV_SB_CSP_ST_IDLE 0x00 +#define SNDRV_SB_CSP_ST_LOADED 0x01 +#define SNDRV_SB_CSP_ST_RUNNING 0x02 +#define SNDRV_SB_CSP_ST_PAUSED 0x04 +#define SNDRV_SB_CSP_ST_AUTO 0x08 +#define SNDRV_SB_CSP_ST_QSOUND 0x10 + +/* maximum QSound value (180 degrees right) */ +#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT 0x20 + +/* maximum microcode RIFF file size */ +#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000 + +/* microcode header */ +struct snd_sb_csp_mc_header { + char codec_name[16]; /* id name of codec */ + unsigned short func_req; /* requested function */ +}; + +/* microcode to be loaded */ +struct snd_sb_csp_microcode { + struct snd_sb_csp_mc_header info; + unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE]; +}; + +/* start CSP with sample_width in mono/stereo */ +struct snd_sb_csp_start { + int sample_width; /* sample width, look above */ + int channels; /* channels, look above */ +}; + +/* CSP information */ +struct snd_sb_csp_info { + char codec_name[16]; /* id name of codec */ + unsigned short func_nr; /* function number */ + unsigned int acc_format; /* accepted PCM formats */ + unsigned short acc_channels; /* accepted channels */ + unsigned short acc_width; /* accepted sample width */ + unsigned short acc_rates; /* accepted sample rates */ + unsigned short csp_mode; /* CSP mode, see above */ + unsigned short run_channels; /* current channels */ + unsigned short run_width; /* current sample width */ + unsigned short version; /* version id: 0x10 - 0x1f */ + unsigned short state; /* state bits */ +}; + +/* HWDEP controls */ +/* get CSP information */ +#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info) +/* load microcode to CSP */ +/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits) + * defined for some architectures like MIPS, and it leads to build errors. + * (x86 and co have 14-bit size, thus it's valid, though.) + * As a workaround for skipping the size-limit check, here we don't use the + * normal _IOW() macro but _IOC() with the manual argument. + */ +#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \ + _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode)) +/* unload microcode from CSP */ +#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12) +/* start CSP */ +#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, struct snd_sb_csp_start) +/* stop CSP */ +#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14) +/* pause CSP and DMA transfer */ +#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15) +/* restart CSP and DMA transfer */ +#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16) + +#ifdef __KERNEL__ #include #include #include -#include struct snd_sb_csp; @@ -87,4 +183,6 @@ struct snd_sb_csp { }; int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep); +#endif + #endif /* __SOUND_SB16_CSP */ diff --git a/trunk/include/uapi/sound/sfnt_info.h b/trunk/include/sound/sfnt_info.h similarity index 100% rename from trunk/include/uapi/sound/sfnt_info.h rename to trunk/include/sound/sfnt_info.h diff --git a/trunk/include/sound/vx_core.h b/trunk/include/sound/vx_core.h index f634f8f85db5..4f67c762cd74 100644 --- a/trunk/include/sound/vx_core.h +++ b/trunk/include/sound/vx_core.h @@ -27,6 +27,12 @@ #include #include +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) +#if !defined(CONFIG_USE_VXLOADER) && !defined(CONFIG_SND_VX_LIB) /* built-in kernel */ +#define SND_VX_FW_LOADER /* use the standard firmware loader */ +#endif +#endif + struct firmware; struct device; diff --git a/trunk/include/uapi/sound/Kbuild b/trunk/include/uapi/sound/Kbuild index 0f7d279ebde3..aafaa5aa54d4 100644 --- a/trunk/include/uapi/sound/Kbuild +++ b/trunk/include/uapi/sound/Kbuild @@ -1,11 +1 @@ # UAPI Header export list -header-y += asequencer.h -header-y += asound.h -header-y += asound_fm.h -header-y += compress_offload.h -header-y += compress_params.h -header-y += emu10k1.h -header-y += hdsp.h -header-y += hdspm.h -header-y += sb16_csp.h -header-y += sfnt_info.h diff --git a/trunk/include/uapi/sound/asequencer.h b/trunk/include/uapi/sound/asequencer.h deleted file mode 100644 index 09c8a00ea503..000000000000 --- a/trunk/include/uapi/sound/asequencer.h +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Main header file for the ALSA sequencer - * Copyright (c) 1998-1999 by Frank van de Pol - * (c) 1998-1999 by Jaroslav Kysela - * - * - * 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 _UAPI__SOUND_ASEQUENCER_H -#define _UAPI__SOUND_ASEQUENCER_H - - -/** version of the sequencer */ -#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1) - -/** - * definition of sequencer event types - */ - -/** system messages - * event data type = #snd_seq_result - */ -#define SNDRV_SEQ_EVENT_SYSTEM 0 -#define SNDRV_SEQ_EVENT_RESULT 1 - -/** note messages (channel specific) - * event data type = #snd_seq_ev_note - */ -#define SNDRV_SEQ_EVENT_NOTE 5 -#define SNDRV_SEQ_EVENT_NOTEON 6 -#define SNDRV_SEQ_EVENT_NOTEOFF 7 -#define SNDRV_SEQ_EVENT_KEYPRESS 8 - -/** control messages (channel specific) - * event data type = #snd_seq_ev_ctrl - */ -#define SNDRV_SEQ_EVENT_CONTROLLER 10 -#define SNDRV_SEQ_EVENT_PGMCHANGE 11 -#define SNDRV_SEQ_EVENT_CHANPRESS 12 -#define SNDRV_SEQ_EVENT_PITCHBEND 13 /**< from -8192 to 8191 */ -#define SNDRV_SEQ_EVENT_CONTROL14 14 /**< 14 bit controller value */ -#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN address + 14 bit unsigned value */ -#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */ - -/** synchronisation messages - * event data type = #snd_seq_ev_ctrl - */ -#define SNDRV_SEQ_EVENT_SONGPOS 20 /* Song Position Pointer with LSB and MSB values */ -#define SNDRV_SEQ_EVENT_SONGSEL 21 /* Song Select with song ID number */ -#define SNDRV_SEQ_EVENT_QFRAME 22 /* midi time code quarter frame */ -#define SNDRV_SEQ_EVENT_TIMESIGN 23 /* SMF Time Signature event */ -#define SNDRV_SEQ_EVENT_KEYSIGN 24 /* SMF Key Signature event */ - -/** timer messages - * event data type = snd_seq_ev_queue_control - */ -#define SNDRV_SEQ_EVENT_START 30 /* midi Real Time Start message */ -#define SNDRV_SEQ_EVENT_CONTINUE 31 /* midi Real Time Continue message */ -#define SNDRV_SEQ_EVENT_STOP 32 /* midi Real Time Stop message */ -#define SNDRV_SEQ_EVENT_SETPOS_TICK 33 /* set tick queue position */ -#define SNDRV_SEQ_EVENT_SETPOS_TIME 34 /* set realtime queue position */ -#define SNDRV_SEQ_EVENT_TEMPO 35 /* (SMF) Tempo event */ -#define SNDRV_SEQ_EVENT_CLOCK 36 /* midi Real Time Clock message */ -#define SNDRV_SEQ_EVENT_TICK 37 /* midi Real Time Tick message */ -#define SNDRV_SEQ_EVENT_QUEUE_SKEW 38 /* skew queue tempo */ - -/** others - * event data type = none - */ -#define SNDRV_SEQ_EVENT_TUNE_REQUEST 40 /* tune request */ -#define SNDRV_SEQ_EVENT_RESET 41 /* reset to power-on state */ -#define SNDRV_SEQ_EVENT_SENSING 42 /* "active sensing" event */ - -/** echo back, kernel private messages - * event data type = any type - */ -#define SNDRV_SEQ_EVENT_ECHO 50 /* echo event */ -#define SNDRV_SEQ_EVENT_OSS 51 /* OSS raw event */ - -/** system status messages (broadcast for subscribers) - * event data type = snd_seq_addr - */ -#define SNDRV_SEQ_EVENT_CLIENT_START 60 /* new client has connected */ -#define SNDRV_SEQ_EVENT_CLIENT_EXIT 61 /* client has left the system */ -#define SNDRV_SEQ_EVENT_CLIENT_CHANGE 62 /* client status/info has changed */ -#define SNDRV_SEQ_EVENT_PORT_START 63 /* new port was created */ -#define SNDRV_SEQ_EVENT_PORT_EXIT 64 /* port was deleted from system */ -#define SNDRV_SEQ_EVENT_PORT_CHANGE 65 /* port status/info has changed */ - -/** port connection changes - * event data type = snd_seq_connect - */ -#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */ -#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */ - -/* 70-89: synthesizer events - obsoleted */ - -/** user-defined events with fixed length - * event data type = any - */ -#define SNDRV_SEQ_EVENT_USR0 90 -#define SNDRV_SEQ_EVENT_USR1 91 -#define SNDRV_SEQ_EVENT_USR2 92 -#define SNDRV_SEQ_EVENT_USR3 93 -#define SNDRV_SEQ_EVENT_USR4 94 -#define SNDRV_SEQ_EVENT_USR5 95 -#define SNDRV_SEQ_EVENT_USR6 96 -#define SNDRV_SEQ_EVENT_USR7 97 -#define SNDRV_SEQ_EVENT_USR8 98 -#define SNDRV_SEQ_EVENT_USR9 99 - -/* 100-118: instrument layer - obsoleted */ -/* 119-129: reserved */ - -/* 130-139: variable length events - * event data type = snd_seq_ev_ext - * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set) - */ -#define SNDRV_SEQ_EVENT_SYSEX 130 /* system exclusive data (variable length) */ -#define SNDRV_SEQ_EVENT_BOUNCE 131 /* error event */ -/* 132-134: reserved */ -#define SNDRV_SEQ_EVENT_USR_VAR0 135 -#define SNDRV_SEQ_EVENT_USR_VAR1 136 -#define SNDRV_SEQ_EVENT_USR_VAR2 137 -#define SNDRV_SEQ_EVENT_USR_VAR3 138 -#define SNDRV_SEQ_EVENT_USR_VAR4 139 - -/* 150-151: kernel events with quote - DO NOT use in user clients */ -#define SNDRV_SEQ_EVENT_KERNEL_ERROR 150 -#define SNDRV_SEQ_EVENT_KERNEL_QUOTE 151 /* obsolete */ - -/* 152-191: reserved */ - -/* 192-254: hardware specific events */ - -/* 255: special event */ -#define SNDRV_SEQ_EVENT_NONE 255 - - -typedef unsigned char snd_seq_event_type_t; - -/** event address */ -struct snd_seq_addr { - unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */ - unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */ -}; - -/** port connection */ -struct snd_seq_connect { - struct snd_seq_addr sender; - struct snd_seq_addr dest; -}; - - -#define SNDRV_SEQ_ADDRESS_UNKNOWN 253 /* unknown source */ -#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS 254 /* send event to all subscribed ports */ -#define SNDRV_SEQ_ADDRESS_BROADCAST 255 /* send event to all queues/clients/ports/channels */ -#define SNDRV_SEQ_QUEUE_DIRECT 253 /* direct dispatch */ - - /* event mode flag - NOTE: only 8 bits available! */ -#define SNDRV_SEQ_TIME_STAMP_TICK (0<<0) /* timestamp in clock ticks */ -#define SNDRV_SEQ_TIME_STAMP_REAL (1<<0) /* timestamp in real time */ -#define SNDRV_SEQ_TIME_STAMP_MASK (1<<0) - -#define SNDRV_SEQ_TIME_MODE_ABS (0<<1) /* absolute timestamp */ -#define SNDRV_SEQ_TIME_MODE_REL (1<<1) /* relative to current time */ -#define SNDRV_SEQ_TIME_MODE_MASK (1<<1) - -#define SNDRV_SEQ_EVENT_LENGTH_FIXED (0<<2) /* fixed event size */ -#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /* variable event size */ -#define SNDRV_SEQ_EVENT_LENGTH_VARUSR (2<<2) /* variable event size - user memory space */ -#define SNDRV_SEQ_EVENT_LENGTH_MASK (3<<2) - -#define SNDRV_SEQ_PRIORITY_NORMAL (0<<4) /* normal priority */ -#define SNDRV_SEQ_PRIORITY_HIGH (1<<4) /* event should be processed before others */ -#define SNDRV_SEQ_PRIORITY_MASK (1<<4) - - - /* note event */ -struct snd_seq_ev_note { - unsigned char channel; - unsigned char note; - unsigned char velocity; - unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */ - unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */ -}; - - /* controller event */ -struct snd_seq_ev_ctrl { - unsigned char channel; - unsigned char unused1, unused2, unused3; /* pad */ - unsigned int param; - signed int value; -}; - - /* generic set of bytes (12x8 bit) */ -struct snd_seq_ev_raw8 { - unsigned char d[12]; /* 8 bit value */ -}; - - /* generic set of integers (3x32 bit) */ -struct snd_seq_ev_raw32 { - unsigned int d[3]; /* 32 bit value */ -}; - - /* external stored data */ -struct snd_seq_ev_ext { - unsigned int len; /* length of data */ - void *ptr; /* pointer to data (note: maybe 64-bit) */ -} __attribute__((packed)); - -struct snd_seq_result { - int event; /* processed event type */ - int result; -}; - - -struct snd_seq_real_time { - unsigned int tv_sec; /* seconds */ - unsigned int tv_nsec; /* nanoseconds */ -}; - -typedef unsigned int snd_seq_tick_time_t; /* midi ticks */ - -union snd_seq_timestamp { - snd_seq_tick_time_t tick; - struct snd_seq_real_time time; -}; - -struct snd_seq_queue_skew { - unsigned int value; - unsigned int base; -}; - - /* queue timer control */ -struct snd_seq_ev_queue_control { - unsigned char queue; /* affected queue */ - unsigned char pad[3]; /* reserved */ - union { - signed int value; /* affected value (e.g. tempo) */ - union snd_seq_timestamp time; /* time */ - unsigned int position; /* sync position */ - struct snd_seq_queue_skew skew; - unsigned int d32[2]; - unsigned char d8[8]; - } param; -}; - - /* quoted event - inside the kernel only */ -struct snd_seq_ev_quote { - struct snd_seq_addr origin; /* original sender */ - unsigned short value; /* optional data */ - struct snd_seq_event *event; /* quoted event */ -} __attribute__((packed)); - - - /* sequencer event */ -struct snd_seq_event { - snd_seq_event_type_t type; /* event type */ - unsigned char flags; /* event flags */ - char tag; - - unsigned char queue; /* schedule queue */ - union snd_seq_timestamp time; /* schedule time */ - - - struct snd_seq_addr source; /* source address */ - struct snd_seq_addr dest; /* destination address */ - - union { /* event data... */ - struct snd_seq_ev_note note; - struct snd_seq_ev_ctrl control; - struct snd_seq_ev_raw8 raw8; - struct snd_seq_ev_raw32 raw32; - struct snd_seq_ev_ext ext; - struct snd_seq_ev_queue_control queue; - union snd_seq_timestamp time; - struct snd_seq_addr addr; - struct snd_seq_connect connect; - struct snd_seq_result result; - struct snd_seq_ev_quote quote; - } data; -}; - - -/* - * bounce event - stored as variable size data - */ -struct snd_seq_event_bounce { - int err; - struct snd_seq_event event; - /* external data follows here. */ -}; - - - /* system information */ -struct snd_seq_system_info { - int queues; /* maximum queues count */ - int clients; /* maximum clients count */ - int ports; /* maximum ports per client */ - int channels; /* maximum channels per port */ - int cur_clients; /* current clients */ - int cur_queues; /* current queues */ - char reserved[24]; -}; - - - /* system running information */ -struct snd_seq_running_info { - unsigned char client; /* client id */ - unsigned char big_endian; /* 1 = big-endian */ - unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */ - unsigned char pad; /* reserved */ - unsigned char reserved[12]; -}; - - - /* known client numbers */ -#define SNDRV_SEQ_CLIENT_SYSTEM 0 - /* internal client numbers */ -#define SNDRV_SEQ_CLIENT_DUMMY 14 /* midi through */ -#define SNDRV_SEQ_CLIENT_OSS 15 /* oss sequencer emulator */ - - - /* client types */ -typedef int __bitwise snd_seq_client_type_t; -#define NO_CLIENT ((__force snd_seq_client_type_t) 0) -#define USER_CLIENT ((__force snd_seq_client_type_t) 1) -#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2) - - /* event filter flags */ -#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */ -#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */ -#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */ -#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */ - -struct snd_seq_client_info { - int client; /* client number to inquire */ - snd_seq_client_type_t type; /* client type */ - char name[64]; /* client name */ - unsigned int filter; /* filter flags */ - unsigned char multicast_filter[8]; /* multicast filter bitmap */ - unsigned char event_filter[32]; /* event filter bitmap */ - int num_ports; /* RO: number of ports */ - int event_lost; /* number of lost events */ - char reserved[64]; /* for future use */ -}; - - -/* client pool size */ -struct snd_seq_client_pool { - int client; /* client number to inquire */ - int output_pool; /* outgoing (write) pool size */ - int input_pool; /* incoming (read) pool size */ - int output_room; /* minimum free pool size for select/blocking mode */ - int output_free; /* unused size */ - int input_free; /* unused size */ - char reserved[64]; -}; - - -/* Remove events by specified criteria */ - -#define SNDRV_SEQ_REMOVE_INPUT (1<<0) /* Flush input queues */ -#define SNDRV_SEQ_REMOVE_OUTPUT (1<<1) /* Flush output queues */ -#define SNDRV_SEQ_REMOVE_DEST (1<<2) /* Restrict by destination q:client:port */ -#define SNDRV_SEQ_REMOVE_DEST_CHANNEL (1<<3) /* Restrict by channel */ -#define SNDRV_SEQ_REMOVE_TIME_BEFORE (1<<4) /* Restrict to before time */ -#define SNDRV_SEQ_REMOVE_TIME_AFTER (1<<5) /* Restrict to time or after */ -#define SNDRV_SEQ_REMOVE_TIME_TICK (1<<6) /* Time is in ticks */ -#define SNDRV_SEQ_REMOVE_EVENT_TYPE (1<<7) /* Restrict to event type */ -#define SNDRV_SEQ_REMOVE_IGNORE_OFF (1<<8) /* Do not flush off events */ -#define SNDRV_SEQ_REMOVE_TAG_MATCH (1<<9) /* Restrict to events with given tag */ - -struct snd_seq_remove_events { - unsigned int remove_mode; /* Flags that determine what gets removed */ - - union snd_seq_timestamp time; - - unsigned char queue; /* Queue for REMOVE_DEST */ - struct snd_seq_addr dest; /* Address for REMOVE_DEST */ - unsigned char channel; /* Channel for REMOVE_DEST */ - - int type; /* For REMOVE_EVENT_TYPE */ - char tag; /* Tag for REMOVE_TAG */ - - int reserved[10]; /* To allow for future binary compatibility */ - -}; - - - /* known port numbers */ -#define SNDRV_SEQ_PORT_SYSTEM_TIMER 0 -#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1 - - /* port capabilities (32 bits) */ -#define SNDRV_SEQ_PORT_CAP_READ (1<<0) /* readable from this port */ -#define SNDRV_SEQ_PORT_CAP_WRITE (1<<1) /* writable to this port */ - -#define SNDRV_SEQ_PORT_CAP_SYNC_READ (1<<2) -#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE (1<<3) - -#define SNDRV_SEQ_PORT_CAP_DUPLEX (1<<4) - -#define SNDRV_SEQ_PORT_CAP_SUBS_READ (1<<5) /* allow read subscription */ -#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /* allow write subscription */ -#define SNDRV_SEQ_PORT_CAP_NO_EXPORT (1<<7) /* routing not allowed */ - - /* port type */ -#define SNDRV_SEQ_PORT_TYPE_SPECIFIC (1<<0) /* hardware specific */ -#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1) /* generic MIDI device */ -#define SNDRV_SEQ_PORT_TYPE_MIDI_GM (1<<2) /* General MIDI compatible device */ -#define SNDRV_SEQ_PORT_TYPE_MIDI_GS (1<<3) /* GS compatible device */ -#define SNDRV_SEQ_PORT_TYPE_MIDI_XG (1<<4) /* XG compatible device */ -#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /* MT-32 compatible device */ -#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2 (1<<6) /* General MIDI 2 compatible device */ - -/* other standards...*/ -#define SNDRV_SEQ_PORT_TYPE_SYNTH (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */ -#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */ -#define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */ -/*...*/ -#define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */ -#define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */ -#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */ -#define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */ -#define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */ - -/* misc. conditioning flags */ -#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT (1<<0) -#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1) -#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2) - -struct snd_seq_port_info { - struct snd_seq_addr addr; /* client/port numbers */ - char name[64]; /* port name */ - - unsigned int capability; /* port capability bits */ - unsigned int type; /* port type bits */ - int midi_channels; /* channels per MIDI port */ - int midi_voices; /* voices per MIDI port */ - int synth_voices; /* voices per SYNTH port */ - - int read_use; /* R/O: subscribers for output (from this port) */ - int write_use; /* R/O: subscribers for input (to this port) */ - - void *kernel; /* reserved for kernel use (must be NULL) */ - unsigned int flags; /* misc. conditioning */ - unsigned char time_queue; /* queue # for timestamping */ - char reserved[59]; /* for future use */ -}; - - -/* queue flags */ -#define SNDRV_SEQ_QUEUE_FLG_SYNC (1<<0) /* sync enabled */ - -/* queue information */ -struct snd_seq_queue_info { - int queue; /* queue id */ - - /* - * security settings, only owner of this queue can start/stop timer - * etc. if the queue is locked for other clients - */ - int owner; /* client id for owner of the queue */ - unsigned locked:1; /* timing queue locked for other queues */ - char name[64]; /* name of this queue */ - unsigned int flags; /* flags */ - char reserved[60]; /* for future use */ - -}; - -/* queue info/status */ -struct snd_seq_queue_status { - int queue; /* queue id */ - int events; /* read-only - queue size */ - snd_seq_tick_time_t tick; /* current tick */ - struct snd_seq_real_time time; /* current time */ - int running; /* running state of queue */ - int flags; /* various flags */ - char reserved[64]; /* for the future */ -}; - - -/* queue tempo */ -struct snd_seq_queue_tempo { - int queue; /* sequencer queue */ - unsigned int tempo; /* current tempo, us/tick */ - int ppq; /* time resolution, ticks/quarter */ - unsigned int skew_value; /* queue skew */ - unsigned int skew_base; /* queue skew base */ - char reserved[24]; /* for the future */ -}; - - -/* sequencer timer sources */ -#define SNDRV_SEQ_TIMER_ALSA 0 /* ALSA timer */ -#define SNDRV_SEQ_TIMER_MIDI_CLOCK 1 /* Midi Clock (CLOCK event) */ -#define SNDRV_SEQ_TIMER_MIDI_TICK 2 /* Midi Timer Tick (TICK event) */ - -/* queue timer info */ -struct snd_seq_queue_timer { - int queue; /* sequencer queue */ - int type; /* source timer type */ - union { - struct { - struct snd_timer_id id; /* ALSA's timer ID */ - unsigned int resolution; /* resolution in Hz */ - } alsa; - } u; - char reserved[64]; /* for the future use */ -}; - - -struct snd_seq_queue_client { - int queue; /* sequencer queue */ - int client; /* sequencer client */ - int used; /* queue is used with this client - (must be set for accepting events) */ - /* per client watermarks */ - char reserved[64]; /* for future use */ -}; - - -#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE (1<<0) /* exclusive connection */ -#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP (1<<1) -#define SNDRV_SEQ_PORT_SUBS_TIME_REAL (1<<2) - -struct snd_seq_port_subscribe { - struct snd_seq_addr sender; /* sender address */ - struct snd_seq_addr dest; /* destination address */ - unsigned int voices; /* number of voices to be allocated (0 = don't care) */ - unsigned int flags; /* modes */ - unsigned char queue; /* input time-stamp queue (optional) */ - unsigned char pad[3]; /* reserved */ - char reserved[64]; -}; - -/* type of query subscription */ -#define SNDRV_SEQ_QUERY_SUBS_READ 0 -#define SNDRV_SEQ_QUERY_SUBS_WRITE 1 - -struct snd_seq_query_subs { - struct snd_seq_addr root; /* client/port id to be searched */ - int type; /* READ or WRITE */ - int index; /* 0..N-1 */ - int num_subs; /* R/O: number of subscriptions on this port */ - struct snd_seq_addr addr; /* R/O: result */ - unsigned char queue; /* R/O: result */ - unsigned int flags; /* R/O: result */ - char reserved[64]; /* for future use */ -}; - - -/* - * IOCTL commands - */ - -#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int) -#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int) -#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info) -#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info) - -#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info) -#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info) - -#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct snd_seq_port_info) -#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct snd_seq_port_info) -#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct snd_seq_port_info) -#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct snd_seq_port_info) - -#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe) -#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe) - -#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct snd_seq_queue_info) -#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct snd_seq_queue_info) -#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info) -#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info) -#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct snd_seq_queue_info) -#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status) -#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct snd_seq_queue_tempo) -#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct snd_seq_queue_tempo) -#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER _IOWR('S', 0x43, struct snd_seq_queue_owner) -#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER _IOW ('S', 0x44, struct snd_seq_queue_owner) -#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct snd_seq_queue_timer) -#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct snd_seq_queue_timer) -/* XXX -#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct snd_seq_queue_sync) -#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct snd_seq_queue_sync) -*/ -#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct snd_seq_queue_client) -#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct snd_seq_queue_client) -#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct snd_seq_client_pool) -#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct snd_seq_client_pool) -#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct snd_seq_remove_events) -#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct snd_seq_query_subs) -#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct snd_seq_port_subscribe) -#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct snd_seq_client_info) -#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct snd_seq_port_info) - -#endif /* _UAPI__SOUND_ASEQUENCER_H */ diff --git a/trunk/include/uapi/sound/asound.h b/trunk/include/uapi/sound/asound.h deleted file mode 100644 index 1774a5c3ef10..000000000000 --- a/trunk/include/uapi/sound/asound.h +++ /dev/null @@ -1,971 +0,0 @@ -/* - * Advanced Linux Sound Architecture - ALSA - Driver - * Copyright (c) 1994-2003 by Jaroslav Kysela , - * Abramo Bagnara - * - * - * 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 _UAPI__SOUND_ASOUND_H -#define _UAPI__SOUND_ASOUND_H - -#include - - -/* - * protocol version - */ - -#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor)) -#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff) -#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff) -#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff) -#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \ - (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \ - (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \ - SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion))) - -/**************************************************************************** - * * - * Digital audio interface * - * * - ****************************************************************************/ - -struct snd_aes_iec958 { - unsigned char status[24]; /* AES/IEC958 channel status bits */ - unsigned char subcode[147]; /* AES/IEC958 subcode bits */ - unsigned char pad; /* nothing */ - unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ -}; - -/**************************************************************************** - * * - * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort * - * * - ****************************************************************************/ - -struct snd_cea_861_aud_if { - unsigned char db1_ct_cc; /* coding type and channel count */ - unsigned char db2_sf_ss; /* sample frequency and size */ - unsigned char db3; /* not used, all zeros */ - unsigned char db4_ca; /* channel allocation code */ - unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */ -}; - -/**************************************************************************** - * * - * Section for driver hardware dependent interface - /dev/snd/hw? * - * * - ****************************************************************************/ - -#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1) - -enum { - SNDRV_HWDEP_IFACE_OPL2 = 0, - SNDRV_HWDEP_IFACE_OPL3, - SNDRV_HWDEP_IFACE_OPL4, - SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */ - SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */ - SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */ - SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */ - SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */ - SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */ - SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */ - SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */ - SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */ - SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */ - SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */ - SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ - SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ - SNDRV_HWDEP_IFACE_HDA, /* HD-audio */ - SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */ - - /* Don't forget to change the following: */ - SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM -}; - -struct snd_hwdep_info { - unsigned int device; /* WR: device number */ - int card; /* R: card number */ - unsigned char id[64]; /* ID (user selectable) */ - unsigned char name[80]; /* hwdep name */ - int iface; /* hwdep interface */ - unsigned char reserved[64]; /* reserved for future */ -}; - -/* generic DSP loader */ -struct snd_hwdep_dsp_status { - unsigned int version; /* R: driver-specific version */ - unsigned char id[32]; /* R: driver-specific ID string */ - unsigned int num_dsps; /* R: number of DSP images to transfer */ - unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */ - unsigned int chip_ready; /* R: 1 = initialization finished */ - unsigned char reserved[16]; /* reserved for future use */ -}; - -struct snd_hwdep_dsp_image { - unsigned int index; /* W: DSP index */ - unsigned char name[64]; /* W: ID (e.g. file name) */ - unsigned char __user *image; /* W: binary image */ - size_t length; /* W: size of image in bytes */ - unsigned long driver_data; /* W: driver-specific data */ -}; - -#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int) -#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info) -#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status) -#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image) - -/***************************************************************************** - * * - * Digital Audio (PCM) interface - /dev/snd/pcm?? * - * * - *****************************************************************************/ - -#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 11) - -typedef unsigned long snd_pcm_uframes_t; -typedef signed long snd_pcm_sframes_t; - -enum { - SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */ - SNDRV_PCM_CLASS_MULTI, /* multichannel device */ - SNDRV_PCM_CLASS_MODEM, /* software modem class */ - SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */ - /* Don't forget to change the following: */ - SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER, -}; - -enum { - SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */ - SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */ - /* Don't forget to change the following: */ - SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX, -}; - -enum { - SNDRV_PCM_STREAM_PLAYBACK = 0, - SNDRV_PCM_STREAM_CAPTURE, - SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE, -}; - -typedef int __bitwise snd_pcm_access_t; -#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */ -#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */ -#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */ -#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */ -#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */ -#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED - -typedef int __bitwise snd_pcm_format_t; -#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0) -#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1) -#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2) -#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3) -#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4) -#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5) -#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */ -#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */ -#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */ -#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */ -#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10) -#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11) -#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12) -#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13) -#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ -#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ -#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ -#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ -#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */ -#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */ -#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20) -#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21) -#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22) -#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23) -#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24) -#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31) -#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */ -#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */ -#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */ -#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */ -#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */ -#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */ -#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */ -#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */ -#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */ -#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */ -#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */ -#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */ -#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */ -#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */ -#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */ -#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ -#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B - -#ifdef SNDRV_LITTLE_ENDIAN -#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE -#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE -#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE -#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE -#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE -#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE -#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE -#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE -#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE -#endif -#ifdef SNDRV_BIG_ENDIAN -#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE -#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE -#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE -#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE -#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE -#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE -#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE -#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE -#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE -#endif - -typedef int __bitwise snd_pcm_subformat_t; -#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0) -#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD - -#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */ -#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */ -#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */ -#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */ -#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */ -#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */ -#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */ -#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */ -#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */ -#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */ -#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */ -#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */ -#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */ -#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */ -#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */ -#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* has audio wall clock for audio/system time sync */ -#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ - -typedef int __bitwise snd_pcm_state_t; -#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */ -#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */ -#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */ -#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */ -#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */ -#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */ -#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */ -#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */ -#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */ -#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED - -enum { - SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000, - SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000, - SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000, -}; - -union snd_pcm_sync_id { - unsigned char id[16]; - unsigned short id16[8]; - unsigned int id32[4]; -}; - -struct snd_pcm_info { - unsigned int device; /* RO/WR (control): device number */ - unsigned int subdevice; /* RO/WR (control): subdevice number */ - int stream; /* RO/WR (control): stream direction */ - int card; /* R: card number */ - unsigned char id[64]; /* ID (user selectable) */ - unsigned char name[80]; /* name of this device */ - unsigned char subname[32]; /* subdevice name */ - int dev_class; /* SNDRV_PCM_CLASS_* */ - int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */ - unsigned int subdevices_count; - unsigned int subdevices_avail; - union snd_pcm_sync_id sync; /* hardware synchronization ID */ - unsigned char reserved[64]; /* reserved for future... */ -}; - -typedef int snd_pcm_hw_param_t; -#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */ -#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */ -#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */ -#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS -#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT - -#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */ -#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */ -#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */ -#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */ -#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between - * interrupts in us - */ -#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between - * interrupts - */ -#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between - * interrupts - */ -#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per - * buffer - */ -#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer - * in us - */ -#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */ -#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */ -#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */ -#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS -#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME - -#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */ -#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */ -#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */ - -struct snd_interval { - unsigned int min, max; - unsigned int openmin:1, - openmax:1, - integer:1, - empty:1; -}; - -#define SNDRV_MASK_MAX 256 - -struct snd_mask { - __u32 bits[(SNDRV_MASK_MAX+31)/32]; -}; - -struct snd_pcm_hw_params { - unsigned int flags; - struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; - struct snd_mask mres[5]; /* reserved masks */ - struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; - struct snd_interval ires[9]; /* reserved intervals */ - unsigned int rmask; /* W: requested masks */ - unsigned int cmask; /* R: changed masks */ - unsigned int info; /* R: Info flags for returned setup */ - unsigned int msbits; /* R: used most significant bits */ - unsigned int rate_num; /* R: rate numerator */ - unsigned int rate_den; /* R: rate denominator */ - snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ - unsigned char reserved[64]; /* reserved for future */ -}; - -enum { - SNDRV_PCM_TSTAMP_NONE = 0, - SNDRV_PCM_TSTAMP_ENABLE, - SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE, -}; - -struct snd_pcm_sw_params { - int tstamp_mode; /* timestamp mode */ - unsigned int period_step; - unsigned int sleep_min; /* min ticks to sleep */ - snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */ - snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */ - snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */ - snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */ - snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */ - snd_pcm_uframes_t silence_size; /* silence block size */ - snd_pcm_uframes_t boundary; /* pointers wrap point */ - unsigned char reserved[64]; /* reserved for future */ -}; - -struct snd_pcm_channel_info { - unsigned int channel; - __kernel_off_t offset; /* mmap offset */ - unsigned int first; /* offset to first sample in bits */ - unsigned int step; /* samples distance in bits */ -}; - -struct snd_pcm_status { - snd_pcm_state_t state; /* stream state */ - struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */ - struct timespec tstamp; /* reference timestamp */ - snd_pcm_uframes_t appl_ptr; /* appl ptr */ - snd_pcm_uframes_t hw_ptr; /* hw ptr */ - snd_pcm_sframes_t delay; /* current delay in frames */ - snd_pcm_uframes_t avail; /* number of frames available */ - snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */ - snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */ - snd_pcm_state_t suspended_state; /* suspended stream state */ - __u32 reserved_alignment; /* must be filled with zero */ - struct timespec audio_tstamp; /* from sample counter or wall clock */ - unsigned char reserved[56-sizeof(struct timespec)]; /* must be filled with zero */ -}; - -struct snd_pcm_mmap_status { - snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */ - int pad1; /* Needed for 64 bit alignment */ - snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */ - struct timespec tstamp; /* Timestamp */ - snd_pcm_state_t suspended_state; /* RO: suspended stream state */ - struct timespec audio_tstamp; /* from sample counter or wall clock */ -}; - -struct snd_pcm_mmap_control { - snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */ - snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */ -}; - -#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */ -#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */ -#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */ - -struct snd_pcm_sync_ptr { - unsigned int flags; - union { - struct snd_pcm_mmap_status status; - unsigned char reserved[64]; - } s; - union { - struct snd_pcm_mmap_control control; - unsigned char reserved[64]; - } c; -}; - -struct snd_xferi { - snd_pcm_sframes_t result; - void __user *buf; - snd_pcm_uframes_t frames; -}; - -struct snd_xfern { - snd_pcm_sframes_t result; - void __user * __user *bufs; - snd_pcm_uframes_t frames; -}; - -enum { - SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */ - SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */ - SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, -}; - -/* channel positions */ -enum { - SNDRV_CHMAP_UNKNOWN = 0, - SNDRV_CHMAP_NA, /* N/A, silent */ - SNDRV_CHMAP_MONO, /* mono stream */ - /* this follows the alsa-lib mixer channel value + 3 */ - SNDRV_CHMAP_FL, /* front left */ - SNDRV_CHMAP_FR, /* front right */ - SNDRV_CHMAP_RL, /* rear left */ - SNDRV_CHMAP_RR, /* rear right */ - SNDRV_CHMAP_FC, /* front center */ - SNDRV_CHMAP_LFE, /* LFE */ - SNDRV_CHMAP_SL, /* side left */ - SNDRV_CHMAP_SR, /* side right */ - SNDRV_CHMAP_RC, /* rear center */ - /* new definitions */ - SNDRV_CHMAP_FLC, /* front left center */ - SNDRV_CHMAP_FRC, /* front right center */ - SNDRV_CHMAP_RLC, /* rear left center */ - SNDRV_CHMAP_RRC, /* rear right center */ - SNDRV_CHMAP_FLW, /* front left wide */ - SNDRV_CHMAP_FRW, /* front right wide */ - SNDRV_CHMAP_FLH, /* front left high */ - SNDRV_CHMAP_FCH, /* front center high */ - SNDRV_CHMAP_FRH, /* front right high */ - SNDRV_CHMAP_TC, /* top center */ - SNDRV_CHMAP_TFL, /* top front left */ - SNDRV_CHMAP_TFR, /* top front right */ - SNDRV_CHMAP_TFC, /* top front center */ - SNDRV_CHMAP_TRL, /* top rear left */ - SNDRV_CHMAP_TRR, /* top rear right */ - SNDRV_CHMAP_TRC, /* top rear center */ - /* new definitions for UAC2 */ - SNDRV_CHMAP_TFLC, /* top front left center */ - SNDRV_CHMAP_TFRC, /* top front right center */ - SNDRV_CHMAP_TSL, /* top side left */ - SNDRV_CHMAP_TSR, /* top side right */ - SNDRV_CHMAP_LLFE, /* left LFE */ - SNDRV_CHMAP_RLFE, /* right LFE */ - SNDRV_CHMAP_BC, /* bottom center */ - SNDRV_CHMAP_BLC, /* bottom left center */ - SNDRV_CHMAP_BRC, /* bottom right center */ - SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC, -}; - -#define SNDRV_CHMAP_POSITION_MASK 0xffff -#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16) -#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16) - -#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) -#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) -#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) -#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int) -#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params) -#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params) -#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) -#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params) -#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status) -#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t) -#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22) -#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr) -#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info) -#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40) -#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41) -#define SNDRV_PCM_IOCTL_START _IO('A', 0x42) -#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43) -#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44) -#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int) -#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t) -#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47) -#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48) -#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t) -#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi) -#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi) -#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern) -#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern) -#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int) -#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61) - -/***************************************************************************** - * * - * MIDI v1.0 interface * - * * - *****************************************************************************/ - -/* - * Raw MIDI section - /dev/snd/midi?? - */ - -#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0) - -enum { - SNDRV_RAWMIDI_STREAM_OUTPUT = 0, - SNDRV_RAWMIDI_STREAM_INPUT, - SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT, -}; - -#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001 -#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002 -#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004 - -struct snd_rawmidi_info { - unsigned int device; /* RO/WR (control): device number */ - unsigned int subdevice; /* RO/WR (control): subdevice number */ - int stream; /* WR: stream */ - int card; /* R: card number */ - unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */ - unsigned char id[64]; /* ID (user selectable) */ - unsigned char name[80]; /* name of device */ - unsigned char subname[32]; /* name of active or selected subdevice */ - unsigned int subdevices_count; - unsigned int subdevices_avail; - unsigned char reserved[64]; /* reserved for future use */ -}; - -struct snd_rawmidi_params { - int stream; - size_t buffer_size; /* queue size in bytes */ - size_t avail_min; /* minimum avail bytes for wakeup */ - unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */ - unsigned char reserved[16]; /* reserved for future use */ -}; - -struct snd_rawmidi_status { - int stream; - struct timespec tstamp; /* Timestamp */ - size_t avail; /* available bytes */ - size_t xruns; /* count of overruns since last status (in bytes) */ - unsigned char reserved[16]; /* reserved for future use */ -}; - -#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) -#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info) -#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params) -#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status) -#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int) -#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int) - -/* - * Timer section - /dev/snd/timer - */ - -#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6) - -enum { - SNDRV_TIMER_CLASS_NONE = -1, - SNDRV_TIMER_CLASS_SLAVE = 0, - SNDRV_TIMER_CLASS_GLOBAL, - SNDRV_TIMER_CLASS_CARD, - SNDRV_TIMER_CLASS_PCM, - SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM, -}; - -/* slave timer classes */ -enum { - SNDRV_TIMER_SCLASS_NONE = 0, - SNDRV_TIMER_SCLASS_APPLICATION, - SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */ - SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */ - SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER, -}; - -/* global timers (device member) */ -#define SNDRV_TIMER_GLOBAL_SYSTEM 0 -#define SNDRV_TIMER_GLOBAL_RTC 1 -#define SNDRV_TIMER_GLOBAL_HPET 2 -#define SNDRV_TIMER_GLOBAL_HRTIMER 3 - -/* info flags */ -#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */ - -struct snd_timer_id { - int dev_class; - int dev_sclass; - int card; - int device; - int subdevice; -}; - -struct snd_timer_ginfo { - struct snd_timer_id tid; /* requested timer ID */ - unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ - int card; /* card number */ - unsigned char id[64]; /* timer identification */ - unsigned char name[80]; /* timer name */ - unsigned long reserved0; /* reserved for future use */ - unsigned long resolution; /* average period resolution in ns */ - unsigned long resolution_min; /* minimal period resolution in ns */ - unsigned long resolution_max; /* maximal period resolution in ns */ - unsigned int clients; /* active timer clients */ - unsigned char reserved[32]; -}; - -struct snd_timer_gparams { - struct snd_timer_id tid; /* requested timer ID */ - unsigned long period_num; /* requested precise period duration (in seconds) - numerator */ - unsigned long period_den; /* requested precise period duration (in seconds) - denominator */ - unsigned char reserved[32]; -}; - -struct snd_timer_gstatus { - struct snd_timer_id tid; /* requested timer ID */ - unsigned long resolution; /* current period resolution in ns */ - unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */ - unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */ - unsigned char reserved[32]; -}; - -struct snd_timer_select { - struct snd_timer_id id; /* bind to timer ID */ - unsigned char reserved[32]; /* reserved */ -}; - -struct snd_timer_info { - unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ - int card; /* card number */ - unsigned char id[64]; /* timer identificator */ - unsigned char name[80]; /* timer name */ - unsigned long reserved0; /* reserved for future use */ - unsigned long resolution; /* average period resolution in ns */ - unsigned char reserved[64]; /* reserved */ -}; - -#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */ -#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */ -#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */ - -struct snd_timer_params { - unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */ - unsigned int ticks; /* requested resolution in ticks */ - unsigned int queue_size; /* total size of queue (32-1024) */ - unsigned int reserved0; /* reserved, was: failure locations */ - unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */ - unsigned char reserved[60]; /* reserved */ -}; - -struct snd_timer_status { - struct timespec tstamp; /* Timestamp - last update */ - unsigned int resolution; /* current period resolution in ns */ - unsigned int lost; /* counter of master tick lost */ - unsigned int overrun; /* count of read queue overruns */ - unsigned int queue; /* used queue size */ - unsigned char reserved[64]; /* reserved */ -}; - -#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) -#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id) -#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int) -#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo) -#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams) -#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus) -#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select) -#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info) -#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params) -#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status) -/* The following four ioctls are changed since 1.0.9 due to confliction */ -#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0) -#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1) -#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2) -#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3) - -struct snd_timer_read { - unsigned int resolution; - unsigned int ticks; -}; - -enum { - SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */ - SNDRV_TIMER_EVENT_TICK, /* val = ticks */ - SNDRV_TIMER_EVENT_START, /* val = resolution in ns */ - SNDRV_TIMER_EVENT_STOP, /* val = 0 */ - SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */ - SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */ - SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */ - SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */ - SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */ - /* master timer events for slave timer instances */ - SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10, - SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10, - SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10, - SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10, - SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10, - SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10, -}; - -struct snd_timer_tread { - int event; - struct timespec tstamp; - unsigned int val; -}; - -/**************************************************************************** - * * - * Section for driver control interface - /dev/snd/control? * - * * - ****************************************************************************/ - -#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7) - -struct snd_ctl_card_info { - int card; /* card number */ - int pad; /* reserved for future (was type) */ - unsigned char id[16]; /* ID of card (user selectable) */ - unsigned char driver[16]; /* Driver name */ - unsigned char name[32]; /* Short name of soundcard */ - unsigned char longname[80]; /* name + info text about soundcard */ - unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */ - unsigned char mixername[80]; /* visual mixer identification */ - unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */ -}; - -typedef int __bitwise snd_ctl_elem_type_t; -#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */ -#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */ -#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */ -#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */ -#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */ -#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */ -#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */ -#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64 - -typedef int __bitwise snd_ctl_elem_iface_t; -#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */ -#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */ -#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */ -#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */ -#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */ -#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */ -#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */ -#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER - -#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0) -#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1) -#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE) -#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */ -#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */ -#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */ -#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */ -#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) -#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */ -#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */ -#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */ -#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */ -#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */ -#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */ -/* bits 30 and 31 are obsoleted (for indirect access) */ - -/* for further details see the ACPI and PCI power management specification */ -#define SNDRV_CTL_POWER_D0 0x0000 /* full On */ -#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */ -#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */ -#define SNDRV_CTL_POWER_D3 0x0300 /* Off */ -#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */ -#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */ - -struct snd_ctl_elem_id { - unsigned int numid; /* numeric identifier, zero = invalid */ - snd_ctl_elem_iface_t iface; /* interface identifier */ - unsigned int device; /* device/client number */ - unsigned int subdevice; /* subdevice (substream) number */ - unsigned char name[44]; /* ASCII name of item */ - unsigned int index; /* index of item */ -}; - -struct snd_ctl_elem_list { - unsigned int offset; /* W: first element ID to get */ - unsigned int space; /* W: count of element IDs to get */ - unsigned int used; /* R: count of element IDs set */ - unsigned int count; /* R: count of all elements */ - struct snd_ctl_elem_id __user *pids; /* R: IDs */ - unsigned char reserved[50]; -}; - -struct snd_ctl_elem_info { - struct snd_ctl_elem_id id; /* W: element ID */ - snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */ - unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */ - unsigned int count; /* count of values */ - __kernel_pid_t owner; /* owner's PID of this control */ - union { - struct { - long min; /* R: minimum value */ - long max; /* R: maximum value */ - long step; /* R: step (0 variable) */ - } integer; - struct { - long long min; /* R: minimum value */ - long long max; /* R: maximum value */ - long long step; /* R: step (0 variable) */ - } integer64; - struct { - unsigned int items; /* R: number of items */ - unsigned int item; /* W: item number */ - char name[64]; /* R: value name */ - __u64 names_ptr; /* W: names list (ELEM_ADD only) */ - unsigned int names_length; - } enumerated; - unsigned char reserved[128]; - } value; - union { - unsigned short d[4]; /* dimensions */ - unsigned short *d_ptr; /* indirect - obsoleted */ - } dimen; - unsigned char reserved[64-4*sizeof(unsigned short)]; -}; - -struct snd_ctl_elem_value { - struct snd_ctl_elem_id id; /* W: element ID */ - unsigned int indirect: 1; /* W: indirect access - obsoleted */ - union { - union { - long value[128]; - long *value_ptr; /* obsoleted */ - } integer; - union { - long long value[64]; - long long *value_ptr; /* obsoleted */ - } integer64; - union { - unsigned int item[128]; - unsigned int *item_ptr; /* obsoleted */ - } enumerated; - union { - unsigned char data[512]; - unsigned char *data_ptr; /* obsoleted */ - } bytes; - struct snd_aes_iec958 iec958; - } value; /* RO */ - struct timespec tstamp; - unsigned char reserved[128-sizeof(struct timespec)]; -}; - -struct snd_ctl_tlv { - unsigned int numid; /* control element numeric identification */ - unsigned int length; /* in bytes aligned to 4 */ - unsigned int tlv[0]; /* first TLV */ -}; - -#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int) -#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info) -#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list) -#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info) -#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value) -#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value) -#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id) -#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id) -#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int) -#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info) -#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info) -#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id) -#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv) -#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv) -#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv) -#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int) -#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info) -#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int) -#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info) -#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int) -#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int) -#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info) -#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int) -#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int) -#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int) - -/* - * Read interface. - */ - -enum sndrv_ctl_event_type { - SNDRV_CTL_EVENT_ELEM = 0, - SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM, -}; - -#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */ -#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */ -#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */ -#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */ -#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */ - -struct snd_ctl_event { - int type; /* event type - SNDRV_CTL_EVENT_* */ - union { - struct { - unsigned int mask; - struct snd_ctl_elem_id id; - } elem; - unsigned char data8[60]; - } data; -}; - -/* - * Control names - */ - -#define SNDRV_CTL_NAME_NONE "" -#define SNDRV_CTL_NAME_PLAYBACK "Playback " -#define SNDRV_CTL_NAME_CAPTURE "Capture " - -#define SNDRV_CTL_NAME_IEC958_NONE "" -#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch" -#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume" -#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default" -#define SNDRV_CTL_NAME_IEC958_MASK "Mask" -#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask" -#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask" -#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream" -#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what - -#endif /* _UAPI__SOUND_ASOUND_H */ diff --git a/trunk/include/uapi/sound/emu10k1.h b/trunk/include/uapi/sound/emu10k1.h deleted file mode 100644 index d1bbaf78457a..000000000000 --- a/trunk/include/uapi/sound/emu10k1.h +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela , - * Creative Labs, Inc. - * Definitions for EMU10K1 (SB Live!) chips - * - * - * 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 _UAPI__SOUND_EMU10K1_H -#define _UAPI__SOUND_EMU10K1_H - -#include - - - -/* - * ---- FX8010 ---- - */ - -#define EMU10K1_CARD_CREATIVE 0x00000000 -#define EMU10K1_CARD_EMUAPS 0x00000001 - -#define EMU10K1_FX8010_PCM_COUNT 8 - -/* instruction set */ -#define iMAC0 0x00 /* R = A + (X * Y >> 31) ; saturation */ -#define iMAC1 0x01 /* R = A + (-X * Y >> 31) ; saturation */ -#define iMAC2 0x02 /* R = A + (X * Y >> 31) ; wraparound */ -#define iMAC3 0x03 /* R = A + (-X * Y >> 31) ; wraparound */ -#define iMACINT0 0x04 /* R = A + X * Y ; saturation */ -#define iMACINT1 0x05 /* R = A + X * Y ; wraparound (31-bit) */ -#define iACC3 0x06 /* R = A + X + Y ; saturation */ -#define iMACMV 0x07 /* R = A, acc += X * Y >> 31 */ -#define iANDXOR 0x08 /* R = (A & X) ^ Y */ -#define iTSTNEG 0x09 /* R = (A >= Y) ? X : ~X */ -#define iLIMITGE 0x0a /* R = (A >= Y) ? X : Y */ -#define iLIMITLT 0x0b /* R = (A < Y) ? X : Y */ -#define iLOG 0x0c /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */ -#define iEXP 0x0d /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */ -#define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */ -#define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */ - -/* GPRs */ -#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */ -#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */ -#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */ -#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */ - /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */ - -#define C_00000000 0x40 -#define C_00000001 0x41 -#define C_00000002 0x42 -#define C_00000003 0x43 -#define C_00000004 0x44 -#define C_00000008 0x45 -#define C_00000010 0x46 -#define C_00000020 0x47 -#define C_00000100 0x48 -#define C_00010000 0x49 -#define C_00080000 0x4a -#define C_10000000 0x4b -#define C_20000000 0x4c -#define C_40000000 0x4d -#define C_80000000 0x4e -#define C_7fffffff 0x4f -#define C_ffffffff 0x50 -#define C_fffffffe 0x51 -#define C_c0000000 0x52 -#define C_4f1bbcdc 0x53 -#define C_5a7ef9db 0x54 -#define C_00100000 0x55 /* ?? */ -#define GPR_ACCU 0x56 /* ACCUM, accumulator */ -#define GPR_COND 0x57 /* CCR, condition register */ -#define GPR_NOISE0 0x58 /* noise source */ -#define GPR_NOISE1 0x59 /* noise source */ -#define GPR_IRQ 0x5a /* IRQ register */ -#define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */ -#define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */ -#define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ -#define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ -#define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */ -#define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */ - -#define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ -#define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ -#define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ -#define A_ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ -#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ -#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ - -#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */ -#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */ -#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */ -#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */ -#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */ -#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */ -#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */ -#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */ -#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */ -#define A_GPR(x) (A_FXGPREGBASE + (x)) - -/* cc_reg constants */ -#define CC_REG_NORMALIZED C_00000001 -#define CC_REG_BORROW C_00000002 -#define CC_REG_MINUS C_00000004 -#define CC_REG_ZERO C_00000008 -#define CC_REG_SATURATE C_00000010 -#define CC_REG_NONZERO C_00000100 - -/* FX buses */ -#define FXBUS_PCM_LEFT 0x00 -#define FXBUS_PCM_RIGHT 0x01 -#define FXBUS_PCM_LEFT_REAR 0x02 -#define FXBUS_PCM_RIGHT_REAR 0x03 -#define FXBUS_MIDI_LEFT 0x04 -#define FXBUS_MIDI_RIGHT 0x05 -#define FXBUS_PCM_CENTER 0x06 -#define FXBUS_PCM_LFE 0x07 -#define FXBUS_PCM_LEFT_FRONT 0x08 -#define FXBUS_PCM_RIGHT_FRONT 0x09 -#define FXBUS_MIDI_REVERB 0x0c -#define FXBUS_MIDI_CHORUS 0x0d -#define FXBUS_PCM_LEFT_SIDE 0x0e -#define FXBUS_PCM_RIGHT_SIDE 0x0f -#define FXBUS_PT_LEFT 0x14 -#define FXBUS_PT_RIGHT 0x15 - -/* Inputs */ -#define EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */ -#define EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */ -#define EXTIN_SPDIF_CD_L 0x02 /* internal S/PDIF CD - onboard - left */ -#define EXTIN_SPDIF_CD_R 0x03 /* internal S/PDIF CD - onboard - right */ -#define EXTIN_ZOOM_L 0x04 /* Zoom Video I2S - left */ -#define EXTIN_ZOOM_R 0x05 /* Zoom Video I2S - right */ -#define EXTIN_TOSLINK_L 0x06 /* LiveDrive - TOSLink Optical - left */ -#define EXTIN_TOSLINK_R 0x07 /* LiveDrive - TOSLink Optical - right */ -#define EXTIN_LINE1_L 0x08 /* LiveDrive - Line/Mic 1 - left */ -#define EXTIN_LINE1_R 0x09 /* LiveDrive - Line/Mic 1 - right */ -#define EXTIN_COAX_SPDIF_L 0x0a /* LiveDrive - Coaxial S/PDIF - left */ -#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */ -#define EXTIN_LINE2_L 0x0c /* LiveDrive - Line/Mic 2 - left */ -#define EXTIN_LINE2_R 0x0d /* LiveDrive - Line/Mic 2 - right */ - -/* Outputs */ -#define EXTOUT_AC97_L 0x00 /* AC'97 playback channel - left */ -#define EXTOUT_AC97_R 0x01 /* AC'97 playback channel - right */ -#define EXTOUT_TOSLINK_L 0x02 /* LiveDrive - TOSLink Optical - left */ -#define EXTOUT_TOSLINK_R 0x03 /* LiveDrive - TOSLink Optical - right */ -#define EXTOUT_AC97_CENTER 0x04 /* SB Live 5.1 - center */ -#define EXTOUT_AC97_LFE 0x05 /* SB Live 5.1 - LFE */ -#define EXTOUT_HEADPHONE_L 0x06 /* LiveDrive - Headphone - left */ -#define EXTOUT_HEADPHONE_R 0x07 /* LiveDrive - Headphone - right */ -#define EXTOUT_REAR_L 0x08 /* Rear channel - left */ -#define EXTOUT_REAR_R 0x09 /* Rear channel - right */ -#define EXTOUT_ADC_CAP_L 0x0a /* ADC Capture buffer - left */ -#define EXTOUT_ADC_CAP_R 0x0b /* ADC Capture buffer - right */ -#define EXTOUT_MIC_CAP 0x0c /* MIC Capture buffer */ -#define EXTOUT_AC97_REAR_L 0x0d /* SB Live 5.1 (c) 2003 - Rear Left */ -#define EXTOUT_AC97_REAR_R 0x0e /* SB Live 5.1 (c) 2003 - Rear Right */ -#define EXTOUT_ACENTER 0x11 /* Analog Center */ -#define EXTOUT_ALFE 0x12 /* Analog LFE */ - -/* Audigy Inputs */ -#define A_EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */ -#define A_EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */ -#define A_EXTIN_SPDIF_CD_L 0x02 /* digital CD left */ -#define A_EXTIN_SPDIF_CD_R 0x03 /* digital CD left */ -#define A_EXTIN_OPT_SPDIF_L 0x04 /* audigy drive Optical SPDIF - left */ -#define A_EXTIN_OPT_SPDIF_R 0x05 /* right */ -#define A_EXTIN_LINE2_L 0x08 /* audigy drive line2/mic2 - left */ -#define A_EXTIN_LINE2_R 0x09 /* right */ -#define A_EXTIN_ADC_L 0x0a /* Philips ADC - left */ -#define A_EXTIN_ADC_R 0x0b /* right */ -#define A_EXTIN_AUX2_L 0x0c /* audigy drive aux2 - left */ -#define A_EXTIN_AUX2_R 0x0d /* - right */ - -/* Audigiy Outputs */ -#define A_EXTOUT_FRONT_L 0x00 /* digital front left */ -#define A_EXTOUT_FRONT_R 0x01 /* right */ -#define A_EXTOUT_CENTER 0x02 /* digital front center */ -#define A_EXTOUT_LFE 0x03 /* digital front lfe */ -#define A_EXTOUT_HEADPHONE_L 0x04 /* headphone audigy drive left */ -#define A_EXTOUT_HEADPHONE_R 0x05 /* right */ -#define A_EXTOUT_REAR_L 0x06 /* digital rear left */ -#define A_EXTOUT_REAR_R 0x07 /* right */ -#define A_EXTOUT_AFRONT_L 0x08 /* analog front left */ -#define A_EXTOUT_AFRONT_R 0x09 /* right */ -#define A_EXTOUT_ACENTER 0x0a /* analog center */ -#define A_EXTOUT_ALFE 0x0b /* analog LFE */ -#define A_EXTOUT_ASIDE_L 0x0c /* analog side left - Audigy 2 ZS */ -#define A_EXTOUT_ASIDE_R 0x0d /* right - Audigy 2 ZS */ -#define A_EXTOUT_AREAR_L 0x0e /* analog rear left */ -#define A_EXTOUT_AREAR_R 0x0f /* right */ -#define A_EXTOUT_AC97_L 0x10 /* AC97 left (front) */ -#define A_EXTOUT_AC97_R 0x11 /* right */ -#define A_EXTOUT_ADC_CAP_L 0x16 /* ADC capture buffer left */ -#define A_EXTOUT_ADC_CAP_R 0x17 /* right */ -#define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */ - -/* Audigy constants */ -#define A_C_00000000 0xc0 -#define A_C_00000001 0xc1 -#define A_C_00000002 0xc2 -#define A_C_00000003 0xc3 -#define A_C_00000004 0xc4 -#define A_C_00000008 0xc5 -#define A_C_00000010 0xc6 -#define A_C_00000020 0xc7 -#define A_C_00000100 0xc8 -#define A_C_00010000 0xc9 -#define A_C_00000800 0xca -#define A_C_10000000 0xcb -#define A_C_20000000 0xcc -#define A_C_40000000 0xcd -#define A_C_80000000 0xce -#define A_C_7fffffff 0xcf -#define A_C_ffffffff 0xd0 -#define A_C_fffffffe 0xd1 -#define A_C_c0000000 0xd2 -#define A_C_4f1bbcdc 0xd3 -#define A_C_5a7ef9db 0xd4 -#define A_C_00100000 0xd5 -#define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */ -#define A_GPR_COND 0xd7 /* CCR, condition register */ -#define A_GPR_NOISE0 0xd8 /* noise source */ -#define A_GPR_NOISE1 0xd9 /* noise source */ -#define A_GPR_IRQ 0xda /* IRQ register */ -#define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */ -#define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */ - -/* definitions for debug register */ -#define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */ -#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */ -#define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */ -#define EMU10K1_DBG_SINGLE_STEP 0x00008000 /* single step mode */ -#define EMU10K1_DBG_STEP 0x00004000 /* start single step */ -#define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */ -#define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */ - -/* tank memory address line */ -#ifndef __KERNEL__ -#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */ -#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */ -#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */ -#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */ -#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */ -#endif - -struct snd_emu10k1_fx8010_info { - unsigned int internal_tram_size; /* in samples */ - unsigned int external_tram_size; /* in samples */ - char fxbus_names[16][32]; /* names of FXBUSes */ - char extin_names[16][32]; /* names of external inputs */ - char extout_names[32][32]; /* names of external outputs */ - unsigned int gpr_controls; /* count of GPR controls */ -}; - -#define EMU10K1_GPR_TRANSLATION_NONE 0 -#define EMU10K1_GPR_TRANSLATION_TABLE100 1 -#define EMU10K1_GPR_TRANSLATION_BASS 2 -#define EMU10K1_GPR_TRANSLATION_TREBLE 3 -#define EMU10K1_GPR_TRANSLATION_ONOFF 4 - -struct snd_emu10k1_fx8010_control_gpr { - struct snd_ctl_elem_id id; /* full control ID definition */ - unsigned int vcount; /* visible count */ - unsigned int count; /* count of GPR (1..16) */ - unsigned short gpr[32]; /* GPR number(s) */ - unsigned int value[32]; /* initial values */ - unsigned int min; /* minimum range */ - unsigned int max; /* maximum range */ - unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ - const unsigned int *tlv; -}; - -/* old ABI without TLV support */ -struct snd_emu10k1_fx8010_control_old_gpr { - struct snd_ctl_elem_id id; - unsigned int vcount; - unsigned int count; - unsigned short gpr[32]; - unsigned int value[32]; - unsigned int min; - unsigned int max; - unsigned int translation; -}; - -struct snd_emu10k1_fx8010_code { - char name[128]; - - DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */ - __u32 __user *gpr_map; /* initializers */ - - unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */ - struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */ - - unsigned int gpr_del_control_count; /* count of GPR controls to remove */ - struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */ - - unsigned int gpr_list_control_count; /* count of GPR controls to list */ - unsigned int gpr_list_control_total; /* total count of GPR controls */ - struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */ - - DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */ - __u32 __user *tram_data_map; /* data initializers */ - __u32 __user *tram_addr_map; /* map initializers */ - - DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */ - __u32 __user *code; /* one instruction - 64 bits */ -}; - -struct snd_emu10k1_fx8010_tram { - unsigned int address; /* 31.bit == 1 -> external TRAM */ - unsigned int size; /* size in samples (4 bytes) */ - unsigned int *samples; /* pointer to samples (20-bit) */ - /* NULL->clear memory */ -}; - -struct snd_emu10k1_fx8010_pcm_rec { - unsigned int substream; /* substream number */ - unsigned int res1; /* reserved */ - unsigned int channels; /* 16-bit channels count, zero = remove this substream */ - unsigned int tram_start; /* ring buffer position in TRAM (in samples) */ - unsigned int buffer_size; /* count of buffered samples */ - unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */ - unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */ - unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */ - unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */ - unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */ - unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */ - unsigned char pad; /* reserved */ - unsigned char etram[32]; /* external TRAM address & data (one per channel) */ - unsigned int res2; /* reserved */ -}; - -#define SNDRV_EMU10K1_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1) - -#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info) -#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code) -#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code) -#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int) -#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram) -#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram) -#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec) -#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec) -#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int) -#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80) -#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81) -#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82) -#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int) -#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int) - -/* typedefs for compatibility to user-space */ -typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t; -typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t; -typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t; -typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t; -typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t; - -#endif /* _UAPI__SOUND_EMU10K1_H */ diff --git a/trunk/include/uapi/sound/sb16_csp.h b/trunk/include/uapi/sound/sb16_csp.h deleted file mode 100644 index 3b96907e2afb..000000000000 --- a/trunk/include/uapi/sound/sb16_csp.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 1999 by Uros Bizjak - * Takashi Iwai - * - * SB16ASP/AWE32 CSP control - * - * 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 _UAPI__SOUND_SB16_CSP_H -#define _UAPI__SOUND_SB16_CSP_H - - -/* CSP modes */ -#define SNDRV_SB_CSP_MODE_NONE 0x00 -#define SNDRV_SB_CSP_MODE_DSP_READ 0x01 /* Record from DSP */ -#define SNDRV_SB_CSP_MODE_DSP_WRITE 0x02 /* Play to DSP */ -#define SNDRV_SB_CSP_MODE_QSOUND 0x04 /* QSound */ - -/* CSP load flags */ -#define SNDRV_SB_CSP_LOAD_FROMUSER 0x01 -#define SNDRV_SB_CSP_LOAD_INITBLOCK 0x02 - -/* CSP sample width */ -#define SNDRV_SB_CSP_SAMPLE_8BIT 0x01 -#define SNDRV_SB_CSP_SAMPLE_16BIT 0x02 - -/* CSP channels */ -#define SNDRV_SB_CSP_MONO 0x01 -#define SNDRV_SB_CSP_STEREO 0x02 - -/* CSP rates */ -#define SNDRV_SB_CSP_RATE_8000 0x01 -#define SNDRV_SB_CSP_RATE_11025 0x02 -#define SNDRV_SB_CSP_RATE_22050 0x04 -#define SNDRV_SB_CSP_RATE_44100 0x08 -#define SNDRV_SB_CSP_RATE_ALL 0x0f - -/* CSP running state */ -#define SNDRV_SB_CSP_ST_IDLE 0x00 -#define SNDRV_SB_CSP_ST_LOADED 0x01 -#define SNDRV_SB_CSP_ST_RUNNING 0x02 -#define SNDRV_SB_CSP_ST_PAUSED 0x04 -#define SNDRV_SB_CSP_ST_AUTO 0x08 -#define SNDRV_SB_CSP_ST_QSOUND 0x10 - -/* maximum QSound value (180 degrees right) */ -#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT 0x20 - -/* maximum microcode RIFF file size */ -#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000 - -/* microcode header */ -struct snd_sb_csp_mc_header { - char codec_name[16]; /* id name of codec */ - unsigned short func_req; /* requested function */ -}; - -/* microcode to be loaded */ -struct snd_sb_csp_microcode { - struct snd_sb_csp_mc_header info; - unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE]; -}; - -/* start CSP with sample_width in mono/stereo */ -struct snd_sb_csp_start { - int sample_width; /* sample width, look above */ - int channels; /* channels, look above */ -}; - -/* CSP information */ -struct snd_sb_csp_info { - char codec_name[16]; /* id name of codec */ - unsigned short func_nr; /* function number */ - unsigned int acc_format; /* accepted PCM formats */ - unsigned short acc_channels; /* accepted channels */ - unsigned short acc_width; /* accepted sample width */ - unsigned short acc_rates; /* accepted sample rates */ - unsigned short csp_mode; /* CSP mode, see above */ - unsigned short run_channels; /* current channels */ - unsigned short run_width; /* current sample width */ - unsigned short version; /* version id: 0x10 - 0x1f */ - unsigned short state; /* state bits */ -}; - -/* HWDEP controls */ -/* get CSP information */ -#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info) -/* load microcode to CSP */ -/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits) - * defined for some architectures like MIPS, and it leads to build errors. - * (x86 and co have 14-bit size, thus it's valid, though.) - * As a workaround for skipping the size-limit check, here we don't use the - * normal _IOW() macro but _IOC() with the manual argument. - */ -#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \ - _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode)) -/* unload microcode from CSP */ -#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12) -/* start CSP */ -#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, struct snd_sb_csp_start) -/* stop CSP */ -#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14) -/* pause CSP and DMA transfer */ -#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15) -/* restart CSP and DMA transfer */ -#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16) - - -#endif /* _UAPI__SOUND_SB16_CSP_H */ diff --git a/trunk/lib/mpi/longlong.h b/trunk/lib/mpi/longlong.h index 678ce4f1e124..095ab157a521 100644 --- a/trunk/lib/mpi/longlong.h +++ b/trunk/lib/mpi/longlong.h @@ -641,7 +641,14 @@ do { \ ************** MIPS ***************** ***************************************/ #if defined(__mips__) && W_TYPE_SIZE == 32 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + UDItype __ll = (UDItype)(u) * (v); \ + w1 = __ll >> 32; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("multu %2,%3" \ : "=l" ((USItype)(w0)), \ @@ -666,7 +673,15 @@ do { \ ************** MIPS/64 ************** ***************************************/ #if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ + __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ + w1 = __ll >> 64; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("dmultu %2,%3" \ : "=l" ((UDItype)(w0)), \ diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index 7bb35ac0964a..bcb72c6e2b2d 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -1405,7 +1405,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) mt = get_pageblock_migratetype(page); if (unlikely(mt != MIGRATE_ISOLATE)) - __mod_zone_freepage_state(zone, -(1UL << order), mt); + __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt); if (alloc_order != order) expand(zone, page, alloc_order, order, diff --git a/trunk/net/core/net-sysfs.c b/trunk/net/core/net-sysfs.c index bcf02f608cbf..017a8bacfb27 100644 --- a/trunk/net/core/net-sysfs.c +++ b/trunk/net/core/net-sysfs.c @@ -429,6 +429,17 @@ static struct attribute_group netstat_group = { .name = "statistics", .attrs = netstat_attrs, }; + +#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) +static struct attribute *wireless_attrs[] = { + NULL +}; + +static struct attribute_group wireless_group = { + .name = "wireless", + .attrs = wireless_attrs, +}; +#endif #endif /* CONFIG_SYSFS */ #ifdef CONFIG_RPS @@ -1409,6 +1420,15 @@ int netdev_register_kobject(struct net_device *net) groups++; *groups++ = &netstat_group; + +#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) + if (net->ieee80211_ptr) + *groups++ = &wireless_group; +#if IS_ENABLED(CONFIG_WIRELESS_EXT) + else if (net->wireless_handlers) + *groups++ = &wireless_group; +#endif +#endif #endif /* CONFIG_SYSFS */ error = device_add(dev); diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index a8c651216fa6..df251424d816 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -1785,6 +1785,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, if (dev_out->flags & IFF_LOOPBACK) flags |= RTCF_LOCAL; + do_cache = true; if (type == RTN_BROADCAST) { flags |= RTCF_BROADCAST | RTCF_LOCAL; fi = NULL; @@ -1793,6 +1794,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr, fl4->flowi4_proto)) flags &= ~RTCF_LOCAL; + else + do_cache = false; /* If multicast route do not exist use * default one, but do not gateway in this case. * Yes, it is hack. @@ -1802,8 +1805,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, } fnhe = NULL; - do_cache = fi != NULL; - if (fi) { + do_cache &= fi != NULL; + if (do_cache) { struct rtable __rcu **prth; struct fib_nh *nh = &FIB_RES_NH(*res); @@ -2597,7 +2600,7 @@ int __init ip_rt_init(void) pr_err("Unable to create route proc files\n"); #ifdef CONFIG_XFRM xfrm_init(); - xfrm4_init(ip_rt_max_size); + xfrm4_init(); #endif rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL); diff --git a/trunk/net/ipv4/xfrm4_policy.c b/trunk/net/ipv4/xfrm4_policy.c index 05c5ab8d983c..3be0ac2c1920 100644 --- a/trunk/net/ipv4/xfrm4_policy.c +++ b/trunk/net/ipv4/xfrm4_policy.c @@ -279,19 +279,8 @@ static void __exit xfrm4_policy_fini(void) xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo); } -void __init xfrm4_init(int rt_max_size) +void __init xfrm4_init(void) { - /* - * Select a default value for the gc_thresh based on the main route - * table hash size. It seems to me the worst case scenario is when - * we have ipsec operating in transport mode, in which we create a - * dst_entry per socket. The xfrm gc algorithm starts trying to remove - * entries at gc_thresh, and prevents new allocations as 2*gc_thresh - * so lets set an initial xfrm gc_thresh value at the rt_max_size/2. - * That will let us store an ipsec connection per route table entry, - * and start cleaning when were 1/2 full - */ - xfrm4_dst_ops.gc_thresh = rt_max_size/2; dst_entries_init(&xfrm4_dst_ops); xfrm4_state_init(); diff --git a/trunk/net/ipv6/inet6_connection_sock.c b/trunk/net/ipv6/inet6_connection_sock.c index c4f934176cab..30647857a375 100644 --- a/trunk/net/ipv6/inet6_connection_sock.c +++ b/trunk/net/ipv6/inet6_connection_sock.c @@ -252,6 +252,7 @@ struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu) return NULL; dst->ops->update_pmtu(dst, sk, NULL, mtu); - return inet6_csk_route_socket(sk, &fl6); + dst = inet6_csk_route_socket(sk, &fl6); + return IS_ERR(dst) ? NULL : dst; } EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu); diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index bf87c70ac6c5..c21e33d1abd0 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -1151,10 +1151,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->u.ibss.mtx); - sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; - memset(sdata->u.ibss.bssid, 0, ETH_ALEN); - sdata->u.ibss.ssid_len = 0; - active_ibss = ieee80211_sta_active_ibss(sdata); if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { @@ -1175,6 +1171,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) } } + ifibss->state = IEEE80211_IBSS_MLME_SEARCH; + memset(ifibss->bssid, 0, ETH_ALEN); + ifibss->ssid_len = 0; + sta_info_flush(sdata->local, sdata); spin_lock_bh(&ifibss->incomplete_lock); diff --git a/trunk/net/netfilter/ipset/ip_set_hash_ip.c b/trunk/net/netfilter/ipset/ip_set_hash_ip.c index ec3dba5dcd62..5c0b78528e55 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_ip.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_ip.c @@ -173,6 +173,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], return adtfn(set, &nip, timeout, flags); } + ip_to = ip; if (tb[IPSET_ATTR_IP_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) @@ -185,8 +186,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], if (!cidr || cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); - } else - ip_to = ip; + } hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); diff --git a/trunk/net/netfilter/ipset/ip_set_hash_ipport.c b/trunk/net/netfilter/ipset/ip_set_hash_ipport.c index 0171f7502fa5..6283351f4eeb 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_ipport.c @@ -162,7 +162,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport4_elem data = { }; - u32 ip, ip_to = 0, p = 0, port, port_to; + u32 ip, ip_to, p = 0, port, port_to; u32 timeout = h->timeout; bool with_ports = false; int ret; @@ -210,7 +210,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], return ip_set_eexist(ret, flags) ? 0 : ret; } - ip = ntohl(data.ip); + ip_to = ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) @@ -223,8 +223,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], if (!cidr || cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); - } else - ip_to = ip; + } port_to = port = ntohs(data.port); if (with_ports && tb[IPSET_ATTR_PORT_TO]) { diff --git a/trunk/net/netfilter/ipset/ip_set_hash_ipportip.c b/trunk/net/netfilter/ipset/ip_set_hash_ipportip.c index 6344ef551ec8..6a21271c8d5a 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_ipportip.c @@ -166,7 +166,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip4_elem data = { }; - u32 ip, ip_to = 0, p = 0, port, port_to; + u32 ip, ip_to, p = 0, port, port_to; u32 timeout = h->timeout; bool with_ports = false; int ret; @@ -218,7 +218,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], return ip_set_eexist(ret, flags) ? 0 : ret; } - ip = ntohl(data.ip); + ip_to = ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) @@ -231,8 +231,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], if (!cidr || cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); - } else - ip_to = ip; + } port_to = port = ntohs(data.port); if (with_ports && tb[IPSET_ATTR_PORT_TO]) { diff --git a/trunk/net/netfilter/ipset/ip_set_hash_ipportnet.c b/trunk/net/netfilter/ipset/ip_set_hash_ipportnet.c index cb71f9a774e7..2d5cd4ee30eb 100644 --- a/trunk/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/trunk/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -215,8 +215,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 }; - u32 ip, ip_to = 0, p = 0, port, port_to; - u32 ip2_from = 0, ip2_to, ip2_last, ip2; + u32 ip, ip_to, p = 0, port, port_to; + u32 ip2_from, ip2_to, ip2_last, ip2; u32 timeout = h->timeout; bool with_ports = false; u8 cidr; @@ -286,6 +286,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], return ip_set_eexist(ret, flags) ? 0 : ret; } + ip_to = ip; if (tb[IPSET_ATTR_IP_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) @@ -306,6 +307,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], if (port > port_to) swap(port, port_to); } + + ip2_to = ip2_from; if (tb[IPSET_ATTR_IP2_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to); if (ret) diff --git a/trunk/net/netfilter/nfnetlink_cttimeout.c b/trunk/net/netfilter/nfnetlink_cttimeout.c index 8847b4d8be06..701c88a20fea 100644 --- a/trunk/net/netfilter/nfnetlink_cttimeout.c +++ b/trunk/net/netfilter/nfnetlink_cttimeout.c @@ -41,7 +41,8 @@ MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tu static LIST_HEAD(cttimeout_list); static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = { - [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING }, + [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING, + .len = CTNL_TIMEOUT_NAME_MAX - 1}, [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 }, [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 }, [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED }, diff --git a/trunk/net/nfc/llcp/llcp.c b/trunk/net/nfc/llcp/llcp.c index cc10d073c338..9e8f4b2801f6 100644 --- a/trunk/net/nfc/llcp/llcp.c +++ b/trunk/net/nfc/llcp/llcp.c @@ -1210,7 +1210,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) local->remote_miu = LLCP_DEFAULT_MIU; local->remote_lto = LLCP_DEFAULT_LTO; - list_add(&llcp_devices, &local->list); + list_add(&local->list, &llcp_devices); return 0; } diff --git a/trunk/scripts/sign-file b/trunk/scripts/sign-file index 87ca59d36e7e..974a20b661b7 100755 --- a/trunk/scripts/sign-file +++ b/trunk/scripts/sign-file @@ -156,12 +156,12 @@ sub asn1_extract($$@) if ($l == 0x1) { $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); - } elsif ($l = 0x2) { + } elsif ($l == 0x2) { $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); - } elsif ($l = 0x3) { + } elsif ($l == 0x3) { $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); - } elsif ($l = 0x4) { + } elsif ($l == 0x4) { $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); } else { die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; diff --git a/trunk/security/selinux/netnode.c b/trunk/security/selinux/netnode.c index 28f911cdd7c7..c5454c0477c3 100644 --- a/trunk/security/selinux/netnode.c +++ b/trunk/security/selinux/netnode.c @@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node) if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) { struct sel_netnode *tail; tail = list_entry( - rcu_dereference(sel_netnode_hash[idx].list.prev), + rcu_dereference_protected(sel_netnode_hash[idx].list.prev, + lockdep_is_held(&sel_netnode_lock)), struct sel_netnode, list); list_del_rcu(&tail->list); kfree_rcu(tail, rcu); diff --git a/trunk/sound/core/oss/pcm_plugin.c b/trunk/sound/core/oss/pcm_plugin.c index 727ac44d39f4..71cc3ddf5c15 100644 --- a/trunk/sound/core/oss/pcm_plugin.c +++ b/trunk/sound/core/oss/pcm_plugin.c @@ -199,13 +199,12 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin) snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames) { struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next; - int stream; + int stream = snd_pcm_plug_stream(plug); if (snd_BUG_ON(!plug)) return -ENXIO; if (drv_frames == 0) return 0; - stream = snd_pcm_plug_stream(plug); if (stream == SNDRV_PCM_STREAM_PLAYBACK) { plugin = snd_pcm_plug_last(plug); while (plugin && drv_frames > 0) { @@ -231,14 +230,13 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc { struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next; snd_pcm_sframes_t frames; - int stream; + int stream = snd_pcm_plug_stream(plug); if (snd_BUG_ON(!plug)) return -ENXIO; if (clt_frames == 0) return 0; frames = clt_frames; - stream = snd_pcm_plug_stream(plug); if (stream == SNDRV_PCM_STREAM_PLAYBACK) { plugin = snd_pcm_plug_first(plug); while (plugin && frames > 0) { diff --git a/trunk/sound/core/pcm.c b/trunk/sound/core/pcm.c index 61798f85d030..030102caeee9 100644 --- a/trunk/sound/core/pcm.c +++ b/trunk/sound/core/pcm.c @@ -981,7 +981,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))); kfree(runtime->hw_constraints.rules); #ifdef CONFIG_SND_PCM_XRUN_DEBUG - kfree(runtime->hwptr_log); + if (runtime->hwptr_log) + kfree(runtime->hwptr_log); #endif kfree(runtime); substream->runtime = NULL; diff --git a/trunk/sound/core/pcm_compat.c b/trunk/sound/core/pcm_compat.c index af49721ba0e3..91cdf9435fec 100644 --- a/trunk/sound/core/pcm_compat.c +++ b/trunk/sound/core/pcm_compat.c @@ -190,9 +190,7 @@ struct snd_pcm_status32 { u32 avail_max; u32 overrange; s32 suspended_state; - u32 reserved_alignment; - struct compat_timespec audio_tstamp; - unsigned char reserved[56-sizeof(struct compat_timespec)]; + unsigned char reserved[60]; } __attribute__((packed)); @@ -207,16 +205,17 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, return err; if (put_user(status.state, &src->state) || - compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || - compat_put_timespec(&status.tstamp, &src->tstamp) || + put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) || + put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) || + put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || + put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || put_user(status.appl_ptr, &src->appl_ptr) || put_user(status.hw_ptr, &src->hw_ptr) || put_user(status.delay, &src->delay) || put_user(status.avail, &src->avail) || put_user(status.avail_max, &src->avail_max) || put_user(status.overrange, &src->overrange) || - put_user(status.suspended_state, &src->suspended_state) || - compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp)) + put_user(status.suspended_state, &src->suspended_state)) return -EFAULT; return err; @@ -365,7 +364,6 @@ struct snd_pcm_mmap_status32 { u32 hw_ptr; struct compat_timespec tstamp; s32 suspended_state; - struct compat_timespec audio_tstamp; } __attribute__((packed)); struct snd_pcm_mmap_control32 { @@ -428,14 +426,12 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, sstatus.hw_ptr = status->hw_ptr % boundary; sstatus.tstamp = status->tstamp; sstatus.suspended_state = status->suspended_state; - sstatus.audio_tstamp = status->audio_tstamp; snd_pcm_stream_unlock_irq(substream); if (put_user(sstatus.state, &src->s.status.state) || put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || - compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || + put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) || + put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) || put_user(sstatus.suspended_state, &src->s.status.suspended_state) || - compat_put_timespec(&sstatus.audio_tstamp, - &src->s.status.audio_tstamp) || put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || put_user(scontrol.avail_min, &src->c.control.avail_min)) return -EFAULT; diff --git a/trunk/sound/core/pcm_lib.c b/trunk/sound/core/pcm_lib.c index c4840ff75d00..f42c10a43315 100644 --- a/trunk/sound/core/pcm_lib.c +++ b/trunk/sound/core/pcm_lib.c @@ -316,8 +316,6 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, unsigned long jdelta; unsigned long curr_jiffies; struct timespec curr_tstamp; - struct timespec audio_tstamp; - int crossed_boundary = 0; old_hw_ptr = runtime->status->hw_ptr; @@ -329,14 +327,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, */ pos = substream->ops->pointer(substream); curr_jiffies = jiffies; - if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { + if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); - if ((runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK) && - (substream->ops->wall_clock)) - substream->ops->wall_clock(substream, &audio_tstamp); - } - if (pos == SNDRV_PCM_POS_XRUN) { xrun(substream); return -EPIPE; @@ -367,10 +360,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, hdelta = curr_jiffies - runtime->hw_ptr_jiffies; if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { hw_base += runtime->buffer_size; - if (hw_base >= runtime->boundary) { + if (hw_base >= runtime->boundary) hw_base = 0; - crossed_boundary++; - } new_hw_ptr = hw_base + pos; goto __delta; } @@ -380,10 +371,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, /* pointer crosses the end of the ring buffer */ if (new_hw_ptr < old_hw_ptr) { hw_base += runtime->buffer_size; - if (hw_base >= runtime->boundary) { + if (hw_base >= runtime->boundary) hw_base = 0; - crossed_boundary++; - } new_hw_ptr = hw_base + pos; } __delta: @@ -421,10 +410,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, while (hdelta > xrun_threshold) { delta += runtime->buffer_size; hw_base += runtime->buffer_size; - if (hw_base >= runtime->boundary) { + if (hw_base >= runtime->boundary) hw_base = 0; - crossed_boundary++; - } new_hw_ptr = hw_base + pos; hdelta -= runtime->hw_ptr_buffer_jiffies; } @@ -469,10 +456,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, /* the delta value is small or zero in most cases */ while (delta > 0) { new_hw_ptr += runtime->period_size; - if (new_hw_ptr >= runtime->boundary) { + if (new_hw_ptr >= runtime->boundary) new_hw_ptr -= runtime->boundary; - crossed_boundary--; - } delta--; } /* align hw_base to buffer_size */ @@ -522,35 +507,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; runtime->hw_ptr_jiffies = curr_jiffies; - if (crossed_boundary) { - snd_BUG_ON(crossed_boundary != 1); - runtime->hw_ptr_wrap += runtime->boundary; - } - if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { + if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) runtime->status->tstamp = curr_tstamp; - if (!(runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK)) { - /* - * no wall clock available, provide audio timestamp - * derived from pointer position+delay - */ - u64 audio_frames, audio_nsecs; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - audio_frames = runtime->hw_ptr_wrap - + runtime->status->hw_ptr - - runtime->delay; - else - audio_frames = runtime->hw_ptr_wrap - + runtime->status->hw_ptr - + runtime->delay; - audio_nsecs = div_u64(audio_frames * 1000000000LL, - runtime->rate); - audio_tstamp = ns_to_timespec(audio_nsecs); - } - runtime->status->audio_tstamp = audio_tstamp; - } - return snd_pcm_update_state(substream, runtime); } @@ -1702,10 +1661,8 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, if (snd_pcm_running(substream) && snd_pcm_update_hw_ptr(substream) >= 0) runtime->status->hw_ptr %= runtime->buffer_size; - else { + else runtime->status->hw_ptr = 0; - runtime->hw_ptr_wrap = 0; - } snd_pcm_stream_unlock_irqrestore(substream, flags); return 0; } diff --git a/trunk/sound/core/pcm_native.c b/trunk/sound/core/pcm_native.c index 09b4286c65f9..f9ddecf2f4cd 100644 --- a/trunk/sound/core/pcm_native.c +++ b/trunk/sound/core/pcm_native.c @@ -602,8 +602,6 @@ int snd_pcm_status(struct snd_pcm_substream *substream, snd_pcm_update_hw_ptr(substream); if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { status->tstamp = runtime->status->tstamp; - status->audio_tstamp = - runtime->status->audio_tstamp; goto _tstamp_end; } } @@ -2000,7 +1998,7 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) if (runtime->dma_bytes) { err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes); if (err < 0) - return err; + return -EINVAL; } if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) { diff --git a/trunk/sound/drivers/Kconfig b/trunk/sound/drivers/Kconfig index 7d02c322ed93..fe5ae09ffccb 100644 --- a/trunk/sound/drivers/Kconfig +++ b/trunk/sound/drivers/Kconfig @@ -14,7 +14,6 @@ config SND_OPL4_LIB config SND_VX_LIB tristate - select FW_LOADER select SND_HWDEP select SND_PCM @@ -36,6 +35,7 @@ config SND_PCSP tristate "PC-Speaker support (READ HELP!)" depends on PCSPKR_PLATFORM && X86 && HIGH_RES_TIMERS depends on INPUT + depends on EXPERIMENTAL select SND_PCM help If you don't have a sound card in your computer, you can include a diff --git a/trunk/sound/drivers/aloop.c b/trunk/sound/drivers/aloop.c index 1904046686e2..0fe6d64ff840 100644 --- a/trunk/sound/drivers/aloop.c +++ b/trunk/sound/drivers/aloop.c @@ -120,6 +120,7 @@ struct loopback_pcm { unsigned int last_drift; unsigned long last_jiffies; struct timer_list timer; + spinlock_t timer_lock; }; static struct platform_device *devices[SNDRV_CARDS]; @@ -165,12 +166,12 @@ static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm) return get_setup(dpcm)->rate_shift; } -/* call in cable->lock */ static void loopback_timer_start(struct loopback_pcm *dpcm) { unsigned long tick; unsigned int rate_shift = get_rate_shift(dpcm); + spin_lock(&dpcm->timer_lock); if (rate_shift != dpcm->pcm_rate_shift) { dpcm->pcm_rate_shift = rate_shift; dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); @@ -183,13 +184,15 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; dpcm->timer.expires = jiffies + tick; add_timer(&dpcm->timer); + spin_unlock(&dpcm->timer_lock); } -/* call in cable->lock */ static inline void loopback_timer_stop(struct loopback_pcm *dpcm) { + spin_lock(&dpcm->timer_lock); del_timer(&dpcm->timer); dpcm->timer.expires = 0; + spin_unlock(&dpcm->timer_lock); } #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) @@ -271,8 +274,8 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock(&cable->lock); cable->running |= stream; cable->pause &= ~stream; - loopback_timer_start(dpcm); spin_unlock(&cable->lock); + loopback_timer_start(dpcm); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); break; @@ -280,23 +283,23 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock(&cable->lock); cable->running &= ~stream; cable->pause &= ~stream; - loopback_timer_stop(dpcm); spin_unlock(&cable->lock); + loopback_timer_stop(dpcm); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) loopback_active_notify(dpcm); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: spin_lock(&cable->lock); cable->pause |= stream; - loopback_timer_stop(dpcm); spin_unlock(&cable->lock); + loopback_timer_stop(dpcm); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: spin_lock(&cable->lock); dpcm->last_jiffies = jiffies; cable->pause &= ~stream; - loopback_timer_start(dpcm); spin_unlock(&cable->lock); + loopback_timer_start(dpcm); break; default: return -EINVAL; @@ -474,7 +477,6 @@ static inline void bytepos_finish(struct loopback_pcm *dpcm, dpcm->buf_pos %= dpcm->pcm_buffer_size; } -/* call in cable->lock */ static unsigned int loopback_pos_update(struct loopback_cable *cable) { struct loopback_pcm *dpcm_play = @@ -483,7 +485,9 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable) cable->streams[SNDRV_PCM_STREAM_CAPTURE]; unsigned long delta_play = 0, delta_capt = 0; unsigned int running, count1, count2; + unsigned long flags; + spin_lock_irqsave(&cable->lock, flags); running = cable->running ^ cable->pause; if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { delta_play = jiffies - dpcm_play->last_jiffies; @@ -525,39 +529,32 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable) bytepos_finish(dpcm_play, count1); bytepos_finish(dpcm_capt, count1); unlock: + spin_unlock_irqrestore(&cable->lock, flags); return running; } static void loopback_timer_function(unsigned long data) { struct loopback_pcm *dpcm = (struct loopback_pcm *)data; - unsigned long flags; + unsigned int running; - spin_lock_irqsave(&dpcm->cable->lock, flags); - if (loopback_pos_update(dpcm->cable) & (1 << dpcm->substream->stream)) { + running = loopback_pos_update(dpcm->cable); + if (running & (1 << dpcm->substream->stream)) { loopback_timer_start(dpcm); if (dpcm->period_update_pending) { dpcm->period_update_pending = 0; - spin_unlock_irqrestore(&dpcm->cable->lock, flags); - /* need to unlock before calling below */ snd_pcm_period_elapsed(dpcm->substream); - return; } } - spin_unlock_irqrestore(&dpcm->cable->lock, flags); } static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct loopback_pcm *dpcm = runtime->private_data; - snd_pcm_uframes_t pos; - spin_lock(&dpcm->cable->lock); loopback_pos_update(dpcm->cable); - pos = dpcm->buf_pos; - spin_unlock(&dpcm->cable->lock); - return bytes_to_frames(runtime, pos); + return bytes_to_frames(runtime, dpcm->buf_pos); } static struct snd_pcm_hardware loopback_pcm_hardware = @@ -675,6 +672,7 @@ static int loopback_open(struct snd_pcm_substream *substream) dpcm->substream = substream; setup_timer(&dpcm->timer, loopback_timer_function, (unsigned long)dpcm); + spin_lock_init(&dpcm->timer_lock); cable = loopback->cables[substream->number][dev]; if (!cable) { diff --git a/trunk/sound/drivers/dummy.c b/trunk/sound/drivers/dummy.c index 4f522cf48455..54bb6644a598 100644 --- a/trunk/sound/drivers/dummy.c +++ b/trunk/sound/drivers/dummy.c @@ -134,9 +134,6 @@ struct snd_dummy { spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST+1][2]; int capture_source[MIXER_ADDR_LAST+1][2]; - int iobox; - struct snd_kcontrol *cd_volume_ctl; - struct snd_kcontrol *cd_switch_ctl; const struct dummy_timer_ops *timer_ops; }; @@ -820,57 +817,6 @@ static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el return change; } -static int snd_dummy_iobox_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - const char *const names[] = { "None", "CD Player" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int snd_dummy_iobox_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - - value->value.enumerated.item[0] = dummy->iobox; - return 0; -} - -static int snd_dummy_iobox_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - int changed; - - if (value->value.enumerated.item[0] > 1) - return -EINVAL; - - changed = value->value.enumerated.item[0] != dummy->iobox; - if (changed) { - dummy->iobox = value->value.enumerated.item[0]; - - if (dummy->iobox) { - dummy->cd_volume_ctl->vd[0].access &= - ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - dummy->cd_switch_ctl->vd[0].access &= - ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - } else { - dummy->cd_volume_ctl->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_INACTIVE; - dummy->cd_switch_ctl->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_INACTIVE; - } - - snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO, - &dummy->cd_volume_ctl->id); - snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO, - &dummy->cd_switch_ctl->id); - } - - return changed; -} - static struct snd_kcontrol_new snd_dummy_controls[] = { DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER), DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER), @@ -881,37 +827,22 @@ DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE), DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC), DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC), DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD), -DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "External I/O Box", - .info = snd_dummy_iobox_info, - .get = snd_dummy_iobox_get, - .put = snd_dummy_iobox_put, -}, +DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD) }; static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) { struct snd_card *card = dummy->card; - struct snd_kcontrol *kcontrol; unsigned int idx; int err; spin_lock_init(&dummy->mixer_lock); strcpy(card->mixername, "Dummy Mixer"); - dummy->iobox = 1; for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) { - kcontrol = snd_ctl_new1(&snd_dummy_controls[idx], dummy); - err = snd_ctl_add(card, kcontrol); + err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy)); if (err < 0) return err; - if (!strcmp(kcontrol->id.name, "CD Volume")) - dummy->cd_volume_ctl = kcontrol; - else if (!strcmp(kcontrol->id.name, "CD Capture Switch")) - dummy->cd_switch_ctl = kcontrol; - } return 0; } diff --git a/trunk/sound/drivers/vx/vx_hwdep.c b/trunk/sound/drivers/vx/vx_hwdep.c index 3014b86362bd..4a1fae99ac55 100644 --- a/trunk/sound/drivers/vx/vx_hwdep.c +++ b/trunk/sound/drivers/vx/vx_hwdep.c @@ -29,6 +29,8 @@ #include #include +#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"); @@ -117,5 +119,142 @@ void snd_vx_free_firmware(struct vx_core *chip) #endif } +#else /* old style firmware loading */ + +static int vx_hwdep_dsp_status(struct snd_hwdep *hw, + struct snd_hwdep_dsp_status *info) +{ + static char *type_ids[VX_TYPE_NUMS] = { + [VX_TYPE_BOARD] = "vxboard", + [VX_TYPE_V2] = "vx222", + [VX_TYPE_MIC] = "vx222", + [VX_TYPE_VXPOCKET] = "vxpocket", + [VX_TYPE_VXP440] = "vxp440", + }; + struct vx_core *vx = hw->private_data; + + if (snd_BUG_ON(!type_ids[vx->type])) + return -EINVAL; + strcpy(info->id, type_ids[vx->type]); + if (vx_is_pcmcia(vx)) + info->num_dsps = 4; + else + info->num_dsps = 3; + if (vx->chip_status & VX_STAT_CHIP_INIT) + info->chip_ready = 1; + info->version = VX_DRIVER_VERSION; + return 0; +} + +static void free_fw(const struct firmware *fw) +{ + if (fw) { + vfree(fw->data); + kfree(fw); + } +} + +static int vx_hwdep_dsp_load(struct snd_hwdep *hw, + struct snd_hwdep_dsp_image *dsp) +{ + struct vx_core *vx = hw->private_data; + int index, err; + struct firmware *fw; + + if (snd_BUG_ON(!vx->ops->load_dsp)) + return -ENXIO; + + fw = kmalloc(sizeof(*fw), GFP_KERNEL); + if (! fw) { + snd_printk(KERN_ERR "cannot allocate firmware\n"); + return -ENOMEM; + } + fw->size = dsp->length; + fw->data = vmalloc(fw->size); + if (! fw->data) { + snd_printk(KERN_ERR "cannot allocate firmware image (length=%d)\n", + (int)fw->size); + kfree(fw); + return -ENOMEM; + } + if (copy_from_user((void *)fw->data, dsp->image, dsp->length)) { + free_fw(fw); + return -EFAULT; + } + + index = dsp->index; + if (! vx_is_pcmcia(vx)) + index++; + err = vx->ops->load_dsp(vx, index, fw); + if (err < 0) { + free_fw(fw); + return err; + } +#ifdef CONFIG_PM + vx->firmware[index] = fw; +#else + free_fw(fw); +#endif + + if (index == 1) + vx->chip_status |= VX_STAT_XILINX_LOADED; + if (index < 3) + return 0; + + /* ok, we reached to the last one */ + /* create the devices if not built yet */ + if (! (vx->chip_status & VX_STAT_DEVICE_INIT)) { + if ((err = snd_vx_pcm_new(vx)) < 0) + return err; + + if ((err = snd_vx_mixer_new(vx)) < 0) + return err; + + if (vx->ops->add_controls) + if ((err = vx->ops->add_controls(vx)) < 0) + return err; + + if ((err = snd_card_register(vx->card)) < 0) + return err; + + vx->chip_status |= VX_STAT_DEVICE_INIT; + } + vx->chip_status |= VX_STAT_CHIP_INIT; + return 0; +} + + +/* exported */ +int snd_vx_setup_firmware(struct vx_core *chip) +{ + int err; + struct snd_hwdep *hw; + + if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0) + return err; + + hw->iface = SNDRV_HWDEP_IFACE_VX; + hw->private_data = chip; + hw->ops.dsp_status = vx_hwdep_dsp_status; + hw->ops.dsp_load = vx_hwdep_dsp_load; + hw->exclusive = 1; + sprintf(hw->name, "VX Loader (%s)", chip->card->driver); + chip->hwdep = hw; + + return snd_card_register(chip->card); +} + +/* exported */ +void snd_vx_free_firmware(struct vx_core *chip) +{ +#ifdef CONFIG_PM + int i; + for (i = 0; i < 4; i++) + free_fw(chip->firmware[i]); +#endif +} + +#endif /* SND_VX_FW_LOADER */ + EXPORT_SYMBOL(snd_vx_setup_firmware); EXPORT_SYMBOL(snd_vx_free_firmware); diff --git a/trunk/sound/firewire/Kconfig b/trunk/sound/firewire/Kconfig index ea063e1f8722..26071489970b 100644 --- a/trunk/sound/firewire/Kconfig +++ b/trunk/sound/firewire/Kconfig @@ -33,17 +33,4 @@ config SND_ISIGHT To compile this driver as a module, choose M here: the module will be called snd-isight. -config SND_SCS1X - tristate "Stanton Control System 1 MIDI" - select SND_PCM - select SND_RAWMIDI - select SND_FIREWIRE_LIB - help - Say Y here to include support for the MIDI ports of the Stanton - SCS.1d/SCS.1m DJ controllers. (SCS.1m audio is still handled - by FFADO.) - - To compile this driver as a module, choose M here: the module - will be called snd-scs1x. - endif # SND_FIREWIRE diff --git a/trunk/sound/firewire/Makefile b/trunk/sound/firewire/Makefile index 460179df5bb5..d71ed8935f76 100644 --- a/trunk/sound/firewire/Makefile +++ b/trunk/sound/firewire/Makefile @@ -2,9 +2,7 @@ snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \ fcp.o cmp.o amdtp.o snd-firewire-speakers-objs := speakers.o snd-isight-objs := isight.o -snd-scs1x-objs := scs1x.o obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o obj-$(CONFIG_SND_ISIGHT) += snd-isight.o -obj-$(CONFIG_SND_SCS1X) += snd-scs1x.o diff --git a/trunk/sound/firewire/scs1x.c b/trunk/sound/firewire/scs1x.c deleted file mode 100644 index 844a555c3b1e..000000000000 --- a/trunk/sound/firewire/scs1x.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Stanton Control System 1 MIDI driver - * - * Copyright (c) Clemens Ladisch - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lib.h" - -#define OUI_STANTON 0x001260 -#define MODEL_SCS_1M 0x001000 -#define MODEL_SCS_1D 0x002000 - -#define HSS1394_ADDRESS 0xc007dedadadaULL -#define HSS1394_MAX_PACKET_SIZE 64 - -#define HSS1394_TAG_USER_DATA 0x00 -#define HSS1394_TAG_CHANGE_ADDRESS 0xf1 - -struct scs { - struct snd_card *card; - struct fw_unit *unit; - struct fw_address_handler hss_handler; - struct fw_transaction transaction; - bool transaction_running; - bool output_idle; - u8 output_status; - u8 output_bytes; - bool output_escaped; - bool output_escape_high_nibble; - u8 input_escape_count; - struct snd_rawmidi_substream *output; - struct snd_rawmidi_substream *input; - struct tasklet_struct tasklet; - wait_queue_head_t idle_wait; - u8 *buffer; -}; - -static const u8 sysex_escape_prefix[] = { - 0xf0, /* SysEx begin */ - 0x00, 0x01, 0x60, /* Stanton DJ */ - 0x48, 0x53, 0x53, /* "HSS" */ -}; - -static int scs_output_open(struct snd_rawmidi_substream *stream) -{ - struct scs *scs = stream->rmidi->private_data; - - scs->output_status = 0; - scs->output_bytes = 1; - scs->output_escaped = false; - - return 0; -} - -static int scs_output_close(struct snd_rawmidi_substream *stream) -{ - return 0; -} - -static void scs_output_trigger(struct snd_rawmidi_substream *stream, int up) -{ - struct scs *scs = stream->rmidi->private_data; - - ACCESS_ONCE(scs->output) = up ? stream : NULL; - if (up) { - scs->output_idle = false; - tasklet_schedule(&scs->tasklet); - } -} - -static void scs_write_callback(struct fw_card *card, int rcode, - void *data, size_t length, void *callback_data) -{ - struct scs *scs = callback_data; - - if (rcode == RCODE_GENERATION) { - /* TODO: retry this packet */ - } - - scs->transaction_running = false; - tasklet_schedule(&scs->tasklet); -} - -static bool is_valid_running_status(u8 status) -{ - return status >= 0x80 && status <= 0xef; -} - -static bool is_one_byte_cmd(u8 status) -{ - return status == 0xf6 || - status >= 0xf8; -} - -static bool is_two_bytes_cmd(u8 status) -{ - return (status >= 0xc0 && status <= 0xdf) || - status == 0xf1 || - status == 0xf3; -} - -static bool is_three_bytes_cmd(u8 status) -{ - return (status >= 0x80 && status <= 0xbf) || - (status >= 0xe0 && status <= 0xef) || - status == 0xf2; -} - -static bool is_invalid_cmd(u8 status) -{ - return status == 0xf4 || - status == 0xf5 || - status == 0xf9 || - status == 0xfd; -} - -static void scs_output_tasklet(unsigned long data) -{ - struct scs *scs = (void *)data; - struct snd_rawmidi_substream *stream; - unsigned int i; - u8 byte; - struct fw_device *dev; - int generation; - - if (scs->transaction_running) - return; - - stream = ACCESS_ONCE(scs->output); - if (!stream) { - scs->output_idle = true; - wake_up(&scs->idle_wait); - return; - } - - i = scs->output_bytes; - for (;;) { - if (snd_rawmidi_transmit(stream, &byte, 1) != 1) { - scs->output_bytes = i; - scs->output_idle = true; - wake_up(&scs->idle_wait); - return; - } - /* - * Convert from real MIDI to what I think the device expects (no - * running status, one command per packet, unescaped SysExs). - */ - if (scs->output_escaped && byte < 0x80) { - if (scs->output_escape_high_nibble) { - if (i < HSS1394_MAX_PACKET_SIZE) { - scs->buffer[i] = byte << 4; - scs->output_escape_high_nibble = false; - } - } else { - scs->buffer[i++] |= byte & 0x0f; - scs->output_escape_high_nibble = true; - } - } else if (byte < 0x80) { - if (i == 1) { - if (!is_valid_running_status(scs->output_status)) - continue; - scs->buffer[0] = HSS1394_TAG_USER_DATA; - scs->buffer[i++] = scs->output_status; - } - scs->buffer[i++] = byte; - if ((i == 3 && is_two_bytes_cmd(scs->output_status)) || - (i == 4 && is_three_bytes_cmd(scs->output_status))) - break; - if (i == 1 + ARRAY_SIZE(sysex_escape_prefix) && - !memcmp(scs->buffer + 1, sysex_escape_prefix, - ARRAY_SIZE(sysex_escape_prefix))) { - scs->output_escaped = true; - scs->output_escape_high_nibble = true; - i = 0; - } - if (i >= HSS1394_MAX_PACKET_SIZE) - i = 1; - } else if (byte == 0xf7) { - if (scs->output_escaped) { - if (i >= 1 && scs->output_escape_high_nibble && - scs->buffer[0] != HSS1394_TAG_CHANGE_ADDRESS) - break; - } else { - if (i > 1 && scs->output_status == 0xf0) { - scs->buffer[i++] = 0xf7; - break; - } - } - i = 1; - scs->output_escaped = false; - } else if (!is_invalid_cmd(byte) && - byte < 0xf8) { - i = 1; - scs->buffer[0] = HSS1394_TAG_USER_DATA; - scs->buffer[i++] = byte; - scs->output_status = byte; - scs->output_escaped = false; - if (is_one_byte_cmd(byte)) - break; - } - } - scs->output_bytes = 1; - scs->output_escaped = false; - - scs->transaction_running = true; - dev = fw_parent_device(scs->unit); - generation = dev->generation; - smp_rmb(); /* node_id vs. generation */ - fw_send_request(dev->card, &scs->transaction, TCODE_WRITE_BLOCK_REQUEST, - dev->node_id, generation, dev->max_speed, - HSS1394_ADDRESS, scs->buffer, i, - scs_write_callback, scs); -} - -static void scs_output_drain(struct snd_rawmidi_substream *stream) -{ - struct scs *scs = stream->rmidi->private_data; - - wait_event(scs->idle_wait, scs->output_idle); -} - -static struct snd_rawmidi_ops output_ops = { - .open = scs_output_open, - .close = scs_output_close, - .trigger = scs_output_trigger, - .drain = scs_output_drain, -}; - -static int scs_input_open(struct snd_rawmidi_substream *stream) -{ - struct scs *scs = stream->rmidi->private_data; - - scs->input_escape_count = 0; - - return 0; -} - -static int scs_input_close(struct snd_rawmidi_substream *stream) -{ - return 0; -} - -static void scs_input_trigger(struct snd_rawmidi_substream *stream, int up) -{ - struct scs *scs = stream->rmidi->private_data; - - ACCESS_ONCE(scs->input) = up ? stream : NULL; -} - -static void scs_input_escaped_byte(struct snd_rawmidi_substream *stream, - u8 byte) -{ - u8 nibbles[2]; - - nibbles[0] = byte >> 4; - nibbles[1] = byte & 0x0f; - snd_rawmidi_receive(stream, nibbles, 2); -} - -static void scs_input_midi_byte(struct scs *scs, - struct snd_rawmidi_substream *stream, - u8 byte) -{ - if (scs->input_escape_count > 0) { - scs_input_escaped_byte(stream, byte); - scs->input_escape_count--; - if (scs->input_escape_count == 0) - snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1); - } else if (byte == 0xf9) { - snd_rawmidi_receive(stream, sysex_escape_prefix, - ARRAY_SIZE(sysex_escape_prefix)); - scs_input_escaped_byte(stream, 0x00); - scs_input_escaped_byte(stream, 0xf9); - scs->input_escape_count = 3; - } else { - snd_rawmidi_receive(stream, &byte, 1); - } -} - -static void scs_input_packet(struct scs *scs, - struct snd_rawmidi_substream *stream, - const u8 *data, unsigned int bytes) -{ - unsigned int i; - - if (data[0] == HSS1394_TAG_USER_DATA) { - for (i = 1; i < bytes; ++i) - scs_input_midi_byte(scs, stream, data[i]); - } else { - snd_rawmidi_receive(stream, sysex_escape_prefix, - ARRAY_SIZE(sysex_escape_prefix)); - for (i = 0; i < bytes; ++i) - scs_input_escaped_byte(stream, data[i]); - snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1); - } -} - -static struct snd_rawmidi_ops input_ops = { - .open = scs_input_open, - .close = scs_input_close, - .trigger = scs_input_trigger, -}; - -static int scs_create_midi(struct scs *scs) -{ - struct snd_rawmidi *rmidi; - int err; - - err = snd_rawmidi_new(scs->card, "SCS.1x", 0, 1, 1, &rmidi); - if (err < 0) - return err; - snprintf(rmidi->name, sizeof(rmidi->name), - "%s MIDI", scs->card->shortname); - rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = scs; - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &output_ops); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &input_ops); - - return 0; -} - -static void handle_hss(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, int generation, - unsigned long long offset, void *data, size_t length, - void *callback_data) -{ - struct scs *scs = callback_data; - struct snd_rawmidi_substream *stream; - - if (offset != scs->hss_handler.offset) { - fw_send_response(card, request, RCODE_ADDRESS_ERROR); - return; - } - if (tcode != TCODE_WRITE_QUADLET_REQUEST && - tcode != TCODE_WRITE_BLOCK_REQUEST) { - fw_send_response(card, request, RCODE_TYPE_ERROR); - return; - } - - if (length >= 1) { - stream = ACCESS_ONCE(scs->input); - if (stream) - scs_input_packet(scs, stream, data, length); - } - - fw_send_response(card, request, RCODE_COMPLETE); -} - -static int scs_init_hss_address(struct scs *scs) -{ - __be64 data; - int err; - - data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) | - scs->hss_handler.offset); - err = snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST, - HSS1394_ADDRESS, &data, 8); - if (err < 0) - dev_err(&scs->unit->device, "HSS1394 communication failed\n"); - - return err; -} - -static void scs_card_free(struct snd_card *card) -{ - struct scs *scs = card->private_data; - - fw_core_remove_address_handler(&scs->hss_handler); - kfree(scs->buffer); -} - -static int scs_probe(struct device *unit_dev) -{ - struct fw_unit *unit = fw_unit(unit_dev); - struct fw_device *fw_dev = fw_parent_device(unit); - struct snd_card *card; - struct scs *scs; - int err; - - err = snd_card_create(-16, NULL, THIS_MODULE, sizeof(*scs), &card); - if (err < 0) - return err; - snd_card_set_dev(card, unit_dev); - - scs = card->private_data; - scs->card = card; - scs->unit = unit; - tasklet_init(&scs->tasklet, scs_output_tasklet, (unsigned long)scs); - init_waitqueue_head(&scs->idle_wait); - scs->output_idle = true; - - scs->buffer = kmalloc(HSS1394_MAX_PACKET_SIZE, GFP_KERNEL); - if (!scs->buffer) - goto err_card; - - scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE; - scs->hss_handler.address_callback = handle_hss; - scs->hss_handler.callback_data = scs; - err = fw_core_add_address_handler(&scs->hss_handler, - &fw_high_memory_region); - if (err < 0) - goto err_buffer; - - card->private_free = scs_card_free; - - strcpy(card->driver, "SCS.1x"); - strcpy(card->shortname, "SCS.1x"); - fw_csr_string(unit->directory, CSR_MODEL, - card->shortname, sizeof(card->shortname)); - snprintf(card->longname, sizeof(card->longname), - "Stanton DJ %s (GUID %08x%08x) at %s, S%d", - card->shortname, fw_dev->config_rom[3], fw_dev->config_rom[4], - dev_name(&unit->device), 100 << fw_dev->max_speed); - strcpy(card->mixername, card->shortname); - - err = scs_init_hss_address(scs); - if (err < 0) - goto err_card; - - err = scs_create_midi(scs); - if (err < 0) - goto err_card; - - err = snd_card_register(card); - if (err < 0) - goto err_card; - - dev_set_drvdata(unit_dev, scs); - - return 0; - -err_buffer: - kfree(scs->buffer); -err_card: - snd_card_free(card); - return err; -} - -static int scs_remove(struct device *dev) -{ - struct scs *scs = dev_get_drvdata(dev); - - snd_card_disconnect(scs->card); - - ACCESS_ONCE(scs->output) = NULL; - ACCESS_ONCE(scs->input) = NULL; - - wait_event(scs->idle_wait, scs->output_idle); - - tasklet_kill(&scs->tasklet); - - snd_card_free_when_closed(scs->card); - - return 0; -} - -static void scs_update(struct fw_unit *unit) -{ - struct scs *scs = dev_get_drvdata(&unit->device); - __be64 data; - - data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) | - scs->hss_handler.offset); - snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST, - HSS1394_ADDRESS, &data, 8); -} - -static const struct ieee1394_device_id scs_id_table[] = { - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID, - .vendor_id = OUI_STANTON, - .model_id = MODEL_SCS_1M, - }, - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID, - .vendor_id = OUI_STANTON, - .model_id = MODEL_SCS_1D, - }, - {} -}; -MODULE_DEVICE_TABLE(ieee1394, scs_id_table); - -MODULE_DESCRIPTION("SCS.1x MIDI driver"); -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_LICENSE("GPL v2"); - -static struct fw_driver scs_driver = { - .driver = { - .owner = THIS_MODULE, - .name = KBUILD_MODNAME, - .bus = &fw_bus_type, - .probe = scs_probe, - .remove = scs_remove, - }, - .update = scs_update, - .id_table = scs_id_table, -}; - -static int __init alsa_scs1x_init(void) -{ - return driver_register(&scs_driver.driver); -} - -static void __exit alsa_scs1x_exit(void) -{ - driver_unregister(&scs_driver.driver); -} - -module_init(alsa_scs1x_init); -module_exit(alsa_scs1x_exit); diff --git a/trunk/sound/isa/Kconfig b/trunk/sound/isa/Kconfig index affa13480659..a38d9643e9d8 100644 --- a/trunk/sound/isa/Kconfig +++ b/trunk/sound/isa/Kconfig @@ -425,7 +425,7 @@ config SND_WAVEFRONT config SND_MSND_PINNACLE tristate "Turtle Beach MultiSound Pinnacle/Fiji driver" - depends on X86 + depends on X86 && EXPERIMENTAL select FW_LOADER select SND_MPU401_UART select SND_PCM @@ -438,7 +438,7 @@ config SND_MSND_PINNACLE config SND_MSND_CLASSIC tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" - depends on X86 + depends on X86 && EXPERIMENTAL select FW_LOADER select SND_MPU401_UART select SND_PCM diff --git a/trunk/sound/oss/sb_audio.c b/trunk/sound/oss/sb_audio.c index 048439a16000..b2b3c014221a 100644 --- a/trunk/sound/oss/sb_audio.c +++ b/trunk/sound/oss/sb_audio.c @@ -442,7 +442,7 @@ static int sb201_audio_set_speed(int dev, int speed) { sb_devc *devc = audio_devs[dev]->devc; int tmp; - int s; + int s = speed * devc->channels; if (speed > 0) { @@ -452,7 +452,6 @@ static int sb201_audio_set_speed(int dev, int speed) speed = 44100; if (devc->opened & OPEN_READ && speed > 15000) speed = 15000; - s = speed * devc->channels; devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff; tmp = 256 - devc->tconst; speed = ((1000000 + tmp / 2) / tmp) / devc->channels; diff --git a/trunk/sound/pci/Kconfig b/trunk/sound/pci/Kconfig index 947cfb4eb30c..f99fa2512286 100644 --- a/trunk/sound/pci/Kconfig +++ b/trunk/sound/pci/Kconfig @@ -572,7 +572,6 @@ source "sound/pci/hda/Kconfig" config SND_HDSP tristate "RME Hammerfall DSP Audio" - select FW_LOADER select SND_HWDEP select SND_RAWMIDI select SND_PCM @@ -631,7 +630,7 @@ config SND_ICE1724 AudioTrak Prodigy 192, 7.1 (HIFI/LT/XT), HD2; Hercules Fortissimo IV; ESI Juli@; Pontis MS300; EGO-SYS WaveTerminal 192M; Albatron K8X800 Pro II; Chaintech ZNF3-150/250, 9CJS, - AV-710; Shuttle SN25P; Philips PSC724 Ultimate Edge. + AV-710; Shuttle SN25P. To compile this driver as a module, choose M here: the module will be called snd-ice1724. @@ -708,7 +707,6 @@ config SND_MAESTRO3_INPUT config SND_MIXART tristate "Digigram miXart" - select FW_LOADER select SND_HWDEP select SND_PCM help @@ -729,7 +727,6 @@ config SND_NM256 config SND_PCXHR tristate "Digigram PCXHR" - select FW_LOADER select SND_PCM select SND_HWDEP help diff --git a/trunk/sound/pci/asihpi/hpidspcd.c b/trunk/sound/pci/asihpi/hpidspcd.c index ac9163770013..456a758f04f6 100644 --- a/trunk/sound/pci/asihpi/hpidspcd.c +++ b/trunk/sound/pci/asihpi/hpidspcd.c @@ -49,12 +49,14 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code, err = request_firmware(&firmware, fw_name, &dev->dev); if (err || !firmware) { - dev_err(&dev->dev, "%d, request_firmware failed for %s\n", - err, fw_name); + dev_printk(KERN_ERR, &dev->dev, + "%d, request_firmware failed for %s\n", err, + fw_name); goto error1; } if (firmware->size < sizeof(header)) { - dev_err(&dev->dev, "Header size too small %s\n", fw_name); + dev_printk(KERN_ERR, &dev->dev, "Header size too small %s\n", + fw_name); goto error2; } memcpy(&header, firmware->data, sizeof(header)); @@ -62,7 +64,7 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code, if ((header.type != 0x45444F43) || /* "CODE" */ (header.adapter != adapter) || (header.size != firmware->size)) { - dev_err(&dev->dev, + dev_printk(KERN_ERR, &dev->dev, "Invalid firmware header size %d != file %zd\n", header.size, firmware->size); goto error2; @@ -70,15 +72,17 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code, if ((header.version >> 9) != (HPI_VER >> 9)) { /* Consider even and subsequent odd minor versions to be compatible */ - dev_err(&dev->dev, "Incompatible firmware version DSP image %X != Driver %X\n", - header.version, HPI_VER); + dev_printk(KERN_ERR, &dev->dev, + "Incompatible firmware version " + "DSP image %X != Driver %X\n", header.version, + HPI_VER); goto error2; } if (header.version != HPI_VER) { - dev_info(&dev->dev, - "Firmware: release version mismatch DSP image %X != Driver %X\n", - header.version, HPI_VER); + dev_printk(KERN_INFO, &dev->dev, + "Firmware: release version mismatch DSP image %X != Driver %X\n", + header.version, HPI_VER); } HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name); diff --git a/trunk/sound/pci/asihpi/hpioctl.c b/trunk/sound/pci/asihpi/hpioctl.c index 8f9674972376..609156205562 100644 --- a/trunk/sound/pci/asihpi/hpioctl.c +++ b/trunk/sound/pci/asihpi/hpioctl.c @@ -326,7 +326,7 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, pci_dev->subsystem_device, pci_dev->devfn); if (pci_enable_device(pci_dev) < 0) { - dev_err(&pci_dev->dev, + dev_printk(KERN_ERR, &pci_dev->dev, "pci_enable_device failed, disabling device\n"); return -EIO; } @@ -398,8 +398,9 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, mutex_init(&adapters[adapter_index].mutex); pci_set_drvdata(pci_dev, &adapters[adapter_index]); - dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n", - adapter.adapter->type, adapter_index); + dev_printk(KERN_INFO, &pci_dev->dev, + "probe succeeded for ASI%04X HPI index %d\n", + adapter.adapter->type, adapter_index); return 0; @@ -447,11 +448,11 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev) pci_set_drvdata(pci_dev, NULL); if (1) - dev_info(&pci_dev->dev, - "remove %04x:%04x,%04x:%04x,%04x, HPI index %d\n", - pci_dev->vendor, pci_dev->device, - pci_dev->subsystem_vendor, pci_dev->subsystem_device, - pci_dev->devfn, pa->adapter->index); + dev_printk(KERN_INFO, &pci_dev->dev, + "remove %04x:%04x,%04x:%04x,%04x," " HPI index %d.\n", + pci_dev->vendor, pci_dev->device, + pci_dev->subsystem_vendor, pci_dev->subsystem_device, + pci_dev->devfn, pa->adapter->index); memset(pa, 0, sizeof(*pa)); } diff --git a/trunk/sound/pci/au88x0/au88x0_core.c b/trunk/sound/pci/au88x0/au88x0_core.c index 2698abf5d05d..525f881f0409 100644 --- a/trunk/sound/pci/au88x0/au88x0_core.c +++ b/trunk/sound/pci/au88x0/au88x0_core.c @@ -2461,12 +2461,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id) #ifndef CHIP_AU8810 for (i = 0; i < NR_WT; i++) { if (vortex->dma_wt[i].fifo_status == FIFO_START) { - /* FIXME: we ignore the return value from - * vortex_wtdma_bufshift() below as the delta - * calculation seems not working for wavetable - * by some reason - */ - vortex_wtdma_bufshift(vortex, i); + if (vortex_wtdma_bufshift(vortex, i)) ; spin_unlock(&vortex->lock); snd_pcm_period_elapsed(vortex->dma_wt[i]. substream); diff --git a/trunk/sound/pci/emu10k1/emu10k1.c b/trunk/sound/pci/emu10k1/emu10k1.c index a168138efc5e..b7c1875ba90e 100644 --- a/trunk/sound/pci/emu10k1/emu10k1.c +++ b/trunk/sound/pci/emu10k1/emu10k1.c @@ -215,8 +215,6 @@ static int snd_emu10k1_suspend(struct device *dev) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - emu->suspend = 1; - snd_pcm_suspend_all(emu->pcm); snd_pcm_suspend_all(emu->pcm_mic); snd_pcm_suspend_all(emu->pcm_efx); @@ -262,8 +260,6 @@ static int snd_emu10k1_resume(struct device *dev) if (emu->card_capabilities->ca0151_chip) snd_p16v_resume(emu); - emu->suspend = 0; - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } diff --git a/trunk/sound/pci/emu10k1/emu10k1_main.c b/trunk/sound/pci/emu10k1/emu10k1_main.c index 527ef216d4ca..c21adb6ef1d5 100644 --- a/trunk/sound/pci/emu10k1/emu10k1_main.c +++ b/trunk/sound/pci/emu10k1/emu10k1_main.c @@ -657,17 +657,22 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) return 0; } -static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu) +static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filename) { + int err; int n, i; int reg; int value; unsigned int write_post; unsigned long flags; - const struct firmware *fw_entry = emu->firmware; + const struct firmware *fw_entry; - if (!fw_entry) - return -EIO; + err = request_firmware(&fw_entry, filename, &emu->pci->dev); + if (err != 0) { + snd_printk(KERN_ERR "firmware: %s not found. Err = %d\n", filename, err); + return err; + } + snd_printk(KERN_INFO "firmware size = 0x%zx\n", fw_entry->size); /* The FPGA is a Xilinx Spartan IIE XC2S50E */ /* GPIO7 -> FPGA PGMN @@ -700,6 +705,7 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu) write_post = inl(emu->port + A_IOCFG); spin_unlock_irqrestore(&emu->emu_lock, flags); + release_firmware(fw_entry); return 0; } @@ -714,10 +720,6 @@ static int emu1010_firmware_thread(void *data) msleep_interruptible(1000); if (kthread_should_stop()) break; -#ifdef CONFIG_PM_SLEEP - if (emu->suspend) - continue; -#endif snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { @@ -725,9 +727,22 @@ static int emu1010_firmware_thread(void *data) /* 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); - err = snd_emu1010_load_firmware(emu); - if (err != 0) - continue; + if (emu->card_capabilities->emu_model == + EMU_MODEL_EMU1010) { + err = snd_emu1010_load_firmware(emu, DOCK_FILENAME); + if (err != 0) + continue; + } else if (emu->card_capabilities->emu_model == + EMU_MODEL_EMU1010B) { + err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); + if (err != 0) + continue; + } else if (emu->card_capabilities->emu_model == + EMU_MODEL_EMU1616) { + err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); + if (err != 0) + continue; + } snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); @@ -792,6 +807,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) unsigned int i; u32 tmp, tmp2, reg; int err; + const char *filename = NULL; snd_printk(KERN_INFO "emu1010: Special config.\n"); /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, @@ -833,33 +849,31 @@ 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 (!emu->firmware) { - const char *filename; - switch (emu->card_capabilities->emu_model) { - case EMU_MODEL_EMU1010: - filename = HANA_FILENAME; - break; - case EMU_MODEL_EMU1010B: - filename = EMU1010B_FILENAME; - break; - case EMU_MODEL_EMU1616: - filename = EMU1010_NOTEBOOK_FILENAME; - break; - case EMU_MODEL_EMU0404: - filename = EMU0404_FILENAME; - break; - default: - return -ENODEV; - } - - err = request_firmware(&emu->firmware, filename, &emu->pci->dev); - if (err != 0) { - snd_printk(KERN_ERR "emu1010: firmware: %s not found. Err = %d\n", filename, err); - return err; - } - snd_printk(KERN_INFO "emu1010: firmware file = %s, size = 0x%zx\n", - filename, emu->firmware->size); + switch (emu->card_capabilities->emu_model) { + case EMU_MODEL_EMU1010: + filename = HANA_FILENAME; + break; + case EMU_MODEL_EMU1010B: + filename = EMU1010B_FILENAME; + break; + case EMU_MODEL_EMU1616: + filename = EMU1010_NOTEBOOK_FILENAME; + break; + case EMU_MODEL_EMU0404: + filename = EMU0404_FILENAME; + break; + default: + filename = NULL; + return -ENODEV; + break; + } + snd_printk(KERN_INFO "emu1010: filename %s testing\n", filename); + err = snd_emu1010_load_firmware(emu, filename); + if (err != 0) { + snd_printk( + KERN_INFO "emu1010: Loading Firmware file %s failed\n", + filename); + return err; } /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ @@ -1245,8 +1259,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) } if (emu->emu1010.firmware_thread) kthread_stop(emu->emu1010.firmware_thread); - if (emu->firmware) - release_firmware(emu->firmware); if (emu->irq >= 0) free_irq(emu->irq, emu); /* remove reserved page */ diff --git a/trunk/sound/pci/hda/Kconfig b/trunk/sound/pci/hda/Kconfig index 6eeb8897624b..7105c3de1bca 100644 --- a/trunk/sound/pci/hda/Kconfig +++ b/trunk/sound/pci/hda/Kconfig @@ -37,8 +37,8 @@ config SND_HDA_HWDEP with codecs for debugging purposes. config SND_HDA_RECONFIG - bool "Allow dynamic codec reconfiguration" - depends on SND_HDA_HWDEP + bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)" + depends on SND_HDA_HWDEP && EXPERIMENTAL help Say Y here to enable the HD-audio codec re-configuration feature. This adds the sysfs interfaces to allow user to clear the whole @@ -72,6 +72,7 @@ config SND_HDA_INPUT_JACK config SND_HDA_PATCH_LOADER bool "Support initialization patch loading for HD-audio" + depends on EXPERIMENTAL select FW_LOADER select SND_HDA_HWDEP select SND_HDA_RECONFIG diff --git a/trunk/sound/pci/hda/Makefile b/trunk/sound/pci/hda/Makefile index 24a251497a1f..bd4149f1aaf4 100644 --- a/trunk/sound/pci/hda/Makefile +++ b/trunk/sound/pci/hda/Makefile @@ -8,7 +8,6 @@ snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o # for trace-points CFLAGS_hda_codec.o := -I$(src) -CFLAGS_hda_intel.o := -I$(src) snd-hda-codec-realtek-objs := patch_realtek.o snd-hda-codec-cmedia-objs := patch_cmedia.o diff --git a/trunk/sound/pci/hda/hda_auto_parser.c b/trunk/sound/pci/hda/hda_auto_parser.c index 7da883a464e3..4ec6dc88b7f8 100644 --- a/trunk/sound/pci/hda/hda_auto_parser.c +++ b/trunk/sound/pci/hda/hda_auto_parser.c @@ -11,7 +11,6 @@ #include #include -#include #include #include "hda_codec.h" #include "hda_local.h" @@ -31,30 +30,29 @@ static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list) return 0; } -/* a pair of input pin and its sequence */ -struct auto_out_pin { - hda_nid_t pin; - short seq; -}; - -static int compare_seq(const void *ap, const void *bp) -{ - const struct auto_out_pin *a = ap; - const struct auto_out_pin *b = bp; - return (int)(a->seq - b->seq); -} /* * Sort an associated group of pins according to their sequence numbers. - * then store it to a pin array. */ -static void sort_pins_by_sequence(hda_nid_t *pins, struct auto_out_pin *list, +static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, int num_pins) { - int i; - sort(list, num_pins, sizeof(list[0]), compare_seq, NULL); - for (i = 0; i < num_pins; i++) - pins[i] = list[i].pin; + 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; + } + } + } } @@ -69,11 +67,21 @@ static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid, } } -static int compare_input_type(const void *ap, const void *bp) +/* sort inputs in the order of AUTO_PIN_* type */ +static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg) { - const struct auto_pin_cfg_item *a = ap; - const struct auto_pin_cfg_item *b = bp; - return (int)(a->type - b->type); + int i, j; + + for (i = 0; i < cfg->num_inputs; i++) { + for (j = i + 1; j < cfg->num_inputs; j++) { + if (cfg->inputs[i].type > cfg->inputs[j].type) { + struct auto_pin_cfg_item tmp; + tmp = cfg->inputs[i]; + cfg->inputs[i] = cfg->inputs[j]; + cfg->inputs[j] = tmp; + } + } + } } /* Reorder the surround channels @@ -121,16 +129,16 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, { hda_nid_t nid, end_nid; short seq, assoc_line_out; - struct auto_out_pin line_out[ARRAY_SIZE(cfg->line_out_pins)]; - struct auto_out_pin speaker_out[ARRAY_SIZE(cfg->speaker_pins)]; - struct auto_out_pin hp_out[ARRAY_SIZE(cfg->hp_pins)]; + short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; + short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; + short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; int i; memset(cfg, 0, sizeof(*cfg)); - memset(line_out, 0, sizeof(line_out)); - memset(speaker_out, 0, sizeof(speaker_out)); - memset(hp_out, 0, sizeof(hp_out)); + memset(sequences_line_out, 0, sizeof(sequences_line_out)); + memset(sequences_speaker, 0, sizeof(sequences_speaker)); + memset(sequences_hp, 0, sizeof(sequences_hp)); assoc_line_out = 0; end_nid = codec->start_nid + codec->num_nodes; @@ -176,8 +184,8 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, continue; if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) continue; - line_out[cfg->line_outs].pin = nid; - line_out[cfg->line_outs].seq = seq; + cfg->line_out_pins[cfg->line_outs] = nid; + sequences_line_out[cfg->line_outs] = seq; cfg->line_outs++; break; case AC_JACK_SPEAKER: @@ -185,8 +193,8 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, assoc = get_defcfg_association(def_conf); if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) continue; - speaker_out[cfg->speaker_outs].pin = nid; - speaker_out[cfg->speaker_outs].seq = (assoc << 4) | seq; + cfg->speaker_pins[cfg->speaker_outs] = nid; + sequences_speaker[cfg->speaker_outs] = (assoc << 4) | seq; cfg->speaker_outs++; break; case AC_JACK_HP_OUT: @@ -194,8 +202,8 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, assoc = get_defcfg_association(def_conf); if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) continue; - hp_out[cfg->hp_outs].pin = nid; - hp_out[cfg->hp_outs].seq = (assoc << 4) | seq; + cfg->hp_pins[cfg->hp_outs] = nid; + sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; cfg->hp_outs++; break; case AC_JACK_MIC_IN: @@ -240,28 +248,34 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, int i = 0; while (i < cfg->hp_outs) { /* The real HPs should have the sequence 0x0f */ - if ((hp_out[i].seq & 0x0f) == 0x0f) { + if ((sequences_hp[i] & 0x0f) == 0x0f) { i++; continue; } /* Move it to the line-out table */ - line_out[cfg->line_outs++] = hp_out[i]; + cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i]; + sequences_line_out[cfg->line_outs] = sequences_hp[i]; + cfg->line_outs++; cfg->hp_outs--; - memmove(hp_out + i, hp_out + i + 1, - sizeof(hp_out[0]) * (cfg->hp_outs - i)); + memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1, + sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i)); + memmove(sequences_hp + i, sequences_hp + i + 1, + sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); } - memset(hp_out + cfg->hp_outs, 0, - sizeof(hp_out[0]) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs)); + memset(cfg->hp_pins + cfg->hp_outs, 0, + sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs)); if (!cfg->hp_outs) cfg->line_out_type = AUTO_PIN_HP_OUT; } /* sort by sequence */ - sort_pins_by_sequence(cfg->line_out_pins, line_out, cfg->line_outs); - sort_pins_by_sequence(cfg->speaker_pins, speaker_out, + 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); - sort_pins_by_sequence(cfg->hp_pins, hp_out, cfg->hp_outs); + sort_pins_by_sequence(cfg->hp_pins, sequences_hp, + cfg->hp_outs); /* * FIX-UP: if no line-outs are detected, try to use speaker or HP pin @@ -290,9 +304,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, reorder_outputs(cfg->hp_outs, cfg->hp_pins); reorder_outputs(cfg->speaker_outs, cfg->speaker_pins); - /* sort inputs in the order of AUTO_PIN_* type */ - sort(cfg->inputs, cfg->num_inputs, sizeof(cfg->inputs[0]), - compare_input_type, NULL); + sort_autocfg_input_pins(cfg); /* * debug prints of the parsed results diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c index d05bcbb61077..d010de12335e 100644 --- a/trunk/sound/pci/hda/hda_codec.c +++ b/trunk/sound/pci/hda/hda_codec.c @@ -95,6 +95,7 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset) EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); #ifdef CONFIG_PM +#define codec_in_pm(codec) ((codec)->in_pm) static void hda_power_work(struct work_struct *work); static void hda_keep_power_on(struct hda_codec *codec); #define hda_codec_is_power_on(codec) ((codec)->power_on) @@ -104,6 +105,7 @@ static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up) bus->ops.pm_notify(bus, power_up); } #else +#define codec_in_pm(codec) 0 static inline void hda_keep_power_on(struct hda_codec *codec) {} #define hda_codec_is_power_on(codec) 1 #define hda_call_pm_notify(bus, state) {} @@ -228,7 +230,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, } mutex_unlock(&bus->cmd_mutex); snd_hda_power_down(codec); - if (!codec->in_pm && res && *res == -1 && bus->rirb_error) { + if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) { if (bus->response_reset) { snd_printd("hda_codec: resetting BUS due to " "fatal communication error\n"); @@ -238,7 +240,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, goto again; } /* clear reset-flag when the communication gets recovered */ - if (!err || codec->in_pm) + if (!err || codec_in_pm(codec)) bus->response_reset = 0; return err; } @@ -991,6 +993,19 @@ static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec, return NULL; } +/* write a config value for the given NID */ +static void set_pincfg(struct hda_codec *codec, hda_nid_t nid, + unsigned int cfg) +{ + int i; + for (i = 0; i < 4; i++) { + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, + cfg & 0xff); + cfg >>= 8; + } +} + /* set the current pin config value for the given NID. * the value is cached, and read via snd_hda_codec_get_pincfg() */ @@ -998,10 +1013,12 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, hda_nid_t nid, unsigned int cfg) { struct hda_pincfg *pin; + unsigned int oldcfg; if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) return -EINVAL; + oldcfg = snd_hda_codec_get_pincfg(codec, nid); pin = look_up_pincfg(codec, list, nid); if (!pin) { pin = snd_array_new(list); @@ -1010,6 +1027,13 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, pin->nid = nid; } pin->cfg = cfg; + + /* change only when needed; e.g. if the pincfg is already present + * in user_pins[], don't write it + */ + cfg = snd_hda_codec_get_pincfg(codec, nid); + if (oldcfg != cfg) + set_pincfg(codec, nid, cfg); return 0; } @@ -1058,6 +1082,17 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) } EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg); +/* restore all current pin configs */ +static void restore_pincfgs(struct hda_codec *codec) +{ + int i; + for (i = 0; i < codec->init_pins.used; i++) { + struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); + set_pincfg(codec, pin->nid, + snd_hda_codec_get_pincfg(codec, pin->nid)); + } +} + /** * snd_hda_shutup_pins - Shut up all pins * @codec: the HDA codec @@ -1102,30 +1137,21 @@ static void restore_shutup_pins(struct hda_codec *codec) } #endif -static void hda_jackpoll_work(struct work_struct *work) -{ - struct hda_codec *codec = - container_of(work, struct hda_codec, jackpoll_work.work); - if (!codec->jackpoll_interval) - return; - - snd_hda_jack_set_dirty_all(codec); - snd_hda_jack_poll_all(codec); - queue_delayed_work(codec->bus->workq, &codec->jackpoll_work, - codec->jackpoll_interval); -} - static void init_hda_cache(struct hda_cache_rec *cache, unsigned int record_size); static void free_hda_cache(struct hda_cache_rec *cache); -/* release all pincfg lists */ -static void free_init_pincfgs(struct hda_codec *codec) +/* restore the initial pin cfgs and release all pincfg lists */ +static void restore_init_pincfgs(struct hda_codec *codec) { + /* first free driver_pins and user_pins, then call restore_pincfg + * so that only the values in init_pins are restored + */ snd_array_free(&codec->driver_pins); #ifdef CONFIG_SND_HDA_HWDEP snd_array_free(&codec->user_pins); #endif + restore_pincfgs(codec); snd_array_free(&codec->init_pins); } @@ -1166,9 +1192,8 @@ static void snd_hda_codec_free(struct hda_codec *codec) { if (!codec) return; - cancel_delayed_work_sync(&codec->jackpoll_work); snd_hda_jack_tbl_clear(codec); - free_init_pincfgs(codec); + restore_init_pincfgs(codec); #ifdef CONFIG_PM cancel_delayed_work(&codec->power_work); flush_workqueue(codec->bus->workq); @@ -1250,8 +1275,6 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64); snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); - snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16); - INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); #ifdef CONFIG_PM spin_lock_init(&codec->power_lock); @@ -2130,12 +2153,12 @@ EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv); /* find a mixer control element with the given name */ static struct snd_kcontrol * -find_mixer_ctl(struct hda_codec *codec, const char *name, int dev, int idx) +_snd_hda_find_mixer_ctl(struct hda_codec *codec, + const char *name, int idx) { struct snd_ctl_elem_id id; memset(&id, 0, sizeof(id)); id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - id.device = dev; id.index = idx; if (snd_BUG_ON(strlen(name) >= sizeof(id.name))) return NULL; @@ -2153,16 +2176,15 @@ find_mixer_ctl(struct hda_codec *codec, const char *name, int dev, int idx) struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, const char *name) { - return find_mixer_ctl(codec, name, 0, 0); + return _snd_hda_find_mixer_ctl(codec, name, 0); } EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); -static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name, - int dev) +static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name) { int idx; for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */ - if (!find_mixer_ctl(codec, name, dev, idx)) + if (!_snd_hda_find_mixer_ctl(codec, name, idx)) return idx; } return -EBUSY; @@ -2329,7 +2351,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) return -EBUSY; /* OK, let it free */ - cancel_delayed_work_sync(&codec->jackpoll_work); + #ifdef CONFIG_PM cancel_delayed_work_sync(&codec->power_work); codec->power_on = 0; @@ -2358,6 +2380,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); /* free only driver_pins so that init_pins + user_pins are restored */ snd_array_free(&codec->driver_pins); + restore_pincfgs(codec); snd_array_free(&codec->cvt_setups); snd_array_free(&codec->spdif_out); codec->num_pcms = 0; @@ -3112,48 +3135,26 @@ static struct snd_kcontrol_new dig_mixes[] = { }; /** - * snd_hda_create_dig_out_ctls - create Output SPDIF-related controls + * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls * @codec: the HDA codec - * @associated_nid: NID that new ctls associated with - * @cvt_nid: converter NID - * @type: HDA_PCM_TYPE_* - * Creates controls related with the digital output. - * Called from each patch supporting the digital out. + * @nid: audio out widget NID + * + * Creates controls related with the SPDIF output. + * Called from each patch supporting the SPDIF out. * * Returns 0 if successful, or a negative error code. */ -int snd_hda_create_dig_out_ctls(struct hda_codec *codec, - hda_nid_t associated_nid, - hda_nid_t cvt_nid, - int type) +int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, + hda_nid_t associated_nid, + hda_nid_t cvt_nid) { int err; struct snd_kcontrol *kctl; struct snd_kcontrol_new *dig_mix; - int idx, dev = 0; - const int spdif_pcm_dev = 1; + int idx; struct hda_spdif_out *spdif; - if (codec->primary_dig_out_type == HDA_PCM_TYPE_HDMI && - type == HDA_PCM_TYPE_SPDIF) { - dev = spdif_pcm_dev; - } else if (codec->primary_dig_out_type == HDA_PCM_TYPE_SPDIF && - type == HDA_PCM_TYPE_HDMI) { - for (idx = 0; idx < codec->spdif_out.used; idx++) { - spdif = snd_array_elem(&codec->spdif_out, idx); - for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { - kctl = find_mixer_ctl(codec, dig_mix->name, 0, idx); - if (!kctl) - break; - kctl->id.device = spdif_pcm_dev; - } - } - codec->primary_dig_out_type = HDA_PCM_TYPE_HDMI; - } - if (!codec->primary_dig_out_type) - codec->primary_dig_out_type = type; - - idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", dev); + idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch"); if (idx < 0) { printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); return -EBUSY; @@ -3163,7 +3164,6 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec, kctl = snd_ctl_new1(dig_mix, codec); if (!kctl) return -ENOMEM; - kctl->id.device = dev; kctl->id.index = idx; kctl->private_value = codec->spdif_out.used - 1; err = snd_hda_ctl_add(codec, associated_nid, kctl); @@ -3176,7 +3176,7 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec, spdif->status = convert_to_spdif_status(spdif->ctls); return 0; } -EXPORT_SYMBOL_HDA(snd_hda_create_dig_out_ctls); +EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls); /* get the hda_spdif_out entry from the given NID * call within spdif_mutex lock @@ -3351,7 +3351,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) struct snd_kcontrol_new *dig_mix; int idx; - idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0); + idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch"); if (idx < 0) { printk(KERN_ERR "hda_codec: too many IEC958 inputs\n"); return -EBUSY; @@ -3650,8 +3650,10 @@ static void hda_call_codec_resume(struct hda_codec *codec) */ hda_keep_power_on(codec); hda_set_power_state(codec, AC_PWRST_D0); + restore_pincfgs(codec); /* restore all current pin configs */ restore_shutup_pins(codec); hda_exec_init_verbs(codec); + snd_hda_jack_set_dirty_all(codec); if (codec->patch_ops.resume) codec->patch_ops.resume(codec); else { @@ -3660,13 +3662,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) snd_hda_codec_resume_amp(codec); snd_hda_codec_resume_cache(codec); } - - if (codec->jackpoll_interval) - hda_jackpoll_work(&codec->jackpoll_work.work); - else { - snd_hda_jack_set_dirty_all(codec); - snd_hda_jack_report_sync(codec); - } + snd_hda_jack_report_sync(codec); codec->in_pm = 0; snd_hda_power_down(codec); /* flag down before returning */ @@ -3716,14 +3712,13 @@ static int add_std_chmaps(struct hda_codec *codec) struct hda_pcm_stream *hinfo = &codec->pcm_info[i].stream[str]; struct snd_pcm_chmap *chmap; - const struct snd_pcm_chmap_elem *elem; if (codec->pcm_info[i].own_chmap) continue; if (!pcm || !hinfo->substreams) continue; - elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps; - err = snd_pcm_add_chmap_ctls(pcm, str, elem, + err = snd_pcm_add_chmap_ctls(pcm, str, + snd_pcm_std_chmaps, hinfo->channels_max, 0, &chmap); if (err < 0) @@ -3734,19 +3729,6 @@ static int add_std_chmaps(struct hda_codec *codec) return 0; } -/* default channel maps for 2.1 speakers; - * since HD-audio supports only stereo, odd number channels are omitted - */ -const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[] = { - { .channels = 2, - .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, - { .channels = 4, - .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, - SNDRV_CHMAP_LFE, SNDRV_CHMAP_LFE } }, - { } -}; -EXPORT_SYMBOL_GPL(snd_pcm_2_1_chmaps); - int snd_hda_codec_build_controls(struct hda_codec *codec) { int err = 0; @@ -3764,10 +3746,7 @@ int snd_hda_codec_build_controls(struct hda_codec *codec) if (err < 0) return err; - if (codec->jackpoll_interval) - hda_jackpoll_work(&codec->jackpoll_work.work); - else - snd_hda_jack_report_sync(codec); /* call at the last init point */ + snd_hda_jack_report_sync(codec); /* call at the last init point */ return 0; } @@ -4479,7 +4458,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, addr = codec->addr; else if (!idx && !knew->index) { idx = find_empty_mixer_ctl_idx(codec, - knew->name, 0); + knew->name); if (idx <= 0) return err; } else @@ -4791,34 +4770,6 @@ int snd_hda_input_mux_put(struct hda_codec *codec, EXPORT_SYMBOL_HDA(snd_hda_input_mux_put); -/* - * process kcontrol info callback of a simple string enum array - * when @num_items is 0 or @texts is NULL, assume a boolean enum array - */ -int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo, - int num_items, const char * const *texts) -{ - static const char * const texts_default[] = { - "Disabled", "Enabled" - }; - - if (!texts || !num_items) { - num_items = 2; - texts = texts_default; - } - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = num_items; - 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; -} -EXPORT_SYMBOL_HDA(snd_hda_enum_helper_info); - /* * Multi-channel / digital-out PCM helper functions */ @@ -4827,20 +4778,10 @@ EXPORT_SYMBOL_HDA(snd_hda_enum_helper_info); static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, unsigned int stream_tag, unsigned int format) { - struct hda_spdif_out *spdif; - unsigned int curr_fmt; - bool reset; - - spdif = snd_hda_spdif_out_of_nid(codec, nid); - curr_fmt = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_STREAM_FORMAT, 0); - reset = codec->spdif_status_reset && - (spdif->ctls & AC_DIG1_ENABLE) && - curr_fmt != format; - - /* turn off SPDIF if needed; otherwise the IEC958 bits won't be - updated */ - if (reset) + struct hda_spdif_out *spdif = snd_hda_spdif_out_of_nid(codec, nid); + + /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ + if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) set_dig_out_convert(codec, nid, spdif->ctls & ~AC_DIG1_ENABLE & 0xff, -1); @@ -4852,7 +4793,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, format); } /* turn on again (if needed) */ - if (reset) + if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) set_dig_out_convert(codec, nid, spdif->ctls & 0xff, -1); } @@ -5196,7 +5137,6 @@ int snd_hda_suspend(struct hda_bus *bus) struct hda_codec *codec; list_for_each_entry(codec, &bus->codec_list, list) { - cancel_delayed_work_sync(&codec->jackpoll_work); if (hda_codec_is_power_on(codec)) hda_call_codec_suspend(codec, false); } diff --git a/trunk/sound/pci/hda/hda_codec.h b/trunk/sound/pci/hda/hda_codec.h index 8665540e55aa..4f4e545c0f4b 100644 --- a/trunk/sound/pci/hda/hda_codec.h +++ b/trunk/sound/pci/hda/hda_codec.h @@ -757,7 +757,6 @@ struct hda_pcm_stream { u32 rates; /* supported rates */ u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */ unsigned int maxbps; /* supported max. bit per sample */ - const struct snd_pcm_chmap_elem *chmap; /* chmap to override */ struct hda_pcm_ops ops; }; @@ -837,7 +836,6 @@ struct hda_codec { struct mutex hash_mutex; struct snd_array spdif_out; unsigned int spdif_in_enable; /* SPDIF input enable? */ - int primary_dig_out_type; /* primary digital out PCM type */ const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ struct snd_array init_pins; /* initial (BIOS) pin configurations */ struct snd_array driver_pins; /* pin configs set by codec parser */ @@ -887,8 +885,6 @@ struct hda_codec { /* jack detection */ struct snd_array jacktbl; - unsigned long jackpoll_interval; /* In jiffies. Zero means no poll, rely on unsol events */ - struct delayed_work jackpoll_work; #ifdef CONFIG_SND_HDA_INPUT_JACK /* jack detection */ @@ -1028,8 +1024,6 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, unsigned int format); -extern const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[]; - /* * Misc */ diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index 4bb52da3ace9..f9d870e554d9 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -47,9 +47,6 @@ #include #include #include -#include -#include - #ifdef CONFIG_X86 /* for snoop control */ #include @@ -71,7 +68,6 @@ static int position_fix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; static int probe_only[SNDRV_CARDS]; -static int jackpoll_ms[SNDRV_CARDS]; static bool single_cmd; static int enable_msi = -1; #ifdef CONFIG_SND_HDA_PATCH_LOADER @@ -99,8 +95,6 @@ module_param_array(probe_mask, int, NULL, 0444); MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); module_param_array(probe_only, int, NULL, 0444); MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); -module_param_array(jackpoll_ms, int, NULL, 0444); -MODULE_PARM_DESC(jackpoll_ms, "Ms between polling for jack events (default = 0, using unsol events only)"); module_param(single_cmd, bool, 0444); MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " "(for debugging only)."); @@ -422,9 +416,6 @@ struct azx_dev { unsigned int insufficient :1; unsigned int wc_marked:1; unsigned int no_period_wakeup:1; - - struct timecounter azx_tc; - struct cyclecounter azx_cc; }; /* CORB/RIRB */ @@ -527,9 +518,6 @@ struct azx { struct list_head list; }; -#define CREATE_TRACE_POINTS -#include "hda_intel_trace.h" - /* driver types */ enum { AZX_DRIVER_ICH, @@ -847,9 +835,8 @@ static void azx_update_rirb(struct azx *chip) smp_wmb(); chip->rirb.cmds[addr]--; } else - snd_printk(KERN_ERR SFX "%s: spurious response %#x:%#x, " + snd_printk(KERN_ERR SFX "spurious response %#x:%#x, " "last cmd=%#08x\n", - pci_name(chip->pci), res, res_ex, chip->last_cmd[addr]); } @@ -1601,22 +1588,6 @@ static void azx_bus_reset(struct hda_bus *bus) bus->in_reset = 0; } -static int get_jackpoll_interval(struct azx *chip) -{ - int i = jackpoll_ms[chip->dev_index]; - unsigned int j; - if (i == 0) - return 0; - if (i < 50 || i > 60000) - j = 0; - else - j = msecs_to_jiffies(i); - if (j == 0) - snd_printk(KERN_WARNING SFX - "jackpoll_ms value out of range: %d\n", i); - return j; -} - /* * Codec initialization */ @@ -1701,7 +1672,6 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode err = snd_hda_codec_new(chip->bus, c, &codec); if (err < 0) continue; - codec->jackpoll_interval = get_jackpoll_interval(chip); codec->beep_mode = chip->beep_mode; codecs++; } @@ -1764,64 +1734,6 @@ static inline void azx_release_device(struct azx_dev *azx_dev) azx_dev->opened = 0; } -static cycle_t azx_cc_read(const struct cyclecounter *cc) -{ - struct azx_dev *azx_dev = container_of(cc, struct azx_dev, azx_cc); - struct snd_pcm_substream *substream = azx_dev->substream; - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - - return azx_readl(chip, WALLCLK); -} - -static void azx_timecounter_init(struct snd_pcm_substream *substream, - bool force, cycle_t last) -{ - struct azx_dev *azx_dev = get_azx_dev(substream); - struct timecounter *tc = &azx_dev->azx_tc; - struct cyclecounter *cc = &azx_dev->azx_cc; - u64 nsec; - - cc->read = azx_cc_read; - cc->mask = CLOCKSOURCE_MASK(32); - - /* - * Converting from 24 MHz to ns means applying a 125/3 factor. - * To avoid any saturation issues in intermediate operations, - * the 125 factor is applied first. The division is applied - * last after reading the timecounter value. - * Applying the 1/3 factor as part of the multiplication - * requires at least 20 bits for a decent precision, however - * overflows occur after about 4 hours or less, not a option. - */ - - cc->mult = 125; /* saturation after 195 years */ - cc->shift = 0; - - nsec = 0; /* audio time is elapsed time since trigger */ - timecounter_init(tc, cc, nsec); - if (force) - /* - * force timecounter to use predefined value, - * used for synchronized starts - */ - tc->cycle_last = last; -} - -static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, - struct timespec *ts) -{ - struct azx_dev *azx_dev = get_azx_dev(substream); - u64 nsec; - - nsec = timecounter_read(&azx_dev->azx_tc); - nsec = div_u64(nsec, 3); /* can be optimized */ - - *ts = ns_to_timespec(nsec); - - return 0; -} - static struct snd_pcm_hardware azx_pcm_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | @@ -1831,7 +1743,6 @@ static struct snd_pcm_hardware azx_pcm_hw = { /* SNDRV_PCM_INFO_RESUME |*/ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_HAS_WALL_CLOCK | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_48000, @@ -1871,12 +1782,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) runtime->hw.rates = hinfo->rates; snd_pcm_limit_hw_rates(runtime); snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - - /* avoid wrap-around with wall-clock */ - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, - 20, - 178000000); - if (chip->align_buffer_size) /* constrain buffer sizes to be multiple of 128 bytes. This is more efficient in terms of memory @@ -1916,12 +1821,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) mutex_unlock(&chip->open_mutex); return -EINVAL; } - - /* disable WALLCLOCK timestamps for capture streams - until we figure out how to handle digital inputs */ - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; - spin_lock_irqsave(&chip->reg_lock, flags); azx_dev->substream = substream; azx_dev->running = 0; @@ -2068,9 +1967,6 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) int rstart = 0, start, nsync = 0, sbits = 0; int nwait, timeout; - azx_dev = get_azx_dev(substream); - trace_azx_pcm_trigger(chip, azx_dev, cmd); - switch (cmd) { case SNDRV_PCM_TRIGGER_START: rstart = 1; @@ -2161,22 +2057,6 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) azx_readl(chip, OLD_SSYNC) & ~sbits); else azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); - if (start) { - azx_timecounter_init(substream, 0, 0); - if (nsync > 1) { - cycle_t cycle_last; - - /* same start cycle for master and group */ - azx_dev = get_azx_dev(substream); - cycle_last = azx_dev->azx_tc.cycle_last; - - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_timecounter_init(s, 1, cycle_last); - } - } - } spin_unlock(&chip->reg_lock); return 0; } @@ -2243,7 +2123,6 @@ static unsigned int azx_get_position(struct azx *chip, { unsigned int pos; int stream = azx_dev->substream->stream; - int delay = 0; switch (chip->position_fix[stream]) { case POS_FIX_LPIB: @@ -2277,6 +2156,7 @@ static unsigned int azx_get_position(struct azx *chip, chip->position_fix[stream] == POS_FIX_POSBUF && (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB); + int delay; if (stream == SNDRV_PCM_STREAM_PLAYBACK) delay = pos - lpib_pos; else @@ -2294,7 +2174,6 @@ static unsigned int azx_get_position(struct azx *chip, azx_dev->substream->runtime->delay = bytes_to_frames(azx_dev->substream->runtime, delay); } - trace_azx_get_position(chip, azx_dev, pos, delay); return pos; } @@ -2320,11 +2199,13 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) { u32 wallclk; unsigned int pos; + int stream; wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk; if (wallclk < (azx_dev->period_wallclk * 2) / 3) return -1; /* bogus (too early) interrupt */ + stream = azx_dev->substream->stream; pos = azx_get_position(chip, azx_dev, true); if (WARN_ONCE(!azx_dev->period_bytes, @@ -2415,7 +2296,6 @@ static struct snd_pcm_ops azx_pcm_ops = { .prepare = azx_pcm_prepare, .trigger = azx_pcm_trigger, .pointer = azx_pcm_pointer, - .wall_clock = azx_get_wallclock_tstamp, .mmap = azx_pcm_mmap, .page = snd_pcm_sgbuf_ops_page, }; @@ -3507,10 +3387,8 @@ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip) chip->fw->data); if (err < 0) goto out_free; -#ifndef CONFIG_PM release_firmware(chip->fw); /* no longer needed */ chip->fw = NULL; -#endif } #endif if ((probe_only[dev] & 1) == 0) { diff --git a/trunk/sound/pci/hda/hda_intel_trace.h b/trunk/sound/pci/hda/hda_intel_trace.h deleted file mode 100644 index 7b5e4c2cf9d5..000000000000 --- a/trunk/sound/pci/hda/hda_intel_trace.h +++ /dev/null @@ -1,62 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM hda_intel -#define TRACE_INCLUDE_FILE hda_intel_trace - -#if !defined(_TRACE_HDA_INTEL_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_HDA_INTEL_H - -#include - -struct azx; -struct azx_dev; - -TRACE_EVENT(azx_pcm_trigger, - - TP_PROTO(struct azx *chip, struct azx_dev *dev, int cmd), - - TP_ARGS(chip, dev, cmd), - - TP_STRUCT__entry( - __field( int, card ) - __field( int, idx ) - __field( int, cmd ) - ), - - TP_fast_assign( - __entry->card = (chip)->card->number; - __entry->idx = (dev)->index; - __entry->cmd = cmd; - ), - - TP_printk("[%d:%d] cmd=%d", __entry->card, __entry->idx, __entry->cmd) -); - -TRACE_EVENT(azx_get_position, - - TP_PROTO(struct azx *chip, struct azx_dev *dev, unsigned int pos, unsigned int delay), - - TP_ARGS(chip, dev, pos, delay), - - TP_STRUCT__entry( - __field( int, card ) - __field( int, idx ) - __field( unsigned int, pos ) - __field( unsigned int, delay ) - ), - - TP_fast_assign( - __entry->card = (chip)->card->number; - __entry->idx = (dev)->index; - __entry->pos = pos; - __entry->delay = delay; - ), - - TP_printk("[%d:%d] pos=%u, delay=%u", __entry->card, __entry->idx, __entry->pos, __entry->delay) -); - -#endif /* _TRACE_HDA_INTEL_H */ - -/* This part must be outside protection */ -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . -#include diff --git a/trunk/sound/pci/hda/hda_jack.c b/trunk/sound/pci/hda/hda_jack.c index 6e9f57bbe667..5c690cb873d4 100644 --- a/trunk/sound/pci/hda/hda_jack.c +++ b/trunk/sound/pci/hda/hda_jack.c @@ -95,6 +95,7 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); if (jack) return jack; + snd_array_init(&codec->jacktbl, sizeof(*jack), 16); jack = snd_array_new(&codec->jacktbl); if (!jack) return NULL; @@ -121,8 +122,6 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) snd_array_free(&codec->jacktbl); } -#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE) - /* update the cached value and notification flag if needed */ static void jack_detect_update(struct hda_codec *codec, struct hda_jack_tbl *jack) @@ -135,21 +134,7 @@ static void jack_detect_update(struct hda_codec *codec, else jack->pin_sense = read_pin_sense(codec, jack->nid); - /* A gating jack indicates the jack is invalid if gating is unplugged */ - if (jack->gating_jack && !snd_hda_jack_detect(codec, jack->gating_jack)) - jack->pin_sense &= ~AC_PINSENSE_PRESENCE; - jack->jack_dirty = 0; - - /* If a jack is gated by this one update it. */ - if (jack->gated_jack) { - struct hda_jack_tbl *gated = - snd_hda_jack_tbl_get(codec, jack->gated_jack); - if (gated) { - gated->jack_dirty = 1; - jack_detect_update(codec, gated); - } - } } /** @@ -188,6 +173,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) } EXPORT_SYMBOL_HDA(snd_hda_pin_sense); +#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE) + /** * snd_hda_jack_detect - query pin Presence Detect status * @codec: the CODEC to sense @@ -219,8 +206,6 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, jack->action = action; if (cb) jack->callback = cb; - if (codec->jackpoll_interval > 0) - return 0; /* No unsol if we're polling instead */ return snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | jack->tag); @@ -234,47 +219,17 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, } EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); -/** - * snd_hda_jack_set_gating_jack - Set gating jack. - * - * Indicates the gated jack is only valid when the gating jack is plugged. - */ -int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, - hda_nid_t gating_nid) -{ - struct hda_jack_tbl *gated = snd_hda_jack_tbl_get(codec, gated_nid); - struct hda_jack_tbl *gating = snd_hda_jack_tbl_get(codec, gating_nid); - - if (!gated || !gating) - return -EINVAL; - - gated->gating_jack = gating_nid; - gating->gated_jack = gated_nid; - - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_jack_set_gating_jack); - /** * snd_hda_jack_report_sync - sync the states of all jacks and report if changed */ void snd_hda_jack_report_sync(struct hda_codec *codec) { - struct hda_jack_tbl *jack; + struct hda_jack_tbl *jack = codec->jacktbl.list; int i, state; - /* update all jacks at first */ - jack = codec->jacktbl.list; - for (i = 0; i < codec->jacktbl.used; i++, jack++) - if (jack->nid) - jack_detect_update(codec, jack); - - /* report the updated jacks; it's done after updating all jacks - * to make sure that all gating jacks properly have been set - */ - jack = codec->jacktbl.list; for (i = 0; i < codec->jacktbl.used; i++, jack++) if (jack->nid) { + jack_detect_update(codec, jack); if (!jack->kctl) continue; state = get_jack_plug_state(jack->pin_sense); @@ -467,19 +422,6 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, } EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); -static void call_jack_callback(struct hda_codec *codec, - struct hda_jack_tbl *jack) -{ - if (jack->callback) - jack->callback(codec, jack); - if (jack->gated_jack) { - struct hda_jack_tbl *gated = - snd_hda_jack_tbl_get(codec, jack->gated_jack); - if (gated && gated->callback) - gated->callback(codec, gated); - } -} - void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res) { struct hda_jack_tbl *event; @@ -490,29 +432,10 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res) return; event->jack_dirty = 1; - call_jack_callback(codec, event); + if (event->callback) + event->callback(codec, event); + snd_hda_jack_report_sync(codec); } EXPORT_SYMBOL_HDA(snd_hda_jack_unsol_event); -void snd_hda_jack_poll_all(struct hda_codec *codec) -{ - struct hda_jack_tbl *jack = codec->jacktbl.list; - int i, changes = 0; - - for (i = 0; i < codec->jacktbl.used; i++, jack++) { - unsigned int old_sense; - if (!jack->nid || !jack->jack_dirty || jack->phantom_jack) - continue; - old_sense = get_jack_plug_state(jack->pin_sense); - jack_detect_update(codec, jack); - if (old_sense == get_jack_plug_state(jack->pin_sense)) - continue; - changes = 1; - call_jack_callback(codec, jack); - } - if (changes) - snd_hda_jack_report_sync(codec); -} -EXPORT_SYMBOL_HDA(snd_hda_jack_poll_all); - diff --git a/trunk/sound/pci/hda/hda_jack.h b/trunk/sound/pci/hda/hda_jack.h index ec12abd45263..af8dd4724da5 100644 --- a/trunk/sound/pci/hda/hda_jack.h +++ b/trunk/sound/pci/hda/hda_jack.h @@ -28,8 +28,6 @@ struct hda_jack_tbl { unsigned int jack_detect:1; /* capable of jack-detection? */ unsigned int jack_dirty:1; /* needs to update? */ unsigned int phantom_jack:1; /* a fixed, always present port? */ - hda_nid_t gating_jack; /* valid when gating jack plugged */ - hda_nid_t gated_jack; /* gated is dependent on this jack */ struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ #ifdef CONFIG_SND_HDA_INPUT_JACK int type; @@ -71,8 +69,6 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, unsigned char action, hda_jack_callback cb); -int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, - hda_nid_t gating_nid); u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); @@ -88,6 +84,4 @@ void snd_hda_jack_report_sync(struct hda_codec *codec); void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res); -void snd_hda_jack_poll_all(struct hda_codec *codec); - #endif /* __SOUND_HDA_JACK_H */ diff --git a/trunk/sound/pci/hda/hda_local.h b/trunk/sound/pci/hda/hda_local.h index 4b40a5e7a8f5..09dbdc37f781 100644 --- a/trunk/sound/pci/hda/hda_local.h +++ b/trunk/sound/pci/hda/hda_local.h @@ -240,11 +240,9 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, /* * SPDIF I/O */ -int snd_hda_create_dig_out_ctls(struct hda_codec *codec, - hda_nid_t associated_nid, - hda_nid_t cvt_nid, int type); -#define snd_hda_create_spdif_out_ctls(codec, anid, cnid) \ - snd_hda_create_dig_out_ctls(codec, anid, cnid, HDA_PCM_TYPE_SPDIF) +int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, + hda_nid_t associated_nid, + hda_nid_t cvt_nid); int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); /* @@ -600,15 +598,6 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) #define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1) -/* - * enum control helper - */ -int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo, - int num_entries, const char * const *texts); -#define snd_hda_enum_bool_helper_info(kcontrol, uinfo) \ - snd_hda_enum_helper_info(kcontrol, uinfo, 0, NULL) - /* * CEA Short Audio Descriptor data */ diff --git a/trunk/sound/pci/hda/patch_analog.c b/trunk/sound/pci/hda/patch_analog.c index 89fc5030ec79..1eeba7386666 100644 --- a/trunk/sound/pci/hda/patch_analog.c +++ b/trunk/sound/pci/hda/patch_analog.c @@ -636,6 +636,7 @@ static void ad198x_free(struct hda_codec *codec) if (!spec) return; + ad198x_shutup(codec); ad198x_free_kctls(codec); kfree(spec); snd_hda_detach_beep_device(codec); @@ -1246,27 +1247,16 @@ static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) return get_defcfg_connect(conf) != AC_JACK_PORT_NONE; } -static int alloc_ad_spec(struct hda_codec *codec) +static int patch_ad1986a(struct hda_codec *codec) { struct ad198x_spec *spec; + int err, board_config; spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) + if (spec == NULL) return -ENOMEM; - codec->spec = spec; - snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); - return 0; -} -static int patch_ad1986a(struct hda_codec *codec) -{ - struct ad198x_spec *spec; - int err, board_config; - - err = alloc_ad_spec(codec); - if (err < 0) - return err; - spec = codec->spec; + codec->spec = spec; err = snd_hda_attach_beep_device(codec, 0x19); if (err < 0) { @@ -1559,10 +1549,11 @@ static int patch_ad1983(struct hda_codec *codec) struct ad198x_spec *spec; int err; - err = alloc_ad_spec(codec); - if (err < 0) - return err; - spec = codec->spec; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { @@ -1964,10 +1955,11 @@ static int patch_ad1981(struct hda_codec *codec) struct ad198x_spec *spec; int err, board_config; - err = alloc_ad_spec(codec); - if (err < 0) + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) return -ENOMEM; - spec = codec->spec; + + codec->spec = spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { @@ -2845,6 +2837,7 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, { struct snd_kcontrol_new *knew; + snd_array_init(&spec->kctls, sizeof(*knew), 32); knew = snd_array_new(&spec->kctls); if (!knew) return -ENOMEM; @@ -3262,10 +3255,11 @@ static int patch_ad1988(struct hda_codec *codec) struct ad198x_spec *spec; int err, board_config; - err = alloc_ad_spec(codec); - if (err < 0) - return err; - spec = codec->spec; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; if (is_rev2(codec)) snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); @@ -3581,10 +3575,11 @@ static int patch_ad1884(struct hda_codec *codec) struct ad198x_spec *spec; int err; - err = alloc_ad_spec(codec); - if (err < 0) - return err; - spec = codec->spec; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { @@ -4580,10 +4575,11 @@ static int patch_ad1884a(struct hda_codec *codec) struct ad198x_spec *spec; int err, board_config; - err = alloc_ad_spec(codec); - if (err < 0) - return err; - spec = codec->spec; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { @@ -4992,10 +4988,11 @@ static int patch_ad1882(struct hda_codec *codec) struct ad198x_spec *spec; int err, board_config; - err = alloc_ad_spec(codec); - if (err < 0) - return err; - spec = codec->spec; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { diff --git a/trunk/sound/pci/hda/patch_cirrus.c b/trunk/sound/pci/hda/patch_cirrus.c index a2537b2f8724..3bcb67172358 100644 --- a/trunk/sound/pci/hda/patch_cirrus.c +++ b/trunk/sound/pci/hda/patch_cirrus.c @@ -68,7 +68,6 @@ struct cs_spec { unsigned int hp_detect:1; unsigned int mic_detect:1; - unsigned int speaker_2_1:1; /* CS421x */ unsigned int spdif_detect:1; unsigned int sense_b:1; @@ -85,7 +84,7 @@ enum { CS420X_GPIO_13, CS420X_GPIO_23, CS420X_MBP101, - CS420X_MBP81, + CS420X_MBP101_COEF, CS420X_AUTO, /* aliases */ CS420X_IMAC27_122 = CS420X_GPIO_23, @@ -344,9 +343,6 @@ static int cs_build_pcms(struct hda_codec *codec) info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dac_nid[0]; info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; - if (spec->speaker_2_1) - info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap = - snd_pcm_2_1_chmaps; info->stream[SNDRV_PCM_STREAM_CAPTURE] = cs_pcm_analog_capture; info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid[spec->cur_input]; @@ -447,9 +443,6 @@ static int parse_output(struct hda_codec *codec) spec->multiout.dac_nids = spec->dac_nid; spec->multiout.max_channels = i * 2; - if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && i == 2) - spec->speaker_2_1 = 1; /* assume 2.1 speakers */ - /* add HP and speakers */ extra_nids = 0; for (i = 0; i < cfg->hp_outs; i++) { @@ -640,9 +633,7 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx, index = idx; break; case AUTO_PIN_SPEAKER_OUT: - if (spec->speaker_2_1) - name = idx ? "Bass Speaker" : "Speaker"; - else if (num_ctls > 1) + if (num_ctls > 1) name = speakers[idx]; else name = "Speaker"; @@ -883,9 +874,8 @@ static int build_digital_output(struct hda_codec *codec) if (!spec->multiout.dig_out_nid) return 0; - err = snd_hda_create_dig_out_ctls(codec, spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid, - spec->pcm_rec[1].pcm_type); + err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid, + spec->multiout.dig_out_nid); if (err < 0) return err; err = snd_hda_create_spdif_share_sw(codec, &spec->multiout); @@ -1089,6 +1079,9 @@ static void init_input(struct hda_codec *codec) if (spec->mic_detect) cs_automic(codec, NULL); + coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ + cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG); if (is_active_pin(codec, CS_DMIC2_PIN_NID)) coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */ @@ -1118,9 +1111,6 @@ static const struct hda_verb cs_coef_init_verbs[] = { | 0x1000 /* Enable DACs High Pass Filter */ | 0x0400 /* Disable Coefficient Auto increment */ )}, - /* ADC1/2 - Digital and Analog Soft Ramp */ - {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG}, - {0x11, AC_VERB_SET_PROC_COEF, 0x000a}, /* Beep */ {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG}, {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */ @@ -1177,6 +1167,14 @@ static const struct hda_verb cs_errata_init_verbs[] = { {} /* terminator */ }; +static const struct hda_verb mbp101_init_verbs[] = { + {0x11, AC_VERB_SET_COEF_INDEX, 0x0002}, + {0x11, AC_VERB_SET_PROC_COEF, 0x100a}, + {0x11, AC_VERB_SET_COEF_INDEX, 0x0004}, + {0x11, AC_VERB_SET_PROC_COEF, 0x000f}, + {} +}; + /* SPDIF setup */ static void init_digital(struct hda_codec *codec) { @@ -1201,8 +1199,6 @@ static int cs_init(struct hda_codec *codec) snd_hda_sequence_write(codec, cs_coef_init_verbs); - snd_hda_gen_apply_verbs(codec); - if (spec->gpio_mask) { snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK, spec->gpio_mask); @@ -1295,7 +1291,6 @@ static const struct hda_model_fixup cs420x_models[] = { { .id = CS420X_IMAC27_122, .name = "imac27_122" }, { .id = CS420X_APPLE, .name = "apple" }, { .id = CS420X_MBP101, .name = "mbp101" }, - { .id = CS420X_MBP81, .name = "mbp81" }, {} }; @@ -1308,7 +1303,6 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = { /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/ /* codec SSID */ - SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81), SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101), SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), @@ -1419,16 +1413,11 @@ static const struct hda_fixup cs420x_fixups[] = { .type = HDA_FIXUP_PINS, .v.pins = mbp101_pincfgs, .chained = true, - .chain_id = CS420X_GPIO_13, + .chain_id = CS420X_MBP101_COEF, }, - [CS420X_MBP81] = { + [CS420X_MBP101_COEF] = { .type = HDA_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* internal mic ADC2: right only, single ended */ - {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG}, - {0x11, AC_VERB_SET_PROC_COEF, 0x102a}, - {} - }, + .v.verbs = mbp101_init_verbs, .chained = true, .chain_id = CS420X_GPIO_13, }, diff --git a/trunk/sound/pci/hda/patch_conexant.c b/trunk/sound/pci/hda/patch_conexant.c index a3a2263d3b37..03b1dc317ff0 100644 --- a/trunk/sound/pci/hda/patch_conexant.c +++ b/trunk/sound/pci/hda/patch_conexant.c @@ -337,8 +337,6 @@ static const struct hda_pcm_stream cx5051_pcm_analog_capture = { }, }; -static bool is_2_1_speaker(struct conexant_spec *spec); - static int conexant_build_pcms(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; @@ -353,9 +351,6 @@ static int conexant_build_pcms(struct hda_codec *codec) spec->multiout.max_channels; info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; - if (is_2_1_speaker(spec)) - info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap = - snd_pcm_2_1_chmaps; if (spec->capture_stream) info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream; else { @@ -477,7 +472,7 @@ static const struct snd_kcontrol_new cxt_beep_mixer[] = { #endif static const char * const slave_pfxs[] = { - "Headphone", "Speaker", "Bass Speaker", "Front", "Surround", "CLFE", + "Headphone", "Speaker", "Front", "Surround", "CLFE", NULL }; @@ -3435,13 +3430,28 @@ static int cx_automute_mode_info(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct conexant_spec *spec = codec->spec; + static const char * const texts2[] = { + "Disabled", "Enabled" + }; static const char * const texts3[] = { "Disabled", "Speaker Only", "Line Out+Speaker" }; + const char * const *texts; - if (spec->automute_hp_lo) - return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3); - return snd_hda_enum_bool_helper_info(kcontrol, uinfo); + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + if (spec->automute_hp_lo) { + uinfo->value.enumerated.items = 3; + texts = texts3; + } else { + uinfo->value.enumerated.items = 2; + texts = texts2; + } + 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 cx_automute_mode_get(struct snd_kcontrol *kcontrol, @@ -4106,26 +4116,11 @@ static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac, return 0; } -static bool is_2_1_speaker(struct conexant_spec *spec) -{ - int i, type, num_spk = 0; - - for (i = 0; i < spec->dac_info_filled; i++) { - type = spec->dac_info[i].type; - if (type == AUTO_PIN_LINE_OUT) - type = spec->autocfg.line_out_type; - if (type == AUTO_PIN_SPEAKER_OUT) - num_spk++; - } - return (num_spk == 2 && spec->autocfg.line_out_type != AUTO_PIN_LINE_OUT); -} - static int cx_auto_build_output_controls(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; int i, err; int num_line = 0, num_hp = 0, num_spk = 0; - bool speaker_2_1; static const char * const texts[3] = { "Front", "Surround", "CLFE" }; if (spec->dac_info_filled == 1) @@ -4133,8 +4128,6 @@ static int cx_auto_build_output_controls(struct hda_codec *codec) spec->dac_info[0].pin, "Master", 0); - speaker_2_1 = is_2_1_speaker(spec); - for (i = 0; i < spec->dac_info_filled; i++) { const char *label; int idx, type; @@ -4153,13 +4146,8 @@ static int cx_auto_build_output_controls(struct hda_codec *codec) idx = num_hp++; break; case AUTO_PIN_SPEAKER_OUT: - if (speaker_2_1) { - label = num_spk++ ? "Bass Speaker" : "Speaker"; - idx = 0; - } else { - label = "Speaker"; - idx = num_spk++; - } + label = "Speaker"; + idx = num_spk++; break; } err = try_add_pb_volume(codec, dac, @@ -4417,10 +4405,7 @@ static const struct hda_codec_ops cx_auto_patch_ops = { enum { CXT_PINCFG_LENOVO_X200, CXT_PINCFG_LENOVO_TP410, - CXT_PINCFG_LEMOTE_A1004, - CXT_PINCFG_LEMOTE_A1205, CXT_FIXUP_STEREO_DMIC, - CXT_FIXUP_INC_MIC_BOOST, }; static void cxt_fixup_stereo_dmic(struct hda_codec *codec, @@ -4430,19 +4415,6 @@ static void cxt_fixup_stereo_dmic(struct hda_codec *codec, spec->fixup_stereo_dmic = 1; } -static void cxt5066_increase_mic_boost(struct hda_codec *codec, - const struct hda_fixup *fix, int action) -{ - if (action != HDA_FIXUP_ACT_PRE_PROBE) - return; - - snd_hda_override_amp_caps(codec, 0x17, HDA_OUTPUT, - (0x3 << AC_AMPCAP_OFFSET_SHIFT) | - (0x4 << AC_AMPCAP_NUM_STEPS_SHIFT) | - (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | - (0 << AC_AMPCAP_MUTE_SHIFT)); -} - /* ThinkPad X200 & co with cxt5051 */ static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = { { 0x16, 0x042140ff }, /* HP (seq# overridden) */ @@ -4460,18 +4432,6 @@ static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = { {} }; -/* Lemote A1004/A1205 with cxt5066 */ -static const struct hda_pintbl cxt_pincfg_lemote[] = { - { 0x1a, 0x90a10020 }, /* Internal mic */ - { 0x1b, 0x03a11020 }, /* External mic */ - { 0x1d, 0x400101f0 }, /* Not used */ - { 0x1e, 0x40a701f0 }, /* Not used */ - { 0x20, 0x404501f0 }, /* Not used */ - { 0x22, 0x404401f0 }, /* Not used */ - { 0x23, 0x40a701f0 }, /* Not used */ - {} -}; - static const struct hda_fixup cxt_fixups[] = { [CXT_PINCFG_LENOVO_X200] = { .type = HDA_FIXUP_PINS, @@ -4481,24 +4441,10 @@ static const struct hda_fixup cxt_fixups[] = { .type = HDA_FIXUP_PINS, .v.pins = cxt_pincfg_lenovo_tp410, }, - [CXT_PINCFG_LEMOTE_A1004] = { - .type = HDA_FIXUP_PINS, - .chained = true, - .chain_id = CXT_FIXUP_INC_MIC_BOOST, - .v.pins = cxt_pincfg_lemote, - }, - [CXT_PINCFG_LEMOTE_A1205] = { - .type = HDA_FIXUP_PINS, - .v.pins = cxt_pincfg_lemote, - }, [CXT_FIXUP_STEREO_DMIC] = { .type = HDA_FIXUP_FUNC, .v.func = cxt_fixup_stereo_dmic, }, - [CXT_FIXUP_INC_MIC_BOOST] = { - .type = HDA_FIXUP_FUNC, - .v.func = cxt5066_increase_mic_boost, - }, }; static const struct snd_pci_quirk cxt5051_fixups[] = { @@ -4515,8 +4461,6 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004), - SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205), {} }; diff --git a/trunk/sound/pci/hda/patch_hdmi.c b/trunk/sound/pci/hda/patch_hdmi.c index 0fcfa6f406b8..71555cc54db1 100644 --- a/trunk/sound/pci/hda/patch_hdmi.c +++ b/trunk/sound/pci/hda/patch_hdmi.c @@ -1193,11 +1193,12 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) struct hdmi_spec_per_pin *per_pin; int err; - caps = snd_hda_query_pin_caps(codec, pin_nid); + caps = snd_hda_param_read(codec, pin_nid, AC_PAR_PIN_CAP); if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) return 0; - config = snd_hda_codec_get_pincfg(codec, pin_nid); + config = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_CONFIG_DEFAULT, 0); if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) return 0; @@ -1271,7 +1272,7 @@ static int hdmi_parse_codec(struct hda_codec *codec) unsigned int caps; unsigned int type; - caps = get_wcaps(codec, nid); + caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); type = get_wcaps_type(caps); if (!(caps & AC_WCAP_DIGITAL)) @@ -1287,17 +1288,13 @@ static int hdmi_parse_codec(struct hda_codec *codec) } } -#ifdef CONFIG_PM - /* We're seeing some problems with unsolicited hot plug events on - * PantherPoint after S3, if this is not enabled */ - if (codec->vendor_id == 0x80862806) - codec->bus->power_keep_link_on = 1; /* * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event * can be lost and presence sense verb will become inaccurate if the * HDA link is powered off at hot plug or hw initialization time. */ - else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & +#ifdef CONFIG_PM + if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & AC_PWRST_EPSS)) codec->bus->power_keep_link_on = 1; #endif @@ -1592,10 +1589,9 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) if (err < 0) return err; - err = snd_hda_create_dig_out_ctls(codec, - per_pin->pin_nid, - per_pin->mux_nids[0], - HDA_PCM_TYPE_HDMI); + err = snd_hda_create_spdif_out_ctls(codec, + per_pin->pin_nid, + per_pin->mux_nids[0]); if (err < 0) return err; snd_hda_spdif_ctls_unassign(codec, pin_idx); diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index 5d8044d4dc52..ad68d223f8af 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -815,13 +815,28 @@ static int alc_automute_mode_info(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; + static const char * const texts2[] = { + "Disabled", "Enabled" + }; static const char * const texts3[] = { "Disabled", "Speaker Only", "Line Out+Speaker" }; + const char * const *texts; - if (spec->automute_speaker_possible && spec->automute_lo_possible) - return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3); - return snd_hda_enum_bool_helper_info(kcontrol, uinfo); + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + if (spec->automute_speaker_possible && spec->automute_lo_possible) { + uinfo->value.enumerated.items = 3; + texts = texts3; + } else { + uinfo->value.enumerated.items = 2; + texts = texts2; + } + 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 alc_automute_mode_get(struct snd_kcontrol *kcontrol, @@ -888,25 +903,23 @@ static const struct snd_kcontrol_new alc_automute_mode_enum = { .put = alc_automute_mode_put, }; -static struct snd_kcontrol_new * -alc_kcontrol_new(struct alc_spec *spec, const char *name, - const struct snd_kcontrol_new *temp) +static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec) { - struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls); - if (!knew) - return NULL; - *knew = *temp; - knew->name = kstrdup(name, GFP_KERNEL); - if (!knew->name) - return NULL; - return knew; + snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); + return snd_array_new(&spec->kctls); } static int alc_add_automute_mode_enum(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + struct snd_kcontrol_new *knew; - if (!alc_kcontrol_new(spec, "Auto-Mute Mode", &alc_automute_mode_enum)) + knew = alc_kcontrol_new(spec); + if (!knew) + return -ENOMEM; + *knew = alc_automute_mode_enum; + knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL); + if (!knew->name) return -ENOMEM; return 0; } @@ -915,12 +928,12 @@ static int alc_add_automute_mode_enum(struct hda_codec *codec) * Check the availability of HP/line-out auto-mute; * Set up appropriately if really supported */ -static int alc_init_automute(struct hda_codec *codec) +static void alc_init_automute(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; int present = 0; - int i, err; + int i; if (cfg->hp_pins[0]) present++; @@ -929,7 +942,7 @@ static int alc_init_automute(struct hda_codec *codec) if (cfg->speaker_pins[0]) present++; if (present < 2) /* need two different output types */ - return 0; + return; if (!cfg->speaker_pins[0] && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { @@ -979,13 +992,9 @@ static int alc_init_automute(struct hda_codec *codec) spec->automute_lo = spec->automute_lo_possible; spec->automute_speaker = spec->automute_speaker_possible; - if (spec->automute_speaker_possible || spec->automute_lo_possible) { + if (spec->automute_speaker_possible || spec->automute_lo_possible) /* create a control for automute mode */ - err = alc_add_automute_mode_enum(codec); - if (err < 0) - return err; - } - return 0; + alc_add_automute_mode_enum(codec); } /* return the position of NID in the list, or -1 if not found */ @@ -1085,7 +1094,7 @@ static bool alc_auto_mic_check_imux(struct hda_codec *codec) * Check the availability of auto-mic switch; * Set up if really supported */ -static int alc_init_auto_mic(struct hda_codec *codec) +static void alc_init_auto_mic(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; @@ -1093,7 +1102,7 @@ static int alc_init_auto_mic(struct hda_codec *codec) int i; if (spec->shared_mic_hp) - return 0; /* no auto-mic for the shared I/O */ + return; /* no auto-mic for the shared I/O */ spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1; @@ -1105,25 +1114,25 @@ static int alc_init_auto_mic(struct hda_codec *codec) switch (snd_hda_get_input_pin_attr(defcfg)) { case INPUT_PIN_ATTR_INT: if (fixed) - return 0; /* already occupied */ + return; /* already occupied */ if (cfg->inputs[i].type != AUTO_PIN_MIC) - return 0; /* invalid type */ + return; /* invalid type */ fixed = nid; break; case INPUT_PIN_ATTR_UNUSED: - return 0; /* invalid entry */ + return; /* invalid entry */ case INPUT_PIN_ATTR_DOCK: if (dock) - return 0; /* already occupied */ + return; /* already occupied */ if (cfg->inputs[i].type > AUTO_PIN_LINE_IN) - return 0; /* invalid type */ + return; /* invalid type */ dock = nid; break; default: if (ext) - return 0; /* already occupied */ + return; /* already occupied */ if (cfg->inputs[i].type != AUTO_PIN_MIC) - return 0; /* invalid type */ + return; /* invalid type */ ext = nid; break; } @@ -1133,11 +1142,11 @@ static int alc_init_auto_mic(struct hda_codec *codec) dock = 0; } if (!ext || !fixed) - return 0; + return; if (!is_jack_detectable(codec, ext)) - return 0; /* no unsol support */ + return; /* no unsol support */ if (dock && !is_jack_detectable(codec, dock)) - return 0; /* no unsol support */ + return; /* no unsol support */ /* check imux indices */ spec->ext_mic_pin = ext; @@ -1146,26 +1155,17 @@ static int alc_init_auto_mic(struct hda_codec *codec) spec->auto_mic = 1; if (!alc_auto_mic_check_imux(codec)) - return 0; + return; snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n", ext, fixed, dock); - - return 0; } /* check the availabilities of auto-mute and auto-mic switches */ -static int alc_auto_check_switches(struct hda_codec *codec) +static void alc_auto_check_switches(struct hda_codec *codec) { - int err; - - err = alc_init_automute(codec); - if (err < 0) - return err; - err = alc_init_auto_mic(codec); - if (err < 0) - return err; - return 0; + alc_init_automute(codec); + alc_init_auto_mic(codec); } /* @@ -1757,9 +1757,12 @@ static const struct snd_kcontrol_new alc_inv_dmic_sw = { static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid) { struct alc_spec *spec = codec->spec; - - if (!alc_kcontrol_new(spec, "Inverted Internal Mic Capture Switch", - &alc_inv_dmic_sw)) + struct snd_kcontrol_new *knew = alc_kcontrol_new(spec); + if (!knew) + return -ENOMEM; + *knew = alc_inv_dmic_sw; + knew->name = kstrdup("Inverted Internal Mic Capture Switch", GFP_KERNEL); + if (!knew->name) return -ENOMEM; spec->inv_dmic_fixup = 1; spec->inv_dmic_muted = 0; @@ -1833,10 +1836,9 @@ static int __alc_build_controls(struct hda_codec *codec) return err; } if (spec->multiout.dig_out_nid) { - err = snd_hda_create_dig_out_ctls(codec, - spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid, - spec->pcm_rec[1].pcm_type); + err = snd_hda_create_spdif_out_ctls(codec, + spec->multiout.dig_out_nid, + spec->multiout.dig_out_nid); if (err < 0) return err; if (!spec->no_analog) { @@ -2257,10 +2259,6 @@ static int alc_build_pcms(struct hda_codec *codec) info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; - if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT && - spec->autocfg.line_outs == 2) - info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap = - snd_pcm_2_1_chmaps; } if (spec->adc_nids) { p = spec->stream_analog_capture; @@ -2401,6 +2399,7 @@ static void alc_free(struct hda_codec *codec) if (!spec) return; + alc_shutup(codec); alc_free_kctls(codec); alc_free_bind_ctls(codec); snd_hda_gen_free(&spec->gen); @@ -2535,9 +2534,13 @@ static int add_control(struct alc_spec *spec, int type, const char *name, { struct snd_kcontrol_new *knew; - knew = alc_kcontrol_new(spec, name, &alc_control_templates[type]); + knew = alc_kcontrol_new(spec); if (!knew) return -ENOMEM; + *knew = alc_control_templates[type]; + knew->name = kstrdup(name, GFP_KERNEL); + if (!knew->name) + return -ENOMEM; knew->index = cidx; if (get_amp_nid_(val)) knew->subdevice = HDA_SUBDEV_AMP_FLAG; @@ -3598,6 +3601,7 @@ static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec, { struct alc_spec *spec = codec->spec; struct hda_bind_ctls **ctlp, *ctl; + snd_array_init(&spec->bind_ctls, sizeof(ctl), 8); ctlp = snd_array_new(&spec->bind_ctls); if (!ctlp) return NULL; @@ -3980,8 +3984,14 @@ static int alc_auto_add_multi_channel_mode(struct hda_codec *codec) struct alc_spec *spec = codec->spec; if (spec->multi_ios > 0) { - if (!alc_kcontrol_new(spec, "Channel Mode", - &alc_auto_channel_mode_enum)) + struct snd_kcontrol_new *knew; + + knew = alc_kcontrol_new(spec); + if (!knew) + return -ENOMEM; + *knew = alc_auto_channel_mode_enum; + knew->name = kstrdup("Channel Mode", GFP_KERNEL); + if (!knew->name) return -ENOMEM; } return 0; @@ -4336,9 +4346,7 @@ static int alc_parse_auto_config(struct hda_codec *codec, alc_ssid_check(codec, ssid_nids); if (!spec->no_analog) { - err = alc_auto_check_switches(codec); - if (err < 0) - return err; + alc_auto_check_switches(codec); err = alc_auto_add_mic_boost(codec); if (err < 0) return err; @@ -4364,8 +4372,6 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid) codec->spec = spec; spec->mixer_nid = mixer_nid; snd_hda_gen_init(&spec->gen); - snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); - snd_array_init(&spec->bind_ctls, sizeof(struct hda_bind_ctls *), 8); err = alc_codec_rename_from_preset(codec); if (err < 0) { @@ -6003,16 +6009,6 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec, } } -static void alc271_hp_gate_mic_jack(struct hda_codec *codec, - const struct alc_fixup *fix, - int action) -{ - struct alc_spec *spec = codec->spec; - - if (action == ALC_FIXUP_ACT_PROBE) - snd_hda_jack_set_gating_jack(codec, spec->ext_mic_pin, - spec->autocfg.hp_pins[0]); -} enum { ALC269_FIXUP_SONY_VAIO, @@ -6035,8 +6031,6 @@ enum { ALC269_FIXUP_INV_DMIC, ALC269_FIXUP_LENOVO_DOCK, ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, - ALC271_FIXUP_AMIC_MIC2, - ALC271_FIXUP_HP_GATE_MIC_JACK, }; static const struct alc_fixup alc269_fixups[] = { @@ -6181,22 +6175,6 @@ static const struct alc_fixup alc269_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_pincfg_no_hp_to_lineout, }, - [ALC271_FIXUP_AMIC_MIC2] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x19, 0x01a19c20 }, /* mic */ - { 0x1b, 0x99a7012f }, /* int-mic */ - { 0x21, 0x0121401f }, /* HP out */ - { } - }, - }, - [ALC271_FIXUP_HP_GATE_MIC_JACK] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc271_hp_gate_mic_jack, - .chained = true, - .chain_id = ALC271_FIXUP_AMIC_MIC2, - }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -6217,7 +6195,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), - SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), diff --git a/trunk/sound/pci/hda/patch_sigmatel.c b/trunk/sound/pci/hda/patch_sigmatel.c index df13c0f84899..9ba8af056170 100644 --- a/trunk/sound/pci/hda/patch_sigmatel.c +++ b/trunk/sound/pci/hda/patch_sigmatel.c @@ -1081,7 +1081,7 @@ static struct snd_kcontrol_new stac_smux_mixer = { static const char * const slave_pfxs[] = { "Front", "Surround", "Center", "LFE", "Side", - "Headphone", "Speaker", "Bass Speaker", "IEC958", "PCM", + "Headphone", "Speaker", "IEC958", "PCM", NULL }; @@ -1136,10 +1136,9 @@ static int stac92xx_build_controls(struct hda_codec *codec) } if (spec->multiout.dig_out_nid) { - err = snd_hda_create_dig_out_ctls(codec, - spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid, - spec->autocfg.dig_out_type[0]); + err = snd_hda_create_spdif_out_ctls(codec, + spec->multiout.dig_out_nid, + spec->multiout.dig_out_nid); if (err < 0) return err; err = snd_hda_create_spdif_share_sw(codec, @@ -2516,11 +2515,6 @@ static int stac92xx_build_pcms(struct hda_codec *codec) info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; - if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT && - spec->autocfg.line_outs == 2) - info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap = - snd_pcm_2_1_chmaps; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs; @@ -2811,6 +2805,7 @@ stac_control_new(struct sigmatel_spec *spec, { struct snd_kcontrol_new *knew; + snd_array_init(&spec->kctls, sizeof(*knew), 32); knew = snd_array_new(&spec->kctls); if (!knew) return NULL; @@ -3273,9 +3268,9 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, idx = i; break; case AUTO_PIN_SPEAKER_OUT: - if (num_outs <= 2) { - name = i ? "Bass Speaker" : "Speaker"; - idx = 0; + if (num_outs <= 1) { + name = "Speaker"; + idx = i; break; } /* Fall through in case of multi speaker outs */ @@ -4574,6 +4569,8 @@ static void stac92xx_free(struct hda_codec *codec) if (! spec) return; + stac92xx_shutup(codec); + kfree(spec); snd_hda_detach_beep_device(codec); } @@ -5158,34 +5155,20 @@ static const struct hda_codec_ops stac92xx_patch_ops = { .reboot_notify = stac92xx_shutup, }; -static int alloc_stac_spec(struct hda_codec *codec, int num_pins, - const hda_nid_t *pin_nids) -{ - struct sigmatel_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ - spec->num_pins = num_pins; - spec->pin_nids = pin_nids; - snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); - return 0; -} - static int patch_stac9200(struct hda_codec *codec) { struct sigmatel_spec *spec; int err; - err = alloc_stac_spec(codec, ARRAY_SIZE(stac9200_pin_nids), - stac9200_pin_nids); - if (err < 0) - return err; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; - spec = codec->spec; + codec->no_trigger_sense = 1; + codec->spec = spec; spec->linear_tone_beep = 1; + spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); + spec->pin_nids = stac9200_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, stac9200_models, stac9200_cfg_tbl); @@ -5241,13 +5224,15 @@ static int patch_stac925x(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - err = alloc_stac_spec(codec, ARRAY_SIZE(stac925x_pin_nids), - stac925x_pin_nids); - if (err < 0) - return err; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; - spec = codec->spec; + codec->no_trigger_sense = 1; + codec->spec = spec; spec->linear_tone_beep = 1; + spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); + spec->pin_nids = stac925x_pin_nids; /* Check first for codec ID */ spec->board_config = snd_hda_check_board_codec_sid_config(codec, @@ -5322,17 +5307,19 @@ static int patch_stac92hd73xx(struct hda_codec *codec) { struct sigmatel_spec *spec; hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; - int err; + int err = 0; int num_dacs; - err = alloc_stac_spec(codec, ARRAY_SIZE(stac92hd73xx_pin_nids), - stac92hd73xx_pin_nids); - if (err < 0) - return err; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; - spec = codec->spec; + codec->no_trigger_sense = 1; + codec->spec = spec; spec->linear_tone_beep = 0; codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; + spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); + spec->pin_nids = stac92hd73xx_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_92HD73XX_MODELS, stac92hd73xx_models, @@ -5609,9 +5596,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) int default_polarity = -1; /* no default cfg */ int err; - err = alloc_stac_spec(codec, 0, NULL); /* pins filled later */ - if (err < 0) - return err; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; if (hp_bnb2011_with_dock(codec)) { snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f); @@ -5619,9 +5606,11 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) } codec->epss = 0; /* longer delay needed for D3 */ + codec->no_trigger_sense = 1; + codec->spec = spec; + stac92hd8x_fill_auto_spec(codec); - spec = codec->spec; spec->linear_tone_beep = 0; codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; spec->digbeep_nid = 0x21; @@ -5790,19 +5779,21 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) struct sigmatel_spec *spec; const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; unsigned int pin_cfg; - int err; + int err = 0; - err = alloc_stac_spec(codec, STAC92HD71BXX_NUM_PINS, - stac92hd71bxx_pin_nids_4port); - if (err < 0) - return err; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; - spec = codec->spec; + codec->no_trigger_sense = 1; + codec->spec = spec; spec->linear_tone_beep = 0; codec->patch_ops = stac92xx_patch_ops; + spec->num_pins = STAC92HD71BXX_NUM_PINS; switch (codec->vendor_id) { case 0x111d76b6: case 0x111d76b7: + spec->pin_nids = stac92hd71bxx_pin_nids_4port; break; case 0x111d7603: case 0x111d7608: @@ -6033,13 +6024,15 @@ static int patch_stac922x(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - err = alloc_stac_spec(codec, ARRAY_SIZE(stac922x_pin_nids), - stac922x_pin_nids); - if (err < 0) - return err; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; - spec = codec->spec; + codec->no_trigger_sense = 1; + codec->spec = spec; spec->linear_tone_beep = 1; + spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); + spec->pin_nids = stac922x_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, stac922x_models, stac922x_cfg_tbl); @@ -6136,14 +6129,16 @@ static int patch_stac927x(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - err = alloc_stac_spec(codec, ARRAY_SIZE(stac927x_pin_nids), - stac927x_pin_nids); - if (err < 0) - return err; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; - spec = codec->spec; + codec->no_trigger_sense = 1; + codec->spec = spec; spec->linear_tone_beep = 1; codec->slave_dig_outs = stac927x_slave_dig_outs; + spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); + spec->pin_nids = stac927x_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, stac927x_models, stac927x_cfg_tbl); @@ -6270,13 +6265,15 @@ static int patch_stac9205(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - err = alloc_stac_spec(codec, ARRAY_SIZE(stac9205_pin_nids), - stac9205_pin_nids); - if (err < 0) - return err; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; - spec = codec->spec; + codec->no_trigger_sense = 1; + codec->spec = spec; spec->linear_tone_beep = 1; + spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); + spec->pin_nids = stac9205_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, stac9205_models, stac9205_cfg_tbl); @@ -6424,13 +6421,14 @@ static int patch_stac9872(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - err = alloc_stac_spec(codec, ARRAY_SIZE(stac9872_pin_nids), - stac9872_pin_nids); - if (err < 0) - return err; - - spec = codec->spec; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + codec->no_trigger_sense = 1; + codec->spec = spec; spec->linear_tone_beep = 1; + spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); + spec->pin_nids = stac9872_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, stac9872_models, diff --git a/trunk/sound/pci/hda/patch_via.c b/trunk/sound/pci/hda/patch_via.c index dd8cd6af5d66..019e1a00414a 100644 --- a/trunk/sound/pci/hda/patch_via.c +++ b/trunk/sound/pci/hda/patch_via.c @@ -241,7 +241,6 @@ static struct via_spec * via_new_spec(struct hda_codec *codec) if (spec == NULL) return NULL; - snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); mutex_init(&spec->config_mutex); codec->spec = spec; spec->codec = codec; @@ -388,6 +387,7 @@ static struct snd_kcontrol_new *__via_clone_ctl(struct via_spec *spec, { struct snd_kcontrol_new *knew; + snd_array_init(&spec->kctls, sizeof(*knew), 32); knew = snd_array_new(&spec->kctls); if (!knew) return NULL; @@ -739,7 +739,18 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - return snd_hda_enum_bool_helper_info(kcontrol, uinfo); + static const char * const texts[] = { + "Disabled", "Enabled" + }; + + 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 via_pin_power_ctl_get(struct snd_kcontrol *kcontrol, @@ -1443,7 +1454,7 @@ static const struct hda_pcm_stream via_pcm_digital_capture = { */ static const char * const via_slave_pfxs[] = { "Front", "Surround", "Center", "LFE", "Side", - "Headphone", "Speaker", "Bass Speaker", + "Headphone", "Speaker", NULL, }; @@ -1544,10 +1555,6 @@ static int via_build_pcms(struct hda_codec *codec) spec->multiout.dac_nids[0]; info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; - if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT - && spec->autocfg.line_outs == 2) - info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap = - snd_pcm_2_1_chmaps; } if (!spec->stream_analog_capture) { @@ -1927,7 +1934,7 @@ static int via_auto_create_multi_out_ctls(struct hda_codec *codec) struct auto_pin_cfg *cfg = &spec->autocfg; struct nid_path *path; static const char * const chname[4] = { - "Front", "Surround", NULL /* "CLFE" */, "Side" + "Front", "Surround", "C/LFE", "Side" }; int i, idx, err; int old_line_outs; @@ -1962,8 +1969,8 @@ static int via_auto_create_multi_out_ctls(struct hda_codec *codec) } else { const char *pfx = chname[i]; if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && - cfg->line_outs <= 2) - pfx = i ? "Bass Speaker" : "Speaker"; + cfg->line_outs == 1) + pfx = "Speaker"; err = create_ch_ctls(codec, pfx, 3, true, path); if (err < 0) return err; diff --git a/trunk/sound/pci/ice1712/Makefile b/trunk/sound/pci/ice1712/Makefile index 7e50c1324556..f7ce33f00ea5 100644 --- a/trunk/sound/pci/ice1712/Makefile +++ b/trunk/sound/pci/ice1712/Makefile @@ -5,7 +5,7 @@ snd-ice17xx-ak4xxx-objs := ak4xxx.o snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o -snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o psc724.o wm8766.o wm8776.o +snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o # Toplevel Module Dependency obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o diff --git a/trunk/sound/pci/ice1712/amp.c b/trunk/sound/pci/ice1712/amp.c index d9bd27b25100..e525da2673be 100644 --- a/trunk/sound/pci/ice1712/amp.c +++ b/trunk/sound/pci/ice1712/amp.c @@ -21,6 +21,7 @@ * */ +#include #include #include #include diff --git a/trunk/sound/pci/ice1712/aureon.c b/trunk/sound/pci/ice1712/aureon.c index ce9941c5e988..20bcddea2eab 100644 --- a/trunk/sound/pci/ice1712/aureon.c +++ b/trunk/sound/pci/ice1712/aureon.c @@ -46,6 +46,7 @@ * on mixer switch and other coll stuff. */ +#include #include #include #include @@ -202,8 +203,7 @@ static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg, static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static const char * const texts[3] = - {"Internal Aux", "Wavetable", "Rear Line-In"}; + char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"}; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; diff --git a/trunk/sound/pci/ice1712/delta.c b/trunk/sound/pci/ice1712/delta.c index bbef99bf77df..20c6b079d0df 100644 --- a/trunk/sound/pci/ice1712/delta.c +++ b/trunk/sound/pci/ice1712/delta.c @@ -22,6 +22,7 @@ * */ +#include #include #include #include diff --git a/trunk/sound/pci/ice1712/ews.c b/trunk/sound/pci/ice1712/ews.c index bf289f0a1ed4..6fe35b812040 100644 --- a/trunk/sound/pci/ice1712/ews.c +++ b/trunk/sound/pci/ice1712/ews.c @@ -22,6 +22,7 @@ * */ +#include #include #include #include @@ -575,7 +576,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice) /* i/o sensitivity - this callback is shared among other devices, too */ static int snd_ice1712_ewx_io_sense_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ - static const char * const texts[2] = { + static char *texts[2] = { "+4dBu", "-10dBV", }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; @@ -898,7 +899,7 @@ static int snd_ice1712_6fire_control_put(struct snd_kcontrol *kcontrol, struct s static int snd_ice1712_6fire_select_input_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static const char * const texts[4] = { + static char *texts[4] = { "Internal", "Front Input", "Rear Input", "Wave Table" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; diff --git a/trunk/sound/pci/ice1712/hoontech.c b/trunk/sound/pci/ice1712/hoontech.c index 3d84d21e484d..6914189073a4 100644 --- a/trunk/sound/pci/ice1712/hoontech.c +++ b/trunk/sound/pci/ice1712/hoontech.c @@ -21,6 +21,7 @@ * */ +#include #include #include #include diff --git a/trunk/sound/pci/ice1712/ice1712.c b/trunk/sound/pci/ice1712/ice1712.c index dd64e223f5cf..5be2e120a14e 100644 --- a/trunk/sound/pci/ice1712/ice1712.c +++ b/trunk/sound/pci/ice1712/ice1712.c @@ -47,6 +47,7 @@ */ +#include #include #include #include @@ -2685,7 +2686,6 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, for (tbl = card_tables; *tbl; tbl++) { for (c = *tbl; c->subvendor; c++) { if (c->subvendor == ice->eeprom.subvendor) { - ice->card_info = c; strcpy(card->shortname, c->name); if (c->driver) /* specific driver? */ strcpy(card->driver, c->driver); @@ -2799,12 +2799,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, static void __devexit snd_ice1712_remove(struct pci_dev *pci) { - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ice1712 *ice = card->private_data; - - if (ice->card_info && ice->card_info->chip_exit) - ice->card_info->chip_exit(ice); - snd_card_free(card); + snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL); } diff --git a/trunk/sound/pci/ice1712/ice1712.h b/trunk/sound/pci/ice1712/ice1712.h index b209fc30b334..d0e7d87f09f0 100644 --- a/trunk/sound/pci/ice1712/ice1712.h +++ b/trunk/sound/pci/ice1712/ice1712.h @@ -22,7 +22,6 @@ * */ -#include #include #include #include @@ -289,7 +288,6 @@ struct snd_ice1712_spdif { } ops; }; -struct snd_ice1712_card_info; struct snd_ice1712 { unsigned long conp_dma_size; @@ -326,7 +324,6 @@ struct snd_ice1712 { struct snd_info_entry *proc_entry; struct snd_ice1712_eeprom eeprom; - struct snd_ice1712_card_info *card_info; unsigned int pro_volumes[20]; unsigned int omni:1; /* Delta Omni I/O */ @@ -384,7 +381,7 @@ struct snd_ice1712 { unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); int (*set_spdif_clock)(struct snd_ice1712 *ice, int type); int (*get_spdif_master_type)(struct snd_ice1712 *ice); - const char * const *ext_clock_names; + char **ext_clock_names; int ext_clock_count; void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *); #ifdef CONFIG_PM_SLEEP @@ -516,11 +513,10 @@ static inline u8 snd_ice1712_read(struct snd_ice1712 *ice, u8 addr) struct snd_ice1712_card_info { unsigned int subvendor; - const char *name; - const char *model; - const char *driver; + char *name; + char *model; + char *driver; int (*chip_init)(struct snd_ice1712 *); - void (*chip_exit)(struct snd_ice1712 *); int (*build_controls)(struct snd_ice1712 *); unsigned int no_mpu401:1; unsigned int mpu401_1_info_flags; diff --git a/trunk/sound/pci/ice1712/ice1724.c b/trunk/sound/pci/ice1712/ice1724.c index ea99e5695f9f..245d874891ba 100644 --- a/trunk/sound/pci/ice1712/ice1724.c +++ b/trunk/sound/pci/ice1712/ice1724.c @@ -22,6 +22,7 @@ * */ +#include #include #include #include @@ -53,7 +54,6 @@ #include "wtm.h" #include "se.h" #include "quartet.h" -#include "psc724.h" MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); @@ -106,7 +106,7 @@ static int PRO_RATE_LOCKED; static int PRO_RATE_RESET = 1; static unsigned int PRO_RATE_DEFAULT = 44100; -static const char * const ext_clock_names[1] = { "IEC958 In" }; +static char *ext_clock_names[1] = { "IEC958 In" }; /* * Basic I/O @@ -2042,7 +2042,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = { static int snd_vt1724_pro_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static const char * const texts[] = { + static char *texts[] = { "PCM Out", /* 0 */ "H/W In 0", "H/W In 1", /* 1-2 */ "IEC958 In L", "IEC958 In R", /* 3-4 */ @@ -2232,7 +2232,7 @@ static unsigned char ooaoo_sq210_eeprom[] __devinitdata = { }; -static struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = { +struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = { { .name = "ooAoo SQ210a", .model = "sq210a", @@ -2257,7 +2257,6 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = { snd_vt1724_se_cards, snd_vt1724_qtet_cards, snd_vt1724_ooaoo_cards, - snd_vt1724_psc724_cards, NULL, }; @@ -2349,7 +2348,6 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice, ice->eeprom.subvendor = c->subvendor; } else if (c->subvendor != ice->eeprom.subvendor) continue; - ice->card_info = c; if (!c->eeprom_size || !c->eeprom_data) goto found; /* if the EEPROM is given by the driver, use it */ @@ -2362,10 +2360,6 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice, } printk(KERN_WARNING "ice1724: No matching model found for ID 0x%x\n", ice->eeprom.subvendor); -#ifdef CONFIG_PM_SLEEP - /* assume AC97-only card which can suspend without additional code */ - ice->pm_suspend_enabled = 1; -#endif found: ice->eeprom.size = snd_vt1724_read_i2c(ice, dev, 0x04); @@ -2377,7 +2371,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice, return -EIO; } ice->eeprom.version = snd_vt1724_read_i2c(ice, dev, 0x05); - if (ice->eeprom.version != 1 && ice->eeprom.version != 2) + if (ice->eeprom.version != 2) printk(KERN_WARNING "ice1724: Invalid EEPROM version %i\n", ice->eeprom.version); size = ice->eeprom.size - 6; @@ -2794,12 +2788,7 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, static void __devexit snd_vt1724_remove(struct pci_dev *pci) { - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ice1712 *ice = card->private_data; - - if (ice->card_info && ice->card_info->chip_exit) - ice->card_info->chip_exit(ice); - snd_card_free(card); + snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL); } diff --git a/trunk/sound/pci/ice1712/juli.c b/trunk/sound/pci/ice1712/juli.c index a6b23b421512..14fd536b6452 100644 --- a/trunk/sound/pci/ice1712/juli.c +++ b/trunk/sound/pci/ice1712/juli.c @@ -23,6 +23,7 @@ * */ +#include #include #include #include @@ -434,8 +435,7 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, } static void __devinit add_slaves(struct snd_card *card, - struct snd_kcontrol *master, - char * const *list) + struct snd_kcontrol *master, char **list) { for (; *list; list++) { struct snd_kcontrol *slave = ctl_find(card, *list); diff --git a/trunk/sound/pci/ice1712/maya44.c b/trunk/sound/pci/ice1712/maya44.c index d8d749e5ed41..726fd4b92e19 100644 --- a/trunk/sound/pci/ice1712/maya44.c +++ b/trunk/sound/pci/ice1712/maya44.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -357,7 +358,7 @@ static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line) static int maya_rec_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static const char * const texts[] = { "Line", "Mic" }; + static char *texts[] = { "Line", "Mic" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; @@ -406,7 +407,7 @@ static int maya_rec_src_put(struct snd_kcontrol *kcontrol, static int maya_pb_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static const char * const texts[] = { + static char *texts[] = { "PCM Out", /* 0 */ "Input 1", "Input 2", "Input 3", "Input 4" }; diff --git a/trunk/sound/pci/ice1712/phase.c b/trunk/sound/pci/ice1712/phase.c index c9be75a457c3..de29be8c9657 100644 --- a/trunk/sound/pci/ice1712/phase.c +++ b/trunk/sound/pci/ice1712/phase.c @@ -42,6 +42,7 @@ * Digital receiver: CS8414-CS (supported in this release) */ +#include #include #include #include @@ -721,7 +722,7 @@ static int phase28_deemp_put(struct snd_kcontrol *kcontrol, static int phase28_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) { - static const char * const texts[2] = { "128x", "64x" }; + static char *texts[2] = { "128x", "64x" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; diff --git a/trunk/sound/pci/ice1712/pontis.c b/trunk/sound/pci/ice1712/pontis.c index 3ce1289263a3..92c1160d7ab5 100644 --- a/trunk/sound/pci/ice1712/pontis.c +++ b/trunk/sound/pci/ice1712/pontis.c @@ -21,6 +21,7 @@ * */ +#include #include #include #include diff --git a/trunk/sound/pci/ice1712/prodigy192.c b/trunk/sound/pci/ice1712/prodigy192.c index 3fcf581e7ef8..e36ddb94c382 100644 --- a/trunk/sound/pci/ice1712/prodigy192.c +++ b/trunk/sound/pci/ice1712/prodigy192.c @@ -54,6 +54,7 @@ * */ +#include #include #include #include @@ -282,7 +283,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static const char * const texts[2] = { "Line In", "Mic" }; + static char *texts[2] = { "Line In", "Mic" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; @@ -561,7 +562,7 @@ static unsigned char prodigy192_ak4114_read(void *private_data, static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static const char * const texts[2] = { "Toslink", "Coax" }; + static char *texts[2] = { "Toslink", "Coax" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; diff --git a/trunk/sound/pci/ice1712/prodigy_hifi.c b/trunk/sound/pci/ice1712/prodigy_hifi.c index 4fea87fb5799..7bf093c51ce5 100644 --- a/trunk/sound/pci/ice1712/prodigy_hifi.c +++ b/trunk/sound/pci/ice1712/prodigy_hifi.c @@ -25,6 +25,7 @@ */ +#include #include #include #include diff --git a/trunk/sound/pci/ice1712/psc724.c b/trunk/sound/pci/ice1712/psc724.c deleted file mode 100644 index 0b6c4e69b8d0..000000000000 --- a/trunk/sound/pci/ice1712/psc724.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for Philips PSC724 Ultimate Edge - * - * Copyright (c) 2012 Ondrej Zary - * - * 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 -#include -#include -#include - -#include "ice1712.h" -#include "envy24ht.h" -#include "psc724.h" -#include "wm8766.h" -#include "wm8776.h" - -struct psc724_spec { - struct snd_wm8766 wm8766; - struct snd_wm8776 wm8776; - bool mute_all, jack_detect; - struct snd_ice1712 *ice; - struct delayed_work hp_work; - bool hp_connected; -}; - -/****************************************************************************/ -/* PHILIPS PSC724 ULTIMATE EDGE */ -/****************************************************************************/ -/* - * VT1722 (Envy24GT) - 6 outputs, 4 inputs (only 2 used), 24-bit/96kHz - * - * system configuration ICE_EEP2_SYSCONF=0x42 - * XIN1 49.152MHz - * no MPU401 - * one stereo ADC, no S/PDIF receiver - * three stereo DACs (FRONT, REAR, CENTER+LFE) - * - * AC-Link configuration ICE_EEP2_ACLINK=0x80 - * use I2S, not AC97 - * - * I2S converters feature ICE_EEP2_I2S=0x30 - * I2S codec has no volume/mute control feature (bug!) - * I2S codec does not support 96KHz or 192KHz (bug!) - * I2S codec 24bits - * - * S/PDIF configuration ICE_EEP2_SPDIF=0xc1 - * Enable integrated S/PDIF transmitter - * internal S/PDIF out implemented - * No S/PDIF input - * External S/PDIF out implemented - * - * - * ** connected chips ** - * - * WM8776 - * 2-channel DAC used for main output and stereo ADC (with 10-channel MUX) - * AIN1: LINE IN, AIN2: CD/VIDEO, AIN3: AUX, AIN4: Front MIC, AIN5: Rear MIC - * Controlled by I2C using VT1722 I2C interface: - * MODE (pin16) -- GND - * CE (pin17) -- GND I2C mode (address=0x34) - * DI (pin18) -- SDA (VT1722 pin70) - * CL (pin19) -- SCLK (VT1722 pin71) - * - * WM8766 - * 6-channel DAC used for rear & center/LFE outputs (only 4 channels used) - * Controlled by SPI using VT1722 GPIO pins: - * MODE (pin 1) -- GPIO19 (VT1722 pin99) - * ML/I2S (pin11) -- GPIO18 (VT1722 pin98) - * MC/IWL (pin12) -- GPIO17 (VT1722 pin97) - * MD/DM (pin13) -- GPIO16 (VT1722 pin96) - * MUTE (pin14) -- GPIO20 (VT1722 pin101) - * - * GPIO14 is used as input for headphone jack detection (1 = connected) - * GPIO22 is used as MUTE ALL output, grounding all 6 channels - * - * ** output pins and device names ** - * - * 5.1ch name -- output connector color -- device (-D option) - * - * FRONT 2ch -- green -- plughw:0,0 - * CENTER(Lch) SUBWOOFER(Rch) -- orange -- plughw:0,2,0 - * REAR 2ch -- black -- plughw:0,2,1 - */ - -/* codec access low-level functions */ - -#define GPIO_HP_JACK (1 << 14) -#define GPIO_MUTE_SUR (1 << 20) -#define GPIO_MUTE_ALL (1 << 22) - -#define JACK_INTERVAL 1000 - -#define PSC724_SPI_DELAY 1 - -#define PSC724_SPI_DATA (1 << 16) -#define PSC724_SPI_CLK (1 << 17) -#define PSC724_SPI_LOAD (1 << 18) -#define PSC724_SPI_MASK (PSC724_SPI_DATA | PSC724_SPI_CLK | PSC724_SPI_LOAD) - -static void psc724_wm8766_write(struct snd_wm8766 *wm, u16 addr, u16 data) -{ - struct psc724_spec *spec = container_of(wm, struct psc724_spec, wm8766); - struct snd_ice1712 *ice = spec->ice; - u32 st, bits; - int i; - - snd_ice1712_save_gpio_status(ice); - - st = ((addr & 0x7f) << 9) | (data & 0x1ff); - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | PSC724_SPI_MASK); - snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~PSC724_SPI_MASK); - bits = snd_ice1712_gpio_read(ice) & ~PSC724_SPI_MASK; - snd_ice1712_gpio_write(ice, bits); - - for (i = 0; i < 16; i++) { - udelay(PSC724_SPI_DELAY); - bits &= ~PSC724_SPI_CLK; - /* MSB first */ - st <<= 1; - if (st & 0x10000) - bits |= PSC724_SPI_DATA; - else - bits &= ~PSC724_SPI_DATA; - snd_ice1712_gpio_write(ice, bits); - /* CLOCK high */ - udelay(PSC724_SPI_DELAY); - bits |= PSC724_SPI_CLK; - snd_ice1712_gpio_write(ice, bits); - } - /* LOAD high */ - udelay(PSC724_SPI_DELAY); - bits |= PSC724_SPI_LOAD; - snd_ice1712_gpio_write(ice, bits); - /* LOAD low, DATA and CLOCK high */ - udelay(PSC724_SPI_DELAY); - bits |= (PSC724_SPI_DATA | PSC724_SPI_CLK); - snd_ice1712_gpio_write(ice, bits); - - snd_ice1712_restore_gpio_status(ice); -} - -static void psc724_wm8776_write(struct snd_wm8776 *wm, u8 addr, u8 data) -{ - struct psc724_spec *spec = container_of(wm, struct psc724_spec, wm8776); - - snd_vt1724_write_i2c(spec->ice, 0x34, addr, data); -} - -/* mute all */ - -static void psc724_set_master_switch(struct snd_ice1712 *ice, bool on) -{ - unsigned int bits = snd_ice1712_gpio_read(ice); - struct psc724_spec *spec = ice->spec; - - spec->mute_all = !on; - if (on) - bits &= ~(GPIO_MUTE_ALL | GPIO_MUTE_SUR); - else - bits |= GPIO_MUTE_ALL | GPIO_MUTE_SUR; - snd_ice1712_gpio_write(ice, bits); -} - -static bool psc724_get_master_switch(struct snd_ice1712 *ice) -{ - struct psc724_spec *spec = ice->spec; - - return !spec->mute_all; -} - -/* jack detection */ - -static void psc724_set_jack_state(struct snd_ice1712 *ice, bool hp_connected) -{ - struct psc724_spec *spec = ice->spec; - struct snd_ctl_elem_id elem_id; - struct snd_kcontrol *kctl; - u16 power = spec->wm8776.regs[WM8776_REG_PWRDOWN] & ~WM8776_PWR_HPPD; - - psc724_set_master_switch(ice, !hp_connected); - if (!hp_connected) - power |= WM8776_PWR_HPPD; - snd_wm8776_set_power(&spec->wm8776, power); - spec->hp_connected = hp_connected; - /* notify about master speaker mute change */ - memset(&elem_id, 0, sizeof(elem_id)); - elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strncpy(elem_id.name, "Master Speakers Playback Switch", - sizeof(elem_id.name)); - kctl = snd_ctl_find_id(ice->card, &elem_id); - snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); - /* and headphone mute change */ - strncpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name, - sizeof(elem_id.name)); - kctl = snd_ctl_find_id(ice->card, &elem_id); - snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); -} - -static void psc724_update_hp_jack_state(struct work_struct *work) -{ - struct psc724_spec *spec = container_of(work, struct psc724_spec, - hp_work.work); - struct snd_ice1712 *ice = spec->ice; - bool hp_connected = snd_ice1712_gpio_read(ice) & GPIO_HP_JACK; - - schedule_delayed_work(&spec->hp_work, msecs_to_jiffies(JACK_INTERVAL)); - if (hp_connected == spec->hp_connected) - return; - psc724_set_jack_state(ice, hp_connected); -} - -static void psc724_set_jack_detection(struct snd_ice1712 *ice, bool on) -{ - struct psc724_spec *spec = ice->spec; - - if (spec->jack_detect == on) - return; - - spec->jack_detect = on; - if (on) { - bool hp_connected = snd_ice1712_gpio_read(ice) & GPIO_HP_JACK; - psc724_set_jack_state(ice, hp_connected); - schedule_delayed_work(&spec->hp_work, - msecs_to_jiffies(JACK_INTERVAL)); - } else - cancel_delayed_work_sync(&spec->hp_work); -} - -static bool psc724_get_jack_detection(struct snd_ice1712 *ice) -{ - struct psc724_spec *spec = ice->spec; - - return spec->jack_detect; -} - -/* mixer controls */ - -struct psc724_control { - const char *name; - void (*set)(struct snd_ice1712 *ice, bool on); - bool (*get)(struct snd_ice1712 *ice); -}; - -static const struct psc724_control psc724_cont[] = { - { - .name = "Master Speakers Playback Switch", - .set = psc724_set_master_switch, - .get = psc724_get_master_switch, - }, - { - .name = "Headphone Jack Detection Playback Switch", - .set = psc724_set_jack_detection, - .get = psc724_get_jack_detection, - }, -}; - -static int psc724_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - - ucontrol->value.integer.value[0] = psc724_cont[n].get(ice); - - return 0; -} - -static int psc724_ctl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - - psc724_cont[n].set(ice, ucontrol->value.integer.value[0]); - - return 0; -} - -static const char *front_volume = "Front Playback Volume"; -static const char *front_switch = "Front Playback Switch"; -static const char *front_zc = "Front Zero Cross Detect Playback Switch"; -static const char *front_izd = "Front Infinite Zero Detect Playback Switch"; -static const char *front_phase = "Front Phase Invert Playback Switch"; -static const char *front_deemph = "Front Deemphasis Playback Switch"; -static const char *ain1_switch = "Line Capture Switch"; -static const char *ain2_switch = "CD Capture Switch"; -static const char *ain3_switch = "AUX Capture Switch"; -static const char *ain4_switch = "Front Mic Capture Switch"; -static const char *ain5_switch = "Rear Mic Capture Switch"; -static const char *rear_volume = "Surround Playback Volume"; -static const char *clfe_volume = "CLFE Playback Volume"; -static const char *rear_switch = "Surround Playback Switch"; -static const char *clfe_switch = "CLFE Playback Switch"; -static const char *rear_phase = "Surround Phase Invert Playback Switch"; -static const char *clfe_phase = "CLFE Phase Invert Playback Switch"; -static const char *rear_deemph = "Surround Deemphasis Playback Switch"; -static const char *clfe_deemph = "CLFE Deemphasis Playback Switch"; -static const char *rear_clfe_izd = "Rear Infinite Zero Detect Playback Switch"; -static const char *rear_clfe_zc = "Rear Zero Cross Detect Playback Switch"; - -static int __devinit psc724_add_controls(struct snd_ice1712 *ice) -{ - struct snd_kcontrol_new cont; - struct snd_kcontrol *ctl; - int err, i; - struct psc724_spec *spec = ice->spec; - - spec->wm8776.ctl[WM8776_CTL_DAC_VOL].name = front_volume; - spec->wm8776.ctl[WM8776_CTL_DAC_SW].name = front_switch; - spec->wm8776.ctl[WM8776_CTL_DAC_ZC_SW].name = front_zc; - spec->wm8776.ctl[WM8776_CTL_AUX_SW].name = NULL; - spec->wm8776.ctl[WM8776_CTL_DAC_IZD_SW].name = front_izd; - spec->wm8776.ctl[WM8776_CTL_PHASE_SW].name = front_phase; - spec->wm8776.ctl[WM8776_CTL_DEEMPH_SW].name = front_deemph; - spec->wm8776.ctl[WM8776_CTL_INPUT1_SW].name = ain1_switch; - spec->wm8776.ctl[WM8776_CTL_INPUT2_SW].name = ain2_switch; - spec->wm8776.ctl[WM8776_CTL_INPUT3_SW].name = ain3_switch; - spec->wm8776.ctl[WM8776_CTL_INPUT4_SW].name = ain4_switch; - spec->wm8776.ctl[WM8776_CTL_INPUT5_SW].name = ain5_switch; - snd_wm8776_build_controls(&spec->wm8776); - spec->wm8766.ctl[WM8766_CTL_CH1_VOL].name = rear_volume; - spec->wm8766.ctl[WM8766_CTL_CH2_VOL].name = clfe_volume; - spec->wm8766.ctl[WM8766_CTL_CH3_VOL].name = NULL; - spec->wm8766.ctl[WM8766_CTL_CH1_SW].name = rear_switch; - spec->wm8766.ctl[WM8766_CTL_CH2_SW].name = clfe_switch; - spec->wm8766.ctl[WM8766_CTL_CH3_SW].name = NULL; - spec->wm8766.ctl[WM8766_CTL_PHASE1_SW].name = rear_phase; - spec->wm8766.ctl[WM8766_CTL_PHASE2_SW].name = clfe_phase; - spec->wm8766.ctl[WM8766_CTL_PHASE3_SW].name = NULL; - spec->wm8766.ctl[WM8766_CTL_DEEMPH1_SW].name = rear_deemph; - spec->wm8766.ctl[WM8766_CTL_DEEMPH2_SW].name = clfe_deemph; - spec->wm8766.ctl[WM8766_CTL_DEEMPH3_SW].name = NULL; - spec->wm8766.ctl[WM8766_CTL_IZD_SW].name = rear_clfe_izd; - spec->wm8766.ctl[WM8766_CTL_ZC_SW].name = rear_clfe_zc; - snd_wm8766_build_controls(&spec->wm8766); - - memset(&cont, 0, sizeof(cont)); - cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - for (i = 0; i < ARRAY_SIZE(psc724_cont); i++) { - cont.private_value = i; - cont.name = psc724_cont[i].name; - cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - cont.info = snd_ctl_boolean_mono_info; - cont.get = psc724_ctl_get; - cont.put = psc724_ctl_put; - ctl = snd_ctl_new1(&cont, ice); - if (!ctl) - return -ENOMEM; - err = snd_ctl_add(ice->card, ctl); - if (err < 0) - return err; - } - - return 0; -} - -static void psc724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate) -{ - struct psc724_spec *spec = ice->spec; - /* restore codec volume settings after rate change (PMCLK stop) */ - snd_wm8776_volume_restore(&spec->wm8776); - snd_wm8766_volume_restore(&spec->wm8766); -} - -/* power management */ - -#ifdef CONFIG_PM_SLEEP -static int psc724_resume(struct snd_ice1712 *ice) -{ - struct psc724_spec *spec = ice->spec; - - snd_wm8776_resume(&spec->wm8776); - snd_wm8766_resume(&spec->wm8766); - - return 0; -} -#endif - -/* init */ - -static int __devinit psc724_init(struct snd_ice1712 *ice) -{ - struct psc724_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - spec->ice = ice; - - ice->num_total_dacs = 6; - ice->num_total_adcs = 2; - spec->wm8776.ops.write = psc724_wm8776_write; - spec->wm8776.card = ice->card; - snd_wm8776_init(&spec->wm8776); - spec->wm8766.ops.write = psc724_wm8766_write; - spec->wm8766.card = ice->card; -#ifdef CONFIG_PM_SLEEP - ice->pm_resume = psc724_resume; - ice->pm_suspend_enabled = 1; -#endif - snd_wm8766_init(&spec->wm8766); - snd_wm8766_set_if(&spec->wm8766, - WM8766_IF_FMT_I2S | WM8766_IF_IWL_24BIT); - ice->gpio.set_pro_rate = psc724_set_pro_rate; - INIT_DELAYED_WORK(&spec->hp_work, psc724_update_hp_jack_state); - psc724_set_jack_detection(ice, true); - return 0; -} - -static void psc724_exit(struct snd_ice1712 *ice) -{ - struct psc724_spec *spec = ice->spec; - - cancel_delayed_work_sync(&spec->hp_work); -} - -/* PSC724 has buggy EEPROM (no 96&192kHz, all FFh GPIOs), so override it here */ -static unsigned char psc724_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x42, /* 49.152MHz, 1 ADC, 3 DACs */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xf0, /* I2S volume, 96kHz, 24bit */ - [ICE_EEP2_SPDIF] = 0xc1, /* spdif out-en, out-int, no input */ - /* GPIO outputs */ - [ICE_EEP2_GPIO_DIR2] = 0x5f, /* MUTE_ALL,WM8766 MUTE/MODE/ML/MC/MD */ - /* GPIO write enable */ - [ICE_EEP2_GPIO_MASK] = 0xff, /* read-only */ - [ICE_EEP2_GPIO_MASK1] = 0xff, /* read-only */ - [ICE_EEP2_GPIO_MASK2] = 0xa0, /* MUTE_ALL,WM8766 MUTE/MODE/ML/MC/MD */ - /* GPIO initial state */ - [ICE_EEP2_GPIO_STATE2] = 0x20, /* unmuted, all WM8766 pins low */ -}; - -struct snd_ice1712_card_info snd_vt1724_psc724_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_PSC724, - .name = "Philips PSC724 Ultimate Edge", - .model = "psc724", - .chip_init = psc724_init, - .chip_exit = psc724_exit, - .build_controls = psc724_add_controls, - .eeprom_size = sizeof(psc724_eeprom), - .eeprom_data = psc724_eeprom, - }, - {} /*terminator*/ -}; diff --git a/trunk/sound/pci/ice1712/psc724.h b/trunk/sound/pci/ice1712/psc724.h deleted file mode 100644 index 858e5fd0eebb..000000000000 --- a/trunk/sound/pci/ice1712/psc724.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __SOUND_PSC724_H -#define __SOUND_PSC724_H - -/* ID */ -#define PSC724_DEVICE_DESC \ - "{Philips,PSC724 Ultimate Edge}," - -#define VT1724_SUBDEVICE_PSC724 0xab170619 - -/* entry struct */ -extern struct snd_ice1712_card_info snd_vt1724_psc724_cards[]; - -#endif /* __SOUND_PSC724_H */ diff --git a/trunk/sound/pci/ice1712/quartet.c b/trunk/sound/pci/ice1712/quartet.c index c85b2ff79115..1948632787e6 100644 --- a/trunk/sound/pci/ice1712/quartet.c +++ b/trunk/sound/pci/ice1712/quartet.c @@ -22,6 +22,7 @@ * */ +#include #include #include #include @@ -46,7 +47,7 @@ struct qtet_kcontrol_private { unsigned int bit; void (*set_register)(struct snd_ice1712 *ice, unsigned int val); unsigned int (*get_register)(struct snd_ice1712 *ice); - unsigned char * const texts[2]; + unsigned char *texts[2]; }; enum { @@ -62,7 +63,7 @@ enum { OUT34_MON12, }; -static const char * const ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS", +static char *ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS", "Word Clock 256xFS"}; /* chip address on I2C bus */ @@ -550,8 +551,7 @@ static int qtet_mute_put(struct snd_kcontrol *kcontrol, static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static const char * const texts[3] = - {"Line In 1/2", "Mic", "Mic + Low-cut"}; + static char *texts[3] = {"Line In 1/2", "Mic", "Mic + Low-cut"}; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = ARRAY_SIZE(texts); @@ -816,7 +816,7 @@ static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, } static void __devinit add_slaves(struct snd_card *card, - struct snd_kcontrol *master, char * const *list) + struct snd_kcontrol *master, char **list) { for (; *list; list++) { struct snd_kcontrol *slave = ctl_find(card, *list); diff --git a/trunk/sound/pci/ice1712/revo.c b/trunk/sound/pci/ice1712/revo.c index a1b79758766b..b508bb360b97 100644 --- a/trunk/sound/pci/ice1712/revo.c +++ b/trunk/sound/pci/ice1712/revo.c @@ -21,6 +21,7 @@ * */ +#include #include #include #include diff --git a/trunk/sound/pci/ice1712/se.c b/trunk/sound/pci/ice1712/se.c index 53b555f5bbea..69673b95869d 100644 --- a/trunk/sound/pci/ice1712/se.c +++ b/trunk/sound/pci/ice1712/se.c @@ -22,6 +22,7 @@ * */ +#include #include #include #include @@ -252,7 +253,7 @@ static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice, se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100); } -static const char * const se200pci_sel[] = { +static const char *se200pci_sel[] = { "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL }; @@ -277,7 +278,7 @@ static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl) se200pci_WM8776_write(ice, 0x16, 0x001); } -static const char * const se200pci_agc[] = { +static const char *se200pci_agc[] = { "Off", "LimiterMode", "ALCMode", NULL }; @@ -351,7 +352,7 @@ static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate) } struct se200pci_control { - const char *name; + char *name; enum { WM8766, WM8776in, @@ -362,7 +363,7 @@ struct se200pci_control { } target; enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type; int ch; - const char * const *member; + const char **member; const char *comment; }; @@ -420,7 +421,7 @@ static const struct se200pci_control se200pci_cont[] = { static int se200pci_get_enum_count(int n) { - const char * const *member; + const char **member; int c; member = se200pci_cont[n].member; diff --git a/trunk/sound/pci/ice1712/vt1720_mobo.c b/trunk/sound/pci/ice1712/vt1720_mobo.c index 8a0a8393ad9e..4c551e147c08 100644 --- a/trunk/sound/pci/ice1712/vt1720_mobo.c +++ b/trunk/sound/pci/ice1712/vt1720_mobo.c @@ -21,6 +21,7 @@ * */ +#include #include #include #include diff --git a/trunk/sound/pci/ice1712/wm8766.c b/trunk/sound/pci/ice1712/wm8766.c deleted file mode 100644 index 8072adeecf68..000000000000 --- a/trunk/sound/pci/ice1712/wm8766.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT17xx - * - * Lowlevel functions for WM8766 codec - * - * Copyright (c) 2012 Ondrej Zary - * - * 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 -#include -#include -#include -#include "wm8766.h" - -/* low-level access */ - -static void snd_wm8766_write(struct snd_wm8766 *wm, u16 addr, u16 data) -{ - if (addr < WM8766_REG_RESET) - wm->regs[addr] = data; - wm->ops.write(wm, addr, data); -} - -/* mixer controls */ - -static const DECLARE_TLV_DB_SCALE(wm8766_tlv, -12750, 50, 1); - -static struct snd_wm8766_ctl snd_wm8766_default_ctl[WM8766_CTL_COUNT] = { - [WM8766_CTL_CH1_VOL] = { - .name = "Channel 1 Playback Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8766_tlv, - .reg1 = WM8766_REG_DACL1, - .reg2 = WM8766_REG_DACR1, - .mask1 = WM8766_VOL_MASK, - .mask2 = WM8766_VOL_MASK, - .max = 0xff, - .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE, - }, - [WM8766_CTL_CH2_VOL] = { - .name = "Channel 2 Playback Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8766_tlv, - .reg1 = WM8766_REG_DACL2, - .reg2 = WM8766_REG_DACR2, - .mask1 = WM8766_VOL_MASK, - .mask2 = WM8766_VOL_MASK, - .max = 0xff, - .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE, - }, - [WM8766_CTL_CH3_VOL] = { - .name = "Channel 3 Playback Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8766_tlv, - .reg1 = WM8766_REG_DACL3, - .reg2 = WM8766_REG_DACR3, - .mask1 = WM8766_VOL_MASK, - .mask2 = WM8766_VOL_MASK, - .max = 0xff, - .flags = WM8766_FLAG_STEREO | WM8766_FLAG_VOL_UPDATE, - }, - [WM8766_CTL_CH1_SW] = { - .name = "Channel 1 Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_DACCTRL2, - .mask1 = WM8766_DAC2_MUTE1, - .flags = WM8766_FLAG_INVERT, - }, - [WM8766_CTL_CH2_SW] = { - .name = "Channel 2 Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_DACCTRL2, - .mask1 = WM8766_DAC2_MUTE2, - .flags = WM8766_FLAG_INVERT, - }, - [WM8766_CTL_CH3_SW] = { - .name = "Channel 3 Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_DACCTRL2, - .mask1 = WM8766_DAC2_MUTE3, - .flags = WM8766_FLAG_INVERT, - }, - [WM8766_CTL_PHASE1_SW] = { - .name = "Channel 1 Phase Invert Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_IFCTRL, - .mask1 = WM8766_PHASE_INVERT1, - }, - [WM8766_CTL_PHASE2_SW] = { - .name = "Channel 2 Phase Invert Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_IFCTRL, - .mask1 = WM8766_PHASE_INVERT2, - }, - [WM8766_CTL_PHASE3_SW] = { - .name = "Channel 3 Phase Invert Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_IFCTRL, - .mask1 = WM8766_PHASE_INVERT3, - }, - [WM8766_CTL_DEEMPH1_SW] = { - .name = "Channel 1 Deemphasis Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_DACCTRL2, - .mask1 = WM8766_DAC2_DEEMP1, - }, - [WM8766_CTL_DEEMPH2_SW] = { - .name = "Channel 2 Deemphasis Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_DACCTRL2, - .mask1 = WM8766_DAC2_DEEMP2, - }, - [WM8766_CTL_DEEMPH3_SW] = { - .name = "Channel 3 Deemphasis Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_DACCTRL2, - .mask1 = WM8766_DAC2_DEEMP3, - }, - [WM8766_CTL_IZD_SW] = { - .name = "Infinite Zero Detect Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_DACCTRL1, - .mask1 = WM8766_DAC_IZD, - }, - [WM8766_CTL_ZC_SW] = { - .name = "Zero Cross Detect Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8766_REG_DACCTRL2, - .mask1 = WM8766_DAC2_ZCD, - .flags = WM8766_FLAG_INVERT, - }, -}; - -/* exported functions */ - -void snd_wm8766_init(struct snd_wm8766 *wm) -{ - int i; - static const u16 default_values[] = { - 0x000, 0x100, - 0x120, 0x000, - 0x000, 0x100, 0x000, 0x100, 0x000, - 0x000, 0x080, - }; - - memcpy(wm->ctl, snd_wm8766_default_ctl, sizeof(wm->ctl)); - - snd_wm8766_write(wm, WM8766_REG_RESET, 0x00); /* reset */ - udelay(10); - /* load defaults */ - for (i = 0; i < ARRAY_SIZE(default_values); i++) - snd_wm8766_write(wm, i, default_values[i]); -} - -void snd_wm8766_resume(struct snd_wm8766 *wm) -{ - int i; - - for (i = 0; i < WM8766_REG_COUNT; i++) - snd_wm8766_write(wm, i, wm->regs[i]); -} - -void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac) -{ - u16 val = wm->regs[WM8766_REG_IFCTRL] & ~WM8766_IF_MASK; - - dac &= WM8766_IF_MASK; - snd_wm8766_write(wm, WM8766_REG_IFCTRL, val | dac); -} - -void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode) -{ - u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_MSTR_MASK; - - mode &= WM8766_DAC3_MSTR_MASK; - snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | mode); -} - -void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power) -{ - u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_POWER_MASK; - - power &= WM8766_DAC3_POWER_MASK; - snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | power); -} - -void snd_wm8766_volume_restore(struct snd_wm8766 *wm) -{ - u16 val = wm->regs[WM8766_REG_DACR1]; - /* restore volume after MCLK stopped */ - snd_wm8766_write(wm, WM8766_REG_DACR1, val | WM8766_VOL_UPDATE); -} - -/* mixer callbacks */ - -static int snd_wm8766_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = (wm->ctl[n].flags & WM8766_FLAG_STEREO) ? 2 : 1; - uinfo->value.integer.min = wm->ctl[n].min; - uinfo->value.integer.max = wm->ctl[n].max; - - return 0; -} - -static int snd_wm8766_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - - return snd_ctl_enum_info(uinfo, 1, wm->ctl[n].max, - wm->ctl[n].enum_names); -} - -static int snd_wm8766_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - u16 val1, val2; - - if (wm->ctl[n].get) - wm->ctl[n].get(wm, &val1, &val2); - else { - val1 = wm->regs[wm->ctl[n].reg1] & wm->ctl[n].mask1; - val1 >>= __ffs(wm->ctl[n].mask1); - if (wm->ctl[n].flags & WM8766_FLAG_STEREO) { - val2 = wm->regs[wm->ctl[n].reg2] & wm->ctl[n].mask2; - val2 >>= __ffs(wm->ctl[n].mask2); - if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE) - val2 &= ~WM8766_VOL_UPDATE; - } - } - if (wm->ctl[n].flags & WM8766_FLAG_INVERT) { - val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min); - val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min); - } - ucontrol->value.integer.value[0] = val1; - if (wm->ctl[n].flags & WM8766_FLAG_STEREO) - ucontrol->value.integer.value[1] = val2; - - return 0; -} - -static int snd_wm8766_ctl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - u16 val, regval1, regval2; - - /* this also works for enum because value is an union */ - regval1 = ucontrol->value.integer.value[0]; - regval2 = ucontrol->value.integer.value[1]; - if (wm->ctl[n].flags & WM8766_FLAG_INVERT) { - regval1 = wm->ctl[n].max - (regval1 - wm->ctl[n].min); - regval2 = wm->ctl[n].max - (regval2 - wm->ctl[n].min); - } - if (wm->ctl[n].set) - wm->ctl[n].set(wm, regval1, regval2); - else { - val = wm->regs[wm->ctl[n].reg1] & ~wm->ctl[n].mask1; - val |= regval1 << __ffs(wm->ctl[n].mask1); - /* both stereo controls in one register */ - if (wm->ctl[n].flags & WM8766_FLAG_STEREO && - wm->ctl[n].reg1 == wm->ctl[n].reg2) { - val &= ~wm->ctl[n].mask2; - val |= regval2 << __ffs(wm->ctl[n].mask2); - } - snd_wm8766_write(wm, wm->ctl[n].reg1, val); - /* stereo controls in different registers */ - if (wm->ctl[n].flags & WM8766_FLAG_STEREO && - wm->ctl[n].reg1 != wm->ctl[n].reg2) { - val = wm->regs[wm->ctl[n].reg2] & ~wm->ctl[n].mask2; - val |= regval2 << __ffs(wm->ctl[n].mask2); - if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE) - val |= WM8766_VOL_UPDATE; - snd_wm8766_write(wm, wm->ctl[n].reg2, val); - } - } - - return 0; -} - -static int snd_wm8766_add_control(struct snd_wm8766 *wm, int num) -{ - struct snd_kcontrol_new cont; - struct snd_kcontrol *ctl; - - memset(&cont, 0, sizeof(cont)); - cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - cont.private_value = num; - cont.name = wm->ctl[num].name; - cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - if (wm->ctl[num].flags & WM8766_FLAG_LIM || - wm->ctl[num].flags & WM8766_FLAG_ALC) - cont.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - cont.tlv.p = NULL; - cont.get = snd_wm8766_ctl_get; - cont.put = snd_wm8766_ctl_put; - - switch (wm->ctl[num].type) { - case SNDRV_CTL_ELEM_TYPE_INTEGER: - cont.info = snd_wm8766_volume_info; - cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - cont.tlv.p = wm->ctl[num].tlv; - break; - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - wm->ctl[num].max = 1; - if (wm->ctl[num].flags & WM8766_FLAG_STEREO) - cont.info = snd_ctl_boolean_stereo_info; - else - cont.info = snd_ctl_boolean_mono_info; - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - cont.info = snd_wm8766_enum_info; - break; - default: - return -EINVAL; - } - ctl = snd_ctl_new1(&cont, wm); - if (!ctl) - return -ENOMEM; - wm->ctl[num].kctl = ctl; - - return snd_ctl_add(wm->card, ctl); -} - -int snd_wm8766_build_controls(struct snd_wm8766 *wm) -{ - int err, i; - - for (i = 0; i < WM8766_CTL_COUNT; i++) - if (wm->ctl[i].name) { - err = snd_wm8766_add_control(wm, i); - if (err < 0) - return err; - } - - return 0; -} diff --git a/trunk/sound/pci/ice1712/wm8766.h b/trunk/sound/pci/ice1712/wm8766.h deleted file mode 100644 index c119f84bd2c2..000000000000 --- a/trunk/sound/pci/ice1712/wm8766.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef __SOUND_WM8766_H -#define __SOUND_WM8766_H - -/* - * ALSA driver for ICEnsemble VT17xx - * - * Lowlevel functions for WM8766 codec - * - * Copyright (c) 2012 Ondrej Zary - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define WM8766_REG_DACL1 0x00 -#define WM8766_REG_DACR1 0x01 -#define WM8766_VOL_MASK 0x1ff /* incl. update bit */ -#define WM8766_VOL_UPDATE (1 << 8) /* update volume */ -#define WM8766_REG_DACCTRL1 0x02 -#define WM8766_DAC_MUTEALL (1 << 0) -#define WM8766_DAC_DEEMPALL (1 << 1) -#define WM8766_DAC_PDWN (1 << 2) -#define WM8766_DAC_ATC (1 << 3) -#define WM8766_DAC_IZD (1 << 4) -#define WM8766_DAC_PL_MASK 0x1e0 -#define WM8766_DAC_PL_LL (1 << 5) /* L chan: L signal */ -#define WM8766_DAC_PL_LR (2 << 5) /* L chan: R signal */ -#define WM8766_DAC_PL_LB (3 << 5) /* L chan: both */ -#define WM8766_DAC_PL_RL (1 << 7) /* R chan: L signal */ -#define WM8766_DAC_PL_RR (2 << 7) /* R chan: R signal */ -#define WM8766_DAC_PL_RB (3 << 7) /* R chan: both */ -#define WM8766_REG_IFCTRL 0x03 -#define WM8766_IF_FMT_RIGHTJ (0 << 0) -#define WM8766_IF_FMT_LEFTJ (1 << 0) -#define WM8766_IF_FMT_I2S (2 << 0) -#define WM8766_IF_FMT_DSP (3 << 0) -#define WM8766_IF_DSP_LATE (1 << 2) /* in DSP mode */ -#define WM8766_IF_LRC_INVERTED (1 << 2) /* in other modes */ -#define WM8766_IF_BCLK_INVERTED (1 << 3) -#define WM8766_IF_IWL_16BIT (0 << 4) -#define WM8766_IF_IWL_20BIT (1 << 4) -#define WM8766_IF_IWL_24BIT (2 << 4) -#define WM8766_IF_IWL_32BIT (3 << 4) -#define WM8766_IF_MASK 0x3f -#define WM8766_PHASE_INVERT1 (1 << 6) -#define WM8766_PHASE_INVERT2 (1 << 7) -#define WM8766_PHASE_INVERT3 (1 << 8) -#define WM8766_REG_DACL2 0x04 -#define WM8766_REG_DACR2 0x05 -#define WM8766_REG_DACL3 0x06 -#define WM8766_REG_DACR3 0x07 -#define WM8766_REG_MASTDA 0x08 -#define WM8766_REG_DACCTRL2 0x09 -#define WM8766_DAC2_ZCD (1 << 0) -#define WM8766_DAC2_ZFLAG_ALL (0 << 1) -#define WM8766_DAC2_ZFLAG_1 (1 << 1) -#define WM8766_DAC2_ZFLAG_2 (2 << 1) -#define WM8766_DAC2_ZFLAG_3 (3 << 1) -#define WM8766_DAC2_MUTE1 (1 << 3) -#define WM8766_DAC2_MUTE2 (1 << 4) -#define WM8766_DAC2_MUTE3 (1 << 5) -#define WM8766_DAC2_DEEMP1 (1 << 6) -#define WM8766_DAC2_DEEMP2 (1 << 7) -#define WM8766_DAC2_DEEMP3 (1 << 8) -#define WM8766_REG_DACCTRL3 0x0a -#define WM8766_DAC3_DACPD1 (1 << 1) -#define WM8766_DAC3_DACPD2 (1 << 2) -#define WM8766_DAC3_DACPD3 (1 << 3) -#define WM8766_DAC3_PWRDNALL (1 << 4) -#define WM8766_DAC3_POWER_MASK 0x1e -#define WM8766_DAC3_MASTER (1 << 5) -#define WM8766_DAC3_DAC128FS (0 << 6) -#define WM8766_DAC3_DAC192FS (1 << 6) -#define WM8766_DAC3_DAC256FS (2 << 6) -#define WM8766_DAC3_DAC384FS (3 << 6) -#define WM8766_DAC3_DAC512FS (4 << 6) -#define WM8766_DAC3_DAC768FS (5 << 6) -#define WM8766_DAC3_MSTR_MASK 0x1e0 -#define WM8766_REG_MUTE1 0x0c -#define WM8766_MUTE1_MPD (1 << 6) -#define WM8766_REG_MUTE2 0x0f -#define WM8766_MUTE2_MPD (1 << 5) -#define WM8766_REG_RESET 0x1f - -#define WM8766_REG_COUNT 0x10 /* don't cache the RESET register */ - -struct snd_wm8766; - -struct snd_wm8766_ops { - void (*write)(struct snd_wm8766 *wm, u16 addr, u16 data); -}; - -enum snd_wm8766_ctl_id { - WM8766_CTL_CH1_VOL, - WM8766_CTL_CH2_VOL, - WM8766_CTL_CH3_VOL, - WM8766_CTL_CH1_SW, - WM8766_CTL_CH2_SW, - WM8766_CTL_CH3_SW, - WM8766_CTL_PHASE1_SW, - WM8766_CTL_PHASE2_SW, - WM8766_CTL_PHASE3_SW, - WM8766_CTL_DEEMPH1_SW, - WM8766_CTL_DEEMPH2_SW, - WM8766_CTL_DEEMPH3_SW, - WM8766_CTL_IZD_SW, - WM8766_CTL_ZC_SW, - - WM8766_CTL_COUNT, -}; - -#define WM8766_ENUM_MAX 16 - -#define WM8766_FLAG_STEREO (1 << 0) -#define WM8766_FLAG_VOL_UPDATE (1 << 1) -#define WM8766_FLAG_INVERT (1 << 2) -#define WM8766_FLAG_LIM (1 << 3) -#define WM8766_FLAG_ALC (1 << 4) - -struct snd_wm8766_ctl { - struct snd_kcontrol *kctl; - const char *name; - snd_ctl_elem_type_t type; - const char *const enum_names[WM8766_ENUM_MAX]; - const unsigned int *tlv; - u16 reg1, reg2, mask1, mask2, min, max, flags; - void (*set)(struct snd_wm8766 *wm, u16 ch1, u16 ch2); - void (*get)(struct snd_wm8766 *wm, u16 *ch1, u16 *ch2); -}; - -enum snd_wm8766_agc_mode { WM8766_AGC_OFF, WM8766_AGC_LIM, WM8766_AGC_ALC }; - -struct snd_wm8766 { - struct snd_card *card; - struct snd_wm8766_ctl ctl[WM8766_CTL_COUNT]; - enum snd_wm8766_agc_mode agc_mode; - struct snd_wm8766_ops ops; - u16 regs[WM8766_REG_COUNT]; /* 9-bit registers */ -}; - - - -void snd_wm8766_init(struct snd_wm8766 *wm); -void snd_wm8766_resume(struct snd_wm8766 *wm); -void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac); -void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode); -void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power); -void snd_wm8766_volume_restore(struct snd_wm8766 *wm); -int snd_wm8766_build_controls(struct snd_wm8766 *wm); - -#endif /* __SOUND_WM8766_H */ diff --git a/trunk/sound/pci/ice1712/wm8776.c b/trunk/sound/pci/ice1712/wm8776.c deleted file mode 100644 index a3c05fe5daf9..000000000000 --- a/trunk/sound/pci/ice1712/wm8776.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT17xx - * - * Lowlevel functions for WM8776 codec - * - * Copyright (c) 2012 Ondrej Zary - * - * 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 -#include -#include -#include -#include "wm8776.h" - -/* low-level access */ - -static void snd_wm8776_write(struct snd_wm8776 *wm, u16 addr, u16 data) -{ - u8 bus_addr = addr << 1 | data >> 8; /* addr + 9th data bit */ - u8 bus_data = data & 0xff; /* remaining 8 data bits */ - - if (addr < WM8776_REG_RESET) - wm->regs[addr] = data; - wm->ops.write(wm, bus_addr, bus_data); -} - -/* register-level functions */ - -static void snd_wm8776_activate_ctl(struct snd_wm8776 *wm, - const char *ctl_name, - bool active) -{ - struct snd_card *card = wm->card; - struct snd_kcontrol *kctl; - struct snd_kcontrol_volatile *vd; - struct snd_ctl_elem_id elem_id; - unsigned int index_offset; - - memset(&elem_id, 0, sizeof(elem_id)); - strncpy(elem_id.name, ctl_name, sizeof(elem_id.name)); - elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - kctl = snd_ctl_find_id(card, &elem_id); - if (!kctl) - return; - index_offset = snd_ctl_get_ioff(kctl, &kctl->id); - vd = &kctl->vd[index_offset]; - if (active) - vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - else - vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); -} - -static void snd_wm8776_update_agc_ctl(struct snd_wm8776 *wm) -{ - int i, flags_on = 0, flags_off = 0; - - switch (wm->agc_mode) { - case WM8776_AGC_OFF: - flags_off = WM8776_FLAG_LIM | WM8776_FLAG_ALC; - break; - case WM8776_AGC_LIM: - flags_off = WM8776_FLAG_ALC; - flags_on = WM8776_FLAG_LIM; - break; - case WM8776_AGC_ALC_R: - case WM8776_AGC_ALC_L: - case WM8776_AGC_ALC_STEREO: - flags_off = WM8776_FLAG_LIM; - flags_on = WM8776_FLAG_ALC; - break; - } - - for (i = 0; i < WM8776_CTL_COUNT; i++) - if (wm->ctl[i].flags & flags_off) - snd_wm8776_activate_ctl(wm, wm->ctl[i].name, false); - else if (wm->ctl[i].flags & flags_on) - snd_wm8776_activate_ctl(wm, wm->ctl[i].name, true); -} - -static void snd_wm8776_set_agc(struct snd_wm8776 *wm, u16 agc, u16 nothing) -{ - u16 alc1 = wm->regs[WM8776_REG_ALCCTRL1] & ~WM8776_ALC1_LCT_MASK; - u16 alc2 = wm->regs[WM8776_REG_ALCCTRL2] & ~WM8776_ALC2_LCEN; - - switch (agc) { - case 0: /* Off */ - wm->agc_mode = WM8776_AGC_OFF; - break; - case 1: /* Limiter */ - alc2 |= WM8776_ALC2_LCEN; - wm->agc_mode = WM8776_AGC_LIM; - break; - case 2: /* ALC Right */ - alc1 |= WM8776_ALC1_LCSEL_ALCR; - alc2 |= WM8776_ALC2_LCEN; - wm->agc_mode = WM8776_AGC_ALC_R; - break; - case 3: /* ALC Left */ - alc1 |= WM8776_ALC1_LCSEL_ALCL; - alc2 |= WM8776_ALC2_LCEN; - wm->agc_mode = WM8776_AGC_ALC_L; - break; - case 4: /* ALC Stereo */ - alc1 |= WM8776_ALC1_LCSEL_ALCSTEREO; - alc2 |= WM8776_ALC2_LCEN; - wm->agc_mode = WM8776_AGC_ALC_STEREO; - break; - } - snd_wm8776_write(wm, WM8776_REG_ALCCTRL1, alc1); - snd_wm8776_write(wm, WM8776_REG_ALCCTRL2, alc2); - snd_wm8776_update_agc_ctl(wm); -} - -static void snd_wm8776_get_agc(struct snd_wm8776 *wm, u16 *mode, u16 *nothing) -{ - *mode = wm->agc_mode; -} - -/* mixer controls */ - -static const DECLARE_TLV_DB_SCALE(wm8776_hp_tlv, -7400, 100, 1); -static const DECLARE_TLV_DB_SCALE(wm8776_dac_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(wm8776_adc_tlv, -10350, 50, 1); -static const DECLARE_TLV_DB_SCALE(wm8776_lct_tlv, -1600, 100, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_tlv, 0, 400, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_ngth_tlv, -7800, 600, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_tlv, -2100, 400, 0); - -static struct snd_wm8776_ctl snd_wm8776_default_ctl[WM8776_CTL_COUNT] = { - [WM8776_CTL_DAC_VOL] = { - .name = "Master Playback Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8776_dac_tlv, - .reg1 = WM8776_REG_DACLVOL, - .reg2 = WM8776_REG_DACRVOL, - .mask1 = WM8776_DACVOL_MASK, - .mask2 = WM8776_DACVOL_MASK, - .max = 0xff, - .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE, - }, - [WM8776_CTL_DAC_SW] = { - .name = "Master Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_DACCTRL1, - .reg2 = WM8776_REG_DACCTRL1, - .mask1 = WM8776_DAC_PL_LL, - .mask2 = WM8776_DAC_PL_RR, - .flags = WM8776_FLAG_STEREO, - }, - [WM8776_CTL_DAC_ZC_SW] = { - .name = "Master Zero Cross Detect Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_DACCTRL1, - .mask1 = WM8776_DAC_DZCEN, - }, - [WM8776_CTL_HP_VOL] = { - .name = "Headphone Playback Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8776_hp_tlv, - .reg1 = WM8776_REG_HPLVOL, - .reg2 = WM8776_REG_HPRVOL, - .mask1 = WM8776_HPVOL_MASK, - .mask2 = WM8776_HPVOL_MASK, - .min = 0x2f, - .max = 0x7f, - .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE, - }, - [WM8776_CTL_HP_SW] = { - .name = "Headphone Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_PWRDOWN, - .mask1 = WM8776_PWR_HPPD, - .flags = WM8776_FLAG_INVERT, - }, - [WM8776_CTL_HP_ZC_SW] = { - .name = "Headphone Zero Cross Detect Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_HPLVOL, - .reg2 = WM8776_REG_HPRVOL, - .mask1 = WM8776_VOL_HPZCEN, - .mask2 = WM8776_VOL_HPZCEN, - .flags = WM8776_FLAG_STEREO, - }, - [WM8776_CTL_AUX_SW] = { - .name = "AUX Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_OUTMUX, - .mask1 = WM8776_OUTMUX_AUX, - }, - [WM8776_CTL_BYPASS_SW] = { - .name = "Bypass Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_OUTMUX, - .mask1 = WM8776_OUTMUX_BYPASS, - }, - [WM8776_CTL_DAC_IZD_SW] = { - .name = "Infinite Zero Detect Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_DACCTRL1, - .mask1 = WM8776_DAC_IZD, - }, - [WM8776_CTL_PHASE_SW] = { - .name = "Phase Invert Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_PHASESWAP, - .reg2 = WM8776_REG_PHASESWAP, - .mask1 = WM8776_PHASE_INVERTL, - .mask2 = WM8776_PHASE_INVERTR, - .flags = WM8776_FLAG_STEREO, - }, - [WM8776_CTL_DEEMPH_SW] = { - .name = "Deemphasis Playback Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_DACCTRL2, - .mask1 = WM8776_DAC2_DEEMPH, - }, - [WM8776_CTL_ADC_VOL] = { - .name = "Input Capture Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8776_adc_tlv, - .reg1 = WM8776_REG_ADCLVOL, - .reg2 = WM8776_REG_ADCRVOL, - .mask1 = WM8776_ADC_GAIN_MASK, - .mask2 = WM8776_ADC_GAIN_MASK, - .max = 0xff, - .flags = WM8776_FLAG_STEREO | WM8776_FLAG_VOL_UPDATE, - }, - [WM8776_CTL_ADC_SW] = { - .name = "Input Capture Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_ADCMUX, - .reg2 = WM8776_REG_ADCMUX, - .mask1 = WM8776_ADC_MUTEL, - .mask2 = WM8776_ADC_MUTER, - .flags = WM8776_FLAG_STEREO | WM8776_FLAG_INVERT, - }, - [WM8776_CTL_INPUT1_SW] = { - .name = "AIN1 Capture Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_ADCMUX, - .mask1 = WM8776_ADC_MUX_AIN1, - }, - [WM8776_CTL_INPUT2_SW] = { - .name = "AIN2 Capture Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_ADCMUX, - .mask1 = WM8776_ADC_MUX_AIN2, - }, - [WM8776_CTL_INPUT3_SW] = { - .name = "AIN3 Capture Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_ADCMUX, - .mask1 = WM8776_ADC_MUX_AIN3, - }, - [WM8776_CTL_INPUT4_SW] = { - .name = "AIN4 Capture Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_ADCMUX, - .mask1 = WM8776_ADC_MUX_AIN4, - }, - [WM8776_CTL_INPUT5_SW] = { - .name = "AIN5 Capture Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_ADCMUX, - .mask1 = WM8776_ADC_MUX_AIN5, - }, - [WM8776_CTL_AGC_SEL] = { - .name = "AGC Select Capture Enum", - .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED, - .enum_names = { "Off", "Limiter", "ALC Right", "ALC Left", - "ALC Stereo" }, - .max = 5, /* .enum_names item count */ - .set = snd_wm8776_set_agc, - .get = snd_wm8776_get_agc, - }, - [WM8776_CTL_LIM_THR] = { - .name = "Limiter Threshold Capture Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8776_lct_tlv, - .reg1 = WM8776_REG_ALCCTRL1, - .mask1 = WM8776_ALC1_LCT_MASK, - .max = 15, - .flags = WM8776_FLAG_LIM, - }, - [WM8776_CTL_LIM_ATK] = { - .name = "Limiter Attack Time Capture Enum", - .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED, - .enum_names = { "0.25 ms", "0.5 ms", "1 ms", "2 ms", "4 ms", - "8 ms", "16 ms", "32 ms", "64 ms", "128 ms", "256 ms" }, - .max = 11, /* .enum_names item count */ - .reg1 = WM8776_REG_ALCCTRL3, - .mask1 = WM8776_ALC3_ATK_MASK, - .flags = WM8776_FLAG_LIM, - }, - [WM8776_CTL_LIM_DCY] = { - .name = "Limiter Decay Time Capture Enum", - .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED, - .enum_names = { "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms", - "19.2 ms", "38.4 ms", "76.8 ms", "154 ms", "307 ms", - "614 ms", "1.23 s" }, - .max = 11, /* .enum_names item count */ - .reg1 = WM8776_REG_ALCCTRL3, - .mask1 = WM8776_ALC3_DCY_MASK, - .flags = WM8776_FLAG_LIM, - }, - [WM8776_CTL_LIM_TRANWIN] = { - .name = "Limiter Transient Window Capture Enum", - .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED, - .enum_names = { "0 us", "62.5 us", "125 us", "250 us", "500 us", - "1 ms", "2 ms", "4 ms" }, - .max = 8, /* .enum_names item count */ - .reg1 = WM8776_REG_LIMITER, - .mask1 = WM8776_LIM_TRANWIN_MASK, - .flags = WM8776_FLAG_LIM, - }, - [WM8776_CTL_LIM_MAXATTN] = { - .name = "Limiter Maximum Attenuation Capture Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8776_maxatten_lim_tlv, - .reg1 = WM8776_REG_LIMITER, - .mask1 = WM8776_LIM_MAXATTEN_MASK, - .min = 3, - .max = 12, - .flags = WM8776_FLAG_LIM | WM8776_FLAG_INVERT, - }, - [WM8776_CTL_ALC_TGT] = { - .name = "ALC Target Level Capture Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8776_lct_tlv, - .reg1 = WM8776_REG_ALCCTRL1, - .mask1 = WM8776_ALC1_LCT_MASK, - .max = 15, - .flags = WM8776_FLAG_ALC, - }, - [WM8776_CTL_ALC_ATK] = { - .name = "ALC Attack Time Capture Enum", - .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED, - .enum_names = { "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms", - "134 ms", "269 ms", "538 ms", "1.08 s", "2.15 s", - "4.3 s", "8.6 s" }, - .max = 11, /* .enum_names item count */ - .reg1 = WM8776_REG_ALCCTRL3, - .mask1 = WM8776_ALC3_ATK_MASK, - .flags = WM8776_FLAG_ALC, - }, - [WM8776_CTL_ALC_DCY] = { - .name = "ALC Decay Time Capture Enum", - .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED, - .enum_names = { "33.5 ms", "67.0 ms", "134 ms", "268 ms", - "536 ms", "1.07 s", "2.14 s", "4.29 s", "8.58 s", - "17.2 s", "34.3 s" }, - .max = 11, /* .enum_names item count */ - .reg1 = WM8776_REG_ALCCTRL3, - .mask1 = WM8776_ALC3_DCY_MASK, - .flags = WM8776_FLAG_ALC, - }, - [WM8776_CTL_ALC_MAXGAIN] = { - .name = "ALC Maximum Gain Capture Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8776_maxgain_tlv, - .reg1 = WM8776_REG_ALCCTRL1, - .mask1 = WM8776_ALC1_MAXGAIN_MASK, - .min = 1, - .max = 7, - .flags = WM8776_FLAG_ALC, - }, - [WM8776_CTL_ALC_MAXATTN] = { - .name = "ALC Maximum Attenuation Capture Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8776_maxatten_alc_tlv, - .reg1 = WM8776_REG_LIMITER, - .mask1 = WM8776_LIM_MAXATTEN_MASK, - .min = 10, - .max = 15, - .flags = WM8776_FLAG_ALC | WM8776_FLAG_INVERT, - }, - [WM8776_CTL_ALC_HLD] = { - .name = "ALC Hold Time Capture Enum", - .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED, - .enum_names = { "0 ms", "2.67 ms", "5.33 ms", "10.6 ms", - "21.3 ms", "42.7 ms", "85.3 ms", "171 ms", "341 ms", - "683 ms", "1.37 s", "2.73 s", "5.46 s", "10.9 s", - "21.8 s", "43.7 s" }, - .max = 16, /* .enum_names item count */ - .reg1 = WM8776_REG_ALCCTRL2, - .mask1 = WM8776_ALC2_HOLD_MASK, - .flags = WM8776_FLAG_ALC, - }, - [WM8776_CTL_NGT_SW] = { - .name = "Noise Gate Capture Switch", - .type = SNDRV_CTL_ELEM_TYPE_BOOLEAN, - .reg1 = WM8776_REG_NOISEGATE, - .mask1 = WM8776_NGAT_ENABLE, - .flags = WM8776_FLAG_ALC, - }, - [WM8776_CTL_NGT_THR] = { - .name = "Noise Gate Threshold Capture Volume", - .type = SNDRV_CTL_ELEM_TYPE_INTEGER, - .tlv = wm8776_ngth_tlv, - .reg1 = WM8776_REG_NOISEGATE, - .mask1 = WM8776_NGAT_THR_MASK, - .max = 7, - .flags = WM8776_FLAG_ALC, - }, -}; - -/* exported functions */ - -void snd_wm8776_init(struct snd_wm8776 *wm) -{ - int i; - static const u16 default_values[] = { - 0x000, 0x100, 0x000, - 0x000, 0x100, 0x000, - 0x000, 0x090, 0x000, 0x000, - 0x022, 0x022, 0x022, - 0x008, 0x0cf, 0x0cf, 0x07b, 0x000, - 0x032, 0x000, 0x0a6, 0x001, 0x001 - }; - - memcpy(wm->ctl, snd_wm8776_default_ctl, sizeof(wm->ctl)); - - snd_wm8776_write(wm, WM8776_REG_RESET, 0x00); /* reset */ - udelay(10); - /* load defaults */ - for (i = 0; i < ARRAY_SIZE(default_values); i++) - snd_wm8776_write(wm, i, default_values[i]); -} - -void snd_wm8776_resume(struct snd_wm8776 *wm) -{ - int i; - - for (i = 0; i < WM8776_REG_COUNT; i++) - snd_wm8776_write(wm, i, wm->regs[i]); -} - -void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac) -{ - snd_wm8776_write(wm, WM8776_REG_DACIFCTRL, dac); -} - -void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc) -{ - snd_wm8776_write(wm, WM8776_REG_ADCIFCTRL, adc); -} - -void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode) -{ - snd_wm8776_write(wm, WM8776_REG_MSTRCTRL, mode); -} - -void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power) -{ - snd_wm8776_write(wm, WM8776_REG_PWRDOWN, power); -} - -void snd_wm8776_volume_restore(struct snd_wm8776 *wm) -{ - u16 val = wm->regs[WM8776_REG_DACRVOL]; - /* restore volume after MCLK stopped */ - snd_wm8776_write(wm, WM8776_REG_DACRVOL, val | WM8776_VOL_UPDATE); -} - -/* mixer callbacks */ - -static int snd_wm8776_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = (wm->ctl[n].flags & WM8776_FLAG_STEREO) ? 2 : 1; - uinfo->value.integer.min = wm->ctl[n].min; - uinfo->value.integer.max = wm->ctl[n].max; - - return 0; -} - -static int snd_wm8776_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - - return snd_ctl_enum_info(uinfo, 1, wm->ctl[n].max, - wm->ctl[n].enum_names); -} - -static int snd_wm8776_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - u16 val1, val2; - - if (wm->ctl[n].get) - wm->ctl[n].get(wm, &val1, &val2); - else { - val1 = wm->regs[wm->ctl[n].reg1] & wm->ctl[n].mask1; - val1 >>= __ffs(wm->ctl[n].mask1); - if (wm->ctl[n].flags & WM8776_FLAG_STEREO) { - val2 = wm->regs[wm->ctl[n].reg2] & wm->ctl[n].mask2; - val2 >>= __ffs(wm->ctl[n].mask2); - if (wm->ctl[n].flags & WM8776_FLAG_VOL_UPDATE) - val2 &= ~WM8776_VOL_UPDATE; - } - } - if (wm->ctl[n].flags & WM8776_FLAG_INVERT) { - val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min); - val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min); - } - ucontrol->value.integer.value[0] = val1; - if (wm->ctl[n].flags & WM8776_FLAG_STEREO) - ucontrol->value.integer.value[1] = val2; - - return 0; -} - -static int snd_wm8776_ctl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wm8776 *wm = snd_kcontrol_chip(kcontrol); - int n = kcontrol->private_value; - u16 val, regval1, regval2; - - /* this also works for enum because value is an union */ - regval1 = ucontrol->value.integer.value[0]; - regval2 = ucontrol->value.integer.value[1]; - if (wm->ctl[n].flags & WM8776_FLAG_INVERT) { - regval1 = wm->ctl[n].max - (regval1 - wm->ctl[n].min); - regval2 = wm->ctl[n].max - (regval2 - wm->ctl[n].min); - } - if (wm->ctl[n].set) - wm->ctl[n].set(wm, regval1, regval2); - else { - val = wm->regs[wm->ctl[n].reg1] & ~wm->ctl[n].mask1; - val |= regval1 << __ffs(wm->ctl[n].mask1); - /* both stereo controls in one register */ - if (wm->ctl[n].flags & WM8776_FLAG_STEREO && - wm->ctl[n].reg1 == wm->ctl[n].reg2) { - val &= ~wm->ctl[n].mask2; - val |= regval2 << __ffs(wm->ctl[n].mask2); - } - snd_wm8776_write(wm, wm->ctl[n].reg1, val); - /* stereo controls in different registers */ - if (wm->ctl[n].flags & WM8776_FLAG_STEREO && - wm->ctl[n].reg1 != wm->ctl[n].reg2) { - val = wm->regs[wm->ctl[n].reg2] & ~wm->ctl[n].mask2; - val |= regval2 << __ffs(wm->ctl[n].mask2); - if (wm->ctl[n].flags & WM8776_FLAG_VOL_UPDATE) - val |= WM8776_VOL_UPDATE; - snd_wm8776_write(wm, wm->ctl[n].reg2, val); - } - } - - return 0; -} - -static int snd_wm8776_add_control(struct snd_wm8776 *wm, int num) -{ - struct snd_kcontrol_new cont; - struct snd_kcontrol *ctl; - - memset(&cont, 0, sizeof(cont)); - cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - cont.private_value = num; - cont.name = wm->ctl[num].name; - cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - if (wm->ctl[num].flags & WM8776_FLAG_LIM || - wm->ctl[num].flags & WM8776_FLAG_ALC) - cont.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - cont.tlv.p = NULL; - cont.get = snd_wm8776_ctl_get; - cont.put = snd_wm8776_ctl_put; - - switch (wm->ctl[num].type) { - case SNDRV_CTL_ELEM_TYPE_INTEGER: - cont.info = snd_wm8776_volume_info; - cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - cont.tlv.p = wm->ctl[num].tlv; - break; - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - wm->ctl[num].max = 1; - if (wm->ctl[num].flags & WM8776_FLAG_STEREO) - cont.info = snd_ctl_boolean_stereo_info; - else - cont.info = snd_ctl_boolean_mono_info; - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - cont.info = snd_wm8776_enum_info; - break; - default: - return -EINVAL; - } - ctl = snd_ctl_new1(&cont, wm); - if (!ctl) - return -ENOMEM; - - return snd_ctl_add(wm->card, ctl); -} - -int snd_wm8776_build_controls(struct snd_wm8776 *wm) -{ - int err, i; - - for (i = 0; i < WM8776_CTL_COUNT; i++) - if (wm->ctl[i].name) { - err = snd_wm8776_add_control(wm, i); - if (err < 0) - return err; - } - - return 0; -} diff --git a/trunk/sound/pci/ice1712/wm8776.h b/trunk/sound/pci/ice1712/wm8776.h deleted file mode 100644 index 93a2d6971154..000000000000 --- a/trunk/sound/pci/ice1712/wm8776.h +++ /dev/null @@ -1,226 +0,0 @@ -#ifndef __SOUND_WM8776_H -#define __SOUND_WM8776_H - -/* - * ALSA driver for ICEnsemble VT17xx - * - * Lowlevel functions for WM8776 codec - * - * Copyright (c) 2012 Ondrej Zary - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define WM8776_REG_HPLVOL 0x00 -#define WM8776_REG_HPRVOL 0x01 -#define WM8776_REG_HPMASTER 0x02 -#define WM8776_HPVOL_MASK 0x17f /* incl. update bit */ -#define WM8776_VOL_HPZCEN (1 << 7) /* zero cross detect */ -#define WM8776_VOL_UPDATE (1 << 8) /* update volume */ -#define WM8776_REG_DACLVOL 0x03 -#define WM8776_REG_DACRVOL 0x04 -#define WM8776_REG_DACMASTER 0x05 -#define WM8776_DACVOL_MASK 0x1ff /* incl. update bit */ -#define WM8776_REG_PHASESWAP 0x06 -#define WM8776_PHASE_INVERTL (1 << 0) -#define WM8776_PHASE_INVERTR (1 << 1) -#define WM8776_REG_DACCTRL1 0x07 -#define WM8776_DAC_DZCEN (1 << 0) -#define WM8776_DAC_ATC (1 << 1) -#define WM8776_DAC_IZD (1 << 2) -#define WM8776_DAC_TOD (1 << 3) -#define WM8776_DAC_PL_MASK 0xf0 -#define WM8776_DAC_PL_LL (1 << 4) /* L chan: L signal */ -#define WM8776_DAC_PL_LR (2 << 4) /* L chan: R signal */ -#define WM8776_DAC_PL_LB (3 << 4) /* L chan: both */ -#define WM8776_DAC_PL_RL (1 << 6) /* R chan: L signal */ -#define WM8776_DAC_PL_RR (2 << 6) /* R chan: R signal */ -#define WM8776_DAC_PL_RB (3 << 6) /* R chan: both */ -#define WM8776_REG_DACMUTE 0x08 -#define WM8776_DACMUTE (1 << 0) -#define WM8776_REG_DACCTRL2 0x09 -#define WM8776_DAC2_DEEMPH (1 << 0) -#define WM8776_DAC2_ZFLAG_DISABLE (0 << 1) -#define WM8776_DAC2_ZFLAG_OWN (1 << 1) -#define WM8776_DAC2_ZFLAG_BOTH (2 << 1) -#define WM8776_DAC2_ZFLAG_EITHER (3 << 1) -#define WM8776_REG_DACIFCTRL 0x0a -#define WM8776_FMT_RIGHTJ (0 << 0) -#define WM8776_FMT_LEFTJ (1 << 0) -#define WM8776_FMT_I2S (2 << 0) -#define WM8776_FMT_DSP (3 << 0) -#define WM8776_FMT_DSP_LATE (1 << 2) /* in DSP mode */ -#define WM8776_FMT_LRC_INVERTED (1 << 2) /* in other modes */ -#define WM8776_FMT_BCLK_INVERTED (1 << 3) -#define WM8776_FMT_16BIT (0 << 4) -#define WM8776_FMT_20BIT (1 << 4) -#define WM8776_FMT_24BIT (2 << 4) -#define WM8776_FMT_32BIT (3 << 4) -#define WM8776_REG_ADCIFCTRL 0x0b -#define WM8776_FMT_ADCMCLK_INVERTED (1 << 6) -#define WM8776_FMT_ADCHPD (1 << 8) -#define WM8776_REG_MSTRCTRL 0x0c -#define WM8776_IF_ADC256FS (2 << 0) -#define WM8776_IF_ADC384FS (3 << 0) -#define WM8776_IF_ADC512FS (4 << 0) -#define WM8776_IF_ADC768FS (5 << 0) -#define WM8776_IF_OVERSAMP64 (1 << 3) -#define WM8776_IF_DAC128FS (0 << 4) -#define WM8776_IF_DAC192FS (1 << 4) -#define WM8776_IF_DAC256FS (2 << 4) -#define WM8776_IF_DAC384FS (3 << 4) -#define WM8776_IF_DAC512FS (4 << 4) -#define WM8776_IF_DAC768FS (5 << 4) -#define WM8776_IF_DAC_MASTER (1 << 7) -#define WM8776_IF_ADC_MASTER (1 << 8) -#define WM8776_REG_PWRDOWN 0x0d -#define WM8776_PWR_PDWN (1 << 0) -#define WM8776_PWR_ADCPD (1 << 1) -#define WM8776_PWR_DACPD (1 << 2) -#define WM8776_PWR_HPPD (1 << 3) -#define WM8776_PWR_AINPD (1 << 6) -#define WM8776_REG_ADCLVOL 0x0e -#define WM8776_REG_ADCRVOL 0x0f -#define WM8776_ADC_GAIN_MASK 0xff -#define WM8776_ADC_ZCEN (1 << 8) -#define WM8776_REG_ALCCTRL1 0x10 -#define WM8776_ALC1_LCT_MASK 0x0f /* 0=-16dB, 1=-15dB..15=-1dB */ -#define WM8776_ALC1_MAXGAIN_MASK 0x70 /* 0,1=0dB, 2=+4dB...7=+24dB */ -#define WM8776_ALC1_LCSEL_MASK 0x180 -#define WM8776_ALC1_LCSEL_LIMITER (0 << 7) -#define WM8776_ALC1_LCSEL_ALCR (1 << 7) -#define WM8776_ALC1_LCSEL_ALCL (2 << 7) -#define WM8776_ALC1_LCSEL_ALCSTEREO (3 << 7) -#define WM8776_REG_ALCCTRL2 0x11 -#define WM8776_ALC2_HOLD_MASK 0x0f /*0=0ms, 1=2.67ms, 2=5.33ms.. */ -#define WM8776_ALC2_ZCEN (1 << 7) -#define WM8776_ALC2_LCEN (1 << 8) -#define WM8776_REG_ALCCTRL3 0x12 -#define WM8776_ALC3_ATK_MASK 0x0f -#define WM8776_ALC3_DCY_MASK 0xf0 -#define WM8776_ALC3_FDECAY (1 << 8) -#define WM8776_REG_NOISEGATE 0x13 -#define WM8776_NGAT_ENABLE (1 << 0) -#define WM8776_NGAT_THR_MASK 0x1c /*0=-78dB, 1=-72dB...7=-36dB */ -#define WM8776_REG_LIMITER 0x14 -#define WM8776_LIM_MAXATTEN_MASK 0x0f -#define WM8776_LIM_TRANWIN_MASK 0x70 /*0=0us, 1=62.5us, 2=125us.. */ -#define WM8776_REG_ADCMUX 0x15 -#define WM8776_ADC_MUX_AIN1 (1 << 0) -#define WM8776_ADC_MUX_AIN2 (1 << 1) -#define WM8776_ADC_MUX_AIN3 (1 << 2) -#define WM8776_ADC_MUX_AIN4 (1 << 3) -#define WM8776_ADC_MUX_AIN5 (1 << 4) -#define WM8776_ADC_MUTER (1 << 6) -#define WM8776_ADC_MUTEL (1 << 7) -#define WM8776_ADC_LRBOTH (1 << 8) -#define WM8776_REG_OUTMUX 0x16 -#define WM8776_OUTMUX_DAC (1 << 0) -#define WM8776_OUTMUX_AUX (1 << 1) -#define WM8776_OUTMUX_BYPASS (1 << 2) -#define WM8776_REG_RESET 0x17 - -#define WM8776_REG_COUNT 0x17 /* don't cache the RESET register */ - -struct snd_wm8776; - -struct snd_wm8776_ops { - void (*write)(struct snd_wm8776 *wm, u8 addr, u8 data); -}; - -enum snd_wm8776_ctl_id { - WM8776_CTL_DAC_VOL, - WM8776_CTL_DAC_SW, - WM8776_CTL_DAC_ZC_SW, - WM8776_CTL_HP_VOL, - WM8776_CTL_HP_SW, - WM8776_CTL_HP_ZC_SW, - WM8776_CTL_AUX_SW, - WM8776_CTL_BYPASS_SW, - WM8776_CTL_DAC_IZD_SW, - WM8776_CTL_PHASE_SW, - WM8776_CTL_DEEMPH_SW, - WM8776_CTL_ADC_VOL, - WM8776_CTL_ADC_SW, - WM8776_CTL_INPUT1_SW, - WM8776_CTL_INPUT2_SW, - WM8776_CTL_INPUT3_SW, - WM8776_CTL_INPUT4_SW, - WM8776_CTL_INPUT5_SW, - WM8776_CTL_AGC_SEL, - WM8776_CTL_LIM_THR, - WM8776_CTL_LIM_ATK, - WM8776_CTL_LIM_DCY, - WM8776_CTL_LIM_TRANWIN, - WM8776_CTL_LIM_MAXATTN, - WM8776_CTL_ALC_TGT, - WM8776_CTL_ALC_ATK, - WM8776_CTL_ALC_DCY, - WM8776_CTL_ALC_MAXGAIN, - WM8776_CTL_ALC_MAXATTN, - WM8776_CTL_ALC_HLD, - WM8776_CTL_NGT_SW, - WM8776_CTL_NGT_THR, - - WM8776_CTL_COUNT, -}; - -#define WM8776_ENUM_MAX 16 - -#define WM8776_FLAG_STEREO (1 << 0) -#define WM8776_FLAG_VOL_UPDATE (1 << 1) -#define WM8776_FLAG_INVERT (1 << 2) -#define WM8776_FLAG_LIM (1 << 3) -#define WM8776_FLAG_ALC (1 << 4) - -struct snd_wm8776_ctl { - const char *name; - snd_ctl_elem_type_t type; - const char *const enum_names[WM8776_ENUM_MAX]; - const unsigned int *tlv; - u16 reg1, reg2, mask1, mask2, min, max, flags; - void (*set)(struct snd_wm8776 *wm, u16 ch1, u16 ch2); - void (*get)(struct snd_wm8776 *wm, u16 *ch1, u16 *ch2); -}; - -enum snd_wm8776_agc_mode { - WM8776_AGC_OFF, - WM8776_AGC_LIM, - WM8776_AGC_ALC_R, - WM8776_AGC_ALC_L, - WM8776_AGC_ALC_STEREO -}; - -struct snd_wm8776 { - struct snd_card *card; - struct snd_wm8776_ctl ctl[WM8776_CTL_COUNT]; - enum snd_wm8776_agc_mode agc_mode; - struct snd_wm8776_ops ops; - u16 regs[WM8776_REG_COUNT]; /* 9-bit registers */ -}; - - - -void snd_wm8776_init(struct snd_wm8776 *wm); -void snd_wm8776_resume(struct snd_wm8776 *wm); -void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac); -void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc); -void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode); -void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power); -void snd_wm8776_volume_restore(struct snd_wm8776 *wm); -int snd_wm8776_build_controls(struct snd_wm8776 *wm); - -#endif /* __SOUND_WM8776_H */ diff --git a/trunk/sound/pci/ice1712/wtm.c b/trunk/sound/pci/ice1712/wtm.c index 184163bbd732..e618f789026e 100644 --- a/trunk/sound/pci/ice1712/wtm.c +++ b/trunk/sound/pci/ice1712/wtm.c @@ -25,6 +25,7 @@ +#include #include #include #include diff --git a/trunk/sound/pci/mixart/mixart_hwdep.c b/trunk/sound/pci/mixart/mixart_hwdep.c index ece1f831c16a..e0f4d87555a0 100644 --- a/trunk/sound/pci/mixart/mixart_hwdep.c +++ b/trunk/sound/pci/mixart/mixart_hwdep.c @@ -546,6 +546,14 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw } +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) +#if !defined(CONFIG_USE_MIXARTLOADER) && !defined(CONFIG_SND_MIXART) /* built-in kernel */ +#define SND_MIXART_FW_LOADER /* use the standard firmware loader */ +#endif +#endif + +#ifdef SND_MIXART_FW_LOADER + int snd_mixart_setup_firmware(struct mixart_mgr *mgr) { static char *fw_files[3] = { @@ -575,3 +583,71 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr) MODULE_FIRMWARE("mixart/miXart8.xlx"); MODULE_FIRMWARE("mixart/miXart8.elf"); MODULE_FIRMWARE("mixart/miXart8AES.xlx"); + +#else /* old style firmware loading */ + +/* miXart hwdep interface id string */ +#define SND_MIXART_HWDEP_ID "miXart Loader" + +static int mixart_hwdep_dsp_status(struct snd_hwdep *hw, + struct snd_hwdep_dsp_status *info) +{ + struct mixart_mgr *mgr = hw->private_data; + + strcpy(info->id, "miXart"); + info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX; + + if (mgr->dsp_loaded & (1 << MIXART_MOTHERBOARD_ELF_INDEX)) + info->chip_ready = 1; + + info->version = MIXART_DRIVER_VERSION; + return 0; +} + +static int mixart_hwdep_dsp_load(struct snd_hwdep *hw, + struct snd_hwdep_dsp_image *dsp) +{ + struct mixart_mgr* mgr = hw->private_data; + struct firmware fw; + int err; + + fw.size = dsp->length; + fw.data = vmalloc(dsp->length); + if (! fw.data) { + snd_printk(KERN_ERR "miXart: cannot allocate image size %d\n", + (int)dsp->length); + return -ENOMEM; + } + if (copy_from_user((void *) fw.data, dsp->image, dsp->length)) { + vfree(fw.data); + return -EFAULT; + } + err = mixart_dsp_load(mgr, dsp->index, &fw); + vfree(fw.data); + if (err < 0) + return err; + mgr->dsp_loaded |= 1 << dsp->index; + return err; +} + +int snd_mixart_setup_firmware(struct mixart_mgr *mgr) +{ + int err; + struct snd_hwdep *hw; + + /* only create hwdep interface for first cardX (see "index" module parameter)*/ + if ((err = snd_hwdep_new(mgr->chip[0]->card, SND_MIXART_HWDEP_ID, 0, &hw)) < 0) + return err; + + hw->iface = SNDRV_HWDEP_IFACE_MIXART; + hw->private_data = mgr; + hw->ops.dsp_status = mixart_hwdep_dsp_status; + hw->ops.dsp_load = mixart_hwdep_dsp_load; + hw->exclusive = 1; + sprintf(hw->name, SND_MIXART_HWDEP_ID); + mgr->dsp_loaded = 0; + + return snd_card_register(mgr->chip[0]->card); +} + +#endif /* SND_MIXART_FW_LOADER */ diff --git a/trunk/sound/pci/oxygen/virtuoso.c b/trunk/sound/pci/oxygen/virtuoso.c index 8104eab90e51..3d71423b23bc 100644 --- a/trunk/sound/pci/oxygen/virtuoso.c +++ b/trunk/sound/pci/oxygen/virtuoso.c @@ -52,7 +52,6 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = { { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, - { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, { } }; diff --git a/trunk/sound/pci/oxygen/xonar_wm87x6.c b/trunk/sound/pci/oxygen/xonar_wm87x6.c index b555b620babb..63cff90706bf 100644 --- a/trunk/sound/pci/oxygen/xonar_wm87x6.c +++ b/trunk/sound/pci/oxygen/xonar_wm87x6.c @@ -1255,6 +1255,7 @@ static void dump_wm87x6_registers(struct oxygen *chip, } static const struct oxygen_model model_xonar_ds = { + .shortname = "Xonar DS", .longname = "Asus Virtuoso 66", .chip = "AV200", .init = xonar_ds_init, @@ -1326,11 +1327,6 @@ int __devinit get_xonar_wm87x6_model(struct oxygen *chip, switch (id->subdevice) { case 0x838e: chip->model = model_xonar_ds; - chip->model.shortname = "Xonar DS"; - break; - case 0x8522: - chip->model = model_xonar_ds; - chip->model.shortname = "Xonar DSX"; break; case 0x835e: chip->model = model_xonar_hdav_slim; diff --git a/trunk/sound/pci/pcxhr/pcxhr_hwdep.c b/trunk/sound/pci/pcxhr/pcxhr_hwdep.c index d995175c1c48..bf207e317f71 100644 --- a/trunk/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/trunk/sound/pci/pcxhr/pcxhr_hwdep.c @@ -35,6 +35,13 @@ #include "pcxhr_mix22.h" +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) +#if !defined(CONFIG_USE_PCXHRLOADER) && !defined(CONFIG_SND_PCXHR) /* built-in kernel */ +#define SND_PCXHR_FW_LOADER /* use the standard firmware loader */ +#endif +#endif + + static int pcxhr_sub_init(struct pcxhr_mgr *mgr); /* * get basic information and init pcxhr card @@ -355,6 +362,8 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, /* * fw loader entry */ +#ifdef SND_PCXHR_FW_LOADER + int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) { static char *fw_files[][5] = { @@ -415,3 +424,80 @@ MODULE_FIRMWARE("pcxhr/xlxc924.dat"); MODULE_FIRMWARE("pcxhr/dspe924.e56"); MODULE_FIRMWARE("pcxhr/dspb924.b56"); MODULE_FIRMWARE("pcxhr/dspd222.d56"); + + +#else /* old style firmware loading */ + +/* pcxhr hwdep interface id string */ +#define PCXHR_HWDEP_ID "pcxhr loader" + + +static int pcxhr_hwdep_dsp_status(struct snd_hwdep *hw, + struct snd_hwdep_dsp_status *info) +{ + struct pcxhr_mgr *mgr = hw->private_data; + sprintf(info->id, "pcxhr%d", mgr->fw_file_set); + info->num_dsps = PCXHR_FIRMWARE_FILES_MAX_INDEX; + + if (hw->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) + info->chip_ready = 1; + + info->version = PCXHR_DRIVER_VERSION; + return 0; +} + +static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw, + struct snd_hwdep_dsp_image *dsp) +{ + struct pcxhr_mgr *mgr = hw->private_data; + int err; + struct firmware fw; + + fw.size = dsp->length; + fw.data = vmalloc(fw.size); + if (! fw.data) { + snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image " + "(%lu bytes)\n", (unsigned long)fw.size); + return -ENOMEM; + } + if (copy_from_user((void *)fw.data, dsp->image, dsp->length)) { + vfree(fw.data); + return -EFAULT; + } + err = pcxhr_dsp_load(mgr, dsp->index, &fw); + vfree(fw.data); + if (err < 0) + return err; + mgr->dsp_loaded |= 1 << dsp->index; + return 0; +} + +int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) +{ + int err; + struct snd_hwdep *hw; + + /* only create hwdep interface for first cardX + * (see "index" module parameter) + */ + err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw); + if (err < 0) + return err; + + hw->iface = SNDRV_HWDEP_IFACE_PCXHR; + hw->private_data = mgr; + hw->ops.dsp_status = pcxhr_hwdep_dsp_status; + hw->ops.dsp_load = pcxhr_hwdep_dsp_load; + hw->exclusive = 1; + /* stereo cards don't need fw_file_0 -> dsp_loaded = 1 */ + hw->dsp_loaded = mgr->is_hr_stereo ? 1 : 0; + mgr->dsp_loaded = 0; + sprintf(hw->name, PCXHR_HWDEP_ID); + + err = snd_card_register(mgr->chip[0]->card); + if (err < 0) + return err; + return 0; +} + +#endif /* SND_PCXHR_FW_LOADER */ diff --git a/trunk/sound/pci/rme9652/hdsp.c b/trunk/sound/pci/rme9652/hdsp.c index 0f82bb5f42ea..0d6930c4f4b7 100644 --- a/trunk/sound/pci/rme9652/hdsp.c +++ b/trunk/sound/pci/rme9652/hdsp.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -60,11 +59,13 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," "{RME HDSP-9652}," "{RME HDSP-9632}}"); +#ifdef HDSP_FW_LOADER MODULE_FIRMWARE("rpm_firmware.bin"); 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 @@ -422,7 +423,12 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); #define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES) #define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024) -#define HDSP_FIRMWARE_SIZE (24413 * 4) +/* use hotplug firmware loader? */ +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) +#if !defined(HDSP_USE_HWDEP_LOADER) +#define HDSP_FW_LOADER +#endif +#endif struct hdsp_9632_meters { u32 input_peak[16]; @@ -469,8 +475,7 @@ struct hdsp { enum HDSP_IO_Type io_type; /* ditto, but for code use */ unsigned short firmware_rev; unsigned short state; /* stores state bits */ - const struct firmware *firmware; - u32 *fw_uploaded; + u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */ size_t period_bytes; /* guess what this is */ unsigned char max_channels; unsigned char qs_in_channels; /* quad speed mode for H9632 */ @@ -707,17 +712,6 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { int i; unsigned long flags; - const u32 *cache; - - if (hdsp->fw_uploaded) - cache = hdsp->fw_uploaded; - else { - if (!hdsp->firmware) - return -ENODEV; - cache = (u32 *)hdsp->firmware->data; - if (!cache) - return -ENODEV; - } if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { @@ -733,8 +727,8 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); - for (i = 0; i < HDSP_FIRMWARE_SIZE / 4; ++i) { - hdsp_write(hdsp, HDSP_fifoData, cache[i]); + for (i = 0; i < 24413; ++i) { + hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]); if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { snd_printk ("Hammerfall-DSP: timeout during firmware loading\n"); return -EIO; @@ -804,7 +798,9 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) } +#ifdef HDSP_FW_LOADER static int hdsp_request_fw_loader(struct hdsp *hdsp); +#endif static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) { @@ -817,8 +813,10 @@ static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); /* try to load firmware */ if (! (hdsp->state & HDSP_FirmwareCached)) { +#ifdef HDSP_FW_LOADER if (! hdsp_request_fw_loader(hdsp)) return 0; +#endif snd_printk(KERN_ERR "Hammerfall-DSP: No firmware loaded nor " "cached, please upload firmware.\n"); @@ -3675,7 +3673,9 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) } } else { int err = -EINVAL; +#ifdef HDSP_FW_LOADER err = hdsp_request_fw_loader(hdsp); +#endif if (err < 0) { snd_iprintf(buffer, "No firmware loaded nor cached, " @@ -5100,18 +5100,8 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne if (hdsp_check_for_iobox (hdsp)) return -EIO; - if (!hdsp->fw_uploaded) { - hdsp->fw_uploaded = vmalloc(HDSP_FIRMWARE_SIZE); - if (!hdsp->fw_uploaded) - return -ENOMEM; - } - - if (copy_from_user(hdsp->fw_uploaded, firmware_data, - HDSP_FIRMWARE_SIZE)) { - vfree(hdsp->fw_uploaded); - hdsp->fw_uploaded = NULL; + if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) return -EFAULT; - } hdsp->state |= HDSP_FirmwareCached; @@ -5340,6 +5330,7 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp return 0; } +#ifdef HDSP_FW_LOADER /* load firmware via hotplug fw loader */ static int hdsp_request_fw_loader(struct hdsp *hdsp) { @@ -5382,13 +5373,16 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile); return -ENOENT; } - if (fw->size < HDSP_FIRMWARE_SIZE) { + if (fw->size < sizeof(hdsp->firmware_cache)) { snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n", - (int)fw->size, HDSP_FIRMWARE_SIZE); + (int)fw->size, (int)sizeof(hdsp->firmware_cache)); + release_firmware(fw); return -EINVAL; } - hdsp->firmware = fw; + memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); + + release_firmware(fw); hdsp->state |= HDSP_FirmwareCached; @@ -5412,6 +5406,7 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) } return 0; } +#endif static int __devinit snd_hdsp_create(struct snd_card *card, struct hdsp *hdsp) @@ -5509,6 +5504,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, return err; if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { +#ifdef HDSP_FW_LOADER if ((err = hdsp_request_fw_loader(hdsp)) < 0) /* we don't fail as this can happen if userspace is not ready for @@ -5518,6 +5514,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, else /* init is complete, we return */ return 0; +#endif /* we defer initialization */ snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n"); if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) @@ -5571,10 +5568,6 @@ static int snd_hdsp_free(struct hdsp *hdsp) snd_hdsp_free_buffers(hdsp); - if (hdsp->firmware) - release_firmware(hdsp->firmware); - vfree(hdsp->fw_uploaded); - if (hdsp->iobase) iounmap(hdsp->iobase); diff --git a/trunk/sound/pci/ymfpci/ymfpci_main.c b/trunk/sound/pci/ymfpci/ymfpci_main.c index 60e8cb24bd44..3a6f03f9b02f 100644 --- a/trunk/sound/pci/ymfpci/ymfpci_main.c +++ b/trunk/sound/pci/ymfpci/ymfpci_main.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -2260,7 +2261,7 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip) #endif #ifdef CONFIG_PM_SLEEP - kfree(chip->saved_regs); + vfree(chip->saved_regs); #endif if (chip->irq >= 0) free_irq(chip->irq, chip); @@ -2470,8 +2471,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card, } #ifdef CONFIG_PM_SLEEP - chip->saved_regs = kmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32), - GFP_KERNEL); + chip->saved_regs = vmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32)); if (chip->saved_regs == NULL) { snd_ymfpci_free(chip); return -ENOMEM; diff --git a/trunk/sound/soc/fsl/Makefile b/trunk/sound/soc/fsl/Makefile index 5f3cf3f52ea0..c3deee897b5a 100644 --- a/trunk/sound/soc/fsl/Makefile +++ b/trunk/sound/soc/fsl/Makefile @@ -26,14 +26,18 @@ obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o # i.MX Platform Support snd-soc-imx-ssi-objs := imx-ssi.o snd-soc-imx-audmux-objs := imx-audmux.o +snd-soc-imx-pcm-objs := imx-pcm.o +ifneq ($(CONFIG_SND_SOC_IMX_PCM_FIQ),) + snd-soc-imx-pcm-objs += imx-pcm-fiq.o +endif +ifneq ($(CONFIG_SND_SOC_IMX_PCM_DMA),) + snd-soc-imx-pcm-objs += imx-pcm-dma.o +endif obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o -snd-soc-imx-pcm-y := imx-pcm.o -snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o -snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o diff --git a/trunk/sound/usb/6fire/comm.c b/trunk/sound/usb/6fire/comm.c index 1a75c36932d8..6c3d531a250e 100644 --- a/trunk/sound/usb/6fire/comm.c +++ b/trunk/sound/usb/6fire/comm.c @@ -129,13 +129,12 @@ int __devinit usb6fire_comm_init(struct sfire_chip *chip) { struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime), GFP_KERNEL); - struct urb *urb; + struct urb *urb = &rt->receiver; int ret; if (!rt) return -ENOMEM; - urb = &rt->receiver; rt->serial = 1; rt->chip = chip; usb_init_urb(urb); diff --git a/trunk/sound/usb/Kconfig b/trunk/sound/usb/Kconfig index 225dfd737265..ff77b28f3da1 100644 --- a/trunk/sound/usb/Kconfig +++ b/trunk/sound/usb/Kconfig @@ -90,7 +90,7 @@ config SND_USB_CAIAQ_INPUT config SND_USB_US122L tristate "Tascam US-122L USB driver" - depends on X86 + depends on X86 && EXPERIMENTAL select SND_HWDEP select SND_RAWMIDI help diff --git a/trunk/sound/usb/card.c b/trunk/sound/usb/card.c index ccf95cfe186f..dbf7999d18b4 100644 --- a/trunk/sound/usb/card.c +++ b/trunk/sound/usb/card.c @@ -25,6 +25,9 @@ * * NOTES: * + * - async unlink should be used for avoiding the sleep inside lock. + * 2.4.22 usb-uhci seems buggy for async unlinking and results in + * oops. in such a cse, pass async_unlink=0 option. * - the linked URBs would be preferred but not used so far because of * the instability of unlinking. * - type II is not supported properly. there is no device which supports @@ -80,6 +83,7 @@ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card * static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; static int nrpacks = 8; /* max. number of packets per urb */ +static bool async_unlink = 1; static int device_setup[SNDRV_CARDS]; /* device parameter for this card */ static bool ignore_ctl_error; @@ -95,6 +99,8 @@ module_param_array(pid, int, NULL, 0444); MODULE_PARM_DESC(pid, "Product ID for the USB audio device."); module_param(nrpacks, int, 0644); MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB."); +module_param(async_unlink, bool, 0444); +MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); module_param_array(device_setup, int, NULL, 0444); MODULE_PARM_DESC(device_setup, "Specific device setup (if needed)."); module_param(ignore_ctl_error, bool, 0444); @@ -339,6 +345,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, chip->card = card; chip->setup = device_setup[idx]; chip->nrpacks = nrpacks; + chip->async_unlink = async_unlink; chip->probing = 1; chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), diff --git a/trunk/sound/usb/card.h b/trunk/sound/usb/card.h index 8a751b4887ea..814cb357ff88 100644 --- a/trunk/sound/usb/card.h +++ b/trunk/sound/usb/card.h @@ -27,7 +27,6 @@ struct audioformat { unsigned int nr_rates; /* number of rate table entries */ unsigned int *rate_table; /* rate table */ unsigned char clock; /* associated clock */ - struct snd_pcm_chmap_elem *chmap; /* (optional) channel map */ }; struct snd_usb_substream; @@ -110,7 +109,6 @@ struct snd_usb_substream { struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */ snd_pcm_format_t pcm_format; /* current audio format (for hw_params callback) */ unsigned int channels; /* current number of channels (for hw_params callback) */ - unsigned int channels_max; /* max channels in the all audiofmts */ unsigned int cur_rate; /* current rate (for hw_params callback) */ unsigned int period_bytes; /* current period bytes (for hw_params callback) */ unsigned int altset_idx; /* USB data format: index of alternate setting */ diff --git a/trunk/sound/usb/endpoint.c b/trunk/sound/usb/endpoint.c index 21049b882ee6..34de6f2faf61 100644 --- a/trunk/sound/usb/endpoint.c +++ b/trunk/sound/usb/endpoint.c @@ -485,10 +485,15 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, static int wait_clear_urbs(struct snd_usb_endpoint *ep) { unsigned long end_time = jiffies + msecs_to_jiffies(1000); + unsigned int i; int alive; do { - alive = bitmap_weight(&ep->active_mask, ep->nurbs); + alive = 0; + for (i = 0; i < ep->nurbs; i++) + if (test_bit(i, &ep->active_mask)) + alive++; + if (!alive) break; @@ -515,24 +520,33 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) /* * unlink active urbs. */ -static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force) +static int deactivate_urbs(struct snd_usb_endpoint *ep, int force, int can_sleep) { unsigned int i; + int async; if (!force && ep->chip->shutdown) /* to be sure... */ return -EBADFD; + async = !can_sleep && ep->chip->async_unlink; + clear_bit(EP_FLAG_RUNNING, &ep->flags); INIT_LIST_HEAD(&ep->ready_playback_urbs); ep->next_packet_read_pos = 0; ep->next_packet_write_pos = 0; + if (!async && in_interrupt()) + return 0; + for (i = 0; i < ep->nurbs; i++) { if (test_bit(i, &ep->active_mask)) { if (!test_and_set_bit(i, &ep->unlink_mask)) { struct urb *u = ep->urb[i].urb; - usb_unlink_urb(u); + if (async) + usb_unlink_urb(u); + else + usb_kill_urb(u); } } } @@ -552,7 +566,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) ep->prepare_data_urb = NULL; /* stop urbs */ - deactivate_urbs(ep, force); + deactivate_urbs(ep, force, 1); wait_clear_urbs(ep); for (i = 0; i < ep->nurbs; i++) @@ -815,7 +829,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, * * Returns an error if the URB submission failed, 0 in all other cases. */ -int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep) +int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) { int err; unsigned int i; @@ -828,7 +842,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep) return 0; /* just to be sure */ - deactivate_urbs(ep, false); + deactivate_urbs(ep, 0, can_sleep); if (can_sleep) wait_clear_urbs(ep); @@ -882,7 +896,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep) __error: clear_bit(EP_FLAG_RUNNING, &ep->flags); ep->use_count--; - deactivate_urbs(ep, false); + deactivate_urbs(ep, 0, 0); return -EPIPE; } @@ -896,11 +910,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep) * actually be deactivated. * * Must be balanced to calls of snd_usb_endpoint_start(). - * - * The caller needs to synchronize the pending stop operation via - * snd_usb_endpoint_sync_pending_stop(). */ -void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) +void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, + int force, int can_sleep, int wait) { if (!ep) return; @@ -909,12 +921,16 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) return; if (--ep->use_count == 0) { - deactivate_urbs(ep, false); + deactivate_urbs(ep, force, can_sleep); ep->data_subs = NULL; ep->sync_slave = NULL; ep->retire_data_urb = NULL; ep->prepare_data_urb = NULL; - set_bit(EP_FLAG_STOPPING, &ep->flags); + + if (wait) + wait_clear_urbs(ep); + else + set_bit(EP_FLAG_STOPPING, &ep->flags); } } @@ -936,7 +952,7 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep) if (!ep) return -EINVAL; - deactivate_urbs(ep, true); + deactivate_urbs(ep, 1, 1); wait_clear_urbs(ep); if (ep->use_count != 0) @@ -1018,18 +1034,15 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, /* * Iterate through the inbound packet and prepare the lengths * for the output packet. The OUT packet we are about to send - * will have the same amount of payload bytes per stride as the - * IN packet we just received. Since the actual size is scaled - * by the stride, use the sender stride to calculate the length - * in case the number of channels differ between the implicitly - * fed-back endpoint and the synchronizing endpoint. + * will have the same amount of payload bytes than the IN + * packet we just received. */ out_packet->packets = in_ctx->packets; for (i = 0; i < in_ctx->packets; i++) { if (urb->iso_frame_desc[i].status == 0) out_packet->packet_size[i] = - urb->iso_frame_desc[i].actual_length / sender->stride; + urb->iso_frame_desc[i].actual_length / ep->stride; else out_packet->packet_size[i] = 0; } diff --git a/trunk/sound/usb/endpoint.h b/trunk/sound/usb/endpoint.h index 447902dd8a4a..3d4c9705041f 100644 --- a/trunk/sound/usb/endpoint.h +++ b/trunk/sound/usb/endpoint.h @@ -16,8 +16,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, struct audioformat *fmt, struct snd_usb_endpoint *sync_ep); -int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep); -void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep); +int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); +void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, + int force, int can_sleep, int wait); void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); diff --git a/trunk/sound/usb/format.c b/trunk/sound/usb/format.c index e831ee4238bb..ddfef57c4c9f 100644 --- a/trunk/sound/usb/format.c +++ b/trunk/sound/usb/format.c @@ -155,7 +155,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", chip->dev->devnum, fp->iface, fp->altsetting); - return -EINVAL; + return -1; } if (nr_rates) { @@ -167,7 +167,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); if (fp->rate_table == NULL) { snd_printk(KERN_ERR "cannot malloc\n"); - return -ENOMEM; + return -1; } fp->nr_rates = 0; @@ -198,7 +198,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof } if (!fp->nr_rates) { hwc_debug("All rates were zero. Skipping format!\n"); - return -EINVAL; + return -1; } } else { /* continuous rates */ @@ -383,7 +383,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, fp->formats = parse_audio_format_i_type(chip, fp, format, fmt, protocol); if (!fp->formats) - return -EINVAL; + return -1; } /* gather possible sample rates */ @@ -409,7 +409,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, if (fp->channels < 1) { snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", chip->dev->devnum, fp->iface, fp->altsetting, fp->channels); - return -EINVAL; + return -1; } return ret; diff --git a/trunk/sound/usb/mixer.c b/trunk/sound/usb/mixer.c index ed4d89c8b52a..298070e8f2d4 100644 --- a/trunk/sound/usb/mixer.c +++ b/trunk/sound/usb/mixer.c @@ -382,8 +382,6 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) { - validx += cval->idx_off; - return (cval->mixer->protocol == UAC_VERSION_1) ? get_ctl_value_v1(cval, request, validx, value_ret) : get_ctl_value_v2(cval, request, validx, value_ret); @@ -434,8 +432,6 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, unsigned char buf[2]; int idx = 0, val_len, err, timeout = 10; - validx += cval->idx_off; - if (cval->mixer->protocol == UAC_VERSION_1) { val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; } else { /* UAC_VERSION_2 */ @@ -723,19 +719,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ return 0; } case UAC1_PROCESSING_UNIT: - case UAC1_EXTENSION_UNIT: - /* UAC2_PROCESSING_UNIT_V2 */ - /* UAC2_EFFECT_UNIT */ { + case UAC1_EXTENSION_UNIT: { struct uac_processing_unit_descriptor *d = p1; - - if (state->mixer->protocol == UAC_VERSION_2 && - hdr[2] == UAC2_EFFECT_UNIT) { - /* UAC2/UAC1 unit IDs overlap here in an - * uncompatible way. Ignore this unit for now. - */ - return 0; - } - if (d->bNrInPins) { id = d->baSourceID[0]; break; /* continue to parse */ @@ -806,33 +791,6 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, struct snd_kcontrol *kctl) { switch (cval->mixer->chip->usb_id) { - case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ - if (strcmp(kctl->id.name, "Effect Duration") == 0) { - cval->min = 0x0000; - cval->max = 0xffff; - cval->res = 0x00e6; - break; - } - if (strcmp(kctl->id.name, "Effect Volume") == 0 || - strcmp(kctl->id.name, "Effect Feedback Volume") == 0) { - cval->min = 0x00; - cval->max = 0xff; - break; - } - if (strstr(kctl->id.name, "Effect Return") != NULL) { - cval->min = 0xb706; - cval->max = 0xff7b; - cval->res = 0x0073; - break; - } - if ((strstr(kctl->id.name, "Playback Volume") != NULL) || - (strstr(kctl->id.name, "Effect Send") != NULL)) { - cval->min = 0xb5fb; /* -73 dB = 0xb6ff */ - cval->max = 0xfcfe; - cval->res = 0x0073; - } - break; - case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ if (strcmp(kctl->id.name, "Effect Duration") == 0) { @@ -1136,32 +1094,6 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str) return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); } -/* A lot of headsets/headphones have a "Speaker" mixer. Make sure we - rename it to "Headphone". We determine if something is a headphone - similar to how udev determines form factor. */ -static void check_no_speaker_on_headset(struct snd_kcontrol *kctl, - struct snd_card *card) -{ - const char *names_to_check[] = { - "Headset", "headset", "Headphone", "headphone", NULL}; - const char **s; - bool found = 0; - - if (strcmp("Speaker", kctl->id.name)) - return; - - for (s = names_to_check; *s; s++) - if (strstr(card->shortname, *s)) { - found = 1; - break; - } - - if (!found) - return; - - strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name)); -} - static void build_feature_ctl(struct mixer_build *state, void *raw_desc, unsigned int ctl_mask, int control, struct usb_audio_term *iterm, int unitid, @@ -1248,10 +1180,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, len = snprintf(kctl->id.name, sizeof(kctl->id.name), "Feature %d", unitid); } - - if (!mapped_name) - check_no_speaker_on_headset(kctl, state->mixer->chip->card); - /* determine the stream direction: * if the connected output is USB stream, then it's likely a * capture stream. otherwise it should be playback (hopefully :) diff --git a/trunk/sound/usb/mixer.h b/trunk/sound/usb/mixer.h index aab80df201bd..a7f3d45a8acf 100644 --- a/trunk/sound/usb/mixer.h +++ b/trunk/sound/usb/mixer.h @@ -43,7 +43,6 @@ struct usb_mixer_elem_info { unsigned int id; unsigned int control; /* CS or ICN (high byte) */ unsigned int cmask; /* channel mask bitmap: 0 = master */ - unsigned int idx_off; /* Control index offset */ unsigned int ch_readonly; unsigned int master_readonly; int channels; diff --git a/trunk/sound/usb/mixer_quirks.c b/trunk/sound/usb/mixer_quirks.c index bf28a1b723dc..ae2b71435220 100644 --- a/trunk/sound/usb/mixer_quirks.c +++ b/trunk/sound/usb/mixer_quirks.c @@ -63,12 +63,11 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) * Since there doesn't seem to be a devices that needs a multichannel * version, we keep it mono for simplicity. */ -static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer, +static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, unsigned int unitid, unsigned int control, unsigned int cmask, int val_type, - unsigned int idx_off, const char *name, snd_kcontrol_tlv_rw_t *tlv_callback) { @@ -86,7 +85,6 @@ static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer, cval->channels = 1; cval->control = control; cval->cmask = cmask; - cval->idx_off = idx_off; /* get_min_max() is called only for integer volumes later, * so provide a short-cut for booleans */ @@ -122,18 +120,6 @@ static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer, return 0; } -static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, - unsigned int unitid, - unsigned int control, - unsigned int cmask, - int val_type, - const char *name, - snd_kcontrol_tlv_rw_t *tlv_callback) -{ - return snd_create_std_mono_ctl_offset(mixer, unitid, control, cmask, - val_type, 0 /* Offset */, name, tlv_callback); -} - /* * Create a set of standard UAC controls from a table */ @@ -635,13 +621,11 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, } /* M-Audio FastTrack Ultra quirks */ -/* FTU Effect switch (also used by C400) */ +/* FTU Effect switch */ struct snd_ftu_eff_switch_priv_val { struct usb_mixer_interface *mixer; int cached_value; int is_cached; - int bUnitID; - int validx; }; static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol, @@ -676,8 +660,9 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, struct snd_ftu_eff_switch_priv_val *pval; int err; unsigned char value[2]; - int id, validx; + const int id = 6; + const int validx = 1; const int val_len = 2; value[0] = 0x00; @@ -699,8 +684,6 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, if (snd_BUG_ON(!chip)) return -EINVAL; - id = pval->bUnitID; - validx = pval->validx; down_read(&mixer->chip->shutdown_rwsem); if (mixer->chip->shutdown) @@ -731,8 +714,10 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer; int changed, cur_val, err, new_val; unsigned char value[2]; - int id, validx; + + const int id = 6; + const int validx = 1; const int val_len = 2; changed = 0; @@ -750,9 +735,6 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, if (snd_BUG_ON(!chip)) return -EINVAL; - id = pval->bUnitID; - validx = pval->validx; - if (!pval->is_cached) { /* Read current value */ down_read(&mixer->chip->shutdown_rwsem); @@ -797,8 +779,7 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, return changed; } -static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, - int validx, int bUnitID) +static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer) { static struct snd_kcontrol_new template = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -821,8 +802,6 @@ static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, pval->cached_value = 0; pval->is_cached = 0; pval->mixer = mixer; - pval->bUnitID = bUnitID; - pval->validx = validx; template.private_value = (unsigned long) pval; kctl = snd_ctl_new1(&template, mixer->chip); @@ -981,10 +960,9 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) if (err < 0) return err; - err = snd_ftu_create_effect_switch(mixer, 1, 6); + err = snd_ftu_create_effect_switch(mixer); if (err < 0) return err; - err = snd_ftu_create_effect_volume_ctl(mixer); if (err < 0) return err; @@ -1027,178 +1005,6 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, } } -/* M-Audio Fast Track C400 */ -/* C400 volume controls, this control needs a volume quirk, see mixer.c */ -static int snd_c400_create_vol_ctls(struct usb_mixer_interface *mixer) -{ - char name[64]; - unsigned int cmask, offset; - int out, chan, err; - - const unsigned int id = 0x40; - const int val_type = USB_MIXER_S16; - const int control = 1; - - for (chan = 0; chan < 10; chan++) { - for (out = 0; out < 6; out++) { - if (chan < 6) { - snprintf(name, sizeof(name), - "PCM%d-Out%d Playback Volume", - chan + 1, out + 1); - } else { - snprintf(name, sizeof(name), - "In%d-Out%d Playback Volume", - chan - 5, out + 1); - } - - cmask = (out == 0) ? 0 : 1 << (out - 1); - offset = chan * 6; - err = snd_create_std_mono_ctl_offset(mixer, id, control, - cmask, val_type, offset, name, - &snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } - } - - return 0; -} - -/* This control needs a volume quirk, see mixer.c */ -static int snd_c400_create_effect_volume_ctl(struct usb_mixer_interface *mixer) -{ - static const char name[] = "Effect Volume"; - const unsigned int id = 0x43; - const int val_type = USB_MIXER_U8; - const unsigned int control = 3; - const unsigned int cmask = 0; - - return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, - name, snd_usb_mixer_vol_tlv); -} - -/* This control needs a volume quirk, see mixer.c */ -static int snd_c400_create_effect_duration_ctl(struct usb_mixer_interface *mixer) -{ - static const char name[] = "Effect Duration"; - const unsigned int id = 0x43; - const int val_type = USB_MIXER_S16; - const unsigned int control = 4; - const unsigned int cmask = 0; - - return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, - name, snd_usb_mixer_vol_tlv); -} - -/* This control needs a volume quirk, see mixer.c */ -static int snd_c400_create_effect_feedback_ctl(struct usb_mixer_interface *mixer) -{ - static const char name[] = "Effect Feedback Volume"; - const unsigned int id = 0x43; - const int val_type = USB_MIXER_U8; - const unsigned int control = 5; - const unsigned int cmask = 0; - - return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, - name, NULL); -} - -static int snd_c400_create_effect_vol_ctls(struct usb_mixer_interface *mixer) -{ - char name[64]; - unsigned int cmask; - int chan, err; - - const unsigned int id = 0x42; - const int val_type = USB_MIXER_S16; - const int control = 1; - - for (chan = 0; chan < 10; chan++) { - if (chan < 6) { - snprintf(name, sizeof(name), - "Effect Send DOut%d", - chan + 1); - } else { - snprintf(name, sizeof(name), - "Effect Send AIn%d", - chan - 5); - } - - cmask = (chan == 0) ? 0 : 1 << (chan - 1); - err = snd_create_std_mono_ctl(mixer, id, control, - cmask, val_type, name, - &snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } - - return 0; -} - -static int snd_c400_create_effect_ret_vol_ctls(struct usb_mixer_interface *mixer) -{ - char name[64]; - unsigned int cmask; - int chan, err; - - const unsigned int id = 0x40; - const int val_type = USB_MIXER_S16; - const int control = 1; - const int chan_id[6] = { 0, 7, 2, 9, 4, 0xb }; - const unsigned int offset = 0x3c; - /* { 0x3c, 0x43, 0x3e, 0x45, 0x40, 0x47 } */ - - for (chan = 0; chan < 6; chan++) { - snprintf(name, sizeof(name), - "Effect Return %d", - chan + 1); - - cmask = (chan_id[chan] == 0) ? 0 : 1 << (chan_id[chan] - 1); - err = snd_create_std_mono_ctl_offset(mixer, id, control, - cmask, val_type, offset, name, - &snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } - - return 0; -} - -static int snd_c400_create_mixer(struct usb_mixer_interface *mixer) -{ - int err; - - err = snd_c400_create_vol_ctls(mixer); - if (err < 0) - return err; - - err = snd_c400_create_effect_vol_ctls(mixer); - if (err < 0) - return err; - - err = snd_c400_create_effect_ret_vol_ctls(mixer); - if (err < 0) - return err; - - err = snd_ftu_create_effect_switch(mixer, 2, 0x43); - if (err < 0) - return err; - - err = snd_c400_create_effect_volume_ctl(mixer); - if (err < 0) - return err; - - err = snd_c400_create_effect_duration_ctl(mixer); - if (err < 0) - return err; - - err = snd_c400_create_effect_feedback_ctl(mixer); - if (err < 0) - return err; - - return 0; -} - /* * The mixer units for Ebox-44 are corrupt, and even where they * are valid they presents mono controls as L and R channels of @@ -1296,10 +1102,6 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) snd_audigy2nx_proc_read); break; - case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ - err = snd_c400_create_mixer(mixer); - break; - case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ err = snd_ftu_create_mixer(mixer); diff --git a/trunk/sound/usb/pcm.c b/trunk/sound/usb/pcm.c index 769821c30031..ef6fa24fc473 100644 --- a/trunk/sound/usb/pcm.c +++ b/trunk/sound/usb/pcm.c @@ -46,9 +46,6 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, int frame_diff; int est_delay; - if (!subs->last_delay) - return 0; /* short path */ - current_frame_number = usb_get_current_frame_number(subs->dev); /* * HCD implementations use different widths, use lower 8 bits. @@ -78,8 +75,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream return SNDRV_PCM_POS_XRUN; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - substream->runtime->delay = snd_usb_pcm_delay(subs, + substream->runtime->delay = snd_usb_pcm_delay(subs, substream->runtime->rate); spin_unlock(&subs->lock); return hwptr_done / (substream->runtime->frame_bits >> 3); @@ -177,8 +173,11 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface, { struct usb_device *dev = chip->dev; unsigned char data[1]; + unsigned int ep; int err; + ep = get_endpoint(alts, 0)->bEndpointAddress; + data[0] = 1; if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, @@ -215,7 +214,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, } } -static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) +static int start_endpoints(struct snd_usb_substream *subs, int can_sleep) { int err; @@ -267,18 +266,16 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) return 0; } -static void stop_endpoints(struct snd_usb_substream *subs, bool wait) +static void stop_endpoints(struct snd_usb_substream *subs, + int force, int can_sleep, int wait) { if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) - snd_usb_endpoint_stop(subs->sync_endpoint); + snd_usb_endpoint_stop(subs->sync_endpoint, + force, can_sleep, wait); if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) - snd_usb_endpoint_stop(subs->data_endpoint); - - if (wait) { - snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); - snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); - } + snd_usb_endpoint_stop(subs->data_endpoint, + force, can_sleep, wait); } static int deactivate_endpoints(struct snd_usb_substream *subs) @@ -362,19 +359,6 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; switch (subs->stream->chip->usb_id) { - case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ - if (is_playback) { - implicit_fb = 1; - ep = 0x81; - iface = usb_ifnum_to_if(dev, 3); - - if (!iface || iface->num_altsetting == 0) - return -EINVAL; - - alts = &iface->altsetting[1]; - goto add_sync_ep; - } - break; case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */ case USB_ID(0x0763, 0x2081): if (is_playback) { @@ -397,7 +381,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) /* ... and check descriptor size before accessing bSynchAddress because there is a version of the SB Audigy 2 NX firmware lacking the audio fields in the endpoint descriptors */ - if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC || + if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != 0x01 || (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && get_endpoint(alts, 1)->bSynchAddress != 0 && !implicit_fb)) { @@ -463,7 +447,7 @@ static int configure_endpoint(struct snd_usb_substream *subs) int ret; /* format changed */ - stop_endpoints(subs, true); + stop_endpoints(subs, 0, 0, 0); ret = snd_usb_endpoint_set_params(subs->data_endpoint, subs->pcm_format, subs->channels, @@ -549,7 +533,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->period_bytes = 0; down_read(&subs->stream->chip->shutdown_rwsem); if (!subs->stream->chip->shutdown) { - stop_endpoints(subs, true); + stop_endpoints(subs, 0, 1, 1); deactivate_endpoints(subs); } up_read(&subs->stream->chip->shutdown_rwsem); @@ -624,7 +608,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) /* for playback, submit the URBs now; otherwise, the first hwptr_done * updates for all URBs would happen at the same time when starting */ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) - ret = start_endpoints(subs, true); + ret = start_endpoints(subs, 1); unlock: up_read(&subs->stream->chip->shutdown_rwsem); @@ -1029,7 +1013,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_usb_substream *subs = &as->substream[direction]; - stop_endpoints(subs, true); + stop_endpoints(subs, 0, 0, 0); if (!as->chip->shutdown && subs->interface >= 0) { usb_set_interface(subs->dev, subs->interface, 0); @@ -1211,9 +1195,6 @@ static void retire_playback_urb(struct snd_usb_substream *subs, return; spin_lock_irqsave(&subs->lock, flags); - if (!subs->last_delay) - goto out; /* short path */ - est_delay = snd_usb_pcm_delay(subs, runtime->rate); /* update delay with exact number of samples played */ if (processed > subs->last_delay) @@ -1231,15 +1212,6 @@ static void retire_playback_urb(struct snd_usb_substream *subs, snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n", est_delay, subs->last_delay); - if (!subs->running) { - /* update last_frame_number for delay counting here since - * prepare_playback_urb won't be called during pause - */ - subs->last_frame_number = - usb_get_current_frame_number(subs->dev) & 0xff; - } - - out: spin_unlock_irqrestore(&subs->lock, flags); } @@ -1276,13 +1248,12 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea subs->running = 1; return 0; case SNDRV_PCM_TRIGGER_STOP: - stop_endpoints(subs, false); + stop_endpoints(subs, 0, 0, 0); subs->running = 0; return 0; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: subs->data_endpoint->prepare_data_urb = NULL; - /* keep retire_data_urb for delay calculation */ - subs->data_endpoint->retire_data_urb = retire_playback_urb; + subs->data_endpoint->retire_data_urb = NULL; subs->running = 0; return 0; } @@ -1298,7 +1269,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream switch (cmd) { case SNDRV_PCM_TRIGGER_START: - err = start_endpoints(subs, false); + err = start_endpoints(subs, 0); if (err < 0) return err; @@ -1306,7 +1277,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream subs->running = 1; return 0; case SNDRV_PCM_TRIGGER_STOP: - stop_endpoints(subs, false); + stop_endpoints(subs, 0, 0, 0); subs->running = 0; return 0; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: diff --git a/trunk/sound/usb/quirks-table.h b/trunk/sound/usb/quirks-table.h index 49f9af995d7a..88d8cebbb244 100644 --- a/trunk/sound/usb/quirks-table.h +++ b/trunk/sound/usb/quirks-table.h @@ -1456,40 +1456,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, -{ - /* Advanced mode of the Roland VG-99, with MIDI and 24-bit PCM at 44.1 - * kHz. In standard mode, the device has ID 0582:00b3, and offers - * 16-bit PCM at 44.1 kHz with no MIDI. - */ - USB_DEVICE(0x0582, 0x00b2), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "VG-99", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - }, - { - .ifnum = -1 - } - } - } -}, { /* Roland SonicCell */ USB_DEVICE(0x0582, 0x00c2), @@ -2196,77 +2162,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, -{ - USB_DEVICE_VENDOR_SPEC(0x0763, 0x2030), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - /* .vendor_name = "M-Audio", */ - /* .product_name = "Fast Track C400", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - /* Playback */ - { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 6, - .iface = 2, - .altsetting = 1, - .altset_idx = 1, - .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, - .endpoint = 0x01, - .ep_attr = 0x09, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 44100, - .rate_max = 96000, - .nr_rates = 4, - .rate_table = (unsigned int[]) { - 44100, 48000, 88200, 96000 - }, - .clock = 0x81, - } - }, - /* Capture */ - { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 4, - .iface = 3, - .altsetting = 1, - .altset_idx = 1, - .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, - .endpoint = 0x81, - .ep_attr = 0x05, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 44100, - .rate_max = 96000, - .nr_rates = 4, - .rate_table = (unsigned int[]) { - 44100, 48000, 88200, 96000 - }, - .clock = 0x81, - } - }, - /* MIDI */ - { - .ifnum = -1 /* Interface = 4 */ - } - } - } -}, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { @@ -2985,99 +2880,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, -/* Reloop Play */ -{ - USB_DEVICE(0x200c, 0x100b), - .bInterfaceClass = USB_CLASS_PER_INTERFACE, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3LE, - .channels = 4, - .iface = 1, - .altsetting = 1, - .altset_idx = 1, - .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, - .endpoint = 0x01, - .ep_attr = USB_ENDPOINT_SYNC_ADAPTIVE, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .nr_rates = 2, - .rate_table = (unsigned int[]) { - 44100, 48000 - } - } - }, - { - .ifnum = -1 - } - } - } -}, - -{ - /* - * Focusrite Scarlett 18i6 - * - * Avoid mixer creation, which otherwise fails because some of - * the interface descriptor subtypes for interface 0 are - * unknown. That should be fixed or worked-around but this at - * least allows the device to be used successfully with a DAW - * and an external mixer. See comments below about other - * ignored interfaces. - */ - USB_DEVICE(0x1235, 0x8004), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Focusrite", - .product_name = "Scarlett 18i6", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - /* InterfaceSubClass 1 (Control Device) */ - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - /* InterfaceSubClass 1 (Control Device) */ - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - /* InterfaceSubClass 1 (Device Firmware Update) */ - .ifnum = 5, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } - } - } -}, - { /* * Some USB MIDI devices don't have an audio control interface, diff --git a/trunk/sound/usb/stream.c b/trunk/sound/usb/stream.c index ad181d538bd9..1de0c8c002a8 100644 --- a/trunk/sound/usb/stream.c +++ b/trunk/sound/usb/stream.c @@ -23,8 +23,6 @@ #include #include -#include -#include #include "usbaudio.h" #include "card.h" @@ -49,7 +47,6 @@ static void free_substream(struct snd_usb_substream *subs) list_for_each_safe(p, n, &subs->fmt_list) { struct audioformat *fp = list_entry(p, struct audioformat, list); kfree(fp->rate_table); - kfree(fp->chmap); kfree(fp); } kfree(subs->rate_list.list); @@ -102,206 +99,6 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, subs->num_formats++; subs->fmt_type = fp->fmt_type; subs->ep_num = fp->endpoint; - if (fp->channels > subs->channels_max) - subs->channels_max = fp->channels; -} - -/* kctl callbacks for usb-audio channel maps */ -static int usb_chmap_ctl_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); - struct snd_usb_substream *subs = info->private_data; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = subs->channels_max; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = SNDRV_CHMAP_LAST; - return 0; -} - -/* check whether a duplicated entry exists in the audiofmt list */ -static bool have_dup_chmap(struct snd_usb_substream *subs, - struct audioformat *fp) -{ - struct list_head *p; - - for (p = fp->list.prev; p != &subs->fmt_list; p = p->prev) { - struct audioformat *prev; - prev = list_entry(p, struct audioformat, list); - if (prev->chmap && - !memcmp(prev->chmap, fp->chmap, sizeof(*fp->chmap))) - return true; - } - return false; -} - -static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv) -{ - struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); - struct snd_usb_substream *subs = info->private_data; - struct audioformat *fp; - unsigned int __user *dst; - int count = 0; - - if (size < 8) - return -ENOMEM; - if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) - return -EFAULT; - size -= 8; - dst = tlv + 2; - list_for_each_entry(fp, &subs->fmt_list, list) { - int i, ch_bytes; - - if (!fp->chmap) - continue; - if (have_dup_chmap(subs, fp)) - continue; - /* copy the entry */ - ch_bytes = fp->chmap->channels * 4; - if (size < 8 + ch_bytes) - return -ENOMEM; - if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) || - put_user(ch_bytes, dst + 1)) - return -EFAULT; - dst += 2; - for (i = 0; i < fp->chmap->channels; i++, dst++) { - if (put_user(fp->chmap->map[i], dst)) - return -EFAULT; - } - - count += 8 + ch_bytes; - size -= 8 + ch_bytes; - } - if (put_user(count, tlv + 1)) - return -EFAULT; - return 0; -} - -static int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); - struct snd_usb_substream *subs = info->private_data; - struct snd_pcm_chmap_elem *chmap = NULL; - int i; - - memset(ucontrol->value.integer.value, 0, - sizeof(ucontrol->value.integer.value)); - if (subs->cur_audiofmt) - chmap = subs->cur_audiofmt->chmap; - if (chmap) { - for (i = 0; i < chmap->channels; i++) - ucontrol->value.integer.value[i] = chmap->map[i]; - } - return 0; -} - -/* create a chmap kctl assigned to the given USB substream */ -static int add_chmap(struct snd_pcm *pcm, int stream, - struct snd_usb_substream *subs) -{ - struct audioformat *fp; - struct snd_pcm_chmap *chmap; - struct snd_kcontrol *kctl; - int err; - - list_for_each_entry(fp, &subs->fmt_list, list) - if (fp->chmap) - goto ok; - /* no chmap is found */ - return 0; - - ok: - err = snd_pcm_add_chmap_ctls(pcm, stream, NULL, 0, 0, &chmap); - if (err < 0) - return err; - - /* override handlers */ - chmap->private_data = subs; - kctl = chmap->kctl; - kctl->info = usb_chmap_ctl_info; - kctl->get = usb_chmap_ctl_get; - kctl->tlv.c = usb_chmap_ctl_tlv; - - return 0; -} - -/* convert from USB ChannelConfig bits to ALSA chmap element */ -static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits, - int protocol) -{ - static unsigned int uac1_maps[] = { - SNDRV_CHMAP_FL, /* left front */ - SNDRV_CHMAP_FR, /* right front */ - SNDRV_CHMAP_FC, /* center front */ - SNDRV_CHMAP_LFE, /* LFE */ - SNDRV_CHMAP_SL, /* left surround */ - SNDRV_CHMAP_SR, /* right surround */ - SNDRV_CHMAP_FLC, /* left of center */ - SNDRV_CHMAP_FRC, /* right of center */ - SNDRV_CHMAP_RC, /* surround */ - SNDRV_CHMAP_SL, /* side left */ - SNDRV_CHMAP_SR, /* side right */ - SNDRV_CHMAP_TC, /* top */ - 0 /* terminator */ - }; - static unsigned int uac2_maps[] = { - SNDRV_CHMAP_FL, /* front left */ - SNDRV_CHMAP_FR, /* front right */ - SNDRV_CHMAP_FC, /* front center */ - SNDRV_CHMAP_LFE, /* LFE */ - SNDRV_CHMAP_RL, /* back left */ - SNDRV_CHMAP_RR, /* back right */ - SNDRV_CHMAP_FLC, /* front left of center */ - SNDRV_CHMAP_FRC, /* front right of center */ - SNDRV_CHMAP_RC, /* back center */ - SNDRV_CHMAP_SL, /* side left */ - SNDRV_CHMAP_SR, /* side right */ - SNDRV_CHMAP_TC, /* top center */ - SNDRV_CHMAP_TFL, /* top front left */ - SNDRV_CHMAP_TFC, /* top front center */ - SNDRV_CHMAP_TFR, /* top front right */ - SNDRV_CHMAP_TRL, /* top back left */ - SNDRV_CHMAP_TRC, /* top back center */ - SNDRV_CHMAP_TRR, /* top back right */ - SNDRV_CHMAP_TFLC, /* top front left of center */ - SNDRV_CHMAP_TFRC, /* top front right of center */ - SNDRV_CHMAP_LLFE, /* left LFE */ - SNDRV_CHMAP_RLFE, /* right LFE */ - SNDRV_CHMAP_TSL, /* top side left */ - SNDRV_CHMAP_TSR, /* top side right */ - SNDRV_CHMAP_BC, /* bottom center */ - SNDRV_CHMAP_BLC, /* bottom left center */ - SNDRV_CHMAP_BRC, /* bottom right center */ - 0 /* terminator */ - }; - struct snd_pcm_chmap_elem *chmap; - const unsigned int *maps; - int c; - - if (!bits) - return NULL; - if (channels > ARRAY_SIZE(chmap->map)) - return NULL; - - chmap = kzalloc(sizeof(*chmap), GFP_KERNEL); - if (!chmap) - return NULL; - - maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps; - chmap->channels = channels; - c = 0; - for (; bits && *maps; maps++, bits >>= 1) { - if (bits & 1) - chmap->map[c++] = *maps; - } - - for (; c < channels; c++) - chmap->map[c] = SNDRV_CHMAP_UNKNOWN; - - return chmap; } /* @@ -343,7 +140,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, if (err < 0) return err; snd_usb_init_substream(as, stream, fp); - return add_chmap(as->pcm, stream, subs); + return 0; } /* create a new pcm */ @@ -377,7 +174,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, snd_usb_proc_pcm_format_add(as); - return add_chmap(pcm, stream, &as->substream[stream]); + return 0; } static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, @@ -421,11 +218,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, return attributes; } -/* find an input terminal descriptor (either UAC1 or UAC2) with the given - * terminal id - */ -static void * -snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, +static struct uac2_input_terminal_descriptor * + snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, int terminal_id) { struct uac2_input_terminal_descriptor *term = NULL; @@ -467,7 +261,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) struct audioformat *fp = NULL; int num, protocol, clock = 0; struct uac_format_type_i_continuous_descriptor *fmt; - unsigned int chconfig; dev = chip->dev; @@ -507,7 +300,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) continue; - chconfig = 0; /* get audio formats */ switch (protocol) { default: @@ -519,7 +311,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) case UAC_VERSION_1: { struct uac1_as_header_descriptor *as = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); - struct uac_input_terminal_descriptor *iterm; if (!as) { snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", @@ -534,14 +325,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) } format = le16_to_cpu(as->wFormatTag); /* remember the format value */ - - iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); - if (iterm) { - num_channels = iterm->bNrChannels; - chconfig = le16_to_cpu(iterm->wChannelConfig); - } - break; } @@ -572,7 +355,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) as->bTerminalLink); if (input_term) { clock = input_term->bCSourceID; - chconfig = le32_to_cpu(input_term->bmChannelConfig); break; } @@ -631,13 +413,13 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; fp->datainterval = snd_usb_parse_datainterval(chip, alts); fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); + /* num_channels is only set for v2 interfaces */ fp->channels = num_channels; if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) * (fp->maxpacksize & 0x7ff); fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); fp->clock = clock; - fp->chmap = convert_chmap(num_channels, chconfig, protocol); /* some quirks for attributes here */ @@ -673,7 +455,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) /* ok, let's parse further... */ if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { kfree(fp->rate_table); - kfree(fp->chmap); kfree(fp); fp = NULL; continue; @@ -683,7 +464,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) err = snd_usb_add_audio_stream(chip, stream, fp); if (err < 0) { kfree(fp->rate_table); - kfree(fp->chmap); kfree(fp); return err; } diff --git a/trunk/sound/usb/usbaudio.h b/trunk/sound/usb/usbaudio.h index 1ac3fd9cc5a6..ef42797f56fb 100644 --- a/trunk/sound/usb/usbaudio.h +++ b/trunk/sound/usb/usbaudio.h @@ -56,6 +56,7 @@ struct snd_usb_audio { int setup; /* from the 'device_setup' module param */ int nrpacks; /* from the 'nrpacks' module param */ + int async_unlink; /* from the 'async_unlink' module param */ struct usb_host_interface *ctrl_intf; /* the audio control interface */ };